# 画面設計書 243-アプリケーション一覧

## 概要

本ドキュメントは、GitLab管理者がインスタンス全体のOAuthアプリケーションを管理する一覧画面の設計書です。

### 本画面の処理概要

アプリケーション一覧画面は、GitLabインスタンスに登録されているOAuthアプリケーション（インスタンスレベル）を一覧表示し、管理するための管理者専用画面です。

**業務上の目的・背景**：GitLabはOAuth 2.0プロバイダとして機能し、外部アプリケーションがGitLab APIにアクセスするための認証を提供します。管理者はこの画面からインスタンス全体のOAuthアプリケーションを管理し、サードパーティ連携の統制を行います。インスタンスレベルのアプリケーションはオーナーを持たず（owner_id = null）、システム全体で利用可能です。

**画面へのアクセス方法**：
1. 管理者としてGitLabにログイン
2. 左サイドメニューから「Admin Area」をクリック
3. 「Applications」をクリック

**主要な操作・処理内容**：
1. 登録済みOAuthアプリケーションの一覧表示
2. 各アプリケーションの詳細表示（名前クリック）
3. アプリケーションの編集（編集アイコンクリック）
4. アプリケーションの削除（削除アイコンクリック、確認モーダル）
5. 新規アプリケーションの追加（「Add new application」ボタン）

**画面遷移**：
- 遷移元：管理者ダッシュボード
- 遷移先：アプリケーション詳細、アプリケーション編集、アプリケーション新規作成

**権限による表示制御**：管理者権限を持つユーザーのみがこの画面にアクセス可能です。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 88 | OAuth2プロバイダ | 主機能 | OAuthアプリケーション一覧表示・管理 |

## 画面種別

一覧

## URL/ルーティング

- URL: `/admin/applications`
- HTTP メソッド: GET
- ルート名: `admin_applications`

## 入出力項目

本画面は一覧表示のため、入力項目はありません。

## 表示項目

| 項目名 | 表示形式 | 備考 |
|--------|----------|------|
| ページタイトル | テキスト | "Instance OAuth applications" |
| アプリケーション数 | バッジ | 総アプリケーション数 |
| Name（名前） | リンク | 詳細画面へのリンク |
| Callback URL | テキスト | リダイレクトURI |
| Trusted | テキスト | Yes/No |
| Confidential | テキスト | Yes/No |
| Actions | アイコンボタン | 編集・削除 |
| ページネーション | リンク | Keyset Pagination |

### 一覧テーブル

| カラム名 | 説明 | ソート | フィルタ |
|---------|------|--------|---------|
| Name | アプリケーション名（詳細へのリンク） | - | - |
| Callback URL | リダイレクトURI | - | - |
| Trusted | 信頼済みフラグ（自動認可） | - | - |
| Confidential | 機密アプリケーションフラグ | - | - |
| Actions | 編集・削除ボタン | - | - |

## イベント仕様

### 1-アプリケーション詳細表示

**トリガー**: アプリケーション名リンククリック

**処理フロー**: アプリケーション詳細画面へ遷移

### 2-アプリケーション編集

**トリガー**: 編集アイコン（鉛筆）クリック

**処理フロー**: アプリケーション編集画面へ遷移

### 3-アプリケーション削除

**トリガー**: 削除アイコン（×）クリック

**処理フロー**:
1. 確認モーダル表示（JavaScriptモーダル）
2. 確認後、DELETEリクエスト送信
3. `Admin::ApplicationsController#destroy`呼び出し
4. アプリケーション削除
5. 本画面へリダイレクト（成功メッセージ付き）

### 4-新規アプリケーション追加

**トリガー**: 「Add new application」ボタンクリック

**処理フロー**: アプリケーション新規作成画面へ遷移

### 5-ページネーション

**トリガー**: ページネーションリンククリック

**処理フロー**:
1. cursorパラメータ付きでGETリクエスト
2. Keyset Paginationでページ切り替え

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 削除ボタン押下 | oauth_applications | DELETE | アプリケーションレコード削除 |
| 削除ボタン押下 | oauth_access_tokens | DELETE | 関連アクセストークン削除 |
| 削除ボタン押下 | oauth_access_grants | DELETE | 関連認可グラント削除 |

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

