# 画面設計書 230-アイデンティティ編集

## 概要

本ドキュメントは、GitLab管理者エリアにおけるユーザーアイデンティティ編集画面の設計について記述する。

### 本画面の処理概要

本画面は特定ユーザーに関連付けられた既存の外部認証プロバイダのアイデンティティ（LDAP、SAML、OAuth等）を編集するための管理者向け画面である。

**業務上の目的・背景**：ユーザーの外部認証プロバイダとの連携情報を修正する必要がある場合に使用する。例えば、LDAPサーバーのユーザーDN変更に伴う識別子の修正や、プロバイダの変更などを行う際に使用される。LDAPアイデンティティを更新した場合は、ブロック状態の修復処理も自動的に実行される。

**画面へのアクセス方法**：管理者としてログイン後、Admin Area > Overview > Users > ユーザー詳細 > Identitiesタブ > 対象アイデンティティのEditリンクをクリック、またはURLで`/admin/users/:user_id/identities/:id/edit`に直接アクセスする。

**主要な操作・処理内容**：
1. プロバイダの変更
2. 外部識別子（extern_uid）の変更
3. アイデンティティの更新保存

**画面遷移**：
- アイデンティティ一覧画面（No.228）からの遷移
- 更新成功時：アイデンティティ一覧画面へリダイレクト
- 更新失敗時：フォームを再表示

**権限による表示制御**：管理者権限が必要。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 111 | ユーザー管理 | 主機能 | ユーザーアイデンティティの編集 |

## 画面種別

編集

## URL/ルーティング

| HTTP メソッド | URL | アクション | 説明 |
|--------------|-----|-----------|------|
| GET | /admin/users/:user_id/identities/:id/edit | edit | アイデンティティ編集画面表示 |
| PATCH/PUT | /admin/users/:user_id/identities/:id | update | アイデンティティ更新処理 |

## 入出力項目

| 項目名 | 入力/出力 | 型 | 必須 | 説明 |
|--------|----------|----|----|------|
| user_id | 入力（URL） | 文字列 | はい | ユーザーID（ユーザー名） |
| id | 入力（URL） | 整数 | はい | アイデンティティID |
| provider | 入力 | 選択 | はい | 認証プロバイダ（既存値選択） |
| extern_uid | 入力 | 文字列 | はい | 外部識別子（既存値表示） |

## 表示項目

| セクション | 項目 | 説明 |
|-----------|------|------|
| パンくず | Users | 管理者ユーザー一覧へのリンク |
| パンくず | ユーザー名 | 対象ユーザーのアイデンティティ一覧へのリンク |
| パンくず | Edit | 現在の画面 |
| ヘッダー | タイトル | "Edit identity for {ユーザー名}" |
| フォーム | Provider | プロバイダ選択ドロップダウン（既存値選択） |
| フォーム | Identifier | 外部識別子入力フィールド（既存値表示、必須） |
| フッター | Save changesボタン | 更新実行 |

## イベント仕様

### 1-Save changesボタン押下

1. フォームをバリデーション
2. PATCH/PUTリクエストを`/admin/users/:user_id/identities/:id`に送信
3. @identity.update(identity_params)を実行
4. 成功時：Users::RepairLdapBlockedServiceを実行（LDAPブロック状態の修復）
5. 成功時：アイデンティティ一覧画面にリダイレクト、「User identity was successfully updated.」メッセージを表示
6. 失敗時：エラーを表示してフォームを再表示

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 画面表示 | users | SELECT | ユーザー情報取得 |
| 画面表示 | identities | SELECT | アイデンティティ情報取得 |
| アイデンティティ更新 | identities | UPDATE | アイデンティティレコード更新 |

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

#### identities

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | provider | フォーム選択値 | 認証プロバイダ名 |
| UPDATE | extern_uid | フォーム入力値 | 外部識別子 |
| UPDATE | saml_provider_id | フォーム入力値（EE版） | SAMLプロバイダID |

## メッセージ仕様

| 種別 | メッセージ | 表示条件 |
|------|----------|---------|
| 成功 | User identity was successfully updated. | 更新成功時 |
| エラー | バリデーションエラーメッセージ | 入力エラー時 |

## 例外処理

| 状態 | 処理 |
|------|------|
| 権限不足 | 403エラー画面にリダイレクト |
| ユーザー不存在 | 404エラー画面にリダイレクト |
| アイデンティティ不存在 | 404エラー画面にリダイレクト |
| バリデーションエラー | フォームを再表示し、エラーメッセージを表示 |
| プロバイダ重複 | 「Provider has already been taken」エラー（同一ユーザー・プロバイダの組み合わせ） |

