# 機能設計書 41-ロール管理

## 概要

本ドキュメントは、Ghost CMSにおけるロール管理機能の設計仕様を記載したものである。

### 本機能の処理概要

ロール管理機能は、Ghost CMSにおけるユーザーの役割（Role）を定義・管理する機能である。ロールはシステム内での操作権限を決定するための基盤となり、各スタッフユーザーにロールを割り当てることで、そのユーザーが実行可能な操作を制御する。

**業務上の目的・背景**：Ghost CMSは複数のスタッフユーザーによる共同運営を想定しており、ユーザーごとに適切な操作権限を設定する必要がある。ロール管理機能により、Owner（サイト所有者）、Administrator（管理者）、Editor（編集者）、Author（著者）、Contributor（投稿者）といった階層的な権限体系を実現し、セキュリティと運用効率の両立を図る。

**機能の利用シーン**：
- サイト管理者がスタッフユーザーに適切なロールを割り当てる場面
- 新規スタッフ招待時にロールを選択する場面
- ユーザーの権限を昇格・降格する場面
- システムがAPI操作時に権限チェックを行う場面

**主要な処理内容**：
1. ロール一覧の取得（Browse）：利用可能なすべてのロールを取得
2. ロールの権限チェック（permissible）：ロール割り当て時の権限検証
3. ロールと権限の関連付け：ロールに紐づく権限（Permission）の管理
4. ロール階層の適用：OwnerはすべてのロールをAdminは一部のロールを割り当て可能

**関連システム・外部連携**：
- 権限管理サービス（Permissions Service）と連携
- ユーザーモデル（User Model）との多対多関係
- APIキーモデル（ApiKey Model）との関連

**権限による制御**：
- Ownerはすべてのロール（Owner含む）を割り当て可能
- Administratorは自分自身およびOwner以外のロールを割り当て可能
- Editor/Super Editorは Author/Contributor のみ割り当て可能
- APIキー経由ではOwnerロールの割り当てを禁止

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 36 | ユーザー・権限設定 | 主画面 | スタッフユーザーへのロール割り当て表示 |
| 36 | ユーザー・権限設定 | 補助機能 | ロール選択UIの表示 |

## 機能種別

CRUD操作（Read）/ バリデーション / 権限チェック

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| permissions | string | No | 権限フィルタオプション | 値は'assign'のみ許可 |
| withRelated | array | No | 関連データの取得指定 | なし |

### 入力データソース

- APIエンドポイント経由でのリクエスト（GET /ghost/api/admin/roles/）
- DBテーブル: roles

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| id | string | ロールの一意識別子（24文字） |
| name | string | ロール名（Owner, Administrator, Editor等） |
| description | string | ロールの説明文 |
| created_at | dateTime | 作成日時 |
| updated_at | dateTime | 更新日時 |
| permissions | array | 関連する権限の配列（withRelated指定時） |

### 出力先

- APIレスポンス（JSON形式）
- 管理画面のロール選択ドロップダウン

## 処理フロー

### 処理シーケンス

```
1. APIリクエスト受信
   └─ GET /ghost/api/admin/roles/ が呼び出される
2. 権限チェック
   └─ 認証済みユーザーの権限を確認
3. モデル取得
   └─ Role.findAll()でDBからロール一覧を取得
4. オプション処理
   └─ withRelatedオプションがある場合は関連データも取得
5. レスポンス返却
   └─ JSON形式でロール一覧を返却
```

### フローチャート

