# 機能設計書 54-ユーザー登録

## 概要

本ドキュメントは、Fat Free CRMにおける新規ユーザー登録機能の設計書である。Deviseライブラリを利用したユーザーセルフサービス登録処理について、処理仕様・セキュリティ・コード構造を定義する。

### 本機能の処理概要

新規ユーザーが自身でアカウントを作成する機能である。ユーザー名、メールアドレス、パスワードを入力し、アカウントを作成する。システム設定により、即時有効化または管理者承認が必要な場合がある。

**業務上の目的・背景**：新しいチームメンバーがCRMシステムを利用開始する際、管理者に依存せずに自分でアカウントを作成できることで、オンボーディングプロセスが効率化される。また、システム設定により登録を無効化したり、承認フローを挟むことで、組織のセキュリティポリシーに対応できる。

**機能の利用シーン**：
- 新入社員がCRMシステムのアカウントを作成する場面
- 外部パートナーにCRMアクセスを提供する場面
- 新しいプロジェクトチームメンバーの追加

**主要な処理内容**：
1. ユーザー登録画面でユーザー名、メールアドレス、パスワードを入力
2. バリデーションチェック（ユーザー名・メールの一意性、パスワード確認）
3. Userレコード作成
4. システム設定に応じて承認待ち状態に設定
5. 確認メール送信（Confirmable有効時）
6. 登録完了後、ログイン画面にリダイレクト

**関連システム・外部連携**：
- メール送信（確認メール）：Action Mailer経由

**権限による制御**：
- システム設定（Setting.user_signup）により登録の可否を制御
  - :allowed - 即時登録可能
  - :needs_approval - 管理者承認が必要
  - :not_allowed - セルフ登録不可

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 2 | ユーザー登録画面 | 主画面 | 新規ユーザー情報入力、アカウント作成 |

## 機能種別

ユーザー登録処理 / INSERT操作

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| user[username] | String | Yes | ユーザー名 | 必須、一意、英数字・ハイフン・アンダースコアのみ |
| user[email] | String | Yes | メールアドレス | 必須、一意、メール形式 |
| user[password] | String | Yes | パスワード | 必須 |
| user[password_confirmation] | String | Yes | パスワード確認 | passwordと一致 |

### 入力データソース

- 画面入力（ユーザー登録フォーム）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| フラッシュメッセージ | String | 登録結果のメッセージ |
| 確認メール | Email | メールアドレス確認用のメール |

### 出力先

- usersテーブル（新規レコード）
- メール（確認メール）

## 処理フロー

### 処理シーケンス

```
1. ユーザー登録画面表示（GET /users/sign_up）
   └─ RegistrationsController#new
2. ユーザーがフォームに情報を入力
   └─ username, email, password, password_confirmation
3. フォーム送信（POST /users）
   └─ Devise::RegistrationsController#create
4. バリデーション実行
   ├─ username: 一意性、形式チェック
   ├─ email: 一意性、形式チェック
   └─ password: 確認フィールドとの一致チェック
5. システム設定チェック
   └─ Setting.user_signup の値を確認
6. ユーザーレコード作成
   ├─ needs_approval設定時: suspended_atを設定
   └─ confirmable有効時: 確認メール送信
7. 結果に応じてリダイレクト
   ├─ 成功時: ログイン画面（after_inactive_sign_up_path_for）
   └─ 失敗時: 登録画面（エラー表示）
```

### フローチャート

