# 機能設計書 171-ユーザープロフィール

## 概要

本ドキュメントは、Chatwootにおけるユーザープロフィール機能の設計仕様を定義する。この機能は、ログインユーザーが自身のプロフィール情報を表示・編集するためのAPIを提供する。

### 本機能の処理概要

**業務上の目的・背景**：
カスタマーサポートチームにおいて、各エージェントが自身の情報（名前、表示名、アバター、メッセージ署名等）を管理できることは、チーム内での識別性と顧客対応時のプロフェッショナルな印象を維持するために重要である。また、UI設定やカスタム属性を通じて、各ユーザーが自分に最適化された作業環境を構築できるようにする。

**機能の利用シーン**：
- 新規エージェントが初めてログインし、自身のプロフィール情報を設定する場合
- 既存ユーザーが表示名やメッセージ署名を更新したい場合
- ユーザーがパスワードを変更したい場合
- UI設定（テーマ、通知設定等）をカスタマイズしたい場合

**主要な処理内容**：
1. プロフィール情報の取得（GET /api/v1/profile）
2. プロフィール情報の更新（PATCH /api/v1/profile）
3. パスワード変更（現在のパスワード検証を含む）
4. カスタム属性（電話番号等）の更新
5. UI設定の保存

**関連システム・外部連携**：
- Gravatar: メールアドレス変更時にアバター画像を自動取得
- DeviseTokenAuth: 認証トークンの管理

**権限による制御**：
認証済みユーザーのみが自身のプロフィール情報にアクセス・編集可能。他のユーザーのプロフィールは編集不可。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 89 | プロフィール設定画面 | 主画面 | プロフィール表示・編集 |

## 機能種別

CRUD操作 / データ更新

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| profile[email] | String | No | メールアドレス | 有効なメール形式 |
| profile[name] | String | No | ユーザー名 | 必須（更新時） |
| profile[display_name] | String | No | 表示名 | - |
| profile[avatar] | File | No | アバター画像 | 15MB以下、JPEG/PNG/GIF |
| profile[message_signature] | String | No | メッセージ署名 | - |
| profile[ui_settings] | JSON | No | UI設定 | JSONオブジェクト |
| profile[phone_number] | String | No | 電話番号（カスタム属性） | - |
| profile[current_password] | String | Conditional | 現在のパスワード | パスワード変更時必須 |
| profile[password] | String | No | 新しいパスワード | Devise要件に従う |
| profile[password_confirmation] | String | No | パスワード確認 | passwordと一致 |

### 入力データソース

- フロントエンド画面からのJSON形式リクエスト
- 認証トークンからのユーザー識別

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| id | Integer | ユーザーID |
| name | String | ユーザー名 |
| display_name | String | 表示名 |
| email | String | メールアドレス |
| avatar_url | String | アバター画像URL |
| message_signature | String | メッセージ署名 |
| ui_settings | JSON | UI設定 |
| custom_attributes | JSON | カスタム属性 |
| confirmed | Boolean | メール確認済みフラグ |
| access_token | String | APIアクセストークン |
| account_id | Integer | アクティブアカウントID |
| role | String | 現在アカウントでのロール |
| accounts | Array | 所属アカウント一覧 |

### 出力先

- JSON形式でHTTPレスポンスとして返却

## 処理フロー

### 処理シーケンス

```
1. リクエスト受信
   └─ 認証トークンの検証
2. ユーザー情報取得
   └─ current_userから@userを設定
3. 処理分岐
   ├─ showアクション: プロフィール情報をJSONで返却
   └─ updateアクション:
       ├─ パスワード変更の場合
       │   └─ 現在のパスワード検証
       │       ├─ 成功: パスワード更新
       │       └─ 失敗: エラー返却
       ├─ プロフィール属性の更新
       └─ カスタム属性のマージ・保存
4. レスポンス生成
   └─ JBuilderテンプレートでJSON生成
```

### フローチャート

