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

## 概要

本ドキュメントは、GitLabグループレベルのOAuthアプリケーション一覧画面の設計書です。グループスコープのOAuthアプリケーションを管理する画面を定義します。

### 本画面の処理概要

本画面では、グループに関連付けられたOAuthアプリケーションの一覧表示、新規作成、管理を行います。

**業務上の目的・背景**：組織内でGitLab APIと連携する社内アプリケーションを運用する際、個人ではなくグループスコープでOAuthアプリケーションを管理することで、チームでの開発・運用を容易にし、アプリケーションの所有権を組織レベルで管理できます。

**画面へのアクセス方法**：グループの設定メニューから「アプリケーション」を選択してアクセスします。アクセスには`admin_group`権限が必要です。

**主要な操作・処理内容**：
1. OAuthアプリケーション一覧の確認
2. 新規OAuthアプリケーションの作成
3. アプリケーション詳細画面への遷移
4. アプリケーションの編集・削除

**画面遷移**：
- 遷移元：グループ設定メニュー、グループ詳細画面
- 遷移先：アプリケーション詳細画面、アプリケーション編集画面

**権限による表示制御**：`admin_group`権限を持つユーザーのみアクセス可能です。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 88 | OAuth2プロバイダ | 主機能 | グループOAuthアプリの一覧 |

## 画面種別

一覧 / 登録

## URL/ルーティング

| パス | HTTPメソッド | アクション |
|------|-------------|----------|
| `/groups/:group_id/-/settings/applications` | GET | index |
| `/groups/:group_id/-/settings/applications` | POST | create |
| `/groups/:group_id/-/settings/applications/:id` | GET | show |
| `/groups/:group_id/-/settings/applications/:id/edit` | GET | edit |
| `/groups/:group_id/-/settings/applications/:id` | PUT/PATCH | update |
| `/groups/:group_id/-/settings/applications/:id` | DELETE | destroy |
| `/groups/:group_id/-/settings/applications/:id/renew` | PUT | renew |

## 入出力項目

### アプリケーション作成フォーム

| 項目名 | 種別 | 必須 | 説明 |
|--------|------|------|------|
| Name | テキスト | 必須 | アプリケーション名 |
| Redirect URI | テキストエリア | 必須 | OAuth認可後のリダイレクトURI |
| Confidential | チェックボックス | 任意 | コンフィデンシャルクライアント |
| Scopes | チェックボックス群 | 必須 | 許可するスコープ |

### 選択可能なスコープ

- `api` - 完全なAPIアクセス
- `read_user` - ユーザー情報の読み取り
- `read_api` - 読み取り専用APIアクセス
- `read_repository` - リポジトリの読み取り
- `write_repository` - リポジトリへの書き込み
- `openid` - OpenID Connect
- `profile` - プロファイル情報
- `email` - メールアドレス

## 表示項目

### ページヘッダー

| 項目名 | 説明 |
|--------|------|
| タイトル | "Group applications" |

### アプリケーション一覧

| 項目名 | 説明 |
|--------|------|
| アプリケーション名 | 登録されたアプリケーションの名前 |
| リダイレクトURI | 設定されたリダイレクトURI |
| スコープ | 許可されたスコープ一覧 |
| 作成日時 | アプリケーションの作成日 |
| 操作ボタン | 詳細、編集、削除へのリンク |

### 新規作成フォーム

| 項目名 | 説明 |
|--------|------|
| アプリケーション作成フォーム | 新規OAuthアプリケーション作成用フォーム |

## イベント仕様

### 1-アプリケーション作成

**トリガー**：作成フォームの送信

**処理フロー**：
1. POSTリクエストをcreateアクションに送信
2. `Applications::CreateService`でアプリケーション作成
3. 成功時：詳細画面へ遷移、クライアントシークレットを表示
4. 失敗時：エラーメッセージを表示、フォームを再表示

### 2-アプリケーション一覧表示

**トリガー**：画面アクセス

**処理フロー**：
1. グループのOAuthアプリケーションを取得
2. キーセットページネーションで一覧表示

### 3-シークレット更新（renew）

**トリガー**：renewボタンのクリック

**処理フロー**：
1. PUTリクエストをrenewアクションに送信
2. `@application.renew_secret`で新しいシークレットを生成
3. JSON形式で新しいシークレットを返却

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| アプリケーション作成 | oauth_applications | INSERT | OAuthアプリケーションを作成 |
| アプリケーション更新 | oauth_applications | UPDATE | アプリケーション情報を更新 |
| アプリケーション削除 | oauth_applications | DELETE | アプリケーションを削除 |
| シークレット更新 | oauth_applications | UPDATE | シークレットを再生成 |

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

