# 機能設計書 87-アクセスリクエスト

## 概要

本ドキュメントは、GitLabにおけるアクセスリクエスト機能の設計を記述する。ユーザーはプロジェクトやグループへのアクセス権を持たない場合、管理者にアクセスリクエストを送信できる。管理者はリクエストを承認または却下することで、メンバーシップを制御する。

### 本機能の処理概要

**業務上の目的・背景**：オープンソースプロジェクトや大規模組織では、すべてのメンバーを事前に把握することが難しい。アクセスリクエスト機能により、ユーザーは自らアクセス権を申請でき、管理者は申請を審査してからアクセスを許可できる。これにより、セキュリティを維持しながら柔軟なメンバー管理が可能となる。

**機能の利用シーン**：
- 公開プロジェクトに貢献したいユーザーがアクセスを申請
- 社内の別部署のプロジェクトにアクセスを申請
- リクエストを送信したが却下された場合の再申請
- 管理者がリクエストを一括確認して承認・却下

**主要な処理内容**：
1. アクセスリクエストの送信
2. リクエストの一覧表示（管理者向け）
3. リクエストの承認（権限レベル指定可能）
4. リクエストの却下
5. リクエストの取り下げ（申請者自身）

**関連システム・外部連携**：
- 通知システム（リクエスト送信時の管理者への通知）
- Todoシステム（承認者へのTodo作成）
- メール送信システム（承認・却下時の通知）

**権限による制御**：
- リクエスト送信は誰でも可能（ただしプライベートプロジェクト/グループでは不可）
- 承認・却下はadmin_member_access_request権限が必要

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 124 | メンバー一覧 | 参照画面 | アクセスリクエスト一覧表示 |
| 144 | グループメンバー一覧 | 参照画面 | アクセスリクエスト一覧表示 |

## 機能種別

CRUD操作 / ワークフロー

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| access_level | Integer | No（承認時Yes） | 承認時の権限レベル | 有効なアクセスレベル |

### 入力データソース

- 画面操作（リクエストボタン、承認/却下ボタン）
- API経由

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| id | Integer | メンバーID |
| user_id | Integer | リクエスト者のユーザーID |
| requested_at | DateTime | リクエスト日時 |
| access_level | Integer | 承認時の権限レベル |

### 出力先

- 画面表示（リクエスト一覧）
- メール送信（承認・却下通知）

## 処理フロー

### 処理シーケンス

```
1. アクセスリクエスト送信
   └─ Members::RequestAccessService#execute
2. メンバーレコード作成（request状態）
   └─ requested_at設定、access_level=Developer
3. 管理者への通知
   └─ メール送信、Todo作成
4. 承認処理
   └─ Members::ApproveAccessRequestService#execute
5. または却下処理
   └─ Members::DestroyService#execute
```

### フローチャート

