# 機能設計書 1-ユーザー管理

## 概要

本ドキュメントは、RuoYiシステムにおけるユーザー管理機能の設計仕様を記載する。ユーザー管理機能は、システム内のユーザーアカウントのライフサイクル全般を管理する中核機能である。

### 本機能の処理概要

ユーザー管理機能は、システム管理者がユーザーアカウントの作成・変更・削除・照会を行うための包括的な機能を提供する。また、ユーザーへのロール割当、役職割当、パスワード管理、ステータス管理、データのインポート・エクスポート機能も含まれる。

**業務上の目的・背景**：企業・組織において、システム利用者の認証・認可を適切に管理することは、情報セキュリティの基盤となる。本機能により、管理者は組織内のユーザーアカウントを一元管理し、適切なアクセス権限を付与することで、セキュリティポリシーの遵守と業務効率の向上を実現する。

**機能の利用シーン**：
- 新入社員のシステムアカウント作成時
- 人事異動に伴う部門・役職変更時
- 退職者のアカウント無効化時
- パスワード忘れによるリセット対応時
- 大量ユーザーの一括登録・更新時（Excel入出力）
- ユーザー情報の棚卸・監査時

**主要な処理内容**：
1. ユーザー一覧の検索・表示（部門ツリーによるフィルタリング含む）
2. ユーザーの新規登録（ロール・役職の同時割当）
3. ユーザー情報の編集・更新
4. ユーザーの論理削除
5. パスワードリセット
6. ユーザーへのロール割当・解除
7. ユーザーステータス（有効/無効）の変更
8. Excelファイルによるユーザーデータのインポート・エクスポート
9. ユーザー詳細情報の表示

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

**権限による制御**：
- `system:user:view` - ユーザー一覧画面の表示権限
- `system:user:list` - ユーザー一覧の取得権限
- `system:user:add` - ユーザー新規登録権限
- `system:user:edit` - ユーザー編集権限
- `system:user:remove` - ユーザー削除権限
- `system:user:export` - ユーザーデータエクスポート権限
- `system:user:import` - ユーザーデータインポート権限
- `system:user:resetPwd` - パスワードリセット権限

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 9 | ユーザー管理一覧 | 主画面 | ユーザー一覧の検索、表示、ステータス変更処理 |
| 10 | ユーザー新規登録 | 主画面 | 新規ユーザー情報入力と登録保存処理 |
| 11 | ユーザー編集 | 主画面 | ユーザー情報の更新保存処理 |
| 12 | ユーザー詳細表示 | 主画面 | ユーザー情報の詳細表示処理 |
| 13 | ユーザーパスワードリセット | 主画面 | 管理者によるパスワード強制変更処理 |
| 14 | ユーザーロール割当 | 主画面 | ユーザーへのロール割当・解除処理 |
| 15 | 部門ツリー選択 | 補助画面 | 部門ツリー表示と選択処理 |

## 機能種別

CRUD操作 / データ連携（Excel入出力） / バリデーション

## 入力仕様

### 入力パラメータ

#### ユーザー検索条件

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| userId | Long | No | ユーザーID | 数値 |
| loginName | String | No | ログイン名（部分一致） | 最大30文字 |
| status | String | No | ステータス | 0:正常, 1:停用 |
| phonenumber | String | No | 電話番号（部分一致） | 最大11文字 |
| deptId | Long | No | 部門ID | 数値 |
| beginTime | String | No | 作成日（開始） | 日付形式 |
| endTime | String | No | 作成日（終了） | 日付形式 |

#### ユーザー登録・更新

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| userId | Long | 更新時必須 | ユーザーID | 数値 |
| deptId | Long | No | 部門ID | 数値 |
| loginName | String | Yes | ログイン名 | 必須、最大30文字、XSS防止、一意性チェック |
| userName | String | No | ユーザー名 | 最大30文字、XSS防止 |
| email | String | No | メールアドレス | メール形式、最大50文字、一意性チェック |
| phonenumber | String | No | 電話番号 | 最大11文字、一意性チェック |
| sex | String | No | 性別 | 0:男, 1:女, 2:未知 |
| password | String | 新規時必須 | パスワード | - |
| status | String | No | ステータス | 0:正常, 1:停用 |
| remark | String | No | 備考 | - |
| roleIds | Long[] | No | ロールID配列 | - |
| postIds | Long[] | No | 役職ID配列 | - |

### 入力データソース

