# 通知設計書 122-user_admin_approval

## 概要

本ドキュメントは、GitLabにおける「ユーザーの管理者承認通知」メールの設計を記載します。管理者がユーザーアカウントの登録リクエストを承認した際に、承認されたユーザーに送信されるウェルカムメールです。

### 本通知の処理概要

本通知は、GitLabインスタンスで管理者承認が必要なユーザー登録フローにおいて、管理者がユーザーのアカウントリクエストを承認した際に送信されるメール機能です。

**業務上の目的・背景**：GitLabでは、セキュリティやリソース管理の観点から、新規ユーザー登録に管理者承認を必須とする設定が可能です。この設定が有効な場合、ユーザーが登録申請を行うと「承認待ち」状態となり、管理者が承認するまでログインできません。本通知は、管理者が承認を行った際にユーザーに「アカウントが利用可能になった」ことを知らせ、スムーズなオンボーディングを支援します。

**通知の送信タイミング**：管理者がGitLab管理画面またはAPI経由で`Users::ApproveService`を実行し、ユーザーをアクティブ化した直後に非同期で送信されます。

**通知の受信者**：承認されたユーザー本人のメールアドレスに送信されます。

**通知内容の概要**：アカウントリクエストが承認されたことを伝え、ユーザー名とサインインページのURLを案内します。

**期待されるアクション**：受信者は、メールに記載されたサインインページURLにアクセスし、設定したパスワード（または追加で送信されるパスワードリセットリンク）を使用してログインを行います。

## 通知種別

メール（Email）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 非同期（`deliver_later`） |
| 優先度 | 中 |
| リトライ | Sidekiqのデフォルトリトライに依存 |

### 送信先決定ロジック

承認されたユーザー（`user`）の登録メールアドレスに送信されます。メールアドレスはUserモデルの`email`属性から取得されます。

## 通知テンプレート

### メール通知の場合

| 項目 | 内容 |
|-----|------|
| 送信元アドレス | `Gitlab.config.gitlab.email_from` |
| 送信元名称 | `Gitlab.config.gitlab.email_display_name` |
| 件名 | `Welcome to GitLab!` |
| 形式 | HTML/テキスト（マルチパート） |

### 本文テンプレート

**HTML版:**
```html
<h1>Hi {ユーザー名}!</h1>
<p>Your GitLab account request has been approved!</p>
<p>Your username is {ユーザー名}.</p>
<p>Your sign-in page is <a href="{GitLab URL}">{GitLab URL}</a>.</p>
```

**テキスト版:**
```
Hi {ユーザー名}!

Your GitLab account request has been approved!

Your username is {ユーザー名}.

Your sign-in page is {GitLab URL}.
```

### 添付ファイル

