# 画面設計書 52-初回ユーザー作成（ウィザード）

## 概要

本ドキュメントは、セットアップウィザード内で初回管理者ユーザーを作成する画面の設計仕様を定義するものである。

### 本画面の処理概要

初回ユーザー作成（ウィザード）画面は、Jenkinsセットアップウィザードのステップの一つとして、最初の管理者ユーザーアカウントを作成するための入力フォームを提供する。

**業務上の目的・背景**：Jenkins初回インストール時に生成される一時的な管理パスワード（initialAdminPassword）は、セキュリティ上の観点から本番運用には適さない。本画面で正式な管理者アカウントを作成することで、初期パスワードファイルを削除し、適切な認証情報で運用を開始できる。また、管理者のユーザー名、パスワード、メールアドレス等を設定することで、パスワードリセットや通知の受信が可能となる。

**画面へのアクセス方法**：セットアップウィザードのプラグインインストールステップ完了後、自動的に遷移する。直接アクセスする場合は`/setupWizard/setupWizardFirstUser`にアクセスする。ただし、セットアップウィザードフィルターが有効な状態でのみアクセス可能。

**主要な操作・処理内容**：
1. ユーザー名の入力（必須）
2. パスワードの入力と確認（必須）
3. フルネームの入力（オプション）
4. メールアドレスの入力（オプション）
5. ユーザー作成ボタンの押下
6. 入力検証とユーザー作成処理

**画面遷移**：
- 遷移元：セットアップウィザード（プラグインインストール完了後）
- 遷移先：インスタンス設定画面（setupWizardConfigureInstance）

**権限による表示制御**：セットアップウィザードコンテキスト内でのみ表示される。`Jenkins.ADMINISTER`権限が必要。初期管理者として認証された状態で表示される。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 30 | ユーザー管理 | 主機能 | セットアップウィザードでの初回ユーザー作成 |
| 28 | 認証（SecurityRealm） | 補助機能 | 認証設定の初期化 |

## 画面種別

登録（フォーム入力）

## URL/ルーティング

- URL: `/setupWizard/setupWizardFirstUser`
- テンプレート: `core/src/main/resources/jenkins/install/SetupWizard/setupWizardFirstUser.jelly`
- POSTアクション: `/setupWizard/createAdminUser`

## 入出力項目

| 項目名 | 項目ID | 入力/出力 | 型 | 必須 | 説明 |
|--------|--------|----------|-----|------|------|
| ユーザー名 | username | 入力 | String | 必須 | 管理者ユーザーのログインID |
| パスワード | password1 | 入力 | String | 必須 | ログインパスワード |
| パスワード確認 | password2 | 入力 | String | 必須 | パスワードの確認入力 |
| フルネーム | fullname | 入力 | String | 任意 | ユーザーの表示名 |
| メールアドレス | email | 入力 | String | 任意 | 通知先メールアドレス |

## 表示項目

| 項目名 | 表示条件 | 説明 |
|--------|----------|------|
| タイトル | 常時 | "Create First Admin User" |
| ユーザー作成フォーム | 常時 | `_entryForm`タグを使用してフォームを表示 |
| エラーメッセージ | 検証エラー時 | 入力検証に失敗した場合のエラー表示 |

## イベント仕様

### 1-フォーム送信（ユーザー作成）

フォーム送信時に`SetupWizard.doCreateAdminUser()`メソッドが呼び出される。

処理フロー：
1. `Jenkins.ADMINISTER`権限の確認
2. `HudsonPrivateSecurityRealm`のインスタンス取得
3. 既存の初期管理者ユーザー（admin）の削除
4. 新規ユーザーの作成（`createAccountFromSetupWizard()`）
5. 初期管理者のAPIトークンがあれば新ユーザーに引き継ぎ
6. `initialAdminPassword`ファイルの削除
7. `initialAdminApiToken`ファイルの削除（存在する場合）
8. インストール状態を`CREATE_ADMIN_USER`から次の状態へ遷移
9. 新ユーザーでの認証セッション確立
10. セッションフィクセーション攻撃対策としてセッション再生成
11. JSON形式でCRUMB情報を含むレスポンスを返却

### 2-入力検証エラー

`AccountCreationFailedException`が発生した場合：
1. HTTPステータス422（Unprocessable Entity）を設定
2. 同じフォームを再表示（エラーメッセージ付き）

## データベース更新仕様

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| ユーザー作成 | ファイルシステム | INSERT | ユーザー設定XMLの作成 |
| 初期ユーザー削除 | ファイルシステム | DELETE | 初期adminユーザーの削除 |
| パスワードファイル削除 | ファイルシステム | DELETE | initialAdminPasswordの削除 |

### テーブル別更新項目詳細

#### ファイルシステム（$JENKINS_HOME/）

| 操作 | 項目（ファイル名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| DELETE | secrets/initialAdminPassword | - | ユーザー作成成功後に削除 |
| DELETE | secrets/initialAdminApiToken | - | 存在する場合のみ削除 |
| INSERT | users/{username}/config.xml | ユーザー設定情報 | 新規ユーザーディレクトリ配下 |
| DELETE | users/admin/config.xml | - | 初期adminユーザー（存在する場合） |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|--------------|----------|
| Create First Admin User | 情報 | 最初の管理者ユーザーを作成 | フォームタイトル |
| AccountCreationFailed | エラー | アカウント作成に失敗しました | ユーザー作成処理でエラー発生時 |

