# tegalog-auth.php — てがろぐ拡張スクリプト共通ログイン連携ライブラリ

てがろぐ本体(`tegalog.cgi` / `index.cgi`)、`psif.cgi` と `tegalog.ini` を読み取り専用で参照して、拡張スクリプト側から「てがろぐにログイン中か」「権限レベルはいくつか」を判定するための単一ファイルの共通部品です。複数の拡張スクリプトから使い回すことを想定しています。

## 配置場所

てがろぐ本体(`tegalog.cgi`)と同じディレクトリに置きます。

```
root/
  tegalog.cgi
  tegalog-auth.php     ← このファイル
  psif.cgi
  tegalog.ini
  ある拡張フォルダ/
    スクリプト.php      ← ここから require_once __DIR__ . '/../tegalog-auth.php'; する
```

## 基本的な使い方

```php
require_once __DIR__ . '/../tegalog-auth.php';

$user = tgauth_currentUser();
if ($user === null) {
    http_response_code(403);
    exit('ログインしてください。');
}

$level = tgauth_userLevel($user);
```

## 関数リファレンス

### ログイン状態・ユーザー情報

#### `tgauth_currentUser(): ?string`
現在のリクエストがてがろぐにログイン中かどうかを判定し、ログイン中ならユーザーIDを返す。未ログイン、または `psif.cgi` / `tegalog.ini` が読めない場合は `null`。読み取り専用の照合のみ行い、セッション有効期限の延長(スライディング)などの書き込みは行わない。

#### `tgauth_isLoggedIn(): bool`
ログイン中かどうかの真偽値だけが欲しい場合のショートカット。

#### `tgauth_userDetail(string $userid): ?array`
指定ユーザーIDの詳細を `tegalog.ini` の `userids` から取得する。見つからなければ `null`。

```php
['id' => string, 'level' => int, 'name' => string, 'intro' => string, 'icon' => string]
```

#### `tgauth_userLevel(string $userid): int`
指定ユーザーの権限レベル(userlv、1〜9)。見つからなければ `0`。

#### `tgauth_currentUserDetail(): ?array`
`tgauth_currentUser()` + `tgauth_userDetail()` のショートカット。ログイン中ユーザー自身の詳細を1回で取得したいときに使う。未ログインなら `null`。

#### `tgauth_isAdmin(int $level = 9): bool`
ログイン中のユーザーの権限レベルが `$level` 以上かどうか。未ログインなら常に `false`。管理者権限が必要な処理の入口ガードに使う想定。

```php
if (!tgauth_isAdmin()) {
    http_response_code(403);
    exit('権限がありません。');
}
```

#### `tgauth_allUsers(): array`
`tegalog.ini` の `userids` に登録されている全ユーザーの一覧を返す。要素は `tgauth_userDetail()` と同じ形。ユーザー選択UIなどで使う。

### ログイン必須化のヘルパー

#### `tgauth_requireLogin(callable $onFail, int $minLevel = 0): string`
ログイン(かつ任意で最低権限レベル)を満たしていなければ `$onFail(string $reason)` を呼んで終了する。`$reason` は `'not_logged_in'` または `'insufficient_level'`。満たしていればユーザーIDを返す。

応答形式(HTML画面かJSON APIか等)は拡張スクリプトごとに異なるため、実際のレスポンス出力とexitは `$onFail` 側で行う設計。

```php
$user = tgauth_requireLogin(function (string $reason) {
    http_response_code(403);
    header('Content-Type: application/json');
    echo json_encode(['ok' => false, 'error' => $reason]);
}, 5); // 権限レベル5以上を要求
```

### CSRF対策

拡張スクリプトはそれぞれ自分の設定ファイル等に秘密文字列(salt)を持つ前提で、それとログインユーザーIDから決定的にトークンを導出する。セッションストレージを持たない単一ファイル配布物のため、サーバー側で状態を持たずに検証できる。

#### `tgauth_csrfToken(string $secret, string $loginUser): string`
CSRFトークンを生成する。

#### `tgauth_verifyCsrfToken(string $secret, string $loginUser, ?string $token): bool`
送られてきたトークンを検証する。

```php
$csrfToken = tgauth_csrfToken($mySecret, $user);
// ... フォームのhidden inputに埋め込む ...

if (!tgauth_verifyCsrfToken($mySecret, $user, $_POST['csrf'] ?? null)) {
    exit('不正なリクエストです。');
}
```

### てがろぐ設定へのアクセス

#### `tgauth_siteConfig(string $key, ?string $default = null): ?string`
`tegalog.ini` の任意のキーを取得する汎用アクセサ。ログイン連携に限らず、てがろぐ本体の設定を参照したい場合に使う。見つからなければ `$default`。

```php
$title = tgauth_siteConfig('title', 'てがろぐ');
```

#### `tgauth_loadIni(string $path): array`
`key=value` 形式のiniファイルを読む汎用パーサ(`tegalog.ini` と同形式)。内部で使われているが、拡張スクリプト自身の設定ファイルを読むのにもそのまま使える。読めない場合は空配列を返す。

#### `tgauth_cookieName(): string`
てがろぐのログインセッションCookie名を返す(`coexistflag` / `coexistsuffix` 設定に対応)。通常は他の関数が内部で使うため直接呼ぶ必要はない。

## 設計上の注意点

- **読み取り専用**: `psif.cgi` への書き込み(ログイン処理・セッション延長・ログアウト)は一切行わない。それらは常にてがろぐ本体の役目とする。ログアウト機能等が必要な場合は別途検討すること。
- **単一ファイル配布**: 依存ライブラリなし、Composer等も不要。拡張スクリプトのフォルダに同梱して配布する運用を想定しているため、クラスや名前空間は使わず `tgauth_` プレフィックス付きのグローバル関数のみで構成している。
- **直接アクセス対策**: このファイルがWebから直接リクエストされた場合は404を返して終了する(関数定義のみで実害はないが念のため)。
- **二重読み込み対策**: 呼び出し側が誤って`require_once`ではなく`require`を使った場合や、複数の経路から読み込まれた場合でも、関数の再定義によるFatal Errorを起こさないよう自己防衛している(既に読み込み済みなら何もせず終了する)。ただし基本は`require_once`を使うこと。

## ライセンス
てがろぐ専用スクリプト開発に限り特に断り・記載なく利用可能です。
ただし利用して生じたトラブルについては責任を負いかねますのでご了承ください。
また、特にサポートは行いませんが、致命的な不具合など見つけた方はhttp://tekitote.s324.xrea.com/へご連絡ください。