```mermaid
flowchart TD
    A[APIリクエスト受信] --> B{認証済み?}
    B -->|No| C[401 Unauthorized]
    B -->|Yes| D{権限チェック}
    D -->|No| E[403 Forbidden]
    D -->|Yes| F[Role.findAll実行]
    F --> G{withRelated指定?}
    G -->|Yes| H[関連データ取得]
    G -->|No| I[ロールデータのみ]
    H --> J[レスポンス返却]
    I --> J
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-41-001 | ロール割り当て階層制限 | 上位ロールは下位ロールのみ割り当て可能 | ロール割り当て操作時 |
| BR-41-002 | Owner割り当て禁止 | APIキー経由でOwnerロールは割り当て不可 | APIキーによる操作時 |
| BR-41-003 | ロール名一意制約 | ロール名はシステム内で一意 | ロール参照時 |

### 計算ロジック

該当なし（ロール管理にはマスタデータ的な性質があり、計算処理は存在しない）

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| ロール一覧取得 | roles | SELECT | 全ロールの取得 |
| ロール権限取得 | permissions_roles | SELECT | ロールに紐づく権限の取得 |
| ユーザーロール確認 | roles_users | SELECT | ユーザーに割り当てられたロールの確認 |

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

#### roles

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | id, name, description, created_at, updated_at | 条件なし（全件取得） | ロールはシステムで定義済み |

#### roles_users

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | role_id, user_id | user_idで検索 | ユーザーのロール確認時 |

#### permissions_roles

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | role_id, permission_id | role_idで検索 | withRelated指定時 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 401 | Unauthorized | 認証なしでアクセス | 認証情報を付与してリクエスト |
| 403 | NoPermissionError | 権限不足でロール割り当て | 上位権限ユーザーで操作 |
| 404 | NotFoundError | 指定ロールが存在しない | 有効なロールIDを指定 |

### リトライ仕様

該当なし（マスタデータ参照のため、リトライは不要）

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

ロール一覧取得は参照のみのため、トランザクション管理は不要。ロール割り当て時は、ユーザーモデル側でトランザクション管理を行う。

## パフォーマンス要件

- ロール一覧取得: 100ms以内
- ロール数は固定（6種類）のため、パフォーマンス問題は発生しにくい

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

- Ownerロールの割り当てはOwnerのみ可能
- APIキー経由ではOwnerロールの割り当てを禁止
- ロール階層に基づく権限チェックを必ず実行
- 権限チェックをスキップするinternalコンテキストは内部処理のみに限定

## 備考

- Ghostの標準ロール: Owner, Administrator, Super Editor, Editor, Author, Contributor
- ロールはfixturesとしてシステム初期化時に作成される
- カスタムロールの追加はサポートされていない

---

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

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

### 推奨読解順序

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

まず、ロールのデータモデルとスキーマを理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | schema.js | `ghost/core/core/server/data/schema/schema.js` | rolesテーブルの定義（193-199行目）を確認 |
| 1-2 | schema.js | `ghost/core/core/server/data/schema/schema.js` | roles_usersテーブル（200-204行目）の多対多関係を理解 |
| 1-3 | schema.js | `ghost/core/core/server/data/schema/schema.js` | permissions_rolesテーブル（219-223行目）の権限関連を確認 |

**読解のコツ**: Ghostのスキーマ定義はJSON形式で記述されており、各カラムの型、制約、デフォルト値が明確に定義されている。

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

APIエンドポイントの定義を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | roles.js | `ghost/core/core/server/api/endpoints/roles.js` | APIコントローラの定義（browseアクション） |

**主要処理フロー**:
1. **6-9行目**: browseアクションの定義、cacheInvalidate: falseでキャッシュ無効化なし
2. **10-16行目**: permissionsオプションで'assign'値のバリデーション
3. **18-21行目**: permissions: trueで権限チェック有効化
4. **19-21行目**: Role.findAllでモデルからデータ取得

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

Roleモデルの実装を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | role.js | `ghost/core/core/server/models/role.js` | Roleモデルの定義（15-120行目） |
| 3-2 | role-utils.js | `ghost/core/core/server/models/role-utils.js` | ロール判定ユーティリティ関数 |

**主要処理フロー**:
- **17行目**: tableName: 'roles' でテーブル名を指定
- **19-23行目**: relationshipsでpermissionsとの関連を定義
- **25-35行目**: users, permissions, api_keysとのリレーション定義
- **59-110行目**: permissible関数でロール割り当ての権限チェック実装
- **81-94行目**: loadedPermissionsからユーザーのロールを判定し、割り当て可能なロールを決定

#### Step 4: 権限チェックの仕組みを理解する

権限管理サービスとの連携を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | can-this.js | `ghost/core/core/server/services/permissions/can-this.js` | 権限チェックのコア実装 |
| 4-2 | providers.js | `ghost/core/core/server/services/permissions/providers.js` | ユーザー・APIキーの権限取得 |

**主要処理フロー**:
- **17-26行目**: objectTypeModelMapでモデルとオブジェクトタイプのマッピング
- **29-106行目**: buildObjectTypeHandlersで各オブジェクトタイプのハンドラを構築
- **91-95行目**: TargetModel.permissibleで対象モデル固有の権限チェックを実行

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

```
API Request (GET /ghost/api/admin/roles/)
    │
    ├─ roles.js (controller)
    │      ├─ permissions check (via api-framework)
    │      │      └─ can-this.js
    │      │             └─ providers.js (load user permissions)
    │      │
    │      └─ Role.findAll()
    │             └─ role.js (model)
    │                    └─ ghostBookshelf.Model.extend
    │                           └─ Bookshelf ORM → Database
```

### データフロー図

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

APIリクエスト ───▶ roles.js (controller) ───▶ JSON Response
     │                    │                        │
     │                    ▼                        │
     │            permissions check                │
     │                    │                        │
     │                    ▼                        │
     │            Role.findAll()                   │
     │                    │                        │
     │                    ▼                        │
     │            Database SELECT                  │
     │                    │                        │
     └────────────────────┴────────────────────────┘
                         roles table
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| role.js | `ghost/core/core/server/models/role.js` | ソース | Roleモデル定義 |
| role-utils.js | `ghost/core/core/server/models/role-utils.js` | ソース | ロール判定ユーティリティ |
| roles.js | `ghost/core/core/server/api/endpoints/roles.js` | ソース | APIエンドポイント |
| schema.js | `ghost/core/core/server/data/schema/schema.js` | 設定 | DBスキーマ定義 |
| fixtures.json | `ghost/core/core/server/data/schema/fixtures/fixtures.json` | 設定 | 初期ロールデータ |
| can-this.js | `ghost/core/core/server/services/permissions/can-this.js` | ソース | 権限チェック |
| providers.js | `ghost/core/core/server/services/permissions/providers.js` | ソース | 権限データ取得 |
| parse-context.js | `ghost/core/core/server/services/permissions/parse-context.js` | ソース | コンテキスト解析 |
