# 機能設計書 17-ユーザー新規作成

## 概要

本ドキュメントは、LEGACY CMSにおける新規ユーザーアカウントの作成機能について記述する。この機能は管理画面のAjaxダイアログを通じて、管理者が新しいユーザーアカウントを作成し、自動生成されたパスワードを含むアカウント情報をメールで送信する。

### 本機能の処理概要

**業務上の目的・背景**：システム管理者が新しいユーザーを追加する際、必要最小限の情報（メールアドレス、エイリアス、氏名、国、ロール）を入力することでアカウントを作成できる。パスワードは自動生成され、ユーザーにメールで通知される。

**機能の利用シーン**：管理者がユーザー管理画面で「New User」ボタンをクリックした際にダイアログが表示され、必要情報を入力して作成を実行する。

**主要な処理内容**：
1. ユーザーの権限チェック（uusers + unewuser権限の確認）
2. Ajaxダイアログでのフォーム表示（GETリクエスト時）
3. POSTリクエスト時のバリデーション
4. パスワードの自動生成
5. usersテーブルとusers_profilesテーブルへのINSERT
6. アカウント情報をメールで送信

**関連システム・外部連携**：
- Zend_Mail：アカウント情報のメール送信

**権限による制御**：`uusers`および`unewuser`リソースへのアクセス権限が必要。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 43 | ユーザー新規作成画面 | 主画面 | 新規ユーザー作成ダイアログ |
| 41 | ユーザー管理画面 | 呼び出し元画面 | New Userボタンからダイアログ呼び出し |
| 7 | ユーザー登録画面 | 参照画面 | フロントエンドでの自己登録 |

## 機能種別