#### oauth_applications

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| DELETE | - | id = 指定アプリケーションID | レコード全体削除 |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|---------------|----------|
| MSG001 | 成功 | Application was successfully destroyed. | 削除成功時 |
| MSG002 | 空状態 | No applications found | アプリケーションが0件の場合 |
| MSG003 | 説明 | Manage applications for your instance that can use GitLab as an OAuth provider. | 画面説明 |

## 例外処理

| 例外条件 | 処理内容 | 表示メッセージ |
|----------|----------|---------------|
| 権限不足 | 403エラー画面へリダイレクト | アクセスが拒否されました |
| 削除対象不存在 | 404エラー画面表示 | ページが見つかりません |

## 備考

- インスタンスレベルのアプリケーションは`owner_id = null`で管理される
- Keyset Paginationを使用（大量データでも効率的）
- Trustedアプリケーションは認可画面をスキップして自動認可される
- Confidentialアプリケーションはクライアントシークレットを安全に保持できるアプリ向け
- 削除時は確認モーダルが表示される（`js-application-delete-modal`）

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | oauth_application.rb | `app/models/authn/oauth_application.rb` | OAuthアプリケーションモデル定義 |
| 1-2 | application.rb | Doorkeeper gem | Doorkeeper::Applicationの継承関係 |

**読解のコツ**:
- `Authn::OauthApplication`は`Doorkeeper::Application`を継承
- `belongs_to :organization`で組織との関連

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | applications_controller.rb | `app/controllers/admin/applications_controller.rb` | indexアクションの処理 |

**主要処理フロー**:
1. **11-15行目**: `index`アクション
2. **12行目**: `ApplicationsFinder.new.execute`でアプリケーション取得
3. **13行目**: `keyset_paginate`でページネーション
4. **14行目**: 総件数取得

#### Step 3: Finderを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | applications_finder.rb | `app/finders/applications_finder.rb` | クエリロジック |

**主要処理フロー**:
- **11行目**: `Authn::OauthApplication.where(owner_id: nil)` - インスタンスレベルのみ取得

#### Step 4: ビュー層を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | index.html.haml | `app/views/admin/applications/index.html.haml` | 一覧画面レイアウト |

**主要処理フロー**:
- **8-16行目**: アプリケーション0件時の空状態表示
- **18-52行目**: CrudComponentを使用したテーブル表示
- **41-50行目**: 各アプリケーション行のレンダリング
- **52行目**: Keyset Pagination

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

```
ブラウザ (GET /admin/applications)
    │
    └─ Admin::ApplicationsController#index
           ├─ ApplicationsFinder.new.execute
           │      └─ Authn::OauthApplication.where(owner_id: nil)
           ├─ applications.keyset_paginate(cursor: params[:cursor])
           └─ applications.count

           └─ View: admin/applications/index.html.haml
                  ├─ 空状態 or CrudComponent
                  ├─ テーブル表示
                  └─ keyset_paginate
```

### データフロー図

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

cursorパラメータ ────▶ ApplicationsController#index ──▶ 一覧HTML
  (ページネーション)          │
                              ├─ ApplicationsFinder
                              │      └─ owner_id = nil でフィルタ
                              └─ Keyset Pagination
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| applications_controller.rb | `app/controllers/admin/applications_controller.rb` | コントローラ | リクエスト処理 |
| oauth_application.rb | `app/models/authn/oauth_application.rb` | モデル | データ定義 |
| applications_finder.rb | `app/finders/applications_finder.rb` | ファインダー | クエリロジック |
| index.html.haml | `app/views/admin/applications/index.html.haml` | ビュー | 一覧画面 |
| admin.rb | `config/routes/admin.rb` | 設定 | ルーティング |
| oauth_applications_concern.rb | `app/controllers/concerns/oauth_applications.rb` | Concern | 共通処理 |
