# 画面設計書 1-ログイン画面

## 概要

本ドキュメントは、Decap CMS のログイン画面（NetlifyAuthenticationPage）の画面設計書である。ユーザーがCMSにアクセスする際の認証フローにおいて、git-gatewayバックエンド設定時に表示される認証画面の仕様を定義する。

### 本画面の処理概要

**業務上の目的・背景**：コンテンツ管理システムへの不正アクセスを防止するため、ユーザー認証を行う画面である。Decap CMSはGitベースのヘッドレスCMSであり、バックエンドのGitリポジトリへの書き込み権限を制御する必要がある。git-gateway設定時には、Netlify Identity経由またはメールアドレス/パスワードによる直接認証の2つの方式をサポートする。

**画面へのアクセス方法**：CMSのURLにアクセスした際、設定ファイル（config.yml）の読み込みが完了し、ユーザーが未認証の場合に自動的に表示される。バックエンド設定が`git-gateway`の場合にこの画面が選択される（App.jsの`authenticating`メソッド、行127）。

**主要な操作・処理内容**：
1. Netlify Identityウィジェットが利用可能な場合、「Login with Netlify Identity」ボタンをクリックしてNetlify Identityのモーダルを開き、認証を行う
2. Netlify Identityウィジェットが利用不可の場合、メールアドレスとパスワードを入力してログインフォームを送信する
3. 認証成功時、`onLogin`コールバックが呼ばれ、Reduxの`loginUser`アクションを経由してバックエンドへの認証が実行される
4. 認証失敗時、エラーメッセージが画面上に表示される

**画面遷移**：
- 遷移元：ローディング画面（設定読み込み完了後、未認証の場合）
- 遷移先：コレクション一覧画面（ログイン成功後）
- 遷移先：ログイン画面（ログイン失敗時、自画面に留まる）

**権限による表示制御**：認証前の画面であるため、権限による表示制御はない。ただし、`window.netlifyIdentity`の有無によってフォーム表示が切り替わる。Netlify Identityウィジェットが存在する場合はボタンのみ、存在しない場合はメール/パスワードフォームが表示される。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 4 | ユーザー認証 | 主機能 | メールアドレスとパスワードによるログイン処理。Netlify Identity経由またはgit-gateway経由での認証実行 |
| 5 | OAuth認証ライブラリ | 補助機能 | Implicit OAuth・Netlify Auth等の認証フローライブラリを利用してバックエンドとの認証処理を実行 |
| 6 | 認証UI | 主機能 | ログインページのUIコンポーネント表示。ログインフォーム（メール・パスワード）またはNetlify Identityボタンの描画 |
| 38 | Git Gatewayバックエンド | API連携 | git-gateway設定時にNetlify Identity経由でGit Gatewayバックエンドへの認証を実行 |

## 画面種別

認証（ログイン）

## URL/ルーティング

- URL変更を伴わない。App.jsの`authenticating`メソッドにより、認証前状態で表示される。
- CMSルートURL（例: `/#/`）にアクセスした際、`user == null`の場合に認証画面が表示される（App.js 行173-174）。

## 入出力項目

### 入力項目（Netlify Identityなしの場合）

| 項目名 | 項目ID | 型 | 必須 | 最大長 | 説明 |
|--------|--------|-----|------|--------|------|
| メールアドレス | email | text | Yes | - | ユーザーのメールアドレス |
| パスワード | password | password | Yes | - | ユーザーのパスワード |

### 入力項目（Netlify Identityありの場合）

- 入力項目なし（Netlify Identityのモーダルウィジェットが認証UIを提供）

## 表示項目

| 項目名 | 表示条件 | 説明 |
|--------|---------|------|
| ロゴ画像 | config.logo_urlまたはconfig.logo.srcが設定されている場合 | カスタムロゴ画像。未設定時はDecap CMSデフォルトロゴ |
| エラーメッセージ（サーバー） | errors.serverが存在する場合 | サーバー認証エラーメッセージ |
| エラーメッセージ（メール） | errors.emailが存在する場合 | メール未入力エラー |
| エラーメッセージ（パスワード） | errors.passwordが存在する場合 | パスワード未入力エラー |
| エラーメッセージ（Identity設定） | errors.identityが存在する場合 | Netlify Identityの設定エラー |
| ログインボタン | 常時 | Netlify Identity時は「Login with Netlify Identity」、フォーム時は「Login」 |
| サイトへ戻るボタン | config.site_urlが設定されている場合 | サイトURLへの戻りリンク |

## イベント仕様

### 1-ログインボタン押下（Netlify Identityあり）

