# 機能設計書 52-ログイン

## 概要

本ドキュメントは、Fat Free CRMにおけるユーザー認証（ログイン）機能の設計書である。Deviseライブラリを利用したユーザー認証処理について、処理仕様・セキュリティ・コード構造を定義する。

### 本機能の処理概要

ユーザーがユーザー名またはメールアドレスとパスワードを入力し、システムへの認証を行う機能である。認証成功後はセッションが作成され、ダッシュボード画面にリダイレクトされる。

**業務上の目的・背景**：CRMシステムには顧客情報や商談情報など機密性の高いデータが含まれるため、認証されたユーザーのみがアクセスできるようにする必要がある。また、ユーザーごとにアクセス権限や表示データが異なるため、個人識別のための認証は必須である。

**機能の利用シーン**：
- 業務開始時にシステムにアクセスする場面
- セッションタイムアウト後に再認証する場面
- 別のデバイスからアクセスする場面
- 「ログイン状態を維持する」オプションを使用してリマインダー認証を行う場面

**主要な処理内容**：
1. ユーザーがログイン画面でユーザー名/メールアドレスとパスワードを入力
2. フォーム送信でDevise::SessionsController#createが呼び出される
3. Userモデルでデータベース認証を実行
4. 認証成功時：セッション作成、サインイン回数更新、最終ログイン日時記録
5. 認証成功時：ダッシュボード（ホーム画面）にリダイレクト
6. 認証失敗時：エラーメッセージを表示してログイン画面に戻る

**関連システム・外部連携**：特になし。Deviseライブラリによる内部認証を使用。

**権限による制御**：
- 認証前はログイン画面・ユーザー登録画面・パスワードリセット画面のみアクセス可能
- アカウントが停止されている場合はログイン不可
- メール確認が完了していない場合はログイン不可（設定による）
- 管理者承認待ちの場合はログイン不可

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 1 | ログイン画面 | 主画面 | メールアドレス・パスワード入力、認証実行、セッション作成 |

## 機能種別

認証処理 / セッション作成

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| user[email] | String | Yes | ユーザー名またはメールアドレス | 必須 |
| user[password] | String | Yes | パスワード | 必須 |
| user[remember_me] | Boolean | No | ログイン状態を維持するか | true/false |

### 入力データソース

- 画面入力（ログインフォーム）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| セッション | HTTPセッション | 認証済みセッション情報 |
| リマインバートークン | String | remember_me有効時に発行されるトークン |
| フラッシュメッセージ | String | 認証結果のメッセージ |

### 出力先

- HTTPセッション（認証情報）
- usersテーブル（ログイン履歴更新）
- ブラウザCookie（remember_meトークン）

## 処理フロー

### 処理シーケンス

```
1. ログイン画面表示（GET /users/sign_in）
   └─ SessionsController#new → sessions/new.html.haml
2. ユーザーがフォームに認証情報を入力
   └─ ユーザー名/メールアドレス、パスワード、remember_me
3. フォーム送信（POST /users/sign_in）
   └─ SessionsController#create
4. 認証処理実行
   ├─ User.find_for_database_authentication
   │      └─ username または email でユーザー検索
   ├─ valid_password? でパスワード検証
   └─ active_for_authentication? でアカウント状態確認
5. 認証結果判定
   ├─ 成功時：セッション作成、ログイン情報更新
   │      └─ current_sign_in_at, sign_in_count 等を更新
   └─ 失敗時：エラーメッセージ設定
6. リダイレクト
   ├─ 成功時：root_path（ダッシュボード）
   └─ 失敗時：ログイン画面（エラー表示）
```

### フローチャート

