@aiquants/authz-react-router 0.8.1 → 0.8.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +10 -614
- package/dist/index.d.ts +10 -614
- package/dist/index.js +2 -3
- package/dist/index.mjs +2 -3
- package/package.json +8 -8
- package/dist/index.js.map +0 -1
- package/dist/index.mjs.map +0 -1
package/dist/index.d.mts
CHANGED
|
@@ -1,184 +1,53 @@
|
|
|
1
|
-
import * as react_router from
|
|
2
|
-
import * as react from
|
|
3
|
-
import { ReactNode, CSSProperties } from
|
|
4
|
-
import * as _aiquants_authz_core from
|
|
5
|
-
import { EffectivePermission, DenyInfo, AuthzAction, MergedScope, AuthzGrant, AuthzRole, AuthzResource, AuthzUser, AuthzAssignment, AuthzGroupRoleAssignment, AuthzGroupSummary, AuthzAdminStore } from
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* React Router (v7) adapter: binds `appKey` + the DI ports and exposes the loader/action authorization API.
|
|
9
|
-
* React Router (v7) 向けアダプタ。`appKey` と DI ポートを束ね、loader/action 用の認可 API を公開するモジュール。
|
|
10
|
-
*
|
|
11
|
-
* 設計上の中心的な不変条件は **判定は 1 回だけ** ということ。ガード (`requirePermission`) と
|
|
12
|
-
* UI 表示用の権限ビューは同一の実効権限から導出されるため、「画面は開けるのに一覧では false」
|
|
13
|
-
* という乖離が構造的に起こり得ない。
|
|
14
|
-
*/
|
|
15
|
-
|
|
1
|
+
import * as react_router from "react-router";
|
|
2
|
+
import * as react from "react";
|
|
3
|
+
import { ReactNode, CSSProperties } from "react";
|
|
4
|
+
import * as _aiquants_authz_core from "@aiquants/authz-core";
|
|
5
|
+
import { EffectivePermission, DenyInfo, AuthzAction, MergedScope, AuthzGrant, AuthzRole, AuthzResource, AuthzUser, AuthzAssignment, AuthzGroupRoleAssignment, AuthzGroupSummary, AuthzAdminStore } from "@aiquants/authz-core";
|
|
16
6
|
type Awaitable<T> = T | Promise<T>;
|
|
17
7
|
type AuthzUserId = string | number;
|
|
18
|
-
/**
|
|
19
|
-
* Thrown when the API itself is called incorrectly (bad arguments, missing port) — a programmer error,
|
|
20
|
-
* never an authorization decision. It is deliberately NOT an `AuthzDeniedError`: a misuse must surface as a
|
|
21
|
-
* loud 500, not as a silent 403 that looks like a permission problem.
|
|
22
|
-
* API の使い方が誤っている場合に送出される例外。認可拒否 (403) とは明確に区別されるプログラマ向けエラー。
|
|
23
|
-
*/
|
|
24
8
|
declare class AuthzUsageError extends Error {
|
|
25
9
|
constructor(message: string);
|
|
26
10
|
}
|
|
27
|
-
/**
|
|
28
|
-
* Arguments handed to the {@link AuthzConfig.getEffectivePermissions} port.
|
|
29
|
-
* 実効権限ポートへ渡す引数。
|
|
30
|
-
*
|
|
31
|
-
* `tenantId` is a **required, non-empty string**. It is never absent and never `null`: a port that
|
|
32
|
-
* receives no tenant would have to guess, and the only guess an SQL adapter can make — omit the
|
|
33
|
-
* predicate — returns every tenant's grants. That inversion is the failure this contract removes.
|
|
34
|
-
* `tenantId` は必須かつ非空 (欠落を「全テナント」に読み替える経路を型ごと塞ぐ形)。
|
|
35
|
-
*/
|
|
36
11
|
type EffectivePermissionsQuery = {
|
|
37
12
|
userId: AuthzUserId | null;
|
|
38
13
|
tenantId: string;
|
|
39
14
|
groupIds?: (string | number)[];
|
|
40
15
|
appKey: string;
|
|
41
|
-
/** Always a de-duplicated, non-empty list — the port may load them all in one round-trip. Read-only: the adapter reports on exactly these keys. */
|
|
42
16
|
resourceKeys: readonly string[];
|
|
43
17
|
};
|
|
44
18
|
type AuthzConfig = {
|
|
45
|
-
/** Stable app identifier (e.g. "quants"). Bound into every permission query. */
|
|
46
19
|
appKey: string;
|
|
47
|
-
/** Resolve the acting user id from the request (cookie/session/openid → the consumer's user id). */
|
|
48
20
|
resolveUserId: (request: Request) => Awaitable<AuthzUserId | null | undefined>;
|
|
49
|
-
/**
|
|
50
|
-
* Resolve the acting tenant id from the request (header / cookie / subdomain → tenant id).
|
|
51
|
-
* **Required**: every permission question is asked within exactly one tenant, so a host that
|
|
52
|
-
* cannot name it must not be able to ask at all. Returning a blank string raises
|
|
53
|
-
* `AuthzTenantError` — it is never read as "no filter" / "every tenant".
|
|
54
|
-
* リクエストからテナント ID を解決するポート (必須)。空文字は「全テナント」ではなく例外。
|
|
55
|
-
*/
|
|
56
21
|
resolveTenantId: (request: Request) => Awaitable<string>;
|
|
57
|
-
/**
|
|
58
|
-
* Prove the acting identity may act **as** the resolved tenant. **Required**, with no permissive
|
|
59
|
-
* default: `resolveTenantId` only says *which* tenant was named, and that name comes from a
|
|
60
|
-
* client-influenced channel (header / sub-domain / cookie). Without this seam a user of tenant A
|
|
61
|
-
* is authorized inside tenant B by naming tenant B — B's `@authenticated` grants apply and every
|
|
62
|
-
* downstream tenant check still passes, because the permission genuinely belongs to B.
|
|
63
|
-
* リクエストが名乗ったテナントへの帰属証明 (必須・既定値なし)。テナント名は利用者が影響できる経路から
|
|
64
|
-
* 来るため、これが無いと「別テナントを名乗るだけで越境認可」になる。
|
|
65
|
-
*
|
|
66
|
-
* Called once per check, **before** any permission is loaded. `userId` is `null` for an anonymous
|
|
67
|
-
* caller; the host decides whether that tenant's `@anonymous` grants may be used (they are public
|
|
68
|
-
* by construction, so `true` is the usual answer).
|
|
69
|
-
* 権限読込より前に 1 回だけ呼ばれる。匿名呼び出しの扱いはホストが決める。
|
|
70
|
-
*/
|
|
71
22
|
assertTenantMembership: (request: Request, tenantId: string, userId: AuthzUserId | null) => Awaitable<boolean>;
|
|
72
|
-
/**
|
|
73
|
-
* Optionally resolve acting user's group IDs, for the tenant the request was scoped to.
|
|
74
|
-
* リクエストのスコープとなったテナントに対して、実行ユーザーのグループ ID を解決する任意ポート。
|
|
75
|
-
*
|
|
76
|
-
* `tenantId` is the value `resolveTenantId` already produced and validated, so a host never has to
|
|
77
|
-
* derive the tenant a second time — a second derivation is a second thing that can disagree.
|
|
78
|
-
* `tenantId` は解決・検証済みの値 (ホスト側での二重解決を不要にし、乖離の余地を作らないため)。
|
|
79
|
-
*/
|
|
80
23
|
resolveGroupIds?: (request: Request, tenantId: string) => Awaitable<(string | number)[] | null | undefined>;
|
|
81
|
-
/**
|
|
82
|
-
* Load effective permissions for (user, app, resources) — **one call, many resources** (typically
|
|
83
|
-
* `getEffectivePermissionsMany` from `@aiquants/authz-drizzle`). A key with no grants may be omitted or
|
|
84
|
-
* mapped to `null`; both mean "no permission" (fail-close).
|
|
85
|
-
*/
|
|
86
24
|
getEffectivePermissions: (args: EffectivePermissionsQuery) => Awaitable<Record<string, EffectivePermission | null | undefined> | null | undefined>;
|
|
87
|
-
/**
|
|
88
|
-
* Optional: every resource key registered for this app **within `tenantId`** (typically
|
|
89
|
-
* `listResourceKeys` from `@aiquants/authz-drizzle`, whose 4th argument is that same tenant).
|
|
90
|
-
* Configuring it is what makes `getMyPermissions(request)` — with no resource list — legal;
|
|
91
|
-
* without it that call throws {@link AuthzUsageError} instead of guessing.
|
|
92
|
-
* 指定テナントに登録済みの全リソースキーを返す任意ポート。
|
|
93
|
-
*
|
|
94
|
-
* The tenant is handed in already resolved and validated: making the host re-derive it from the
|
|
95
|
-
* raw `Request` would create a second, divergable tenant source, and a host that derived it
|
|
96
|
-
* differently (or could not) would report on another tenant's resource keys.
|
|
97
|
-
* テナントは解決・検証済みの値として渡す (ホスト側での再導出は第 2 のテナント源となり乖離するため)。
|
|
98
|
-
*
|
|
99
|
-
* Called only after `assertTenantMembership` has proven the caller may act as `tenantId`: the set of
|
|
100
|
-
* registered keys is itself that tenant's information, so a non-member must not be able to provoke
|
|
101
|
-
* this query at all.
|
|
102
|
-
* 帰属証明を通った後にのみ呼ばれる (登録済みキーの集合自体がテナントの情報であるため)。
|
|
103
|
-
*/
|
|
104
25
|
listResourceKeys?: (request: Request, tenantId: string) => Awaitable<readonly string[] | null | undefined>;
|
|
105
|
-
/** Default deny handler. If omitted, denies throw AuthzDeniedError (403). */
|
|
106
26
|
onDeny?: (info: DenyInfo) => void;
|
|
107
27
|
};
|
|
108
28
|
type RequirePermissionOptions = {
|
|
109
|
-
/** When set, denials `throw redirect(failureRedirect)` instead of throwing 403. */
|
|
110
29
|
failureRedirect?: string;
|
|
111
30
|
};
|
|
112
|
-
/**
|
|
113
|
-
* Serializable per-resource permission summary for UI (loader → component).
|
|
114
|
-
* UI 向けの直列化可能なリソース単位権限サマリ (loader からコンポーネントへ受け渡す形)。
|
|
115
|
-
*
|
|
116
|
-
* 真偽値は `can` 接頭辞で統一されている。`delete` のような素の動詞名は分割代入できず
|
|
117
|
-
* (`const { delete } = view` は構文エラー)、フックの戻り値との二重語彙も生むため採用しない。
|
|
118
|
-
*/
|
|
119
31
|
type PermissionView<K extends string = string> = {
|
|
120
32
|
resourceKey: K;
|
|
121
33
|
canRead: boolean;
|
|
122
34
|
canCreate: boolean;
|
|
123
35
|
canUpdate: boolean;
|
|
124
36
|
canDelete: boolean;
|
|
125
|
-
/** create ∪ update */
|
|
126
37
|
canWrite: boolean;
|
|
127
|
-
/** read granted but row and/or column restricted (→ △ partial). */
|
|
128
38
|
readPartial: boolean;
|
|
129
39
|
actions: AuthzAction[];
|
|
130
40
|
};
|
|
131
|
-
/** Result of a successful {@link createAuthz} guard. ガード成功時の戻り値。 */
|
|
132
41
|
type RequirePermissionResult<K extends string = string> = {
|
|
133
42
|
userId: AuthzUserId | null;
|
|
134
|
-
/** The tenant the decision was made within (always present, never blank). 判定を行ったテナント。 */
|
|
135
43
|
tenantId: string;
|
|
136
|
-
/** Effective row/column scope for the guarded action — apply as WHERE / column mask. */
|
|
137
44
|
scope: MergedScope;
|
|
138
|
-
/** UI view derived from the **same** evaluation as the guard decision (no second lookup). */
|
|
139
45
|
permission: PermissionView<K>;
|
|
140
46
|
};
|
|
141
|
-
/**
|
|
142
|
-
* Permission views keyed by the exact resource keys that were requested.
|
|
143
|
-
* 要求したキーで型付けした権限ビュー群。
|
|
144
|
-
*
|
|
145
|
-
* リテラルのキーを渡した場合だけ「そのキーは必ず存在する」形になる。`string[]` のようにキーが実行時に
|
|
146
|
-
* しか分からない場合は `| undefined` を含む索引型へ落ち、存在チェックを強制する (総和型の索引を
|
|
147
|
-
* 名乗ると、要求していないキーが型の上では必ず存在することになり、元の不具合と同じ罠に戻る)。
|
|
148
|
-
*
|
|
149
|
-
* ⚠️ キーは配列の **要素型** から導かれる。`flag ? ["a"] : ["b"]` のように要素型が合併になる式では、
|
|
150
|
-
* 実行時に片方しか無くても型の上では両方が存在する扱いになる。リテラル配列を直接渡すか
|
|
151
|
-
* `resourceKeysOf(registry)` を使うこと。
|
|
152
|
-
* ⚠️ 戻り値を `Record<string, …>` 型の変数へ代入すると、その文脈から `K` が `string` へ広がり
|
|
153
|
-
* 索引型 (値は `| undefined`) に落ちる。リテラルキーの保証が要る箇所では代入先を広げないこと。
|
|
154
|
-
* ⚠️ 戻り値は素のオブジェクト。要求していない `toString` などのキーを読むと `Object.prototype` の
|
|
155
|
-
* メンバが返る (索引型の `| undefined` とは一致しない)。要求したキーだけを読むこと。
|
|
156
|
-
*/
|
|
157
47
|
type PermissionViewMap<K extends string> = string extends K ? Record<string, PermissionView | undefined> : {
|
|
158
48
|
[P in K]: PermissionView<P>;
|
|
159
49
|
};
|
|
160
|
-
/**
|
|
161
|
-
* Map an EffectivePermission to a serializable {@link PermissionView}.
|
|
162
|
-
* 実効権限を直列化可能な {@link PermissionView} へ変換する処理。
|
|
163
|
-
*
|
|
164
|
-
* @returns The UI-facing permission summary (all-false when `perm` is absent). UI 表示用の権限サマリ。
|
|
165
|
-
*/
|
|
166
50
|
declare function toPermissionView<K extends string>(resourceKey: K, perm: EffectivePermission | null | undefined): PermissionView<K>;
|
|
167
|
-
/**
|
|
168
|
-
* React Router adapter. Binds `appKey` and the DI deps, exposing:
|
|
169
|
-
* - `requirePermission(request, {resourceKey, action}, options?)` → `{ userId, tenantId, scope, permission }` on allow
|
|
170
|
-
* (apply row WHERE / column mask with `scope`; render `permission` in the UI); denies throw 403 or redirect.
|
|
171
|
-
* Every check is scoped to the tenant `resolveTenantId` returns, that tenant must be one the caller is proven
|
|
172
|
-
* to belong to (`assertTenantMembership`, else deny `not-a-tenant-member`), and a permission issued for
|
|
173
|
-
* another tenant is denied (`tenant-mismatch`) rather than trusted.
|
|
174
|
-
* - `getMyPermissions(request, {resourceKeys})` → `Record<resourceKey, PermissionView>` for the UI,
|
|
175
|
-
* or `getMyPermissions(request)` for every registered resource when `listResourceKeys` is configured.
|
|
176
|
-
* Membership is proven **before** that resource list is read, so naming a foreign tenant never reveals
|
|
177
|
-
* which resources it has registered.
|
|
178
|
-
* `appKey` と DI ポートを束ね、ガードと自己権限取得の 2 面だけを公開するファクトリ。
|
|
179
|
-
*
|
|
180
|
-
* @returns The bound `requirePermission` / `getMyPermissions` pair. 結線済みの認可 API 一式。
|
|
181
|
-
*/
|
|
182
51
|
declare function createAuthz(config: AuthzConfig): {
|
|
183
52
|
requirePermission: <K extends string>(request: Request, query: {
|
|
184
53
|
resourceKey: K;
|
|
@@ -193,21 +62,6 @@ declare function createAuthz(config: AuthzConfig): {
|
|
|
193
62
|
}): Promise<Record<string, PermissionView | undefined>>;
|
|
194
63
|
};
|
|
195
64
|
};
|
|
196
|
-
|
|
197
|
-
/**
|
|
198
|
-
* The label contract of the authorization admin UI: its string shape, the English defaults, and the
|
|
199
|
-
* per-section merge that resolves a host's partial overrides against them.
|
|
200
|
-
* 認可管理 UI のラベル契約 (文言の型・英語既定値・部分上書きを解決するセクション単位マージ)。
|
|
201
|
-
*
|
|
202
|
-
* A host overrides whole sections through `createAuthzAdminRoutes(..., { labels })`; sections it
|
|
203
|
-
* leaves out keep the defaults, so a partial translation never blanks a screen.
|
|
204
|
-
* アプリ側は `createAuthzAdminRoutes(..., { labels })` でセクション単位に上書きする形
|
|
205
|
-
* (未指定セクションは既定値のまま残るため、部分翻訳でも画面が空にならない)。
|
|
206
|
-
*/
|
|
207
|
-
/**
|
|
208
|
-
* Authz admin UI strings (i18n). Defaults are English; override per-section via `createAuthzAdminRoutes(..., { labels })`.
|
|
209
|
-
* 認可管理 UI の文言 (i18n)。既定は英語で、セクション単位に上書きできる形。
|
|
210
|
-
*/
|
|
211
65
|
type AuthzAdminLabels = {
|
|
212
66
|
title: string;
|
|
213
67
|
myPermission: string;
|
|
@@ -219,10 +73,6 @@ type AuthzAdminLabels = {
|
|
|
219
73
|
group_roles: string;
|
|
220
74
|
graph: string;
|
|
221
75
|
};
|
|
222
|
-
/**
|
|
223
|
-
* Strings shared by every tab, including the tenant column / field every tenant-scoped table shows.
|
|
224
|
-
* 全タブ共通の文言 (テナント列・テナント入力欄を含む)。
|
|
225
|
-
*/
|
|
226
76
|
common: {
|
|
227
77
|
add: string;
|
|
228
78
|
save: string;
|
|
@@ -325,27 +175,10 @@ type PartialAuthzAdminLabels = {
|
|
|
325
175
|
error?: Partial<AuthzAdminLabels["error"]>;
|
|
326
176
|
warn?: Partial<AuthzAdminLabels["warn"]>;
|
|
327
177
|
};
|
|
328
|
-
/**
|
|
329
|
-
* Merge partial overrides onto the English defaults, one section at a time.
|
|
330
|
-
* 部分的な上書きを英語の既定値へセクション単位で統合する処理。
|
|
331
|
-
*
|
|
332
|
-
* The merge is shallow **per section**, not a whole-object replace: a host that overrides only
|
|
333
|
-
* `grants.note` keeps every other `grants` string instead of losing them.
|
|
334
|
-
* 統合はセクション単位の浅いマージであり全体置換ではない形
|
|
335
|
-
* (`grants.note` だけを上書きしても、同セクションの他文言は失われない)。
|
|
336
|
-
*
|
|
337
|
-
* @param over Partial overrides, or `undefined` to keep the defaults. 部分的な上書き (`undefined` なら既定値のまま)。
|
|
338
|
-
* @returns The fully resolved label set. 解決済みの全文言。
|
|
339
|
-
*/
|
|
340
178
|
declare function resolveLabels(over?: PartialAuthzAdminLabels): AuthzAdminLabels;
|
|
341
|
-
|
|
342
179
|
type WithLabels = {
|
|
343
180
|
labels: AuthzAdminLabels;
|
|
344
181
|
};
|
|
345
|
-
/**
|
|
346
|
-
* Loader payload of any tenant-scoped tab: the tenant every row on screen was loaded for.
|
|
347
|
-
* テナント単位タブの loader ペイロード共通部 (画面上の全行を読み込んだテナント)。
|
|
348
|
-
*/
|
|
349
182
|
type WithTenant = {
|
|
350
183
|
tenantId: string;
|
|
351
184
|
};
|
|
@@ -367,88 +200,24 @@ type AuthzLayoutProps = {
|
|
|
367
200
|
annotation: React.ReactNode;
|
|
368
201
|
}) => React.ReactNode;
|
|
369
202
|
};
|
|
370
|
-
/**
|
|
371
|
-
* Layout route for a nested route configuration; the active tab is rendered through `Outlet`.
|
|
372
|
-
* ネストルート構成用のレイアウト (子タブは `Outlet` で描画)。`routes.ts` をネスト構成にする場合の入口。
|
|
373
|
-
*
|
|
374
|
-
* @param props Optional header renderer. 任意のヘッダ描画関数。
|
|
375
|
-
* @returns The framed admin page hosting the nested route. ネストされた子ルートを収めた管理画面。
|
|
376
|
-
*/
|
|
377
203
|
declare function AuthzLayout({ renderHeader }?: AuthzLayoutProps): react.JSX.Element;
|
|
378
|
-
/**
|
|
379
|
-
* Build the admin UI's error boundary with labels baked in.
|
|
380
|
-
* ラベルを埋め込んだ認可管理 UI のエラー境界を生成する処理。
|
|
381
|
-
*
|
|
382
|
-
* An error boundary cannot read loader data, so its wording cannot come from the loader the way
|
|
383
|
-
* every tab's does; the host injects its own locale here instead.
|
|
384
|
-
* エラー境界は loader データを読めないため、他タブのようにラベルを loader から得られない形
|
|
385
|
-
* (アプリ側が自分のロケールをここで注入する)。
|
|
386
|
-
*
|
|
387
|
-
* @param over Partial label overrides; omitted sections keep the English defaults. 部分的なラベル上書き (未指定は英語の既定値)。
|
|
388
|
-
* @returns An error boundary component bound to those labels. そのラベルを束縛したエラー境界コンポーネント。
|
|
389
|
-
*/
|
|
390
204
|
declare function makeAuthzErrorBoundary(over?: PartialAuthzAdminLabels): () => React.ReactElement;
|
|
391
|
-
/**
|
|
392
|
-
* The error boundary bound to the package's English default labels.
|
|
393
|
-
* 英語 (既定ラベル) のエラー境界。i18n する場合は {@link makeAuthzErrorBoundary} を使う形。
|
|
394
|
-
*/
|
|
395
205
|
declare const AuthzErrorBoundary: () => React.ReactElement;
|
|
396
206
|
type AuthzRolesData = WithLabels & WithTenant & {
|
|
397
207
|
roles: AuthzRole[];
|
|
398
208
|
selfAdminRoleIds?: number[];
|
|
399
209
|
};
|
|
400
|
-
/**
|
|
401
|
-
* Roles tab: lists the tenant's roles and offers create / rename / enable / delete.
|
|
402
|
-
* ロールタブ。当該テナントのロール一覧と、作成・改名・有効切替・削除の操作を提供するコンポーネント。
|
|
403
|
-
*
|
|
404
|
-
* Reads {@link AuthzRolesData}; the tenant shown in every row is the one the guard resolved, which
|
|
405
|
-
* the loader also echoes as `tenantId`.
|
|
406
|
-
* {@link AuthzRolesData} を読む形。表示するテナントはガードが解決したもの (loader が `tenantId` として同梱)。
|
|
407
|
-
*
|
|
408
|
-
* @returns The roles tab. ロールタブ。
|
|
409
|
-
*/
|
|
410
210
|
declare function AuthzRolesView(): react.JSX.Element;
|
|
411
211
|
type AuthzResourcesData = WithLabels & WithTenant & {
|
|
412
212
|
resources: AuthzResource[];
|
|
413
213
|
};
|
|
414
|
-
/**
|
|
415
|
-
* Resources tab: lists the tenant's resources and offers create / rename / delete.
|
|
416
|
-
* リソースタブ。当該テナントのリソース一覧と、作成・改名・削除の操作を提供するコンポーネント。
|
|
417
|
-
*
|
|
418
|
-
* Reads {@link AuthzResourcesData}; the tenant shown is the guard-resolved one.
|
|
419
|
-
* {@link AuthzResourcesData} を読む形 (表示するテナントはガードが解決したもの)。
|
|
420
|
-
*
|
|
421
|
-
* @returns The resources tab. リソースタブ。
|
|
422
|
-
*/
|
|
423
214
|
declare function AuthzResourcesView(): react.JSX.Element;
|
|
424
|
-
/**
|
|
425
|
-
* Grants tab payload. `roles` / `resources` are the **full** rows, not just the id + key pairs the
|
|
426
|
-
* select boxes need: a grant row carries no tenant of its own, so the referenced role's projected
|
|
427
|
-
* tenant is what the tenant column shows.
|
|
428
|
-
* 付与タブのペイロード。`roles` / `resources` は全項目を持つ行 (付与行にテナント列が無く、参照先ロールの実テナントを表示するため)。
|
|
429
|
-
*/
|
|
430
215
|
type AuthzGrantsData = WithLabels & WithTenant & {
|
|
431
216
|
grants: AuthzGrant[];
|
|
432
217
|
roles: AuthzRole[];
|
|
433
218
|
resources: AuthzResource[];
|
|
434
219
|
};
|
|
435
|
-
/**
|
|
436
|
-
* Permissions tab: lists the tenant's grants and offers grant / re-scope / revoke.
|
|
437
|
-
* 権限付与タブ。当該テナントの付与一覧と、付与・スコープ変更・削除の操作を提供するコンポーネント。
|
|
438
|
-
*
|
|
439
|
-
* Reads {@link AuthzGrantsData}; its role and resource pickers are already narrowed to the
|
|
440
|
-
* guard-resolved tenant by the loader, so a cross-tenant pair cannot be selected here.
|
|
441
|
-
* {@link AuthzGrantsData} を読む形。ロール・リソースの選択肢は loader が解決済みテナントへ絞ってあるため、
|
|
442
|
-
* 越境した組み合わせは選べない。
|
|
443
|
-
*
|
|
444
|
-
* @returns The permissions tab. 権限付与タブ。
|
|
445
|
-
*/
|
|
446
220
|
declare function AuthzGrantsView(): react.JSX.Element;
|
|
447
|
-
/**
|
|
448
|
-
* User-assignment tab payload. `roles` holds the **full** role rows because `TDUserRole` has no tenant
|
|
449
|
-
* column: the assignment's tenant is the one projected onto the role it points at.
|
|
450
|
-
* ユーザー割当タブのペイロード。`TDUserRole` にテナント列が無いため、`roles` は参照先ロールの実テナントを含む全項目行。
|
|
451
|
-
*/
|
|
452
221
|
type AuthzUserRolesData = WithLabels & WithTenant & {
|
|
453
222
|
assignments: AuthzAssignment[];
|
|
454
223
|
roles: AuthzRole[];
|
|
@@ -456,33 +225,12 @@ type AuthzUserRolesData = WithLabels & WithTenant & {
|
|
|
456
225
|
actorUserId?: number;
|
|
457
226
|
selfAdminRoleIds?: number[];
|
|
458
227
|
};
|
|
459
|
-
/**
|
|
460
|
-
* User-roles tab: lists the tenant's user assignments and offers assign / unassign.
|
|
461
|
-
* ユーザー割当タブ。当該テナントのユーザー×ロール割当一覧と、割当・解除の操作を提供するコンポーネント。
|
|
462
|
-
*
|
|
463
|
-
* Reads {@link AuthzUserRolesData}; removing an assignment that supports the actor's own admin
|
|
464
|
-
* status is confirmed first through {@link confirmGuard}.
|
|
465
|
-
* {@link AuthzUserRolesData} を読む形 (実行者自身の管理権限を支える割当の解除は {@link confirmGuard} で確認)。
|
|
466
|
-
*
|
|
467
|
-
* @returns The user-roles tab. ユーザー割当タブ。
|
|
468
|
-
*/
|
|
469
228
|
declare function AuthzUserRolesView(): react.JSX.Element;
|
|
470
229
|
type AuthzGroupRolesData = WithLabels & WithTenant & {
|
|
471
230
|
groupRoles: AuthzGroupRoleAssignment[];
|
|
472
231
|
roles: AuthzRole[];
|
|
473
232
|
groups: AuthzGroupSummary[];
|
|
474
233
|
};
|
|
475
|
-
/**
|
|
476
|
-
* Group-roles tab: lists the tenant's group assignments and offers assign / unassign.
|
|
477
|
-
* グループ割当タブ。当該テナントのグループ×ロール割当一覧と、割当・解除の操作を提供するコンポーネント。
|
|
478
|
-
*
|
|
479
|
-
* Reads {@link AuthzGroupRolesData}. See the module docstring for its known layout deviations from
|
|
480
|
-
* the other tabs (hard-coded confirmation text, no tenant column, error alert placed differently).
|
|
481
|
-
* {@link AuthzGroupRolesData} を読む形。他タブとの既知の逸脱 (確認文言のハードコード・テナント列の非表示・
|
|
482
|
-
* エラー表示位置の相違) はモジュール冒頭の記載を参照。
|
|
483
|
-
*
|
|
484
|
-
* @returns The group-roles tab. グループ割当タブ。
|
|
485
|
-
*/
|
|
486
234
|
declare function AuthzGroupRolesView(): react.JSX.Element;
|
|
487
235
|
type AuthzGraphData = WithLabels & WithTenant & {
|
|
488
236
|
users: AuthzUser[];
|
|
@@ -494,16 +242,6 @@ type AuthzGraphData = WithLabels & WithTenant & {
|
|
|
494
242
|
groups?: AuthzGroupSummary[];
|
|
495
243
|
};
|
|
496
244
|
type AuthzNodeType = "user" | "group" | "role" | "resource";
|
|
497
|
-
/**
|
|
498
|
-
* Graph tab: the authorization relations of the tenant, as a topology map or as linked columns.
|
|
499
|
-
* グラフタブ。当該テナントの認可関係を、トポロジ図または連動カラム表示で俯瞰するコンポーネント。
|
|
500
|
-
*
|
|
501
|
-
* Reads {@link AuthzGraphData}. Selecting a node filters the other three columns to what that node
|
|
502
|
-
* actually reaches, and the search box narrows every column at once.
|
|
503
|
-
* {@link AuthzGraphData} を読む形 (ノード選択で他 3 カラムを到達範囲に絞り、検索は全カラムへ同時適用)。
|
|
504
|
-
*
|
|
505
|
-
* @returns The graph tab. グラフタブ。
|
|
506
|
-
*/
|
|
507
245
|
declare function AuthzGraphView(): react.JSX.Element;
|
|
508
246
|
type AuthzAdminAppViewProps = {
|
|
509
247
|
renderHeader?: (props: {
|
|
@@ -511,19 +249,7 @@ type AuthzAdminAppViewProps = {
|
|
|
511
249
|
annotation: React.ReactNode;
|
|
512
250
|
}) => React.ReactNode;
|
|
513
251
|
};
|
|
514
|
-
/**
|
|
515
|
-
* Render the whole admin UI from a single splat route (`authz/*`), without depending on any store.
|
|
516
|
-
* スプラット (`authz/*`) 1 ルートで認可管理 UI 全体を描画するコンポーネント (store 非依存)。
|
|
517
|
-
*
|
|
518
|
-
* The loader's `segment` selects the tab; the shell and the tab read one merged loader payload
|
|
519
|
-
* (the segment's rows plus `myPermissions` and `labels` at the top level).
|
|
520
|
-
* loader が返す `segment` に応じてタブを選ぶ形 (外枠と各ビューは統合済みの同一 loader データを読む)。
|
|
521
|
-
*
|
|
522
|
-
* @param props Optional header renderer. 任意のヘッダ描画関数。
|
|
523
|
-
* @returns The admin page for the requested segment. 要求セグメントに対応する管理画面。
|
|
524
|
-
*/
|
|
525
252
|
declare function AuthzAdminAppView({ renderHeader }?: AuthzAdminAppViewProps): react.JSX.Element;
|
|
526
|
-
|
|
527
253
|
type Req = {
|
|
528
254
|
request: Request;
|
|
529
255
|
};
|
|
@@ -531,121 +257,36 @@ type PermissionQuery = {
|
|
|
531
257
|
resourceKey: string;
|
|
532
258
|
action: AuthzAction;
|
|
533
259
|
};
|
|
534
|
-
/**
|
|
535
|
-
* Everything a guarded admin request resolved to: the tenant it acts within and the acting user.
|
|
536
|
-
* ガード済みの管理リクエストが解決した文脈 (操作対象テナントと実行ユーザー)。
|
|
537
|
-
*
|
|
538
|
-
* Both fields are required. The tenant is what every store call is scoped by, and the user id is what
|
|
539
|
-
* the audit columns and the "last administrator" warning are computed from; neither has a meaningful
|
|
540
|
-
* "absent" value on this route.
|
|
541
|
-
* 双方必須 (テナントは全ストア呼び出しの絞り込み、ユーザー ID は監査列と自己管理者判定の基準)。
|
|
542
|
-
*/
|
|
543
260
|
type AuthzAdminContext = {
|
|
544
261
|
tenantId: string;
|
|
545
262
|
userId: string | number;
|
|
546
263
|
};
|
|
547
264
|
type CreateAuthzAdminServerOptions = {
|
|
548
265
|
store: AuthzAdminStore;
|
|
549
|
-
/** 管理画面のガード資源キー(既定 `authz_admin`)。 */
|
|
550
266
|
resourceKey?: string;
|
|
551
|
-
/** 未ログインをログインへ誘導する(例: throw redirect(...))。 */
|
|
552
267
|
requireUser: (request: Request) => Promise<unknown>;
|
|
553
|
-
/**
|
|
554
|
-
* Authorization guard supplied by the app (from `createAuthz`); allow → `{ userId, tenantId, permission }`.
|
|
555
|
-
* 認可ガード (アプリの createAuthz 由来)。allow で { userId, tenantId, permission } を返すポート。
|
|
556
|
-
* `userId` は nullable(未解決/万一の public 付与)であり、createAuthzAdminServer 内で deny する
|
|
557
|
-
* (管理経路は監査・自己権限計算に実 id が必須のため非 null を保証)。
|
|
558
|
-
* `tenantId` は **ガードが判定に使ったテナントそのもの**。ここで捨てて画面側が別経路で引き直すと、
|
|
559
|
-
* 「A テナントの権限で B テナントを編集できる」という越境が構造的に開く。
|
|
560
|
-
* `permission` は **同一判定から導かれた** 自己権限ビューであり、表示用に再取得しない
|
|
561
|
-
* (再取得は「ガードは通るのにバッジは権限なし」という乖離の温床)。
|
|
562
|
-
*/
|
|
563
268
|
requirePermission: (request: Request, query: PermissionQuery) => Promise<{
|
|
564
269
|
userId: string | number | null;
|
|
565
270
|
tenantId: string;
|
|
566
271
|
permission: PermissionView;
|
|
567
272
|
}>;
|
|
568
|
-
/** 文言の部分上書き(既定は日本語)。 */
|
|
569
273
|
labels?: PartialAuthzAdminLabels;
|
|
570
274
|
};
|
|
571
|
-
/**
|
|
572
|
-
* Build the authorization admin UI's server side: one guard seam, per-tab data loaders, and the
|
|
573
|
-
* loader / action pair of every route.
|
|
574
|
-
* 認可管理 UI のサーバ側 (単一のガードシーム、タブ別データ取得、各ルートの loader/action) を構築する処理。
|
|
575
|
-
*
|
|
576
|
-
* Every route entry is guarded through the app-supplied `requirePermission`, whose result — the
|
|
577
|
-
* tenant, the acting user, and the self-permission view — comes from **one** evaluation and is
|
|
578
|
-
* carried onward as an {@link AuthzAdminContext}. Nothing here re-derives the tenant from the request
|
|
579
|
-
* or re-loads the permission for display: a second lookup can disagree with the first, which is
|
|
580
|
-
* exactly the "guard allows but the badge says denied" failure, and re-deriving the tenant is how a
|
|
581
|
-
* screen ends up editing a tenant the guard never authorized.
|
|
582
|
-
* 各ルートはアプリ由来の `requirePermission` を通し、その 1 回の判定から得たテナント・実行ユーザー・
|
|
583
|
-
* 自己権限を {@link AuthzAdminContext} として持ち回る形 (テナントの引き直しも表示用の再取得も行わない)。
|
|
584
|
-
*
|
|
585
|
-
* Writes never trust the submitted ids: each one is re-loaded from a tenant-scoped listing and, where
|
|
586
|
-
* the row carries its own tenant, compared against it. A missing row and a foreign row are answered
|
|
587
|
-
* identically, so the screen cannot be used as a cross-tenant existence oracle.
|
|
588
|
-
* 書き込みは送信された id を信用せず、テナント絞り込みの一覧から引き直して帰属を確認する形
|
|
589
|
-
* (「存在しない」と「別テナント」は同じ応答にし、他テナントの存在確認手段にしない)。
|
|
590
|
-
*
|
|
591
|
-
* @param opts Store port, guard seams, admin resource key and label overrides.
|
|
592
|
-
* store ポート・ガードシーム・管理リソースキー・文言上書き。
|
|
593
|
-
* @returns The labels, the guarded resource key, `layoutGuard`, and every route's loader / action.
|
|
594
|
-
* 文言・ガード対象リソースキー・`layoutGuard`・各ルートの loader/action。
|
|
595
|
-
*/
|
|
596
275
|
declare function createAuthzAdminServer(opts: CreateAuthzAdminServerOptions): {
|
|
597
|
-
/** 露出: スプラットマウント(app.ts)がガードを 1 回だけ行うために使う。 */
|
|
598
276
|
labels: AuthzAdminLabels;
|
|
599
277
|
resourceKey: string;
|
|
600
278
|
layoutGuard: (request: Request) => Promise<AuthzAdminContext & {
|
|
601
279
|
myPermissions: Record<string, PermissionView | undefined>;
|
|
602
280
|
}>;
|
|
603
|
-
/** /authz レイアウト: requireUser(302) → requirePermission(read, 403)。自己権限はガードの戻り値から得る。 */
|
|
604
281
|
layout: {
|
|
605
|
-
/**
|
|
606
|
-
* Layout loader: guard once, then hand the shell the tenant and the self-permission map.
|
|
607
|
-
* レイアウトの loader。ガードを 1 回だけ行い、テナントと自己権限マップを外枠へ渡す処理。
|
|
608
|
-
*
|
|
609
|
-
* @param args The route arguments (request only). ルート引数 (request のみ)。
|
|
610
|
-
* @returns The layout payload. レイアウトの表示データ。
|
|
611
|
-
* @throws {Response} `302` when unauthenticated, `403` when the read is denied. 未認証は 302、拒否は 403。
|
|
612
|
-
*/
|
|
613
282
|
loader({ request }: Req): Promise<AuthzLayoutData>;
|
|
614
283
|
};
|
|
615
|
-
/** /authz index → roles へ。 */
|
|
616
284
|
index: {
|
|
617
|
-
/**
|
|
618
|
-
* Index loader: the admin root has no view of its own, so it redirects to the roles tab.
|
|
619
|
-
* インデックスの loader。管理ルートは固有の表示を持たないためロールタブへ転送する処理。
|
|
620
|
-
*
|
|
621
|
-
* @returns Never returns; always throws the redirect. 常に転送を送出 (正常復帰しない)。
|
|
622
|
-
* @throws {Response} The `/authz/roles` redirect. `/authz/roles` への転送。
|
|
623
|
-
*/
|
|
624
285
|
loader(): never;
|
|
625
286
|
};
|
|
626
287
|
roles: {
|
|
627
288
|
data: (ctx: AuthzAdminContext) => Promise<AuthzRolesData>;
|
|
628
|
-
/**
|
|
629
|
-
* Roles tab loader: guard for `read`, then load the tab within the guarded tenant.
|
|
630
|
-
* ロールタブの loader。`read` をガードし、ガード済みテナントの範囲で読み込む処理。
|
|
631
|
-
*
|
|
632
|
-
* @param args The route arguments (request only). ルート引数 (request のみ)。
|
|
633
|
-
* @returns The roles tab payload. ロールタブの表示データ。
|
|
634
|
-
* @throws {AuthzDeniedError} When the read is denied. 読み取りが拒否された場合。
|
|
635
|
-
*/
|
|
636
289
|
loader({ request }: Req): Promise<AuthzRolesData>;
|
|
637
|
-
/**
|
|
638
|
-
* Roles tab action: create / save / toggle / delete, each guarded for its own verb.
|
|
639
|
-
* ロールタブの action。作成・保存・有効切替・削除を、それぞれの動詞でガードして実行する処理。
|
|
640
|
-
*
|
|
641
|
-
* `create` and `save` additionally reconcile the submitted `tenantId` with the guarded one
|
|
642
|
-
* before the store is called, and every id is re-loaded through `ownedRole`.
|
|
643
|
-
* `create`/`save` は送信された `tenantId` をガード側と突合し、id は必ず `ownedRole` で引き直す形。
|
|
644
|
-
*
|
|
645
|
-
* @param args The route arguments (request only). ルート引数 (request のみ)。
|
|
646
|
-
* @returns `{ ok: true }`, or a `400` payload on a validation failure. 成功、または検証失敗時の 400 応答。
|
|
647
|
-
* @throws {Response} `403` when the guard denies the verb. 動詞のガードが拒否した場合。
|
|
648
|
-
*/
|
|
649
290
|
action({ request }: Req): Promise<react_router.UNSAFE_DataWithResponseInit<{
|
|
650
291
|
error: string;
|
|
651
292
|
}> | {
|
|
@@ -654,27 +295,7 @@ declare function createAuthzAdminServer(opts: CreateAuthzAdminServerOptions): {
|
|
|
654
295
|
};
|
|
655
296
|
resources: {
|
|
656
297
|
data: (ctx: AuthzAdminContext) => Promise<AuthzResourcesData>;
|
|
657
|
-
/**
|
|
658
|
-
* Resources tab loader: guard for `read`, then load the tab within the guarded tenant.
|
|
659
|
-
* リソースタブの loader。`read` をガードし、ガード済みテナントの範囲で読み込む処理。
|
|
660
|
-
*
|
|
661
|
-
* @param args The route arguments (request only). ルート引数 (request のみ)。
|
|
662
|
-
* @returns The resources tab payload. リソースタブの表示データ。
|
|
663
|
-
* @throws {AuthzDeniedError} When the read is denied. 読み取りが拒否された場合。
|
|
664
|
-
*/
|
|
665
298
|
loader({ request }: Req): Promise<AuthzResourcesData>;
|
|
666
|
-
/**
|
|
667
|
-
* Resources tab action: create / save / delete, each guarded for its own verb.
|
|
668
|
-
* リソースタブの action。作成・保存・削除を、それぞれの動詞でガードして実行する処理。
|
|
669
|
-
*
|
|
670
|
-
* `create` reconciles the submitted `tenantId` with the guarded one; `save` and `delete`
|
|
671
|
-
* re-load the id through `ownedResource` instead of trusting the form.
|
|
672
|
-
* `create` は送信 `tenantId` を突合し、`save`/`delete` は `ownedResource` で id を引き直す形。
|
|
673
|
-
*
|
|
674
|
-
* @param args The route arguments (request only). ルート引数 (request のみ)。
|
|
675
|
-
* @returns `{ ok: true }`, or a `400` payload on a validation failure. 成功、または検証失敗時の 400 応答。
|
|
676
|
-
* @throws {Response} `403` when the guard denies the verb. 動詞のガードが拒否した場合。
|
|
677
|
-
*/
|
|
678
299
|
action({ request }: Req): Promise<react_router.UNSAFE_DataWithResponseInit<{
|
|
679
300
|
error: string;
|
|
680
301
|
}> | {
|
|
@@ -683,28 +304,7 @@ declare function createAuthzAdminServer(opts: CreateAuthzAdminServerOptions): {
|
|
|
683
304
|
};
|
|
684
305
|
grants: {
|
|
685
306
|
data: (ctx: AuthzAdminContext) => Promise<AuthzGrantsData>;
|
|
686
|
-
/**
|
|
687
|
-
* Grants tab loader: guard for `read`, then load the tab within the guarded tenant.
|
|
688
|
-
* 権限付与タブの loader。`read` をガードし、ガード済みテナントの範囲で読み込む処理。
|
|
689
|
-
*
|
|
690
|
-
* @param args The route arguments (request only). ルート引数 (request のみ)。
|
|
691
|
-
* @returns The grants tab payload. 権限付与タブの表示データ。
|
|
692
|
-
* @throws {AuthzDeniedError} When the read is denied. 読み取りが拒否された場合。
|
|
693
|
-
*/
|
|
694
307
|
loader({ request }: Req): Promise<AuthzGrantsData>;
|
|
695
|
-
/**
|
|
696
|
-
* Grants tab action: create / save / delete, each guarded for its own verb.
|
|
697
|
-
* 権限付与タブの action。作成・保存・削除を、それぞれの動詞でガードして実行する処理。
|
|
698
|
-
*
|
|
699
|
-
* A grant links two rows, so `create` proves **both** the role and the resource belong to
|
|
700
|
-
* the guarded tenant; `save` and `delete` prove the grant itself through `assertOwnedGrant`.
|
|
701
|
-
* 付与は 2 行を結ぶため `create` はロール・リソース双方の帰属を証明し、`save`/`delete` は
|
|
702
|
-
* `assertOwnedGrant` で付与自体の帰属を証明する形。
|
|
703
|
-
*
|
|
704
|
-
* @param args The route arguments (request only). ルート引数 (request のみ)。
|
|
705
|
-
* @returns `{ ok: true }`, or a `400` payload on a validation failure. 成功、または検証失敗時の 400 応答。
|
|
706
|
-
* @throws {Response} `403` when the guard denies the verb. 動詞のガードが拒否した場合。
|
|
707
|
-
*/
|
|
708
308
|
action({ request }: Req): Promise<react_router.UNSAFE_DataWithResponseInit<{
|
|
709
309
|
error: string;
|
|
710
310
|
}> | {
|
|
@@ -713,28 +313,7 @@ declare function createAuthzAdminServer(opts: CreateAuthzAdminServerOptions): {
|
|
|
713
313
|
};
|
|
714
314
|
userRoles: {
|
|
715
315
|
data: (ctx: AuthzAdminContext) => Promise<AuthzUserRolesData>;
|
|
716
|
-
/**
|
|
717
|
-
* User-roles tab loader: guard for `read`, then load the tab within the guarded tenant.
|
|
718
|
-
* ユーザー割当タブの loader。`read` をガードし、ガード済みテナントの範囲で読み込む処理。
|
|
719
|
-
*
|
|
720
|
-
* @param args The route arguments (request only). ルート引数 (request のみ)。
|
|
721
|
-
* @returns The user-roles tab payload. ユーザー割当タブの表示データ。
|
|
722
|
-
* @throws {AuthzDeniedError} When the read is denied. 読み取りが拒否された場合。
|
|
723
|
-
*/
|
|
724
316
|
loader({ request }: Req): Promise<AuthzUserRolesData>;
|
|
725
|
-
/**
|
|
726
|
-
* User-roles tab action: assign / remove, each guarded for its own verb.
|
|
727
|
-
* ユーザー割当タブの action。割当・解除を、それぞれの動詞でガードして実行する処理。
|
|
728
|
-
*
|
|
729
|
-
* The assignment row carries no tenant of its own, so both ends are proven — the user
|
|
730
|
-
* through `assertOwnedUser` and the role through `ownedRole` — before the store is called.
|
|
731
|
-
* 割当行はテナントを持たないため、ユーザー側 (`assertOwnedUser`) とロール側 (`ownedRole`) の
|
|
732
|
-
* 両端の帰属を証明してからストアを呼ぶ形。
|
|
733
|
-
*
|
|
734
|
-
* @param args The route arguments (request only). ルート引数 (request のみ)。
|
|
735
|
-
* @returns `{ ok: true }`, or a `400` payload on a validation failure. 成功、または検証失敗時の 400 応答。
|
|
736
|
-
* @throws {Response} `403` when the guard denies the verb. 動詞のガードが拒否した場合。
|
|
737
|
-
*/
|
|
738
317
|
action({ request }: Req): Promise<react_router.UNSAFE_DataWithResponseInit<{
|
|
739
318
|
error: string;
|
|
740
319
|
}> | {
|
|
@@ -743,27 +322,7 @@ declare function createAuthzAdminServer(opts: CreateAuthzAdminServerOptions): {
|
|
|
743
322
|
};
|
|
744
323
|
groupRoles: {
|
|
745
324
|
data: (ctx: AuthzAdminContext) => Promise<AuthzGroupRolesData>;
|
|
746
|
-
/**
|
|
747
|
-
* Group-roles tab loader: guard for `read`, then load the tab within the guarded tenant.
|
|
748
|
-
* グループ割当タブの loader。`read` をガードし、ガード済みテナントの範囲で読み込む処理。
|
|
749
|
-
*
|
|
750
|
-
* @param args The route arguments (request only). ルート引数 (request のみ)。
|
|
751
|
-
* @returns The group-roles tab payload. グループ割当タブの表示データ。
|
|
752
|
-
* @throws {AuthzDeniedError} When the read is denied. 読み取りが拒否された場合。
|
|
753
|
-
*/
|
|
754
325
|
loader({ request }: Req): Promise<AuthzGroupRolesData>;
|
|
755
|
-
/**
|
|
756
|
-
* Group-roles tab action: assign / remove, each guarded for its own verb.
|
|
757
|
-
* グループ割当タブの action。割当・解除を、それぞれの動詞でガードして実行する処理。
|
|
758
|
-
*
|
|
759
|
-
* As with user roles the link row carries no tenant, so both the group (`ownedGroup`) and
|
|
760
|
-
* the role (`ownedRole`) are proven to belong to the guarded tenant first.
|
|
761
|
-
* ユーザー割当と同様に割当行はテナントを持たないため、グループ側・ロール側双方の帰属を先に証明する形。
|
|
762
|
-
*
|
|
763
|
-
* @param args The route arguments (request only). ルート引数 (request のみ)。
|
|
764
|
-
* @returns `{ ok: true }`, or a `400` payload on a validation failure. 成功、または検証失敗時の 400 応答。
|
|
765
|
-
* @throws {Response} `403` when the guard denies the verb. 動詞のガードが拒否した場合。
|
|
766
|
-
*/
|
|
767
326
|
action({ request }: Req): Promise<react_router.UNSAFE_DataWithResponseInit<{
|
|
768
327
|
error: string;
|
|
769
328
|
}> | {
|
|
@@ -772,32 +331,16 @@ declare function createAuthzAdminServer(opts: CreateAuthzAdminServerOptions): {
|
|
|
772
331
|
};
|
|
773
332
|
graph: {
|
|
774
333
|
data: (ctx: AuthzAdminContext) => Promise<AuthzGraphData>;
|
|
775
|
-
/**
|
|
776
|
-
* Graph tab loader: guard for `read`, then load every listing of the guarded tenant.
|
|
777
|
-
* グラフタブの loader。`read` をガードし、ガード済みテナントの全一覧を読み込む処理。
|
|
778
|
-
*
|
|
779
|
-
* @param args The route arguments (request only). ルート引数 (request のみ)。
|
|
780
|
-
* @returns The graph tab payload. グラフタブの表示データ。
|
|
781
|
-
* @throws {AuthzDeniedError} When the read is denied. 読み取りが拒否された場合。
|
|
782
|
-
*/
|
|
783
334
|
loader({ request }: Req): Promise<AuthzGraphData>;
|
|
784
335
|
};
|
|
785
336
|
};
|
|
786
|
-
|
|
787
337
|
type RouteArgs = {
|
|
788
338
|
request: Request;
|
|
789
339
|
params: Record<string, string | undefined>;
|
|
790
340
|
};
|
|
791
341
|
type CreateAuthzAdminAppOptions = CreateAuthzAdminServerOptions & {
|
|
792
|
-
/** マウントのベースパス(タブリンク/未指定セグメントのリダイレクト先)。既定 `/authz`。 */
|
|
793
342
|
basePath?: string;
|
|
794
343
|
};
|
|
795
|
-
/**
|
|
796
|
-
* Build the loader/action pair that serves the whole authorization admin UI from one splat route.
|
|
797
|
-
* 認可管理 UI 全体を 1 本のスプラットルートで提供する loader/action 対を生成するファクトリ。
|
|
798
|
-
*
|
|
799
|
-
* @returns The route `loader` / `action` plus the underlying server for direct use. ルートの loader/action と内部サーバ。
|
|
800
|
-
*/
|
|
801
344
|
declare function createAuthzAdminApp(opts: CreateAuthzAdminAppOptions): {
|
|
802
345
|
loader: (args: RouteArgs) => Promise<{
|
|
803
346
|
labels: AuthzAdminLabels;
|
|
@@ -915,16 +458,6 @@ declare function createAuthzAdminApp(opts: CreateAuthzAdminAppOptions): {
|
|
|
915
458
|
};
|
|
916
459
|
};
|
|
917
460
|
};
|
|
918
|
-
|
|
919
|
-
/**
|
|
920
|
-
* Inline styles shared by the admin tabs, keyed by role.
|
|
921
|
-
* 管理タブ共通のインラインスタイル (役割名をキーとする形)。
|
|
922
|
-
*
|
|
923
|
-
* `satisfies` is used rather than a `Record<string, CSSProperties>` annotation: the annotation
|
|
924
|
-
* erases the key set, so a typo such as `ui.dangerBtn` type-checks and silently renders unstyled.
|
|
925
|
-
* `Record<string, CSSProperties>` の注釈ではなく `satisfies` を用いる形 (注釈はキー集合を消し、
|
|
926
|
-
* `ui.dangerBtn` のような綴り誤りが型検査を素通りして無装飾描画になるため)。
|
|
927
|
-
*/
|
|
928
461
|
declare const ui: {
|
|
929
462
|
page: {
|
|
930
463
|
padding: string;
|
|
@@ -1069,72 +602,27 @@ declare const ui: {
|
|
|
1069
602
|
padding: string;
|
|
1070
603
|
};
|
|
1071
604
|
};
|
|
1072
|
-
/**
|
|
1073
|
-
* Stack a label above its control, keeping the two from overlapping and the tabs consistent.
|
|
1074
|
-
* ラベルを上、コントロールを下に縦積みするフィールド (重なり防止・レイアウト統一)。
|
|
1075
|
-
*
|
|
1076
|
-
* A `<div>` rather than a `<label>`: the control is expected to carry its own `aria-label`.
|
|
1077
|
-
* `<label>` ではなく `<div>` で構成する形 (コントロール側が `aria-label` を持つ前提のため)。
|
|
1078
|
-
*
|
|
1079
|
-
* @param props The label text, an optional hint, and the control to wrap. ラベル文言・任意の補足・包むコントロール。
|
|
1080
|
-
* @returns The stacked field. 縦積みされたフィールド。
|
|
1081
|
-
*/
|
|
1082
605
|
declare function Field({ label, hint, children }: {
|
|
1083
606
|
label: string;
|
|
1084
607
|
hint?: string;
|
|
1085
608
|
children: ReactNode;
|
|
1086
609
|
}): react.JSX.Element;
|
|
1087
|
-
/**
|
|
1088
|
-
* Render an error message as an assertive alert, or nothing when there is no message.
|
|
1089
|
-
* エラーメッセージを `role="alert"` で表示するコンポーネント (メッセージが無ければ何も描画しない形)。
|
|
1090
|
-
*
|
|
1091
|
-
* @param props The message to show, if any. 表示するメッセージ (省略可)。
|
|
1092
|
-
* @returns The alert element, or `null`. アラート要素、または `null`。
|
|
1093
|
-
*/
|
|
1094
610
|
declare function ErrorAlert({ message }: {
|
|
1095
611
|
message?: string;
|
|
1096
612
|
}): react.JSX.Element | null;
|
|
1097
|
-
|
|
1098
613
|
type MyPermissionGroupItem = {
|
|
1099
|
-
/** Expected or actual resource key */
|
|
1100
614
|
resourceKey?: string;
|
|
1101
|
-
/** Human-readable resource display name (e.g. "NI", "KT", "オリジナル") */
|
|
1102
615
|
resourceName: string;
|
|
1103
|
-
/** Permission view data for this resource */
|
|
1104
616
|
permission: PermissionView | null | undefined;
|
|
1105
|
-
/** Expected resource key to detect mismatches with permission.resourceKey during development */
|
|
1106
617
|
expectedResourceKey?: string;
|
|
1107
|
-
/** Nesting level for hierarchical rendering (0: root, 1: child, etc.) */
|
|
1108
618
|
level?: number;
|
|
1109
|
-
/** Optional child items for hierarchical rendering */
|
|
1110
619
|
children?: MyPermissionGroupItem[];
|
|
1111
620
|
};
|
|
1112
|
-
/**
|
|
1113
|
-
* Flattens hierarchical items tree into a single array with computed nesting levels.
|
|
1114
|
-
* 木構造またはフラット配列のアイテムに level 属性を付与してフラット化する処理。
|
|
1115
|
-
*/
|
|
1116
621
|
declare function flattenGroupItems(items: MyPermissionGroupItem[], currentLevel?: number): MyPermissionGroupItem[];
|
|
1117
622
|
type MyPermissionGroupStatusProps = {
|
|
1118
|
-
/** List of resources and their permissions */
|
|
1119
623
|
items: MyPermissionGroupItem[];
|
|
1120
|
-
/** Prefix label shown before group items or inside popover header. Default: "あなたの権限" */
|
|
1121
624
|
prefixLabel?: string;
|
|
1122
|
-
/**
|
|
1123
|
-
* Display style variant:
|
|
1124
|
-
* - "pills": Inline parent label + compact status tags per item
|
|
1125
|
-
* - "popover": Compact single button trigger opening detailed popup card
|
|
1126
|
-
* Default: "pills"
|
|
1127
|
-
*/
|
|
1128
625
|
variant?: "pills" | "popover";
|
|
1129
|
-
/**
|
|
1130
|
-
* Component size variant:
|
|
1131
|
-
* - "2xs": Ultra micro size for extremely dense UI
|
|
1132
|
-
* - "xs": Extra small size for compact headers
|
|
1133
|
-
* - "sm": Small size
|
|
1134
|
-
* - "md": Standard default size
|
|
1135
|
-
* - "lg": Larger size
|
|
1136
|
-
* Default: "md"
|
|
1137
|
-
*/
|
|
1138
626
|
size?: "2xs" | "xs" | "sm" | "md" | "lg";
|
|
1139
627
|
labels?: {
|
|
1140
628
|
read?: string;
|
|
@@ -1149,107 +637,50 @@ type MyPermissionGroupStatusProps = {
|
|
|
1149
637
|
className?: string;
|
|
1150
638
|
style?: CSSProperties;
|
|
1151
639
|
};
|
|
1152
|
-
/**
|
|
1153
|
-
* Get human-readable summary text and style for a resource permission.
|
|
1154
|
-
* 権限状態から簡潔なサマリテキストとスタイルを判定 (カスタムラベル対応)。
|
|
1155
|
-
*/
|
|
1156
640
|
declare function getPermissionSummary(permission: PermissionView | null | undefined, customLabels?: MyPermissionGroupStatusProps["labels"]): {
|
|
1157
641
|
text: string;
|
|
1158
642
|
color: string;
|
|
1159
643
|
bgColor: string;
|
|
1160
644
|
borderColor: string;
|
|
1161
645
|
};
|
|
1162
|
-
/**
|
|
1163
|
-
* Multi-resource "Your Permissions" status component.
|
|
1164
|
-
* Supports inline compact pills (Proposal 1) and dropdown popover card (Proposal 2).
|
|
1165
|
-
* 複数リソースの権限状態を共通レイアウト(pills/popover)で綺麗に整列・表示するコンポーネント。
|
|
1166
|
-
*/
|
|
1167
646
|
declare function MyPermissionGroupStatus({ items, prefixLabel, variant, size, labels, className, style }: MyPermissionGroupStatusProps): react.JSX.Element;
|
|
1168
|
-
|
|
1169
647
|
type MyPermissionIndicatorProps<K extends string = string> = {
|
|
1170
648
|
permission: PermissionView<K> | null | undefined;
|
|
1171
|
-
/** Human-readable resource display name (e.g. "文書データ"). Falls back to permission.resourceKey. */
|
|
1172
649
|
resourceName?: string;
|
|
1173
|
-
/**
|
|
1174
|
-
* Expected resource key. Typed as `NoInfer<K>`, so when the permission carries a literal key
|
|
1175
|
-
* (`getMyPermissions` / `requirePermission` both do) a mismatch is a **compile error**; the runtime
|
|
1176
|
-
* detector below stays for dynamically-keyed and JavaScript callers.
|
|
1177
|
-
*/
|
|
1178
650
|
expectedResourceKey?: NoInfer<K>;
|
|
1179
|
-
/** Whether to include resource name/key tooltip. Default true. */
|
|
1180
651
|
showResourceTooltip?: boolean;
|
|
1181
652
|
labels?: {
|
|
1182
653
|
read?: string;
|
|
1183
654
|
write?: string;
|
|
1184
655
|
delete?: string;
|
|
1185
656
|
};
|
|
1186
|
-
/** Show a "(部分)" hint when read is partial. Default true. */
|
|
1187
657
|
showScopeSummary?: boolean;
|
|
1188
658
|
className?: string;
|
|
1189
659
|
};
|
|
1190
660
|
type MyPermissionStatusProps<K extends string = string> = MyPermissionIndicatorProps<K> & {
|
|
1191
|
-
/** Label prefix shown before the indicator badges. Default: "あなたの権限" */
|
|
1192
661
|
prefixLabel?: string;
|
|
1193
|
-
/** Whether to display the prefix label. Default: true */
|
|
1194
662
|
showPrefixLabel?: boolean;
|
|
1195
|
-
/** Additional inline styles for wrapper element. */
|
|
1196
663
|
style?: React.CSSProperties;
|
|
1197
664
|
};
|
|
1198
|
-
/**
|
|
1199
|
-
* Format human-readable resource tooltip text.
|
|
1200
|
-
* リソース表示名およびキーからツールチップ用テキストを生成。
|
|
1201
|
-
*/
|
|
1202
665
|
declare function formatResourceTooltip(resourceKey?: string, resourceName?: string): string | undefined;
|
|
1203
|
-
/**
|
|
1204
|
-
* Display permission indicator badges for read, write, and delete capabilities.
|
|
1205
|
-
* 閲覧・編集・削除の権限状態バッジ群を描画。
|
|
1206
|
-
*/
|
|
1207
666
|
declare function MyPermissionIndicator<K extends string = string>({ permission, resourceName, expectedResourceKey, showResourceTooltip, labels, showScopeSummary, className }: MyPermissionIndicatorProps<K>): react.JSX.Element;
|
|
1208
|
-
/**
|
|
1209
|
-
* Reusable "Your Permissions" status bar component suitable for any application page.
|
|
1210
|
-
* 「あなたの権限」ラベルと権限状態インジケータを束ねた再利用可能なコンポーネント。
|
|
1211
|
-
*/
|
|
1212
667
|
declare function MyPermissionStatus<K extends string = string>({ permission, resourceName, expectedResourceKey, prefixLabel, showPrefixLabel, showResourceTooltip, labels, showScopeSummary, className, style, }: MyPermissionStatusProps<K>): react.JSX.Element;
|
|
1213
|
-
|
|
1214
|
-
/**
|
|
1215
|
-
* Resource definition and registry utilities for preventing page-resource mismatches.
|
|
1216
|
-
* ページとリソースの表示・権限食い違いを防止するためのリソースレジストリ定義。
|
|
1217
|
-
*/
|
|
1218
668
|
type ResourceDefinition = {
|
|
1219
|
-
/** Unique resource key used in authorization rules (e.g. "documents") */
|
|
1220
669
|
key: string;
|
|
1221
|
-
/** Human-readable display name (e.g. "文書管理") */
|
|
1222
670
|
name: string;
|
|
1223
|
-
/** Optional description for administration UI */
|
|
1224
671
|
description?: string;
|
|
1225
672
|
};
|
|
1226
673
|
type ResourceDefinitionInput = {
|
|
1227
|
-
/** Optional explicit resource key; defaults to the object property name */
|
|
1228
674
|
key?: string;
|
|
1229
|
-
/** Human-readable display name (e.g. "文書管理") */
|
|
1230
675
|
name: string;
|
|
1231
|
-
/** Optional description for administration UI */
|
|
1232
676
|
description?: string;
|
|
1233
677
|
};
|
|
1234
678
|
type ResourceRegistry<T extends Record<string, ResourceDefinition>> = T;
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
* `extends string` では偽になってプロパティ名を名乗ってしまうため (実行時は `key` を使うので型が嘘になる)。
|
|
1241
|
-
* `key` を書いていないエントリでは `Extract` が `never` になり、プロパティ名へ落ちる。
|
|
1242
|
-
*/
|
|
1243
|
-
type ResolvedResourceKey<PropertyName extends string, Input extends ResourceDefinitionInput> = [Extract<Input["key"], string>] extends [never] ? PropertyName : Extract<Input["key"], string>;
|
|
1244
|
-
/**
|
|
1245
|
-
* Define type-safe resource registry for an application.
|
|
1246
|
-
* アプリ全体のリソース定義(キー・表示名・説明)を一元管理するヘルパー。
|
|
1247
|
-
*
|
|
1248
|
-
* 各エントリの `key` はリテラル型のまま保持する。`Record<string, …>` へ広げてしまうと
|
|
1249
|
-
* {@link resourceKeysOf} が `string[]` に落ち、権限マップのキー型検査が効かなくなるため。
|
|
1250
|
-
*
|
|
1251
|
-
* @returns The registry with literal-typed resource keys. リソースキーをリテラル型で保持したレジストリ。
|
|
1252
|
-
*/
|
|
679
|
+
type ResolvedResourceKey<PropertyName extends string, Input extends ResourceDefinitionInput> = [
|
|
680
|
+
Extract<Input["key"], string>
|
|
681
|
+
] extends [
|
|
682
|
+
never
|
|
683
|
+
] ? PropertyName : Extract<Input["key"], string>;
|
|
1253
684
|
declare function defineResources<const T extends Record<string, ResourceDefinitionInput>>(resources: T): {
|
|
1254
685
|
[K in keyof T & string]: {
|
|
1255
686
|
key: ResolvedResourceKey<K, T[K]>;
|
|
@@ -1257,54 +688,19 @@ declare function defineResources<const T extends Record<string, ResourceDefiniti
|
|
|
1257
688
|
description?: string;
|
|
1258
689
|
};
|
|
1259
690
|
};
|
|
1260
|
-
/**
|
|
1261
|
-
* Extract a registry's resource keys with their literal types preserved.
|
|
1262
|
-
* レジストリのリソースキーをリテラル型を保ったまま取り出す処理。
|
|
1263
|
-
*
|
|
1264
|
-
* `Object.keys(registry)` は `string[]` になり、`getMyPermissions` の戻り値も索引型へ落ちてキーの誤りを
|
|
1265
|
-
* 検出できなくなる。加えて `Object.keys` は **プロパティ名** を返すため、`key` を明示したエントリでは
|
|
1266
|
-
* 実際のリソースキーと食い違う。
|
|
1267
|
-
*
|
|
1268
|
-
* ⚠️ 1 エントリでもリテラルでない `key` (例: 変数由来の `string`) を持つと、合併の性質上レジストリ全体の
|
|
1269
|
-
* キー型が `string` へ広がり、他のエントリ分のコンパイル時検査も無効になる。`key` は必ずリテラルで書くこと。
|
|
1270
|
-
*
|
|
1271
|
-
* @returns The registry's resource keys as a literal union array. リテラル合併型のリソースキー配列。
|
|
1272
|
-
*/
|
|
1273
691
|
declare function resourceKeysOf<T extends Record<string, {
|
|
1274
692
|
key: string;
|
|
1275
693
|
}>>(registry: T): Array<T[keyof T & string]["key"]>;
|
|
1276
|
-
|
|
1277
|
-
/**
|
|
1278
|
-
* Display-state derivation for a {@link PermissionView} (pure, no React state involved).
|
|
1279
|
-
* {@link PermissionView} から表示状態を導出するモジュール (React の状態は一切持たない純粋関数)。
|
|
1280
|
-
*/
|
|
1281
|
-
|
|
1282
694
|
type PermState = "full" | "partial" | "none";
|
|
1283
|
-
/**
|
|
1284
|
-
* Display-oriented reading of a {@link PermissionView}: the same `can*` booleans (safe defaults when the
|
|
1285
|
-
* view is absent) plus the ○△× tri-state used by the indicator components.
|
|
1286
|
-
* {@link PermissionView} の表示向け読み取り結果。同名の `can*` 真偽値と ○△× の三値状態を併せ持つ形。
|
|
1287
|
-
*/
|
|
1288
695
|
type UsePermission = {
|
|
1289
696
|
canRead: boolean;
|
|
1290
697
|
canCreate: boolean;
|
|
1291
698
|
canUpdate: boolean;
|
|
1292
699
|
canDelete: boolean;
|
|
1293
|
-
/** create ∪ update */
|
|
1294
700
|
canWrite: boolean;
|
|
1295
|
-
/** read: none(×) / partial(△, row|col restricted) / full(○). */
|
|
1296
701
|
readState: PermState;
|
|
1297
|
-
/** write = create ∪ update: full(○ both) / partial(△ one) / none(×). */
|
|
1298
702
|
writeState: PermState;
|
|
1299
703
|
deleteState: PermState;
|
|
1300
704
|
};
|
|
1301
|
-
/**
|
|
1302
|
-
* Derive ○△× display states from a {@link PermissionView}. Pure (safe to call in render);
|
|
1303
|
-
* named `usePermission` for ergonomic call-sites.
|
|
1304
|
-
* {@link PermissionView} から ○△× の表示状態を導出する純粋関数 (レンダー内から安全に呼べる形)。
|
|
1305
|
-
*
|
|
1306
|
-
* @returns The permission booleans plus their display states. 権限の真偽値と表示状態の組。
|
|
1307
|
-
*/
|
|
1308
705
|
declare function usePermission(view: PermissionView | null | undefined): UsePermission;
|
|
1309
|
-
|
|
1310
706
|
export { AuthzAdminAppView, type AuthzAdminAppViewProps, type AuthzAdminContext, type AuthzAdminLabels, type AuthzConfig, AuthzErrorBoundary, type AuthzGrantsData, AuthzGrantsView, type AuthzGraphData, AuthzGraphView, type AuthzGroupRolesData, AuthzGroupRolesView, AuthzLayout, type AuthzLayoutData, type AuthzLayoutProps, type AuthzLayoutShellProps, type AuthzNodeType, type AuthzResourcesData, AuthzResourcesView, type AuthzRolesData, AuthzRolesView, AuthzUsageError, type AuthzUserId, type AuthzUserRolesData, AuthzUserRolesView, type CreateAuthzAdminAppOptions, type CreateAuthzAdminServerOptions, type EffectivePermissionsQuery, ErrorAlert, Field, type MyPermissionGroupItem, MyPermissionGroupStatus, type MyPermissionGroupStatusProps, MyPermissionIndicator, type MyPermissionIndicatorProps, MyPermissionStatus, type MyPermissionStatusProps, type PartialAuthzAdminLabels, type PermState, type PermissionView, type PermissionViewMap, type RequirePermissionOptions, type RequirePermissionResult, type ResourceDefinition, type ResourceDefinitionInput, type ResourceRegistry, type UsePermission, createAuthz, createAuthzAdminApp, createAuthzAdminServer, defaultAuthzAdminLabels, defineResources, flattenGroupItems, formatResourceTooltip, getPermissionSummary, makeAuthzErrorBoundary, resolveLabels, resourceKeysOf, toPermissionView, ui, usePermission };
|