| ファイル名 | 形式 | 条件 | 説明 |
|----------|------|------|------|
| なし | - | - | 本通知には添付ファイルはありません |

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| @resource | 承認されたユーザー | Userモデル | Yes |
| @resource.name | ユーザー表示名 | users.name | Yes |
| @resource.username | ユーザー名（ログインID） | users.username | Yes |
| Gitlab.config.gitlab.url | GitLabインスタンスURL | 設定ファイル | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| サービス実行 | `Users::ApproveService#execute` | ユーザーのアクティブ化が成功した場合 | 管理者がユーザー承認操作を実行 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| ユーザーが既にアクティブ | `user.active?`がtrueの場合、承認処理自体がエラーとなる |
| 承認が不要な状態 | `blocked_pending_approval?`がfalseの場合、承認処理自体がエラーとなる |
| アクティベーション失敗 | `user.activate`がfalseを返した場合 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[管理者がユーザー承認操作] --> B[Users::ApproveService#execute]
    B --> C{権限チェック}
    C -->|NG| D[エラー返却]
    C -->|OK| E{ユーザー状態チェック}
    E -->|既にアクティブまたは承認不要| F[コンフリクトエラー]
    E -->|承認待ち| G[user.activate]
    G --> H{アクティベーション結果}
    H -->|失敗| I[エラー返却]
    H -->|成功| J[resend_confirmation_instructions]
    J --> K[accept_pending_invitations!]
    K --> L[DeviseMailer.user_admin_approval.deliver_later]
    L --> M{created_by_id存在?}
    M -->|Yes| N[reset_token生成 + NotificationService.new_user]
    M -->|No| O[スキップ]
    N --> P[ログ記録]
    O --> P
    P --> Q[成功返却]
```

## データベース参照・更新仕様

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| users | 対象ユーザー情報の取得 | name, username, email, state |

### テーブル別参照項目詳細

#### users

| 参照項目（カラム名） | 用途 | 取得条件 |
|-------------------|------|---------|
| name | メール本文の挨拶文に使用 | 承認対象ユーザー |
| username | ユーザー名の案内に使用 | 承認対象ユーザー |
| email | メール送信先 | 承認対象ユーザー |
| state | 承認前の状態確認 | blocked_pending_approval |
| created_by_id | 追加通知の判定 | 管理者が作成したユーザーかどうか |

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| users | UPDATE | stateをactiveに更新（user.activate） |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| 権限エラー | 実行者に`approve_user`権限がない | 403 Forbiddenを返却 |
| 状態エラー | ユーザーが既にアクティブまたは承認不要 | 409 Conflictを返却 |
| アクティベーション失敗 | バリデーションエラー等 | 422 Unprocessable Entityを返却 |
| 送信失敗 | SMTPサーバー接続エラー | Sidekiqリトライに依存 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | Sidekiqデフォルト（25回） |
| リトライ間隔 | 指数バックオフ |
| リトライ対象エラー | 一時的なネットワークエラー、SMTP接続エラー |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | 制限なし |
| 1日あたり上限 | 制限なし |

### 配信時間帯

制限なし（承認操作時に即座にキューイング）

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

- 本通知には認証情報（パスワード等）は含まれない
- ユーザーが`created_by_id`を持つ場合は、別途`NotificationService.new_user`でパスワードリセットトークンが送信される
- `validate_single_recipient_in_opts!`により、複数宛先への送信は防止される
- 管理者のみが承認操作を実行できるよう、`can?(current_user, :approve_user)`で権限チェック

## 備考

- 本通知はDeviseのカスタム通知として実装されている
- メール確認が未完了の場合は、`resend_confirmation_instructions`で確認メールも再送される
- 保留中の招待がある場合は、`accept_pending_invitations!`で自動承諾される
- 件名には`email_subject_suffix`が設定されている場合、自動的に付加される

---

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

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

### 推奨読解順序

#### Step 1: サービス層を理解する

承認処理のエントリーポイントとなるサービスクラスを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | approve_service.rb | `app/services/users/approve_service.rb` | 承認処理のメインロジック、メール送信トリガー |

**主要処理フロー**:
1. **行9-11**: 権限チェックと状態チェック
2. **行13-18**: ユーザーアクティベーションと関連処理
3. **行18**: `DeviseMailer.user_admin_approval(user).deliver_later`でメール送信

#### Step 2: メーラーの実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | devise_mailer.rb | `app/mailers/devise_mailer.rb` | DeviseMailerクラス、`user_admin_approval`メソッド |

**主要処理フロー**:
- **行25-27**: `user_admin_approval`メソッドの定義、`devise_mail`を呼び出し

#### Step 3: テンプレートを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | user_admin_approval.html.haml | `app/views/devise/mailer/user_admin_approval.html.haml` | HTML版メールテンプレート |
| 3-2 | user_admin_approval.text.erb | `app/views/devise/mailer/user_admin_approval.text.erb` | テキスト版メールテンプレート |

**主要処理フロー**:
- **行1**: `email_default_heading`と`say_hi`で挨拶文を生成
- **行3-4**: アカウント承認のメッセージ
- **行5-6**: ユーザー名の案内
- **行7-8**: サインインページURLの案内

#### Step 4: ヘルパーメソッドを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | emails_helper.rb | `app/helpers/emails_helper.rb` | `say_hi`の実装 |

**主要処理フロー**:
- **行221-223**: `say_hi`でユーザー名を含む挨拶文を返却

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

```
Admin Controller / API
    │
    └─ Users::ApproveService#execute
           │
           ├─ can?(current_user, :approve_user)
           │
           ├─ user.activate
           │
           ├─ user.resend_confirmation_instructions
           │
           ├─ user.accept_pending_invitations!
           │
           └─ DeviseMailer.user_admin_approval(user).deliver_later
                  │
                  └─ devise_mail(record, :user_admin_approval)
                         └─ テンプレートレンダリング
                                ├─ user_admin_approval.html.haml
                                └─ user_admin_approval.text.erb
```

### データフロー図

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

管理者操作
(ユーザー承認)   ───▶  Users::ApproveService
                              │
                              ▼
                        user.activate
                              │
                              ▼
                        DeviseMailer
                        .user_admin_approval
                        .deliver_later    ───▶  Sidekiqキュー
                                                    │
                                                    ▼
                                               メール送信
                                               (承認ユーザー)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| approve_service.rb | `app/services/users/approve_service.rb` | ソース | 承認処理サービス |
| devise_mailer.rb | `app/mailers/devise_mailer.rb` | ソース | Deviseメーラー |
| user_admin_approval.html.haml | `app/views/devise/mailer/user_admin_approval.html.haml` | テンプレート | HTML版メールテンプレート |
| user_admin_approval.text.erb | `app/views/devise/mailer/user_admin_approval.text.erb` | テンプレート | テキスト版メールテンプレート |
| emails_helper.rb | `app/helpers/emails_helper.rb` | ソース | メール本文生成ヘルパー |
| devise_mailer_spec.rb | `spec/mailers/devise_mailer_spec.rb` | テスト | メーラーのテスト |
| approve_service_spec.rb | `spec/services/users/approve_service_spec.rb` | テスト | サービスのテスト |