CRUD操作（Create）/ データ新規作成 / メール送信 / Ajaxダイアログ

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| email | string | Yes | メールアドレス | NotEmpty, EmailAddress, 重複チェック |
| alias | string | Yes | ユーザーエイリアス | NotEmpty, Alnum(スペース許可), 重複チェック |
| first | string | Yes | 名 | NotEmpty, 正規表現(/^[a-zA-Z-' ]*$/) |
| last | string | Yes | 姓 | NotEmpty, 正規表現(/^[a-zA-Z-' ]*$/) |
| country | string | Yes | 国コード | NotEmpty |
| role | integer | Yes | ロールID | NotEmpty, Digits |

### 入力データソース

- POSTリクエストボディ（フォームデータ）
- セッション（ログインユーザー情報、ACL情報）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| posted | string | フォーム投稿状態（'N'=未投稿/バリデーションエラー） |
| messages | array | バリデーションエラーメッセージ |
| alias, email, first, last, country, role | string/int | 入力値（エラー時の再表示用） |

### 作成されるユーザーデータ

#### usersテーブル

| 項目名 | 型 | 説明 |
|--------|-----|------|
| user_alias | string | 入力されたエイリアス |
| user_email | string | 入力されたメールアドレス |
| user_role | integer | 入力されたロールID |
| user_password | string | MD5ハッシュ化されたパスワード |
| user_key | string | MD5(email + password) |
| user_date | datetime | 作成日時（NOW()） |
| user_mailformat | string | デフォルト'text' |
| user_status | string | デフォルト'active' |

#### users_profilesテーブル

| 項目名 | 型 | 説明 |
|--------|-----|------|
| upro_userid | integer | 作成されたユーザーID |
| upro_first | string | 入力された名 |
| upro_last | string | 入力された姓 |
| upro_country | string | 入力された国コード |
| upro_date | datetime | 作成日時（NOW()） |

### 出力先

- Ajaxダイアログ内のHTML
- usersテーブルへの新規レコード挿入
- users_profilesテーブルへの新規レコード挿入
- メール送信

## 処理フロー

### 処理シーケンス

```
1. newAction()が呼び出される（Ajaxダイアログ経由）
   └─ レイアウト無効化

2. 権限チェック
   ├─ uusers権限チェック
   └─ unewuser権限チェック
      ├─ 権限なし → privileges画面へフォワード
      └─ 権限あり → 次のステップへ

3. リクエスト種別の判定
   ├─ GETリクエスト → フォーム表示（posted='N'）
   └─ POSTリクエスト → バリデーション処理へ

4. バリデーション処理（POSTの場合）
   └─ Zend_Filter_Inputによる入力検証
      ├─ email: NotEmpty, EmailAddress, DB重複チェック
      ├─ alias: NotEmpty, Alnum, DB重複チェック
      ├─ first: NotEmpty, 正規表現
      ├─ last: NotEmpty, 正規表現
      ├─ country: NotEmpty
      └─ role: NotEmpty, Digits

5. パスワード生成
   └─ createRandomPassword()で8文字のランダムパスワード生成

6. ユーザー作成処理
   ├─ usersテーブルへINSERT
   ├─ lastInsertId()でユーザーID取得
   └─ users_profilesテーブルへINSERT

7. メール送信
   └─ Zend_Mailでアカウント情報（email, password）を送信

8. 結果表示
   └─ 成功メッセージとCloseボタン表示
```

### フローチャート

```mermaid
flowchart TD
    A[開始: newAction] --> B[レイアウト無効化]
    B --> C{uusers+unewuser権限あり?}
    C -->|No| D[privileges画面へフォワード]
    C -->|Yes| E{POSTリクエスト?}
    E -->|No| F[フォーム表示 posted=N]
    E -->|Yes| G[パスワード自動生成]
    G --> H[Zend_Filter_Inputでバリデーション]
    H --> I{バリデーション成功?}
    I -->|No| J[エラーメッセージ設定]
    J --> F
    I -->|Yes| K[usersテーブルINSERT]
    K --> L[lastInsertId取得]
    L --> M[users_profilesテーブルINSERT]
    M --> N[Zend_Mailでアカウント情報送信]
    N --> O[成功メッセージ+Closeボタン表示]
    O --> P[終了]
    F --> P
    D --> P
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 初期ステータス | 新規作成時はactive状態で作成 | 常時 |
| BR-02 | パスワード自動生成 | 8文字のランダムパスワードを自動生成 | 常時 |
| BR-03 | メール通知 | アカウント情報をメールでユーザーに通知 | 常時 |
| BR-04 | メールアドレス一意性 | メールアドレスは他ユーザーと重複不可 | 常時 |
| BR-05 | エイリアス一意性 | エイリアスは他ユーザーと重複不可 | 常時 |
| BR-06 | メール形式 | デフォルトのメール形式は'text' | 常時 |

### 計算ロジック

パスワード生成：`createRandomPassword()`で英数字8文字のランダム文字列を生成
ユーザーキー生成：`md5(email + password)`

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| ユーザー作成 | users | INSERT | ユーザーアカウント情報挿入 |
| プロフィール作成 | users_profiles | INSERT | ユーザープロフィール情報挿入 |

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

#### usersテーブル

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | user_alias | 入力値 | 重複チェック済み |
| INSERT | user_email | 入力値（小文字変換） | 重複チェック済み |
| INSERT | user_role | 入力値 | |
| INSERT | user_password | md5(password) | 自動生成パスワードをハッシュ化 |
| INSERT | user_key | md5(email+password) | |
| INSERT | user_date | NOW() | |
| INSERT | user_mailformat | 'text' | デフォルト値 |
| INSERT | user_status | 'active' | デフォルト値 |

#### users_profilesテーブル

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | upro_userid | lastInsertId() | usersのAUTO_INCREMENT値 |
| INSERT | upro_first | 入力値 | |
| INSERT | upro_last | 入力値 | |
| INSERT | upro_country | 入力値 | |
| INSERT | upro_date | NOW() | |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 権限エラー | uusers/unewuser権限なし | privileges画面へフォワード |
| IS_EMPTY | バリデーションエラー | 必須項目が空 | 該当項目のエラーメッセージ表示 |
| INVALID | バリデーションエラー | メールアドレス形式不正 | "Invalid E-mail Address"メッセージ |
| ERROR_RECORD_FOUND | バリデーションエラー | メールアドレス重複 | "Invalid E-mail Address - e-mail address in use"メッセージ |
| NOT_ALNUM | バリデーションエラー | エイリアスに不正文字 | "Invalid Alias"メッセージ |
| ERROR_RECORD_FOUND | バリデーションエラー | エイリアス重複 | "Invalid Alias - alias in use"メッセージ |
| NOT_MATCH | バリデーションエラー | 名/姓に不正文字 | "Invalid First/Last Name"メッセージ |
| NOT_DIGITS | バリデーションエラー | ロールが数値でない | "Invalid Role"メッセージ |

### リトライ仕様

特になし（ユーザーがフォームを修正して再送信）

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

usersとusers_profilesへの2回のINSERT操作が行われるが、明示的なトランザクション管理は行っていない。メール送信失敗時もDBへの挿入はロールバックされない。

## パフォーマンス要件

- 2回のINSERT操作
- メール送信（外部SMTPサーバーとの通信）

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

- ACLによる権限チェック（uusers + unewuserリソース）
- Zend_Filter_Inputによる入力バリデーション
- メールアドレス・エイリアスの重複チェック
- パスワードはMD5でハッシュ化して保存（注：MD5は現在推奨されない）
- メールでパスワードを平文送信（セキュリティ上の懸念点）

## 備考

- パスワードハッシュにMD5を使用（現在のセキュリティ基準では推奨されない）
- ソルトなしのMD5ハッシュ（脆弱性あり）
- パスワードを平文でメール送信（セキュリティリスク）
- Dojo Toolkitのダイアログウィジェット使用
- countriesOptionsヘルパーで国選択肢を生成

---

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

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

### 推奨読解順序

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

ユーザー関連テーブルの構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | database.sql | `database.sql` | usersテーブル（347-361行目）、users_profiles（457-477行目） |

**読解のコツ**: usersテーブルには認証情報、users_profilesには個人情報が格納される。upro_useridがusersのuser_idと対応。

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

コントローラーのnewActionを確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | UsersController.php | `application/modules/admin/controllers/UsersController.php` | newAction（590-746行目） |

**主要処理フロー**:
1. **592行目**: uusers + unewuser権限の複合チェック
2. **594行目**: レイアウト無効化
3. **599行目**: POSTリクエスト判定
4. **601行目**: createRandomPassword()でパスワード生成
5. **605-651行目**: バリデータ定義
6. **656行目**: バリデーション成功判定
7. **663-672行目**: usersテーブルへINSERT
8. **677行目**: lastInsertId()取得
9. **680-686行目**: users_profilesテーブルへINSERT
10. **691-705行目**: Zend_Mailでアカウント情報送信

#### Step 3: パスワード生成を理解する

ランダムパスワード生成メソッドを確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | UsersController.php | `application/modules/admin/controllers/UsersController.php` | generatePassword()（44-59行目） |

**主要処理フロー**:
- **46行目**: 使用可能文字セット定義
- **47-56行目**: 8文字のランダム文字列生成

#### Step 4: ビューテンプレートを理解する

新規作成フォームのUIを確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | new.phtml | `application/modules/admin/views/scripts/users/new.phtml` | 新規作成フォームテンプレート |

**主要処理フロー**:
- **9行目**: posted='N'の場合のみフォーム表示
- **10行目**: エラーメッセージレンダリング
- **14-26行目**: メールアドレス入力（regExp検証付き）
- **29-43行目**: エイリアス入力
- **46-61行目**: 名入力
- **63-78行目**: 姓入力
- **80-93行目**: 国選択（countriesOptionsヘルパー）
- **95-105行目**: ロール選択（URoleSelectヘルパー）

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

```
manage.phtml [New Userボタンクリック]
    │
    └─ getDialog('/admin/users/new/','New User')
           │
           └─ UsersController::newAction()
                  │
                  ├─ ACL::isAllowed() [権限チェック x2]
                  │
                  ├─ [GETの場合] new.phtml表示
                  │
                  └─ [POSTの場合]
                         │
                         ├─ generatePassword() [パスワード生成]
                         │
                         ├─ Zend_Filter_Input [バリデーション]
                         │
                         ├─ Zend_Db::insert('users') [ユーザー挿入]
                         │
                         ├─ lastInsertId() [ID取得]
                         │
                         ├─ Zend_Db::insert('users_profiles') [プロフィール挿入]
                         │
                         └─ Zend_Mail::send() [アカウント情報メール送信]
```

### データフロー図

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

ダイアログ表示要求 ───▶ newAction (GET)          ───▶ new.phtml
                         └─ レイアウト無効化             └─ フォーム表示

                                    │
                                    ▼

フォーム送信         ───▶ newAction (POST)        ───▶
(email,alias,             ├─ 権限チェック               ├─ [成功]
 first,last,              ├─ generatePassword()              ├─ 成功メッセージ
 country,role)            ├─ バリデーション                   └─ Closeボタン
                          ├─ usersテーブルINSERT         │
                          ├─ users_profilesINSERT       └─ [失敗] フォーム再表示
                          └─ Zend_Mail送信                     + エラーメッセージ
                                    │
                                    ▼
                          メール送信
                          To: 入力されたメールアドレス
                          内容: email + password
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| UsersController.php | `application/modules/admin/controllers/UsersController.php` | コントローラー | newActionの実装 |
| new.phtml | `application/modules/admin/views/scripts/users/new.phtml` | ビュー | 新規作成フォーム |
| manage.phtml | `application/modules/admin/views/scripts/users/manage.phtml` | ビュー | New Userボタン配置 |
| CountriesOptions.php | `application/modules/admin/views/helpers/CountriesOptions.php` | ヘルパー | 国選択肢生成 |
| URoleSelect.php | `application/modules/admin/views/helpers/URoleSelect.php` | ヘルパー | ロール選択肢生成 |
| common.js | `public/_scripts/admin/common.js` | JavaScript | getDialog(), doDialog()関数 |
| database.sql | `database.sql` | スキーマ | users, users_profilesテーブル定義 |
