# 画面設計書 13-ユーザーパスワードリセット

## 概要

本ドキュメントは、RuoYi後台管理システムにおけるユーザーパスワードリセット画面の設計仕様を定義するものである。

### 本画面の処理概要

ユーザーパスワードリセット画面は、システム管理者が特定のユーザーのパスワードを強制的にリセットするための画面である。ユーザー本人がパスワードを忘れた場合や、セキュリティ上の理由でパスワード変更が必要な場合に管理者が使用する。

**業務上の目的・背景**：ユーザーがパスワードを忘れた場合、自分でパスワードを回復する手段がない場合がある。また、セキュリティインシデント発生時に特定ユーザーのパスワードを強制変更する必要がある。本画面は、管理者がユーザーに代わってパスワードをリセットし、新しいパスワードを設定できる機能を提供する。初期パスワードはシステム設定から取得され、デフォルト値として表示される。

**画面へのアクセス方法**：ユーザー管理一覧画面から対象ユーザーの「パスワードリセット」ボタン（または「更多操作」メニューから選択）をクリックすると、モーダルダイアログ形式でこの画面が表示される。URLパターンは `/system/user/resetPwd/{userId}` で、userIdパスパラメータで対象のユーザーを特定する。

**主要な操作・処理内容**：
1. 画面表示時に対象ユーザーのログイン名と初期パスワードを表示
2. 管理者が新しいパスワードを入力（またはデフォルトの初期パスワードを使用）
3. パスワード表示/非表示の切り替え（マウス押下でパスワード表示）
4. 「確定」ボタンでパスワードリセット処理を実行
5. 成功時はモーダルを閉じて一覧画面に戻る

**画面遷移**：
- 遷移元：ユーザー管理一覧画面（No.9）
- 遷移先：なし（保存後はモーダルを閉じて一覧に戻る）

**権限による表示制御**：本画面へのアクセスには `system:user:resetPwd` 権限が必要。管理者ユーザー（admin）のパスワードリセットは禁止されている。データ権限によって対象ユーザーへのアクセス可否が制御される。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 1 | ユーザー管理 | 主機能 | 管理者によるパスワード強制変更処理 |

## 画面種別

編集（モーダルダイアログ形式・単一機能）

## URL/ルーティング

| メソッド | URL | 説明 |
|---------|-----|------|
| GET | /system/user/resetPwd/{userId} | パスワードリセット画面表示 |
| POST | /system/user/resetPwd | パスワードリセット処理実行 |

## 入出力項目

### 入力項目

| No | 項目名 | 物理名 | 型 | 桁数 | 必須 | 初期値 | バリデーション |
|----|--------|--------|----|----|------|--------|--------------|
| 1 | ユーザーID | userId | hidden | - | ○ | 対象ユーザーID | - |
| 2 | 登録名称 | loginName | text(読取専用) | - | - | 対象ユーザーのログイン名 | 変更不可 |
| 3 | 輸入密碼 | password | password | 20 | ○ | sys.user.initPassword設定値 | 5〜20文字、特殊記号チェック |

## 表示項目

| No | 項目名 | 説明 |
|----|--------|------|
| 1 | 登録名称 | 対象ユーザーのログイン名（読み取り専用） |
| 2 | パスワード表示ボタン | マウス押下中のみパスワードをテキスト表示するアイコンボタン |

## イベント仕様

### 1-画面初期表示

| 項目 | 内容 |
|------|------|
| トリガー | ユーザー管理一覧画面から「パスワードリセット」ボタン押下時 |
| 処理内容 | 1. コントローラーがuserIdパラメータを受け取り、データ権限チェックを実行<br>2. 該当ユーザー情報を取得<br>3. システム設定から初期パスワード（sys.user.initPassword）を取得<br>4. モーダルウィンドウを表示し、ログイン名と初期パスワードを設定 |
| 呼び出しAPI | GET /system/user/resetPwd/{userId} |
| 遷移先 | - |

### 2-パスワード表示ボタン押下（onmousedown）

| 項目 | 内容 |
|------|------|
| トリガー | パスワード入力欄右のキーアイコンをマウスで押下した時 |
| 処理内容 | パスワード入力欄のtype属性を"text"に変更し、入力中のパスワードを可視化 |
| 呼び出しAPI | - |
| 遷移先 | - |

### 3-パスワード表示ボタン離す（onmouseup）

| 項目 | 内容 |
|------|------|
| トリガー | パスワード入力欄右のキーアイコンからマウスを離した時 |
| 処理内容 | パスワード入力欄のtype属性を"password"に戻し、入力中のパスワードを非表示化 |
| 呼び出しAPI | - |
| 遷移先 | - |

### 4-確定ボタン押下（submitHandler）

| 項目 | 内容 |
|------|------|
| トリガー | モーダルダイアログの「確定」ボタン押下時 |
| 処理内容 | 1. フォームバリデーション実行（パスワード必須、5〜20文字、特殊記号チェック）<br>2. バリデーションエラーがあれば処理中断<br>3. フォームデータをシリアライズしてPOST送信<br>4. パスワードを暗号化して更新<br>5. 成功時はモーダルを閉じて一覧を更新 |
| 呼び出しAPI | POST /system/user/resetPwd |
| 遷移先 | ユーザー管理一覧画面（更新後） |

## データベース更新仕様

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 確定ボタン押下 | sys_user | UPDATE | パスワード関連項目の更新 |