- 画面入力：管理者による直接入力
- Excelファイル：一括インポート時のデータソース

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| userId | Long | ユーザーID |
| deptId | Long | 部門ID |
| loginName | String | ログイン名 |
| userName | String | ユーザー名 |
| email | String | メールアドレス |
| phonenumber | String | 電話番号 |
| sex | String | 性別 |
| avatar | String | アバター画像パス |
| status | String | ステータス |
| loginIp | String | 最終ログインIP |
| loginDate | Date | 最終ログイン日時 |
| createTime | Date | 作成日時 |
| dept | SysDept | 所属部門情報 |
| roles | List&lt;SysRole&gt; | 割当ロール一覧 |

### 出力先

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

## 処理フロー

### 処理シーケンス

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

2. ユーザー新規登録
   └─ 入力バリデーション
   └─ ログイン名・電話番号・メールの一意性チェック
   └─ パスワード暗号化（MD5 + Salt）
   └─ ユーザー情報登録
   └─ ユーザー・役職関連登録
   └─ ユーザー・ロール関連登録

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

4. ユーザー削除
   └─ 自分自身削除不可チェック
   └─ 操作対象ユーザーの権限チェック
   └─ データスコープチェック
   └─ ユーザー・ロール関連削除
   └─ ユーザー・役職関連削除
   └─ ユーザー論理削除（del_flag='2'）

5. パスワードリセット
   └─ 操作対象ユーザーの権限チェック
   └─ データスコープチェック
   └─ 新パスワード暗号化
   └─ パスワード更新

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
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | 管理者操作禁止 | 超級管理員（userId=1）に対する編集・削除操作は禁止 | ユーザー更新・削除・ステータス変更時 |
| BR-002 | 自己削除禁止 | ログインユーザー自身を削除することはできない | ユーザー削除時 |
| BR-003 | ログイン名一意性 | システム内でログイン名は一意でなければならない | ユーザー登録・更新時 |
| BR-004 | 電話番号一意性 | システム内で電話番号は一意でなければならない | ユーザー登録・更新時（入力がある場合） |
| BR-005 | メールアドレス一意性 | システム内でメールアドレスは一意でなければならない | ユーザー登録・更新時（入力がある場合） |
| BR-006 | データスコープ制限 | ユーザーは自身のデータスコープ内のユーザーのみ操作可能 | 全操作時（管理者除く） |
| BR-007 | 論理削除 | ユーザー削除は物理削除ではなく論理削除（del_flag='2'）とする | ユーザー削除時 |
| BR-008 | パスワード暗号化 | パスワードはMD5+Saltで暗号化して保存 | ユーザー登録・パスワードリセット時 |

### 計算ロジック

**パスワード暗号化**：
```
暗号化パスワード = MD5(loginName + password + salt)
```

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| ユーザー一覧取得 | sys_user, sys_dept | SELECT | 条件に合致するユーザー一覧を取得 |
| ユーザー登録 | sys_user | INSERT | 新規ユーザー情報を登録 |
| ユーザー登録 | sys_user_role | INSERT | ユーザーとロールの関連を登録 |
| ユーザー登録 | sys_user_post | INSERT | ユーザーと役職の関連を登録 |
| ユーザー更新 | sys_user | UPDATE | ユーザー情報を更新 |
| ユーザー更新 | sys_user_role | DELETE/INSERT | ユーザーとロールの関連を再登録 |
| ユーザー更新 | sys_user_post | DELETE/INSERT | ユーザーと役職の関連を再登録 |
| ユーザー削除 | sys_user | UPDATE | del_flagを'2'に更新（論理削除） |
| ユーザー削除 | sys_user_role | DELETE | ユーザーとロールの関連を削除 |
| ユーザー削除 | sys_user_post | DELETE | ユーザーと役職の関連を削除 |
| パスワードリセット | sys_user | UPDATE | password, salt, pwd_update_dateを更新 |
| ステータス変更 | sys_user | UPDATE | statusを更新 |

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

#### sys_user

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | user_id | 自動採番 | 主キー |
| INSERT | dept_id | 入力値 | 部門ID |
| INSERT | login_name | 入力値 | ログイン名 |
| INSERT | user_name | 入力値 | ユーザー名 |
| INSERT | password | 暗号化済みパスワード | MD5+Salt |
| INSERT | salt | ランダム生成 | 暗号化用Salt |
| INSERT | status | 入力値または'0' | デフォルト正常 |
| INSERT | create_by | ログインユーザー名 | 作成者 |
| INSERT | create_time | sysdate() | 作成日時 |
| UPDATE | del_flag | '2' | 論理削除時 |
| SELECT | del_flag | '0' | 有効データのみ取得 |