```mermaid
flowchart TD
    A[ユーザー登録画面表示] --> B[情報入力]
    B --> C[フォーム送信]
    C --> D{バリデーション}
    D -->|失敗| E[エラー表示]
    D -->|成功| F{signup設定?}
    F -->|not_allowed| G[登録不可]
    F -->|needs_approval| H[承認待ち状態で作成]
    F -->|allowed| I[通常作成]
    H --> J[確認メール送信]
    I --> J
    J --> K[ログイン画面へリダイレクト]
    E --> A
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-54-01 | ユーザー名一意性 | ユーザー名はシステム内で一意でなければならない（大文字小文字区別なし） | 常時 |
| BR-54-02 | メール一意性 | メールアドレスはシステム内で一意でなければならない（大文字小文字区別なし） | 常時 |
| BR-54-03 | パスワード確認 | パスワードと確認用パスワードが一致すること | 常時 |
| BR-54-04 | 承認フロー | needs_approval設定時は管理者承認まで停止状態 | 設定依存 |
| BR-54-05 | メール確認 | confirmable有効時はメール確認完了までログイン不可 | 設定依存 |
| BR-54-06 | 登録可否 | Setting.user_signupがnot_allowedの場合は登録リンク非表示 | 設定依存 |

### 計算ロジック

特になし

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| ユーザー作成 | users | INSERT | 新規ユーザーレコード作成 |

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

#### users

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | username | 入力値 | 必須 |
| INSERT | email | 入力値 | 必須 |
| INSERT | encrypted_password | bcryptハッシュ値 | パスワードのハッシュ |
| INSERT | password_salt | ソルト値 | bcrypt用 |
| INSERT | admin | false | デフォルト |
| INSERT | sign_in_count | 0 | 初期値 |
| INSERT | suspended_at | 現在日時またはNULL | needs_approval時に設定 |
| INSERT | confirmation_token | トークン値 | confirmable用 |
| INSERT | confirmation_sent_at | 現在日時 | confirmable用 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | バリデーションエラー | ユーザー名が既に使用されている | エラーメッセージ表示 |
| - | バリデーションエラー | メールアドレスが既に使用されている | エラーメッセージ表示 |
| - | バリデーションエラー | パスワードと確認が不一致 | エラーメッセージ表示 |
| - | バリデーションエラー | ユーザー名の形式が不正 | エラーメッセージ表示 |
| - | バリデーションエラー | メールアドレスの形式が不正 | エラーメッセージ表示 |

### リトライ仕様

- 登録失敗時は同一画面で修正・再試行可能

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

ユーザーレコード作成は単一トランザクションで処理。確認メール送信は非同期で実行される場合がある。

## パフォーマンス要件

- レスポンス時間: 2秒以内（メール送信を含む場合）
- パスワードハッシュ化にbcryptを使用（意図的に処理時間がかかる）

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

- パスワードはbcrypt（encryptable）でハッシュ化して保存
- CSRFトークン検証によりクロスサイトリクエストフォージェリを防止
- ユーザー名・メールアドレスの一意性チェックはレースコンディションに注意（DBレベルの制約あり）
- 確認メールのトークンは推測困難なランダム値

## 備考

- DeviseのRegisterableモジュールを使用
- 登録後のリダイレクト先はafter_inactive_sign_up_path_forでカスタマイズ
- プロファイル編集はDevise標準ではなく独自のUsersControllerを使用

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | user.rb | `app/models/users/user.rb` | バリデーションルール、Deviseモジュール |
| 1-2 | schema.rb | `db/schema.rb` | usersテーブル構造 |

**読解のコツ**:
- **49-50行目（user.rb）**: Deviseモジュール設定（registerable, confirmable）
- **51行目（user.rb）**: `before_create :suspend_if_needs_approval`
- **87-98行目（user.rb）**: バリデーションルール
- **182-184行目（user.rb）**: `suspend_if_needs_approval`メソッド

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | registrations_controller.rb | `app/controllers/registrations_controller.rb` | Devise拡張 |
| 2-2 | routes.rb | `config/routes.rb` | ルーティング |

**主要処理フロー**:
1. **8行目（registrations_controller.rb）**: Devise::RegistrationsControllerを継承
2. **12-14行目（registrations_controller.rb）**: editをprofile_pathにリダイレクト
3. **16-18行目（registrations_controller.rb）**: 登録後のリダイレクト先

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | new.html.haml | `app/views/devise/registrations/new.html.haml` | 登録フォームUI |

**主要処理フロー**:
- **2行目**: simple_form_forで登録フォーム生成
- **3-5行目**: ログインリンク
- **10-18行目**: username, email, password, password_confirmationフィールド
- **20-21行目**: 送信ボタン

#### Step 4: システム設定を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | user.rb | `app/models/users/user.rb` | can_signup?クラスメソッド |

**主要処理フロー**:
- **200-202行目**: `User.can_signup?`でSetting.user_signupを確認

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

```
GET /users/sign_up
    │
    └─ Devise::RegistrationsController#new
           └─ views/devise/registrations/new.html.haml

POST /users
    │
    └─ Devise::RegistrationsController#create
           │
           ├─ User.new(user_params)
           │
           ├─ user.save
           │      │
           │      ├─ バリデーション実行
           │      │
           │      └─ before_create :suspend_if_needs_approval
           │             └─ Setting.user_signup == :needs_approval 時に停止
           │
           ├─ send_confirmation_instructions（Confirmable）
           │
           └─ redirect_to after_inactive_sign_up_path_for
                  └─ new_user_session_path
```

### データフロー図

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

登録フォーム
  │
  ├─ username ───▶ バリデーション ───────────▶ usersテーブル
  ├─ email ──────▶ 一意性チェック              │
  ├─ password ───▶ bcryptハッシュ化 ─────────▶ encrypted_password
  └─ password_confirmation ───────────────────┘
                           │
                           ├───────────────────▶ confirmation_token
                           │                      生成・保存
                           │
                           └───────────────────▶ 確認メール送信
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| registrations_controller.rb | `app/controllers/registrations_controller.rb` | コントローラー | 登録処理カスタマイズ |
| user.rb | `app/models/users/user.rb` | モデル | ユーザーモデル、バリデーション |
| new.html.haml | `app/views/devise/registrations/new.html.haml` | ビュー | 登録フォーム |
| routes.rb | `config/routes.rb` | 設定 | ルーティング定義 |
| schema.rb | `db/schema.rb` | スキーマ | usersテーブル定義 |
| confirmation_instructions.html.haml | `app/views/devise/mailer/confirmation_instructions.html.haml` | ビュー | 確認メールテンプレート |
