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

## 概要

本ドキュメントは、RuoYiシステムにおけるロール管理機能の設計仕様を記載する。ロール管理機能は、システムのアクセス制御を実現するための権限グループを管理する機能である。

### 本機能の処理概要

ロール管理機能は、システム管理者がロール（権限グループ）の作成・変更・削除・照会を行うための機能を提供する。各ロールにはメニュー権限とデータ権限を設定でき、ユーザーにロールを割り当てることでアクセス制御を実現する。

**業務上の目的・背景**：企業・組織において、職責や役割に応じた適切なアクセス権限を付与することは、情報セキュリティと業務効率の両立に不可欠である。本機能により、管理者は「営業部長」「一般社員」などの役割に応じた権限テンプレートを作成・管理し、ユーザーへの権限付与を効率化できる。

**機能の利用シーン**：
- 新しい職種・役職に対応した権限グループの作成時
- 組織変更に伴う権限範囲の見直し時
- 機能追加に伴うメニュー権限の更新時
- データアクセス範囲（部門スコープ）の設定時
- ロールへのユーザー一括割当時
- 権限設定の棚卸・監査時

**主要な処理内容**：
1. ロール一覧の検索・表示
2. ロールの新規登録（メニュー権限の同時設定）
3. ロール情報の編集・更新
4. ロールの論理削除
5. データ権限（部門スコープ）の設定
6. ロールへのユーザー割当・解除
7. ロールステータス（有効/無効）の変更
8. Excelファイルによるロールデータのエクスポート

**関連システム・外部連携**：本機能は単独で動作し、外部システムとの直接連携はない。ただし、ユーザー管理、メニュー管理、部門管理機能と密接に連携する。

**権限による制御**：
- `system:role:view` - ロール一覧画面の表示権限
- `system:role:list` - ロール一覧の取得権限
- `system:role:add` - ロール新規登録権限
- `system:role:edit` - ロール編集権限
- `system:role:remove` - ロール削除権限
- `system:role:export` - ロールデータエクスポート権限

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 19 | ロール管理一覧 | 主画面 | ロール一覧の検索、表示、ステータス変更処理 |
| 20 | ロール新規登録 | 主画面 | 新規ロール情報入力と登録保存処理 |
| 21 | ロール編集 | 主画面 | ロール情報の更新保存処理 |
| 22 | ロールデータ権限設定 | 主画面 | ロールのデータアクセス権限設定処理 |
| 23 | ロールユーザー割当 | 主画面 | ロールへのユーザー割当・解除処理 |
| 24 | ユーザー選択ダイアログ | 補助画面 | ユーザー検索と選択処理 |

## 機能種別

CRUD操作 / 権限管理 / データ連携（Excel出力） / バリデーション

## 入力仕様

### 入力パラメータ

#### ロール検索条件

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| roleId | Long | No | ロールID | 数値 |
| roleName | String | No | ロール名（部分一致） | 最大30文字 |
| roleKey | String | No | 権限文字列（部分一致） | 最大100文字 |
| status | String | No | ステータス | 0:正常, 1:停用 |
| beginTime | String | No | 作成日（開始） | 日付形式 |
| endTime | String | No | 作成日（終了） | 日付形式 |

#### ロール登録・更新

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| roleId | Long | 更新時必須 | ロールID | 数値 |
| roleName | String | Yes | ロール名 | 必須、最大30文字、一意性チェック |
| roleKey | String | Yes | 権限文字列 | 必須、最大100文字、一意性チェック |
| roleSort | String | Yes | 表示順序 | 必須 |
| dataScope | String | No | データスコープ | 1-5の数値 |
| status | String | No | ステータス | 0:正常, 1:停用 |
| remark | String | No | 備考 | - |
| menuIds | Long[] | No | メニューID配列 | - |
| deptIds | Long[] | No | 部門ID配列（データ権限用） | - |

### 入力データソース

