# 機能設計書 67-ユーザー無効化

## 概要

本ドキュメントは、Fizzyアプリケーションにおけるユーザーを無効化（退会）する機能の設計を詳述する。

### 本機能の処理概要

**業務上の目的・背景**：チームメンバーが退職や異動などでアカウントから離脱する場合、そのユーザーを無効化する必要がある。無効化されたユーザーはログインできなくなり、ボードへのアクセス権も失われる。ただし、過去のアクティビティ（作成したカード、コメントなど）は保持される。

**機能の利用シーン**：アカウント管理者がメンバーを退会させる場面、または本人が自主的に退会する場面で利用される。アカウント設定画面のユーザー一覧から実行される。

**主要な処理内容**：
1. トランザクション内で以下の処理を実行
2. ユーザーのすべてのボードアクセス権（accesses）を削除
3. ユーザーのactive属性をfalseに更新
4. ユーザーとidentityの関連を解除
5. ActionCableのリモート接続を切断（reconnect: false）

**関連システム・外部連携**：ActionCableによるリアルタイム接続の切断、認証システム（Identity）との連携解除。

**権限による制御**：can_change?メソッドで権限を判定。自分自身または管理者（admin）のみが無効化可能。ただし、オーナー（owner）は他者から無効化されない。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 53 | アカウント設定画面 | 主画面 | ユーザーを無効化（退会） |

## 機能種別

データ更新処理（UPDATE / DELETE）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| id | UUID | Yes | ユーザーID（URLパラメータ） | Current.account.users.active内に存在 |

### 入力データソース

- URLパラメータ（id）
- 確認ダイアログからの承認（turbo_confirm）

## 出力仕様

### 出力データ

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

### 出力先

- アカウント設定画面へリダイレクト（HTML）
- head :no_content（JSON）

## 処理フロー

### 処理シーケンス

```
1. リクエスト受信（DELETE /users/:id）
   └─ UsersController#destroy
2. ユーザー取得
   └─ set_user (before_action)
3. 権限チェック
   └─ ensure_permission_to_change_user (before_action)
4. 無効化処理
   └─ @user.deactivate
5. リダイレクト
   └─ redirect_to account_settings_path
```

### フローチャート

```mermaid
flowchart TD
    A[DELETE /users/:id] --> B[set_user でユーザー取得]
    B --> C{ユーザーが存在?}
    C -->|No| D[404 Not Found]
    C -->|Yes| E[ensure_permission_to_change_user]
    E --> F{can_change?}
    F -->|No| G[403 Forbidden]
    F -->|Yes| H[@user.deactivate]
    H --> I[Transaction開始]
    I --> J[accesses.destroy_all]
    J --> K[active: false, identity: nil 更新]
    K --> L[close_remote_connections]
    L --> M[Transaction完了]
    M --> N[redirect_to account_settings_path]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-67-01 | 自己退会可能 | 自分自身は常に無効化可能 | other == self |
| BR-67-02 | 管理者操作可能 | 管理者は非オーナーユーザーを無効化可能 | admin? && !other.owner? |
| BR-67-03 | オーナー保護 | オーナーは他者から無効化されない | other.owner? |
| BR-67-04 | アクセス権削除 | 無効化時にすべてのボードアクセス権を削除 | 常に |
| BR-67-05 | Identity解除 | 無効化時にIdentityとの関連を解除 | 常に |
| BR-67-06 | 接続切断 | ActionCableの接続を切断（再接続不可） | 常に |

### 計算ロジック

特になし

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| アクセス削除 | accesses | DELETE | ユーザーの全アクセス権を削除 |
| ユーザー更新 | users | UPDATE | active=false, identity_id=nilに更新 |

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

#### accesses

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| DELETE | - | user_id = @user.id | 全レコード削除 |

#### users

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | active | false | 無効化フラグ |
| UPDATE | identity_id | NULL | Identity関連解除 |
| UPDATE | updated_at | 現在日時 | 自動更新 |

## エラー処理

### エラーケース一覧

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

### リトライ仕様

リトライ不要。処理はトランザクションで保護されているため、失敗時は自動ロールバック。

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

- deactivateメソッド内でtransactionブロックを使用
- accesses.destroy_all、update!、close_remote_connectionsをアトミックに実行
- いずれかが失敗した場合はロールバック

## パフォーマンス要件

- レスポンス時間：1秒以内
- アクセス権の削除は一括で実行

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

- 認証必須
- can_change?による権限チェック
- 削除確認ダイアログ（turbo_confirm）による誤操作防止
- Identity関連解除によりログイン不可に

## 備考

- 無効化されたユーザーは一覧から非表示になる（activeスコープ）
- 物理削除ではなく論理削除（active=false）
- 過去のアクティビティ（カード、コメント等）は保持される
- 無効化後の再有効化機能は現時点では未実装

---

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

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

### 推奨読解順序

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

Userモデルのdeactivateメソッドを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | user.rb | `app/models/user.rb` | deactivateメソッドの実装 |

**読解のコツ**: user.rbの19-25行目でdeactivateメソッドが定義されている。transactionブロック内でaccesses.destroy_all、update!、close_remote_connectionsを実行。

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

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

**主要処理フロー**:
1. **2行目**: before_action :set_userでユーザーを取得
2. **3行目**: before_action :ensure_permission_to_change_userでdestroyアクションに権限チェック
3. **29-36行目**: destroyアクションで@user.deactivateを呼び出し

#### Step 3: 権限判定ロジックを理解する

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

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | _user.html.erb | `app/views/account/settings/_user.html.erb` | 削除ボタンの実装 |

**読解のコツ**: _user.html.erbの23-28行目で削除ボタンが実装されている。button_toでDELETEリクエスト、turbo_confirmで確認ダイアログ、disabled: !Current.user.can_administer?(user)で権限制御。

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

```
UsersController#destroy
    │
    ├─ before_action :set_user
    │      └─ Current.account.users.active.find(params[:id])
    │
    ├─ before_action :ensure_permission_to_change_user
    │      └─ Current.user.can_change?(@user)
    │
    └─ @user.deactivate
           │
           └─ transaction do
                  │
                  ├─ accesses.destroy_all
                  │      └─ DELETE FROM accesses WHERE user_id = ?
                  │
                  ├─ update! active: false, identity: nil
                  │      └─ UPDATE users SET active = false, identity_id = NULL
                  │
                  └─ close_remote_connections
                         └─ ActionCable.server.remote_connections
                                .where(current_user: self)
                                .disconnect(reconnect: false)
```

### データフロー図

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

params[:id]     ───▶ Current.account.users.active.find ───▶ @user
                              │
                              ▼
                    @user.deactivate
                              │
                    ┌─────────┴─────────┐
                    ▼                   ▼
          accesses.destroy_all    update!(active: false, identity: nil)
                              │
                              ▼
                    close_remote_connections
                              │
                              ▼
                    redirect_to account_settings_path
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| users_controller.rb | `app/controllers/users_controller.rb` | コントローラー | ユーザー無効化のエントリーポイント |
| user.rb | `app/models/user.rb` | モデル | deactivateメソッドの実装 |
| role.rb | `app/models/user/role.rb` | モデルconcern | can_change?の定義 |
| _user.html.erb | `app/views/account/settings/_user.html.erb` | ビュー（パーシャル） | 削除ボタンの表示 |
| routes.rb | `config/routes.rb` | 設定 | ルーティング定義（13行目） |
