# 画面設計書 331-OAuthアプリケーション詳細

## 概要

本ドキュメントは、GitLabにおけるOAuthアプリケーション詳細画面の設計仕様を定義する。

### 本画面の処理概要

OAuthアプリケーション詳細画面は、ユーザーが作成したOAuth2.0アプリケーションの詳細情報を表示し、管理するための画面である。

**業務上の目的・背景**：OAuth2.0は、サードパーティアプリケーションがユーザーの認証情報を直接取得せずに、ユーザーのリソースへのアクセス権限を取得するための業界標準プロトコルである。GitLabユーザーは、外部アプリケーションとGitLabを連携させるためにOAuthアプリケーションを登録する必要があり、本画面はその登録済みアプリケーションの詳細情報（Application ID、Secret、コールバックURL、スコープ等）を確認・管理するために必要である。

**画面へのアクセス方法**：
1. GitLabにログイン後、プロフィールアイコンをクリック
2. 「User Settings」から「Applications」を選択
3. アプリケーション一覧から対象アプリケーション名をクリック
4. または、直接URL `/oauth/applications/:id` にアクセス

**主要な操作・処理内容**：
1. アプリケーションID（Client ID）の確認とクリップボードへのコピー
2. アプリケーションシークレット（Client Secret）の確認と再生成
3. コールバックURL（Redirect URI）の確認
4. 機密性（Confidential）設定の確認
5. 許可されたスコープの確認
6. アプリケーション編集画面への遷移
7. アプリケーションの削除

**画面遷移**：
- 遷移元：OAuthアプリケーション一覧画面（No.330）、アプリケーション作成成功後
- 遷移先：OAuthアプリケーション編集画面（No.332）、OAuthアプリケーション一覧画面（No.330）

**権限による表示制御**：
- ログインユーザーのみアクセス可能
- 自分が所有するアプリケーションのみ閲覧可能
- 管理者はすべてのアプリケーションを閲覧可能（Admin Area経由）

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 88 | OAuth2プロバイダ | 主機能 | OAuthアプリケーション詳細表示 |
| 81 | 個人アクセストークン | 補助機能 | トークンスコープの表示 |

## 画面種別

詳細

## URL/ルーティング

| メソッド | パス | アクション |
|---------|------|-----------|
| GET | `/oauth/applications/:id` | `oauth/applications#show` |
| PATCH | `/oauth/applications/:id/renew` | `oauth/applications#renew` |

## 入出力項目

本画面は主に表示専用画面であるが、シークレット再生成機能を持つ。

| 項目名 | 入力/出力 | データ型 | 必須 | 説明 |
|--------|----------|---------|------|------|
| Application ID | 出力 | String | - | アプリケーション識別子（Client ID） |
| Secret | 出力 | String | - | アプリケーションシークレット（Client Secret） |
| Callback URL | 出力 | String | - | リダイレクトURI（複数可） |
| Confidential | 出力 | Boolean | - | 機密性設定 |
| Scopes | 出力 | Array | - | 許可されたスコープ一覧 |

## 表示項目

| 項目名 | データソース | 表示形式 | 備考 |
|--------|-------------|---------|------|
| Application ID | @application.uid | テキスト（モノスペース） | コピーボタン付き |
| Secret | @application.plaintext_secret | テキスト（マスク可） | 再生成ボタン付き |
| Callback URL | @application.redirect_uri | テキストリスト | 複数URIは改行区切り |
| Confidential | @application.confidential? | Yes/No | - |
| Scopes | @application.scopes | テーブル | スコープ名と説明 |

## イベント仕様

### 1-コピーボタン（Application ID）

**トリガー**: Application IDのコピーボタンをクリック

**処理内容**:
1. クリップボードAPIを使用してApplication IDをコピー
2. コピー成功のフィードバック表示

**関連コンポーネント**: `clipboard_button`

---

### 2-シークレット再生成

**トリガー**: シークレット再生成ボタンをクリック

**処理内容**:
1. 確認ダイアログを表示
2. PATCH `/oauth/applications/:id/renew` にリクエスト送信
3. 新しいシークレットを生成してデータベースに保存
4. レスポンスとして新しいシークレットを返却
5. 画面上のシークレット表示を更新

**エンドポイント**: `oauth_applications#renew`

---

### 3-編集ボタン

**トリガー**: 「Edit」ボタンをクリック

**処理内容**:
1. OAuthアプリケーション編集画面（No.332）へ遷移
2. 遷移先URL: `/oauth/applications/:id/edit`

---

### 4-削除ボタン

**トリガー**: 削除ボタンをクリック

**処理内容**:
1. 確認ダイアログを表示
2. DELETE `/oauth/applications/:id` にリクエスト送信
3. アプリケーションを削除
4. OAuthアプリケーション一覧画面へリダイレクト

---

### 5-続行ボタン（作成直後）

**トリガー**: アプリケーション作成直後に「Continue」ボタンをクリック

**処理内容**:
1. OAuthアプリケーション一覧画面（No.330）へ遷移
2. @createdフラグがtrueの場合のみ表示される

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 画面表示 | oauth_applications | SELECT | アプリケーション情報の取得 |
| シークレット再生成 | oauth_applications | UPDATE | シークレットの更新 |
| アプリケーション削除 | oauth_applications | DELETE | アプリケーションの削除 |
| アプリケーション削除 | oauth_access_tokens | DELETE | 関連アクセストークンの削除 |

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