- 画面入力：管理者による直接入力
- メニューツリー：メニュー権限選択時にツリー形式で表示
- 部門ツリー：データ権限設定時にツリー形式で表示

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| roleId | Long | ロールID |
| roleName | String | ロール名 |
| roleKey | String | 権限文字列 |
| roleSort | String | 表示順序 |
| dataScope | String | データスコープ |
| status | String | ステータス |
| delFlag | String | 削除フラグ |
| createBy | String | 作成者 |
| createTime | Date | 作成日時 |
| updateBy | String | 更新者 |
| updateTime | Date | 更新日時 |
| remark | String | 備考 |

### 出力先

- 画面表示：ロール一覧、詳細画面
- Excelファイル：エクスポート機能

## 処理フロー

### 処理シーケンス

```
1. ロール一覧取得
   └─ 検索条件を受け取り、データスコープを適用してロール一覧を取得

2. ロール新規登録
   └─ 入力バリデーション
   └─ ロール名・権限文字列の一意性チェック
   └─ ロール情報登録
   └─ ロール・メニュー関連登録
   └─ 認可キャッシュクリア

3. ロール更新
   └─ 入力バリデーション
   └─ 操作対象ロールの権限チェック（管理者ロール不可）
   └─ データスコープチェック
   └─ 一意性チェック
   └─ ロール情報更新
   └─ 既存のロール・メニュー関連削除
   └─ 新しいロール・メニュー関連登録
   └─ 認可キャッシュクリア

4. ロール削除
   └─ 操作対象ロールの権限チェック
   └─ データスコープチェック
   └─ ユーザー割当確認（割当済みの場合は削除不可）
   └─ ロール・メニュー関連削除
   └─ ロール・部門関連削除
   └─ ロール論理削除

5. データ権限設定
   └─ 操作対象ロールの権限チェック
   └─ データスコープチェック
   └─ ロール情報更新（dataScope）
   └─ 既存のロール・部門関連削除
   └─ 新しいロール・部門関連登録

6. ユーザー割当
   └─ データスコープチェック
   └─ ユーザー・ロール関連登録

7. ユーザー割当解除
   └─ ユーザー・ロール関連削除
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{操作種別}
    B -->|一覧取得| C[検索条件取得]
    C --> D[データスコープ適用]
    D --> E[ロール一覧取得]
    E --> Z[終了]

    B -->|新規登録| F[入力バリデーション]
    F --> G{バリデーションOK?}
    G -->|No| H[エラー返却]
    H --> Z
    G -->|Yes| I[一意性チェック]
    I --> J{一意?}
    J -->|No| H
    J -->|Yes| K[ロール登録]
    K --> L[メニュー権限登録]
    L --> M[認可キャッシュクリア]
    M --> Z

    B -->|更新| N[権限チェック]
    N --> O{権限OK?}
    O -->|No| H
    O -->|Yes| P[入力バリデーション]
    P --> Q[一意性チェック]
    Q --> R[ロール更新]
    R --> S[メニュー関連再登録]
    S --> T[認可キャッシュクリア]
    T --> Z

    B -->|削除| U[ユーザー割当確認]
    U --> V{割当あり?}
    V -->|Yes| H
    V -->|No| W[権限チェック]
    W --> X[関連削除・論理削除]
    X --> Z

    B -->|データ権限設定| Y[権限チェック]
    Y --> AA[ロール更新]
    AA --> AB[部門関連再登録]
    AB --> Z
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | 管理者ロール操作禁止 | 超級管理員ロール（roleId=1）に対する編集・削除操作は禁止 | ロール更新・削除・ステータス変更時 |
| BR-002 | 割当済みロール削除禁止 | ユーザーに割り当てられているロールは削除できない | ロール削除時 |
| BR-003 | ロール名一意性 | システム内でロール名は一意でなければならない | ロール登録・更新時 |
| BR-004 | 権限文字列一意性 | システム内で権限文字列（roleKey）は一意でなければならない | ロール登録・更新時 |
| BR-005 | データスコープ制限 | ユーザーは自身のデータスコープ内のロールのみ操作可能 | 全操作時（管理者除く） |
| BR-006 | 論理削除 | ロール削除は物理削除ではなく論理削除（del_flag='2'）とする | ロール削除時 |

### データスコープ値

| 値 | 説明 |
|---|------|
| 1 | 所有数据权限（全データ） |
| 2 | 自定义数据权限（カスタム） |
| 3 | 本部门数据权限（自部門のみ） |
| 4 | 本部门及以下数据权限（自部門以下） |
| 5 | 仅本人数据权限（本人のみ） |

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| ロール一覧取得 | sys_role | SELECT | 条件に合致するロール一覧を取得 |
| ロール登録 | sys_role | INSERT | 新規ロール情報を登録 |
| ロール登録 | sys_role_menu | INSERT | ロールとメニューの関連を登録 |
| ロール更新 | sys_role | UPDATE | ロール情報を更新 |
| ロール更新 | sys_role_menu | DELETE/INSERT | ロールとメニューの関連を再登録 |
| ロール削除 | sys_role | UPDATE | del_flagを'2'に更新（論理削除） |
| ロール削除 | sys_role_menu | DELETE | ロールとメニューの関連を削除 |
| ロール削除 | sys_role_dept | DELETE | ロールと部門の関連を削除 |
| データ権限設定 | sys_role | UPDATE | dataScopeを更新 |
| データ権限設定 | sys_role_dept | DELETE/INSERT | ロールと部門の関連を再登録 |
| ユーザー割当 | sys_user_role | INSERT | ユーザーとロールの関連を登録 |
| ユーザー割当解除 | sys_user_role | DELETE | ユーザーとロールの関連を削除 |

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

#### sys_role

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | role_id | 自動採番 | 主キー |
| INSERT | role_name | 入力値 | ロール名 |
| INSERT | role_key | 入力値 | 権限文字列 |
| INSERT | role_sort | 入力値 | 表示順序 |
| INSERT | data_scope | 入力値または'1' | デフォルト全データ |
| INSERT | status | 入力値または'0' | デフォルト正常 |
| INSERT | create_by | ログインユーザー名 | 作成者 |
| INSERT | create_time | sysdate() | 作成日時 |
| UPDATE | del_flag | '2' | 論理削除時 |
| SELECT | del_flag | '0' | 有効データのみ取得 |

#### sys_role_menu

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | role_id | ロールID | 複合主キー |
| INSERT | menu_id | メニューID | 複合主キー |
| DELETE | role_id | 対象ロールID | ロール更新・削除時 |

#### sys_role_dept

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | role_id | ロールID | 複合主キー |
| INSERT | dept_id | 部門ID | 複合主キー |
| DELETE | role_id | 対象ロールID | データ権限更新・ロール削除時 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | バリデーションエラー | 必須項目未入力、形式不正 | エラーメッセージを画面表示 |
| - | 一意性エラー | ロール名/権限文字列が重複 | 「〜已存在」メッセージを表示 |
| - | 権限エラー | 操作対象が管理者ロール、またはデータスコープ外 | 「不允许操作〜」メッセージを表示 |
| - | 割当エラー | 削除対象ロールにユーザーが割当済み | 「〜已分配,不能删除」メッセージを表示 |

### リトライ仕様

特になし。エラー発生時は即座にエラーメッセージを返却する。

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

- ロール登録：sys_role登録、sys_role_menu登録を1トランザクションで実行
- ロール更新：sys_role更新、sys_role_menu削除・再登録を1トランザクションで実行
- ロール削除：sys_role_menu削除、sys_role_dept削除、sys_role論理削除を1トランザクションで実行
- データ権限設定：sys_role更新、sys_role_dept削除・再登録を1トランザクションで実行

## パフォーマンス要件

- ロール一覧取得：ページング処理により1ページあたり適切な件数を取得
- Excelエクスポート：検索条件に合致する全件を出力

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

1. **権限制御**：Apache Shiroによるメソッドレベルの権限チェック
2. **データスコープ**：@DataScopeアノテーションによる行レベルアクセス制御
3. **管理者保護**：超級管理員ロール（roleId=1）への操作制限
4. **監査ログ**：@Logアノテーションによる操作ログ記録
5. **認可キャッシュ管理**：ロール変更時に認可キャッシュをクリアし、即座に反映

## 備考

- ロール削除は論理削除のため、データベース上にはレコードが残存する
- メニュー権限の設定はツリー形式のチェックボックスで選択
- データ権限設定でカスタム（dataScope=2）を選択した場合のみ、部門選択が有効

---

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

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

### 推奨読解順序

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

まず、ロール管理で扱うデータ構造を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | SysRole.java | `ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysRole.java` | ロールエンティティの全フィールド定義、バリデーションアノテーションを確認 |
| 1-2 | SysRoleMenu.java | `ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRoleMenu.java` | ロールとメニューの関連テーブルの構造を確認 |
| 1-3 | SysRoleDept.java | `ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRoleDept.java` | ロールと部門の関連テーブル（データ権限用）の構造を確認 |

**読解のコツ**: `isAdmin()`メソッド（79-87行目）でroleId=1を管理者として判定。`menuIds`と`deptIds`フィールドは関連登録用の一時保持フィールド。

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

処理の起点となるControllerを確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | SysRoleController.java | `ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java` | 各エンドポイントのマッピング、権限アノテーションを確認 |

**主要処理フロー**:
- **49-54行目**: ロール管理画面の表示
- **56-64行目**: ロール一覧取得（`list`メソッド）
- **90-108行目**: 新規登録保存（`addSave`メソッド）- 一意性チェック、登録、認可キャッシュクリア
- **125-144行目**: 更新保存（`editSave`メソッド）- 権限チェック、一意性チェック、更新
- **160-175行目**: データ権限保存（`authDataScopeSave`メソッド）
- **177-184行目**: 削除（`remove`メソッド）
- **232-252行目**: 分配ユーザー一覧取得・割当画面
- **302-313行目**: ユーザー一括割当（`selectAuthUserAll`メソッド）

#### Step 3: ビジネスロジック層を理解する

サービス層の実装を確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | ISysRoleService.java | `ruoyi-system/src/main/java/com/ruoyi/system/service/ISysRoleService.java` | サービスインターフェースで提供されるメソッド一覧を確認 |
| 3-2 | SysRoleServiceImpl.java | `ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java` | ビジネスロジックの実装詳細を確認 |

**主要処理フロー**:
- **54-59行目**: `selectRoleList` - `@DataScope`アノテーションによるデータスコープ適用
- **153-173行目**: `deleteRoleByIds` - 割当チェック、関連削除、論理削除
- **181-188行目**: `insertRole` - ロール登録とメニュー関連登録
- **196-205行目**: `updateRole` - ロール更新とメニュー関連再登録
- **213-223行目**: `authDataScope` - データ権限設定と部門関連登録
- **230-247行目**: `insertRoleMenu` - ロール・メニュー関連の一括登録
- **314-321行目**: `checkRoleAllowed` - 管理者ロール操作禁止チェック
- **328-344行目**: `checkRoleDataScope` - データスコープチェック
- **402-416行目**: `insertAuthUsers` - ユーザー一括割当

#### Step 4: データアクセス層を理解する

Mapper層の定義とSQLを確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | SysRoleMapper.java | `ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMapper.java` | Mapperインターフェースのメソッド定義を確認 |
| 4-2 | SysRoleMenuMapper.java | `ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMenuMapper.java` | ロール・メニュー関連のMapper |
| 4-3 | SysRoleDeptMapper.java | `ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleDeptMapper.java` | ロール・部門関連のMapper |

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

```
SysRoleController
    │
    ├─ list() [ロール一覧取得]
    │      └─ ISysRoleService.selectRoleList()
    │             └─ SysRoleMapper.selectRoleList()
    │
    ├─ addSave() [ロール新規登録]
    │      ├─ ISysRoleService.checkRoleNameUnique()
    │      ├─ ISysRoleService.checkRoleKeyUnique()
    │      ├─ ISysRoleService.insertRole()
    │      │      ├─ SysRoleMapper.insertRole()
    │      │      └─ SysRoleMenuMapper.batchRoleMenu()
    │      └─ AuthorizationUtils.clearAllCachedAuthorizationInfo()
    │
    ├─ editSave() [ロール更新]
    │      ├─ ISysRoleService.checkRoleAllowed()
    │      ├─ ISysRoleService.checkRoleDataScope()
    │      ├─ ISysRoleService.checkRoleNameUnique()
    │      ├─ ISysRoleService.checkRoleKeyUnique()
    │      ├─ ISysRoleService.updateRole()
    │      │      ├─ SysRoleMapper.updateRole()
    │      │      ├─ SysRoleMenuMapper.deleteRoleMenuByRoleId()
    │      │      └─ SysRoleMenuMapper.batchRoleMenu()
    │      └─ AuthorizationUtils.clearAllCachedAuthorizationInfo()
    │
    ├─ remove() [ロール削除]
    │      └─ ISysRoleService.deleteRoleByIds()
    │             ├─ checkRoleAllowed()
    │             ├─ checkRoleDataScope()
    │             ├─ countUserRoleByRoleId()
    │             ├─ SysRoleMenuMapper.deleteRoleMenu()
    │             ├─ SysRoleDeptMapper.deleteRoleDept()
    │             └─ SysRoleMapper.deleteRoleByIds()
    │
    ├─ authDataScopeSave() [データ権限設定]
    │      ├─ ISysRoleService.checkRoleAllowed()
    │      ├─ ISysRoleService.checkRoleDataScope()
    │      └─ ISysRoleService.authDataScope()
    │             ├─ SysRoleMapper.updateRole()
    │             ├─ SysRoleDeptMapper.deleteRoleDeptByRoleId()
    │             └─ SysRoleDeptMapper.batchRoleDept()
    │
    └─ selectAuthUserAll() [ユーザー一括割当]
           ├─ ISysRoleService.checkRoleDataScope()
           └─ ISysRoleService.insertAuthUsers()
                  └─ SysUserRoleMapper.batchUserRole()