## 備考

- プロバイダのリストはGitlab::Auth::OAuth::Provider.providersから動的に生成される
- LDAPアイデンティティを更新した場合、Users::RepairLdapBlockedServiceが実行される
- EE版ではSAMLプロバイダIDフィールドが追加される（render_if_existsで条件付き表示）
- feature_categoryは`system_access`に設定されている
- 新規作成画面（No.229）と同じ_form.html.hamlパーシャルを共有

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | identity.rb | `app/models/identity.rb` | Identityモデルの構造、バリデーション |

**読解のコツ**:
- provider、extern_uid、user_idの関係を理解
- validates :provider, uniqueness: { scope: :user_id }でユーザーごとのプロバイダ一意性を確認
- ldap?メソッドでLDAPプロバイダかどうかを判定

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | identities_controller.rb | `app/controllers/admin/identities_controller.rb` | editアクション、updateアクション |

**主要処理フロー**:
- **行35**: editアクションは空（before_actionでidentityが設定される）
- **行37-45**: updateアクションでアイデンティティ更新
- **行38**: @identity.update(identity_params)で更新
- **行39**: Users::RepairLdapBlockedService.new(@user).executeでLDAPブロック修復
- **行41**: 成功時リダイレクト
- **行43**: 失敗時render :edit
- **行66-68**: identityメソッドでuser.identities.find(id)

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | edit.html.haml | `app/views/admin/identities/edit.html.haml` | 編集画面構造 |
| 3-2 | _form.html.haml | `app/views/admin/identities/_form.html.haml` | フォームフィールド定義（new.htmlと共通） |

**主要処理フロー**:
- **edit.html.haml 行1-3**: パンくずリスト設定
- **edit.html.haml 行4**: ページタイトル（プロバイダ名を含む詳細タイトル）
- **edit.html.haml 行6**: PageHeadingComponentでヘッダー表示（"Edit identity for {ユーザー名}"）
- **edit.html.haml 行7**: _formパーシャルをレンダリング
- **_form.html.haml**: 新規作成と同じフォームを使用（既存値が自動的に表示される）

#### Step 4: サービスクラスを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | repair_ldap_blocked_service.rb | `app/services/users/repair_ldap_blocked_service.rb` | LDAPブロック修復ロジック |

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

```
Admin::IdentitiesController#edit
    │
    ├─ before_action: user（ユーザー取得）
    │
    ├─ before_action: identity（アイデンティティ取得）
    │      └─ user.identities.find(params[:id])
    │
    └─ view: edit.html.haml
           │
           └─ partial: _form.html.haml（既存値表示）
                  │
                  ├─ Gitlab::Auth::OAuth::Provider.providers
                  │
                  └─ render_if_exists: _provider_id（EE）

Admin::IdentitiesController#update
    │
    ├─ @identity.update(identity_params)
    │      │
    │      ├─ 成功
    │      │      │
    │      │      ├─ Users::RepairLdapBlockedService#execute
    │      │      │
    │      │      └─ redirect_to identities_path + notice
    │      │
    │      └─ 失敗 → render :edit
    │
    └─ identity_params
           └─ provider, extern_uid, saml_provider_id
```

### データフロー図

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

URL /:user_id       IdentitiesController#edit
/:id/edit ─────────▶      │
                         ├─ user（before_action）
                         ├─ identity（before_action）
                         │
                         └─ view: edit.html.haml（既存値表示）

フォーム入力 ───────▶ IdentitiesController#update ───▶ @identity.update
                         │                               │
                         │ identity_params               ▼
                         │                        identitiesテーブル UPDATE
                         │                               │
                         └───────────────────────────────┘
                                  │
                                  ▼
                         RepairLdapBlockedService#execute
                                  │
                                  ▼
                         リダイレクト（一覧画面）
                              + フラッシュ
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| identities_controller.rb | `app/controllers/admin/identities_controller.rb` | コントローラ | edit/updateアクション（行35-45, 66-68） |
| edit.html.haml | `app/views/admin/identities/edit.html.haml` | テンプレート | 編集画面 |
| _form.html.haml | `app/views/admin/identities/_form.html.haml` | パーシャル | フォームフィールド（new.htmlと共通） |
| identity.rb | `app/models/identity.rb` | モデル | アイデンティティモデル |
| repair_ldap_blocked_service.rb | `app/services/users/repair_ldap_blocked_service.rb` | サービス | LDAPブロック修復 |
| admin.rb | `config/routes/admin.rb` | ルーティング | URL定義 |