#### oauth_applications

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | name | フォーム入力値 | アプリケーション名 |
| INSERT | redirect_uri | フォーム入力値 | リダイレクトURI |
| INSERT | confidential | フォーム入力値 | コンフィデンシャルフラグ |
| INSERT | scopes | 選択されたスコープ | スコープ文字列 |
| INSERT | owner_id | グループID | グループとの関連付け |
| INSERT | owner_type | 'Namespace' | オーナー種別 |
| INSERT | organization_id | Current.organization | 組織との関連付け |
| UPDATE | secret | 新しいシークレット | renew時に更新 |

## メッセージ仕様

| 種別 | メッセージ | 表示条件 |
|------|----------|----------|
| 成功 | doorkeeper.flash.applications.create.notice | アプリケーション作成成功時 |
| 成功 | "Application was successfully updated." | アプリケーション更新成功時 |
| 成功 | "Application was successfully destroyed." | アプリケーション削除成功時 |
| エラー | バリデーションエラー | 作成/更新失敗時 |

## 例外処理

| 例外 | 処理 |
|------|------|
| 権限不足 | アクセス拒否ページへリダイレクト |
| アプリケーション作成失敗 | エラーメッセージを表示、フォームを再表示 |
| シークレット更新失敗 | JSON形式でエラーを返却 |

## 備考

- スタイルは`page_bundles/settings`を使用
- `OauthApplications` Concernで共通処理を実装
- `Authn::OauthApplication`モデルを使用
- キーセットページネーション（cursor ベース）でアプリケーション一覧を取得
- 共有パーシャル`shared/doorkeeper/applications/_index`を使用

---

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

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

### 推奨読解順序

#### Step 1: コントローラーを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | applications_controller.rb | `app/controllers/groups/settings/applications_controller.rb` | CRUD実装 |
| 1-2 | oauth_applications.rb | `app/controllers/concerns/oauth_applications.rb` | 共通処理 |

**主要処理フロー**:
1. **行8**: before_actionで`authorize_admin_group!`
2. **行9**: before_actionで`set_application`（show, edit, update, renew, destroy）
3. **行10**: before_actionで`load_scopes`
4. **行14-16**: indexアクションで一覧とフォーム初期化
5. **行22-33**: createアクションでアプリケーション作成
6. **行45-52**: renewアクションでシークレット更新

#### Step 2: ビューレイヤーを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | index.html.haml | `app/views/groups/settings/applications/index.html.haml` | ページ構成 |
| 2-2 | _index.html.haml | `app/views/shared/doorkeeper/applications/_index.html.haml` | アプリケーション一覧 |

**主要処理フロー**:
- **行5-10**: 共有パーシャルに各種URLを渡して呼び出し

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

```
groups/settings/applications_controller.rb#index
    │
    ├─ authorize_admin_group! (before_action)
    │
    ├─ load_scopes (before_action)
    │
    └─ set_index_vars
           │
           ├─ @applications = @group.oauth_applications.keyset_paginate
           ├─ @applications_total_count = @group.oauth_applications.count
           └─ @application = Authn::OauthApplication.new
           │
           └─ index.html.haml
                  │
                  └─ shared/doorkeeper/applications/_index
                         ├─ form_url: group_settings_applications_path
                         ├─ application_url: group_settings_application_path
                         └─ edit_application_url: edit_group_settings_application_path

groups/settings/applications_controller.rb#create
    │
    ├─ Applications::CreateService.new(current_user, request, params).execute
    │
    ├─ [成功] @created = true, render :show
    │
    └─ [失敗] set_index_vars, render :index
```

### データフロー図

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

グループID ───────────▶ ApplicationsController#index ───▶ index.html.haml
    │                        │                                │
    │                        ▼                                ▼
    │               @applications =                    アプリケーション一覧
    │               @group.oauth_applications          + 作成フォーム
    │               .keyset_paginate
    │
    │
アプリ作成 ─────────────▶ ApplicationsController#create
フォームデータ                │
                             ▼
                    Applications::CreateService.execute
                             │
                             └─ oauth_applications INSERT
                                    │
                                    ▼
                             show画面 + クライアントシークレット表示
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| applications_controller.rb | `app/controllers/groups/settings/applications_controller.rb` | コントローラー | リクエスト処理 |
| oauth_applications.rb | `app/controllers/concerns/oauth_applications.rb` | Concern | 共通処理 |
| index.html.haml | `app/views/groups/settings/applications/index.html.haml` | ビュー | 一覧画面描画 |
| _index.html.haml | `app/views/shared/doorkeeper/applications/_index.html.haml` | パーシャル | アプリ一覧共通 |
| group.rb | `config/routes/group.rb` | ルーティング | URL定義（行82-84） |
| oauth_application.rb | `app/models/authn/oauth_application.rb` | モデル | OAuthアプリモデル |
| create_service.rb | `app/services/applications/create_service.rb` | サービス | アプリケーション作成 |