1. `handleIdentity`メソッドが呼ばれる（NetlifyAuthenticationPage.js 行121-128）
2. `window.netlifyIdentity.currentUser()`で既存ユーザーを確認
3. ユーザーが存在する場合: `onLogin(user)`を呼び出し、認証処理を実行
4. ユーザーが存在しない場合: `window.netlifyIdentity.open()`でIdentityモーダルを開く
5. Identityモーダルでログイン成功時: `handleIdentityLogin`イベントハンドラが発火し、`onLogin(user)`を呼び出す
6. `onLogin`はApp.jsの`handleLogin` -> `loginUser`アクション -> バックエンド認証の順に処理される

### 2-ログインフォーム送信（Netlify Identityなし）

1. フォームの`onSubmit`で`handleLogin`メソッドが呼ばれる（NetlifyAuthenticationPage.js 行136-164）
2. クライアント側バリデーション: メール・パスワードの未入力チェック
3. バリデーションエラーがある場合: `this.setState({ errors })`でエラーメッセージを表示し処理終了
4. バリデーション通過後: `NetlifyAuthenticationPage.authClient()`でクライアントを取得
5. `client.login(email, password, true)`で認証を実行
6. 認証成功時: `onLogin(user)`を呼び出し、`loginUser`アクション経由でRedux stateを更新
7. 認証失敗時: `this.setState({ errors: { server: error.description || error.msg || error } })`でサーバーエラーを表示

### 3-コンポーネントマウント時の自動認証

1. `componentDidMount`で既存のNetlify Identityユーザーを確認（行93-96）
2. 既にログイン済みのユーザーが存在する場合、自動的に`onLogin`を呼び出す
3. Identityモーダルを閉じる

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| ログインボタン押下 | Redux State (auth) | UPDATE | AUTH_REQUEST -> AUTH_SUCCESS または AUTH_FAILURE でauth stateを更新 |

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

#### Redux State: auth

| 操作 | 項目（キー） | 更新値・取得条件 | 備考 |
|-----|-------------|-----------------|------|
| UPDATE | isFetching | true -> false | AUTH_REQUEST時にtrue、AUTH_SUCCESS/FAILURE時にfalse |
| UPDATE | user | 認証成功時のユーザーオブジェクト | AUTH_SUCCESS時に設定 |
| UPDATE | error | 認証失敗時のエラーオブジェクト | AUTH_FAILURE時に設定 |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|--------------|---------|
| auth.errors.email | エラー | メールアドレス未入力エラー | メールフィールドが空でフォーム送信時 |
| auth.errors.password | エラー | パスワード未入力エラー | パスワードフィールドが空でフォーム送信時 |
| auth.errors.identitySettings | エラー | Netlify Identity設定エラー | Identityの設定読み込みに失敗した場合 |
| auth.loggingIn | 情報 | ログイン処理中表示 | inProgress=true時のボタンラベル |
| auth.login | 情報 | ログインボタンラベル | inProgress=false時のボタンラベル |
| auth.loginWithNetlifyIdentity | 情報 | Netlify Identityログインボタンラベル | Netlify Identityウィジェット使用時 |
| ui.toast.onFailToAuth | エラー | 認証失敗トースト通知 | loginUserアクションで認証が失敗した場合 |

## 例外処理

| 例外条件 | 処理内容 | 画面表示 |
|---------|---------|---------|
| メール未入力 | stateにエラーを設定 | メールフィールド上部にエラーメッセージ表示 |
| パスワード未入力 | stateにエラーを設定 | パスワードフィールド上部にエラーメッセージ表示 |
| サーバー認証失敗 | stateにサーバーエラーを設定 | フォーム上部にサーバーエラーメッセージ表示 |
| Netlify Identity設定エラー | Identityモーダルを閉じ、エラーリンクを表示 | Netlifyドキュメントへのリンク付きエラーメッセージ |
| authClient未設定 | 例外がcatchされサーバーエラーとして表示 | サーバーエラーメッセージ表示 |

## 備考

- `window.netlifyIdentity`はNetlify Identity Widgetの外部スクリプトにより提供される。スクリプトがHTMLに含まれている場合のみ利用可能。
- `config.logo_url`は非推奨（Deprecated）であり、`config.logo.src`が推奨される。
- `NetlifyAuthenticationPage.authClient`は静的プロパティとしてバックエンドから注入される。
- サイトURLが設定されている場合、「Go back to site」ボタンが表示される（AuthenticationPage.js 行101）。
- React 19の変更に対応し、`componentDidMount`内でPropTypesの手動バリデーションを実施している。

---

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

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

### 推奨読解順序

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

認証に関するRedux stateの構造と、認証アクションの型定義を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | auth.ts | `packages/decap-cms-core/src/actions/auth.ts` | AUTH_REQUEST, AUTH_SUCCESS, AUTH_FAILUREのアクション型定義。loginUser, logoutUser等のアクションクリエーター |
| 1-2 | AuthenticationPage.js | `packages/decap-cms-ui-default/src/AuthenticationPage.js` | 認証ページの共通UIレイアウト。ロゴ、ボタン、エラーメッセージの表示構造 |