```mermaid
flowchart TD
    A[アクセスリクエスト] --> B{リクエスト可能?}
    B -->|No| C[アクセス拒否]
    B -->|Yes| D[メンバーレコード作成]
    D --> E[requested_at設定]
    E --> F[管理者へ通知]
    F --> G[Todo作成]
    G --> H[リクエスト完了]

    I[管理者操作] --> J{承認/却下}
    J -->|承認| K[ApproveAccessRequestService]
    J -->|却下| L[DestroyService]
    K --> M[requested_at = null]
    M --> N[メンバー有効化]
    L --> O[リクエスト削除]
    N --> P[承認通知メール]
    O --> Q[却下通知メール]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-87-01 | デフォルト権限 | リクエスト作成時のデフォルト権限はDeveloper | 常時 |
| BR-87-02 | 承認時権限変更 | 承認時に権限レベルを変更可能 | 承認時 |
| BR-87-03 | 通知先制限 | 通知を送る管理者は最大10人 | 通知時 |
| BR-87-04 | 自己取り下げ | リクエスト者は自身のリクエストを取り下げ可能 | 常時 |

### 計算ロジック

**通知先決定**：`access_request_approvers_to_be_notified`メソッドで最大10人の承認者を取得。

## データベース操作仕様

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| リクエスト作成 | members | INSERT | requested_at設定 |
| 承認 | members | UPDATE | requested_at=null, request_accepted_at設定 |
| 却下/取り下げ | members | DELETE | レコード削除 |
| Todo作成 | todos | INSERT | 承認者へのTodo |

### テーブル別操作詳細

#### members

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | user_id | リクエスト者ID | |
| INSERT | requested_at | 現在日時 | |
| INSERT | access_level | Gitlab::Access::DEVELOPER (30) | |
| UPDATE | requested_at | null | 承認時 |
| UPDATE | request_accepted_at | 現在日時 | 承認時 |
| UPDATE | created_by | 承認者ID | 承認時 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 権限エラー | リクエスト不可な状態 | アクセス拒否 |
| - | 権限エラー | 承認権限なし | アクセス拒否 |

### リトライ仕様

特になし。

## トランザクション仕様

単一レコードの操作のため、明示的なトランザクション不要。

## パフォーマンス要件

- リクエスト処理：500ms以内

## セキュリティ考慮事項

- プライベートプロジェクト/グループへのリクエストは閲覧権限が必要
- 承認者への通知は最大10人に制限（スパム防止）

## 備考

- ACCESS_REQUEST_APPROVERS_TO_BE_NOTIFIED_LIMIT = 10
- request?メソッドでリクエスト状態を判定

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | member.rb | `app/models/member.rb` | request関連メソッド |

**主要処理フロー**:
- **23行目**: ACCESS_REQUEST_APPROVERS_TO_BE_NOTIFIED_LIMIT = 10
- **193-194行目**: request/non_requestスコープ
- **536-538行目**: request?メソッド
- **550-557行目**: accept_requestメソッド
- **708-716行目**: send_requestメソッド（通知送信）

#### Step 2: サービス層を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | request_access_service.rb | `app/services/members/request_access_service.rb` | リクエスト作成 |
| 2-2 | approve_access_request_service.rb | `app/services/members/approve_access_request_service.rb` | 承認処理 |

**主要処理フロー（RequestAccessService）**:
- **7-14行目**: executeメソッド
- **17-19行目**: default_access_level = DEVELOPER

**主要処理フロー（ApproveAccessRequestService）**:
- **7-17行目**: executeメソッド
- **21-24行目**: handle_request_acceptance
- **40-43行目**: can_approve_access_requester?

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

```
Members::RequestAccessService#execute
    │
    ├─ can_request_access?(source) - 権限チェック
    ├─ source.members.create(requested_at: Time.current)
    └─ after_commit: send_request
           ├─ Members::AccessRequestedMailer (各承認者へ)
           └─ TodoService#create_member_access_request_todos

Members::ApproveAccessRequestService#execute
    │
    ├─ validate_access! - 承認権限チェック
    ├─ access_requester.access_level = params[:access_level]
    ├─ handle_request_acceptance
    │      └─ access_requester.accept_request(current_user)
    └─ after_execute
           └─ resolve_access_request_todos
```

### データフロー図

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

ユーザー操作         RequestAccessService             DB保存
(リクエスト)     ──▶ ├─権限チェック              ──▶  members
                      └─メンバー作成(request)          (request状態)
                                                      ▼
                                                   管理者通知
                                                   Todo作成
                                                      ▼
管理者操作
(承認/却下)       ──▶  ApproveAccessRequestService
                      / DestroyService
                                                      ▼
                                                   メンバー有効化/削除
                                                   通知メール送信
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| member.rb | `app/models/member.rb` | モデル | request関連メソッド |
| request_access_service.rb | `app/services/members/request_access_service.rb` | サービス | リクエスト作成 |
| approve_access_request_service.rb | `app/services/members/approve_access_request_service.rb` | サービス | 承認処理 |
| access_requested_mailer.rb | `app/mailers/members/access_requested_mailer.rb` | メーラー | リクエスト通知 |
| access_denied_mailer.rb | `app/mailers/members/access_denied_mailer.rb` | メーラー | 却下通知 |
| access_requests_finder.rb | `app/finders/access_requests_finder.rb` | Finder | リクエスト検索 |