#### sys_user_role

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

#### sys_user_post

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | user_id | ユーザーID | 複合主キー |
| INSERT | post_id | 役職ID | 複合主キー |
| DELETE | user_id | 対象ユーザーID | ユーザー更新・削除時 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | バリデーションエラー | 必須項目未入力、形式不正 | エラーメッセージを画面表示 |
| - | 一意性エラー | ログイン名/電話番号/メールが重複 | 「〜已存在」メッセージを表示 |
| - | 権限エラー | 操作対象が管理者、またはデータスコープ外 | 「不允许操作〜」メッセージを表示 |
| - | 自己削除エラー | 自分自身を削除しようとした | 「当前用户不能删除」メッセージを表示 |
| - | インポートエラー | Excelデータ形式不正 | 件数と詳細エラーを表示 |

### リトライ仕様

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

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

- ユーザー登録：sys_user登録、sys_user_role登録、sys_user_post登録を1トランザクションで実行
- ユーザー更新：関連削除、sys_user更新、関連再登録を1トランザクションで実行
- ユーザー削除：関連削除、sys_user論理削除を1トランザクションで実行
- Excelインポート：1ユーザーずつ個別トランザクション（一部失敗しても他は継続）

## パフォーマンス要件

- ユーザー一覧取得：ページング処理により1ページあたり最大100件
- Excelエクスポート：検索条件に合致する全件を出力
- Excelインポート：1ファイルあたりの件数制限は設けていない

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

1. **パスワード保護**：パスワードはMD5+Saltで暗号化し、JSONレスポンスからは除外（@JsonIgnore）
2. **XSS対策**：ログイン名、ユーザー名に対してXSSフィルタリングを実施
3. **権限制御**：Apache Shiroによるメソッドレベルの権限チェック
4. **データスコープ**：@DataScopeアノテーションによる行レベルアクセス制御
5. **管理者保護**：超級管理員（userId=1）への操作制限
6. **監査ログ**：@Logアノテーションによる操作ログ記録

## 備考

- ユーザー削除は論理削除のため、データベース上にはレコードが残存する
- 部門ツリーでのフィルタリングは、選択した部門およびその配下の部門に所属するユーザーを表示
- Excelインポート時のデフォルトパスワードはシステム設定（sys.user.initPassword）から取得

---

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

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

### 推奨読解順序

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

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | SysUser.java | `ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java` | ユーザーエンティティの全フィールド定義、バリデーションアノテーション、Excel出力設定を確認 |
| 1-2 | SysUserRole.java | `ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserRole.java` | ユーザーとロールの関連テーブルの構造を確認 |
| 1-3 | SysUserPost.java | `ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserPost.java` | ユーザーと役職の関連テーブルの構造を確認 |

**読解のコツ**: `@Excel`アノテーションはExcel出力時のカラム設定、`@NotBlank`/`@Size`等はバリデーション設定。`@JsonIgnore`が付いたフィールド（password, salt）はAPIレスポンスから除外される。

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

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

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

**主要処理フロー**:
- **64-69行目**: ユーザー管理画面の表示（`@GetMapping`）
- **71-79行目**: ユーザー一覧取得（`list`メソッド）- ページング開始、サービス呼び出し
- **116-123行目**: 新規登録画面表示 - ロール一覧と役職一覧を取得してビューに渡す
- **128-153行目**: 新規登録保存（`addSave`メソッド）- バリデーション、一意性チェック、パスワード暗号化、登録
- **187-212行目**: 更新保存（`editSave`メソッド）- 権限チェック、バリデーション、更新、認可キャッシュクリア
- **276-287行目**: 削除（`remove`メソッド）- 自己削除チェック、サービス呼び出し

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

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

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

**主要処理フロー**:
- **80-85行目**: `selectUserList` - `@DataScope`アノテーションによるデータスコープ適用
- **180-188行目**: `deleteUserById` - トランザクション処理、関連削除後にユーザー削除
- **219-230行目**: `insertUser` - ユーザー登録、役職関連登録、ロール関連登録をトランザクション内で実行
- **251-265行目**: `updateUser` - 既存関連の削除と再登録
- **336-354行目**: `insertUserRole` - ユーザー・ロール関連の一括登録
- **441-448行目**: `checkUserAllowed` - 管理者操作禁止チェック
- **455-468行目**: `checkUserDataScope` - データスコープチェック

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