#### oauth_applications

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | uid, secret, redirect_uri, confidential, scopes | WHERE id = :id AND owner_id = :current_user_id | 所有者チェック |
| UPDATE | secret | 新規生成されたハッシュ値 | renew時 |
| DELETE | 全項目 | WHERE id = :id | 関連レコードもカスケード削除 |

## メッセージ仕様

| 種別 | メッセージID | メッセージ内容 | 表示条件 |
|------|-------------|---------------|---------|
| 成功 | flash.applications.destroy.notice | Application was successfully destroyed. | 削除成功時 |
| 成功 | flash.applications.create.notice | Application was successfully created. | 作成直後の表示時 |
| エラー | errors.not_found | Page not found | アプリケーションが見つからない場合 |
| 警告 | secret_renewal_warning | The secret will be permanently changed. | シークレット再生成確認時 |

## 例外処理

| 例外状況 | 処理内容 | 表示/遷移先 |
|---------|---------|------------|
| アプリケーションが見つからない | ActiveRecord::RecordNotFound | 404エラーページ |
| 権限不足 | 所有者以外のアクセス | 404エラーページ |
| シークレット再生成失敗 | JSON形式でエラー返却 | エラーメッセージ表示 |

## 備考

- シークレットは作成直後またはrenew直後のみプレーンテキストで表示される
- シークレットはデータベース上では暗号化されて保存される
- Confidentialアプリケーションの場合、自動認可（skip_authorization）が有効になる場合がある
- 管理者用画面（Admin Area）からも同様の詳細画面にアクセス可能だが、trusted設定の表示など追加項目がある

---

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

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

### 推奨読解順序

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

OAuthアプリケーションのデータモデルを理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | oauth_application.rb | `app/models/authn/oauth_application.rb` | OAuthアプリケーションモデルの定義、Doorkeeper::Applicationの拡張 |
| 1-2 | doorkeeper.rb | `config/initializers/doorkeeper.rb` | Doorkeeper gemの設定、スコープ定義 |

**読解のコツ**: `Authn::OauthApplication`はDoorkeeper gemの`Doorkeeper::Application`を継承している。GitLab独自の拡張（organization関連付け、secret_matches?メソッド等）に注目。

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

処理の起点となるコントローラを特定。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | applications_controller.rb | `app/controllers/oauth/applications_controller.rb` | コントローラの全体構造、認証・認可処理 |

**主要処理フロー**:
1. **行15**: `authenticate_user!` - ユーザー認証
2. **行14**: `verify_user_oauth_applications_enabled` - 機能有効チェック
3. **行28**: `show` - 詳細表示アクション
4. **行76-78**: `set_application` - アプリケーション取得（所有者スコープ）
5. **行44-53**: `renew` - シークレット再生成処理

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

画面表示のロジックを確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | show.html.haml | `app/views/doorkeeper/applications/show.html.haml` | メインビュー、パンくずリスト設定 |
| 3-2 | _show.html.haml | `app/views/shared/doorkeeper/applications/_show.html.haml` | 共通表示コンポーネント、詳細テーブル |
| 3-3 | _scopes_list.html.haml | `app/views/shared/tokens/_scopes_list.html.haml` | スコープ一覧表示 |

**主要処理フロー**:
- **行5-10**: ページヘッダー設定、共有partialのレンダリング
- **_show.html.haml 行10-12**: Application IDの表示とコピーボタン
- **_show.html.haml 行17**: シークレット表示（Vue.jsコンポーネント）
- **_show.html.haml 行40**: スコープ一覧表示

#### Step 4: JavaScriptコンポーネントを理解する

フロントエンド側の処理を確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | js-oauth-application-secret | フロントエンドコンポーネント | シークレット表示・再生成のVue.jsコンポーネント |

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

```
Oauth::ApplicationsController#show
    │
    ├─ set_application (before_action)
    │      └─ current_user.oauth_applications.find(params[:id])
    │
    └─ render 'doorkeeper/applications/show'
           └─ render 'shared/doorkeeper/applications/show'
                  ├─ clipboard_button
                  ├─ #js-oauth-application-secret (Vue component)
                  ├─ render 'shared/tokens/scopes_list'
                  └─ render 'shared/doorkeeper/applications/delete_form'
```

### データフロー図

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

URL :id ───▶ ApplicationsController ───▶ @application
                    │
                    ├─ set_application
                    │      └─ User.oauth_applications.find(:id)
                    │
                    └─ render show.html.haml ───▶ HTML Response
                           │
                           └─ 表示項目:
                              - Application ID
                              - Secret
                              - Callback URL
                              - Confidential
                              - Scopes
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| applications_controller.rb | `app/controllers/oauth/applications_controller.rb` | コントローラ | リクエスト処理 |
| oauth_application.rb | `app/models/authn/oauth_application.rb` | モデル | データモデル |
| show.html.haml | `app/views/doorkeeper/applications/show.html.haml` | テンプレート | メインビュー |
| _show.html.haml | `app/views/shared/doorkeeper/applications/_show.html.haml` | テンプレート | 共有partial |
| _delete_form.html.haml | `app/views/shared/doorkeeper/applications/_delete_form.html.haml` | テンプレート | 削除フォーム |
| _scopes_list.html.haml | `app/views/shared/tokens/_scopes_list.html.haml` | テンプレート | スコープ表示 |
| doorkeeper.rb | `config/initializers/doorkeeper.rb` | 設定 | Doorkeeper設定 |
| routes.rb | `config/routes.rb` | 設定 | ルーティング定義 |
