@aiquants/authz-react-router 0.2.5 → 0.3.0
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 +13 -4
- package/dist/index.d.mts +56 -2
- package/dist/index.d.ts +56 -2
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -89,8 +89,14 @@ WHERE r.role_key='viewer';
|
|
|
89
89
|
|
|
90
90
|
```tsx
|
|
91
91
|
// loader: const myPermissions = await getMyPermissions(request, { resourceKeys: ["report"] })
|
|
92
|
-
import { MyPermissionIndicator } from "@aiquants/authz-react-router"
|
|
93
|
-
|
|
92
|
+
import { MyPermissionIndicator, MyPermissionStatus } from "@aiquants/authz-react-router"
|
|
93
|
+
|
|
94
|
+
// 1. Single indicator badge group
|
|
95
|
+
<MyPermissionIndicator permission={myPermissions.report} resourceName="月次レポート" />
|
|
96
|
+
|
|
97
|
+
// 2. Full "Your Permissions" status bar component for any page header/toolbar
|
|
98
|
+
<MyPermissionStatus permission={myPermissions.report} resourceName="月次レポート" />
|
|
99
|
+
// → "あなたの権限: [閲覧○][編集△][削除×]" with tooltip "対象リソース: 月次レポート (report)"
|
|
94
100
|
```
|
|
95
101
|
|
|
96
102
|
## Scope cheat-sheet (§3.2)
|
|
@@ -108,12 +114,15 @@ Multiple roles **union** (wider wins): rows OR'd (any `NULL` ⇒ all rows); colu
|
|
|
108
114
|
|
|
109
115
|
## API
|
|
110
116
|
|
|
111
|
-
- `createAuthz({ appKey, resolveUserId, getEffectivePermissions, onDeny? })` → `{ requirePermission, getMyPermissions }`.
|
|
117
|
+
- `createAuthz({ appKey, resolveUserId, getEffectivePermissions, onDeny? })` → `{ requirePermission, getMyPermissions, requireAndGetPermission }`.
|
|
112
118
|
- `requirePermission(request, {resourceKey, action}, options?)` → `{ userId, scope }` on allow (so loaders apply row WHERE / column mask — not just 403). Denies throw `AuthzDeniedError` (403), or `throw redirect(options.failureRedirect)` when set.
|
|
119
|
+
- `requireAndGetPermission(request, {resourceKey, action}, options?)` → `{ userId, scope, permission }`. Atomically performs guard and fetches matching UI `PermissionView` to prevent page-resource mismatches.
|
|
120
|
+
- `defineResources({ ... })` → Type-safe centralized resource registry helper for resource keys and display names.
|
|
113
121
|
- `getMyPermissions(request, {resourceKeys})` → `Record<resourceKey, PermissionView>` for the UI.
|
|
114
122
|
- `toPermissionView(resourceKey, perm)` → serializable view (loader → client).
|
|
115
123
|
- `usePermission(view)` → ○△× display states (`readState`/`writeState`/`deleteState`); pure, safe in render.
|
|
116
|
-
- `<MyPermissionIndicator permission={view} />` → read / write(create∪update) / delete as ○△×. `read` is △ when row/column-restricted; `write` is ○ only when both create & update are held, △ when one.
|
|
124
|
+
- `<MyPermissionIndicator permission={view} resourceName="文書管理" expectedResourceKey="documents" />` → read / write(create∪update) / delete as ○△×. `read` is △ when row/column-restricted; `write` is ○ only when both create & update are held, △ when one. Hover shows resource name & key tooltip. Automatically flags mismatches if `permission.resourceKey !== expectedResourceKey`.
|
|
125
|
+
- `<MyPermissionStatus permission={view} resourceName="文書管理" expectedResourceKey="documents" prefixLabel="あなたの権限" />` → Reusable status component combining prefix label and permission indicator badges for any application page.
|
|
117
126
|
|
|
118
127
|
## Demo App
|
|
119
128
|
|
package/dist/index.d.mts
CHANGED
|
@@ -53,6 +53,12 @@ declare function createAuthz(config: AuthzConfig): {
|
|
|
53
53
|
getMyPermissions: (request: Request, query: {
|
|
54
54
|
resourceKeys: string[];
|
|
55
55
|
}) => Promise<Record<string, PermissionView>>;
|
|
56
|
+
requireAndGetPermission: (request: Request, query: {
|
|
57
|
+
resourceKey: string;
|
|
58
|
+
action: AuthzAction;
|
|
59
|
+
}, options?: RequirePermissionOptions) => Promise<GuardResult<AuthzUserId> & {
|
|
60
|
+
permission: PermissionView;
|
|
61
|
+
}>;
|
|
56
62
|
};
|
|
57
63
|
|
|
58
64
|
/** Authz admin UI strings (i18n). Defaults are English; override per-section via `createAuthzAdminRoutes(..., { labels })`. */
|
|
@@ -121,6 +127,7 @@ type AuthzAdminLabels = {
|
|
|
121
127
|
};
|
|
122
128
|
userRoles: {
|
|
123
129
|
heading: string;
|
|
130
|
+
note: string;
|
|
124
131
|
user: string;
|
|
125
132
|
role: string;
|
|
126
133
|
empty: string;
|
|
@@ -444,6 +451,12 @@ declare function ErrorAlert({ message }: {
|
|
|
444
451
|
|
|
445
452
|
type MyPermissionIndicatorProps = {
|
|
446
453
|
permission: PermissionView | null | undefined;
|
|
454
|
+
/** Human-readable resource display name (e.g. "文書データ"). Falls back to permission.resourceKey. */
|
|
455
|
+
resourceName?: string;
|
|
456
|
+
/** Expected resource key to detect mismatches with permission.resourceKey during development. */
|
|
457
|
+
expectedResourceKey?: string;
|
|
458
|
+
/** Whether to include resource name/key tooltip. Default true. */
|
|
459
|
+
showResourceTooltip?: boolean;
|
|
447
460
|
labels?: {
|
|
448
461
|
read?: string;
|
|
449
462
|
write?: string;
|
|
@@ -453,7 +466,48 @@ type MyPermissionIndicatorProps = {
|
|
|
453
466
|
showScopeSummary?: boolean;
|
|
454
467
|
className?: string;
|
|
455
468
|
};
|
|
456
|
-
|
|
469
|
+
type MyPermissionStatusProps = MyPermissionIndicatorProps & {
|
|
470
|
+
/** Label prefix shown before the indicator badges. Default: "あなたの権限" */
|
|
471
|
+
prefixLabel?: string;
|
|
472
|
+
/** Whether to display the prefix label. Default: true */
|
|
473
|
+
showPrefixLabel?: boolean;
|
|
474
|
+
/** Additional inline styles for wrapper element. */
|
|
475
|
+
style?: React.CSSProperties;
|
|
476
|
+
};
|
|
477
|
+
/**
|
|
478
|
+
* Format human-readable resource tooltip text.
|
|
479
|
+
* リソース表示名およびキーからツールチップ用テキストを生成。
|
|
480
|
+
*/
|
|
481
|
+
declare function formatResourceTooltip(resourceKey?: string, resourceName?: string): string | undefined;
|
|
482
|
+
/**
|
|
483
|
+
* Display permission indicator badges for read, write, and delete capabilities.
|
|
484
|
+
* 閲覧・編集・削除の権限状態バッジ群を描画。
|
|
485
|
+
*/
|
|
486
|
+
declare function MyPermissionIndicator({ permission, resourceName, expectedResourceKey, showResourceTooltip, labels, showScopeSummary, className, }: MyPermissionIndicatorProps): react.JSX.Element;
|
|
487
|
+
/**
|
|
488
|
+
* Reusable "Your Permissions" status bar component suitable for any application page.
|
|
489
|
+
* 「あなたの権限」ラベルと権限状態インジケータを束ねた再利用可能なコンポーネント。
|
|
490
|
+
*/
|
|
491
|
+
declare function MyPermissionStatus({ permission, resourceName, expectedResourceKey, prefixLabel, showPrefixLabel, showResourceTooltip, labels, showScopeSummary, className, style, }: MyPermissionStatusProps): react.JSX.Element;
|
|
492
|
+
|
|
493
|
+
/**
|
|
494
|
+
* Resource definition and registry utilities for preventing page-resource mismatches.
|
|
495
|
+
* ページとリソースの表示・権限食い違いを防止するためのリソースレジストリ定義。
|
|
496
|
+
*/
|
|
497
|
+
type ResourceDefinition = {
|
|
498
|
+
/** Unique resource key used in authorization rules (e.g. "documents") */
|
|
499
|
+
key: string;
|
|
500
|
+
/** Human-readable display name (e.g. "文書管理") */
|
|
501
|
+
name: string;
|
|
502
|
+
/** Optional description for administration UI */
|
|
503
|
+
description?: string;
|
|
504
|
+
};
|
|
505
|
+
type ResourceRegistry<T extends Record<string, ResourceDefinition>> = T;
|
|
506
|
+
/**
|
|
507
|
+
* Define type-safe resource registry for an application.
|
|
508
|
+
* アプリ全体のリソース定義(キー・表示名・説明)を一元管理するヘルパー。
|
|
509
|
+
*/
|
|
510
|
+
declare function defineResources<T extends Record<string, ResourceDefinition>>(resources: T): T;
|
|
457
511
|
|
|
458
512
|
type PermState = "full" | "partial" | "none";
|
|
459
513
|
type UsePermission = {
|
|
@@ -472,4 +526,4 @@ type UsePermission = {
|
|
|
472
526
|
*/
|
|
473
527
|
declare function usePermission(view: PermissionView | null | undefined): UsePermission;
|
|
474
528
|
|
|
475
|
-
export { AuthzAdminAppView, type AuthzAdminLabels, type AuthzConfig, AuthzErrorBoundary, type AuthzGrantsData, AuthzGrantsView, AuthzLayout, type AuthzLayoutData, type AuthzResourcesData, AuthzResourcesView, type AuthzRolesData, AuthzRolesView, type AuthzUserId, type AuthzUserRolesData, AuthzUserRolesView, type CreateAuthzAdminAppOptions, type CreateAuthzAdminServerOptions, ErrorAlert, Field, MyPermissionIndicator, type MyPermissionIndicatorProps, type PartialAuthzAdminLabels, type PermState, type PermissionView, type RequirePermissionOptions, type UsePermission, createAuthz, createAuthzAdminApp, createAuthzAdminServer, defaultAuthzAdminLabels, makeAuthzErrorBoundary, resolveLabels, toPermissionView, ui, usePermission };
|
|
529
|
+
export { AuthzAdminAppView, type AuthzAdminLabels, type AuthzConfig, AuthzErrorBoundary, type AuthzGrantsData, AuthzGrantsView, AuthzLayout, type AuthzLayoutData, type AuthzResourcesData, AuthzResourcesView, type AuthzRolesData, AuthzRolesView, type AuthzUserId, type AuthzUserRolesData, AuthzUserRolesView, type CreateAuthzAdminAppOptions, type CreateAuthzAdminServerOptions, ErrorAlert, Field, MyPermissionIndicator, type MyPermissionIndicatorProps, MyPermissionStatus, type MyPermissionStatusProps, type PartialAuthzAdminLabels, type PermState, type PermissionView, type RequirePermissionOptions, type ResourceDefinition, type ResourceRegistry, type UsePermission, createAuthz, createAuthzAdminApp, createAuthzAdminServer, defaultAuthzAdminLabels, defineResources, formatResourceTooltip, makeAuthzErrorBoundary, resolveLabels, toPermissionView, ui, usePermission };
|
package/dist/index.d.ts
CHANGED
|
@@ -53,6 +53,12 @@ declare function createAuthz(config: AuthzConfig): {
|
|
|
53
53
|
getMyPermissions: (request: Request, query: {
|
|
54
54
|
resourceKeys: string[];
|
|
55
55
|
}) => Promise<Record<string, PermissionView>>;
|
|
56
|
+
requireAndGetPermission: (request: Request, query: {
|
|
57
|
+
resourceKey: string;
|
|
58
|
+
action: AuthzAction;
|
|
59
|
+
}, options?: RequirePermissionOptions) => Promise<GuardResult<AuthzUserId> & {
|
|
60
|
+
permission: PermissionView;
|
|
61
|
+
}>;
|
|
56
62
|
};
|
|
57
63
|
|
|
58
64
|
/** Authz admin UI strings (i18n). Defaults are English; override per-section via `createAuthzAdminRoutes(..., { labels })`. */
|
|
@@ -121,6 +127,7 @@ type AuthzAdminLabels = {
|
|
|
121
127
|
};
|
|
122
128
|
userRoles: {
|
|
123
129
|
heading: string;
|
|
130
|
+
note: string;
|
|
124
131
|
user: string;
|
|
125
132
|
role: string;
|
|
126
133
|
empty: string;
|
|
@@ -444,6 +451,12 @@ declare function ErrorAlert({ message }: {
|
|
|
444
451
|
|
|
445
452
|
type MyPermissionIndicatorProps = {
|
|
446
453
|
permission: PermissionView | null | undefined;
|
|
454
|
+
/** Human-readable resource display name (e.g. "文書データ"). Falls back to permission.resourceKey. */
|
|
455
|
+
resourceName?: string;
|
|
456
|
+
/** Expected resource key to detect mismatches with permission.resourceKey during development. */
|
|
457
|
+
expectedResourceKey?: string;
|
|
458
|
+
/** Whether to include resource name/key tooltip. Default true. */
|
|
459
|
+
showResourceTooltip?: boolean;
|
|
447
460
|
labels?: {
|
|
448
461
|
read?: string;
|
|
449
462
|
write?: string;
|
|
@@ -453,7 +466,48 @@ type MyPermissionIndicatorProps = {
|
|
|
453
466
|
showScopeSummary?: boolean;
|
|
454
467
|
className?: string;
|
|
455
468
|
};
|
|
456
|
-
|
|
469
|
+
type MyPermissionStatusProps = MyPermissionIndicatorProps & {
|
|
470
|
+
/** Label prefix shown before the indicator badges. Default: "あなたの権限" */
|
|
471
|
+
prefixLabel?: string;
|
|
472
|
+
/** Whether to display the prefix label. Default: true */
|
|
473
|
+
showPrefixLabel?: boolean;
|
|
474
|
+
/** Additional inline styles for wrapper element. */
|
|
475
|
+
style?: React.CSSProperties;
|
|
476
|
+
};
|
|
477
|
+
/**
|
|
478
|
+
* Format human-readable resource tooltip text.
|
|
479
|
+
* リソース表示名およびキーからツールチップ用テキストを生成。
|
|
480
|
+
*/
|
|
481
|
+
declare function formatResourceTooltip(resourceKey?: string, resourceName?: string): string | undefined;
|
|
482
|
+
/**
|
|
483
|
+
* Display permission indicator badges for read, write, and delete capabilities.
|
|
484
|
+
* 閲覧・編集・削除の権限状態バッジ群を描画。
|
|
485
|
+
*/
|
|
486
|
+
declare function MyPermissionIndicator({ permission, resourceName, expectedResourceKey, showResourceTooltip, labels, showScopeSummary, className, }: MyPermissionIndicatorProps): react.JSX.Element;
|
|
487
|
+
/**
|
|
488
|
+
* Reusable "Your Permissions" status bar component suitable for any application page.
|
|
489
|
+
* 「あなたの権限」ラベルと権限状態インジケータを束ねた再利用可能なコンポーネント。
|
|
490
|
+
*/
|
|
491
|
+
declare function MyPermissionStatus({ permission, resourceName, expectedResourceKey, prefixLabel, showPrefixLabel, showResourceTooltip, labels, showScopeSummary, className, style, }: MyPermissionStatusProps): react.JSX.Element;
|
|
492
|
+
|
|
493
|
+
/**
|
|
494
|
+
* Resource definition and registry utilities for preventing page-resource mismatches.
|
|
495
|
+
* ページとリソースの表示・権限食い違いを防止するためのリソースレジストリ定義。
|
|
496
|
+
*/
|
|
497
|
+
type ResourceDefinition = {
|
|
498
|
+
/** Unique resource key used in authorization rules (e.g. "documents") */
|
|
499
|
+
key: string;
|
|
500
|
+
/** Human-readable display name (e.g. "文書管理") */
|
|
501
|
+
name: string;
|
|
502
|
+
/** Optional description for administration UI */
|
|
503
|
+
description?: string;
|
|
504
|
+
};
|
|
505
|
+
type ResourceRegistry<T extends Record<string, ResourceDefinition>> = T;
|
|
506
|
+
/**
|
|
507
|
+
* Define type-safe resource registry for an application.
|
|
508
|
+
* アプリ全体のリソース定義(キー・表示名・説明)を一元管理するヘルパー。
|
|
509
|
+
*/
|
|
510
|
+
declare function defineResources<T extends Record<string, ResourceDefinition>>(resources: T): T;
|
|
457
511
|
|
|
458
512
|
type PermState = "full" | "partial" | "none";
|
|
459
513
|
type UsePermission = {
|
|
@@ -472,4 +526,4 @@ type UsePermission = {
|
|
|
472
526
|
*/
|
|
473
527
|
declare function usePermission(view: PermissionView | null | undefined): UsePermission;
|
|
474
528
|
|
|
475
|
-
export { AuthzAdminAppView, type AuthzAdminLabels, type AuthzConfig, AuthzErrorBoundary, type AuthzGrantsData, AuthzGrantsView, AuthzLayout, type AuthzLayoutData, type AuthzResourcesData, AuthzResourcesView, type AuthzRolesData, AuthzRolesView, type AuthzUserId, type AuthzUserRolesData, AuthzUserRolesView, type CreateAuthzAdminAppOptions, type CreateAuthzAdminServerOptions, ErrorAlert, Field, MyPermissionIndicator, type MyPermissionIndicatorProps, type PartialAuthzAdminLabels, type PermState, type PermissionView, type RequirePermissionOptions, type UsePermission, createAuthz, createAuthzAdminApp, createAuthzAdminServer, defaultAuthzAdminLabels, makeAuthzErrorBoundary, resolveLabels, toPermissionView, ui, usePermission };
|
|
529
|
+
export { AuthzAdminAppView, type AuthzAdminLabels, type AuthzConfig, AuthzErrorBoundary, type AuthzGrantsData, AuthzGrantsView, AuthzLayout, type AuthzLayoutData, type AuthzResourcesData, AuthzResourcesView, type AuthzRolesData, AuthzRolesView, type AuthzUserId, type AuthzUserRolesData, AuthzUserRolesView, type CreateAuthzAdminAppOptions, type CreateAuthzAdminServerOptions, ErrorAlert, Field, MyPermissionIndicator, type MyPermissionIndicatorProps, MyPermissionStatus, type MyPermissionStatusProps, type PartialAuthzAdminLabels, type PermState, type PermissionView, type RequirePermissionOptions, type ResourceDefinition, type ResourceRegistry, type UsePermission, createAuthz, createAuthzAdminApp, createAuthzAdminServer, defaultAuthzAdminLabels, defineResources, formatResourceTooltip, makeAuthzErrorBoundary, resolveLabels, toPermissionView, ui, usePermission };
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
"use strict";var E=Object.defineProperty;var Z=Object.getOwnPropertyDescriptor;var j=Object.getOwnPropertyNames;var X=Object.prototype.hasOwnProperty;var ee=(t,n)=>{for(var s in n)E(t,s,{get:n[s],enumerable:!0})},te=(t,n,s,d)=>{if(n&&typeof n=="object"||typeof n=="function")for(let o of j(n))!X.call(t,o)&&o!==s&&E(t,o,{get:()=>n[o],enumerable:!(d=Z(n,o))||d.enumerable});return t};var re=t=>te(E({},"__esModule",{value:!0}),t);var pe={};ee(pe,{AuthzAdminAppView:()=>ce,AuthzErrorBoundary:()=>le,AuthzGrantsView:()=>M,AuthzLayout:()=>ae,AuthzResourcesView:()=>B,AuthzRolesView:()=>q,AuthzUserRolesView:()=>O,ErrorAlert:()=>k,Field:()=>w,MyPermissionIndicator:()=>F,createAuthz:()=>me,createAuthzAdminApp:()=>oe,createAuthzAdminServer:()=>N,defaultAuthzAdminLabels:()=>W,makeAuthzErrorBoundary:()=>G,resolveLabels:()=>L,toPermissionView:()=>Q,ui:()=>r,usePermission:()=>U});module.exports=re(pe);var _=require("react-router");var v=require("@aiquants/authz-core"),A=require("react-router");var W={title:"Authorization (RBAC)",myPermission:"Your permissions",tabs:{roles:"Roles",resources:"Resources",role_permissions:"Permissions",user_roles:"User assignments"},common:{add:"Add",save:"Save",delete:"Delete",remove:"Remove",assign:"Assign",grant:"Grant",select:"Select\u2026",active:"\u25CB Enabled",inactive:"\xD7 Disabled",optional:"optional"},roles:{heading:"Roles (TMRole)",note:"Edit name / description inline and click Save (role_key is an immutable identifier).",roleKey:"role_key",name:"name",description:"description",activeHeader:"Active",empty:"No roles",newHeading:"New role",hintRoleKey:"e.g. admin"},resources:{heading:"Resources (TMResource)",note:"Edit name / description inline and click Save (app_key / resource_key are immutable identifiers).",appKey:"app_key",resourceKey:"resource_key",name:"name",description:"description",empty:"No resources",newHeading:"New resource",hintAppKey:"e.g. quants",hintResourceKey:"e.g. daily_report",hintDailyReport:"optional"},grants:{heading:"Permissions (TDRolePermission)",note:"Empty row_scope / column_scope = all rows / all columns (NULL). JSON must satisfy the \xA73.2 contract.",role:"role",resource:"resource",action:"action",rowScope:"row_scope",columnScope:"column_scope",empty:"No permissions",newHeading:"Grant a permission",rowScopeHint:"JSON / empty = all rows",columnScopeHint:"JSON / empty = all columns",rowScopePlaceholder:"empty = all rows (NULL)",columnScopePlaceholder:"empty = all columns (NULL)",nullRows:"NULL (all rows)",nullCols:"NULL (all columns)",selectPlaceholder:"Select\u2026"},userRoles:{heading:"User assignments (TDUserRole)",user:"user",role:"role",empty:"No assignments",newHeading:"Assign a role",selectPlaceholder:"Select\u2026"},error:{forbiddenTitle:"Access denied",forbiddenBody:"You don't have permission to view this screen. Ask an administrator to grant access.",genericTitlePrefix:"Error",genericTitle:"An error occurred",genericBody:"An unexpected error occurred. Please try again later."},warn:{selfRoleDisable:"This role backs your own authorization-admin access. Disabling it may lock you out of this screen. Continue?",selfRoleDelete:"This role backs your own authorization-admin access. Deleting it may lock you out of this screen. Continue?",selfAssignmentRemove:"This assignment backs your own authorization-admin access. Removing it may lock you out of this screen. Continue?"}};function L(t){let n=W;return t?{title:t.title??n.title,myPermission:t.myPermission??n.myPermission,tabs:{...n.tabs,...t.tabs},common:{...n.common,...t.common},roles:{...n.roles,...t.roles},resources:{...n.resources,...t.resources},grants:{...n.grants,...t.grants},userRoles:{...n.userRoles,...t.userRoles},error:{...n.error,...t.error},warn:{...n.warn,...t.warn}}:n}var ne=t=>t instanceof Response;function D(t){if(ne(t))throw t;if(t instanceof v.AuthzDeniedError)throw new Response(t.message,{status:403});return(0,A.data)({error:t instanceof Error?t.message:"\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F"},{status:400})}function N(t){let n=t.store,s=t.resourceKey??"authz_admin",d=L(t.labels),o=async(u,a)=>{let{userId:g}=await t.requirePermission(u,a);if(g==null)throw new v.AuthzDeniedError({appKey:"",resourceKey:a.resourceKey,action:a.action,reason:"unresolved-user",userId:null});return{userId:g}};async function c(u){await t.requireUser(u);try{return await o(u,{resourceKey:s,action:"read"})}catch(a){throw a instanceof v.AuthzDeniedError?new Response(`Forbidden: ${s}`,{status:403}):a}}let l=u=>t.getMyPermissions(u,{resourceKeys:[s]}),y=async u=>{let[a,g]=await Promise.all([n.listRoles(),n.getSelfAdminContext(Number(u))]);return{roles:a,selfAdminRoleIds:g.selfAdminRoleIds,labels:d}},h=async()=>({resources:await n.listResources(),labels:d}),f=async()=>{let[u,a,g]=await Promise.all([n.listGrants(),n.listRoles(),n.listResources()]);return{grants:u,roles:a,resources:g,labels:d}},S=async u=>{let[a,g,p,i]=await Promise.all([n.listUserRoles(),n.listRoles(),n.listUsers(),n.getSelfAdminContext(Number(u))]);return{assignments:a,roles:g,users:p,actorUserId:i.actorUserId,selfAdminRoleIds:i.selfAdminRoleIds,labels:d}};return{labels:d,resourceKey:s,layoutGuard:c,loadMyPermissions:l,layout:{async loader({request:u}){return await c(u),{myPermissions:await l(u),labels:d,adminResourceKey:s}}},index:{loader(){throw(0,A.redirect)("/authz/roles")}},roles:{data:y,async loader({request:u}){let{userId:a}=await o(u,{resourceKey:s,action:"read"});return y(a)},async action({request:u}){let a=await u.formData(),g=String(a.get("_action"));try{switch(g){case"create":{let{userId:p}=await o(u,{resourceKey:s,action:"create"}),i=String(a.get("roleKey")??"").trim(),b=String(a.get("name")??"").trim();return i&&b?(await n.createRole({roleKey:i,name:b,description:String(a.get("description")??"").trim()||null},String(p)),{ok:!0}):(0,A.data)({error:"role_key \u3068 name \u306F\u5FC5\u9808\u3067\u3059"},{status:400})}case"save":{let{userId:p}=await o(u,{resourceKey:s,action:"update"}),i=String(a.get("roleKey")??"").trim(),b=String(a.get("name")??"").trim();return i&&b?(await n.updateRole(Number(a.get("id")),{roleKey:i,name:b,description:String(a.get("description")??"").trim()||null},String(p)),{ok:!0}):(0,A.data)({error:"roleKey \u3068 name \u306F\u5FC5\u9808\u3067\u3059"},{status:400})}case"toggle":{let{userId:p}=await o(u,{resourceKey:s,action:"update"});return await n.setRoleActive(Number(a.get("id")),a.get("isActive")==="true",String(p)),{ok:!0}}case"delete":return await o(u,{resourceKey:s,action:"delete"}),await n.deleteRole(Number(a.get("id"))),{ok:!0};default:return(0,A.data)({error:"unknown action"},{status:400})}}catch(p){return D(p)}}},resources:{data:h,async loader({request:u}){return await o(u,{resourceKey:s,action:"read"}),h()},async action({request:u}){let a=await u.formData(),g=String(a.get("_action"));try{switch(g){case"create":{let{userId:p}=await o(u,{resourceKey:s,action:"create"}),i=String(a.get("appKey")??"").trim(),b=String(a.get("resourceKey")??"").trim(),I=String(a.get("name")??"").trim();return i&&b&&I?(await n.createResource({appKey:i,resourceKey:b,name:I,description:String(a.get("description")??"").trim()||null},String(p)),{ok:!0}):(0,A.data)({error:"app_key / resource_key / name \u306F\u5FC5\u9808\u3067\u3059"},{status:400})}case"save":{let{userId:p}=await o(u,{resourceKey:s,action:"update"}),i=String(a.get("name")??"").trim();return i?(await n.updateResource(Number(a.get("id")),{name:i,description:String(a.get("description")??"").trim()||null},String(p)),{ok:!0}):(0,A.data)({error:"name \u306F\u5FC5\u9808\u3067\u3059"},{status:400})}case"delete":return await o(u,{resourceKey:s,action:"delete"}),await n.deleteResource(Number(a.get("id"))),{ok:!0};default:return(0,A.data)({error:"unknown action"},{status:400})}}catch(p){return D(p)}}},grants:{data:f,async loader({request:u}){return await o(u,{resourceKey:s,action:"read"}),f()},async action({request:u}){let a=await u.formData(),g=String(a.get("_action"));try{switch(g){case"create":{let{userId:p}=await o(u,{resourceKey:s,action:"create"}),i=Number(a.get("roleId")),b=Number(a.get("resourceId"));if(!(i&&b))return(0,A.data)({error:"\u30ED\u30FC\u30EB\u3068\u30EA\u30BD\u30FC\u30B9\u3092\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044"},{status:400});let I=String(a.get("action")??"");if(!v.AUTHZ_ACTIONS.includes(I))return(0,A.data)({error:"\u7121\u52B9\u306A action \u3067\u3059"},{status:400});let Y=I;return await n.createGrant({roleId:i,resourceId:b,action:Y,rowScope:String(a.get("rowScope")??""),columnScope:String(a.get("columnScope")??"")},String(p)),{ok:!0}}case"save":{let{userId:p}=await o(u,{resourceKey:s,action:"update"}),i=String(a.get("action")??"");if(!v.AUTHZ_ACTIONS.includes(i))return(0,A.data)({error:"\u7121\u52B9\u306A action \u3067\u3059"},{status:400});let b=i;return await n.updateGrant(Number(a.get("id")),{action:b,rowScope:String(a.get("rowScope")??""),columnScope:String(a.get("columnScope")??"")},String(p)),{ok:!0}}case"delete":return await o(u,{resourceKey:s,action:"delete"}),await n.deleteGrant(Number(a.get("id"))),{ok:!0};default:return(0,A.data)({error:"unknown action"},{status:400})}}catch(p){return D(p)}}},userRoles:{data:S,async loader({request:u}){let{userId:a}=await o(u,{resourceKey:s,action:"read"});return S(a)},async action({request:u}){let a=await u.formData(),g=String(a.get("_action"));try{switch(g){case"assign":{let{userId:p}=await o(u,{resourceKey:s,action:"create"}),i=Number(a.get("userId")),b=Number(a.get("roleId"));return i&&b?(await n.assignUserRole(i,b,String(p)),{ok:!0}):(0,A.data)({error:"\u30E6\u30FC\u30B6\u30FC\u3068\u30ED\u30FC\u30EB\u3092\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044"},{status:400})}case"remove":return await o(u,{resourceKey:s,action:"delete"}),await n.removeUserRole(Number(a.get("userId")),Number(a.get("roleId"))),{ok:!0};default:return(0,A.data)({error:"unknown action"},{status:400})}}catch(p){return D(p)}}}}}function V(t){return String(t["*"]??"").split("/")[0]}function oe(t){let n=N(t),s=t.basePath??"/authz",d=["roles","resources","role_permissions","user_roles"],o={roles:n.roles.data,resources:n.resources.data,role_permissions:n.grants.data,user_roles:n.userRoles.data},c={roles:n.roles.action,resources:n.resources.action,role_permissions:n.grants.action,user_roles:n.userRoles.action};async function l(h){let f=V(h.params);if(!d.includes(f))throw(0,_.redirect)(`${s}/roles`);let{userId:S}=await n.layoutGuard(h.request),[u,a]=await Promise.all([n.loadMyPermissions(h.request),o[f](S)]);return{segment:f,basePath:s,myPermissions:u,adminResourceKey:n.resourceKey,...a}}async function y(h){let f=V(h.params),S=c[f];return S?S(h):(0,_.data)({error:"unknown action"},{status:400})}return{loader:l,action:y,server:n}}var K=require("react/jsx-runtime"),r={page:{padding:"1.25rem",maxWidth:1280,margin:"0 auto",color:"#0f172a"},tableContainer:{width:"100%",overflowX:"auto",marginBottom:"1rem",WebkitOverflowScrolling:"touch"},table:{borderCollapse:"collapse",width:"100%",fontSize:"0.9rem"},th:{textAlign:"left",borderBottom:"2px solid #e2e8f0",padding:"0.45rem 0.65rem",fontSize:"0.78rem",color:"#475569",fontWeight:600,textTransform:"uppercase",letterSpacing:"0.03em"},td:{borderBottom:"1px solid #f1f5f9",padding:"0.5rem 0.65rem",verticalAlign:"middle"},input:{padding:"0.4rem 0.55rem",border:"1px solid #cbd5e1",borderRadius:6,fontSize:"0.9rem",background:"#fff",width:"100%",boxSizing:"border-box"},select:{padding:"0.4rem 0.55rem",border:"1px solid #cbd5e1",borderRadius:6,fontSize:"0.9rem",background:"#fff",width:"100%",boxSizing:"border-box"},textarea:{padding:"0.4rem 0.55rem",border:"1px solid #cbd5e1",borderRadius:6,fontSize:"0.82rem",fontFamily:"ui-monospace, SFMono-Regular, Menlo, monospace",minHeight:"3.25rem",resize:"vertical",width:"100%",boxSizing:"border-box"},button:{padding:"0.3rem 0.7rem",border:"1px solid #cbd5e1",borderRadius:6,background:"#fff",cursor:"pointer",fontSize:"0.82rem",color:"#334155"},save:{padding:"0.3rem 0.7rem",border:"1px solid #2563eb",borderRadius:6,background:"#eff6ff",cursor:"pointer",fontSize:"0.82rem",color:"#2563eb",fontWeight:600},danger:{padding:"0.3rem 0.7rem",border:"1px solid #fecaca",borderRadius:6,background:"#fff",cursor:"pointer",fontSize:"0.82rem",color:"#dc2626"},primary:{padding:"0.5rem 1.25rem",border:"1px solid #2563eb",borderRadius:6,background:"#2563eb",color:"#fff",cursor:"pointer",fontSize:"0.9rem",fontWeight:600,alignSelf:"flex-start"},card:{display:"flex",flexDirection:"column",gap:"0.85rem",maxWidth:600,marginTop:"0.75rem",padding:"1rem 1.1rem",border:"1px solid #e2e8f0",borderRadius:10,background:"#f8fafc"},code:{fontFamily:"ui-monospace, SFMono-Regular, Menlo, monospace",fontSize:"0.78rem",color:"#334155",wordBreak:"break-all"},muted:{color:"#94a3b8"},h2:{fontSize:"1.05rem",margin:"0 0 0.35rem",fontWeight:700},h3:{fontSize:"0.92rem",margin:"1.25rem 0 0",color:"#334155",fontWeight:600},note:{color:"#64748b",fontSize:"0.82rem",margin:"0 0 0.75rem"},empty:{color:"#94a3b8",padding:"0.75rem 0.65rem"}};function w({label:t,hint:n,children:s}){return(0,K.jsxs)("div",{style:{display:"flex",flexDirection:"column",gap:"0.3rem"},children:[(0,K.jsxs)("span",{style:{fontSize:"0.8rem",color:"#475569",fontWeight:600},children:[t,n?(0,K.jsxs)("span",{style:{fontWeight:400,color:"#94a3b8"},children:[" \u2014 ",n]}):null]}),s]})}function k({message:t}){return t?(0,K.jsx)("p",{role:"alert",style:{color:"#dc2626",background:"#fef2f2",border:"1px solid #fecaca",borderRadius:8,padding:"0.55rem 0.8rem",fontSize:"0.85rem",margin:"0.25rem 0"},children:t}):null}var $=require("@aiquants/authz-core"),z=require("@aiquants/select-box"),P=require("react"),m=require("react-router");function U(t){let n=t?.read?t.readPartial?"partial":"full":"none",s=t?.create&&t?.update?"full":t?.create||t?.update?"partial":"none",d=t?.delete?"full":"none";return{canRead:!!t?.read,canWrite:!!t?.write,canDelete:!!t?.delete,readState:n,writeState:s,deleteState:d}}var R=require("react/jsx-runtime"),se={full:{bg:"#ecfdf5",text:"#047857",border:"#a7f3d0"},partial:{bg:"#fffbeb",text:"#b45309",border:"#fde68a"},none:{bg:"#f8fafc",text:"#94a3b8",border:"#cbd5e1"}};function ie({state:t}){return t==="full"?(0,R.jsx)("svg",{style:{width:"0.85rem",height:"0.85rem",flexShrink:0},fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:3,"aria-hidden":"true",children:(0,R.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M5 13l4 4L19 7"})}):t==="partial"?(0,R.jsx)("svg",{style:{width:"0.85rem",height:"0.85rem",flexShrink:0},fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:2.5,"aria-hidden":"true",children:(0,R.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"})}):(0,R.jsx)("svg",{style:{width:"0.85rem",height:"0.85rem",flexShrink:0},fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:2.5,"aria-hidden":"true",children:(0,R.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M18.364 18.364A9 9 0 005.636 5.636m12.728 12.728A9 9 0 015.636 5.636m12.728 12.728L5.636 5.636"})})}function F({permission:t,labels:n,showScopeSummary:s=!0,className:d="authz-permission-indicator"}){let o=U(t),c={read:n?.read??"\u95B2\u89A7",write:n?.write??"\u7DE8\u96C6",delete:n?.delete??"\u524A\u9664"},l=(y,h,f)=>{let S=se[h];return(0,R.jsxs)("span",{"data-perm":y,"data-state":h,title:`${f}: ${h}`,style:{display:"inline-flex",alignItems:"center",gap:"0.25rem",padding:"0.2rem 0.5rem",borderRadius:"100px",fontSize:"0.75rem",fontWeight:600,backgroundColor:S.bg,color:S.text,border:`1px solid ${S.border}`,lineHeight:1,userSelect:"none"},children:[(0,R.jsx)(ie,{state:h}),(0,R.jsx)("span",{children:f})]})};return(0,R.jsxs)("span",{className:d,"data-resource":t?.resourceKey??"",style:{display:"inline-flex",gap:"0.35rem",alignItems:"center",verticalAlign:"middle"},children:[l("read",o.readState,c.read),l("write",o.writeState,c.write),l("delete",o.deleteState,c.delete),s&&o.readState==="partial"?(0,R.jsx)("span",{"data-perm":"scope",style:{fontSize:"0.7rem",color:"#b45309",backgroundColor:"#fef3c7",padding:"0.15rem 0.35rem",borderRadius:"4px",fontWeight:600},children:"\u90E8\u5206\u5236\u9650"}):null]})}var e=require("react/jsx-runtime"),C=t=>t?.error;function H({children:t}){let{myPermissions:n,labels:s,adminResourceKey:d,basePath:o}=(0,m.useLoaderData)(),c=o??"/authz",l=[["roles",s.tabs.roles],["resources",s.tabs.resources],["role_permissions",s.tabs.role_permissions],["user_roles",s.tabs.user_roles]];return(0,e.jsxs)("div",{className:"authz-admin",style:r.page,children:[(0,e.jsxs)("header",{style:{display:"flex",alignItems:"baseline",justifyContent:"space-between",gap:"1rem",flexWrap:"wrap"},children:[(0,e.jsx)("h1",{style:{fontSize:"1.3rem",margin:0,fontWeight:700},children:s.title}),(0,e.jsxs)("span",{style:{fontSize:"0.82rem",color:"#475569",display:"inline-flex",alignItems:"center",gap:"0.4rem"},children:[s.myPermission,": ",(0,e.jsx)(F,{permission:n[d]})]})]}),(0,e.jsx)("nav",{style:{display:"flex",gap:"0.25rem",borderBottom:"1px solid #e2e8f0",margin:"0.9rem 0 1.25rem"},children:l.map(([y,h])=>(0,e.jsx)(m.NavLink,{to:`${c}/${y}`,style:({isActive:f})=>({padding:"0.5rem 0.9rem",textDecoration:"none",color:f?"#2563eb":"#475569",borderBottom:f?"2px solid #2563eb":"2px solid transparent",marginBottom:-1,fontWeight:f?700:500,fontSize:"0.92rem"}),children:h},y))}),t]})}function ae(){return(0,e.jsx)(H,{children:(0,e.jsx)(m.Outlet,{})})}function G(t){let n=L(t).error;return function(){let d=(0,m.useRouteError)(),o=(0,m.isRouteErrorResponse)(d)?d:null,c=o?.status===403,l=c?n.forbiddenTitle:o?`${n.genericTitlePrefix} (${o.status})`:n.genericTitle,y=c?n.forbiddenBody:o?typeof o.data=="string"&&o.data?o.data:o.statusText:n.genericBody;return(0,e.jsx)("div",{style:r.page,children:(0,e.jsxs)("div",{role:"alert",style:{maxWidth:480,margin:"3rem auto",padding:"1.5rem",border:"1px solid #fecaca",borderRadius:12,background:"#fef2f2"},children:[(0,e.jsx)("h1",{style:{fontSize:"1.1rem",fontWeight:700,color:"#b91c1c",margin:"0 0 0.5rem"},children:l}),(0,e.jsx)("p",{style:{color:"#7f1d1d",fontSize:"0.9rem",margin:0,lineHeight:1.7},children:y})]})})}}var le=G(),T=(t,n)=>s=>{t&&!window.confirm(n)&&s.preventDefault()};function q(){let{roles:t,selfAdminRoleIds:n,labels:s}=(0,m.useLoaderData)(),d=s.roles,o=s.common,c=new Set(n??[]);return(0,e.jsxs)("section",{children:[(0,e.jsx)("h2",{style:r.h2,children:d.heading}),(0,e.jsx)(k,{message:C((0,m.useActionData)())}),(0,e.jsx)("p",{style:r.note,children:d.note}),(0,e.jsx)("div",{style:r.tableContainer,children:(0,e.jsxs)("table",{style:r.table,children:[(0,e.jsx)("thead",{children:(0,e.jsxs)("tr",{children:[(0,e.jsx)("th",{style:{...r.th,width:"20%"},children:d.roleKey}),(0,e.jsx)("th",{style:{...r.th,width:"25%"},children:d.name}),(0,e.jsx)("th",{style:{...r.th,width:"35%"},children:d.description}),(0,e.jsx)("th",{style:{...r.th,width:"10%"},children:d.activeHeader}),(0,e.jsx)("th",{style:{...r.th,width:"10%"}})]})}),(0,e.jsxs)("tbody",{children:[t.map(l=>(0,e.jsxs)("tr",{children:[(0,e.jsx)("td",{style:r.td,children:l.roleKey==="@authenticated"||l.roleKey==="@anonymous"?(0,e.jsx)("span",{style:r.code,children:l.roleKey}):(0,e.jsx)("input",{name:"roleKey",defaultValue:l.roleKey,form:`save-role-${l.id}`,"aria-label":`roleKey-${l.id}`,required:!0,style:r.input})}),(0,e.jsx)("td",{style:r.td,children:(0,e.jsx)("input",{name:"name",defaultValue:l.name,form:`save-role-${l.id}`,"aria-label":`name-${l.id}`,required:!0,style:r.input})}),(0,e.jsx)("td",{style:r.td,children:(0,e.jsx)("input",{name:"description",defaultValue:l.description??"",form:`save-role-${l.id}`,"aria-label":`description-${l.id}`,style:r.input})}),(0,e.jsx)("td",{style:r.td,children:(0,e.jsxs)(m.Form,{method:"post",style:{display:"inline"},children:[(0,e.jsx)("input",{type:"hidden",name:"_action",value:"toggle"}),(0,e.jsx)("input",{type:"hidden",name:"id",value:l.id}),(0,e.jsx)("input",{type:"hidden",name:"isActive",value:String(!l.isActive)}),(0,e.jsx)("button",{type:"submit",style:r.button,onClick:l.isActive?T(c.has(l.id),s.warn.selfRoleDisable):void 0,children:l.isActive?o.active:o.inactive})]})}),(0,e.jsxs)("td",{style:{...r.td,whiteSpace:"nowrap"},children:[(0,e.jsxs)(m.Form,{method:"post",id:`save-role-${l.id}`,style:{display:"inline"},children:[(0,e.jsx)("input",{type:"hidden",name:"_action",value:"save"}),(0,e.jsx)("input",{type:"hidden",name:"id",value:l.id}),(0,e.jsx)("button",{type:"submit",style:r.save,children:o.save})]}),(0,e.jsxs)(m.Form,{method:"post",style:{display:"inline",marginLeft:"0.4rem"},children:[(0,e.jsx)("input",{type:"hidden",name:"_action",value:"delete"}),(0,e.jsx)("input",{type:"hidden",name:"id",value:l.id}),(0,e.jsx)("button",{type:"submit",style:r.danger,onClick:T(c.has(l.id),s.warn.selfRoleDelete),children:o.delete})]})]})]},l.id)),t.length===0?(0,e.jsx)("tr",{children:(0,e.jsx)("td",{style:r.empty,colSpan:5,children:d.empty})}):null]})]})}),(0,e.jsx)("h3",{style:r.h3,children:d.newHeading}),(0,e.jsxs)(m.Form,{method:"post",style:r.card,children:[(0,e.jsx)("input",{type:"hidden",name:"_action",value:"create"}),(0,e.jsx)(w,{label:d.roleKey,hint:d.hintRoleKey,children:(0,e.jsx)("input",{name:"roleKey","aria-label":"role_key",required:!0,style:r.input})}),(0,e.jsx)(w,{label:d.name,children:(0,e.jsx)("input",{name:"name","aria-label":"name",required:!0,style:r.input})}),(0,e.jsx)(w,{label:d.description,hint:o.optional,children:(0,e.jsx)("input",{name:"description","aria-label":"description",style:r.input})}),(0,e.jsx)("button",{type:"submit",style:r.primary,children:o.add})]})]})}function B(){let{resources:t,labels:n}=(0,m.useLoaderData)(),s=n.resources,d=n.common;return(0,e.jsxs)("section",{children:[(0,e.jsx)("h2",{style:r.h2,children:s.heading}),(0,e.jsx)(k,{message:C((0,m.useActionData)())}),(0,e.jsx)("p",{style:r.note,children:s.note}),(0,e.jsx)("div",{style:r.tableContainer,children:(0,e.jsxs)("table",{style:r.table,children:[(0,e.jsx)("thead",{children:(0,e.jsxs)("tr",{children:[(0,e.jsx)("th",{style:{...r.th,width:"15%"},children:s.appKey}),(0,e.jsx)("th",{style:{...r.th,width:"20%"},children:s.resourceKey}),(0,e.jsx)("th",{style:{...r.th,width:"25%"},children:s.name}),(0,e.jsx)("th",{style:{...r.th,width:"30%"},children:s.description}),(0,e.jsx)("th",{style:{...r.th,width:"10%"}})]})}),(0,e.jsxs)("tbody",{children:[t.map(o=>(0,e.jsxs)("tr",{children:[(0,e.jsx)("td",{style:r.td,children:(0,e.jsx)("span",{style:r.code,children:o.appKey})}),(0,e.jsx)("td",{style:r.td,children:(0,e.jsx)("span",{style:r.code,children:o.resourceKey})}),(0,e.jsx)("td",{style:r.td,children:(0,e.jsx)("input",{name:"name",defaultValue:o.name,form:`save-res-${o.id}`,"aria-label":`name-${o.id}`,required:!0,style:r.input})}),(0,e.jsx)("td",{style:r.td,children:(0,e.jsx)("input",{name:"description",defaultValue:o.description??"",form:`save-res-${o.id}`,"aria-label":`description-${o.id}`,style:r.input})}),(0,e.jsxs)("td",{style:{...r.td,whiteSpace:"nowrap"},children:[(0,e.jsxs)(m.Form,{method:"post",id:`save-res-${o.id}`,style:{display:"inline"},children:[(0,e.jsx)("input",{type:"hidden",name:"_action",value:"save"}),(0,e.jsx)("input",{type:"hidden",name:"id",value:o.id}),(0,e.jsx)("button",{type:"submit",style:r.save,children:d.save})]}),(0,e.jsxs)(m.Form,{method:"post",style:{display:"inline",marginLeft:"0.4rem"},children:[(0,e.jsx)("input",{type:"hidden",name:"_action",value:"delete"}),(0,e.jsx)("input",{type:"hidden",name:"id",value:o.id}),(0,e.jsx)("button",{type:"submit",style:r.danger,children:d.delete})]})]})]},o.id)),t.length===0?(0,e.jsx)("tr",{children:(0,e.jsx)("td",{style:r.empty,colSpan:5,children:s.empty})}):null]})]})}),(0,e.jsx)("h3",{style:r.h3,children:s.newHeading}),(0,e.jsxs)(m.Form,{method:"post",style:r.card,children:[(0,e.jsx)("input",{type:"hidden",name:"_action",value:"create"}),(0,e.jsx)(w,{label:s.appKey,hint:s.hintAppKey,children:(0,e.jsx)("input",{name:"appKey","aria-label":"app_key",required:!0,style:r.input})}),(0,e.jsx)(w,{label:s.resourceKey,hint:s.hintResourceKey,children:(0,e.jsx)("input",{name:"resourceKey","aria-label":"resource_key",required:!0,style:r.input})}),(0,e.jsx)(w,{label:s.name,children:(0,e.jsx)("input",{name:"name","aria-label":"name",required:!0,style:r.input})}),(0,e.jsx)(w,{label:s.description,hint:d.optional,children:(0,e.jsx)("input",{name:"description","aria-label":"description",style:r.input})}),(0,e.jsx)("button",{type:"submit",style:r.primary,children:d.add})]})]})}function de({g:t,labels:n}){let s=n.common,[d,o]=(0,P.useState)({label:t.action,value:t.action});return(0,e.jsxs)("tr",{children:[(0,e.jsx)("td",{style:r.td,children:(0,e.jsx)("span",{style:r.code,children:t.roleKey})}),(0,e.jsx)("td",{style:r.td,children:(0,e.jsxs)("span",{style:r.code,children:[t.appKey,":",t.resourceKey]})}),(0,e.jsx)("td",{style:r.td,children:t.roleKey==="@anonymous"?(0,e.jsx)("span",{style:r.code,children:t.action}):(0,e.jsxs)(e.Fragment,{children:[(0,e.jsx)("input",{type:"hidden",name:"action",value:d.value,form:`save-grant-${t.id}`}),(0,e.jsx)(z.SelectBox,{options:$.AUTHZ_ACTIONS.map(c=>({label:c,value:c})),value:d,onChange:c=>{c&&o(c)}})]})}),(0,e.jsx)("td",{style:r.td,children:(0,e.jsx)("textarea",{name:"rowScope",defaultValue:t.rowScope??"",form:`save-grant-${t.id}`,"aria-label":`row_scope-${t.id}`,rows:2,placeholder:n.grants.rowScopePlaceholder,style:r.textarea})}),(0,e.jsx)("td",{style:r.td,children:(0,e.jsx)("textarea",{name:"columnScope",defaultValue:t.columnScope??"",form:`save-grant-${t.id}`,"aria-label":`column_scope-${t.id}`,rows:2,placeholder:n.grants.columnScopePlaceholder,style:r.textarea})}),(0,e.jsxs)("td",{style:{...r.td,whiteSpace:"nowrap"},children:[(0,e.jsxs)(m.Form,{method:"post",id:`save-grant-${t.id}`,style:{display:"inline"},children:[(0,e.jsx)("input",{type:"hidden",name:"_action",value:"save"}),(0,e.jsx)("input",{type:"hidden",name:"id",value:t.id}),(0,e.jsx)("button",{type:"submit",style:r.save,children:s.save})]}),(0,e.jsxs)(m.Form,{method:"post",style:{display:"inline",marginLeft:"0.4rem"},children:[(0,e.jsx)("input",{type:"hidden",name:"_action",value:"delete"}),(0,e.jsx)("input",{type:"hidden",name:"id",value:t.id}),(0,e.jsx)("button",{type:"submit",style:r.danger,children:s.delete})]})]})]})}function M(){let{grants:t,roles:n,resources:s,labels:d}=(0,m.useLoaderData)(),o=d.grants,c=d.common,l=n.map(i=>({label:i.roleKey,value:i.id})),y=s.map(i=>({label:`${i.appKey}:${i.resourceKey}`,value:i.id})),h=$.AUTHZ_ACTIONS.map(i=>({label:i,value:i})),[f,S]=(0,P.useState)(void 0),[u,a]=(0,P.useState)(void 0),[g,p]=(0,P.useState)({label:"read",value:"read"});return(0,e.jsxs)("section",{children:[(0,e.jsx)("h2",{style:r.h2,children:o.heading}),(0,e.jsx)("p",{style:r.note,children:o.note}),(0,e.jsx)(k,{message:C((0,m.useActionData)())}),(0,e.jsx)("div",{style:r.tableContainer,children:(0,e.jsxs)("table",{style:r.table,children:[(0,e.jsx)("thead",{children:(0,e.jsxs)("tr",{children:[(0,e.jsx)("th",{style:{...r.th,width:"15%"},children:o.role}),(0,e.jsx)("th",{style:{...r.th,width:"20%"},children:o.resource}),(0,e.jsx)("th",{style:{...r.th,width:"15%"},children:o.action}),(0,e.jsx)("th",{style:{...r.th,width:"20%"},children:o.rowScope}),(0,e.jsx)("th",{style:{...r.th,width:"20%"},children:o.columnScope}),(0,e.jsx)("th",{style:{...r.th,width:"10%"}})]})}),(0,e.jsxs)("tbody",{children:[t.map(i=>(0,e.jsx)(de,{g:i,labels:d},i.id)),t.length===0?(0,e.jsx)("tr",{children:(0,e.jsx)("td",{style:r.empty,colSpan:6,children:o.empty})}):null]})]})}),(0,e.jsx)("h3",{style:r.h3,children:o.newHeading}),(0,e.jsxs)(m.Form,{method:"post",style:r.card,children:[(0,e.jsx)("input",{type:"hidden",name:"_action",value:"create"}),(0,e.jsx)("input",{type:"hidden",name:"roleId",value:f?.value??""}),(0,e.jsx)("input",{type:"hidden",name:"resourceId",value:u?.value??""}),(0,e.jsx)("input",{type:"hidden",name:"action",value:g?.value??""}),(0,e.jsx)(w,{label:o.role,children:(0,e.jsx)(z.SelectBox,{options:l,value:f,onChange:i=>S(i||void 0),placeholder:o.selectPlaceholder})}),(0,e.jsx)(w,{label:o.resource,children:(0,e.jsx)(z.SelectBox,{options:y,value:u,onChange:i=>a(i||void 0),placeholder:o.selectPlaceholder})}),(0,e.jsx)(w,{label:o.action,children:(0,e.jsx)(z.SelectBox,{options:h,value:g,onChange:i=>p(i||void 0)})}),(0,e.jsx)(w,{label:o.rowScope,hint:o.rowScopeHint,children:(0,e.jsx)("textarea",{name:"rowScope","aria-label":"row_scope",rows:2,style:r.textarea,placeholder:'{"filters":[{"field":"\u90E8\u9580CD","op":"in","values":["A"]}]}'})}),(0,e.jsx)(w,{label:o.columnScope,hint:o.columnScopeHint,children:(0,e.jsx)("textarea",{name:"columnScope","aria-label":"column_scope",rows:2,style:r.textarea,placeholder:'{"mode":"deny","columns":["\u91D1\u984D"]}'})}),(0,e.jsx)("button",{type:"submit",style:r.primary,children:c.grant})]})]})}function O(){let{assignments:t,roles:n,users:s,actorUserId:d,selfAdminRoleIds:o,labels:c}=(0,m.useLoaderData)(),l=c.userRoles,y=c.common,h=new Set(o??[]),f=s.map(i=>({label:`${i.email}\uFF08${i.displayName}\uFF09`,value:i.id})),S=n.filter(i=>i.roleKey!=="@authenticated"&&i.roleKey!=="@anonymous").map(i=>({label:i.roleKey,value:i.id})),[u,a]=(0,P.useState)(void 0),[g,p]=(0,P.useState)(void 0);return(0,e.jsxs)("section",{children:[(0,e.jsx)("h2",{style:r.h2,children:l.heading}),(0,e.jsx)(k,{message:C((0,m.useActionData)())}),(0,e.jsx)("div",{style:r.tableContainer,children:(0,e.jsxs)("table",{style:r.table,children:[(0,e.jsx)("thead",{children:(0,e.jsxs)("tr",{children:[(0,e.jsx)("th",{style:{...r.th,width:"45%"},children:l.user}),(0,e.jsx)("th",{style:{...r.th,width:"45%"},children:l.role}),(0,e.jsx)("th",{style:{...r.th,width:"10%"}})]})}),(0,e.jsxs)("tbody",{children:[t.map(i=>(0,e.jsxs)("tr",{children:[(0,e.jsxs)("td",{style:r.td,children:[i.email,(0,e.jsxs)("span",{style:r.muted,children:["\uFF08",i.displayName,"\uFF09"]})]}),(0,e.jsx)("td",{style:r.td,children:i.roleKey}),(0,e.jsx)("td",{style:r.td,children:(0,e.jsxs)(m.Form,{method:"post",style:{display:"inline"},children:[(0,e.jsx)("input",{type:"hidden",name:"_action",value:"remove"}),(0,e.jsx)("input",{type:"hidden",name:"userId",value:i.userId}),(0,e.jsx)("input",{type:"hidden",name:"roleId",value:i.roleId}),(0,e.jsx)("button",{type:"submit",style:r.danger,onClick:T(i.userId===d&&h.has(i.roleId),c.warn.selfAssignmentRemove),children:y.remove})]})})]},`${i.userId}-${i.roleId}`)),t.length===0?(0,e.jsx)("tr",{children:(0,e.jsx)("td",{style:r.empty,colSpan:3,children:l.empty})}):null]})]})}),(0,e.jsx)("h3",{style:r.h3,children:l.newHeading}),(0,e.jsxs)(m.Form,{method:"post",style:r.card,children:[(0,e.jsx)("input",{type:"hidden",name:"_action",value:"assign"}),(0,e.jsx)("input",{type:"hidden",name:"userId",value:u?.value??""}),(0,e.jsx)("input",{type:"hidden",name:"roleId",value:g?.value??""}),(0,e.jsx)(w,{label:l.user,children:(0,e.jsx)(z.SelectBox,{options:f,value:u,onChange:i=>a(i||void 0),placeholder:l.selectPlaceholder})}),(0,e.jsx)(w,{label:l.role,children:(0,e.jsx)(z.SelectBox,{options:S,value:g,onChange:i=>p(i||void 0),placeholder:l.selectPlaceholder})}),(0,e.jsx)("button",{type:"submit",style:r.primary,children:y.assign})]})]})}var ue={roles:q,resources:B,role_permissions:M,user_roles:O};function ce(){let{segment:t}=(0,m.useLoaderData)(),n=ue[t]??q;return(0,e.jsx)(H,{children:(0,e.jsx)(n,{})})}var x=require("@aiquants/authz-core"),J=require("react-router");function Q(t,n){let s=(0,x.can)(n,"read"),d=(0,x.can)(n,"create"),o=(0,x.can)(n,"update"),c=(0,x.can)(n,"delete"),l=n?.scopeByAction.read,y=s&&!!l&&(l.rowScope!==null||l.columnScope!==null);return{resourceKey:t,read:s,create:d,update:o,delete:c,write:d||o,readPartial:y,actions:n?Array.from(n.actions):[]}}function me(t){async function n(d,o,c){let l=c?.failureRedirect?()=>{throw(0,J.redirect)(c.failureRedirect)}:t.onDeny;return(0,x.createRequirePermission)({resolveUserId:t.resolveUserId,getEffectivePermissions:t.getEffectivePermissions,onDeny:l})(d,{appKey:t.appKey,resourceKey:o.resourceKey,action:o.action})}async function s(d,o){let c=await t.resolveUserId(d),l={};for(let y of o.resourceKeys){let h=await t.getEffectivePermissions({userId:c??null,appKey:t.appKey,resourceKey:y});l[y]=Q(y,h)}return l}return{requirePermission:n,getMyPermissions:s}}0&&(module.exports={AuthzAdminAppView,AuthzErrorBoundary,AuthzGrantsView,AuthzLayout,AuthzResourcesView,AuthzRolesView,AuthzUserRolesView,ErrorAlert,Field,MyPermissionIndicator,createAuthz,createAuthzAdminApp,createAuthzAdminServer,defaultAuthzAdminLabels,makeAuthzErrorBoundary,resolveLabels,toPermissionView,ui,usePermission});
|
|
1
|
+
"use strict";var E=Object.defineProperty;var X=Object.getOwnPropertyDescriptor;var ee=Object.getOwnPropertyNames;var te=Object.prototype.hasOwnProperty;var re=(t,r)=>{for(var s in r)E(t,s,{get:r[s],enumerable:!0})},ne=(t,r,s,l)=>{if(r&&typeof r=="object"||typeof r=="function")for(let o of ee(r))!te.call(t,o)&&o!==s&&E(t,o,{get:()=>r[o],enumerable:!(l=X(r,o))||l.enumerable});return t};var oe=t=>ne(E({},"__esModule",{value:!0}),t);var he={};re(he,{AuthzAdminAppView:()=>pe,AuthzErrorBoundary:()=>ue,AuthzGrantsView:()=>Q,AuthzLayout:()=>de,AuthzResourcesView:()=>J,AuthzRolesView:()=>M,AuthzUserRolesView:()=>Y,ErrorAlert:()=>I,Field:()=>R,MyPermissionIndicator:()=>H,MyPermissionStatus:()=>F,createAuthz:()=>ge,createAuthzAdminApp:()=>ie,createAuthzAdminServer:()=>T,defaultAuthzAdminLabels:()=>V,defineResources:()=>ye,formatResourceTooltip:()=>U,makeAuthzErrorBoundary:()=>O,resolveLabels:()=>L,toPermissionView:()=>j,ui:()=>n,usePermission:()=>$});module.exports=oe(he);var _=require("react-router");var P=require("@aiquants/authz-core"),S=require("react-router");var V={title:"Authorization (RBAC)",myPermission:"Your permissions",tabs:{roles:"Roles",resources:"Resources",role_permissions:"Permissions",user_roles:"User assignments"},common:{add:"Add",save:"Save",delete:"Delete",remove:"Remove",assign:"Assign",grant:"Grant",select:"Select\u2026",active:"\u25CB Enabled",inactive:"\xD7 Disabled",optional:"optional"},roles:{heading:"Roles (TMRole)",note:"Edit name / description inline and click Save (role_key is an immutable identifier).",roleKey:"role_key",name:"name",description:"description",activeHeader:"Active",empty:"No roles",newHeading:"New role",hintRoleKey:"e.g. admin"},resources:{heading:"Resources (TMResource)",note:"Edit name / description inline and click Save (app_key / resource_key are immutable identifiers).",appKey:"app_key",resourceKey:"resource_key",name:"name",description:"description",empty:"No resources",newHeading:"New resource",hintAppKey:"e.g. quants",hintResourceKey:"e.g. daily_report",hintDailyReport:"optional"},grants:{heading:"Permissions (TDRolePermission)",note:"Empty row_scope / column_scope = all rows / all columns (NULL). JSON must satisfy the \xA73.2 contract.",role:"role",resource:"resource",action:"action",rowScope:"row_scope",columnScope:"column_scope",empty:"No permissions",newHeading:"Grant a permission",rowScopeHint:"JSON / empty = all rows",columnScopeHint:"JSON / empty = all columns",rowScopePlaceholder:"empty = all rows (NULL)",columnScopePlaceholder:"empty = all columns (NULL)",nullRows:"NULL (all rows)",nullCols:"NULL (all columns)",selectPlaceholder:"Select\u2026"},userRoles:{heading:"User assignments (TDUserRole)",note:"Assign active roles to specific users.",user:"user",role:"role",empty:"No assignments",newHeading:"Assign a role",selectPlaceholder:"Select\u2026"},error:{forbiddenTitle:"Access denied",forbiddenBody:"You don't have permission to view this screen. Ask an administrator to grant access.",genericTitlePrefix:"Error",genericTitle:"An error occurred",genericBody:"An unexpected error occurred. Please try again later."},warn:{selfRoleDisable:"This role backs your own authorization-admin access. Disabling it may lock you out of this screen. Continue?",selfRoleDelete:"This role backs your own authorization-admin access. Deleting it may lock you out of this screen. Continue?",selfAssignmentRemove:"This assignment backs your own authorization-admin access. Removing it may lock you out of this screen. Continue?"}};function L(t){let r=V;return t?{title:t.title??r.title,myPermission:t.myPermission??r.myPermission,tabs:{...r.tabs,...t.tabs},common:{...r.common,...t.common},roles:{...r.roles,...t.roles},resources:{...r.resources,...t.resources},grants:{...r.grants,...t.grants},userRoles:{...r.userRoles,...t.userRoles},error:{...r.error,...t.error},warn:{...r.warn,...t.warn}}:r}var se=t=>t instanceof Response;function D(t){if(se(t))throw t;if(t instanceof P.AuthzDeniedError)throw new Response(t.message,{status:403});return(0,S.data)({error:t instanceof Error?t.message:"\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F"},{status:400})}function T(t){let r=t.store,s=t.resourceKey??"authz_admin",l=L(t.labels),o=async(u,a)=>{let{userId:f}=await t.requirePermission(u,a);if(f==null)throw new P.AuthzDeniedError({appKey:"",resourceKey:a.resourceKey,action:a.action,reason:"unresolved-user",userId:null});return{userId:f}};async function c(u){await t.requireUser(u);try{return await o(u,{resourceKey:s,action:"read"})}catch(a){throw a instanceof P.AuthzDeniedError?new Response(`Forbidden: ${s}`,{status:403}):a}}let d=u=>t.getMyPermissions(u,{resourceKeys:[s]}),y=async u=>{let[a,f]=await Promise.all([r.listRoles(),r.getSelfAdminContext(Number(u))]);return{roles:a,selfAdminRoleIds:f.selfAdminRoleIds,labels:l}},h=async()=>({resources:await r.listResources(),labels:l}),g=async()=>{let[u,a,f]=await Promise.all([r.listGrants(),r.listRoles(),r.listResources()]);return{grants:u,roles:a,resources:f,labels:l}},A=async u=>{let[a,f,p,i]=await Promise.all([r.listUserRoles(),r.listRoles(),r.listUsers(),r.getSelfAdminContext(Number(u))]);return{assignments:a,roles:f,users:p,actorUserId:i.actorUserId,selfAdminRoleIds:i.selfAdminRoleIds,labels:l}};return{labels:l,resourceKey:s,layoutGuard:c,loadMyPermissions:d,layout:{async loader({request:u}){return await c(u),{myPermissions:await d(u),labels:l,adminResourceKey:s}}},index:{loader(){throw(0,S.redirect)("/authz/roles")}},roles:{data:y,async loader({request:u}){let{userId:a}=await o(u,{resourceKey:s,action:"read"});return y(a)},async action({request:u}){let a=await u.formData(),f=String(a.get("_action"));try{switch(f){case"create":{let{userId:p}=await o(u,{resourceKey:s,action:"create"}),i=String(a.get("roleKey")??"").trim(),b=String(a.get("name")??"").trim();return i&&b?(await r.createRole({roleKey:i,name:b,description:String(a.get("description")??"").trim()||null},String(p)),{ok:!0}):(0,S.data)({error:"role_key \u3068 name \u306F\u5FC5\u9808\u3067\u3059"},{status:400})}case"save":{let{userId:p}=await o(u,{resourceKey:s,action:"update"}),i=String(a.get("roleKey")??"").trim(),b=String(a.get("name")??"").trim();return i&&b?(await r.updateRole(Number(a.get("id")),{roleKey:i,name:b,description:String(a.get("description")??"").trim()||null},String(p)),{ok:!0}):(0,S.data)({error:"roleKey \u3068 name \u306F\u5FC5\u9808\u3067\u3059"},{status:400})}case"toggle":{let{userId:p}=await o(u,{resourceKey:s,action:"update"});return await r.setRoleActive(Number(a.get("id")),a.get("isActive")==="true",String(p)),{ok:!0}}case"delete":return await o(u,{resourceKey:s,action:"delete"}),await r.deleteRole(Number(a.get("id"))),{ok:!0};default:return(0,S.data)({error:"unknown action"},{status:400})}}catch(p){return D(p)}}},resources:{data:h,async loader({request:u}){return await o(u,{resourceKey:s,action:"read"}),h()},async action({request:u}){let a=await u.formData(),f=String(a.get("_action"));try{switch(f){case"create":{let{userId:p}=await o(u,{resourceKey:s,action:"create"}),i=String(a.get("appKey")??"").trim(),b=String(a.get("resourceKey")??"").trim(),v=String(a.get("name")??"").trim();return i&&b&&v?(await r.createResource({appKey:i,resourceKey:b,name:v,description:String(a.get("description")??"").trim()||null},String(p)),{ok:!0}):(0,S.data)({error:"app_key / resource_key / name \u306F\u5FC5\u9808\u3067\u3059"},{status:400})}case"save":{let{userId:p}=await o(u,{resourceKey:s,action:"update"}),i=String(a.get("name")??"").trim();return i?(await r.updateResource(Number(a.get("id")),{name:i,description:String(a.get("description")??"").trim()||null},String(p)),{ok:!0}):(0,S.data)({error:"name \u306F\u5FC5\u9808\u3067\u3059"},{status:400})}case"delete":return await o(u,{resourceKey:s,action:"delete"}),await r.deleteResource(Number(a.get("id"))),{ok:!0};default:return(0,S.data)({error:"unknown action"},{status:400})}}catch(p){return D(p)}}},grants:{data:g,async loader({request:u}){return await o(u,{resourceKey:s,action:"read"}),g()},async action({request:u}){let a=await u.formData(),f=String(a.get("_action"));try{switch(f){case"create":{let{userId:p}=await o(u,{resourceKey:s,action:"create"}),i=Number(a.get("roleId")),b=Number(a.get("resourceId"));if(!(i&&b))return(0,S.data)({error:"\u30ED\u30FC\u30EB\u3068\u30EA\u30BD\u30FC\u30B9\u3092\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044"},{status:400});let v=String(a.get("action")??"");if(!P.AUTHZ_ACTIONS.includes(v))return(0,S.data)({error:"\u7121\u52B9\u306A action \u3067\u3059"},{status:400});let N=v;return await r.createGrant({roleId:i,resourceId:b,action:N,rowScope:String(a.get("rowScope")??""),columnScope:String(a.get("columnScope")??"")},String(p)),{ok:!0}}case"save":{let{userId:p}=await o(u,{resourceKey:s,action:"update"}),i=String(a.get("action")??"");if(!P.AUTHZ_ACTIONS.includes(i))return(0,S.data)({error:"\u7121\u52B9\u306A action \u3067\u3059"},{status:400});let b=i;return await r.updateGrant(Number(a.get("id")),{action:b,rowScope:String(a.get("rowScope")??""),columnScope:String(a.get("columnScope")??"")},String(p)),{ok:!0}}case"delete":return await o(u,{resourceKey:s,action:"delete"}),await r.deleteGrant(Number(a.get("id"))),{ok:!0};default:return(0,S.data)({error:"unknown action"},{status:400})}}catch(p){return D(p)}}},userRoles:{data:A,async loader({request:u}){let{userId:a}=await o(u,{resourceKey:s,action:"read"});return A(a)},async action({request:u}){let a=await u.formData(),f=String(a.get("_action"));try{switch(f){case"assign":{let{userId:p}=await o(u,{resourceKey:s,action:"create"}),i=Number(a.get("userId")),b=Number(a.get("roleId"));return i&&b?(await r.assignUserRole(i,b,String(p)),{ok:!0}):(0,S.data)({error:"\u30E6\u30FC\u30B6\u30FC\u3068\u30ED\u30FC\u30EB\u3092\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044"},{status:400})}case"remove":return await o(u,{resourceKey:s,action:"delete"}),await r.removeUserRole(Number(a.get("userId")),Number(a.get("roleId"))),{ok:!0};default:return(0,S.data)({error:"unknown action"},{status:400})}}catch(p){return D(p)}}}}}function G(t){return String(t["*"]??"").split("/")[0]}function ie(t){let r=T(t),s=t.basePath??"/authz",l=["roles","resources","role_permissions","user_roles"],o={roles:r.roles.data,resources:r.resources.data,role_permissions:r.grants.data,user_roles:r.userRoles.data},c={roles:r.roles.action,resources:r.resources.action,role_permissions:r.grants.action,user_roles:r.userRoles.action};async function d(h){let g=G(h.params);if(!l.includes(g))throw(0,_.redirect)(`${s}/roles`);let{userId:A}=await r.layoutGuard(h.request),[u,a]=await Promise.all([r.loadMyPermissions(h.request),o[g](A)]);return{segment:g,basePath:s,myPermissions:u,adminResourceKey:r.resourceKey,...a}}async function y(h){let g=G(h.params),A=c[g];return A?A(h):(0,_.data)({error:"unknown action"},{status:400})}return{loader:d,action:y,server:r}}var k=require("react/jsx-runtime"),n={page:{padding:"1.25rem",maxWidth:1280,margin:"0 auto",color:"#0f172a"},tableContainer:{width:"100%",overflowX:"auto",marginBottom:"1rem",WebkitOverflowScrolling:"touch"},table:{borderCollapse:"collapse",width:"100%",fontSize:"0.9rem",tableLayout:"fixed"},th:{textAlign:"left",borderBottom:"2px solid #e2e8f0",padding:"0.45rem 0.65rem",fontSize:"0.78rem",color:"#475569",fontWeight:600,textTransform:"uppercase",letterSpacing:"0.03em"},td:{borderBottom:"1px solid #f1f5f9",padding:"0.5rem 0.65rem",verticalAlign:"middle",wordBreak:"break-all"},input:{padding:"0.4rem 0.55rem",border:"1px solid #cbd5e1",borderRadius:6,fontSize:"0.9rem",background:"#fff",width:"100%",boxSizing:"border-box"},select:{padding:"0.4rem 0.55rem",border:"1px solid #cbd5e1",borderRadius:6,fontSize:"0.9rem",background:"#fff",width:"100%",boxSizing:"border-box"},textarea:{padding:"0.4rem 0.55rem",border:"1px solid #cbd5e1",borderRadius:6,fontSize:"0.82rem",fontFamily:"ui-monospace, SFMono-Regular, Menlo, monospace",minHeight:"3.25rem",resize:"vertical",width:"100%",boxSizing:"border-box"},button:{padding:"0.3rem 0.7rem",border:"1px solid #cbd5e1",borderRadius:6,background:"#fff",cursor:"pointer",fontSize:"0.82rem",color:"#334155"},save:{padding:"0.3rem 0.7rem",border:"1px solid #2563eb",borderRadius:6,background:"#eff6ff",cursor:"pointer",fontSize:"0.82rem",color:"#2563eb",fontWeight:600},danger:{padding:"0.3rem 0.7rem",border:"1px solid #fecaca",borderRadius:6,background:"#fff",cursor:"pointer",fontSize:"0.82rem",color:"#dc2626"},primary:{padding:"0.5rem 1.25rem",border:"1px solid #2563eb",borderRadius:6,background:"#2563eb",color:"#fff",cursor:"pointer",fontSize:"0.9rem",fontWeight:600,alignSelf:"flex-start"},card:{display:"flex",flexDirection:"column",gap:"0.85rem",maxWidth:600,marginTop:"0.75rem",padding:"1rem 1.1rem",border:"1px solid #e2e8f0",borderRadius:10,background:"#f8fafc"},code:{fontFamily:"ui-monospace, SFMono-Regular, Menlo, monospace",fontSize:"0.78rem",color:"#334155",wordBreak:"break-all"},muted:{color:"#94a3b8"},h2:{fontSize:"1.05rem",margin:"0 0 0.35rem",fontWeight:700},h3:{fontSize:"0.92rem",margin:"1.25rem 0 0",color:"#334155",fontWeight:600},note:{color:"#64748b",fontSize:"0.82rem",margin:"0 0 0.75rem"},empty:{color:"#94a3b8",padding:"0.75rem 0.65rem"}};function R({label:t,hint:r,children:s}){return(0,k.jsxs)("div",{style:{display:"flex",flexDirection:"column",gap:"0.3rem"},children:[(0,k.jsxs)("span",{style:{fontSize:"0.8rem",color:"#475569",fontWeight:600},children:[t,r?(0,k.jsxs)("span",{style:{fontWeight:400,color:"#94a3b8"},children:[" \u2014 ",r]}):null]}),s]})}function I({message:t}){return t?(0,k.jsx)("p",{role:"alert",style:{color:"#dc2626",background:"#fef2f2",border:"1px solid #fecaca",borderRadius:8,padding:"0.55rem 0.8rem",fontSize:"0.85rem",margin:"0.25rem 0"},children:t}):null}var W=require("@aiquants/authz-core"),z=require("@aiquants/select-box"),x=require("react"),m=require("react-router");function $(t){let r=t?.read?t.readPartial?"partial":"full":"none",s=t?.create&&t?.update?"full":t?.create||t?.update?"partial":"none",l=t?.delete?"full":"none";return{canRead:!!t?.read,canWrite:!!t?.write,canDelete:!!t?.delete,readState:r,writeState:s,deleteState:l}}var w=require("react/jsx-runtime"),ae={full:{bg:"#ecfdf5",text:"#047857",border:"#a7f3d0"},partial:{bg:"#fffbeb",text:"#b45309",border:"#fde68a"},none:{bg:"#f8fafc",text:"#94a3b8",border:"#cbd5e1"}};function U(t,r){let s=t?.trim(),l=r?.trim();if(l&&s&&l!==s)return`\u5BFE\u8C61\u30EA\u30BD\u30FC\u30B9: ${l} (${s})`;if(l||s)return`\u5BFE\u8C61\u30EA\u30BD\u30FC\u30B9: ${l||s}`}function le({state:t}){return t==="full"?(0,w.jsx)("svg",{style:{width:"0.85rem",height:"0.85rem",flexShrink:0},fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:3,"aria-hidden":"true",children:(0,w.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M5 13l4 4L19 7"})}):t==="partial"?(0,w.jsx)("svg",{style:{width:"0.85rem",height:"0.85rem",flexShrink:0},fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:2.5,"aria-hidden":"true",children:(0,w.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"})}):(0,w.jsx)("svg",{style:{width:"0.85rem",height:"0.85rem",flexShrink:0},fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:2.5,"aria-hidden":"true",children:(0,w.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M18.364 18.364A9 9 0 005.636 5.636m12.728 12.728A9 9 0 015.636 5.636m12.728 12.728L5.636 5.636"})})}function H({permission:t,resourceName:r,expectedResourceKey:s,showResourceTooltip:l=!0,labels:o,showScopeSummary:c=!0,className:d="authz-permission-indicator"}){let y=$(t),h={read:o?.read??"\u95B2\u89A7",write:o?.write??"\u7DE8\u96C6",delete:o?.delete??"\u524A\u9664"},g=t?.resourceKey,A=r||g,u=l?U(g,r):void 0,a=!!(s&&g&&g!==s);a&&typeof console<"u"&&typeof console.error=="function"&&console.error(`[Authz Warning] Resource key mismatch in MyPermissionIndicator! Expected: "${s}", but received permission for: "${g}".`);let f=(p,i,b)=>{let v=ae[i],N=u?`${b}: ${i}
|
|
2
|
+
${u}`:`${b}: ${i}`;return(0,w.jsxs)("span",{"data-perm":p,"data-state":i,title:N,style:{display:"inline-flex",alignItems:"center",gap:"0.25rem",padding:"0.2rem 0.5rem",borderRadius:"100px",fontSize:"0.75rem",fontWeight:600,backgroundColor:v.bg,color:v.text,border:`1px solid ${v.border}`,lineHeight:1,userSelect:"none"},children:[(0,w.jsx)(le,{state:i}),(0,w.jsx)("span",{children:b})]})};return(0,w.jsxs)("span",{className:d,title:u,"data-resource":g??"","data-resource-name":A??"","data-mismatch":a?"true":void 0,style:{display:"inline-flex",gap:"0.35rem",alignItems:"center",verticalAlign:"middle"},children:[f("read",y.readState,h.read),f("write",y.writeState,h.write),f("delete",y.deleteState,h.delete),c&&y.readState==="partial"?(0,w.jsx)("span",{"data-perm":"scope",title:u,style:{fontSize:"0.7rem",color:"#b45309",backgroundColor:"#fef3c7",padding:"0.15rem 0.35rem",borderRadius:"4px",fontWeight:600},children:"\u90E8\u5206\u5236\u9650"}):null,a?(0,w.jsxs)("span",{"data-testid":"resource-mismatch-warning",title:`expected: "${s}", actual: "${g}"`,style:{fontSize:"0.7rem",color:"#991b1b",backgroundColor:"#fee2e2",border:"1px solid #fca5a5",padding:"0.15rem 0.35rem",borderRadius:"4px",fontWeight:700},children:["\u26A0\uFE0F \u30EA\u30BD\u30FC\u30B9\u4E0D\u4E00\u81F4 (",g," \u2260 ",s,")"]}):null]})}function F({permission:t,resourceName:r,expectedResourceKey:s,prefixLabel:l="\u3042\u306A\u305F\u306E\u6A29\u9650",showPrefixLabel:o=!0,showResourceTooltip:c=!0,labels:d,showScopeSummary:y=!0,className:h="authz-permission-status",style:g}){let A=t?.resourceKey,u=r||A,a=c?U(A,r):void 0;return(0,w.jsxs)("span",{className:h,title:a,"data-testid":"my-permission-status","data-resource":A??"","data-resource-name":u??"",style:{fontSize:"0.82rem",color:"#475569",display:"inline-flex",alignItems:"center",gap:"0.4rem",...g},children:[o&&(0,w.jsxs)("span",{"data-testid":"prefix-label",children:[l,":"]}),(0,w.jsx)(H,{permission:t,resourceName:r,expectedResourceKey:s,showResourceTooltip:c,labels:d,showScopeSummary:y})]})}var e=require("react/jsx-runtime"),C=t=>t?.error;function B({children:t}){let{myPermissions:r,labels:s,adminResourceKey:l,basePath:o}=(0,m.useLoaderData)(),c=o??"/authz",d=[["roles",s.tabs.roles],["resources",s.tabs.resources],["role_permissions",s.tabs.role_permissions],["user_roles",s.tabs.user_roles]];return(0,e.jsxs)("div",{className:"authz-admin",style:n.page,children:[(0,e.jsxs)("header",{style:{display:"flex",alignItems:"baseline",justifyContent:"space-between",gap:"1rem",flexWrap:"wrap"},children:[(0,e.jsx)("h1",{style:{fontSize:"1.3rem",margin:0,fontWeight:700},children:s.title}),(0,e.jsx)(F,{prefixLabel:s.myPermission,permission:r[l],resourceName:l})]}),(0,e.jsx)("nav",{style:{display:"flex",gap:"0.25rem",borderBottom:"1px solid #e2e8f0",margin:"0.9rem 0 1.25rem"},children:d.map(([y,h])=>(0,e.jsx)(m.NavLink,{to:`${c}/${y}`,style:({isActive:g})=>({padding:"0.5rem 0.9rem",textDecoration:"none",color:g?"#2563eb":"#475569",borderBottom:g?"2px solid #2563eb":"2px solid transparent",marginBottom:-1,fontWeight:g?700:500,fontSize:"0.92rem"}),children:h},y))}),t]})}function de(){return(0,e.jsx)(B,{children:(0,e.jsx)(m.Outlet,{})})}function O(t){let r=L(t).error;return function(){let l=(0,m.useRouteError)(),o=(0,m.isRouteErrorResponse)(l)?l:null,c=o?.status===403,d=c?r.forbiddenTitle:o?`${r.genericTitlePrefix} (${o.status})`:r.genericTitle,y=c?r.forbiddenBody:o?typeof o.data=="string"&&o.data?o.data:o.statusText:r.genericBody;return(0,e.jsx)("div",{style:n.page,children:(0,e.jsxs)("div",{role:"alert",style:{maxWidth:480,margin:"3rem auto",padding:"1.5rem",border:"1px solid #fecaca",borderRadius:12,background:"#fef2f2"},children:[(0,e.jsx)("h1",{style:{fontSize:"1.1rem",fontWeight:700,color:"#b91c1c",margin:"0 0 0.5rem"},children:d}),(0,e.jsx)("p",{style:{color:"#7f1d1d",fontSize:"0.9rem",margin:0,lineHeight:1.7},children:y})]})})}}var ue=O(),q=(t,r)=>s=>{t&&!window.confirm(r)&&s.preventDefault()};function M(){let{roles:t,selfAdminRoleIds:r,labels:s}=(0,m.useLoaderData)(),l=s.roles,o=s.common,c=new Set(r??[]);return(0,e.jsxs)("section",{children:[(0,e.jsx)("h2",{style:n.h2,children:l.heading}),(0,e.jsx)(I,{message:C((0,m.useActionData)())}),(0,e.jsx)("p",{style:n.note,children:l.note}),(0,e.jsx)("div",{style:n.tableContainer,children:(0,e.jsxs)("table",{style:n.table,children:[(0,e.jsx)("thead",{children:(0,e.jsxs)("tr",{children:[(0,e.jsx)("th",{style:{...n.th,width:"20%"},children:l.roleKey}),(0,e.jsx)("th",{style:{...n.th,width:"25%"},children:l.name}),(0,e.jsx)("th",{style:{...n.th,width:"35%"},children:l.description}),(0,e.jsx)("th",{style:{...n.th,width:"10%"},children:l.activeHeader}),(0,e.jsx)("th",{style:{...n.th,width:"10%"}})]})}),(0,e.jsxs)("tbody",{children:[t.map(d=>(0,e.jsxs)("tr",{children:[(0,e.jsx)("td",{style:n.td,children:d.roleKey==="@authenticated"||d.roleKey==="@anonymous"?(0,e.jsx)("span",{style:n.code,children:d.roleKey}):(0,e.jsx)("input",{name:"roleKey",defaultValue:d.roleKey,form:`save-role-${d.id}`,"aria-label":`roleKey-${d.id}`,required:!0,style:n.input})}),(0,e.jsx)("td",{style:n.td,children:(0,e.jsx)("input",{name:"name",defaultValue:d.name,form:`save-role-${d.id}`,"aria-label":`name-${d.id}`,required:!0,style:n.input})}),(0,e.jsx)("td",{style:n.td,children:(0,e.jsx)("input",{name:"description",defaultValue:d.description??"",form:`save-role-${d.id}`,"aria-label":`description-${d.id}`,style:n.input})}),(0,e.jsx)("td",{style:n.td,children:(0,e.jsxs)(m.Form,{method:"post",style:{display:"inline"},children:[(0,e.jsx)("input",{type:"hidden",name:"_action",value:"toggle"}),(0,e.jsx)("input",{type:"hidden",name:"id",value:d.id}),(0,e.jsx)("input",{type:"hidden",name:"isActive",value:String(!d.isActive)}),(0,e.jsx)("button",{type:"submit",style:n.button,onClick:d.isActive?q(c.has(d.id),s.warn.selfRoleDisable):void 0,children:d.isActive?o.active:o.inactive})]})}),(0,e.jsxs)("td",{style:{...n.td,whiteSpace:"nowrap"},children:[(0,e.jsxs)(m.Form,{method:"post",id:`save-role-${d.id}`,style:{display:"inline"},children:[(0,e.jsx)("input",{type:"hidden",name:"_action",value:"save"}),(0,e.jsx)("input",{type:"hidden",name:"id",value:d.id}),(0,e.jsx)("button",{type:"submit",style:n.save,children:o.save})]}),(0,e.jsxs)(m.Form,{method:"post",style:{display:"inline",marginLeft:"0.4rem"},children:[(0,e.jsx)("input",{type:"hidden",name:"_action",value:"delete"}),(0,e.jsx)("input",{type:"hidden",name:"id",value:d.id}),(0,e.jsx)("button",{type:"submit",style:n.danger,onClick:q(c.has(d.id),s.warn.selfRoleDelete),children:o.delete})]})]})]},d.id)),t.length===0?(0,e.jsx)("tr",{children:(0,e.jsx)("td",{style:n.empty,colSpan:5,children:l.empty})}):null]})]})}),(0,e.jsx)("h3",{style:n.h3,children:l.newHeading}),(0,e.jsxs)(m.Form,{method:"post",style:n.card,children:[(0,e.jsx)("input",{type:"hidden",name:"_action",value:"create"}),(0,e.jsx)(R,{label:l.roleKey,hint:l.hintRoleKey,children:(0,e.jsx)("input",{name:"roleKey","aria-label":"role_key",required:!0,style:n.input})}),(0,e.jsx)(R,{label:l.name,children:(0,e.jsx)("input",{name:"name","aria-label":"name",required:!0,style:n.input})}),(0,e.jsx)(R,{label:l.description,hint:o.optional,children:(0,e.jsx)("input",{name:"description","aria-label":"description",style:n.input})}),(0,e.jsx)("button",{type:"submit",style:n.primary,children:o.add})]})]})}function J(){let{resources:t,labels:r}=(0,m.useLoaderData)(),s=r.resources,l=r.common;return(0,e.jsxs)("section",{children:[(0,e.jsx)("h2",{style:n.h2,children:s.heading}),(0,e.jsx)(I,{message:C((0,m.useActionData)())}),(0,e.jsx)("p",{style:n.note,children:s.note}),(0,e.jsx)("div",{style:n.tableContainer,children:(0,e.jsxs)("table",{style:n.table,children:[(0,e.jsx)("thead",{children:(0,e.jsxs)("tr",{children:[(0,e.jsx)("th",{style:{...n.th,width:"15%"},children:s.appKey}),(0,e.jsx)("th",{style:{...n.th,width:"20%"},children:s.resourceKey}),(0,e.jsx)("th",{style:{...n.th,width:"25%"},children:s.name}),(0,e.jsx)("th",{style:{...n.th,width:"30%"},children:s.description}),(0,e.jsx)("th",{style:{...n.th,width:"10%"}})]})}),(0,e.jsxs)("tbody",{children:[t.map(o=>(0,e.jsxs)("tr",{children:[(0,e.jsx)("td",{style:n.td,children:(0,e.jsx)("span",{style:n.code,children:o.appKey})}),(0,e.jsx)("td",{style:n.td,children:(0,e.jsx)("span",{style:n.code,children:o.resourceKey})}),(0,e.jsx)("td",{style:n.td,children:(0,e.jsx)("input",{name:"name",defaultValue:o.name,form:`save-res-${o.id}`,"aria-label":`name-${o.id}`,required:!0,style:n.input})}),(0,e.jsx)("td",{style:n.td,children:(0,e.jsx)("input",{name:"description",defaultValue:o.description??"",form:`save-res-${o.id}`,"aria-label":`description-${o.id}`,style:n.input})}),(0,e.jsxs)("td",{style:{...n.td,whiteSpace:"nowrap"},children:[(0,e.jsxs)(m.Form,{method:"post",id:`save-res-${o.id}`,style:{display:"inline"},children:[(0,e.jsx)("input",{type:"hidden",name:"_action",value:"save"}),(0,e.jsx)("input",{type:"hidden",name:"id",value:o.id}),(0,e.jsx)("button",{type:"submit",style:n.save,children:l.save})]}),(0,e.jsxs)(m.Form,{method:"post",style:{display:"inline",marginLeft:"0.4rem"},children:[(0,e.jsx)("input",{type:"hidden",name:"_action",value:"delete"}),(0,e.jsx)("input",{type:"hidden",name:"id",value:o.id}),(0,e.jsx)("button",{type:"submit",style:n.danger,children:l.delete})]})]})]},o.id)),t.length===0?(0,e.jsx)("tr",{children:(0,e.jsx)("td",{style:n.empty,colSpan:5,children:s.empty})}):null]})]})}),(0,e.jsx)("h3",{style:n.h3,children:s.newHeading}),(0,e.jsxs)(m.Form,{method:"post",style:n.card,children:[(0,e.jsx)("input",{type:"hidden",name:"_action",value:"create"}),(0,e.jsx)(R,{label:s.appKey,hint:s.hintAppKey,children:(0,e.jsx)("input",{name:"appKey","aria-label":"app_key",required:!0,style:n.input})}),(0,e.jsx)(R,{label:s.resourceKey,hint:s.hintResourceKey,children:(0,e.jsx)("input",{name:"resourceKey","aria-label":"resource_key",required:!0,style:n.input})}),(0,e.jsx)(R,{label:s.name,children:(0,e.jsx)("input",{name:"name","aria-label":"name",required:!0,style:n.input})}),(0,e.jsx)(R,{label:s.description,hint:l.optional,children:(0,e.jsx)("input",{name:"description","aria-label":"description",style:n.input})}),(0,e.jsx)("button",{type:"submit",style:n.primary,children:l.add})]})]})}function ce({g:t,labels:r}){let s=r.common,[l,o]=(0,x.useState)({label:t.action,value:t.action});return(0,e.jsxs)("tr",{children:[(0,e.jsx)("td",{style:n.td,children:(0,e.jsx)("span",{style:n.code,children:t.roleKey})}),(0,e.jsx)("td",{style:n.td,children:(0,e.jsxs)("span",{style:n.code,children:[t.appKey,":",t.resourceKey]})}),(0,e.jsx)("td",{style:n.td,children:t.roleKey==="@anonymous"?(0,e.jsx)("span",{style:n.code,children:t.action}):(0,e.jsxs)(e.Fragment,{children:[(0,e.jsx)("input",{type:"hidden",name:"action",value:l.value,form:`save-grant-${t.id}`}),(0,e.jsx)(z.SelectBox,{options:W.AUTHZ_ACTIONS.map(c=>({label:c,value:c})),value:l,onChange:c=>{c&&o(c)}})]})}),(0,e.jsx)("td",{style:n.td,children:(0,e.jsx)("textarea",{name:"rowScope",defaultValue:t.rowScope??"",form:`save-grant-${t.id}`,"aria-label":`row_scope-${t.id}`,rows:2,placeholder:r.grants.rowScopePlaceholder,style:n.textarea})}),(0,e.jsx)("td",{style:n.td,children:(0,e.jsx)("textarea",{name:"columnScope",defaultValue:t.columnScope??"",form:`save-grant-${t.id}`,"aria-label":`column_scope-${t.id}`,rows:2,placeholder:r.grants.columnScopePlaceholder,style:n.textarea})}),(0,e.jsxs)("td",{style:{...n.td,whiteSpace:"nowrap"},children:[(0,e.jsxs)(m.Form,{method:"post",id:`save-grant-${t.id}`,style:{display:"inline"},children:[(0,e.jsx)("input",{type:"hidden",name:"_action",value:"save"}),(0,e.jsx)("input",{type:"hidden",name:"id",value:t.id}),(0,e.jsx)("button",{type:"submit",style:n.save,children:s.save})]}),(0,e.jsxs)(m.Form,{method:"post",style:{display:"inline",marginLeft:"0.4rem"},children:[(0,e.jsx)("input",{type:"hidden",name:"_action",value:"delete"}),(0,e.jsx)("input",{type:"hidden",name:"id",value:t.id}),(0,e.jsx)("button",{type:"submit",style:n.danger,children:s.delete})]})]})]})}function Q(){let{grants:t,roles:r,resources:s,labels:l}=(0,m.useLoaderData)(),o=l.grants,c=l.common,d=r.map(i=>({label:i.roleKey,value:i.id})),y=s.map(i=>({label:`${i.appKey}:${i.resourceKey}`,value:i.id})),h=W.AUTHZ_ACTIONS.map(i=>({label:i,value:i})),[g,A]=(0,x.useState)(void 0),[u,a]=(0,x.useState)(void 0),[f,p]=(0,x.useState)({label:"read",value:"read"});return(0,e.jsxs)("section",{children:[(0,e.jsx)("h2",{style:n.h2,children:o.heading}),(0,e.jsx)("p",{style:n.note,children:o.note}),(0,e.jsx)(I,{message:C((0,m.useActionData)())}),(0,e.jsx)("div",{style:n.tableContainer,children:(0,e.jsxs)("table",{style:n.table,children:[(0,e.jsx)("thead",{children:(0,e.jsxs)("tr",{children:[(0,e.jsx)("th",{style:{...n.th,width:"15%"},children:o.role}),(0,e.jsx)("th",{style:{...n.th,width:"20%"},children:o.resource}),(0,e.jsx)("th",{style:{...n.th,width:"15%"},children:o.action}),(0,e.jsx)("th",{style:{...n.th,width:"20%"},children:o.rowScope}),(0,e.jsx)("th",{style:{...n.th,width:"20%"},children:o.columnScope}),(0,e.jsx)("th",{style:{...n.th,width:"10%"}})]})}),(0,e.jsxs)("tbody",{children:[t.map(i=>(0,e.jsx)(ce,{g:i,labels:l},i.id)),t.length===0?(0,e.jsx)("tr",{children:(0,e.jsx)("td",{style:n.empty,colSpan:6,children:o.empty})}):null]})]})}),(0,e.jsx)("h3",{style:n.h3,children:o.newHeading}),(0,e.jsxs)(m.Form,{method:"post",style:n.card,children:[(0,e.jsx)("input",{type:"hidden",name:"_action",value:"create"}),(0,e.jsx)("input",{type:"hidden",name:"roleId",value:g?.value??""}),(0,e.jsx)("input",{type:"hidden",name:"resourceId",value:u?.value??""}),(0,e.jsx)("input",{type:"hidden",name:"action",value:f?.value??""}),(0,e.jsx)(R,{label:o.role,children:(0,e.jsx)(z.SelectBox,{options:d,value:g,onChange:i=>A(i||void 0),placeholder:o.selectPlaceholder})}),(0,e.jsx)(R,{label:o.resource,children:(0,e.jsx)(z.SelectBox,{options:y,value:u,onChange:i=>a(i||void 0),placeholder:o.selectPlaceholder})}),(0,e.jsx)(R,{label:o.action,children:(0,e.jsx)(z.SelectBox,{options:h,value:f,onChange:i=>p(i||void 0)})}),(0,e.jsx)(R,{label:o.rowScope,hint:o.rowScopeHint,children:(0,e.jsx)("textarea",{name:"rowScope","aria-label":"row_scope",rows:2,style:n.textarea,placeholder:'{"filters":[{"field":"\u90E8\u9580CD","op":"in","values":["A"]}]}'})}),(0,e.jsx)(R,{label:o.columnScope,hint:o.columnScopeHint,children:(0,e.jsx)("textarea",{name:"columnScope","aria-label":"column_scope",rows:2,style:n.textarea,placeholder:'{"mode":"deny","columns":["\u91D1\u984D"]}'})}),(0,e.jsx)("button",{type:"submit",style:n.primary,children:c.grant})]})]})}function Y(){let{assignments:t,roles:r,users:s,actorUserId:l,selfAdminRoleIds:o,labels:c}=(0,m.useLoaderData)(),d=c.userRoles,y=c.common,h=new Set(o??[]),g=s.map(i=>({label:`${i.email}\uFF08${i.displayName}\uFF09`,value:i.id})),A=r.filter(i=>i.roleKey!=="@authenticated"&&i.roleKey!=="@anonymous").map(i=>({label:i.roleKey,value:i.id})),[u,a]=(0,x.useState)(void 0),[f,p]=(0,x.useState)(void 0);return(0,e.jsxs)("section",{children:[(0,e.jsx)("h2",{style:n.h2,children:d.heading}),(0,e.jsx)(I,{message:C((0,m.useActionData)())}),(0,e.jsx)("p",{style:n.note,children:d.note}),(0,e.jsx)("div",{style:n.tableContainer,children:(0,e.jsxs)("table",{style:n.table,children:[(0,e.jsx)("thead",{children:(0,e.jsxs)("tr",{children:[(0,e.jsx)("th",{style:{...n.th,width:"45%"},children:d.user}),(0,e.jsx)("th",{style:{...n.th,width:"45%"},children:d.role}),(0,e.jsx)("th",{style:{...n.th,width:"10%"}})]})}),(0,e.jsxs)("tbody",{children:[t.map(i=>(0,e.jsxs)("tr",{children:[(0,e.jsxs)("td",{style:n.td,children:[i.email,(0,e.jsxs)("span",{style:n.muted,children:["\uFF08",i.displayName,"\uFF09"]})]}),(0,e.jsx)("td",{style:n.td,children:i.roleKey}),(0,e.jsx)("td",{style:n.td,children:(0,e.jsxs)(m.Form,{method:"post",style:{display:"inline"},children:[(0,e.jsx)("input",{type:"hidden",name:"_action",value:"remove"}),(0,e.jsx)("input",{type:"hidden",name:"userId",value:i.userId}),(0,e.jsx)("input",{type:"hidden",name:"roleId",value:i.roleId}),(0,e.jsx)("button",{type:"submit",style:n.danger,onClick:q(i.userId===l&&h.has(i.roleId),c.warn.selfAssignmentRemove),children:y.remove})]})})]},`${i.userId}-${i.roleId}`)),t.length===0?(0,e.jsx)("tr",{children:(0,e.jsx)("td",{style:n.empty,colSpan:3,children:d.empty})}):null]})]})}),(0,e.jsx)("h3",{style:n.h3,children:d.newHeading}),(0,e.jsxs)(m.Form,{method:"post",style:n.card,children:[(0,e.jsx)("input",{type:"hidden",name:"_action",value:"assign"}),(0,e.jsx)("input",{type:"hidden",name:"userId",value:u?.value??""}),(0,e.jsx)("input",{type:"hidden",name:"roleId",value:f?.value??""}),(0,e.jsx)(R,{label:d.user,children:(0,e.jsx)(z.SelectBox,{options:g,value:u,onChange:i=>a(i||void 0),placeholder:d.selectPlaceholder})}),(0,e.jsx)(R,{label:d.role,children:(0,e.jsx)(z.SelectBox,{options:A,value:f,onChange:i=>p(i||void 0),placeholder:d.selectPlaceholder})}),(0,e.jsx)("button",{type:"submit",style:n.primary,children:y.assign})]})]})}var me={roles:M,resources:J,role_permissions:Q,user_roles:Y};function pe(){let{segment:t}=(0,m.useLoaderData)(),r=me[t]??M;return(0,e.jsx)(B,{children:(0,e.jsx)(r,{})})}function ye(t){return t}var K=require("@aiquants/authz-core"),Z=require("react-router");function j(t,r){let s=(0,K.can)(r,"read"),l=(0,K.can)(r,"create"),o=(0,K.can)(r,"update"),c=(0,K.can)(r,"delete"),d=r?.scopeByAction.read,y=s&&!!d&&(d.rowScope!==null||d.columnScope!==null);return{resourceKey:t,read:s,create:l,update:o,delete:c,write:l||o,readPartial:y,actions:r?Array.from(r.actions):[]}}function ge(t){async function r(o,c,d){let y=d?.failureRedirect?()=>{throw(0,Z.redirect)(d.failureRedirect)}:t.onDeny;return(0,K.createRequirePermission)({resolveUserId:t.resolveUserId,getEffectivePermissions:t.getEffectivePermissions,onDeny:y})(o,{appKey:t.appKey,resourceKey:c.resourceKey,action:c.action})}async function s(o,c){let d=await t.resolveUserId(o),y={};for(let h of c.resourceKeys){let g=await t.getEffectivePermissions({userId:d??null,appKey:t.appKey,resourceKey:h});y[h]=j(h,g)}return y}async function l(o,c,d){let y=await r(o,c,d),h=await s(o,{resourceKeys:[c.resourceKey]});return{...y,permission:h[c.resourceKey]}}return{requirePermission:r,getMyPermissions:s,requireAndGetPermission:l}}0&&(module.exports={AuthzAdminAppView,AuthzErrorBoundary,AuthzGrantsView,AuthzLayout,AuthzResourcesView,AuthzRolesView,AuthzUserRolesView,ErrorAlert,Field,MyPermissionIndicator,MyPermissionStatus,createAuthz,createAuthzAdminApp,createAuthzAdminServer,defaultAuthzAdminLabels,defineResources,formatResourceTooltip,makeAuthzErrorBoundary,resolveLabels,toPermissionView,ui,usePermission});
|
|
2
3
|
//# sourceMappingURL=index.js.map
|