**読解のコツ**: TypeScriptのアクション定義（`as const`パターン）はReduxのアクション型を厳密に管理するためのもの。ReturnTypeを使ったユニオン型の定義に注目。

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

App.jsの認証フローの分岐ロジックを把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | App.js | `packages/decap-cms-core/src/components/App/App.js` | renderメソッド（行147-257）の条件分岐。user==null時にauthenticatingメソッドを呼び出す流れ |

**主要処理フロー**:
1. **行161-171**: config.error, config.isFetchingの判定でエラー画面・ローディング画面を表示
2. **行173-174**: user==nullの判定で認証画面を表示
3. **行112-139**: authenticatingメソッドでバックエンドのauthComponentを動的に取得し、認証コンポーネントを描画
4. **行127**: `React.createElement(backend.authComponent(), { onLogin: this.handleLogin.bind(this), ... })` でNetlifyAuthenticationPageを生成

#### Step 3: 認証UIコンポーネントを理解する

NetlifyAuthenticationPageの3つの表示パターンと認証処理を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | NetlifyAuthenticationPage.js | `packages/decap-cms-ui-auth/src/NetlifyAuthenticationPage.js` | renderメソッド（行166-237）の3つの表示パターン分岐。handleLoginメソッド（行136-164）の認証処理フロー |

**主要処理フロー**:
- **行56-66**: モジュールスコープでNetlify Identityイベントリスナーを登録
- **行84-97**: componentDidMountで既存ユーザーの自動ログイン処理
- **行136-164**: handleLoginでクライアント側バリデーション -> authClientによるサーバー認証
- **行166-237**: renderメソッドで3パターン（Identity+エラー / Identity / フォーム）の描画

#### Step 4: 認証アクションの実行フローを理解する

loginUserアクションの非同期処理とエラーハンドリングを把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | auth.ts | `packages/decap-cms-core/src/actions/auth.ts` | loginUser関数（行79-108）。authenticating -> backend.authenticate -> authenticate/authErrorの流れ |

**主要処理フロー**:
- **行79-84**: dispatch(authenticating())で認証中状態に遷移
- **行85-92**: backend.authenticate(credentials)でバックエンド認証を実行
- **行93-106**: エラー時にaddNotification, authErrorをdispatch

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

```
App.js (render)
    |
    +-- authenticating() [行112-139]
    |       |
    |       +-- currentBackend(config)
    |       +-- backend.authComponent() -> NetlifyAuthenticationPage
    |
    +-- NetlifyAuthenticationPage (render) [行166-237]
            |
            +-- [Netlify Identity有] handleIdentity() [行121-128]
            |       |
            |       +-- window.netlifyIdentity.currentUser()
            |       +-- onLogin(user) -> App.handleLogin()
            |       +-- window.netlifyIdentity.open()
            |
            +-- [Netlify Identity無] handleLogin() [行136-164]
                    |
                    +-- クライアント側バリデーション
                    +-- NetlifyAuthenticationPage.authClient()
                    +-- client.login(email, password, true)
                    +-- onLogin(user) -> App.handleLogin()
                            |
                            +-- loginUser(credentials) [auth.ts 行79]
                                    |
                                    +-- dispatch(authenticating())
                                    +-- backend.authenticate(credentials)
                                    +-- dispatch(authenticate(user)) or dispatch(authError(error))
```

### データフロー図

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

メールアドレス      ──▶  NetlifyAuthenticationPage          ──▶  Redux State (auth.user)
パスワード               .handleLogin()                          auth.error
                              |                                  auth.isFetching
                              v
                         authClient.login()
                              |
                              v
                         App.handleLogin()
                              |
                              v
                         loginUser(credentials)
                         [auth.ts]
                              |
                              v
                         backend.authenticate()
                              |
                    +---------+---------+
                    |                   |
                    v                   v
             AUTH_SUCCESS          AUTH_FAILURE
             (user object)         (error + notification)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| NetlifyAuthenticationPage.js | `packages/decap-cms-ui-auth/src/NetlifyAuthenticationPage.js` | ソース | ログイン画面のメインコンポーネント。フォーム表示と認証処理 |
| AuthenticationPage.js | `packages/decap-cms-ui-default/src/AuthenticationPage.js` | ソース | 認証ページの共通UIレイアウトコンポーネント |
| App.js | `packages/decap-cms-core/src/components/App/App.js` | ソース | アプリケーションルート。認証状態に応じた画面切り替え |
| auth.ts | `packages/decap-cms-core/src/actions/auth.ts` | ソース | 認証関連のReduxアクションクリエーター |
| index.js | `packages/decap-cms-ui-auth/src/index.js` | ソース | 認証UIパッケージのエクスポート定義 |
| GoBackButton.js | `packages/decap-cms-ui-default/src/GoBackButton.js` | ソース | 「Go back to site」ボタンコンポーネント |