```mermaid
flowchart TD
    A[ログイン画面表示] --> B[認証情報入力]
    B --> C[フォーム送信]
    C --> D{ユーザー存在?}
    D -->|No| E[認証失敗]
    D -->|Yes| F{パスワード正しい?}
    F -->|No| E
    F -->|Yes| G{アカウント有効?}
    G -->|No| H[アカウント無効エラー]
    G -->|Yes| I{メール確認済み?}
    I -->|No| J[メール未確認エラー]
    I -->|Yes| K{承認済み?}
    K -->|No| L[承認待ちエラー]
    K -->|Yes| M[セッション作成]
    M --> N[ログイン情報更新]
    N --> O[ダッシュボードへリダイレクト]
    E --> P[エラーメッセージ表示]
    H --> P
    J --> P
    L --> P
    P --> A
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-52-01 | ユーザー名/メール認証 | ユーザー名またはメールアドレスのどちらでもログイン可能 | 常時 |
| BR-52-02 | 大文字小文字区別なし | ユーザー名・メールアドレスの検索は大文字小文字を区別しない | 常時 |
| BR-52-03 | アカウント停止チェック | suspended_atが設定されているユーザーはログイン不可 | 常時 |
| BR-52-04 | メール確認チェック | confirmed_atがNULLのユーザーはログイン不可 | Devise設定による |
| BR-52-05 | 承認チェック | signup設定がneeds_approvalの場合、承認前はログイン不可 | 設定による |
| BR-52-06 | Remember Me | remember_meチェック時は長期セッションを維持 | ユーザー選択時 |

### 計算ロジック

特になし

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| ユーザー検索 | users | SELECT | username/emailでユーザーを検索 |
| ログイン情報更新 | users | UPDATE | サインイン履歴を更新 |
| セッション保存 | sessions | INSERT/UPDATE | セッションデータを保存 |

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

#### users（認証成功時）

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | current_sign_in_at | 現在日時 | 今回のログイン日時 |
| UPDATE | last_sign_in_at | 前回のcurrent_sign_in_at | 前回のログイン日時 |
| UPDATE | current_sign_in_ip | リクエスト元IP | 今回のログインIP |
| UPDATE | last_sign_in_ip | 前回のcurrent_sign_in_ip | 前回のログインIP |
| UPDATE | sign_in_count | sign_in_count + 1 | ログイン回数 |
| UPDATE | remember_token | トークン値 | remember_me有効時 |
| UPDATE | remember_created_at | 現在日時 | remember_me有効時 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 認証エラー | ユーザー名/メールが存在しない | エラーメッセージ表示 |
| - | 認証エラー | パスワードが不正 | エラーメッセージ表示 |
| - | アカウントエラー | アカウントが停止されている | 停止メッセージ表示 |
| - | 確認エラー | メールアドレス未確認 | 確認案内メッセージ表示 |
| - | 承認エラー | 管理者承認待ち | 承認待ちメッセージ表示 |

### リトライ仕様

- ログイン失敗時は同一画面で再試行可能
- Deviseのロックアウト機能は未設定（必要に応じて設定可能）

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

認証処理とログイン情報更新は同一トランザクションで処理される。

## パフォーマンス要件

- レスポンス時間: 1秒以内
- パスワードハッシュ化にbcryptを使用（意図的に処理時間がかかる）

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

- パスワードはbcrypt（encryptable）でハッシュ化して保存
- セッションIDはリクエストごとに再生成（セッション固定攻撃対策）
- CSRFトークン検証によりクロスサイトリクエストフォージェリを防止
- 認証失敗時のエラーメッセージは汎用的なものを使用（情報漏洩防止）
- remember_meトークンは暗号化して保存

## 備考

- DeviseのDatabaseAuthenticatable, Rememberable, Trackableモジュールを使用
- ユーザー登録が無効化されている場合（Setting.user_signup == :not_allowed）はユーザー登録リンクが非表示

---

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

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

### 推奨読解順序

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

認証に関連するUserモデルのカラムとDeviseモジュールを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | user.rb | `app/models/users/user.rb` | Deviseモジュールの設定、認証関連メソッド |
| 1-2 | schema.rb | `db/schema.rb` | usersテーブルの認証関連カラム（433-475行目） |

**読解のコツ**:
- **49-50行目（user.rb）**: `devise :database_authenticatable, :registerable, :confirmable, :encryptable, :recoverable, :rememberable, :trackable` でDeviseモジュールを確認
- **111-113行目（user.rb）**: `suspended?`メソッドでアカウント停止判定
- **116-118行目（user.rb）**: `awaits_approval?`メソッドで承認待ち判定
- **120-122行目（user.rb）**: `active_for_authentication?`でログイン可否を判定

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | sessions_controller.rb | `app/controllers/sessions_controller.rb` | Devise::SessionsControllerの継承 |
| 2-2 | routes.rb | `config/routes.rb` | deviseルーティング（17-20行目） |

**主要処理フロー**:
1. **8-9行目（sessions_controller.rb）**: Devise::SessionsControllerを継承、HTML形式のみ対応
2. **12-14行目（sessions_controller.rb）**: ログアウト後のリダイレクト先を設定

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

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

**主要処理フロー**:
- **14行目**: simple_form_forでログインフォーム生成
- **15-18行目**: ユーザー登録可否の条件分岐
- **21-24行目**: ユーザー名/パスワード入力フィールド
- **26-28行目**: remember_meチェックボックス、送信ボタン
- **30-31行目**: パスワードリセットリンク

#### Step 4: カスタム認証ロジックを理解する

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

**主要処理フロー**:
- **206-211行目**: username/emailのどちらでも認証可能にするカスタマイズ

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

```
GET /users/sign_in
    │
    └─ SessionsController#new
           └─ views/devise/sessions/new.html.haml

POST /users/sign_in
    │
    └─ Devise::SessionsController#create（継承）
           │
           ├─ User.find_for_database_authentication
           │      └─ username/email でユーザー検索
           │
           ├─ valid_password?（Devise）
           │      └─ bcryptでパスワード検証
           │
           ├─ active_for_authentication?（User）
           │      ├─ confirmed?
           │      ├─ !awaits_approval?
           │      └─ !suspended?
           │
           └─ sign_in（Warden）
                  └─ セッション作成、Trackable更新
```

### データフロー図

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

ログインフォーム
  │
  ├─ email ──────▶ find_for_database_authentication ──▶ User検索
  │                        │
  ├─ password ──▶ valid_password? ────────────────────▶ 認証判定
  │                        │
  └─ remember_me ─▶ create_session ────────────────────▶ セッション作成
                           │
                           ├───────────────────────────▶ usersテーブル更新
                           │                              （Trackable）
                           │
                           └───────────────────────────▶ ダッシュボードへ
                                                          リダイレクト
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| sessions_controller.rb | `app/controllers/sessions_controller.rb` | コントローラー | セッション管理 |
| user.rb | `app/models/users/user.rb` | モデル | ユーザーモデル、認証ロジック |
| new.html.haml | `app/views/devise/sessions/new.html.haml` | ビュー | ログインフォーム |
| routes.rb | `config/routes.rb` | 設定 | ルーティング定義 |
| schema.rb | `db/schema.rb` | スキーマ | usersテーブル定義 |
