# 画面設計書 49-ユーザーアカウント設定

## 概要

本ドキュメントは、Jenkinsのユーザーアカウント設定画面（Account）の画面設計書です。ユーザーのアカウントに関連するプロパティ（表示名、説明、メールアドレス等）を設定するカテゴリ別設定画面について記述します。

### 本画面の処理概要

この画面では、ユーザーのアカウントに関連するプロパティを一括で設定します。UserPropertyのうち、AccountカテゴリおよびUnclassifiedカテゴリに分類されるプロパティがこの画面で設定可能です。これはメインのユーザー設定画面であり、表示名や説明といった基本情報も含まれます。

**業務上の目的・背景**：Jenkins 2.468以降、ユーザー設定はカテゴリ別に分離されました。アカウント設定は最も基本的なユーザー情報を管理する画面です。Unclassifiedカテゴリのプロパティもここで設定できるため、互換性と利便性を両立しています。ユーザーの表示名（フルネーム）や説明はここで変更できます。

**画面へのアクセス方法**：ユーザー詳細画面のサイドパネルから「Account」リンクをクリック、または `/user/{userId}/account` にURL直接アクセスします。ADMINISTER権限がない場合、サイドパネルにリンクが表示されません。

**主要な操作・処理内容**：
1. 表示名（Full Name）の編集
2. 説明（Description）の編集
3. AccountおよびUnclassifiedカテゴリのプロパティの編集
4. 設定の保存

**画面遷移**：
- 遷移元：ユーザー詳細画面（/user/{userId}/）、サイドパネル
- 遷移先：ユーザー詳細画面（/user/{userId}/）（保存後）

**権限による表示制御**：ADMINISTER権限を持つユーザーのみがこの画面にアクセスできます。権限がない場合、サイドパネルにリンクが表示されません（getIconFileName()がnullを返す）。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 30 | ユーザー管理 | 主機能 | ユーザーアカウントプロパティの設定 |

## 画面種別

設定

## URL/ルーティング

- **URL**: `/user/{userId}/account`
- **Jellyテンプレート**: `core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index.jelly`
- **権限**: `Jenkins.ADMINISTER`

## 入出力項目

### 基本情報セクション

| 項目名 | 項目ID | 種別 | 必須 | データ型 | 説明 |
|--------|--------|------|------|----------|------|
| 表示名 | fullName | 入力 | - | String | ユーザーの表示名（フルネーム） |
| 説明 | description | 入力 | - | String | ユーザーの説明文 |

### 動的プロパティセクション

入力項目は`allByTwoCategoryClasses(Unclassified.class, Account.class)`で取得されるディスクリプターに依存します。代表的なプロパティ：

| 項目名 | 項目ID | 種別 | 必須 | データ型 | 説明 |
|--------|--------|------|------|----------|------|
| メールアドレス | emailAddress | 入力 | - | String | ユーザーのメールアドレス（Mailerプラグインが提供） |

## 表示項目

### ヘッダー部分

| 項目名 | 説明 |
|--------|------|
| タイトル | 「Account」（Messages.UserPropertyCategoryAccountAction_DisplayName()から取得） |

### プロパティ設定フォーム

| 項目名 | 説明 |
|--------|------|
| Full Name | 表示名入力フィールド |
| Description | 説明入力エリア |
| 各UserPropertyのconfig.jelly | AccountおよびUnclassifiedカテゴリの各UserPropertyが提供する設定フォーム |

## イベント仕様

### 1-画面表示

1. 画面アクセス時にADMINISTER権限をチェック
2. getMyCategoryDescriptors()でAccountおよびUnclassifiedカテゴリのプロパティディスクリプターを取得
3. 基本情報フィールドと各プロパティのconfig.jellyを描画

### 2-設定保存（doConfigSubmit）

1. 「Save」ボタンをクリック
2. POSTリクエストがdoConfigSubmitアクションに送信される
3. fullNameとdescriptionを抽出してUserに設定
4. 各プロパティの入力値を取得し、reconfigure()またはnewInstance()を呼び出す
5. User.addProperties()で一括更新
6. User.save()で永続化
7. fullNameが変更された場合、UserDetailsCacheを無効化
8. ユーザー詳細画面にリダイレクト（FormApply.success("..")）

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

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

| 操作（イベント） | 対象ファイル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 設定保存 | users/{userId}/config.xml | UPDATE | UserPropertyおよび基本情報の更新 |

### ファイル別更新項目詳細

#### users/{userId}/config.xml

