# 機能設計書 42-セッション作成

## 概要

本ドキュメントは、Etherpadにおけるセッション作成機能の詳細設計を記載したものである。この機能は、著者とグループ間のセッションを作成し、グループパッドへのアクセス制御を実現するAPI機能を提供する。

### 本機能の処理概要

**業務上の目的・背景**：
Etherpadでは、グループパッド（非公開パッド）へのアクセスを制御するためにセッション機構を使用する。セッションは著者（ユーザー）とグループを紐付け、有効期限を設定することで、時限付きのアクセス権を付与できる。これにより、外部認証システムとの連携や、一時的なアクセス権の付与が可能となる。

**機能の利用シーン**：
- 外部認証システムと連携してユーザーにグループパッドへのアクセス権を付与する場合
- 一時的なゲストアクセスを許可する場合
- SSO（シングルサインオン）環境でEtherpadを使用する場合
- 有効期限付きの共有リンクを発行する場合

**主要な処理内容**：
1. グループIDとauthorIDの存在確認
2. 有効期限（validUntil）のバリデーション
3. ユニークなセッションIDの生成
4. セッション情報のデータベース登録
5. グループ・著者とセッションの関連付け更新

**関連システム・外部連携**：
- ueberDB2データベースによるデータ永続化
- 外部認証システム（OAuth2等）との連携時に使用
- クライアントのセッションCookie管理と連携

**権限による制御**：
- APIキーまたはOAuth2トークンによる認証が必要
- 管理者権限での操作を想定

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 本機能は直接的な画面連携はなく、APIとして提供される |

## 機能種別

CRUD操作（CREATE）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| groupID | string | Yes | グループID（形式: g.XXXXXXXXXXXXXXXX） | グループが存在すること |
| authorID | string | Yes | 著者ID（形式: a.XXXXXXXXXXXXXXXX） | 著者が存在すること |
| validUntil | number | Yes | セッションの有効期限（UNIXタイムスタンプ・秒） | 正の整数、未来の日時 |

### 入力データソース

- REST API: `POST /api/2/sessions`
- リクエストボディ（JSON形式）でパラメータを受け取る

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| code | number | 処理結果コード（0: 成功、1: パラメータエラー） |
| message | string | 処理結果メッセージ |
| data.sessionID | string | 生成されたセッションID（形式: s.XXXXXXXXXXXXXXXX） |

### 出力先

- HTTP Response（JSON形式）
- Content-Type: application/json

## 処理フロー

### 処理シーケンス

```
1. APIリクエスト受信
   └─ RestAPI.ts で /api/2/sessions (POST) エンドポイントを処理

2. 認証・認可チェック
   └─ APIHandler.ts で APIキーまたはOAuth2トークンを検証

3. パラメータ抽出
   └─ リクエストボディから groupID, authorID, validUntil を取得

4. API関数呼び出し
   └─ API.ts 経由で SessionManager.createSession を呼び出し

5. グループ存在チェック
   └─ GroupManager.doesGroupExist でグループの存在確認

6. 著者存在チェック
   └─ AuthorManager.doesAuthorExist で著者の存在確認

7. validUntil バリデーション
   └─ 数値チェック、非負数チェック、整数チェック、未来日時チェック

8. セッションID生成
   └─ s.{16文字ランダム文字列} 形式のIDを生成

9. セッションデータ保存
   └─ session:{sessionID} に {groupID, authorID, validUntil} を保存

10. 関連データ更新
    └─ group2sessions:{groupID} と author2sessions:{authorID} を更新

11. レスポンス返却
    └─ {sessionID: "s.xxx"} 形式で返却
```

### フローチャート