### テーブル別更新項目詳細

#### sys_user

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | password | 暗号化されたパスワード | passwordService.encryptPasswordで暗号化 |
| UPDATE | salt | ランダム生成されたソルト値 | ShiroUtils.randomSalt() |
| UPDATE | pwd_update_date | sysdate() | パスワード更新日時 |
| UPDATE | update_time | sysdate() | 更新日時 |

## メッセージ仕様

| No | 種別 | メッセージ | 表示条件 |
|----|------|----------|----------|
| 1 | 成功 | 操作成功 | パスワードリセット成功時 |
| 2 | エラー | 操作失敗 | パスワードリセット失敗時 |
| 3 | バリデーション | 必須入力です | パスワード未入力時 |
| 4 | バリデーション | 5文字以上で入力してください | パスワード5文字未満時 |
| 5 | バリデーション | 20文字以下で入力してください | パスワード20文字超過時 |

## 例外処理

| 例外パターン | 対応処理 |
|------------|---------|
| 管理者パスワードリセット試行 | adminユーザーのパスワードリセットは禁止、エラー返却 |
| データ権限不足 | 対象ユーザーへのデータ権限がない場合、アクセス拒否エラー |
| 対象ユーザー不存在 | 対象のユーザーIDが存在しない場合、エラー画面表示 |
| 通信エラー | Ajax通信失敗時、システムエラーメッセージを表示 |

## 備考

- 初期パスワードはシステム設定（sys_config）の `sys.user.initPassword` キーから取得
- パスワードはMD5+Salt方式で暗号化（passwordService.encryptPassword）
- jQueryValidateのspecialSignルールで特殊記号チェックを実行
- 管理者自身がリセットした場合、現在のセッションのユーザー情報も更新

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | SysUser.java | `ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java` | password, salt, pwdUpdateDateフィールド |

**読解のコツ**: パスワードはpasswordフィールドに暗号化された状態で格納され、saltフィールドと組み合わせて認証に使用される。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | SysUserController.java | `ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java` | resetPwd()とresetPwdSave()メソッド |

**主要処理フロー**:
1. **214-221行目**: `resetPwd()` メソッド - 画面表示、データ権限チェック後ユーザー情報取得
2. **223-242行目**: `resetPwdSave()` メソッド - パスワードリセット処理、暗号化してDB更新

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | SysPasswordService.java | `ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/service/SysPasswordService.java` | encryptPasswordメソッドの暗号化ロジック |
| 3-2 | ISysUserService.java | `ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java` | resetUserPwdメソッドの定義 |

**主要処理フロー**:
- `encryptPassword()`: ログイン名+パスワード+ソルトからMD5ハッシュ生成
- `resetUserPwd()`: sys_userテーブルのパスワード関連フィールドを更新

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | SysUserMapper.xml | `ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml` | resetUserPwd SQLの確認（173-175行目） |

#### Step 5: 画面テンプレートを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | resetPwd.html | `ruoyi-admin/src/main/resources/templates/system/user/resetPwd.html` | フォーム構造、初期パスワード取得、パスワード表示制御 |

**主要処理フロー**:
- **9行目**: hidden項目でuserIdを保持
- **13行目**: loginName表示（readonly）
- **20行目**: `@config.getKey('sys.user.initPassword')` で初期パスワード取得
- **21-23行目**: マウスイベントでパスワード表示/非表示切り替え
- **31-41行目**: jQueryValidateによるバリデーション設定
- **43-47行目**: submitHandler()関数による保存処理

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

```
ユーザー管理一覧画面 [パスワードリセット]ボタン押下
    │
    ├─ SysUserController.resetPwd()           ← GET /system/user/resetPwd/{userId}
    │      ├─ userService.checkUserDataScope()    ← 権限チェック
    │      └─ userService.selectUserById()        ← ユーザー情報取得
    │
    └─ resetPwd.html 表示
           │
           └─ [確定]ボタン押下
                  │
                  ├─ submitHandler() → $.operate.save()
                  │
                  └─ SysUserController.resetPwdSave()  ← POST /system/user/resetPwd
                         ├─ userService.checkUserAllowed()    ← admin保護チェック
                         ├─ userService.checkUserDataScope()  ← 権限チェック
                         ├─ ShiroUtils.randomSalt()           ← ソルト生成
                         ├─ passwordService.encryptPassword() ← パスワード暗号化
                         │
                         └─ userService.resetUserPwd()
                                └─ userMapper.resetUserPwd()  ← DB更新
```

### データフロー図

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

userId (hidden)
loginName (readonly)   SysUserController.resetPwdSave()   sys_user更新
password (入力)   ───▶    │                                ├─ password (暗号化)
                         ├─ ShiroUtils.randomSalt()  ───▶ ├─ salt
                         └─ encryptPassword()             ├─ pwd_update_date
                                                          └─ update_time
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| SysUserController.java | `ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java` | コントローラー | resetPwd(), resetPwdSave()メソッド |
| resetPwd.html | `ruoyi-admin/src/main/resources/templates/system/user/resetPwd.html` | テンプレート | パスワードリセット画面UI |
| SysUser.java | `ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java` | エンティティ | ユーザードメイン |
| SysPasswordService.java | `ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/service/SysPasswordService.java` | サービス | パスワード暗号化処理 |
| ISysUserService.java | `ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java` | インターフェース | サービス定義 |
| SysUserMapper.xml | `ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml` | Mapper | resetUserPwd SQL |