## 例外処理

| 例外種別 | 発生条件 | 処理内容 |
|----------|----------|----------|
| AccountCreationFailedException | ユーザー作成処理が失敗 | HTTPステータス422を返却し、フォームを再表示 |
| SecurityException | 権限不足 | アクセス拒否エラー |
| IOException | ファイル操作失敗 | 例外をスローし、処理を中断 |

## 備考

- この画面は`HudsonPrivateSecurityRealm`の`_entryForm`タグを再利用している
- キャプチャは無効化されている（`captcha="${false}"`）
- ユーザー作成後、新しいユーザーで自動的にログイン状態となる
- セッションは安全のため再生成される（セッションフィクセーション対策）
- 作成されたユーザーには初期管理者のAPIトークンが引き継がれる（存在する場合）

---

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

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

### 推奨読解順序

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

まず、ユーザーアカウントのデータ構造を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | User.java | `core/src/main/java/hudson/model/User.java` | Userオブジェクトの構造とプロパティ |
| 1-2 | HudsonPrivateSecurityRealm.java | `core/src/main/java/hudson/security/HudsonPrivateSecurityRealm.java` | セキュリティレルムとユーザー管理 |

**読解のコツ**: `HudsonPrivateSecurityRealm`がどのようにユーザー情報を永続化するか（ファイルシステムベース）を把握する。

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

処理の起点となるファイル・関数を特定。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | setupWizardFirstUser.jelly | `core/src/main/resources/jenkins/install/SetupWizard/setupWizardFirstUser.jelly` | フォームのHTMLテンプレート |
| 2-2 | _entryForm.jelly | `core/src/main/resources/hudson/security/HudsonPrivateSecurityRealm/_entryForm.jelly` | ユーザー入力フォームコンポーネント |

**主要処理フロー**:
1. **7行目**: フォームアクションが`/setupWizard/createAdminUser`に設定
2. **8行目**: `_entryForm`タグでフォーム本体を生成

#### Step 3: バックエンド処理を理解する

ユーザー作成のサーバーサイド処理。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | SetupWizard.java | `core/src/main/java/jenkins/install/SetupWizard.java` | `doCreateAdminUser()`メソッド（332-414行目） |
| 3-2 | HudsonPrivateSecurityRealm.java | `core/src/main/java/hudson/security/HudsonPrivateSecurityRealm.java` | `createAccountFromSetupWizard()`メソッド |

**主要処理フロー**:
- **337行目**: 権限チェック `j.checkPermission(Jenkins.ADMINISTER)`
- **340行目**: セキュリティレルムの取得
- **342-348行目**: 既存admin削除、APIトークン退避
- **351行目**: 新規ユーザー作成
- **361-374行目**: パスワードファイル、APIトークンファイルの削除
- **376行目**: 状態遷移処理
- **379-393行目**: 認証とセッション処理

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

```
setupWizardFirstUser.jelly
    │
    └─ フォームPOST → /setupWizard/createAdminUser
           │
           └─ SetupWizard.doCreateAdminUser()
                  │
                  ├─ Jenkins.checkPermission(ADMINISTER)
                  │
                  ├─ HudsonPrivateSecurityRealm.getUser("admin")
                  │      └─ admin.delete()
                  │
                  ├─ HudsonPrivateSecurityRealm.createAccountFromSetupWizard()
                  │      ├─ User作成
                  │      └─ パスワードハッシュ化・保存
                  │
                  ├─ getInitialAdminPasswordFile().delete()
                  │
                  ├─ InstallUtil.proceedToNextStateFrom()
                  │
                  └─ 認証・セッション処理
                         ├─ UsernamePasswordAuthenticationToken
                         ├─ SecurityContextHolder
                         └─ Session再生成
```

### データフロー図

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

ユーザー名 ─────────────▶ ┌─────────────────────────┐
パスワード ─────────────▶ │ doCreateAdminUser()     │──▶ User設定XML作成
パスワード確認 ─────────▶ │                         │
フルネーム ─────────────▶ │ 入力検証                │──▶ initialAdminPassword削除
メールアドレス ─────────▶ │ ユーザー作成            │
                          │ 認証セッション確立      │──▶ セッション確立
                          └─────────────────────────┘
                                   │
                                   ▼
                          InstallState遷移
                                   │
                                   ▼
                          インスタンス設定画面へ
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| setupWizardFirstUser.jelly | `core/src/main/resources/jenkins/install/SetupWizard/setupWizardFirstUser.jelly` | テンプレート | メイン画面テンプレート |
| _entryForm.jelly | `core/src/main/resources/hudson/security/HudsonPrivateSecurityRealm/_entryForm.jelly` | テンプレート | ユーザー入力フォーム |
| SetupWizard.java | `core/src/main/java/jenkins/install/SetupWizard.java` | ソース | コントローラー |
| HudsonPrivateSecurityRealm.java | `core/src/main/java/hudson/security/HudsonPrivateSecurityRealm.java` | ソース | ユーザー管理 |
| User.java | `core/src/main/java/hudson/model/User.java` | ソース | ユーザーモデル |
| ApiTokenProperty.java | `core/src/main/java/jenkins/security/ApiTokenProperty.java` | ソース | APIトークン管理 |
| UserSeedProperty.java | `core/src/main/java/jenkins/security/seed/UserSeedProperty.java` | ソース | セッションシード管理 |