```mermaid
flowchart TD
    A[APIリクエスト受信] --> B{認証チェック}
    B -->|失敗| C[401 Unauthorized]
    B -->|成功| D[パラメータ取得]
    D --> E{グループ存在?}
    E -->|No| F[エラー: groupID does not exist]
    E -->|Yes| G{著者存在?}
    G -->|No| H[エラー: authorID does not exist]
    G -->|Yes| I{validUntil検証}
    I -->|無効| J[エラー: validUntilエラー]
    I -->|有効| K[セッションID生成]
    K --> L[DBにセッション保存]
    L --> M[関連データ更新]
    M --> N[レスポンス返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-42-01 | グループ存在必須 | 指定されたグループIDが存在しない場合はエラー | 常時 |
| BR-42-02 | 著者存在必須 | 指定された著者IDが存在しない場合はエラー | 常時 |
| BR-42-03 | validUntil数値必須 | validUntilは数値でなければならない | 常時 |
| BR-42-04 | validUntil非負 | validUntilは負の値であってはならない | 常時 |
| BR-42-05 | validUntil整数 | validUntilは整数でなければならない（浮動小数点不可） | 常時 |
| BR-42-06 | validUntil未来日時 | validUntilは現在時刻より未来でなければならない | 常時 |
| BR-42-07 | 複数セッション許可 | 同一著者・グループ間で複数のセッションを作成可能 | 常時 |

### 計算ロジック

- validUntilの現在時刻比較: `validUntil < Math.floor(Date.now() / 1000)` で過去判定

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| グループ確認 | group:{groupID} | SELECT | グループの存在確認 |
| 著者確認 | globalAuthor:{authorID} | SELECT | 著者の存在確認 |
| セッション作成 | session:{sessionID} | INSERT | セッション情報の登録 |
| グループ関連更新 | group2sessions:{groupID} | UPDATE | セッションIDの追加 |
| 著者関連更新 | author2sessions:{authorID} | UPDATE | セッションIDの追加 |

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

#### session:{sessionID}

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | groupID | 入力値 | グループID |
| INSERT | authorID | 入力値 | 著者ID |
| INSERT | validUntil | 入力値 | 有効期限（UNIXタイムスタンプ） |

#### group2sessions:{groupID}

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | sessionIDs.{sessionID} | 1 | 新規セッションIDをキーとして追加 |

#### author2sessions:{authorID}

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | sessionIDs.{sessionID} | 1 | 新規セッションIDをキーとして追加 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 1 | apierror | groupIDが存在しない | 正しいグループIDを指定 |
| 1 | apierror | authorIDが存在しない | 正しい著者IDを指定 |
| 1 | apierror | validUntilが数値でない | 数値を指定 |
| 1 | apierror | validUntilが負の値 | 正の値を指定 |
| 1 | apierror | validUntilが浮動小数点 | 整数を指定 |
| 1 | apierror | validUntilが過去 | 未来の日時を指定 |
| 4 | 認証エラー | APIキーまたはトークンが無効 | 正しい認証情報を設定 |

### リトライ仕様

リトライは不要（べき等性はないが、新しいセッションIDが生成される）

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

- セッションデータの保存とgroup2sessions/author2sessionsの更新はPromise.allで並列実行
- セッションデータの保存が先に完了してから関連データを更新することで整合性を確保
- 関連データの更新はueberDBのsetSub（アトミック操作）を使用

## パフォーマンス要件

- レスポンス時間: 200ms以内（標準的な環境）
- セッション生成はランダム文字列生成を含むため、わずかな遅延が発生する可能性あり

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

- APIキー認証またはOAuth2認証による保護
- セッションIDは推測困難な16文字のランダム文字列
- validUntilにより有効期限を強制
- グループ・著者の存在確認により不正なアクセス権付与を防止

## 備考

- 作成されたセッションIDはクライアント側でCookie（sessionID）として保存される
- セッションは自動で期限切れにならないため、削除は明示的に行う必要がある
- 期限切れセッションはfindAuthorID呼び出し時に無効として扱われる

---

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

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

### 推奨読解順序

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

セッションデータの構造と関連するDBキーを理解することが重要である。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | SessionManager.ts | `src/node/db/SessionManager.ts` | セッションデータ構造と関連テーブルの理解 |

**読解のコツ**:
- session:{sessionID} に保存されるオブジェクト構造を把握
- group2sessions と author2sessions の関連を理解

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

REST APIエンドポイントの定義を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | RestAPI.ts | `src/node/handler/RestAPI.ts` | POST /sessions エンドポイントの定義 |

**主要処理フロー**:
1. **439-464行目**: POST /sessions エンドポイントの定義
2. **440行目**: functionName: 'createSession' の指定
3. **441-457行目**: groupID, authorID, validUntil パラメータの定義

#### Step 3: API関数層を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | API.ts | `src/node/db/API.ts` | API関数のエクスポート定義 |
| 3-2 | APIHandler.ts | `src/node/handler/APIHandler.ts` | 認証と関数呼び出しの処理 |

**主要処理フロー**:
- **72行目（API.ts）**: `exports.createSession = sessionManager.createSession;`
- **45行目（APIHandler.ts）**: `createSession: ['groupID', 'authorID', 'validUntil']`

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | SessionManager.ts | `src/node/db/SessionManager.ts` | createSession関数の実装 |
| 4-2 | GroupManager.ts | `src/node/db/GroupManager.ts` | グループ存在確認 |
| 4-3 | AuthorManager.ts | `src/node/db/AuthorManager.ts` | 著者存在確認 |

**主要処理フロー**:
- **105-159行目**: createSession関数の実装
- **107-110行目**: グループ存在チェック
- **112-116行目**: 著者存在チェック
- **118-141行目**: validUntilのバリデーション
- **144行目**: セッションID生成
- **147行目**: DBへのセッション保存
- **151-156行目**: group2sessionsとauthor2sessionsの更新

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

```
HTTP Request: POST /api/2/sessions
    │
    ├─ RestAPI.ts: expressCreateServer (エンドポイント定義)
    │      └─ mapping.get(POST)!["/sessions"]
    │
    ├─ APIHandler.ts: handle (認証・パラメータ処理)
    │      ├─ 認証チェック（APIキー or OAuth2）
    │      └─ api[functionName].apply() 呼び出し
    │
    └─ SessionManager.ts: createSession
           ├─ GroupManager.doesGroupExist
           ├─ AuthorManager.doesAuthorExist
           ├─ validUntil バリデーション
           ├─ randomString(16) でセッションID生成
           ├─ db.set(`session:${sessionID}`)
           └─ Promise.all([
                 db.setSub(`group2sessions:${groupID}`),
                 db.setSub(`author2sessions:${authorID}`)
              ])
