# 機能設計書 145-ファイルアップロード

## 概要

本ドキュメントは、GitLabのファイルアップロード機能に関する設計書である。ファイルアップロード機能はイシュー、マージリクエスト等へのファイル添付や、各種エンティティの画像アップロードを担う。

### 本機能の処理概要

ファイルアップロード機能は、GitLab上の様々なエンティティ（ユーザー、プロジェクト、グループ、ノート、スニペット等）に対してファイルを添付・アップロードするための汎用的な機能である。Workhorseと連携した効率的なファイル転送、権限に基づくアクセス制御、キャッシュ管理などを提供する。

**業務上の目的・背景**：イシューやマージリクエストでの議論において、スクリーンショットやログファイル、設計書などの添付ファイルが必要となる。また、ユーザーアバターやプロジェクトロゴなどの画像アップロードも必要である。これらを統一的に管理する機能が本機能である。

**機能の利用シーン**：
- イシューコメントへのスクリーンショット添付
- マージリクエストへのドキュメント添付
- ユーザーアバターのアップロード
- プロジェクト/グループのロゴ設定
- アラート管理のメトリック画像添付
- 組織の詳細画像設定

**主要な処理内容**：
1. ファイルアップロードの事前認可（Workhorse連携）
2. アップロードファイルの受信・保存
3. アップロードファイルの取得・配信
4. モデル別の権限チェック
5. キャッシュ制御（モデル種別による）

**関連システム・外部連携**：
- GitLab Workhorse（ファイルアップロード最適化）
- オブジェクトストレージ（S3互換等）
- CarrierWave（ファイルアップローダー）

**権限による制御**：
- モデル種別ごとに異なる権限チェック
- User: update_user権限
- Note: read_project権限
- Snippet: read_snippet権限
- AlertManagement::MetricImage: read_alert_management_metric_image権限
- その他: read_{model_class}権限

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | 各種フォーム画面 | 補助機能 | ファイル添付処理 |

## 機能種別

ファイル操作 / アップロード / ダウンロード

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| model | String | Yes | モデル種別（user, project, note, group等） | MODEL_CLASSESに定義されていること |
| id | Integer | Yes | モデルID | 存在するIDであること |
| mounted_as | String | No | マウントポイント（avatar, attachment, file等） | UPLOAD_MOUNTSに含まれること |
| filename | String | No | ファイル名（表示時） | パストラバーサル攻撃対策あり |
| secret | String | No | ファイルシークレット | 一時ファイルアクセス時 |
| file | File | Yes | アップロードファイル（作成時） | ファイルサイズ制限あり |

### 入力データソース

- マルチパートフォームデータ
- Workhorse経由のファイル転送

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| link | Object | アップロードされたファイルへのリンク情報（create時） |
| ファイル | Binary | アップロードされたファイル（show時） |

### 出力先

- JSON形式HTTPレスポンス（create時）
- ファイルストリーム（show時）
- Workhorse認可情報（authorize時）

## 処理フロー

### 処理シーケンス

```
1. authorizeアクション（アップロード事前認可）
   └─ Workhorse APIリクエスト検証
   └─ アップロード権限確認
   └─ Workhorse認可情報を返却

2. createアクション（ファイルアップロード）
   └─ アップロード権限確認
   └─ UploadService.new().execute
   └─ アップロードリンク情報をJSON返却

3. showアクション（ファイル取得）
   └─ パストラバーサル攻撃チェック
   └─ アクセス権限確認
   └─ キャッシュ設定
   └─ ファイル送信（send_upload）
```

### フローチャート

```mermaid
flowchart TD
    A[リクエスト受信] --> B{アクション判定}

    B -->|authorize| C[Workhorse API検証]
    B -->|create| D[アップロード権限確認]
    B -->|show| E[アクセス権限確認]

    C --> F{検証OK?}
    F -->|Yes| G[認可情報返却]
    F -->|No| H[404エラー]

    D --> I{権限あり?}
    I -->|Yes| J[UploadService実行]
    I -->|No| K[認証要求/404]

    J --> L{アップロード成功?}
    L -->|Yes| M[リンク情報JSON]
    L -->|No| N[422エラー]

    E --> O{アクセス可?}
    O -->|Yes| P{ファイル存在?}
    O -->|No| Q[認証要求/404]

    P -->|Yes| R[キャッシュ設定]
    P -->|No| H

    R --> S[ファイル送信]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-145-01 | モデル別権限 | モデル種別ごとに異なる権限チェックを適用 | 全アクション |
| BR-145-02 | シークレットファイル | secretパラメータ付きファイルは追加権限チェック | User モデル |
| BR-145-03 | 公開エンティティキャッシュ | User, Appearance, Topic等は5分キャッシュ（public） | showアクション |
| BR-145-04 | 非公開エンティティキャッシュ | Project, Groupは5分キャッシュ（private, must_revalidate） | showアクション |
| BR-145-05 | ファイルサイズ制限 | max_attachment_size設定によりサイズ制限 | authorizeアクション |

### 計算ロジック

**キャッシュ設定**:
```ruby
case model
when User, Appearance, Projects::Topic, Achievements::Achievement, Organizations::OrganizationDetail
  [5.minutes, { public: true, must_revalidate: false }]
