# 機能設計書 198-プラットフォームユーザー

## 概要

本ドキュメントは、ChatwootにおけるPlatform API用ユーザー管理機能の設計を記載したものである。この機能により、外部アプリケーションがPlatform APIを通じてユーザーの作成・取得・更新・削除、およびSSOログインURLの生成が可能となる。

### 本機能の処理概要

**業務上の目的・背景**：Chatwootを他のシステムと統合する際、プログラムからユーザーを管理する必要がある。Platform APIは、外部アプリケーション（SaaS統合、カスタムダッシュボード、自動化ツール等）がChatwootのユーザーを操作するための安全なインターフェースを提供する。

**機能の利用シーン**：SaaS製品がChatwootを組み込む際に、顧客のユーザーを自動作成する。カスタムダッシュボードからユーザー情報を取得・更新する。SSOリンクを生成してシームレスなログイン体験を提供する。

**主要な処理内容**：
1. ユーザーの作成（既存ユーザーの再利用含む）
2. ユーザー情報の取得
3. ユーザー情報の更新
4. ユーザーの削除（非同期）
5. SSOログインURL生成
6. アクセストークンの取得

**関連システム・外部連携**：Platform App（api_access_token）を通じた認証。

**権限による制御**：Platform Appに関連付けられたユーザーのみ操作可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | APIのみ（画面なし） |

## 機能種別

CRUD操作 + 認証

## 入力仕様

### 入力パラメータ

#### createアクション

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| name | String | Yes | ユーザー名 | - |
| email | String | Yes | メールアドレス | 既存の場合は再利用 |
| password | String | No | パスワード | - |
| display_name | String | No | 表示名 | - |
| custom_attributes | Hash | No | カスタム属性 | - |

#### updateアクション

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| name | String | No | ユーザー名 | - |
| email | String | No | メールアドレス | - |
| password | String | No | パスワード | - |
| display_name | String | No | 表示名 | - |
| custom_attributes | Hash | No | カスタム属性 | 既存値とマージ |

### 入力データソース

- Platform API経由のHTTPリクエスト（JSON形式）
- api_access_tokenヘッダーによる認証

## 出力仕様

### 出力データ

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

### 出力先

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

## 処理フロー

### 処理シーケンス

```
1. リクエスト受信
   └─ api_access_tokenヘッダーの検証
2. Platform App確認
   └─ アクセストークンの所有者がPlatform Appか確認
3. アクション実行
   ├─ show: ユーザー情報を返却
   ├─ create: ユーザー作成または既存ユーザー再利用
   ├─ update: ユーザー情報更新
   ├─ destroy: 非同期削除ジョブ発行
   ├─ login: SSOログインURL生成
   └─ token: アクセストークン返却
4. Permissible検証（update/show/destroy/login/token）
   └─ Platform Appに関連付けられているか確認
```

### フローチャート

```mermaid
flowchart TD
    A[リクエスト受信] --> B{api_access_token有効?}
    B -->|No| C[401 Unauthorized]
    B -->|Yes| D{Platform App?}
    D -->|No| C
    D -->|Yes| E{アクション?}
    E -->|show| F[set_resource + validate_permissible]
    E -->|create| G[User.from_email or User.new]
    E -->|update| F
    E -->|destroy| F
    E -->|login| H[set_resource + validate_permissible]
    E -->|token| H
    F --> I{Permissible?}
    I -->|No| J[401 Non permissible]
    I -->|Yes| K[処理実行]
    G --> L[skip_confirmation! + save!]
    L --> M[Permissible作成]
    H --> I
    K --> N[レスポンス返却]
    M --> N
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-198-01 | Platform App認証 | api_access_tokenがPlatform Appに紐づいている必要がある | 常時 |
| BR-198-02 | Permissible検証 | 操作対象リソースがPlatform Appに関連付けられている必要がある | show/update/destroy/login/token |
| BR-198-03 | 既存ユーザー再利用 | メールアドレスが既存の場合は既存ユーザーを再利用 | create |
| BR-198-04 | 確認スキップ | 作成時はメール確認をスキップ | create |
| BR-198-05 | カスタム属性マージ | 更新時はカスタム属性を既存値とマージ | update |
| BR-198-06 | 再確認スキップ | メールアドレス変更時は再確認をスキップ | update |
| BR-198-07 | 非同期削除 | 削除はDeleteObjectJobで非同期実行 | destroy |

### 計算ロジック

**カスタム属性マージ**:
```ruby
def user_custom_attributes
  return @resource.custom_attributes.merge(user_params[:custom_attributes]) if user_params[:custom_attributes]
  @resource.custom_attributes
