@aiquants/authz-react-router 0.7.2 → 0.8.1
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/README.md +59 -10
- package/dist/index.d.mts +573 -92
- package/dist/index.d.ts +573 -92
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2 -2
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -5
package/dist/index.d.mts
CHANGED
|
@@ -2,7 +2,7 @@ import * as react_router from 'react-router';
|
|
|
2
2
|
import * as react from 'react';
|
|
3
3
|
import { ReactNode, CSSProperties } from 'react';
|
|
4
4
|
import * as _aiquants_authz_core from '@aiquants/authz-core';
|
|
5
|
-
import { EffectivePermission, DenyInfo, AuthzAction, MergedScope, AuthzGrant,
|
|
5
|
+
import { EffectivePermission, DenyInfo, AuthzAction, MergedScope, AuthzGrant, AuthzRole, AuthzResource, AuthzUser, AuthzAssignment, AuthzGroupRoleAssignment, AuthzGroupSummary, AuthzAdminStore } from '@aiquants/authz-core';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* React Router (v7) adapter: binds `appKey` + the DI ports and exposes the loader/action authorization API.
|
|
@@ -24,9 +24,18 @@ type AuthzUserId = string | number;
|
|
|
24
24
|
declare class AuthzUsageError extends Error {
|
|
25
25
|
constructor(message: string);
|
|
26
26
|
}
|
|
27
|
-
/**
|
|
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
|
+
*/
|
|
28
36
|
type EffectivePermissionsQuery = {
|
|
29
37
|
userId: AuthzUserId | null;
|
|
38
|
+
tenantId: string;
|
|
30
39
|
groupIds?: (string | number)[];
|
|
31
40
|
appKey: string;
|
|
32
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. */
|
|
@@ -37,8 +46,38 @@ type AuthzConfig = {
|
|
|
37
46
|
appKey: string;
|
|
38
47
|
/** Resolve the acting user id from the request (cookie/session/openid → the consumer's user id). */
|
|
39
48
|
resolveUserId: (request: Request) => Awaitable<AuthzUserId | null | undefined>;
|
|
40
|
-
/**
|
|
41
|
-
|
|
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
|
+
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
|
+
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
|
+
resolveGroupIds?: (request: Request, tenantId: string) => Awaitable<(string | number)[] | null | undefined>;
|
|
42
81
|
/**
|
|
43
82
|
* Load effective permissions for (user, app, resources) — **one call, many resources** (typically
|
|
44
83
|
* `getEffectivePermissionsMany` from `@aiquants/authz-drizzle`). A key with no grants may be omitted or
|
|
@@ -46,11 +85,23 @@ type AuthzConfig = {
|
|
|
46
85
|
*/
|
|
47
86
|
getEffectivePermissions: (args: EffectivePermissionsQuery) => Awaitable<Record<string, EffectivePermission | null | undefined> | null | undefined>;
|
|
48
87
|
/**
|
|
49
|
-
* Optional: every resource key registered for this app
|
|
50
|
-
* `@aiquants/authz-drizzle
|
|
51
|
-
*
|
|
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
|
+
* 帰属証明を通った後にのみ呼ばれる (登録済みキーの集合自体がテナントの情報であるため)。
|
|
52
103
|
*/
|
|
53
|
-
listResourceKeys?: (request: Request) => Awaitable<readonly string[] | null | undefined>;
|
|
104
|
+
listResourceKeys?: (request: Request, tenantId: string) => Awaitable<readonly string[] | null | undefined>;
|
|
54
105
|
/** Default deny handler. If omitted, denies throw AuthzDeniedError (403). */
|
|
55
106
|
onDeny?: (info: DenyInfo) => void;
|
|
56
107
|
};
|
|
@@ -80,6 +131,8 @@ type PermissionView<K extends string = string> = {
|
|
|
80
131
|
/** Result of a successful {@link createAuthz} guard. ガード成功時の戻り値。 */
|
|
81
132
|
type RequirePermissionResult<K extends string = string> = {
|
|
82
133
|
userId: AuthzUserId | null;
|
|
134
|
+
/** The tenant the decision was made within (always present, never blank). 判定を行ったテナント。 */
|
|
135
|
+
tenantId: string;
|
|
83
136
|
/** Effective row/column scope for the guarded action — apply as WHERE / column mask. */
|
|
84
137
|
scope: MergedScope;
|
|
85
138
|
/** UI view derived from the **same** evaluation as the guard decision (no second lookup). */
|
|
@@ -113,10 +166,15 @@ type PermissionViewMap<K extends string> = string extends K ? Record<string, Per
|
|
|
113
166
|
declare function toPermissionView<K extends string>(resourceKey: K, perm: EffectivePermission | null | undefined): PermissionView<K>;
|
|
114
167
|
/**
|
|
115
168
|
* React Router adapter. Binds `appKey` and the DI deps, exposing:
|
|
116
|
-
* - `requirePermission(request, {resourceKey, action}, options?)` → `{ userId, scope, permission }` on allow
|
|
169
|
+
* - `requirePermission(request, {resourceKey, action}, options?)` → `{ userId, tenantId, scope, permission }` on allow
|
|
117
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.
|
|
118
174
|
* - `getMyPermissions(request, {resourceKeys})` → `Record<resourceKey, PermissionView>` for the UI,
|
|
119
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.
|
|
120
178
|
* `appKey` と DI ポートを束ね、ガードと自己権限取得の 2 面だけを公開するファクトリ。
|
|
121
179
|
*
|
|
122
180
|
* @returns The bound `requirePermission` / `getMyPermissions` pair. 結線済みの認可 API 一式。
|
|
@@ -136,7 +194,20 @@ declare function createAuthz(config: AuthzConfig): {
|
|
|
136
194
|
};
|
|
137
195
|
};
|
|
138
196
|
|
|
139
|
-
/**
|
|
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
|
+
*/
|
|
140
211
|
type AuthzAdminLabels = {
|
|
141
212
|
title: string;
|
|
142
213
|
myPermission: string;
|
|
@@ -148,6 +219,10 @@ type AuthzAdminLabels = {
|
|
|
148
219
|
group_roles: string;
|
|
149
220
|
graph: string;
|
|
150
221
|
};
|
|
222
|
+
/**
|
|
223
|
+
* Strings shared by every tab, including the tenant column / field every tenant-scoped table shows.
|
|
224
|
+
* 全タブ共通の文言 (テナント列・テナント入力欄を含む)。
|
|
225
|
+
*/
|
|
151
226
|
common: {
|
|
152
227
|
add: string;
|
|
153
228
|
save: string;
|
|
@@ -159,6 +234,9 @@ type AuthzAdminLabels = {
|
|
|
159
234
|
active: string;
|
|
160
235
|
inactive: string;
|
|
161
236
|
optional: string;
|
|
237
|
+
tenant: string;
|
|
238
|
+
tenantHint: string;
|
|
239
|
+
unknownTenant: string;
|
|
162
240
|
};
|
|
163
241
|
roles: {
|
|
164
242
|
heading: string;
|
|
@@ -247,13 +325,31 @@ type PartialAuthzAdminLabels = {
|
|
|
247
325
|
error?: Partial<AuthzAdminLabels["error"]>;
|
|
248
326
|
warn?: Partial<AuthzAdminLabels["warn"]>;
|
|
249
327
|
};
|
|
250
|
-
/**
|
|
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
|
+
*/
|
|
251
340
|
declare function resolveLabels(over?: PartialAuthzAdminLabels): AuthzAdminLabels;
|
|
252
341
|
|
|
253
342
|
type WithLabels = {
|
|
254
343
|
labels: AuthzAdminLabels;
|
|
255
344
|
};
|
|
256
|
-
|
|
345
|
+
/**
|
|
346
|
+
* Loader payload of any tenant-scoped tab: the tenant every row on screen was loaded for.
|
|
347
|
+
* テナント単位タブの loader ペイロード共通部 (画面上の全行を読み込んだテナント)。
|
|
348
|
+
*/
|
|
349
|
+
type WithTenant = {
|
|
350
|
+
tenantId: string;
|
|
351
|
+
};
|
|
352
|
+
type AuthzLayoutData = WithLabels & WithTenant & {
|
|
257
353
|
myPermissions: Record<string, PermissionView | undefined>;
|
|
258
354
|
adminResourceKey: string;
|
|
259
355
|
basePath?: string;
|
|
@@ -271,56 +367,124 @@ type AuthzLayoutProps = {
|
|
|
271
367
|
annotation: React.ReactNode;
|
|
272
368
|
}) => React.ReactNode;
|
|
273
369
|
};
|
|
274
|
-
/**
|
|
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
|
+
*/
|
|
275
377
|
declare function AuthzLayout({ renderHeader }?: AuthzLayoutProps): react.JSX.Element;
|
|
276
378
|
/**
|
|
277
|
-
*
|
|
278
|
-
*
|
|
279
|
-
*
|
|
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. そのラベルを束縛したエラー境界コンポーネント。
|
|
280
389
|
*/
|
|
281
390
|
declare function makeAuthzErrorBoundary(over?: PartialAuthzAdminLabels): () => React.ReactElement;
|
|
282
|
-
/**
|
|
391
|
+
/**
|
|
392
|
+
* The error boundary bound to the package's English default labels.
|
|
393
|
+
* 英語 (既定ラベル) のエラー境界。i18n する場合は {@link makeAuthzErrorBoundary} を使う形。
|
|
394
|
+
*/
|
|
283
395
|
declare const AuthzErrorBoundary: () => React.ReactElement;
|
|
284
|
-
type AuthzRolesData = WithLabels & {
|
|
396
|
+
type AuthzRolesData = WithLabels & WithTenant & {
|
|
285
397
|
roles: AuthzRole[];
|
|
286
398
|
selfAdminRoleIds?: number[];
|
|
287
399
|
};
|
|
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
|
+
*/
|
|
288
410
|
declare function AuthzRolesView(): react.JSX.Element;
|
|
289
|
-
type AuthzResourcesData = WithLabels & {
|
|
411
|
+
type AuthzResourcesData = WithLabels & WithTenant & {
|
|
290
412
|
resources: AuthzResource[];
|
|
291
413
|
};
|
|
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
|
+
*/
|
|
292
423
|
declare function AuthzResourcesView(): react.JSX.Element;
|
|
293
|
-
|
|
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
|
+
type AuthzGrantsData = WithLabels & WithTenant & {
|
|
294
431
|
grants: AuthzGrant[];
|
|
295
|
-
roles:
|
|
296
|
-
|
|
297
|
-
roleKey: string;
|
|
298
|
-
}>;
|
|
299
|
-
resources: Array<{
|
|
300
|
-
id: number;
|
|
301
|
-
appKey: string;
|
|
302
|
-
resourceKey: string;
|
|
303
|
-
}>;
|
|
432
|
+
roles: AuthzRole[];
|
|
433
|
+
resources: AuthzResource[];
|
|
304
434
|
};
|
|
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
|
+
*/
|
|
305
446
|
declare function AuthzGrantsView(): react.JSX.Element;
|
|
306
|
-
|
|
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
|
+
type AuthzUserRolesData = WithLabels & WithTenant & {
|
|
307
453
|
assignments: AuthzAssignment[];
|
|
308
|
-
roles:
|
|
309
|
-
id: number;
|
|
310
|
-
roleKey: string;
|
|
311
|
-
}>;
|
|
454
|
+
roles: AuthzRole[];
|
|
312
455
|
users: AuthzUser[];
|
|
313
456
|
actorUserId?: number;
|
|
314
457
|
selfAdminRoleIds?: number[];
|
|
315
458
|
};
|
|
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
|
+
*/
|
|
316
469
|
declare function AuthzUserRolesView(): react.JSX.Element;
|
|
317
|
-
type AuthzGroupRolesData = WithLabels & {
|
|
470
|
+
type AuthzGroupRolesData = WithLabels & WithTenant & {
|
|
318
471
|
groupRoles: AuthzGroupRoleAssignment[];
|
|
319
472
|
roles: AuthzRole[];
|
|
320
473
|
groups: AuthzGroupSummary[];
|
|
321
474
|
};
|
|
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
|
+
*/
|
|
322
486
|
declare function AuthzGroupRolesView(): react.JSX.Element;
|
|
323
|
-
type AuthzGraphData = WithLabels & {
|
|
487
|
+
type AuthzGraphData = WithLabels & WithTenant & {
|
|
324
488
|
users: AuthzUser[];
|
|
325
489
|
roles: AuthzRole[];
|
|
326
490
|
resources: AuthzResource[];
|
|
@@ -330,6 +494,16 @@ type AuthzGraphData = WithLabels & {
|
|
|
330
494
|
groups?: AuthzGroupSummary[];
|
|
331
495
|
};
|
|
332
496
|
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
|
+
*/
|
|
333
507
|
declare function AuthzGraphView(): react.JSX.Element;
|
|
334
508
|
type AuthzAdminAppViewProps = {
|
|
335
509
|
renderHeader?: (props: {
|
|
@@ -338,9 +512,15 @@ type AuthzAdminAppViewProps = {
|
|
|
338
512
|
}) => React.ReactNode;
|
|
339
513
|
};
|
|
340
514
|
/**
|
|
341
|
-
*
|
|
342
|
-
*
|
|
343
|
-
*
|
|
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. 要求セグメントに対応する管理画面。
|
|
344
524
|
*/
|
|
345
525
|
declare function AuthzAdminAppView({ renderHeader }?: AuthzAdminAppViewProps): react.JSX.Element;
|
|
346
526
|
|
|
@@ -351,6 +531,19 @@ type PermissionQuery = {
|
|
|
351
531
|
resourceKey: string;
|
|
352
532
|
action: AuthzAction;
|
|
353
533
|
};
|
|
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
|
+
type AuthzAdminContext = {
|
|
544
|
+
tenantId: string;
|
|
545
|
+
userId: string | number;
|
|
546
|
+
};
|
|
354
547
|
type CreateAuthzAdminServerOptions = {
|
|
355
548
|
store: AuthzAdminStore;
|
|
356
549
|
/** 管理画面のガード資源キー(既定 `authz_admin`)。 */
|
|
@@ -358,39 +551,101 @@ type CreateAuthzAdminServerOptions = {
|
|
|
358
551
|
/** 未ログインをログインへ誘導する(例: throw redirect(...))。 */
|
|
359
552
|
requireUser: (request: Request) => Promise<unknown>;
|
|
360
553
|
/**
|
|
361
|
-
* Authorization guard supplied by the app (from `createAuthz`); allow → `{ userId, permission }`.
|
|
362
|
-
* 認可ガード (アプリの createAuthz 由来)。allow で { userId, permission } を返すポート。
|
|
554
|
+
* Authorization guard supplied by the app (from `createAuthz`); allow → `{ userId, tenantId, permission }`.
|
|
555
|
+
* 認可ガード (アプリの createAuthz 由来)。allow で { userId, tenantId, permission } を返すポート。
|
|
363
556
|
* `userId` は nullable(未解決/万一の public 付与)であり、createAuthzAdminServer 内で deny する
|
|
364
557
|
* (管理経路は監査・自己権限計算に実 id が必須のため非 null を保証)。
|
|
558
|
+
* `tenantId` は **ガードが判定に使ったテナントそのもの**。ここで捨てて画面側が別経路で引き直すと、
|
|
559
|
+
* 「A テナントの権限で B テナントを編集できる」という越境が構造的に開く。
|
|
365
560
|
* `permission` は **同一判定から導かれた** 自己権限ビューであり、表示用に再取得しない
|
|
366
561
|
* (再取得は「ガードは通るのにバッジは権限なし」という乖離の温床)。
|
|
367
562
|
*/
|
|
368
563
|
requirePermission: (request: Request, query: PermissionQuery) => Promise<{
|
|
369
564
|
userId: string | number | null;
|
|
565
|
+
tenantId: string;
|
|
370
566
|
permission: PermissionView;
|
|
371
567
|
}>;
|
|
372
568
|
/** 文言の部分上書き(既定は日本語)。 */
|
|
373
569
|
labels?: PartialAuthzAdminLabels;
|
|
374
570
|
};
|
|
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
|
+
*/
|
|
375
596
|
declare function createAuthzAdminServer(opts: CreateAuthzAdminServerOptions): {
|
|
376
597
|
/** 露出: スプラットマウント(app.ts)がガードを 1 回だけ行うために使う。 */
|
|
377
598
|
labels: AuthzAdminLabels;
|
|
378
599
|
resourceKey: string;
|
|
379
|
-
layoutGuard: (request: Request) => Promise<{
|
|
380
|
-
userId: string | number;
|
|
600
|
+
layoutGuard: (request: Request) => Promise<AuthzAdminContext & {
|
|
381
601
|
myPermissions: Record<string, PermissionView | undefined>;
|
|
382
602
|
}>;
|
|
383
603
|
/** /authz レイアウト: requireUser(302) → requirePermission(read, 403)。自己権限はガードの戻り値から得る。 */
|
|
384
604
|
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
|
+
*/
|
|
385
613
|
loader({ request }: Req): Promise<AuthzLayoutData>;
|
|
386
614
|
};
|
|
387
615
|
/** /authz index → roles へ。 */
|
|
388
616
|
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
|
+
*/
|
|
389
624
|
loader(): never;
|
|
390
625
|
};
|
|
391
626
|
roles: {
|
|
392
|
-
data: (
|
|
627
|
+
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
|
+
*/
|
|
393
636
|
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
|
+
*/
|
|
394
649
|
action({ request }: Req): Promise<react_router.UNSAFE_DataWithResponseInit<{
|
|
395
650
|
error: string;
|
|
396
651
|
}> | {
|
|
@@ -398,8 +653,28 @@ declare function createAuthzAdminServer(opts: CreateAuthzAdminServerOptions): {
|
|
|
398
653
|
}>;
|
|
399
654
|
};
|
|
400
655
|
resources: {
|
|
401
|
-
data: () => Promise<AuthzResourcesData>;
|
|
656
|
+
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
|
+
*/
|
|
402
665
|
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
|
+
*/
|
|
403
678
|
action({ request }: Req): Promise<react_router.UNSAFE_DataWithResponseInit<{
|
|
404
679
|
error: string;
|
|
405
680
|
}> | {
|
|
@@ -407,8 +682,29 @@ declare function createAuthzAdminServer(opts: CreateAuthzAdminServerOptions): {
|
|
|
407
682
|
}>;
|
|
408
683
|
};
|
|
409
684
|
grants: {
|
|
410
|
-
data: () => Promise<AuthzGrantsData>;
|
|
685
|
+
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
|
+
*/
|
|
411
694
|
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
|
+
*/
|
|
412
708
|
action({ request }: Req): Promise<react_router.UNSAFE_DataWithResponseInit<{
|
|
413
709
|
error: string;
|
|
414
710
|
}> | {
|
|
@@ -416,8 +712,29 @@ declare function createAuthzAdminServer(opts: CreateAuthzAdminServerOptions): {
|
|
|
416
712
|
}>;
|
|
417
713
|
};
|
|
418
714
|
userRoles: {
|
|
419
|
-
data: (
|
|
715
|
+
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
|
+
*/
|
|
420
724
|
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
|
+
*/
|
|
421
738
|
action({ request }: Req): Promise<react_router.UNSAFE_DataWithResponseInit<{
|
|
422
739
|
error: string;
|
|
423
740
|
}> | {
|
|
@@ -425,8 +742,28 @@ declare function createAuthzAdminServer(opts: CreateAuthzAdminServerOptions): {
|
|
|
425
742
|
}>;
|
|
426
743
|
};
|
|
427
744
|
groupRoles: {
|
|
428
|
-
data: () => Promise<AuthzGroupRolesData>;
|
|
745
|
+
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
|
+
*/
|
|
429
754
|
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
|
+
*/
|
|
430
767
|
action({ request }: Req): Promise<react_router.UNSAFE_DataWithResponseInit<{
|
|
431
768
|
error: string;
|
|
432
769
|
}> | {
|
|
@@ -434,7 +771,15 @@ declare function createAuthzAdminServer(opts: CreateAuthzAdminServerOptions): {
|
|
|
434
771
|
}>;
|
|
435
772
|
};
|
|
436
773
|
graph: {
|
|
437
|
-
data: () => Promise<AuthzGraphData>;
|
|
774
|
+
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
|
+
*/
|
|
438
783
|
loader({ request }: Req): Promise<AuthzGraphData>;
|
|
439
784
|
};
|
|
440
785
|
};
|
|
@@ -456,6 +801,7 @@ type CreateAuthzAdminAppOptions = CreateAuthzAdminServerOptions & {
|
|
|
456
801
|
declare function createAuthzAdminApp(opts: CreateAuthzAdminAppOptions): {
|
|
457
802
|
loader: (args: RouteArgs) => Promise<{
|
|
458
803
|
labels: AuthzAdminLabels;
|
|
804
|
+
tenantId: string;
|
|
459
805
|
roles: _aiquants_authz_core.AuthzRole[];
|
|
460
806
|
selfAdminRoleIds?: number[];
|
|
461
807
|
segment: string;
|
|
@@ -464,6 +810,7 @@ declare function createAuthzAdminApp(opts: CreateAuthzAdminAppOptions): {
|
|
|
464
810
|
adminResourceKey: string;
|
|
465
811
|
} | {
|
|
466
812
|
labels: AuthzAdminLabels;
|
|
813
|
+
tenantId: string;
|
|
467
814
|
resources: _aiquants_authz_core.AuthzResource[];
|
|
468
815
|
segment: string;
|
|
469
816
|
basePath: string;
|
|
@@ -471,36 +818,7 @@ declare function createAuthzAdminApp(opts: CreateAuthzAdminAppOptions): {
|
|
|
471
818
|
adminResourceKey: string;
|
|
472
819
|
} | {
|
|
473
820
|
labels: AuthzAdminLabels;
|
|
474
|
-
|
|
475
|
-
roles: Array<{
|
|
476
|
-
id: number;
|
|
477
|
-
roleKey: string;
|
|
478
|
-
}>;
|
|
479
|
-
resources: Array<{
|
|
480
|
-
id: number;
|
|
481
|
-
appKey: string;
|
|
482
|
-
resourceKey: string;
|
|
483
|
-
}>;
|
|
484
|
-
segment: string;
|
|
485
|
-
basePath: string;
|
|
486
|
-
myPermissions: Record<string, PermissionView | undefined>;
|
|
487
|
-
adminResourceKey: string;
|
|
488
|
-
} | {
|
|
489
|
-
labels: AuthzAdminLabels;
|
|
490
|
-
assignments: _aiquants_authz_core.AuthzAssignment[];
|
|
491
|
-
roles: Array<{
|
|
492
|
-
id: number;
|
|
493
|
-
roleKey: string;
|
|
494
|
-
}>;
|
|
495
|
-
users: _aiquants_authz_core.AuthzUser[];
|
|
496
|
-
actorUserId?: number;
|
|
497
|
-
selfAdminRoleIds?: number[];
|
|
498
|
-
segment: string;
|
|
499
|
-
basePath: string;
|
|
500
|
-
myPermissions: Record<string, PermissionView | undefined>;
|
|
501
|
-
adminResourceKey: string;
|
|
502
|
-
} | {
|
|
503
|
-
labels: AuthzAdminLabels;
|
|
821
|
+
tenantId: string;
|
|
504
822
|
groupRoles: _aiquants_authz_core.AuthzGroupRoleAssignment[];
|
|
505
823
|
roles: _aiquants_authz_core.AuthzRole[];
|
|
506
824
|
groups: _aiquants_authz_core.AuthzGroupSummary[];
|
|
@@ -513,8 +831,7 @@ declare function createAuthzAdminApp(opts: CreateAuthzAdminAppOptions): {
|
|
|
513
831
|
server: {
|
|
514
832
|
labels: AuthzAdminLabels;
|
|
515
833
|
resourceKey: string;
|
|
516
|
-
layoutGuard: (request: Request) => Promise<{
|
|
517
|
-
userId: string | number;
|
|
834
|
+
layoutGuard: (request: Request) => Promise<AuthzAdminContext & {
|
|
518
835
|
myPermissions: Record<string, PermissionView | undefined>;
|
|
519
836
|
}>;
|
|
520
837
|
layout: {
|
|
@@ -526,7 +843,7 @@ declare function createAuthzAdminApp(opts: CreateAuthzAdminAppOptions): {
|
|
|
526
843
|
loader(): never;
|
|
527
844
|
};
|
|
528
845
|
roles: {
|
|
529
|
-
data: (
|
|
846
|
+
data: (ctx: AuthzAdminContext) => Promise<AuthzRolesData>;
|
|
530
847
|
loader({ request }: {
|
|
531
848
|
request: Request;
|
|
532
849
|
}): Promise<AuthzRolesData>;
|
|
@@ -539,7 +856,7 @@ declare function createAuthzAdminApp(opts: CreateAuthzAdminAppOptions): {
|
|
|
539
856
|
}>;
|
|
540
857
|
};
|
|
541
858
|
resources: {
|
|
542
|
-
data: () => Promise<AuthzResourcesData>;
|
|
859
|
+
data: (ctx: AuthzAdminContext) => Promise<AuthzResourcesData>;
|
|
543
860
|
loader({ request }: {
|
|
544
861
|
request: Request;
|
|
545
862
|
}): Promise<AuthzResourcesData>;
|
|
@@ -552,7 +869,7 @@ declare function createAuthzAdminApp(opts: CreateAuthzAdminAppOptions): {
|
|
|
552
869
|
}>;
|
|
553
870
|
};
|
|
554
871
|
grants: {
|
|
555
|
-
data: () => Promise<AuthzGrantsData>;
|
|
872
|
+
data: (ctx: AuthzAdminContext) => Promise<AuthzGrantsData>;
|
|
556
873
|
loader({ request }: {
|
|
557
874
|
request: Request;
|
|
558
875
|
}): Promise<AuthzGrantsData>;
|
|
@@ -565,7 +882,7 @@ declare function createAuthzAdminApp(opts: CreateAuthzAdminAppOptions): {
|
|
|
565
882
|
}>;
|
|
566
883
|
};
|
|
567
884
|
userRoles: {
|
|
568
|
-
data: (
|
|
885
|
+
data: (ctx: AuthzAdminContext) => Promise<AuthzUserRolesData>;
|
|
569
886
|
loader({ request }: {
|
|
570
887
|
request: Request;
|
|
571
888
|
}): Promise<AuthzUserRolesData>;
|
|
@@ -578,7 +895,7 @@ declare function createAuthzAdminApp(opts: CreateAuthzAdminAppOptions): {
|
|
|
578
895
|
}>;
|
|
579
896
|
};
|
|
580
897
|
groupRoles: {
|
|
581
|
-
data: () => Promise<AuthzGroupRolesData>;
|
|
898
|
+
data: (ctx: AuthzAdminContext) => Promise<AuthzGroupRolesData>;
|
|
582
899
|
loader({ request }: {
|
|
583
900
|
request: Request;
|
|
584
901
|
}): Promise<AuthzGroupRolesData>;
|
|
@@ -591,7 +908,7 @@ declare function createAuthzAdminApp(opts: CreateAuthzAdminAppOptions): {
|
|
|
591
908
|
}>;
|
|
592
909
|
};
|
|
593
910
|
graph: {
|
|
594
|
-
data: () => Promise<AuthzGraphData>;
|
|
911
|
+
data: (ctx: AuthzAdminContext) => Promise<AuthzGraphData>;
|
|
595
912
|
loader({ request }: {
|
|
596
913
|
request: Request;
|
|
597
914
|
}): Promise<AuthzGraphData>;
|
|
@@ -599,17 +916,181 @@ declare function createAuthzAdminApp(opts: CreateAuthzAdminAppOptions): {
|
|
|
599
916
|
};
|
|
600
917
|
};
|
|
601
918
|
|
|
602
|
-
declare const ui: Record<string, CSSProperties>;
|
|
603
919
|
/**
|
|
604
|
-
*
|
|
605
|
-
*
|
|
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
|
+
declare const ui: {
|
|
929
|
+
page: {
|
|
930
|
+
padding: string;
|
|
931
|
+
maxWidth: number;
|
|
932
|
+
margin: string;
|
|
933
|
+
color: "#0f172a";
|
|
934
|
+
};
|
|
935
|
+
tableContainer: {
|
|
936
|
+
width: string;
|
|
937
|
+
overflowX: "auto";
|
|
938
|
+
marginBottom: string;
|
|
939
|
+
WebkitOverflowScrolling: "touch";
|
|
940
|
+
};
|
|
941
|
+
table: {
|
|
942
|
+
borderCollapse: "collapse";
|
|
943
|
+
width: string;
|
|
944
|
+
fontSize: string;
|
|
945
|
+
tableLayout: "fixed";
|
|
946
|
+
};
|
|
947
|
+
th: {
|
|
948
|
+
textAlign: "left";
|
|
949
|
+
borderBottom: string;
|
|
950
|
+
padding: string;
|
|
951
|
+
fontSize: string;
|
|
952
|
+
color: "#475569";
|
|
953
|
+
fontWeight: number;
|
|
954
|
+
textTransform: "uppercase";
|
|
955
|
+
letterSpacing: string;
|
|
956
|
+
};
|
|
957
|
+
td: {
|
|
958
|
+
borderBottom: string;
|
|
959
|
+
padding: string;
|
|
960
|
+
verticalAlign: string;
|
|
961
|
+
wordBreak: "break-all";
|
|
962
|
+
};
|
|
963
|
+
input: {
|
|
964
|
+
padding: string;
|
|
965
|
+
border: string;
|
|
966
|
+
borderRadius: number;
|
|
967
|
+
fontSize: string;
|
|
968
|
+
background: string;
|
|
969
|
+
width: string;
|
|
970
|
+
boxSizing: "border-box";
|
|
971
|
+
};
|
|
972
|
+
select: {
|
|
973
|
+
padding: string;
|
|
974
|
+
border: string;
|
|
975
|
+
borderRadius: number;
|
|
976
|
+
fontSize: string;
|
|
977
|
+
background: string;
|
|
978
|
+
width: string;
|
|
979
|
+
boxSizing: "border-box";
|
|
980
|
+
};
|
|
981
|
+
textarea: {
|
|
982
|
+
padding: string;
|
|
983
|
+
border: string;
|
|
984
|
+
borderRadius: number;
|
|
985
|
+
fontSize: string;
|
|
986
|
+
fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace";
|
|
987
|
+
minHeight: string;
|
|
988
|
+
resize: "vertical";
|
|
989
|
+
width: string;
|
|
990
|
+
boxSizing: "border-box";
|
|
991
|
+
};
|
|
992
|
+
button: {
|
|
993
|
+
padding: string;
|
|
994
|
+
border: string;
|
|
995
|
+
borderRadius: number;
|
|
996
|
+
background: string;
|
|
997
|
+
cursor: "pointer";
|
|
998
|
+
fontSize: string;
|
|
999
|
+
color: "#334155";
|
|
1000
|
+
};
|
|
1001
|
+
save: {
|
|
1002
|
+
padding: string;
|
|
1003
|
+
border: string;
|
|
1004
|
+
borderRadius: number;
|
|
1005
|
+
background: string;
|
|
1006
|
+
cursor: "pointer";
|
|
1007
|
+
fontSize: string;
|
|
1008
|
+
color: "#2563eb";
|
|
1009
|
+
fontWeight: number;
|
|
1010
|
+
};
|
|
1011
|
+
danger: {
|
|
1012
|
+
padding: string;
|
|
1013
|
+
border: string;
|
|
1014
|
+
borderRadius: number;
|
|
1015
|
+
background: string;
|
|
1016
|
+
cursor: "pointer";
|
|
1017
|
+
fontSize: string;
|
|
1018
|
+
color: "#dc2626";
|
|
1019
|
+
};
|
|
1020
|
+
primary: {
|
|
1021
|
+
padding: string;
|
|
1022
|
+
border: string;
|
|
1023
|
+
borderRadius: number;
|
|
1024
|
+
background: string;
|
|
1025
|
+
color: "#fff";
|
|
1026
|
+
cursor: "pointer";
|
|
1027
|
+
fontSize: string;
|
|
1028
|
+
fontWeight: number;
|
|
1029
|
+
alignSelf: "flex-start";
|
|
1030
|
+
};
|
|
1031
|
+
card: {
|
|
1032
|
+
display: "flex";
|
|
1033
|
+
flexDirection: "column";
|
|
1034
|
+
gap: string;
|
|
1035
|
+
maxWidth: number;
|
|
1036
|
+
marginTop: string;
|
|
1037
|
+
padding: string;
|
|
1038
|
+
border: string;
|
|
1039
|
+
borderRadius: number;
|
|
1040
|
+
background: string;
|
|
1041
|
+
};
|
|
1042
|
+
code: {
|
|
1043
|
+
fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace";
|
|
1044
|
+
fontSize: string;
|
|
1045
|
+
color: "#334155";
|
|
1046
|
+
wordBreak: "break-all";
|
|
1047
|
+
};
|
|
1048
|
+
muted: {
|
|
1049
|
+
color: "#94a3b8";
|
|
1050
|
+
};
|
|
1051
|
+
h2: {
|
|
1052
|
+
fontSize: string;
|
|
1053
|
+
margin: string;
|
|
1054
|
+
fontWeight: number;
|
|
1055
|
+
};
|
|
1056
|
+
h3: {
|
|
1057
|
+
fontSize: string;
|
|
1058
|
+
margin: string;
|
|
1059
|
+
color: "#334155";
|
|
1060
|
+
fontWeight: number;
|
|
1061
|
+
};
|
|
1062
|
+
note: {
|
|
1063
|
+
color: "#64748b";
|
|
1064
|
+
fontSize: string;
|
|
1065
|
+
margin: string;
|
|
1066
|
+
};
|
|
1067
|
+
empty: {
|
|
1068
|
+
color: "#94a3b8";
|
|
1069
|
+
padding: string;
|
|
1070
|
+
};
|
|
1071
|
+
};
|
|
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. 縦積みされたフィールド。
|
|
606
1081
|
*/
|
|
607
1082
|
declare function Field({ label, hint, children }: {
|
|
608
1083
|
label: string;
|
|
609
1084
|
hint?: string;
|
|
610
1085
|
children: ReactNode;
|
|
611
1086
|
}): react.JSX.Element;
|
|
612
|
-
/**
|
|
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
|
+
*/
|
|
613
1094
|
declare function ErrorAlert({ message }: {
|
|
614
1095
|
message?: string;
|
|
615
1096
|
}): react.JSX.Element | null;
|
|
@@ -826,4 +1307,4 @@ type UsePermission = {
|
|
|
826
1307
|
*/
|
|
827
1308
|
declare function usePermission(view: PermissionView | null | undefined): UsePermission;
|
|
828
1309
|
|
|
829
|
-
export { AuthzAdminAppView, type AuthzAdminAppViewProps, 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 };
|
|
1310
|
+
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 };
|