when Project, Group
  [5.minutes, { private: true, must_revalidate: true }]
end
```

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| モデル検索 | 各モデルテーブル | SELECT | アップロード対象モデルの検索 |
| アップロード記録 | uploads | INSERT | アップロードファイル情報の保存 |
| アップロード取得 | uploads | SELECT | ファイル情報の取得 |

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

#### uploads

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | model_type, model_id, uploader, path, size, checksum | UploadService経由 | 新規アップロード |
| SELECT | path, secret | model + uploader + path | ファイル取得 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 400 | Bad Request | パストラバーサル攻撃検出 | head :bad_request |
| 404 | Not Found | モデル/ファイルが存在しない | render_404 |
| 422 | Unprocessable Entity | 無効なファイル | "Invalid file." メッセージ |
| 500 | Internal Server Error | オブジェクトストレージ接続エラー | "Error uploading file" |

### リトライ仕様

特になし

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

- アップロード処理はUploadService内でトランザクション管理

## パフォーマンス要件

- Workhorseによるファイル転送最適化
- キャッシュによる負荷軽減（5分間）
- feature_category: groups_and_projects

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

- パストラバーサル攻撃対策（Gitlab::PathTraversal.check_path_traversal!）
- FileUploader::InvalidSecret例外ハンドリング
- モデル別の権限チェック
- 2FAチェックスキップ（showアクションのみ）
- Workhorse API検証（verify_workhorse_api!）
- 最大アップロードサイズ制限

## 備考

- MODEL_CLASSESで対応モデルを定義
- UPLOAD_MOUNTSでマウントポイントを制限
- PrependでEE機能を拡張可能（UploadsController.prepend_mod_with）

---

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

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

### 推奨読解順序

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

メインコントローラの処理フローを把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | uploads_controller.rb | `app/controllers/uploads_controller.rb` | アップロード機能のエントリーポイント |

**主要処理フロー**:
1. **9-22行目**: MODEL_CLASSES定数 - 対応モデルの定義
2. **26-27行目**: skip_before_action - 認証スキップ条件
3. **43-46行目**: find_model - モデル検索
4. **48-74行目**: authorized? - モデル別権限チェック
5. **80-90行目**: authorize_create_access! - アップロード権限確認
6. **100-107行目**: cache_settings - キャッシュ設定

**読解のコツ**:
- UploadsActionsモジュールに実際のアクション（create, show, authorize）が定義
- モデル別の権限チェックはcaseで分岐

#### Step 2: アップロードアクションを理解する

UploadsActionsモジュールの実装を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | uploads_actions.rb | `app/controllers/concerns/uploads_actions.rb` | create, show, authorizeアクションの実装 |

**主要処理フロー**:
1. **29-43行目**: create アクション - UploadService経由でアップロード
2. **49-68行目**: show アクション - ファイル配信
3. **70-80行目**: authorize アクション - Workhorse認可

#### Step 3: Uploadモデルを理解する

アップロードデータの永続化を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | upload.rb | `app/models/upload.rb` | アップロードモデル |

**主要処理フロー**:
1. **16-19行目**: バリデーション
2. **26-34行目**: before_save/after_destroy コールバック
3. **65-70行目**: absolute_path - ファイルパス取得
4. **107-122行目**: exist? - ファイル存在確認

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

```
UploadsController
    │
    ├─ authorize (UploadsActions)
    │      ├─ verify_workhorse_api!
    │      ├─ authorize_create_access!
    │      └─ uploader_class.workhorse_authorize
    │
    ├─ create (UploadsActions)
    │      ├─ authorize_create_access!
    │      └─ UploadService.new(model, file).execute
    │             └─ Upload.create
    │
    └─ show (UploadsActions)
           ├─ Gitlab::PathTraversal.check_path_traversal!
           ├─ authorize_access!
           │      └─ authorized? (モデル別権限チェック)
           ├─ cache_settings
           └─ send_upload
```

### データフロー図

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

POST /authorize       ───▶  UploadsController         ───▶  Workhorse認可JSON
                            └─ workhorse_authorize

POST /uploads         ───▶  UploadsController         ───▶  { link: {...} }
                            └─ UploadService
                                   └─ Upload INSERT

GET /uploads/:id/:file ───▶ UploadsController          ───▶  ファイルストリーム
                            ├─ Upload SELECT
                            └─ send_upload
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| uploads_controller.rb | `app/controllers/uploads_controller.rb` | コントローラ | アップロード機能のエントリーポイント |
| uploads_actions.rb | `app/controllers/concerns/uploads_actions.rb` | Concern | アップロードアクション実装 |
| upload.rb | `app/models/upload.rb` | モデル | アップロードモデル |
| upload_service.rb | `app/services/upload_service.rb` | サービス | アップロード処理サービス |
| personal_file_uploader.rb | `app/uploaders/personal_file_uploader.rb` | アップローダー | 個人ファイルアップローダー |
| file_uploader.rb | `app/uploaders/file_uploader.rb` | アップローダー | 汎用ファイルアップローダー |
| send_file_upload.rb | `app/controllers/concerns/send_file_upload.rb` | Concern | ファイル送信処理 |
| workhorse_request.rb | `app/controllers/concerns/workhorse_request.rb` | Concern | Workhorse連携 |
