# 機能設計書 70-ロール変更

## 概要

本ドキュメントは、Fizzyアプリケーションにおけるユーザーのロール（member/admin）を変更する機能の設計を詳述する。

### 本機能の処理概要

**業務上の目的・背景**：チーム内での権限管理を行うため、ユーザーのロールを変更する機能が必要である。管理者（admin）はアカウント設定の変更やユーザー管理が可能であり、メンバー（member）は通常の操作のみが許可される。

**機能の利用シーン**：アカウント設定画面でユーザー一覧を表示し、特定のユーザーのロールを変更する場面で利用される。チェックボックスの切り替えで即座にロール変更が実行される。

**主要な処理内容**：
1. 対象ユーザーの特定
2. 権限チェック（can_administer?）
3. ロールの値をmemberまたはadminに設定
4. データベースを更新
5. アカウント設定画面にリダイレクト

**関連システム・外部連携**：ユーザー一覧表示（機能No.64）と連携。

**権限による制御**：can_administer?メソッドで権限を判定。管理者（admin）のみが他のユーザーのロールを変更可能。ただし、オーナー（owner）のロールは変更不可。また、自分自身のロールは変更不可。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 53 | アカウント設定画面 | 主画面 | ユーザーのロール（member/admin）を変更 |

## 機能種別

データ更新処理（UPDATE）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| user_id | UUID | Yes | ユーザーID（URLパラメータ） | Current.account.users.active内に存在 |
| user[role] | String | Yes | ロール（admin または member） | %w[member admin]内の値、それ以外はmemberにフォールバック |

### 入力データソース

- URLパラメータ（user_id）
- フォームパラメータ（user[role]）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| リダイレクト先 | URL | /account/settings |

### 出力先

- アカウント設定画面へリダイレクト

## 処理フロー

### 処理シーケンス

```
1. リクエスト受信（PATCH /users/:user_id/role）
   └─ Users::RolesController#update
2. ユーザー取得
   └─ set_user (before_action)
3. 権限チェック
   └─ ensure_permission_to_administer_user (before_action)
   └─ Current.user.can_administer?(@user)
4. ロールパラメータ検証
   └─ role_params: admin/memberのみ許可、それ以外はmember
5. ユーザー更新
   └─ @user.update!(role_params)
6. リダイレクト
   └─ redirect_to account_settings_path
```

### フローチャート

```mermaid
flowchart TD
    A[PATCH /users/:user_id/role] --> B[set_user でユーザー取得]
    B --> C{ユーザーが存在?}
    C -->|No| D[404 Not Found]
    C -->|Yes| E[ensure_permission_to_administer_user]
    E --> F{can_administer?}
    F -->|No| G[403 Forbidden]
    F -->|Yes| H[role_params取得]
    H --> I{roleが有効値?}
    I -->|admin/member| J[そのまま使用]
    I -->|その他| K[memberにフォールバック]
    J --> L[@user.update!]
    K --> L
    L --> M[redirect_to account_settings_path]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-70-01 | 管理者のみ変更可能 | admin権限を持つユーザーのみがロールを変更可能 | 常に |
| BR-70-02 | オーナー保護 | オーナーのロールは変更不可 | other.owner? |
| BR-70-03 | 自己変更禁止 | 自分自身のロールは変更不可 | other == self |
| BR-70-04 | ロール値制限 | admin/member以外の値はmemberにフォールバック | 常に |
| BR-70-05 | ownerロール不可 | ownerロールへの変更は不可（presence_in制限） | 常に |

### 計算ロジック

role_paramsの処理:
- params[:user][:role].presence_in(%w[member admin]) || "member"
- 有効な値（member/admin）であればその値を使用
- 無効な値の場合はmemberにフォールバック

can_administer?(other)の判定ロジック:
- admin? が true（管理者権限を持つ）
- かつ other.owner? が false（対象がオーナーではない）
- かつ other != self（対象が自分自身ではない）

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| ロール更新 | users | UPDATE | roleカラムの更新 |

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

#### users

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | role | 'admin' または 'member' | 許可値のみ |
| UPDATE | updated_at | 現在日時 | 自動更新 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 404 | ActiveRecord::RecordNotFound | ユーザーが存在しない | Rails標準の404ページ |
| 403 | Forbidden | can_administer?がfalse | head :forbidden |

### リトライ仕様

リトライ不要。

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

- @user.update!は暗黙のトランザクションで実行
- 失敗時は例外が発生しロールバック

## パフォーマンス要件

- レスポンス時間：500ms以内

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

- 認証必須
- can_administer?による厳格な権限チェック
- 自分自身のロール変更を防止
- オーナーロールへの昇格を防止（presence_in制限）
- 無効な値のフォールバック処理

## 備考

- チェックボックスによるUI実装（adminならチェックON、memberならOFF）
- update!を使用しているため失敗時は例外が発生
- オーナー（owner）ロールは別途設定され、この機能では変更不可

---

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

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

### 推奨読解順序

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

User::Roleモジュールの構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | role.rb | `app/models/user/role.rb` | ロールの定義とcan_administer? |

**読解のコツ**: role.rbの5行目でenumが定義されている（owner, admin, member, system）。can_administer?（21-23行目）は管理者が自分以外の非オーナーを管理できるかを判定。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | roles_controller.rb | `app/controllers/users/roles_controller.rb` | updateアクション |

**主要処理フロー**:
1. **2行目**: before_action :set_user
2. **3行目**: before_action :ensure_permission_to_administer_user
3. **5-8行目**: updateアクションで@user.update!(role_params)を実行
4. **11-13行目**: set_userでCurrent.account.users.active.findを実行
5. **15-17行目**: ensure_permission_to_administer_userでcan_administer?チェック
6. **19-21行目**: role_paramsで有効な値のみ許可し、それ以外はmemberにフォールバック

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | _user.html.erb | `app/views/account/settings/_user.html.erb` | ロール変更チェックボックス |

**読解のコツ**: _user.html.erbの12-19行目でロール変更のフォームが実装されている。チェックボックスはchecked: user.admin?でadminロールの場合にチェック、値はadmin/memberを切り替え。

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

```
Users::RolesController#update
    │
    ├─ before_action :set_user
    │      └─ Current.account.users.active.find(params[:user_id])
    │
    ├─ before_action :ensure_permission_to_administer_user
    │      └─ Current.user.can_administer?(@user)
    │             ├─ admin? = true
    │             ├─ !@user.owner? = true
    │             └─ @user != Current.user = true
    │
    └─ @user.update!(role_params)
           │
           └─ role: params[:user][:role].presence_in(%w[member admin]) || "member"
```

### データフロー図

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

params[:user_id] ───▶ Current.account.users.active.find ───▶ @user
                              │
params[:user][:role] ───▶ presence_in(%w[member admin])
                              │
                    ┌─────────┴─────────┐
                    ▼                   ▼
              'admin'/'member'       その他
                    │                   │
                    │                   ▼
                    │              'member' (フォールバック)
                    └─────────┬─────────┘
                              ▼
                    @user.update!(role: role)
                              │
                              ▼
                    redirect_to account_settings_path
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| roles_controller.rb | `app/controllers/users/roles_controller.rb` | コントローラー | ロール変更のエントリーポイント |
| role.rb | `app/models/user/role.rb` | モデルconcern | ロール定義とcan_administer? |
| _user.html.erb | `app/views/account/settings/_user.html.erb` | ビュー（パーシャル） | ロール変更チェックボックス |
| routes.rb | `config/routes.rb` | 設定 | ルーティング定義（16行目） |