| 操作 | 要素 | 更新値・取得条件 | 備考 |
|-----|------|-----------------|------|
| UPDATE | fullName | フォームのfullName入力値 | 空の場合はIDが設定される |
| UPDATE | description | フォームのdescription入力値 | HTML許可（MarkupFormatter依存） |
| UPDATE | properties/*/（AccountおよびUnclassifiedカテゴリ） | フォーム入力値 | 各プロパティのシリアライズ形式に依存 |

## メッセージ仕様

| 種別 | メッセージ | 発生条件 |
|------|----------|----------|
| タイトル | Account | 画面タイトル（Messagesから取得） |

## 例外処理

| 状態 | 処理 |
|------|------|
| 権限不足 | サイドパネルにリンク非表示、直接アクセス時は403エラー |
| バリデーションエラー | エラーメッセージを表示し、フォームを再表示 |

## 備考

- このアクションクラスはExtension(ordinal = 400)で登録されており、サイドパネルでの表示順序は400です（最も高い順序）
- シンボル名は`@Symbol("account")`で「account」です
- アイコンは`symbol-settings`が使用されます
- doConfigSubmitがオーバーライドされており、fullNameとdescriptionの処理が追加されています
- fullName変更時にUserDetailsCacheが無効化されます

---

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

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

### 推奨読解順序

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

ユーザープロパティとカテゴリの関係を把握します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | UserProperty.java | `core/src/main/java/hudson/model/UserProperty.java` | UserPropertyの基本構造 |
| 1-2 | UserPropertyCategory.java | `core/src/main/java/hudson/model/userproperty/UserPropertyCategory.java` | カテゴリ分類の仕組み |

**読解のコツ**: `UserPropertyCategory.Account`と`UserPropertyCategory.Unclassified`の両方がこの画面で扱われます。

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

アクションクラスの構造を把握します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | UserPropertyCategoryAction.java | `core/src/main/java/hudson/model/userproperty/UserPropertyCategoryAction.java` | 基底クラス |
| 2-2 | UserPropertyCategoryAccountAction.java | `core/src/main/java/hudson/model/userproperty/UserPropertyCategoryAccountAction.java` | Accountカテゴリ固有実装、doConfigSubmitオーバーライド |
| 2-3 | index.jelly | `core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index.jelly` | 画面テンプレート |

**主要処理フロー**:
1. **getMyCategoryDescriptors()**: `allByTwoCategoryClasses(Unclassified.class, Account.class)`で2カテゴリを取得
2. **doConfigSubmit()**: オーバーライドしてfullNameとdescriptionの処理を追加（行94-110）
3. **UserDetailsCache.invalidate()**: fullName変更時にキャッシュ無効化（行107-109）

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

```
ブラウザ (index.jelly)
    |
    +-- getMyCategoryDescriptors()
    |      |
    |      +-- allByTwoCategoryClasses(Unclassified.class, Account.class)
    |
    +-- [POST] doConfigSubmit()
           |
           +-- UserPropertyCategoryAccountAction.doConfigSubmit() [オーバーライド]
                  |
                  +-- checkPermission(Jenkins.ADMINISTER)
                  +-- targetUser.setFullName(json.getString("fullName"))
                  +-- targetUser.setDescription(json.getString("description"))
                  |
                  +-- super.doConfigSubmit() [基底クラス呼び出し]
                  |      |
                  |      +-- foreach descriptor:
                  |      |      +-- property.reconfigure() または descriptor.newInstance()
                  |      +-- user.addProperties(props)
                  |      +-- user.save()
                  |
                  +-- if (fullName changed): UserDetailsCache.invalidate()
                  +-- FormApply.success("..")
```

### データフロー図

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

fullName/description ───> doConfigSubmit() ────────────> config.xml更新
                               |
プロパティフォーム入力 ──────┘
                               |
                               +-- setFullName()
                               +-- setDescription()
                               +-- プロパティ再構成
                               +-- user.save()
                               |
                               +────────────────────────> リダイレクト（..）
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| UserPropertyCategoryAccountAction.java | `core/src/main/java/hudson/model/userproperty/UserPropertyCategoryAccountAction.java` | ソース | アカウント設定カテゴリアクション |
| UserPropertyCategoryAction.java | `core/src/main/java/hudson/model/userproperty/UserPropertyCategoryAction.java` | ソース | カテゴリアクション基底クラス |
| index.jelly | `core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index.jelly` | テンプレート | 画面表示 |
| UserProperty.java | `core/src/main/java/hudson/model/UserProperty.java` | ソース | ユーザープロパティ基底クラス |
| UserPropertyCategory.java | `core/src/main/java/hudson/model/userproperty/UserPropertyCategory.java` | ソース | カテゴリ定義 |
| UserDetailsCache.java | `core/src/main/java/jenkins/security/UserDetailsCache.java` | ソース | ユーザー詳細キャッシュ |