```

### データフロー図

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

画面入力 ─────────▶ SysRoleController ────────▶ JSON/画面
                         │
                         ▼
                   ISysRoleService
                         │
         ┌───────────────┼───────────────┐
         ▼               ▼               ▼
   SysRoleMapper   SysRoleMenuMapper   SysRoleDeptMapper
         │               │               │
         ▼               ▼               ▼
      sys_role     sys_role_menu    sys_role_dept
                         │
                         ▼
                   SysUserRoleMapper
                         │
                         ▼
                   sys_user_role
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| SysRoleController.java | `ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java` | Controller | リクエスト受付、レスポンス返却 |
| SysRole.java | `ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysRole.java` | Entity | ロールエンティティ |
| SysRoleMenu.java | `ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRoleMenu.java` | Entity | ロール・メニュー関連エンティティ |
| SysRoleDept.java | `ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRoleDept.java` | Entity | ロール・部門関連エンティティ |
| ISysRoleService.java | `ruoyi-system/src/main/java/com/ruoyi/system/service/ISysRoleService.java` | Interface | サービスインターフェース |
| SysRoleServiceImpl.java | `ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java` | Service | ビジネスロジック実装 |
| SysRoleMapper.java | `ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMapper.java` | Mapper | データアクセスインターフェース |
| SysRoleMenuMapper.java | `ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMenuMapper.java` | Mapper | ロール・メニュー関連データアクセス |
| SysRoleDeptMapper.java | `ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleDeptMapper.java` | Mapper | ロール・部門関連データアクセス |
| SysUserRoleMapper.java | `ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserRoleMapper.java` | Mapper | ユーザー・ロール関連データアクセス |