```mermaid
flowchart TD
    A[リクエスト受信] --> B{認証済み?}
    B -->|No| C[401 Unauthorized]
    B -->|Yes| D{アクション種別}
    D -->|show| E[プロフィール情報取得]
    D -->|update| F{パスワード変更?}
    F -->|Yes| G{現在のパスワード正しい?}
    G -->|No| H[エラー返却]
    G -->|Yes| I[パスワード更新]
    F -->|No| J[プロフィール属性更新]
    I --> J
    J --> K[カスタム属性マージ]
    K --> L[保存]
    E --> M[JSON生成]
    L --> M
    M --> N[レスポンス返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-171-01 | パスワード変更時の検証 | パスワード変更時は現在のパスワードを検証する | password パラメータが存在する場合 |
| BR-171-02 | メール変更時のGravatar取得 | メールアドレス変更時は30秒後にGravatarからアバターを取得試行 | email が変更された場合 |
| BR-171-03 | カスタム属性のマージ | 既存のカスタム属性に新しい値をマージする | custom_attributes が存在する場合 |

### 計算ロジック

特になし

## データベース操作仕様

### 操作別データベース影響一覧

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| プロフィール表示 | users | SELECT | ユーザー情報の取得 |
| プロフィール更新 | users | UPDATE | ユーザー情報の更新 |
| アカウント情報取得 | account_users | SELECT | 所属アカウント情報の取得 |

### テーブル別操作詳細

#### users

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | 全カラム | id = current_user.id | プロフィール表示時 |
| UPDATE | email | パラメータ値 | メールアドレス変更時 |
| UPDATE | name | パラメータ値 | ユーザー名変更時 |
| UPDATE | display_name | パラメータ値 | 表示名変更時 |
| UPDATE | message_signature | パラメータ値 | 署名変更時 |
| UPDATE | ui_settings | パラメータ値 | UI設定変更時 |
| UPDATE | custom_attributes | マージ後の値 | カスタム属性変更時 |
| UPDATE | encrypted_password | 暗号化後のパスワード | パスワード変更時 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 401 | Unauthorized | 認証トークンが無効 | 再ログイン |
| 422 | Unprocessable Entity | 現在のパスワードが不正 | 正しいパスワードを入力 |
| 422 | Unprocessable Entity | バリデーションエラー | 入力値を修正 |

### リトライ仕様

特になし

## トランザクション仕様

updateアクションでは暗黙のトランザクション内でユーザー情報が更新される。パスワード変更とプロフィール更新は同一トランザクション内で処理される。

## パフォーマンス要件

- レスポンス時間: 500ms以内
- 同時アクセス: 特別な制限なし

## セキュリティ考慮事項

- パスワード変更時は現在のパスワードの検証が必須
- パスワードはDeviseによりbcryptで暗号化して保存
- 認証トークンによるアクセス制御
- MFAに関連するOTPシークレットとバックアップコードは暗号化して保存

## 備考

- DeviseTokenAuthを使用した認証基盤上で動作
- Gravatarからのアバター取得は非同期ジョブで実行

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | user.rb | `app/models/user.rb` | Userモデルのスキーマ定義とカラム構成を確認。特に1-36行目のSchemaコメントを参照 |
| 1-2 | account_user.rb | `app/models/account_user.rb` | アカウントとユーザーの関連、availability等のカラムを確認 |

**読解のコツ**: Userモデルは多くのconcernをincludeしている。AccessTokenable、Avatarable、DeviseTokenAuth::Concerns::Userなどがプロフィール機能に関連する主要なconcernである。

#### Step 2: エントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | profiles_controller.rb | `app/controllers/api/v1/profiles_controller.rb` | コントローラーの全体構造、各アクションの実装 |

**主要処理フロー**:
1. **2行目**: `before_action :set_user` - 全アクション前にcurrent_userを@userに設定
2. **4行目**: `show` - プロフィール表示（JBuilderテンプレートへ委譲）
3. **6-16行目**: `update` - プロフィール更新処理
4. **7-10行目**: パスワード変更時の現在パスワード検証ロジック
5. **13-15行目**: プロフィール属性とカスタム属性の更新・保存

#### Step 3: ビューテンプレートを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | show.json.jbuilder | `app/views/api/v1/profiles/show.json.jbuilder` | レスポンスJSON構造 |
| 3-2 | _user.json.jbuilder | `app/views/api/v1/models/_user.json.jbuilder` | ユーザー情報のJSON出力詳細 |

**主要処理フロー**:
- **1行目**: partialテンプレートを呼び出し
- **_user.json.jbuilder 1-35行目**: アクセストークン、アカウント情報、アバターURL等を含む完全なユーザー情報を出力

#### Step 4: 関連するconcernを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | access_tokenable.rb | `app/models/concerns/access_tokenable.rb` | アクセストークンの自動生成 |
| 4-2 | avatarable.rb | `app/models/concerns/avatarable.rb` | アバター管理とGravatar連携 |

**主要処理フロー**:
- **access_tokenable.rb 4-6行目**: ユーザー作成時にアクセストークンを自動生成
- **avatarable.rb 19-26行目**: メール変更時にGravatarからアバターを取得するジョブをスケジュール

### プログラム呼び出し階層図

```
Api::V1::ProfilesController
    │
    ├─ show
    │      └─ JBuilder (show.json.jbuilder)
    │             └─ _user.json.jbuilder
    │                    └─ User#avatar_url (Avatarable)
    │                    └─ User#access_token (AccessTokenable)
    │
    └─ update
           ├─ User#valid_password? (Devise)
           ├─ User#assign_attributes
           ├─ User#custom_attributes.merge!
           └─ User#save!
                  └─ Avatarable#fetch_avatar_from_gravatar
```

### データフロー図

```
[入力]                    [処理]                         [出力]

HTTPリクエスト ───────▶ ProfilesController ───────▶ JSON Response
(profile params)              │
                              │
                              ▼
                        User Model
                              │
                              ├─▶ users テーブル
                              │
                              └─▶ account_users テーブル
                                    (accounts情報)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| profiles_controller.rb | `app/controllers/api/v1/profiles_controller.rb` | コントローラー | プロフィールAPIのエントリーポイント |
| user.rb | `app/models/user.rb` | モデル | ユーザーデータの管理 |
| account_user.rb | `app/models/account_user.rb` | モデル | ユーザーとアカウントの関連管理 |
| access_token.rb | `app/models/access_token.rb` | モデル | APIアクセストークンの管理 |
| access_tokenable.rb | `app/models/concerns/access_tokenable.rb` | concern | トークン自動生成機能 |
| avatarable.rb | `app/models/concerns/avatarable.rb` | concern | アバター管理機能 |
| show.json.jbuilder | `app/views/api/v1/profiles/show.json.jbuilder` | ビュー | showアクションのレスポンス |
| update.json.jbuilder | `app/views/api/v1/profiles/update.json.jbuilder` | ビュー | updateアクションのレスポンス |
| _user.json.jbuilder | `app/views/api/v1/models/_user.json.jbuilder` | ビュー | ユーザー情報のpartialテンプレート |
| routes.rb | `config/routes.rb` | 設定 | ルーティング定義（368-385行目） |
