@aiquants/authz-react-router 0.3.0 → 0.4.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
@@ -92,11 +92,11 @@ WHERE r.role_key='viewer';
92
92
  import { MyPermissionIndicator, MyPermissionStatus } from "@aiquants/authz-react-router"
93
93
 
94
94
  // 1. Single indicator badge group
95
- <MyPermissionIndicator permission={myPermissions.report} resourceName="月次レポート" />
95
+ <MyPermissionIndicator permission={myPermissions.report} resourceName="Monthly Report" />
96
96
 
97
97
  // 2. Full "Your Permissions" status bar component for any page header/toolbar
98
- <MyPermissionStatus permission={myPermissions.report} resourceName="月次レポート" />
99
- // → "あなたの権限: [閲覧○][編集△][削除×]" with tooltip "対象リソース: 月次レポート (report)"
98
+ <MyPermissionStatus permission={myPermissions.report} resourceName="Monthly Report" />
99
+ // → "Your Permissions: [Read ○][Write △][Delete ×]" with tooltip "Target Resource: Monthly Report (report)"
100
100
  ```
101
101
 
102
102
  ## Scope cheat-sheet (§3.2)
@@ -121,8 +121,9 @@ Multiple roles **union** (wider wins): rows OR'd (any `NULL` ⇒ all rows); colu
121
121
  - `getMyPermissions(request, {resourceKeys})` → `Record<resourceKey, PermissionView>` for the UI.
122
122
  - `toPermissionView(resourceKey, perm)` → serializable view (loader → client).
123
123
  - `usePermission(view)` → ○△× display states (`readState`/`writeState`/`deleteState`); pure, safe in render.
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.
124
+ - `<MyPermissionIndicator permission={view} resourceName="Documents" 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="Documents" expectedResourceKey="documents" prefixLabel="Your Permissions" />` → Reusable status component combining prefix label and permission indicator badges for any application page.
126
+ - `<MyPermissionGroupStatus items={[{ resourceName: "Primary Resource", permission: primaryView }, { resourceName: "Sub Resource", permission: subView, level: 1 }]} variant="pills" | "popover" size="xs" labels={{ fullWrite: "Writable", readOnly: "Read-only" }} />` → Multi-resource permission widget for pages with multiple distinct resource scopes. Supports inline status tags (`variant="pills"`), single-button popover cards (`variant="popover"`), hierarchical tree indentation via `level` / `children`, and fully customizable status label mappings (`labels`).
126
127
 
127
128
  ## Demo App
128
129
 
@@ -133,7 +134,7 @@ This package contains an interactive React Router 7 SPA demo in the `demo/` subd
133
134
  - **Role-Based Access Control**: Demonstrates role switching (Admin, Manager, Operator, Reader) and how it affects UI elements.
134
135
  - **Route Guards**: Uses `authz.requirePermission` to protect routes and handle unauthorized access.
135
136
  - **Scope Verification**: Demonstrates `rowScope` (row filters) and `columnScope` (masked values) dynamically applied based on the active role's permissions.
136
- - **In-Browser Database Reset**: Includes a **「デモデータ初期化」 (Reset Demo Data)** button in the header of key views (Dashboard, Protected Documents, and Sales pages) to wipe customized roles, assignments, permissions, and CRUD data from `localStorage`, instantly restoring default test states.
137
+ - **In-Browser Database Reset**: Includes a **"Reset Demo Data"** button in the header of key views (Dashboard, Protected Documents, and Sales pages) to wipe customized roles, assignments, permissions, and CRUD data from `localStorage`, instantly restoring default test states.
137
138
 
138
139
  ### Running the Demo
139
140
 
package/dist/index.d.mts CHANGED
@@ -449,6 +449,77 @@ declare function ErrorAlert({ message }: {
449
449
  message?: string;
450
450
  }): react.JSX.Element | null;
451
451
 
452
+ type MyPermissionGroupItem = {
453
+ /** Expected or actual resource key */
454
+ resourceKey?: string;
455
+ /** Human-readable resource display name (e.g. "NI", "KT", "オリジナル") */
456
+ resourceName: string;
457
+ /** Permission view data for this resource */
458
+ permission: PermissionView | null | undefined;
459
+ /** Expected resource key to detect mismatches with permission.resourceKey during development */
460
+ expectedResourceKey?: string;
461
+ /** Nesting level for hierarchical rendering (0: root, 1: child, etc.) */
462
+ level?: number;
463
+ /** Optional child items for hierarchical rendering */
464
+ children?: MyPermissionGroupItem[];
465
+ };
466
+ /**
467
+ * Flattens hierarchical items tree into a single array with computed nesting levels.
468
+ * 木構造またはフラット配列のアイテムに level 属性を付与してフラット化する処理。
469
+ */
470
+ declare function flattenGroupItems(items: MyPermissionGroupItem[], currentLevel?: number): MyPermissionGroupItem[];
471
+ type MyPermissionGroupStatusProps = {
472
+ /** List of resources and their permissions */
473
+ items: MyPermissionGroupItem[];
474
+ /** Prefix label shown before group items or inside popover header. Default: "あなたの権限" */
475
+ prefixLabel?: string;
476
+ /**
477
+ * Display style variant:
478
+ * - "pills": Inline parent label + compact status tags per item
479
+ * - "popover": Compact single button trigger opening detailed popup card
480
+ * Default: "pills"
481
+ */
482
+ variant?: "pills" | "popover";
483
+ /**
484
+ * Component size variant:
485
+ * - "2xs": Ultra micro size for extremely dense UI
486
+ * - "xs": Extra small size for compact headers
487
+ * - "sm": Small size
488
+ * - "md": Standard default size
489
+ * - "lg": Larger size
490
+ * Default: "md"
491
+ */
492
+ size?: "2xs" | "xs" | "sm" | "md" | "lg";
493
+ labels?: {
494
+ read?: string;
495
+ write?: string;
496
+ delete?: string;
497
+ noPermission?: string;
498
+ fullWrite?: string;
499
+ partialWrite?: string;
500
+ readOnly?: string;
501
+ partialRead?: string;
502
+ };
503
+ className?: string;
504
+ style?: CSSProperties;
505
+ };
506
+ /**
507
+ * Get human-readable summary text and style for a resource permission.
508
+ * 権限状態から簡潔なサマリテキストとスタイルを判定 (カスタムラベル対応)。
509
+ */
510
+ declare function getPermissionSummary(permission: PermissionView | null | undefined, customLabels?: MyPermissionGroupStatusProps["labels"]): {
511
+ text: string;
512
+ color: string;
513
+ bgColor: string;
514
+ borderColor: string;
515
+ };
516
+ /**
517
+ * Multi-resource "Your Permissions" status component.
518
+ * Supports inline compact pills (Proposal 1) and dropdown popover card (Proposal 2).
519
+ * 複数リソースの権限状態を共通レイアウト(pills/popover)で綺麗に整列・表示するコンポーネント。
520
+ */
521
+ declare function MyPermissionGroupStatus({ items, prefixLabel, variant, size, labels, className, style }: MyPermissionGroupStatusProps): react.JSX.Element;
522
+
452
523
  type MyPermissionIndicatorProps = {
453
524
  permission: PermissionView | null | undefined;
454
525
  /** Human-readable resource display name (e.g. "文書データ"). Falls back to permission.resourceKey. */
@@ -502,12 +573,22 @@ type ResourceDefinition = {
502
573
  /** Optional description for administration UI */
503
574
  description?: string;
504
575
  };
576
+ type ResourceDefinitionInput = {
577
+ /** Optional explicit resource key; defaults to the object property name */
578
+ key?: string;
579
+ /** Human-readable display name (e.g. "文書管理") */
580
+ name: string;
581
+ /** Optional description for administration UI */
582
+ description?: string;
583
+ };
505
584
  type ResourceRegistry<T extends Record<string, ResourceDefinition>> = T;
506
585
  /**
507
586
  * Define type-safe resource registry for an application.
508
587
  * アプリ全体のリソース定義(キー・表示名・説明)を一元管理するヘルパー。
509
588
  */
510
- declare function defineResources<T extends Record<string, ResourceDefinition>>(resources: T): T;
589
+ declare function defineResources<T extends Record<string, ResourceDefinitionInput>>(resources: T): {
590
+ [K in keyof T & string]: ResourceDefinition;
591
+ };
511
592
 
512
593
  type PermState = "full" | "partial" | "none";
513
594
  type UsePermission = {
@@ -526,4 +607,4 @@ type UsePermission = {
526
607
  */
527
608
  declare function usePermission(view: PermissionView | null | undefined): UsePermission;
528
609
 
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 };
610
+ 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, type MyPermissionGroupItem, MyPermissionGroupStatus, type MyPermissionGroupStatusProps, MyPermissionIndicator, type MyPermissionIndicatorProps, MyPermissionStatus, type MyPermissionStatusProps, type PartialAuthzAdminLabels, type PermState, type PermissionView, type RequirePermissionOptions, type ResourceDefinition, type ResourceDefinitionInput, type ResourceRegistry, type UsePermission, createAuthz, createAuthzAdminApp, createAuthzAdminServer, defaultAuthzAdminLabels, defineResources, flattenGroupItems, formatResourceTooltip, getPermissionSummary, makeAuthzErrorBoundary, resolveLabels, toPermissionView, ui, usePermission };
package/dist/index.d.ts CHANGED
@@ -449,6 +449,77 @@ declare function ErrorAlert({ message }: {
449
449
  message?: string;
450
450
  }): react.JSX.Element | null;
451
451
 
452
+ type MyPermissionGroupItem = {
453
+ /** Expected or actual resource key */
454
+ resourceKey?: string;
455
+ /** Human-readable resource display name (e.g. "NI", "KT", "オリジナル") */
456
+ resourceName: string;
457
+ /** Permission view data for this resource */
458
+ permission: PermissionView | null | undefined;
459
+ /** Expected resource key to detect mismatches with permission.resourceKey during development */
460
+ expectedResourceKey?: string;
461
+ /** Nesting level for hierarchical rendering (0: root, 1: child, etc.) */
462
+ level?: number;
463
+ /** Optional child items for hierarchical rendering */
464
+ children?: MyPermissionGroupItem[];
465
+ };
466
+ /**
467
+ * Flattens hierarchical items tree into a single array with computed nesting levels.
468
+ * 木構造またはフラット配列のアイテムに level 属性を付与してフラット化する処理。
469
+ */
470
+ declare function flattenGroupItems(items: MyPermissionGroupItem[], currentLevel?: number): MyPermissionGroupItem[];
471
+ type MyPermissionGroupStatusProps = {
472
+ /** List of resources and their permissions */
473
+ items: MyPermissionGroupItem[];
474
+ /** Prefix label shown before group items or inside popover header. Default: "あなたの権限" */
475
+ prefixLabel?: string;
476
+ /**
477
+ * Display style variant:
478
+ * - "pills": Inline parent label + compact status tags per item
479
+ * - "popover": Compact single button trigger opening detailed popup card
480
+ * Default: "pills"
481
+ */
482
+ variant?: "pills" | "popover";
483
+ /**
484
+ * Component size variant:
485
+ * - "2xs": Ultra micro size for extremely dense UI
486
+ * - "xs": Extra small size for compact headers
487
+ * - "sm": Small size
488
+ * - "md": Standard default size
489
+ * - "lg": Larger size
490
+ * Default: "md"
491
+ */
492
+ size?: "2xs" | "xs" | "sm" | "md" | "lg";
493
+ labels?: {
494
+ read?: string;
495
+ write?: string;
496
+ delete?: string;
497
+ noPermission?: string;
498
+ fullWrite?: string;
499
+ partialWrite?: string;
500
+ readOnly?: string;
501
+ partialRead?: string;
502
+ };
503
+ className?: string;
504
+ style?: CSSProperties;
505
+ };
506
+ /**
507
+ * Get human-readable summary text and style for a resource permission.
508
+ * 権限状態から簡潔なサマリテキストとスタイルを判定 (カスタムラベル対応)。
509
+ */
510
+ declare function getPermissionSummary(permission: PermissionView | null | undefined, customLabels?: MyPermissionGroupStatusProps["labels"]): {
511
+ text: string;
512
+ color: string;
513
+ bgColor: string;
514
+ borderColor: string;
515
+ };
516
+ /**
517
+ * Multi-resource "Your Permissions" status component.
518
+ * Supports inline compact pills (Proposal 1) and dropdown popover card (Proposal 2).
519
+ * 複数リソースの権限状態を共通レイアウト(pills/popover)で綺麗に整列・表示するコンポーネント。
520
+ */
521
+ declare function MyPermissionGroupStatus({ items, prefixLabel, variant, size, labels, className, style }: MyPermissionGroupStatusProps): react.JSX.Element;
522
+
452
523
  type MyPermissionIndicatorProps = {
453
524
  permission: PermissionView | null | undefined;
454
525
  /** Human-readable resource display name (e.g. "文書データ"). Falls back to permission.resourceKey. */
@@ -502,12 +573,22 @@ type ResourceDefinition = {
502
573
  /** Optional description for administration UI */
503
574
  description?: string;
504
575
  };
576
+ type ResourceDefinitionInput = {
577
+ /** Optional explicit resource key; defaults to the object property name */
578
+ key?: string;
579
+ /** Human-readable display name (e.g. "文書管理") */
580
+ name: string;
581
+ /** Optional description for administration UI */
582
+ description?: string;
583
+ };
505
584
  type ResourceRegistry<T extends Record<string, ResourceDefinition>> = T;
506
585
  /**
507
586
  * Define type-safe resource registry for an application.
508
587
  * アプリ全体のリソース定義(キー・表示名・説明)を一元管理するヘルパー。
509
588
  */
510
- declare function defineResources<T extends Record<string, ResourceDefinition>>(resources: T): T;
589
+ declare function defineResources<T extends Record<string, ResourceDefinitionInput>>(resources: T): {
590
+ [K in keyof T & string]: ResourceDefinition;
591
+ };
511
592
 
512
593
  type PermState = "full" | "partial" | "none";
513
594
  type UsePermission = {
@@ -526,4 +607,4 @@ type UsePermission = {
526
607
  */
527
608
  declare function usePermission(view: PermissionView | null | undefined): UsePermission;
528
609
 
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 };
610
+ 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, type MyPermissionGroupItem, MyPermissionGroupStatus, type MyPermissionGroupStatusProps, MyPermissionIndicator, type MyPermissionIndicatorProps, MyPermissionStatus, type MyPermissionStatusProps, type PartialAuthzAdminLabels, type PermState, type PermissionView, type RequirePermissionOptions, type ResourceDefinition, type ResourceDefinitionInput, type ResourceRegistry, type UsePermission, createAuthz, createAuthzAdminApp, createAuthzAdminServer, defaultAuthzAdminLabels, defineResources, flattenGroupItems, formatResourceTooltip, getPermissionSummary, makeAuthzErrorBoundary, resolveLabels, toPermissionView, ui, usePermission };
package/dist/index.js CHANGED
@@ -1,3 +1,3 @@
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});
1
+ "use strict";var F=Object.defineProperty;var oe=Object.getOwnPropertyDescriptor;var se=Object.getOwnPropertyNames;var ie=Object.prototype.hasOwnProperty;var ae=(t,r)=>{for(var n in r)F(t,n,{get:r[n],enumerable:!0})},le=(t,r,n,i)=>{if(r&&typeof r=="object"||typeof r=="function")for(let o of se(r))!ie.call(t,o)&&o!==n&&F(t,o,{get:()=>r[o],enumerable:!(i=oe(r,o))||i.enumerable});return t};var de=t=>le(F({},"__esModule",{value:!0}),t);var xe={};ae(xe,{AuthzAdminAppView:()=>Se,AuthzErrorBoundary:()=>he,AuthzGrantsView:()=>ee,AuthzLayout:()=>fe,AuthzResourcesView:()=>X,AuthzRolesView:()=>B,AuthzUserRolesView:()=>te,ErrorAlert:()=>C,Field:()=>x,MyPermissionGroupStatus:()=>q,MyPermissionIndicator:()=>_,MyPermissionStatus:()=>ye,createAuthz:()=>Re,createAuthzAdminApp:()=>ce,createAuthzAdminServer:()=>T,defaultAuthzAdminLabels:()=>H,defineResources:()=>Ae,flattenGroupItems:()=>U,formatResourceTooltip:()=>W,getPermissionSummary:()=>Q,makeAuthzErrorBoundary:()=>Z,resolveLabels:()=>D,toPermissionView:()=>ne,ui:()=>s,usePermission:()=>M});module.exports=de(xe);var G=require("react-router");var z=require("@aiquants/authz-core"),R=require("react-router");var H={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 D(t){let r=H;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 ue=t=>t instanceof Response;function N(t){if(ue(t))throw t;if(t instanceof z.AuthzDeniedError)throw new Response(t.message,{status:403});return(0,R.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,n=t.resourceKey??"authz_admin",i=D(t.labels),o=async(u,a)=>{let{userId:y}=await t.requirePermission(u,a);if(y==null)throw new z.AuthzDeniedError({appKey:"",resourceKey:a.resourceKey,action:a.action,reason:"unresolved-user",userId:null});return{userId:y}};async function c(u){await t.requireUser(u);try{return await o(u,{resourceKey:n,action:"read"})}catch(a){throw a instanceof z.AuthzDeniedError?new Response(`Forbidden: ${n}`,{status:403}):a}}let l=u=>t.getMyPermissions(u,{resourceKeys:[n]}),p=async u=>{let[a,y]=await Promise.all([r.listRoles(),r.getSelfAdminContext(Number(u))]);return{roles:a,selfAdminRoleIds:y.selfAdminRoleIds,labels:i}},g=async()=>({resources:await r.listResources(),labels:i}),f=async()=>{let[u,a,y]=await Promise.all([r.listGrants(),r.listRoles(),r.listResources()]);return{grants:u,roles:a,resources:y,labels:i}},b=async u=>{let[a,y,m,d]=await Promise.all([r.listUserRoles(),r.listRoles(),r.listUsers(),r.getSelfAdminContext(Number(u))]);return{assignments:a,roles:y,users:m,actorUserId:d.actorUserId,selfAdminRoleIds:d.selfAdminRoleIds,labels:i}};return{labels:i,resourceKey:n,layoutGuard:c,loadMyPermissions:l,layout:{async loader({request:u}){return await c(u),{myPermissions:await l(u),labels:i,adminResourceKey:n}}},index:{loader(){throw(0,R.redirect)("/authz/roles")}},roles:{data:p,async loader({request:u}){let{userId:a}=await o(u,{resourceKey:n,action:"read"});return p(a)},async action({request:u}){let a=await u.formData(),y=String(a.get("_action"));try{switch(y){case"create":{let{userId:m}=await o(u,{resourceKey:n,action:"create"}),d=String(a.get("roleKey")??"").trim(),w=String(a.get("name")??"").trim();return d&&w?(await r.createRole({roleKey:d,name:w,description:String(a.get("description")??"").trim()||null},String(m)),{ok:!0}):(0,R.data)({error:"role_key \u3068 name \u306F\u5FC5\u9808\u3067\u3059"},{status:400})}case"save":{let{userId:m}=await o(u,{resourceKey:n,action:"update"}),d=String(a.get("roleKey")??"").trim(),w=String(a.get("name")??"").trim();return d&&w?(await r.updateRole(Number(a.get("id")),{roleKey:d,name:w,description:String(a.get("description")??"").trim()||null},String(m)),{ok:!0}):(0,R.data)({error:"roleKey \u3068 name \u306F\u5FC5\u9808\u3067\u3059"},{status:400})}case"toggle":{let{userId:m}=await o(u,{resourceKey:n,action:"update"});return await r.setRoleActive(Number(a.get("id")),a.get("isActive")==="true",String(m)),{ok:!0}}case"delete":return await o(u,{resourceKey:n,action:"delete"}),await r.deleteRole(Number(a.get("id"))),{ok:!0};default:return(0,R.data)({error:"unknown action"},{status:400})}}catch(m){return N(m)}}},resources:{data:g,async loader({request:u}){return await o(u,{resourceKey:n,action:"read"}),g()},async action({request:u}){let a=await u.formData(),y=String(a.get("_action"));try{switch(y){case"create":{let{userId:m}=await o(u,{resourceKey:n,action:"create"}),d=String(a.get("appKey")??"").trim(),w=String(a.get("resourceKey")??"").trim(),v=String(a.get("name")??"").trim();return d&&w&&v?(await r.createResource({appKey:d,resourceKey:w,name:v,description:String(a.get("description")??"").trim()||null},String(m)),{ok:!0}):(0,R.data)({error:"app_key / resource_key / name \u306F\u5FC5\u9808\u3067\u3059"},{status:400})}case"save":{let{userId:m}=await o(u,{resourceKey:n,action:"update"}),d=String(a.get("name")??"").trim();return d?(await r.updateResource(Number(a.get("id")),{name:d,description:String(a.get("description")??"").trim()||null},String(m)),{ok:!0}):(0,R.data)({error:"name \u306F\u5FC5\u9808\u3067\u3059"},{status:400})}case"delete":return await o(u,{resourceKey:n,action:"delete"}),await r.deleteResource(Number(a.get("id"))),{ok:!0};default:return(0,R.data)({error:"unknown action"},{status:400})}}catch(m){return N(m)}}},grants:{data:f,async loader({request:u}){return await o(u,{resourceKey:n,action:"read"}),f()},async action({request:u}){let a=await u.formData(),y=String(a.get("_action"));try{switch(y){case"create":{let{userId:m}=await o(u,{resourceKey:n,action:"create"}),d=Number(a.get("roleId")),w=Number(a.get("resourceId"));if(!(d&&w))return(0,R.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(!z.AUTHZ_ACTIONS.includes(v))return(0,R.data)({error:"\u7121\u52B9\u306A action \u3067\u3059"},{status:400});let E=v;return await r.createGrant({roleId:d,resourceId:w,action:E,rowScope:String(a.get("rowScope")??""),columnScope:String(a.get("columnScope")??"")},String(m)),{ok:!0}}case"save":{let{userId:m}=await o(u,{resourceKey:n,action:"update"}),d=String(a.get("action")??"");if(!z.AUTHZ_ACTIONS.includes(d))return(0,R.data)({error:"\u7121\u52B9\u306A action \u3067\u3059"},{status:400});let w=d;return await r.updateGrant(Number(a.get("id")),{action:w,rowScope:String(a.get("rowScope")??""),columnScope:String(a.get("columnScope")??"")},String(m)),{ok:!0}}case"delete":return await o(u,{resourceKey:n,action:"delete"}),await r.deleteGrant(Number(a.get("id"))),{ok:!0};default:return(0,R.data)({error:"unknown action"},{status:400})}}catch(m){return N(m)}}},userRoles:{data:b,async loader({request:u}){let{userId:a}=await o(u,{resourceKey:n,action:"read"});return b(a)},async action({request:u}){let a=await u.formData(),y=String(a.get("_action"));try{switch(y){case"assign":{let{userId:m}=await o(u,{resourceKey:n,action:"create"}),d=Number(a.get("userId")),w=Number(a.get("roleId"));return d&&w?(await r.assignUserRole(d,w,String(m)),{ok:!0}):(0,R.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:n,action:"delete"}),await r.removeUserRole(Number(a.get("userId")),Number(a.get("roleId"))),{ok:!0};default:return(0,R.data)({error:"unknown action"},{status:400})}}catch(m){return N(m)}}}}}function j(t){return String(t["*"]??"").split("/")[0]}function ce(t){let r=T(t),n=t.basePath??"/authz",i=["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 l(g){let f=j(g.params);if(!i.includes(f))throw(0,G.redirect)(`${n}/roles`);let{userId:b}=await r.layoutGuard(g.request),[u,a]=await Promise.all([r.loadMyPermissions(g.request),o[f](b)]);return{segment:f,basePath:n,myPermissions:u,adminResourceKey:r.resourceKey,...a}}async function p(g){let f=j(g.params),b=c[f];return b?b(g):(0,G.data)({error:"unknown action"},{status:400})}return{loader:l,action:p,server:r}}var I=require("react/jsx-runtime"),s={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 x({label:t,hint:r,children:n}){return(0,I.jsxs)("div",{style:{display:"flex",flexDirection:"column",gap:"0.3rem"},children:[(0,I.jsxs)("span",{style:{fontSize:"0.8rem",color:"#475569",fontWeight:600},children:[t,r?(0,I.jsxs)("span",{style:{fontWeight:400,color:"#94a3b8"},children:[" \u2014 ",r]}):null]}),n]})}function C({message:t}){return t?(0,I.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 V=require("@aiquants/authz-core"),K=require("@aiquants/select-box"),P=require("react"),h=require("react-router");var L=require("react");function M(t){let r=t?.read?t.readPartial?"partial":"full":"none",n=t?.create&&t?.update?"full":t?.create||t?.update?"partial":"none",i=t?.delete?"full":"none";return{canRead:!!t?.read,canWrite:!!t?.write,canDelete:!!t?.delete,readState:r,writeState:n,deleteState:i}}var A=require("react/jsx-runtime"),pe={full:{bg:"#ecfdf5",text:"#047857",border:"#a7f3d0"},partial:{bg:"#fffbeb",text:"#b45309",border:"#fde68a"},none:{bg:"#f8fafc",text:"#94a3b8",border:"#cbd5e1"}};function W(t,r){let n=t?.trim(),i=r?.trim();if(i&&n&&i!==n)return`\u5BFE\u8C61\u30EA\u30BD\u30FC\u30B9: ${i} (${n})`;if(i||n)return`\u5BFE\u8C61\u30EA\u30BD\u30FC\u30B9: ${i||n}`}function me({state:t}){return t==="full"?(0,A.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,A.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M5 13l4 4L19 7"})}):t==="partial"?(0,A.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,A.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,A.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,A.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 _({permission:t,resourceName:r,expectedResourceKey:n,showResourceTooltip:i=!0,labels:o,showScopeSummary:c=!0,className:l="authz-permission-indicator"}){let p=M(t),g={read:o?.read??"\u95B2\u89A7",write:o?.write??"\u7DE8\u96C6",delete:o?.delete??"\u524A\u9664"},f=t?.resourceKey,b=r||f,u=i?W(f,r):void 0,a=!!(n&&f&&f!==n);a&&typeof console<"u"&&typeof console.error=="function"&&console.error(`[Authz Warning] Resource key mismatch in MyPermissionIndicator! Expected: "${n}", but received permission for: "${f}".`);let y=(m,d,w)=>{let v=pe[d],E=u?`${w}: ${d}
2
+ ${u}`:`${w}: ${d}`;return(0,A.jsxs)("span",{"data-perm":m,"data-state":d,title:E,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,A.jsx)(me,{state:d}),(0,A.jsx)("span",{children:w})]})};return(0,A.jsxs)("span",{className:l,title:u,"data-resource":f??"","data-resource-name":b??"","data-mismatch":a?"true":void 0,style:{display:"inline-flex",gap:"0.35rem",alignItems:"center",verticalAlign:"middle"},children:[y("read",p.readState,g.read),y("write",p.writeState,g.write),y("delete",p.deleteState,g.delete),c&&p.readState==="partial"?(0,A.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,A.jsxs)("span",{"data-testid":"resource-mismatch-warning",title:`expected: "${n}", actual: "${f}"`,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 (",f," \u2260 ",n,")"]}):null]})}function ye({permission:t,resourceName:r,expectedResourceKey:n,prefixLabel:i="\u3042\u306A\u305F\u306E\u6A29\u9650",showPrefixLabel:o=!0,showResourceTooltip:c=!0,labels:l,showScopeSummary:p=!0,className:g="authz-permission-status",style:f}){let b=t?.resourceKey,u=r||b,a=c?W(b,r):void 0;return(0,A.jsxs)("span",{className:g,title:a,"data-testid":"my-permission-status","data-resource":b??"","data-resource-name":u??"",style:{fontSize:"0.82rem",color:"#475569",display:"inline-flex",alignItems:"center",gap:"0.4rem",...f},children:[o&&(0,A.jsxs)("span",{"data-testid":"prefix-label",children:[i,":"]}),(0,A.jsx)(_,{permission:t,resourceName:r,expectedResourceKey:n,showResourceTooltip:c,labels:l,showScopeSummary:p})]})}var S=require("react/jsx-runtime");function U(t,r=0){let n=[];for(let i of t){let o=i.level??r;n.push({...i,level:o}),i.children&&i.children.length>0&&n.push(...U(i.children,o+1))}return n}var J={"2xs":{fontSize:"0.6rem",pillPadding:"0.05rem 0.25rem",pillGap:"0.15rem",wrapperGap:"0.15rem",triggerPadding:"0.1rem 0.35rem",triggerFontSize:"0.62rem",badgeFontSize:"0.58rem"},xs:{fontSize:"0.65rem",pillPadding:"0.08rem 0.35rem",pillGap:"0.18rem",wrapperGap:"0.2rem",triggerPadding:"0.12rem 0.4rem",triggerFontSize:"0.68rem",badgeFontSize:"0.62rem"},sm:{fontSize:"0.72rem",pillPadding:"0.1rem 0.4rem",pillGap:"0.2rem",wrapperGap:"0.25rem",triggerPadding:"0.15rem 0.45rem",triggerFontSize:"0.72rem",badgeFontSize:"0.65rem"},md:{fontSize:"0.78rem",pillPadding:"0.15rem 0.5rem",pillGap:"0.3rem",wrapperGap:"0.35rem",triggerPadding:"0.2rem 0.6rem",triggerFontSize:"0.78rem",badgeFontSize:"0.7rem"},lg:{fontSize:"0.85rem",pillPadding:"0.25rem 0.65rem",pillGap:"0.4rem",wrapperGap:"0.45rem",triggerPadding:"0.25rem 0.75rem",triggerFontSize:"0.85rem",badgeFontSize:"0.75rem"}};function Q(t,r){let n=r?.noPermission??"\u6A29\u9650\u306A\u3057",i=r?.fullWrite??"\u7DE8\u96C6\u53EF",o=r?.partialRead??"\u4E00\u90E8\u95B2\u89A7",c=r?.readOnly??"\u95B2\u89A7\u306E\u307F";return t&&(t.read||t.write||t.delete)?t.write?{text:i,color:"#047857",bgColor:"#ecfdf5",borderColor:"#a7f3d0"}:t.read?t.readPartial?{text:o,color:"#b45309",bgColor:"#fffbeb",borderColor:"#fde68a"}:{text:c,color:"#1d4ed8",bgColor:"#eff6ff",borderColor:"#bfdbfe"}:{text:n,color:"#64748b",bgColor:"#f1f5f9",borderColor:"#cbd5e1"}:{text:n,color:"#64748b",bgColor:"#f1f5f9",borderColor:"#cbd5e1"}}function ge({item:t,size:r="md",labels:n}){let i=Q(t.permission,n),o=t.permission?.resourceKey||t.resourceKey||t.expectedResourceKey,c=t.resourceName||o,l=!!(t.expectedResourceKey&&t.permission?.resourceKey&&t.permission.resourceKey!==t.expectedResourceKey),p=J[r],g=`\u5BFE\u8C61: ${c}${o?` (${o})`:""}${t.permission?` | ${n?.read??"\u95B2\u89A7"}:${t.permission.read?"\u25CB":"\xD7"} ${n?.write??"\u7DE8\u96C6"}:${t.permission.write?"\u25CB":"\xD7"} ${n?.delete??"\u524A\u9664"}:${t.permission.delete?"\u25CB":"\xD7"}`:""}`;return(0,S.jsxs)("span",{title:g,"data-testid":`permission-pill-${t.resourceName}`,"data-mismatch":l?"true":"false",style:{display:"inline-flex",alignItems:"center",gap:p.pillGap,fontSize:p.fontSize,padding:p.pillPadding,borderRadius:"9999px",backgroundColor:l?"#fee2e2":i.bgColor,color:l?"#991b1b":i.color,border:`1px solid ${l?"#fca5a5":i.borderColor}`,fontWeight:600,lineHeight:"1.2"},children:[(0,S.jsxs)("span",{children:[c,":"]}),(0,S.jsx)("span",{children:i.text}),l&&(0,S.jsx)("span",{title:`expected "${t.expectedResourceKey}", actual "${t.permission?.resourceKey}"`,children:"\u26A0\uFE0F"})]})}function q({items:t,prefixLabel:r="\u3042\u306A\u305F\u306E\u6A29\u9650",variant:n="pills",size:i="md",labels:o,className:c="authz-permission-group-status",style:l}){let[p,g]=(0,L.useState)(!1),f=(0,L.useRef)(null),b=J[i];if((0,L.useEffect)(()=>{if(n!=="popover"||!p)return;function u(y){f.current&&!f.current.contains(y.target)&&g(!1)}function a(y){y.key==="Escape"&&g(!1)}return document.addEventListener("mousedown",u),document.addEventListener("keydown",a),()=>{document.removeEventListener("mousedown",u),document.removeEventListener("keydown",a)}},[n,p]),n==="popover"){let u=t.filter(m=>m.permission?.write).length,a=t.length,y=u===a?o?.fullWrite??"\u7DE8\u96C6\u53EF":u>0?o?.partialWrite??"\u4E00\u90E8\u7DE8\u96C6\u53EF":o?.readOnly??"\u95B2\u89A7\u306E\u307F";return(0,S.jsxs)("span",{ref:f,className:c,"data-testid":"my-permission-group-popover",style:{position:"relative",display:"inline-block",...l},children:[(0,S.jsxs)("button",{type:"button",onClick:()=>g(!p),"data-testid":"permission-popover-trigger",style:{display:"inline-flex",alignItems:"center",gap:b.wrapperGap,fontSize:b.triggerFontSize,padding:b.triggerPadding,borderRadius:"6px",backgroundColor:"#f8fafc",color:"#334155",border:"1px solid #cbd5e1",fontWeight:600,cursor:"pointer"},children:[(0,S.jsxs)("span",{children:["\u{1F512} ",r]}),(0,S.jsxs)("span",{style:{fontSize:b.badgeFontSize,color:"#64748b"},children:["(",y,")"]}),(0,S.jsx)("span",{style:{fontSize:"0.65rem",marginLeft:"0.1rem"},children:p?"\u25B2":"\u25BE"})]}),p&&(0,S.jsxs)("div",{"data-testid":"permission-popover-card",style:{position:"absolute",top:"calc(100% + 6px)",right:0,zIndex:50,minWidth:"280px",whiteSpace:"nowrap",padding:"0.75rem 0.85rem",backgroundColor:"#ffffff",borderRadius:"8px",boxShadow:"0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)",border:"1px solid #e2e8f0",fontSize:"0.82rem"},children:[(0,S.jsxs)("div",{style:{display:"flex",alignItems:"center",justifyContent:"space-between",marginBottom:"0.5rem",paddingBottom:"0.4rem",borderBottom:"1px solid #f1f5f9",fontWeight:700,color:"#1e293b",whiteSpace:"nowrap"},children:[(0,S.jsxs)("span",{children:["\u{1F512} ",r]}),(0,S.jsx)("button",{type:"button",onClick:()=>g(!1),style:{border:"none",background:"none",cursor:"pointer",color:"#94a3b8",fontSize:"0.85rem",padding:"0 0.2rem"},children:"\u2715"})]}),(0,S.jsx)("div",{style:{display:"flex",flexDirection:"column",gap:"0.4rem"},children:U(t).map(m=>{let d=m.level??0,w=d>0;return(0,S.jsxs)("div",{style:{display:"flex",alignItems:"center",justifyContent:"space-between",gap:"1.25rem",whiteSpace:"nowrap",paddingLeft:w?`${d*.85}rem`:"0"},children:[(0,S.jsxs)("div",{style:{display:"inline-flex",alignItems:"center",whiteSpace:"nowrap"},children:[w&&(0,S.jsx)("span",{"aria-hidden":"true",style:{display:"inline-block",width:"10px",height:"10px",borderLeft:"1.5px solid #cbd5e1",borderBottom:"1.5px solid #cbd5e1",borderBottomLeftRadius:"3px",marginRight:"6px",marginTop:"-4px",flexShrink:0}}),(0,S.jsxs)("span",{style:{fontWeight:w?500:600,color:w?"#64748b":"#1e293b",fontSize:w?"0.78rem":"0.82rem",whiteSpace:"nowrap"},children:[m.resourceName,":"]})]}),(0,S.jsx)(_,{permission:m.permission,resourceName:m.resourceName,expectedResourceKey:m.expectedResourceKey,labels:o})]},m.resourceName)})})]})]})}return(0,S.jsxs)("span",{className:c,"data-testid":"my-permission-group-pills",style:{display:"inline-flex",alignItems:"center",flexWrap:"wrap",gap:b.pillGap,fontSize:b.fontSize,color:"#475569",...l},children:[r&&(0,S.jsxs)("span",{style:{fontWeight:600,color:"#334155"},children:[r,":"]}),(0,S.jsx)("span",{style:{display:"inline-flex",alignItems:"center",flexWrap:"wrap",gap:b.pillGap},children:t.map(u=>(0,S.jsx)(ge,{item:u,size:i,labels:o},u.resourceName))})]})}var e=require("react/jsx-runtime"),$=t=>t?.error;function Y({children:t}){let{myPermissions:r,labels:n,adminResourceKey:i,basePath:o}=(0,h.useLoaderData)(),c=o??"/authz",[l,p]=(0,P.useState)("pills"),g=[["roles",n.tabs.roles],["resources",n.tabs.resources],["role_permissions",n.tabs.role_permissions],["user_roles",n.tabs.user_roles]],f=Object.entries(r||{}).map(([u,a])=>({resourceKey:u,resourceName:a?.resourceKey||u,permission:a,expectedResourceKey:u})),b=f.length>0?f:[{resourceKey:i,resourceName:i,permission:r?.[i],expectedResourceKey:i}];return(0,e.jsxs)("div",{className:"authz-admin",style:s.page,children:[(0,e.jsxs)("header",{style:{display:"flex",alignItems:"center",justifyContent:"space-between",gap:"0.75rem",flexWrap:"wrap",margin:"0 0 0.4rem"},children:[(0,e.jsx)("h1",{style:{fontSize:"1.15rem",margin:0,fontWeight:700,color:"#1e293b"},children:n.title}),(0,e.jsxs)("div",{style:{display:"flex",alignItems:"center",gap:"0.4rem"},children:[(0,e.jsx)(q,{prefixLabel:n.myPermission,items:b,variant:l,size:"xs"}),(0,e.jsxs)("div",{style:{display:"inline-flex",borderRadius:"4px",border:"1px solid #cbd5e1",padding:"1px",backgroundColor:"#f8fafc",fontSize:"0.7rem"},children:[(0,e.jsx)("button",{type:"button",onClick:()=>p("pills"),"data-testid":"switch-variant-pills",style:{padding:"1px 5px",borderRadius:"3px",border:"none",cursor:"pointer",fontSize:"0.7rem",lineHeight:"1.2",fontWeight:l==="pills"?600:400,backgroundColor:l==="pills"?"#ffffff":"transparent",color:l==="pills"?"#1e293b":"#64748b",boxShadow:l==="pills"?"0 1px 2px rgba(0,0,0,0.05)":"none"},children:"Pills"}),(0,e.jsx)("button",{type:"button",onClick:()=>p("popover"),"data-testid":"switch-variant-popover",style:{padding:"1px 5px",borderRadius:"3px",border:"none",cursor:"pointer",fontSize:"0.7rem",lineHeight:"1.2",fontWeight:l==="popover"?600:400,backgroundColor:l==="popover"?"#ffffff":"transparent",color:l==="popover"?"#1e293b":"#64748b",boxShadow:l==="popover"?"0 1px 2px rgba(0,0,0,0.05)":"none"},children:"Popover"})]})]})]}),(0,e.jsx)("nav",{style:{display:"flex",gap:"0.25rem",borderBottom:"1px solid #e2e8f0",margin:"0.6rem 0 1rem"},children:g.map(([u,a])=>(0,e.jsx)(h.NavLink,{to:`${c}/${u}`,style:({isActive:y})=>({padding:"0.5rem 0.9rem",textDecoration:"none",color:y?"#2563eb":"#475569",borderBottom:y?"2px solid #2563eb":"2px solid transparent",marginBottom:-1,fontWeight:y?700:500,fontSize:"0.92rem"}),children:a},u))}),t]})}function fe(){return(0,e.jsx)(Y,{children:(0,e.jsx)(h.Outlet,{})})}function Z(t){let r=D(t).error;return function(){let i=(0,h.useRouteError)(),o=(0,h.isRouteErrorResponse)(i)?i:null,c=o?.status===403,l=c?r.forbiddenTitle:o?`${r.genericTitlePrefix} (${o.status})`:r.genericTitle,p=c?r.forbiddenBody:o?typeof o.data=="string"&&o.data?o.data:o.statusText:r.genericBody;return(0,e.jsx)("div",{style:s.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:p})]})})}}var he=Z(),O=(t,r)=>n=>{t&&!window.confirm(r)&&n.preventDefault()};function B(){let{roles:t,selfAdminRoleIds:r,labels:n}=(0,h.useLoaderData)(),i=n.roles,o=n.common,c=new Set(r??[]);return(0,e.jsxs)("section",{children:[(0,e.jsx)("h2",{style:s.h2,children:i.heading}),(0,e.jsx)(C,{message:$((0,h.useActionData)())}),(0,e.jsx)("p",{style:s.note,children:i.note}),(0,e.jsx)("div",{style:s.tableContainer,children:(0,e.jsxs)("table",{style:s.table,children:[(0,e.jsx)("thead",{children:(0,e.jsxs)("tr",{children:[(0,e.jsx)("th",{style:{...s.th,width:"20%"},children:i.roleKey}),(0,e.jsx)("th",{style:{...s.th,width:"25%"},children:i.name}),(0,e.jsx)("th",{style:{...s.th,width:"35%"},children:i.description}),(0,e.jsx)("th",{style:{...s.th,width:"10%"},children:i.activeHeader}),(0,e.jsx)("th",{style:{...s.th,width:"10%"}})]})}),(0,e.jsxs)("tbody",{children:[t.map(l=>(0,e.jsxs)("tr",{children:[(0,e.jsx)("td",{style:s.td,children:l.roleKey==="@authenticated"||l.roleKey==="@anonymous"?(0,e.jsx)("span",{style:s.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:s.input})}),(0,e.jsx)("td",{style:s.td,children:(0,e.jsx)("input",{name:"name",defaultValue:l.name,form:`save-role-${l.id}`,"aria-label":`name-${l.id}`,required:!0,style:s.input})}),(0,e.jsx)("td",{style:s.td,children:(0,e.jsx)("input",{name:"description",defaultValue:l.description??"",form:`save-role-${l.id}`,"aria-label":`description-${l.id}`,style:s.input})}),(0,e.jsx)("td",{style:s.td,children:(0,e.jsxs)(h.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:s.button,onClick:l.isActive?O(c.has(l.id),n.warn.selfRoleDisable):void 0,children:l.isActive?o.active:o.inactive})]})}),(0,e.jsxs)("td",{style:{...s.td,whiteSpace:"nowrap"},children:[(0,e.jsxs)(h.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:s.save,children:o.save})]}),(0,e.jsxs)(h.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:s.danger,onClick:O(c.has(l.id),n.warn.selfRoleDelete),children:o.delete})]})]})]},l.id)),t.length===0?(0,e.jsx)("tr",{children:(0,e.jsx)("td",{style:s.empty,colSpan:5,children:i.empty})}):null]})]})}),(0,e.jsx)("h3",{style:s.h3,children:i.newHeading}),(0,e.jsxs)(h.Form,{method:"post",style:s.card,children:[(0,e.jsx)("input",{type:"hidden",name:"_action",value:"create"}),(0,e.jsx)(x,{label:i.roleKey,hint:i.hintRoleKey,children:(0,e.jsx)("input",{name:"roleKey","aria-label":"role_key",required:!0,style:s.input})}),(0,e.jsx)(x,{label:i.name,children:(0,e.jsx)("input",{name:"name","aria-label":"name",required:!0,style:s.input})}),(0,e.jsx)(x,{label:i.description,hint:o.optional,children:(0,e.jsx)("input",{name:"description","aria-label":"description",style:s.input})}),(0,e.jsx)("button",{type:"submit",style:s.primary,children:o.add})]})]})}function X(){let{resources:t,labels:r}=(0,h.useLoaderData)(),n=r.resources,i=r.common;return(0,e.jsxs)("section",{children:[(0,e.jsx)("h2",{style:s.h2,children:n.heading}),(0,e.jsx)(C,{message:$((0,h.useActionData)())}),(0,e.jsx)("p",{style:s.note,children:n.note}),(0,e.jsx)("div",{style:s.tableContainer,children:(0,e.jsxs)("table",{style:s.table,children:[(0,e.jsx)("thead",{children:(0,e.jsxs)("tr",{children:[(0,e.jsx)("th",{style:{...s.th,width:"15%"},children:n.appKey}),(0,e.jsx)("th",{style:{...s.th,width:"20%"},children:n.resourceKey}),(0,e.jsx)("th",{style:{...s.th,width:"25%"},children:n.name}),(0,e.jsx)("th",{style:{...s.th,width:"30%"},children:n.description}),(0,e.jsx)("th",{style:{...s.th,width:"10%"}})]})}),(0,e.jsxs)("tbody",{children:[t.map(o=>(0,e.jsxs)("tr",{children:[(0,e.jsx)("td",{style:s.td,children:(0,e.jsx)("span",{style:s.code,children:o.appKey})}),(0,e.jsx)("td",{style:s.td,children:(0,e.jsx)("span",{style:s.code,children:o.resourceKey})}),(0,e.jsx)("td",{style:s.td,children:(0,e.jsx)("input",{name:"name",defaultValue:o.name,form:`save-res-${o.id}`,"aria-label":`name-${o.id}`,required:!0,style:s.input})}),(0,e.jsx)("td",{style:s.td,children:(0,e.jsx)("input",{name:"description",defaultValue:o.description??"",form:`save-res-${o.id}`,"aria-label":`description-${o.id}`,style:s.input})}),(0,e.jsxs)("td",{style:{...s.td,whiteSpace:"nowrap"},children:[(0,e.jsxs)(h.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:s.save,children:i.save})]}),(0,e.jsxs)(h.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:s.danger,children:i.delete})]})]})]},o.id)),t.length===0?(0,e.jsx)("tr",{children:(0,e.jsx)("td",{style:s.empty,colSpan:5,children:n.empty})}):null]})]})}),(0,e.jsx)("h3",{style:s.h3,children:n.newHeading}),(0,e.jsxs)(h.Form,{method:"post",style:s.card,children:[(0,e.jsx)("input",{type:"hidden",name:"_action",value:"create"}),(0,e.jsx)(x,{label:n.appKey,hint:n.hintAppKey,children:(0,e.jsx)("input",{name:"appKey","aria-label":"app_key",required:!0,style:s.input})}),(0,e.jsx)(x,{label:n.resourceKey,hint:n.hintResourceKey,children:(0,e.jsx)("input",{name:"resourceKey","aria-label":"resource_key",required:!0,style:s.input})}),(0,e.jsx)(x,{label:n.name,children:(0,e.jsx)("input",{name:"name","aria-label":"name",required:!0,style:s.input})}),(0,e.jsx)(x,{label:n.description,hint:i.optional,children:(0,e.jsx)("input",{name:"description","aria-label":"description",style:s.input})}),(0,e.jsx)("button",{type:"submit",style:s.primary,children:i.add})]})]})}function be({g:t,labels:r}){let n=r.common,[i,o]=(0,P.useState)({label:t.action,value:t.action});return(0,e.jsxs)("tr",{children:[(0,e.jsx)("td",{style:s.td,children:(0,e.jsx)("span",{style:s.code,children:t.roleKey})}),(0,e.jsx)("td",{style:s.td,children:(0,e.jsxs)("span",{style:s.code,children:[t.appKey,":",t.resourceKey]})}),(0,e.jsx)("td",{style:s.td,children:t.roleKey==="@anonymous"?(0,e.jsx)("span",{style:s.code,children:t.action}):(0,e.jsxs)(e.Fragment,{children:[(0,e.jsx)("input",{type:"hidden",name:"action",value:i.value,form:`save-grant-${t.id}`}),(0,e.jsx)(K.SelectBox,{options:V.AUTHZ_ACTIONS.map(c=>({label:c,value:c})),value:i,onChange:c=>{c&&o(c)}})]})}),(0,e.jsx)("td",{style:s.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:s.textarea})}),(0,e.jsx)("td",{style:s.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:s.textarea})}),(0,e.jsxs)("td",{style:{...s.td,whiteSpace:"nowrap"},children:[(0,e.jsxs)(h.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:s.save,children:n.save})]}),(0,e.jsxs)(h.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:s.danger,children:n.delete})]})]})]})}function ee(){let{grants:t,roles:r,resources:n,labels:i}=(0,h.useLoaderData)(),o=i.grants,c=i.common,l=r.map(d=>({label:d.roleKey,value:d.id})),p=n.map(d=>({label:`${d.appKey}:${d.resourceKey}`,value:d.id})),g=V.AUTHZ_ACTIONS.map(d=>({label:d,value:d})),[f,b]=(0,P.useState)(void 0),[u,a]=(0,P.useState)(void 0),[y,m]=(0,P.useState)({label:"read",value:"read"});return(0,e.jsxs)("section",{children:[(0,e.jsx)("h2",{style:s.h2,children:o.heading}),(0,e.jsx)("p",{style:s.note,children:o.note}),(0,e.jsx)(C,{message:$((0,h.useActionData)())}),(0,e.jsx)("div",{style:s.tableContainer,children:(0,e.jsxs)("table",{style:s.table,children:[(0,e.jsx)("thead",{children:(0,e.jsxs)("tr",{children:[(0,e.jsx)("th",{style:{...s.th,width:"15%"},children:o.role}),(0,e.jsx)("th",{style:{...s.th,width:"20%"},children:o.resource}),(0,e.jsx)("th",{style:{...s.th,width:"15%"},children:o.action}),(0,e.jsx)("th",{style:{...s.th,width:"20%"},children:o.rowScope}),(0,e.jsx)("th",{style:{...s.th,width:"20%"},children:o.columnScope}),(0,e.jsx)("th",{style:{...s.th,width:"10%"}})]})}),(0,e.jsxs)("tbody",{children:[t.map(d=>(0,e.jsx)(be,{g:d,labels:i},d.id)),t.length===0?(0,e.jsx)("tr",{children:(0,e.jsx)("td",{style:s.empty,colSpan:6,children:o.empty})}):null]})]})}),(0,e.jsx)("h3",{style:s.h3,children:o.newHeading}),(0,e.jsxs)(h.Form,{method:"post",style:s.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:y?.value??""}),(0,e.jsx)(x,{label:o.role,children:(0,e.jsx)(K.SelectBox,{options:l,value:f,onChange:d=>b(d||void 0),placeholder:o.selectPlaceholder})}),(0,e.jsx)(x,{label:o.resource,children:(0,e.jsx)(K.SelectBox,{options:p,value:u,onChange:d=>a(d||void 0),placeholder:o.selectPlaceholder})}),(0,e.jsx)(x,{label:o.action,children:(0,e.jsx)(K.SelectBox,{options:g,value:y,onChange:d=>m(d||void 0)})}),(0,e.jsx)(x,{label:o.rowScope,hint:o.rowScopeHint,children:(0,e.jsx)("textarea",{name:"rowScope","aria-label":"row_scope",rows:2,style:s.textarea,placeholder:'{"filters":[{"field":"\u90E8\u9580CD","op":"in","values":["A"]}]}'})}),(0,e.jsx)(x,{label:o.columnScope,hint:o.columnScopeHint,children:(0,e.jsx)("textarea",{name:"columnScope","aria-label":"column_scope",rows:2,style:s.textarea,placeholder:'{"mode":"deny","columns":["\u91D1\u984D"]}'})}),(0,e.jsx)("button",{type:"submit",style:s.primary,children:c.grant})]})]})}function te(){let{assignments:t,roles:r,users:n,actorUserId:i,selfAdminRoleIds:o,labels:c}=(0,h.useLoaderData)(),l=c.userRoles,p=c.common,g=new Set(o??[]),f=n.map(d=>({label:`${d.email}\uFF08${d.displayName}\uFF09`,value:d.id})),b=r.filter(d=>d.roleKey!=="@authenticated"&&d.roleKey!=="@anonymous").map(d=>({label:d.roleKey,value:d.id})),[u,a]=(0,P.useState)(void 0),[y,m]=(0,P.useState)(void 0);return(0,e.jsxs)("section",{children:[(0,e.jsx)("h2",{style:s.h2,children:l.heading}),(0,e.jsx)(C,{message:$((0,h.useActionData)())}),(0,e.jsx)("p",{style:s.note,children:l.note}),(0,e.jsx)("div",{style:s.tableContainer,children:(0,e.jsxs)("table",{style:s.table,children:[(0,e.jsx)("thead",{children:(0,e.jsxs)("tr",{children:[(0,e.jsx)("th",{style:{...s.th,width:"45%"},children:l.user}),(0,e.jsx)("th",{style:{...s.th,width:"45%"},children:l.role}),(0,e.jsx)("th",{style:{...s.th,width:"10%"}})]})}),(0,e.jsxs)("tbody",{children:[t.map(d=>(0,e.jsxs)("tr",{children:[(0,e.jsxs)("td",{style:s.td,children:[d.email,(0,e.jsxs)("span",{style:s.muted,children:["\uFF08",d.displayName,"\uFF09"]})]}),(0,e.jsx)("td",{style:s.td,children:d.roleKey}),(0,e.jsx)("td",{style:s.td,children:(0,e.jsxs)(h.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:d.userId}),(0,e.jsx)("input",{type:"hidden",name:"roleId",value:d.roleId}),(0,e.jsx)("button",{type:"submit",style:s.danger,onClick:O(d.userId===i&&g.has(d.roleId),c.warn.selfAssignmentRemove),children:p.remove})]})})]},`${d.userId}-${d.roleId}`)),t.length===0?(0,e.jsx)("tr",{children:(0,e.jsx)("td",{style:s.empty,colSpan:3,children:l.empty})}):null]})]})}),(0,e.jsx)("h3",{style:s.h3,children:l.newHeading}),(0,e.jsxs)(h.Form,{method:"post",style:s.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:y?.value??""}),(0,e.jsx)(x,{label:l.user,children:(0,e.jsx)(K.SelectBox,{options:f,value:u,onChange:d=>a(d||void 0),placeholder:l.selectPlaceholder})}),(0,e.jsx)(x,{label:l.role,children:(0,e.jsx)(K.SelectBox,{options:b,value:y,onChange:d=>m(d||void 0),placeholder:l.selectPlaceholder})}),(0,e.jsx)("button",{type:"submit",style:s.primary,children:p.assign})]})]})}var we={roles:B,resources:X,role_permissions:ee,user_roles:te};function Se(){let{segment:t}=(0,h.useLoaderData)(),r=we[t]??B;return(0,e.jsx)(Y,{children:(0,e.jsx)(r,{})})}function Ae(t){let r={};for(let n of Object.keys(t)){let i=t[n];r[n]={key:i.key??n,name:i.name,description:i.description}}return r}var k=require("@aiquants/authz-core"),re=require("react-router");function ne(t,r){let n=(0,k.can)(r,"read"),i=(0,k.can)(r,"create"),o=(0,k.can)(r,"update"),c=(0,k.can)(r,"delete"),l=r?.scopeByAction.read,p=n&&!!l&&(l.rowScope!==null||l.columnScope!==null);return{resourceKey:t,read:n,create:i,update:o,delete:c,write:i||o,readPartial:p,actions:r?Array.from(r.actions):[]}}function Re(t){async function r(o,c,l){let p=l?.failureRedirect?()=>{throw(0,re.redirect)(l.failureRedirect)}:t.onDeny;return(0,k.createRequirePermission)({resolveUserId:t.resolveUserId,getEffectivePermissions:t.getEffectivePermissions,onDeny:p})(o,{appKey:t.appKey,resourceKey:c.resourceKey,action:c.action})}async function n(o,c){let l=await t.resolveUserId(o),p={};for(let g of c.resourceKeys){let f=await t.getEffectivePermissions({userId:l??null,appKey:t.appKey,resourceKey:g});p[g]=ne(g,f)}return p}async function i(o,c,l){let p=await r(o,c,l),g=await n(o,{resourceKeys:[c.resourceKey]});return{...p,permission:g[c.resourceKey]}}return{requirePermission:r,getMyPermissions:n,requireAndGetPermission:i}}0&&(module.exports={AuthzAdminAppView,AuthzErrorBoundary,AuthzGrantsView,AuthzLayout,AuthzResourcesView,AuthzRolesView,AuthzUserRolesView,ErrorAlert,Field,MyPermissionGroupStatus,MyPermissionIndicator,MyPermissionStatus,createAuthz,createAuthzAdminApp,createAuthzAdminServer,defaultAuthzAdminLabels,defineResources,flattenGroupItems,formatResourceTooltip,getPermissionSummary,makeAuthzErrorBoundary,resolveLabels,toPermissionView,ui,usePermission});
3
3
  //# sourceMappingURL=index.js.map