end
```

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| show | users | SELECT | ユーザー情報取得 |
| create | users | INSERT/UPDATE | ユーザー作成または既存更新 |
| create | platform_app_permissibles | INSERT | Permissible関連付け |
| update | users | UPDATE | ユーザー情報更新 |
| destroy | users | DELETE | ユーザー削除（非同期） |

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

#### users

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | id | params[:id] | - |
| INSERT | name, email, password, display_name, custom_attributes | リクエストパラメータ | - |
| UPDATE | name, email, password, display_name, custom_attributes | リクエストパラメータ | custom_attributesはマージ |

#### platform_app_permissibles

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | platform_app_id, permissible_type, permissible_id | Platform App ID, 'User', User ID | find_or_create_by |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 401 | Unauthorized | api_access_tokenが無効 | エラーメッセージ「Invalid access_token」 |
| 401 | Unauthorized | Platform Appに関連付けられていないリソース | エラーメッセージ「Non permissible resource」 |

### リトライ仕様

なし

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

- ユーザー作成とPermissible作成は同一リクエスト内で実行
- 削除は非同期ジョブで実行

## パフォーマンス要件

- DeleteObjectJobによる非同期削除でレスポンス時間を短縮

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

- api_access_tokenによるPlatform App認証
- Permissible検証によるアクセス制御
- メール確認スキップはPlatform API経由での作成時のみ

## 備考

- SSOログインURLはgenerate_sso_linkメソッドで生成される
- Platform APIはサードパーティ統合用に設計されている

---

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

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

### 推奨読解順序

#### Step 1: 基底コントローラーを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | platform_controller.rb | `app/controllers/platform_controller.rb` | Platform API共通処理 |

**主要処理フロー**:
1. **4行目**: `before_action :ensure_access_token` - トークン検証
2. **5行目**: `before_action :set_platform_app` - Platform App設定
3. **6-7行目**: `before_action :set_resource, :validate_platform_app_permissible` - リソース検証
4. **17-20行目**: `ensure_access_token`メソッド - トークン取得
5. **22-25行目**: `set_platform_app`メソッド - Platform App検証
6. **32-36行目**: `validate_platform_app_permissible`メソッド - Permissible検証

**読解のコツ**: `@access_token.owner`がPlatformAppインスタンスであることを確認している。これにより、Platform App以外のアクセストークンでのAPIアクセスを防いでいる。

#### Step 2: ユーザーコントローラーを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | users_controller.rb | `app/controllers/platform/api/v1/users_controller.rb` | ユーザー管理API |

**主要処理フロー**:
1. **5-6行目**: login/tokenアクションのbefore_action設定
2. **8行目**: `show`アクション - ユーザー情報表示
3. **10-15行目**: `create`アクション - ユーザー作成
4. **17-19行目**: `login`アクション - SSOログインURL生成
5. **21行目**: `token`アクション - トークン返却
6. **23-30行目**: `update`アクション - ユーザー更新
7. **32-35行目**: `destroy`アクション - ユーザー削除
8. **39-48行目**: `user_custom_attributes`と`user_update_params` - カスタム属性マージ

#### Step 3: ビューを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | _user.json.jbuilder | `app/views/platform/api/v1/models/_user.json.jbuilder` | JSON出力形式 |

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

```
Platform::Api::V1::UsersController
    │
    ├─ PlatformController (継承)
    │      ├─ ensure_access_token
    │      │      └─ AccessToken.find_by(token: ...)
    │      ├─ set_platform_app
    │      │      └─ @access_token.owner.is_a?(PlatformApp)
    │      └─ validate_platform_app_permissible
    │             └─ @platform_app.platform_app_permissibles.find_by(...)
    │
    ├─ create
    │      ├─ User.from_email(email) || User.new
    │      ├─ skip_confirmation!
    │      ├─ save!
    │      └─ platform_app_permissibles.find_or_create_by!(...)
    │
    ├─ update
    │      ├─ user_update_params (custom_attributes merge)
    │      ├─ skip_reconfirmation!
    │      └─ save!
    │
    ├─ destroy
    │      └─ DeleteObjectJob.perform_later(@resource)
    │
    ├─ login
    │      └─ @resource.generate_sso_link
    │
    └─ token
           └─ @resource.access_token.token
```

### データフロー図

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

api_access_token   ───▶ PlatformController
(Header)                    │
                            ▼
                    ensure_access_token
                            │
                            ▼
                    set_platform_app
                            │
                            ▼
name, email,       ───▶ UsersController#create
password,                   │
display_name,               ▼
custom_attributes  ───▶ User.from_email or User.new
                            │
                            ▼
                    skip_confirmation!
                            │
                            ▼
                    save!
                            │
                            ▼
                    find_or_create_by!(permissible)
                            │
                            ▼
                    { user JSON }
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| users_controller.rb | `app/controllers/platform/api/v1/users_controller.rb` | ソース | ユーザー管理APIコントローラー |
| platform_controller.rb | `app/controllers/platform_controller.rb` | ソース | Platform API基底コントローラー |
| _user.json.jbuilder | `app/views/platform/api/v1/models/_user.json.jbuilder` | テンプレート | JSON出力テンプレート |
| user.rb | `app/models/user.rb` | ソース | Userモデル |
| platform_app.rb | `app/models/platform_app.rb` | ソース | PlatformAppモデル |
| platform_app_permissible.rb | `app/models/platform_app_permissible.rb` | ソース | Permissibleモデル |
| routes.rb | `config/routes.rb` | 設定 | ルーティング定義（487-492行目） |
