@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 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
- <MyPermissionIndicator permission={myPermissions.report} /> // → 読○ 書△ 削除×
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
- declare function MyPermissionIndicator({ permission, labels, showScopeSummary, className }: MyPermissionIndicatorProps): react.JSX.Element;
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
- declare function MyPermissionIndicator({ permission, labels, showScopeSummary, className }: MyPermissionIndicatorProps): react.JSX.Element;
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