```

### データフロー図

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

groupID (string)    ───┐
authorID (string)   ───┼───▶  SessionManager.createSession  ───▶  {sessionID: string}
validUntil (number) ───┘              │
                                      ├─▶ DB: session:{sessionID}
                                      ├─▶ DB: group2sessions:{groupID}
                                      └─▶ DB: author2sessions:{authorID}
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| API.ts | `src/node/db/API.ts` | ソース | API関数の集約・エクスポート |
| SessionManager.ts | `src/node/db/SessionManager.ts` | ソース | セッション管理のビジネスロジック |
| GroupManager.ts | `src/node/db/GroupManager.ts` | ソース | グループ存在確認 |
| AuthorManager.ts | `src/node/db/AuthorManager.ts` | ソース | 著者存在確認 |
| RestAPI.ts | `src/node/handler/RestAPI.ts` | ソース | RESTエンドポイント定義 |
| APIHandler.ts | `src/node/handler/APIHandler.ts` | ソース | API認証・パラメータ処理 |
| DB.ts | `src/node/db/DB.ts` | ソース | データベース接続・操作 |
| randomstring.ts | `src/node/utils/randomstring.ts` | ソース | ランダム文字列生成 |
| sessionsAndGroups.ts | `src/tests/backend/specs/api/sessionsAndGroups.ts` | テスト | APIのテストケース |