Mapper層の定義とSQLを確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | SysUserMapper.java | `ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java` | Mapperインターフェースのメソッド定義を確認 |
| 4-2 | SysUserMapper.xml | `ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml` | 実際のSQL文を確認 |

**主要処理フロー**:
- **52-60行目（XML）**: `selectUserVo` - ユーザー取得の基本SQL（sys_user, sys_dept, sys_roleのJOIN）
- **62-89行目（XML）**: `selectUserList` - 検索条件の動的SQL、データスコープ（`${params.dataScope}`）の埋め込み
- **158-160行目（XML）**: `deleteUserById` - 論理削除（`del_flag = '2'`に更新）
- **208-244行目（XML）**: `insertUser` - 動的INSERT文

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

```
SysUserController
    │
    ├─ list() [ユーザー一覧取得]
    │      └─ ISysUserService.selectUserList()
    │             └─ SysUserMapper.selectUserList()
    │
    ├─ addSave() [ユーザー新規登録]
    │      ├─ ISysDeptService.checkDeptDataScope()
    │      ├─ ISysRoleService.checkRoleDataScope()
    │      ├─ ISysUserService.checkLoginNameUnique()
    │      ├─ ISysUserService.checkPhoneUnique()
    │      ├─ ISysUserService.checkEmailUnique()
    │      ├─ SysPasswordService.encryptPassword()
    │      └─ ISysUserService.insertUser()
    │             ├─ SysUserMapper.insertUser()
    │             ├─ SysUserPostMapper.batchUserPost()
    │             └─ SysUserRoleMapper.batchUserRole()
    │
    ├─ editSave() [ユーザー更新]
    │      ├─ ISysUserService.checkUserAllowed()
    │      ├─ ISysUserService.checkUserDataScope()
    │      ├─ ISysDeptService.checkDeptDataScope()
    │      ├─ ISysRoleService.checkRoleDataScope()
    │      ├─ ISysUserService.updateUser()
    │      │      ├─ SysUserRoleMapper.deleteUserRoleByUserId()
    │      │      ├─ SysUserRoleMapper.batchUserRole()
    │      │      ├─ SysUserPostMapper.deleteUserPostByUserId()
    │      │      ├─ SysUserPostMapper.batchUserPost()
    │      │      └─ SysUserMapper.updateUser()
    │      └─ AuthorizationUtils.clearAllCachedAuthorizationInfo()
    │
    └─ remove() [ユーザー削除]
           └─ ISysUserService.deleteUserByIds()
                  ├─ checkUserAllowed()
                  ├─ checkUserDataScope()
                  ├─ SysUserRoleMapper.deleteUserRole()
                  ├─ SysUserPostMapper.deleteUserPost()
                  └─ SysUserMapper.deleteUserByIds()
```

### データフロー図

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

画面入力 ─────────▶ SysUserController ────────▶ JSON/画面
                         │
                         ▼
                   ISysUserService
                         │
         ┌───────────────┼───────────────┐
         ▼               ▼               ▼
   SysUserMapper   SysUserRoleMapper   SysUserPostMapper
         │               │               │
         ▼               ▼               ▼
      sys_user     sys_user_role    sys_user_post
                         │
                         ▼
                      sys_dept（JOIN）
                      sys_role（JOIN）
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| SysUserController.java | `ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java` | Controller | リクエスト受付、レスポンス返却 |
| SysUser.java | `ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java` | Entity | ユーザーエンティティ |
| SysUserRole.java | `ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserRole.java` | Entity | ユーザー・ロール関連エンティティ |
| SysUserPost.java | `ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserPost.java` | Entity | ユーザー・役職関連エンティティ |
| ISysUserService.java | `ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java` | Interface | サービスインターフェース |
| SysUserServiceImpl.java | `ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java` | Service | ビジネスロジック実装 |
| SysUserMapper.java | `ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java` | Mapper | データアクセスインターフェース |
| SysUserMapper.xml | `ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml` | XML | SQL定義 |
| SysUserRoleMapper.java | `ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserRoleMapper.java` | Mapper | ユーザー・ロール関連データアクセス |
| SysUserPostMapper.java | `ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserPostMapper.java` | Mapper | ユーザー・役職関連データアクセス |
| SysPasswordService.java | `ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/service/SysPasswordService.java` | Service | パスワード暗号化サービス |
| BaseController.java | `ruoyi-common/src/main/java/com/ruoyi/common/core/controller/BaseController.java` | Controller | コントローラー基底クラス |
