@aiquants/authz-react-router 0.2.4 → 0.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +0 -4
- package/dist/index.d.ts +0 -4
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -3
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/admin/app.ts","../src/admin/server.ts","../src/admin/labels.ts","../src/admin/ui.tsx","../src/admin/views.tsx","../src/usePermission.ts","../src/MyPermissionIndicator.tsx","../src/server.ts"],"sourcesContent":["export * from \"./admin/app\"\nexport * from \"./admin/labels\"\nexport * from \"./admin/server\"\nexport * from \"./admin/ui\"\nexport * from \"./admin/views\"\nexport * from \"./MyPermissionIndicator\"\nexport * from \"./server\"\nexport * from \"./usePermission\"\n","/**\n * 認可管理 UI を **スプラット 1 ルート(`authz/*`)** にマウントするためのサーバ結線。\n * `routes.ts` の 1 エントリ + 極小のマウントファイル 1 個だけで全タブを提供できる\n * (タブごとのルートディレクトリ/ファイルが不要)。\n *\n * 返り値の `loader`/`action` は store 依存(サーバ)。Component は store 非依存の\n * `AuthzAdminAppView`(views.tsx)を、ErrorBoundary は `makeAuthzErrorBoundary` を使う。\n */\nimport { data, redirect } from \"react-router\"\nimport { type CreateAuthzAdminServerOptions, createAuthzAdminServer } from \"./server\"\n\ntype RouteArgs = { request: Request; params: Record<string, string | undefined> }\n\nexport type CreateAuthzAdminAppOptions = CreateAuthzAdminServerOptions & {\n /** マウントのベースパス(タブリンク/未指定セグメントのリダイレクト先)。既定 `/authz`。 */\n basePath?: string\n}\n\n/** スプラット param(\"*\")から先頭セグメントを取り出す(`roles/...` → `roles`)。 */\nfunction segmentOf(params: Record<string, string | undefined>): string {\n return String(params[\"*\"] ?? \"\").split(\"/\")[0]\n}\n\nexport function createAuthzAdminApp(opts: CreateAuthzAdminAppOptions) {\n const server = createAuthzAdminServer(opts)\n const basePath = opts.basePath ?? \"/authz\"\n const SEGMENTS = [\"roles\", \"resources\", \"role_permissions\", \"user_roles\"] as const\n // データ取得(ガード無し)。ガードはスプラット loader で 1 回だけ行い、userId を渡す。\n const segmentData = { roles: server.roles.data, resources: server.resources.data, role_permissions: server.grants.data, user_roles: server.userRoles.data }\n const actions = { roles: server.roles.action, resources: server.resources.action, role_permissions: server.grants.action, user_roles: server.userRoles.action }\n\n async function loader(args: RouteArgs) {\n const segment = segmentOf(args.params)\n if (!(SEGMENTS as readonly string[]).includes(segment)) throw redirect(`${basePath}/roles`)\n // ガードは 1 回だけ(requireUser + requirePermission(read))。userId を取り回して再ガードしない。\n const { userId } = await server.layoutGuard(args.request)\n const [myPermissions, segData] = await Promise.all([server.loadMyPermissions(args.request), segmentData[segment as (typeof SEGMENTS)[number]](userId)])\n // segData は labels を含む(各 data 関数が付与)。myPermissions/adminResourceKey はレイアウト殻用。\n return { segment, basePath, myPermissions, adminResourceKey: server.resourceKey, ...segData }\n }\n\n async function action(args: RouteArgs) {\n const segment = segmentOf(args.params)\n const act = actions[segment as (typeof SEGMENTS)[number]]\n if (!act) return data({ error: \"unknown action\" }, { status: 400 })\n return act(args)\n }\n\n // server: 個別タブの loader/action を露出(統合テスト等から直接呼ぶ用)。\n return { loader, action, server }\n}\n","/**\n * 認可管理 UI のサーバ結線(loader/action 工場)。store ポート + アプリのガード/セッションを束ね、\n * 各ルートの loader/action を生成する。返り値の loader データには解決済みラベルを含める。\n * store(drizzle)を渡すのはこの工場の呼び出し側(アプリのサーバモジュール)に限る。\n */\nimport { AUTHZ_ACTIONS, type AuthzAction, type AuthzAdminStore, AuthzDeniedError } from \"@aiquants/authz-core\"\nimport { data, redirect } from \"react-router\"\nimport type { PermissionView } from \"../server\"\nimport { type AuthzAdminLabels, type PartialAuthzAdminLabels, resolveLabels } from \"./labels\"\nimport type { AuthzGrantsData, AuthzLayoutData, AuthzResourcesData, AuthzRolesData, AuthzUserRolesData } from \"./views\"\n\ntype Req = { request: Request }\ntype PermissionQuery = { resourceKey: string; action: AuthzAction }\n\nexport type CreateAuthzAdminServerOptions = {\n store: AuthzAdminStore\n /** 管理画面のガード資源キー(既定 `authz_admin`)。 */\n resourceKey?: string\n /** 未ログインをログインへ誘導する(例: throw redirect(...))。 */\n requireUser: (request: Request) => Promise<unknown>\n /**\n * 認可ガード(アプリの createAuthz 由来)。allow で { userId } を返す。\n * 0.2.0 で GuardResult.userId が nullable 化したため、戻り型も null を受ける。\n * userId==null(未解決/万一の public 付与)は createAuthzAdminServer 内で deny する\n * (管理経路は監査・自己権限計算に実 id が必須のため非 null を保証)。\n */\n requirePermission: (request: Request, query: PermissionQuery) => Promise<{ userId: string | number | null }>\n /** 自己権限表示用(アプリの createAuthz 由来)。 */\n getMyPermissions: (request: Request, args: { resourceKeys: string[] }) => Promise<Record<string, PermissionView>>\n /** 文言の部分上書き(既定は日本語)。 */\n labels?: PartialAuthzAdminLabels\n}\n\nconst isResponse = (e: unknown): e is Response => e instanceof Response\n\n/** action 内の例外を 403(認可拒否のみ)/ 400(検証等)へ変換する。 */\nfunction toActionError(e: unknown) {\n if (isResponse(e)) throw e\n if (e instanceof AuthzDeniedError) throw new Response(e.message, { status: 403 })\n return data({ error: e instanceof Error ? e.message : \"エラーが発生しました\" }, { status: 400 })\n}\n\nexport function createAuthzAdminServer(opts: CreateAuthzAdminServerOptions) {\n const store = opts.store\n const RES = opts.resourceKey ?? \"authz_admin\"\n const labels: AuthzAdminLabels = resolveLabels(opts.labels)\n // 未解決ユーザー(userId==null)を境界で 1 回だけ deny。これ以降の userId は非 null 保証。\n // 管理リソースは public を付与しない前提だが、防御的に拒否する(監査/自己権限計算に実 id が必須)。\n const requirePermission = async (request: Request, query: PermissionQuery): Promise<{ userId: string | number }> => {\n const { userId } = await opts.requirePermission(request, query)\n if (userId == null) {\n throw new AuthzDeniedError({ appKey: \"\", resourceKey: query.resourceKey, action: query.action, reason: \"unresolved-user\", userId: null })\n }\n return { userId }\n }\n\n /** レイアウトガード: requireUser(302) → requirePermission(read, 403)。userId を返す(1 回だけ実行)。 */\n async function layoutGuard(request: Request): Promise<{ userId: string | number }> {\n await opts.requireUser(request)\n try {\n return await requirePermission(request, { resourceKey: RES, action: \"read\" })\n } catch (e) {\n if (e instanceof AuthzDeniedError) throw new Response(`Forbidden: ${RES}`, { status: 403 })\n throw e\n }\n }\n /** 自己権限(インジケータ表示用)。 */\n const loadMyPermissions = (request: Request) => opts.getMyPermissions(request, { resourceKeys: [RES] })\n\n // ---- データ取得(ガード無し)。ガード済みの userId を受け取る(resources/grants は未使用)。 ----\n const rolesData = async (userId?: string | number): Promise<AuthzRolesData> => {\n const [roles, self] = await Promise.all([store.listRoles(), store.getSelfAdminContext(Number(userId))])\n return { roles, selfAdminRoleIds: self.selfAdminRoleIds, labels }\n }\n const resourcesData = async (): Promise<AuthzResourcesData> => ({ resources: await store.listResources(), labels })\n const grantsData = async (): Promise<AuthzGrantsData> => {\n const [grants, roles, resources] = await Promise.all([store.listGrants(), store.listRoles(), store.listResources()])\n return { grants, roles, resources, labels }\n }\n const userRolesData = async (userId?: string | number): Promise<AuthzUserRolesData> => {\n const [assignments, roles, users, self] = await Promise.all([store.listUserRoles(), store.listRoles(), store.listUsers(), store.getSelfAdminContext(Number(userId))])\n return { assignments, roles, users, actorUserId: self.actorUserId, selfAdminRoleIds: self.selfAdminRoleIds, labels }\n }\n\n return {\n /** 露出: スプラットマウント(app.ts)がガードを 1 回だけ行うために使う。 */\n labels,\n resourceKey: RES,\n layoutGuard,\n loadMyPermissions,\n\n /** /authz レイアウト: requireUser(302) → requirePermission(read, 403) → 自己権限取得。 */\n layout: {\n async loader({ request }: Req): Promise<AuthzLayoutData> {\n await layoutGuard(request)\n return { myPermissions: await loadMyPermissions(request), labels, adminResourceKey: RES }\n },\n },\n\n /** /authz index → roles へ。 */\n index: {\n loader() {\n throw redirect(\"/authz/roles\")\n },\n },\n\n roles: {\n data: rolesData,\n async loader({ request }: Req): Promise<AuthzRolesData> {\n const { userId } = await requirePermission(request, { resourceKey: RES, action: \"read\" })\n return rolesData(userId)\n },\n async action({ request }: Req) {\n const form = await request.formData()\n const intent = String(form.get(\"_action\"))\n try {\n switch (intent) {\n case \"create\": {\n const { userId } = await requirePermission(request, { resourceKey: RES, action: \"create\" })\n const roleKey = String(form.get(\"roleKey\") ?? \"\").trim()\n const name = String(form.get(\"name\") ?? \"\").trim()\n if (!(roleKey && name)) return data({ error: \"role_key と name は必須です\" }, { status: 400 })\n await store.createRole({ roleKey, name, description: String(form.get(\"description\") ?? \"\").trim() || null }, String(userId))\n return { ok: true }\n }\n case \"save\": {\n const { userId } = await requirePermission(request, { resourceKey: RES, action: \"update\" })\n const name = String(form.get(\"name\") ?? \"\").trim()\n if (!name) return data({ error: \"name は必須です\" }, { status: 400 })\n await store.updateRole(Number(form.get(\"id\")), { name, description: String(form.get(\"description\") ?? \"\").trim() || null }, String(userId))\n return { ok: true }\n }\n case \"toggle\": {\n const { userId } = await requirePermission(request, { resourceKey: RES, action: \"update\" })\n await store.setRoleActive(Number(form.get(\"id\")), form.get(\"isActive\") === \"true\", String(userId))\n return { ok: true }\n }\n case \"delete\": {\n await requirePermission(request, { resourceKey: RES, action: \"delete\" })\n await store.deleteRole(Number(form.get(\"id\")))\n return { ok: true }\n }\n default:\n return data({ error: \"unknown action\" }, { status: 400 })\n }\n } catch (e) {\n return toActionError(e)\n }\n },\n },\n\n resources: {\n data: resourcesData,\n async loader({ request }: Req): Promise<AuthzResourcesData> {\n await requirePermission(request, { resourceKey: RES, action: \"read\" })\n return resourcesData()\n },\n async action({ request }: Req) {\n const form = await request.formData()\n const intent = String(form.get(\"_action\"))\n try {\n switch (intent) {\n case \"create\": {\n const { userId } = await requirePermission(request, { resourceKey: RES, action: \"create\" })\n const appKey = String(form.get(\"appKey\") ?? \"\").trim()\n const resourceKey = String(form.get(\"resourceKey\") ?? \"\").trim()\n const name = String(form.get(\"name\") ?? \"\").trim()\n if (!(appKey && resourceKey && name)) return data({ error: \"app_key / resource_key / name は必須です\" }, { status: 400 })\n await store.createResource({ appKey, resourceKey, name, description: String(form.get(\"description\") ?? \"\").trim() || null }, String(userId))\n return { ok: true }\n }\n case \"save\": {\n const { userId } = await requirePermission(request, { resourceKey: RES, action: \"update\" })\n const name = String(form.get(\"name\") ?? \"\").trim()\n if (!name) return data({ error: \"name は必須です\" }, { status: 400 })\n await store.updateResource(Number(form.get(\"id\")), { name, description: String(form.get(\"description\") ?? \"\").trim() || null }, String(userId))\n return { ok: true }\n }\n case \"delete\": {\n await requirePermission(request, { resourceKey: RES, action: \"delete\" })\n await store.deleteResource(Number(form.get(\"id\")))\n return { ok: true }\n }\n default:\n return data({ error: \"unknown action\" }, { status: 400 })\n }\n } catch (e) {\n return toActionError(e)\n }\n },\n },\n\n grants: {\n data: grantsData,\n async loader({ request }: Req): Promise<AuthzGrantsData> {\n await requirePermission(request, { resourceKey: RES, action: \"read\" })\n return grantsData()\n },\n async action({ request }: Req) {\n const form = await request.formData()\n const intent = String(form.get(\"_action\"))\n try {\n switch (intent) {\n case \"create\": {\n const { userId } = await requirePermission(request, { resourceKey: RES, action: \"create\" })\n const roleId = Number(form.get(\"roleId\"))\n const resourceId = Number(form.get(\"resourceId\"))\n if (!(roleId && resourceId)) return data({ error: \"ロールとリソースを選択してください\" }, { status: 400 })\n const rawAction = String(form.get(\"action\") ?? \"\")\n if (!(AUTHZ_ACTIONS as readonly string[]).includes(rawAction)) return data({ error: \"無効な action です\" }, { status: 400 })\n const action = rawAction as AuthzAction\n await store.createGrant({ roleId, resourceId, action, rowScope: String(form.get(\"rowScope\") ?? \"\"), columnScope: String(form.get(\"columnScope\") ?? \"\") }, String(userId))\n return { ok: true }\n }\n case \"save\": {\n const { userId } = await requirePermission(request, { resourceKey: RES, action: \"update\" })\n await store.updateGrant(Number(form.get(\"id\")), { rowScope: String(form.get(\"rowScope\") ?? \"\"), columnScope: String(form.get(\"columnScope\") ?? \"\") }, String(userId))\n return { ok: true }\n }\n case \"delete\": {\n await requirePermission(request, { resourceKey: RES, action: \"delete\" })\n await store.deleteGrant(Number(form.get(\"id\")))\n return { ok: true }\n }\n default:\n return data({ error: \"unknown action\" }, { status: 400 })\n }\n } catch (e) {\n return toActionError(e)\n }\n },\n },\n\n userRoles: {\n data: userRolesData,\n async loader({ request }: Req): Promise<AuthzUserRolesData> {\n const { userId } = await requirePermission(request, { resourceKey: RES, action: \"read\" })\n return userRolesData(userId)\n },\n async action({ request }: Req) {\n const form = await request.formData()\n const intent = String(form.get(\"_action\"))\n try {\n switch (intent) {\n case \"assign\": {\n const { userId: actor } = await requirePermission(request, { resourceKey: RES, action: \"create\" })\n const userId = Number(form.get(\"userId\"))\n const roleId = Number(form.get(\"roleId\"))\n if (!(userId && roleId)) return data({ error: \"ユーザーとロールを選択してください\" }, { status: 400 })\n await store.assignUserRole(userId, roleId, String(actor))\n return { ok: true }\n }\n case \"remove\": {\n await requirePermission(request, { resourceKey: RES, action: \"delete\" })\n await store.removeUserRole(Number(form.get(\"userId\")), Number(form.get(\"roleId\")))\n return { ok: true }\n }\n default:\n return data({ error: \"unknown action\" }, { status: 400 })\n }\n } catch (e) {\n return toActionError(e)\n }\n },\n },\n }\n}\n","/** Authz admin UI strings (i18n). Defaults are English; override per-section via `createAuthzAdminRoutes(..., { labels })`. */\nexport type AuthzAdminLabels = {\n title: string\n myPermission: string\n tabs: { roles: string; resources: string; role_permissions: string; user_roles: string }\n common: { add: string; save: string; delete: string; remove: string; assign: string; grant: string; select: string; active: string; inactive: string; optional: string }\n roles: { heading: string; note: string; roleKey: string; name: string; description: string; activeHeader: string; empty: string; newHeading: string; hintRoleKey: string }\n resources: { heading: string; note: string; appKey: string; resourceKey: string; name: string; description: string; empty: string; newHeading: string; hintAppKey: string; hintResourceKey: string; hintDailyReport: string }\n grants: {\n heading: string\n note: string\n role: string\n resource: string\n action: string\n rowScope: string\n columnScope: string\n empty: string\n newHeading: string\n rowScopeHint: string\n columnScopeHint: string\n rowScopePlaceholder: string\n columnScopePlaceholder: string\n nullRows: string\n nullCols: string\n selectPlaceholder: string\n }\n userRoles: { heading: string; user: string; role: string; empty: string; newHeading: string; selectPlaceholder: string }\n error: { forbiddenTitle: string; forbiddenBody: string; genericTitlePrefix: string; genericTitle: string; genericBody: string }\n warn: { selfRoleDisable: string; selfRoleDelete: string; selfAssignmentRemove: string }\n}\n\nexport const defaultAuthzAdminLabels: AuthzAdminLabels = {\n title: \"Authorization (RBAC)\",\n myPermission: \"Your permissions\",\n tabs: { roles: \"Roles\", resources: \"Resources\", role_permissions: \"Permissions\", user_roles: \"User assignments\" },\n common: { add: \"Add\", save: \"Save\", delete: \"Delete\", remove: \"Remove\", assign: \"Assign\", grant: \"Grant\", select: \"Select…\", active: \"○ Enabled\", inactive: \"× Disabled\", optional: \"optional\" },\n roles: {\n heading: \"Roles (TMRole)\",\n note: \"Edit name / description inline and click Save (role_key is an immutable identifier).\",\n roleKey: \"role_key\",\n name: \"name\",\n description: \"description\",\n activeHeader: \"Active\",\n empty: \"No roles\",\n newHeading: \"New role\",\n hintRoleKey: \"e.g. admin\",\n },\n resources: {\n heading: \"Resources (TMResource)\",\n note: \"Edit name / description inline and click Save (app_key / resource_key are immutable identifiers).\",\n appKey: \"app_key\",\n resourceKey: \"resource_key\",\n name: \"name\",\n description: \"description\",\n empty: \"No resources\",\n newHeading: \"New resource\",\n hintAppKey: \"e.g. quants\",\n hintResourceKey: \"e.g. daily_report\",\n hintDailyReport: \"optional\",\n },\n grants: {\n heading: \"Permissions (TDRolePermission)\",\n note: \"Empty row_scope / column_scope = all rows / all columns (NULL). JSON must satisfy the §3.2 contract.\",\n role: \"role\",\n resource: \"resource\",\n action: \"action\",\n rowScope: \"row_scope\",\n columnScope: \"column_scope\",\n empty: \"No permissions\",\n newHeading: \"Grant a permission\",\n rowScopeHint: \"JSON / empty = all rows\",\n columnScopeHint: \"JSON / empty = all columns\",\n rowScopePlaceholder: \"empty = all rows (NULL)\",\n columnScopePlaceholder: \"empty = all columns (NULL)\",\n nullRows: \"NULL (all rows)\",\n nullCols: \"NULL (all columns)\",\n selectPlaceholder: \"Select…\",\n },\n userRoles: { heading: \"User assignments (TDUserRole)\", user: \"user\", role: \"role\", empty: \"No assignments\", newHeading: \"Assign a role\", selectPlaceholder: \"Select…\" },\n error: {\n forbiddenTitle: \"Access denied\",\n forbiddenBody: \"You don't have permission to view this screen. Ask an administrator to grant access.\",\n genericTitlePrefix: \"Error\",\n genericTitle: \"An error occurred\",\n genericBody: \"An unexpected error occurred. Please try again later.\",\n },\n warn: {\n selfRoleDisable: \"This role backs your own authorization-admin access. Disabling it may lock you out of this screen. Continue?\",\n selfRoleDelete: \"This role backs your own authorization-admin access. Deleting it may lock you out of this screen. Continue?\",\n selfAssignmentRemove: \"This assignment backs your own authorization-admin access. Removing it may lock you out of this screen. Continue?\",\n },\n}\n\nexport type PartialAuthzAdminLabels = {\n title?: string\n myPermission?: string\n tabs?: Partial<AuthzAdminLabels[\"tabs\"]>\n common?: Partial<AuthzAdminLabels[\"common\"]>\n roles?: Partial<AuthzAdminLabels[\"roles\"]>\n resources?: Partial<AuthzAdminLabels[\"resources\"]>\n grants?: Partial<AuthzAdminLabels[\"grants\"]>\n userRoles?: Partial<AuthzAdminLabels[\"userRoles\"]>\n error?: Partial<AuthzAdminLabels[\"error\"]>\n warn?: Partial<AuthzAdminLabels[\"warn\"]>\n}\n\n/** Shallow per-section merge over the English defaults. */\nexport function resolveLabels(over?: PartialAuthzAdminLabels): AuthzAdminLabels {\n const d = defaultAuthzAdminLabels\n if (!over) return d\n return {\n title: over.title ?? d.title,\n myPermission: over.myPermission ?? d.myPermission,\n tabs: { ...d.tabs, ...over.tabs },\n common: { ...d.common, ...over.common },\n roles: { ...d.roles, ...over.roles },\n resources: { ...d.resources, ...over.resources },\n grants: { ...d.grants, ...over.grants },\n userRoles: { ...d.userRoles, ...over.userRoles },\n error: { ...d.error, ...over.error },\n warn: { ...d.warn, ...over.warn },\n }\n}\n","/** 認可管理UI 共有のプレゼンテーション部品・スタイル。 */\nimport type { CSSProperties, ReactNode } from \"react\"\n\nexport const ui: Record<string, CSSProperties> = {\n page: { padding: \"1.25rem\", maxWidth: 1120, margin: \"0 auto\", color: \"#0f172a\" },\n table: { borderCollapse: \"collapse\", width: \"100%\", fontSize: \"0.9rem\" },\n th: { textAlign: \"left\", borderBottom: \"2px solid #e2e8f0\", padding: \"0.45rem 0.65rem\", fontSize: \"0.78rem\", color: \"#475569\", fontWeight: 600, textTransform: \"uppercase\", letterSpacing: \"0.03em\" },\n td: { borderBottom: \"1px solid #f1f5f9\", padding: \"0.5rem 0.65rem\", verticalAlign: \"middle\" },\n input: { padding: \"0.4rem 0.55rem\", border: \"1px solid #cbd5e1\", borderRadius: 6, fontSize: \"0.9rem\", background: \"#fff\", width: \"100%\", boxSizing: \"border-box\" },\n select: { padding: \"0.4rem 0.55rem\", border: \"1px solid #cbd5e1\", borderRadius: 6, fontSize: \"0.9rem\", background: \"#fff\", width: \"100%\", boxSizing: \"border-box\" },\n 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\" },\n button: { padding: \"0.3rem 0.7rem\", border: \"1px solid #cbd5e1\", borderRadius: 6, background: \"#fff\", cursor: \"pointer\", fontSize: \"0.82rem\", color: \"#334155\" },\n save: { padding: \"0.3rem 0.7rem\", border: \"1px solid #2563eb\", borderRadius: 6, background: \"#eff6ff\", cursor: \"pointer\", fontSize: \"0.82rem\", color: \"#2563eb\", fontWeight: 600 },\n danger: { padding: \"0.3rem 0.7rem\", border: \"1px solid #fecaca\", borderRadius: 6, background: \"#fff\", cursor: \"pointer\", fontSize: \"0.82rem\", color: \"#dc2626\" },\n 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\" },\n 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\" },\n code: { fontFamily: \"ui-monospace, SFMono-Regular, Menlo, monospace\", fontSize: \"0.78rem\", color: \"#334155\", wordBreak: \"break-all\" },\n muted: { color: \"#94a3b8\" },\n h2: { fontSize: \"1.05rem\", margin: \"0 0 0.35rem\", fontWeight: 700 },\n h3: { fontSize: \"0.92rem\", margin: \"1.25rem 0 0\", color: \"#334155\", fontWeight: 600 },\n note: { color: \"#64748b\", fontSize: \"0.82rem\", margin: \"0 0 0.75rem\" },\n empty: { color: \"#94a3b8\", padding: \"0.75rem 0.65rem\" },\n}\n\n/**\n * ラベルを上、コントロールを下に縦積みするフィールド(重なり防止・一貫レイアウト)。\n * コントロール側は `aria-label` を持つ前提なので `<div>` で構成する。\n */\nexport function Field({ label, hint, children }: { label: string; hint?: string; children: ReactNode }) {\n return (\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: \"0.3rem\" }}>\n <span style={{ fontSize: \"0.8rem\", color: \"#475569\", fontWeight: 600 }}>\n {label}\n {hint ? <span style={{ fontWeight: 400, color: \"#94a3b8\" }}> — {hint}</span> : null}\n </span>\n {children}\n </div>\n )\n}\n\n/** エラー表示(role=\"alert\")。 */\nexport function ErrorAlert({ message }: { message?: string }) {\n if (!message) return null\n return (\n <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\" }}>\n {message}\n </p>\n )\n}\n","/**\n * 認可管理 UI のプレゼンテーション部品(client-safe)。\n * loader データ(行 + ラベル + 自己管理者ヒント)を `useLoaderData` で受け取り描画する。\n * DB/ストアには一切依存しない(サーバ結線は admin/server.ts)。\n */\nimport { AUTHZ_ACTIONS, type AuthzAssignment, type AuthzGrant, type AuthzResource, type AuthzRole, type AuthzUser } from \"@aiquants/authz-core\"\nimport { Form, isRouteErrorResponse, NavLink, Outlet, useActionData, useLoaderData, useRouteError } from \"react-router\"\nimport { MyPermissionIndicator } from \"../MyPermissionIndicator\"\nimport type { PermissionView } from \"../server\"\nimport { type AuthzAdminLabels, type PartialAuthzAdminLabels, resolveLabels } from \"./labels\"\nimport { ErrorAlert, Field, ui } from \"./ui\"\n\ntype WithLabels = { labels: AuthzAdminLabels }\ntype ActionError = { error?: string } | undefined\nconst actionError = (d: ActionError) => d?.error\n\n// ============================ Layout ============================\n\nexport type AuthzLayoutData = WithLabels & { myPermissions: Record<string, PermissionView>; adminResourceKey: string; basePath?: string }\n\n/** ヘッダ(タイトル + あなたの権限) + タブ。中身は children(splat) か Outlet(ネスト)。 */\nfunction AuthzLayoutShell({ children }: { children: React.ReactNode }) {\n const { myPermissions, labels, adminResourceKey, basePath } = useLoaderData() as AuthzLayoutData\n const base = basePath ?? \"/authz\"\n const tabs: ReadonlyArray<readonly [string, string]> = [\n [\"roles\", labels.tabs.roles],\n [\"resources\", labels.tabs.resources],\n [\"role_permissions\", labels.tabs.role_permissions],\n [\"user_roles\", labels.tabs.user_roles],\n ]\n return (\n <div className=\"authz-admin\" style={ui.page}>\n <header style={{ display: \"flex\", alignItems: \"baseline\", justifyContent: \"space-between\", gap: \"1rem\", flexWrap: \"wrap\" }}>\n <h1 style={{ fontSize: \"1.3rem\", margin: 0, fontWeight: 700 }}>{labels.title}</h1>\n <span style={{ fontSize: \"0.82rem\", color: \"#475569\", display: \"inline-flex\", alignItems: \"center\", gap: \"0.4rem\" }}>\n {labels.myPermission}: <MyPermissionIndicator permission={myPermissions[adminResourceKey]} />\n </span>\n </header>\n <nav style={{ display: \"flex\", gap: \"0.25rem\", borderBottom: \"1px solid #e2e8f0\", margin: \"0.9rem 0 1.25rem\" }}>\n {tabs.map(([key, label]) => (\n <NavLink\n key={key}\n to={`${base}/${key}`}\n style={({ isActive }) => ({\n padding: \"0.5rem 0.9rem\",\n textDecoration: \"none\",\n color: isActive ? \"#2563eb\" : \"#475569\",\n borderBottom: isActive ? \"2px solid #2563eb\" : \"2px solid transparent\",\n marginBottom: -1,\n fontWeight: isActive ? 700 : 500,\n fontSize: \"0.92rem\",\n })}>\n {label}\n </NavLink>\n ))}\n </nav>\n {children}\n </div>\n )\n}\n\n/** ネストルート用レイアウト(子は Outlet)。`routes.ts` でネスト構成にする場合に使う。 */\nexport function AuthzLayout() {\n return (\n <AuthzLayoutShell>\n <Outlet />\n </AuthzLayoutShell>\n )\n}\n\n/**\n * 認可管理 UI のエラー境界。ErrorBoundary は loader データを読めないため、ラベルは\n * `makeAuthzErrorBoundary(labels)` で注入する(アプリは自分のロケールで生成する)。\n * 既定の `AuthzErrorBoundary` は英語(パッケージ既定)。\n */\nexport function makeAuthzErrorBoundary(over?: PartialAuthzAdminLabels): () => React.ReactElement {\n const L = resolveLabels(over).error\n return function AuthzErrorBoundary() {\n const error = useRouteError()\n const routeError = isRouteErrorResponse(error) ? error : null\n const is403 = routeError?.status === 403\n const title = is403 ? L.forbiddenTitle : routeError ? `${L.genericTitlePrefix} (${routeError.status})` : L.genericTitle\n const message = is403 ? L.forbiddenBody : routeError ? (typeof routeError.data === \"string\" && routeError.data ? routeError.data : routeError.statusText) : L.genericBody\n return (\n <div style={ui.page}>\n <div role=\"alert\" style={{ maxWidth: 480, margin: \"3rem auto\", padding: \"1.5rem\", border: \"1px solid #fecaca\", borderRadius: 12, background: \"#fef2f2\" }}>\n <h1 style={{ fontSize: \"1.1rem\", fontWeight: 700, color: \"#b91c1c\", margin: \"0 0 0.5rem\" }}>{title}</h1>\n <p style={{ color: \"#7f1d1d\", fontSize: \"0.9rem\", margin: 0, lineHeight: 1.7 }}>{message}</p>\n </div>\n </div>\n )\n }\n}\n\n/** 英語(既定ラベル)のエラー境界。i18n したい場合は {@link makeAuthzErrorBoundary} を使う。 */\nexport const AuthzErrorBoundary = makeAuthzErrorBoundary()\n\n/** 自分の管理権限を支える対象への破壊操作前に警告(キャンセルで送信中止)。 */\nconst confirmGuard = (active: boolean, message: string) => (e: React.MouseEvent) => {\n if (active && !window.confirm(message)) e.preventDefault()\n}\n\n// ============================ Roles ============================\n\nexport type AuthzRolesData = WithLabels & { roles: AuthzRole[]; selfAdminRoleIds?: number[] }\n\nexport function AuthzRolesView() {\n const { roles, selfAdminRoleIds, labels } = useLoaderData() as AuthzRolesData\n const L = labels.roles\n const C = labels.common\n const selfAdmin = new Set(selfAdminRoleIds ?? [])\n return (\n <section>\n <h2 style={ui.h2}>{L.heading}</h2>\n <ErrorAlert message={actionError(useActionData() as ActionError)} />\n <p style={ui.note}>{L.note}</p>\n <table style={ui.table}>\n <thead>\n <tr>\n <th style={ui.th}>{L.roleKey}</th>\n <th style={ui.th}>{L.name}</th>\n <th style={ui.th}>{L.description}</th>\n <th style={ui.th}>{L.activeHeader}</th>\n <th style={ui.th} />\n </tr>\n </thead>\n <tbody>\n {roles.map((r) => (\n <tr key={r.id}>\n <td style={ui.td}>\n <span style={ui.code}>{r.roleKey}</span>\n </td>\n <td style={ui.td}>\n <input name=\"name\" defaultValue={r.name} form={`save-role-${r.id}`} aria-label={`name-${r.id}`} required style={ui.input} />\n </td>\n <td style={ui.td}>\n <input name=\"description\" defaultValue={r.description ?? \"\"} form={`save-role-${r.id}`} aria-label={`description-${r.id}`} style={ui.input} />\n </td>\n <td style={ui.td}>\n <Form method=\"post\" style={{ display: \"inline\" }}>\n <input type=\"hidden\" name=\"_action\" value=\"toggle\" />\n <input type=\"hidden\" name=\"id\" value={r.id} />\n <input type=\"hidden\" name=\"isActive\" value={String(!r.isActive)} />\n <button type=\"submit\" style={ui.button} onClick={r.isActive ? confirmGuard(selfAdmin.has(r.id), labels.warn.selfRoleDisable) : undefined}>\n {r.isActive ? C.active : C.inactive}\n </button>\n </Form>\n </td>\n <td style={{ ...ui.td, whiteSpace: \"nowrap\" }}>\n <Form method=\"post\" id={`save-role-${r.id}`} style={{ display: \"inline\" }}>\n <input type=\"hidden\" name=\"_action\" value=\"save\" />\n <input type=\"hidden\" name=\"id\" value={r.id} />\n <button type=\"submit\" style={ui.save}>\n {C.save}\n </button>\n </Form>\n <Form method=\"post\" style={{ display: \"inline\", marginLeft: \"0.4rem\" }}>\n <input type=\"hidden\" name=\"_action\" value=\"delete\" />\n <input type=\"hidden\" name=\"id\" value={r.id} />\n <button type=\"submit\" style={ui.danger} onClick={confirmGuard(selfAdmin.has(r.id), labels.warn.selfRoleDelete)}>\n {C.delete}\n </button>\n </Form>\n </td>\n </tr>\n ))}\n {roles.length === 0 ? (\n <tr>\n <td style={ui.empty} colSpan={5}>\n {L.empty}\n </td>\n </tr>\n ) : null}\n </tbody>\n </table>\n\n <h3 style={ui.h3}>{L.newHeading}</h3>\n <Form method=\"post\" style={ui.card}>\n <input type=\"hidden\" name=\"_action\" value=\"create\" />\n <Field label={L.roleKey} hint={L.hintRoleKey}>\n <input name=\"roleKey\" aria-label=\"role_key\" required style={ui.input} />\n </Field>\n <Field label={L.name}>\n <input name=\"name\" aria-label=\"name\" required style={ui.input} />\n </Field>\n <Field label={L.description} hint={C.optional}>\n <input name=\"description\" aria-label=\"description\" style={ui.input} />\n </Field>\n <button type=\"submit\" style={ui.primary}>\n {C.add}\n </button>\n </Form>\n </section>\n )\n}\n\n// ============================ Resources ============================\n\nexport type AuthzResourcesData = WithLabels & { resources: AuthzResource[] }\n\nexport function AuthzResourcesView() {\n const { resources, labels } = useLoaderData() as AuthzResourcesData\n const L = labels.resources\n const C = labels.common\n return (\n <section>\n <h2 style={ui.h2}>{L.heading}</h2>\n <ErrorAlert message={actionError(useActionData() as ActionError)} />\n <p style={ui.note}>{L.note}</p>\n <table style={ui.table}>\n <thead>\n <tr>\n <th style={ui.th}>{L.appKey}</th>\n <th style={ui.th}>{L.resourceKey}</th>\n <th style={ui.th}>{L.name}</th>\n <th style={ui.th}>{L.description}</th>\n <th style={ui.th} />\n </tr>\n </thead>\n <tbody>\n {resources.map((r) => (\n <tr key={r.id}>\n <td style={ui.td}>\n <span style={ui.code}>{r.appKey}</span>\n </td>\n <td style={ui.td}>\n <span style={ui.code}>{r.resourceKey}</span>\n </td>\n <td style={ui.td}>\n <input name=\"name\" defaultValue={r.name} form={`save-res-${r.id}`} aria-label={`name-${r.id}`} required style={ui.input} />\n </td>\n <td style={ui.td}>\n <input name=\"description\" defaultValue={r.description ?? \"\"} form={`save-res-${r.id}`} aria-label={`description-${r.id}`} style={ui.input} />\n </td>\n <td style={{ ...ui.td, whiteSpace: \"nowrap\" }}>\n <Form method=\"post\" id={`save-res-${r.id}`} style={{ display: \"inline\" }}>\n <input type=\"hidden\" name=\"_action\" value=\"save\" />\n <input type=\"hidden\" name=\"id\" value={r.id} />\n <button type=\"submit\" style={ui.save}>\n {C.save}\n </button>\n </Form>\n <Form method=\"post\" style={{ display: \"inline\", marginLeft: \"0.4rem\" }}>\n <input type=\"hidden\" name=\"_action\" value=\"delete\" />\n <input type=\"hidden\" name=\"id\" value={r.id} />\n <button type=\"submit\" style={ui.danger}>\n {C.delete}\n </button>\n </Form>\n </td>\n </tr>\n ))}\n {resources.length === 0 ? (\n <tr>\n <td style={ui.empty} colSpan={5}>\n {L.empty}\n </td>\n </tr>\n ) : null}\n </tbody>\n </table>\n\n <h3 style={ui.h3}>{L.newHeading}</h3>\n <Form method=\"post\" style={ui.card}>\n <input type=\"hidden\" name=\"_action\" value=\"create\" />\n <Field label={L.appKey} hint={L.hintAppKey}>\n <input name=\"appKey\" aria-label=\"app_key\" required style={ui.input} />\n </Field>\n <Field label={L.resourceKey} hint={L.hintResourceKey}>\n <input name=\"resourceKey\" aria-label=\"resource_key\" required style={ui.input} />\n </Field>\n <Field label={L.name}>\n <input name=\"name\" aria-label=\"name\" required style={ui.input} />\n </Field>\n <Field label={L.description} hint={C.optional}>\n <input name=\"description\" aria-label=\"description\" style={ui.input} />\n </Field>\n <button type=\"submit\" style={ui.primary}>\n {C.add}\n </button>\n </Form>\n </section>\n )\n}\n\n// ============================ Grants (role_permissions) ============================\n\nexport type AuthzGrantsData = WithLabels & { grants: AuthzGrant[]; roles: Array<{ id: number; roleKey: string }>; resources: Array<{ id: number; appKey: string; resourceKey: string }> }\n\nexport function AuthzGrantsView() {\n const { grants, roles, resources, labels } = useLoaderData() as AuthzGrantsData\n const L = labels.grants\n const C = labels.common\n return (\n <section>\n <h2 style={ui.h2}>{L.heading}</h2>\n <p style={ui.note}>{L.note}</p>\n <ErrorAlert message={actionError(useActionData() as ActionError)} />\n <table style={ui.table}>\n <thead>\n <tr>\n <th style={ui.th}>{L.role}</th>\n <th style={ui.th}>{L.resource}</th>\n <th style={ui.th}>{L.action}</th>\n <th style={ui.th}>{L.rowScope}</th>\n <th style={ui.th}>{L.columnScope}</th>\n <th style={ui.th} />\n </tr>\n </thead>\n <tbody>\n {grants.map((g) => (\n <tr key={g.id}>\n <td style={ui.td}>\n <span style={ui.code}>{g.roleKey}</span>\n </td>\n <td style={ui.td}>\n <span style={ui.code}>\n {g.appKey}:{g.resourceKey}\n </span>\n </td>\n <td style={ui.td}>{g.action}</td>\n <td style={ui.td}>\n <textarea name=\"rowScope\" defaultValue={g.rowScope ?? \"\"} form={`save-grant-${g.id}`} aria-label={`row_scope-${g.id}`} rows={2} placeholder={L.rowScopePlaceholder} style={ui.textarea} />\n </td>\n <td style={ui.td}>\n <textarea name=\"columnScope\" defaultValue={g.columnScope ?? \"\"} form={`save-grant-${g.id}`} aria-label={`column_scope-${g.id}`} rows={2} placeholder={L.columnScopePlaceholder} style={ui.textarea} />\n </td>\n <td style={{ ...ui.td, whiteSpace: \"nowrap\" }}>\n <Form method=\"post\" id={`save-grant-${g.id}`} style={{ display: \"inline\" }}>\n <input type=\"hidden\" name=\"_action\" value=\"save\" />\n <input type=\"hidden\" name=\"id\" value={g.id} />\n <button type=\"submit\" style={ui.save}>\n {C.save}\n </button>\n </Form>\n <Form method=\"post\" style={{ display: \"inline\", marginLeft: \"0.4rem\" }}>\n <input type=\"hidden\" name=\"_action\" value=\"delete\" />\n <input type=\"hidden\" name=\"id\" value={g.id} />\n <button type=\"submit\" style={ui.danger}>\n {C.delete}\n </button>\n </Form>\n </td>\n </tr>\n ))}\n {grants.length === 0 ? (\n <tr>\n <td style={ui.empty} colSpan={6}>\n {L.empty}\n </td>\n </tr>\n ) : null}\n </tbody>\n </table>\n\n <h3 style={ui.h3}>{L.newHeading}</h3>\n <Form method=\"post\" style={ui.card}>\n <input type=\"hidden\" name=\"_action\" value=\"create\" />\n <Field label={L.role}>\n <select name=\"roleId\" aria-label=\"role\" required style={ui.select}>\n <option value=\"\">{L.selectPlaceholder}</option>\n {roles.map((r) => (\n <option key={r.id} value={r.id}>\n {r.roleKey}\n </option>\n ))}\n </select>\n </Field>\n <Field label={L.resource}>\n <select name=\"resourceId\" aria-label=\"resource\" required style={ui.select}>\n <option value=\"\">{L.selectPlaceholder}</option>\n {resources.map((r) => (\n <option key={r.id} value={r.id}>\n {r.appKey}:{r.resourceKey}\n </option>\n ))}\n </select>\n </Field>\n <Field label={L.action}>\n <select name=\"action\" aria-label=\"action\" required style={ui.select}>\n {AUTHZ_ACTIONS.map((a) => (\n <option key={a} value={a}>\n {a}\n </option>\n ))}\n </select>\n </Field>\n <Field label={L.rowScope} hint={L.rowScopeHint}>\n <textarea name=\"rowScope\" aria-label=\"row_scope\" rows={2} style={ui.textarea} placeholder='{\"filters\":[{\"field\":\"部門CD\",\"op\":\"in\",\"values\":[\"A\"]}]}' />\n </Field>\n <Field label={L.columnScope} hint={L.columnScopeHint}>\n <textarea name=\"columnScope\" aria-label=\"column_scope\" rows={2} style={ui.textarea} placeholder='{\"mode\":\"deny\",\"columns\":[\"金額\"]}' />\n </Field>\n <button type=\"submit\" style={ui.primary}>\n {C.grant}\n </button>\n </Form>\n </section>\n )\n}\n\n// ============================ User roles ============================\n\nexport type AuthzUserRolesData = WithLabels & { assignments: AuthzAssignment[]; roles: Array<{ id: number; roleKey: string }>; users: AuthzUser[]; actorUserId?: number; selfAdminRoleIds?: number[] }\n\nexport function AuthzUserRolesView() {\n const { assignments, roles, users, actorUserId, selfAdminRoleIds, labels } = useLoaderData() as AuthzUserRolesData\n const L = labels.userRoles\n const C = labels.common\n const selfAdmin = new Set(selfAdminRoleIds ?? [])\n return (\n <section>\n <h2 style={ui.h2}>{L.heading}</h2>\n <ErrorAlert message={actionError(useActionData() as ActionError)} />\n <table style={ui.table}>\n <thead>\n <tr>\n <th style={ui.th}>{L.user}</th>\n <th style={ui.th}>{L.role}</th>\n <th style={ui.th} />\n </tr>\n </thead>\n <tbody>\n {assignments.map((a) => (\n <tr key={`${a.userId}-${a.roleId}`}>\n <td style={ui.td}>\n {a.email}\n <span style={ui.muted}>({a.displayName})</span>\n </td>\n <td style={ui.td}>{a.roleKey}</td>\n <td style={ui.td}>\n <Form method=\"post\" style={{ display: \"inline\" }}>\n <input type=\"hidden\" name=\"_action\" value=\"remove\" />\n <input type=\"hidden\" name=\"userId\" value={a.userId} />\n <input type=\"hidden\" name=\"roleId\" value={a.roleId} />\n <button type=\"submit\" style={ui.danger} onClick={confirmGuard(a.userId === actorUserId && selfAdmin.has(a.roleId), labels.warn.selfAssignmentRemove)}>\n {C.remove}\n </button>\n </Form>\n </td>\n </tr>\n ))}\n {assignments.length === 0 ? (\n <tr>\n <td style={ui.empty} colSpan={3}>\n {L.empty}\n </td>\n </tr>\n ) : null}\n </tbody>\n </table>\n\n <h3 style={ui.h3}>{L.newHeading}</h3>\n <Form method=\"post\" style={ui.card}>\n <input type=\"hidden\" name=\"_action\" value=\"assign\" />\n <Field label={L.user}>\n <select name=\"userId\" aria-label=\"user\" required style={ui.select}>\n <option value=\"\">{L.selectPlaceholder}</option>\n {users.map((u) => (\n <option key={u.id} value={u.id}>\n {u.email}\n </option>\n ))}\n </select>\n </Field>\n <Field label={L.role}>\n <select name=\"roleId\" aria-label=\"role\" required style={ui.select}>\n <option value=\"\">{L.selectPlaceholder}</option>\n {roles\n .filter((r) => r.roleKey !== \"@authenticated\" && r.roleKey !== \"@anonymous\")\n .map((r) => (\n <option key={r.id} value={r.id}>\n {r.roleKey}\n </option>\n ))}\n </select>\n </Field>\n <button type=\"submit\" style={ui.primary}>\n {C.assign}\n </button>\n </Form>\n </section>\n )\n}\n\n// ============================ Single-file (splat) app view ============================\n\nconst SEGMENT_VIEWS: Record<string, () => React.ReactElement> = {\n roles: AuthzRolesView,\n resources: AuthzResourcesView,\n role_permissions: AuthzGrantsView,\n user_roles: AuthzUserRolesView,\n}\n\n/**\n * スプラット(`authz/*`)1 ルートで認可管理 UI 全体を描画するコンポーネント(store 非依存)。\n * loader が返す `segment` に応じて該当タブのビューを描画する。レイアウト殻と各ビューは同一の\n * loader データ(セグメントデータ + myPermissions + labels をトップレベルに統合)を読む。\n */\nexport function AuthzAdminAppView() {\n const { segment } = useLoaderData() as { segment: string }\n const View = SEGMENT_VIEWS[segment] ?? AuthzRolesView\n return (\n <AuthzLayoutShell>\n <View />\n </AuthzLayoutShell>\n )\n}\n","import type { PermissionView } from \"./server\"\n\nexport type PermState = \"full\" | \"partial\" | \"none\"\n\nexport type UsePermission = {\n canRead: boolean\n canWrite: boolean\n canDelete: boolean\n /** read: none(×) / partial(△, row|col restricted) / full(○). */\n readState: PermState\n /** write = create ∪ update: full(○ both) / partial(△ one) / none(×). */\n writeState: PermState\n deleteState: PermState\n}\n\n/**\n * Derive ○△× display states from a {@link PermissionView}. Pure (safe to call in render);\n * named `usePermission` for ergonomic call-sites.\n */\nexport function usePermission(view: PermissionView | null | undefined): UsePermission {\n const readState: PermState = !view?.read ? \"none\" : view.readPartial ? \"partial\" : \"full\"\n const writeState: PermState = view?.create && view?.update ? \"full\" : view?.create || view?.update ? \"partial\" : \"none\"\n const deleteState: PermState = view?.delete ? \"full\" : \"none\"\n return {\n canRead: !!view?.read,\n canWrite: !!view?.write,\n canDelete: !!view?.delete,\n readState,\n writeState,\n deleteState,\n }\n}\n","import type { PermissionView } from \"./server\"\nimport { type PermState, usePermission } from \"./usePermission\"\n\nconst MARK: Record<PermState, string> = { full: \"○\", partial: \"△\", none: \"×\" }\n\nexport type MyPermissionIndicatorProps = {\n permission: PermissionView | null | undefined\n labels?: { read?: string; write?: string; delete?: string }\n /** Show a \"(部分)\" hint when read is partial. Default true. */\n showScopeSummary?: boolean\n className?: string\n}\n\n/**\n * Compact self-permission indicator: read / write(create∪update) / delete as ○△×.\n * `write` is ○ only when both create & update are held, △ when one, × when none.\n */\nexport function MyPermissionIndicator({ permission, labels, showScopeSummary = true, className = \"authz-permission-indicator\" }: MyPermissionIndicatorProps) {\n const p = usePermission(permission)\n const l = { read: labels?.read ?? \"読\", write: labels?.write ?? \"書\", delete: labels?.delete ?? \"削除\" }\n return (\n <span className={className} data-resource={permission?.resourceKey ?? \"\"}>\n <span data-perm=\"read\" title={`${l.read}: ${p.readState}`}>\n {l.read}\n {MARK[p.readState]}\n </span>\n <span data-perm=\"write\" title={`${l.write}: ${p.writeState}`}>\n {l.write}\n {MARK[p.writeState]}\n </span>\n <span data-perm=\"delete\" title={`${l.delete}: ${p.deleteState}`}>\n {l.delete}\n {MARK[p.deleteState]}\n </span>\n {showScopeSummary && p.readState === \"partial\" ? <span data-perm=\"scope\">(部分)</span> : null}\n </span>\n )\n}\n","import { type AuthzAction, can, createRequirePermission, type DenyInfo, type EffectivePermission, type GuardResult } from \"@aiquants/authz-core\"\nimport { redirect } from \"react-router\"\n\ntype Awaitable<T> = T | Promise<T>\nexport type AuthzUserId = string | number\n\nexport type AuthzConfig = {\n /** Stable app identifier (e.g. \"quants\"). Bound into every permission query. */\n appKey: string\n /** Resolve the acting user id from the request (cookie/session/openid → TDUsers.id). */\n resolveUserId: (request: Request) => Awaitable<AuthzUserId | null | undefined>\n /** Load effective permissions for (user, app, resource) — typically via @aiquants/authz-drizzle. */\n getEffectivePermissions: (args: { userId: AuthzUserId | null; appKey: string; resourceKey: string }) => Awaitable<EffectivePermission | null | undefined>\n /** Default deny handler. If omitted, denies throw AuthzDeniedError (403). */\n onDeny?: (info: DenyInfo) => void\n}\n\nexport type RequirePermissionOptions = {\n /** When set, denials `throw redirect(failureRedirect)` instead of throwing 403. */\n failureRedirect?: string\n}\n\n/** Serializable per-resource permission summary for UI (loader → component). */\nexport type PermissionView = {\n resourceKey: string\n read: boolean\n create: boolean\n update: boolean\n delete: boolean\n /** create ∪ update */\n write: boolean\n /** read granted but row and/or column restricted (→ △ partial). */\n readPartial: boolean\n actions: AuthzAction[]\n}\n\n/** Map an EffectivePermission to a serializable {@link PermissionView}. */\nexport function toPermissionView(resourceKey: string, perm: EffectivePermission | null | undefined): PermissionView {\n const read = can(perm, \"read\")\n const create = can(perm, \"create\")\n const update = can(perm, \"update\")\n const del = can(perm, \"delete\")\n const readScope = perm?.scopeByAction.read\n const readPartial = read && !!readScope && (readScope.rowScope !== null || readScope.columnScope !== null)\n return {\n resourceKey,\n read,\n create,\n update,\n delete: del,\n write: create || update,\n readPartial,\n actions: perm ? Array.from(perm.actions) : [],\n }\n}\n\n/**\n * React Router adapter. Binds `appKey` and the DI deps, exposing:\n * - `requirePermission(request, {resourceKey, action}, options?)` → `{ userId, scope }` on allow\n * (apply row WHERE / column mask with the returned scope); denies throw 403 or redirect.\n * - `getMyPermissions(request, {resourceKeys})` → `Record<resourceKey, PermissionView>` for the UI.\n */\nexport function createAuthz(config: AuthzConfig) {\n async function requirePermission(request: Request, query: { resourceKey: string; action: AuthzAction }, options?: RequirePermissionOptions): Promise<GuardResult<AuthzUserId>> {\n const onDeny: ((info: DenyInfo) => void) | undefined = options?.failureRedirect\n ? () => {\n throw redirect(options.failureRedirect as string)\n }\n : config.onDeny\n const guard = createRequirePermission<Request, AuthzUserId>({\n resolveUserId: config.resolveUserId,\n getEffectivePermissions: config.getEffectivePermissions,\n onDeny,\n })\n return guard(request, { appKey: config.appKey, resourceKey: query.resourceKey, action: query.action })\n }\n\n async function getMyPermissions(request: Request, query: { resourceKeys: string[] }): Promise<Record<string, PermissionView>> {\n const userId = await config.resolveUserId(request)\n const out: Record<string, PermissionView> = {}\n for (const resourceKey of query.resourceKeys) {\n const perm = await config.getEffectivePermissions({ userId: userId ?? null, appKey: config.appKey, resourceKey })\n out[resourceKey] = toPermissionView(resourceKey, perm)\n }\n return out\n }\n\n return { requirePermission, getMyPermissions }\n}\n"],"mappings":"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","names":["index_exports","__export","AuthzAdminAppView","AuthzErrorBoundary","AuthzGrantsView","AuthzLayout","AuthzResourcesView","AuthzRolesView","AuthzUserRolesView","ErrorAlert","Field","MyPermissionIndicator","createAuthz","createAuthzAdminApp","createAuthzAdminServer","defaultAuthzAdminLabels","makeAuthzErrorBoundary","resolveLabels","toPermissionView","ui","usePermission","__toCommonJS","import_react_router","import_authz_core","import_react_router","defaultAuthzAdminLabels","resolveLabels","over","d","isResponse","e","toActionError","createAuthzAdminServer","opts","store","RES","labels","resolveLabels","requirePermission","request","query","userId","layoutGuard","loadMyPermissions","rolesData","roles","self","resourcesData","grantsData","grants","resources","userRolesData","assignments","users","form","intent","roleKey","name","appKey","resourceKey","roleId","resourceId","rawAction","action","actor","segmentOf","params","createAuthzAdminApp","opts","server","createAuthzAdminServer","basePath","SEGMENTS","segmentData","actions","loader","args","segment","userId","myPermissions","segData","action","act","import_jsx_runtime","ui","Field","label","hint","children","ErrorAlert","message","import_authz_core","import_react_router","usePermission","view","readState","writeState","deleteState","import_jsx_runtime","MARK","MyPermissionIndicator","permission","labels","showScopeSummary","className","p","usePermission","l","import_jsx_runtime","actionError","d","AuthzLayoutShell","children","myPermissions","labels","adminResourceKey","basePath","base","tabs","ui","MyPermissionIndicator","key","label","isActive","AuthzLayout","makeAuthzErrorBoundary","over","L","resolveLabels","error","routeError","is403","title","message","AuthzErrorBoundary","confirmGuard","active","e","AuthzRolesView","roles","selfAdminRoleIds","C","selfAdmin","ErrorAlert","r","Field","AuthzResourcesView","resources","AuthzGrantsView","grants","g","a","AuthzUserRolesView","assignments","users","actorUserId","u","SEGMENT_VIEWS","AuthzAdminAppView","segment","View","import_authz_core","import_react_router","toPermissionView","resourceKey","perm","read","create","update","del","readScope","readPartial","createAuthz","config","requirePermission","request","query","options","onDeny","getMyPermissions","userId","out"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/admin/app.ts","../src/admin/server.ts","../src/admin/labels.ts","../src/admin/ui.tsx","../src/admin/views.tsx","../src/usePermission.ts","../src/MyPermissionIndicator.tsx","../src/server.ts"],"sourcesContent":["export * from \"./admin/app\"\nexport * from \"./admin/labels\"\nexport * from \"./admin/server\"\nexport * from \"./admin/ui\"\nexport * from \"./admin/views\"\nexport * from \"./MyPermissionIndicator\"\nexport * from \"./server\"\nexport * from \"./usePermission\"\n","/**\n * 認可管理 UI を **スプラット 1 ルート(`authz/*`)** にマウントするためのサーバ結線。\n * `routes.ts` の 1 エントリ + 極小のマウントファイル 1 個だけで全タブを提供できる\n * (タブごとのルートディレクトリ/ファイルが不要)。\n *\n * 返り値の `loader`/`action` は store 依存(サーバ)。Component は store 非依存の\n * `AuthzAdminAppView`(views.tsx)を、ErrorBoundary は `makeAuthzErrorBoundary` を使う。\n */\nimport { data, redirect } from \"react-router\"\nimport { type CreateAuthzAdminServerOptions, createAuthzAdminServer } from \"./server\"\n\ntype RouteArgs = { request: Request; params: Record<string, string | undefined> }\n\nexport type CreateAuthzAdminAppOptions = CreateAuthzAdminServerOptions & {\n /** マウントのベースパス(タブリンク/未指定セグメントのリダイレクト先)。既定 `/authz`。 */\n basePath?: string\n}\n\n/** スプラット param(\"*\")から先頭セグメントを取り出す(`roles/...` → `roles`)。 */\nfunction segmentOf(params: Record<string, string | undefined>): string {\n return String(params[\"*\"] ?? \"\").split(\"/\")[0]\n}\n\nexport function createAuthzAdminApp(opts: CreateAuthzAdminAppOptions) {\n const server = createAuthzAdminServer(opts)\n const basePath = opts.basePath ?? \"/authz\"\n const SEGMENTS = [\"roles\", \"resources\", \"role_permissions\", \"user_roles\"] as const\n // データ取得(ガード無し)。ガードはスプラット loader で 1 回だけ行い、userId を渡す。\n const segmentData = { roles: server.roles.data, resources: server.resources.data, role_permissions: server.grants.data, user_roles: server.userRoles.data }\n const actions = { roles: server.roles.action, resources: server.resources.action, role_permissions: server.grants.action, user_roles: server.userRoles.action }\n\n async function loader(args: RouteArgs) {\n const segment = segmentOf(args.params)\n if (!(SEGMENTS as readonly string[]).includes(segment)) throw redirect(`${basePath}/roles`)\n // ガードは 1 回だけ(requireUser + requirePermission(read))。userId を取り回して再ガードしない。\n const { userId } = await server.layoutGuard(args.request)\n const [myPermissions, segData] = await Promise.all([server.loadMyPermissions(args.request), segmentData[segment as (typeof SEGMENTS)[number]](userId)])\n // segData は labels を含む(各 data 関数が付与)。myPermissions/adminResourceKey はレイアウト殻用。\n return { segment, basePath, myPermissions, adminResourceKey: server.resourceKey, ...segData }\n }\n\n async function action(args: RouteArgs) {\n const segment = segmentOf(args.params)\n const act = actions[segment as (typeof SEGMENTS)[number]]\n if (!act) return data({ error: \"unknown action\" }, { status: 400 })\n return act(args)\n }\n\n // server: 個別タブの loader/action を露出(統合テスト等から直接呼ぶ用)。\n return { loader, action, server }\n}\n","/**\n * 認可管理 UI のサーバ結線(loader/action 工場)。store ポート + アプリのガード/セッションを束ね、\n * 各ルートの loader/action を生成する。返り値の loader データには解決済みラベルを含める。\n * store(drizzle)を渡すのはこの工場の呼び出し側(アプリのサーバモジュール)に限る。\n */\nimport { AUTHZ_ACTIONS, type AuthzAction, type AuthzAdminStore, AuthzDeniedError } from \"@aiquants/authz-core\"\nimport { data, redirect } from \"react-router\"\nimport type { PermissionView } from \"../server\"\nimport { type AuthzAdminLabels, type PartialAuthzAdminLabels, resolveLabels } from \"./labels\"\nimport type { AuthzGrantsData, AuthzLayoutData, AuthzResourcesData, AuthzRolesData, AuthzUserRolesData } from \"./views\"\n\ntype Req = { request: Request }\ntype PermissionQuery = { resourceKey: string; action: AuthzAction }\n\nexport type CreateAuthzAdminServerOptions = {\n store: AuthzAdminStore\n /** 管理画面のガード資源キー(既定 `authz_admin`)。 */\n resourceKey?: string\n /** 未ログインをログインへ誘導する(例: throw redirect(...))。 */\n requireUser: (request: Request) => Promise<unknown>\n /**\n * 認可ガード(アプリの createAuthz 由来)。allow で { userId } を返す。\n * 0.2.0 で GuardResult.userId が nullable 化したため、戻り型も null を受ける。\n * userId==null(未解決/万一の public 付与)は createAuthzAdminServer 内で deny する\n * (管理経路は監査・自己権限計算に実 id が必須のため非 null を保証)。\n */\n requirePermission: (request: Request, query: PermissionQuery) => Promise<{ userId: string | number | null }>\n /** 自己権限表示用(アプリの createAuthz 由来)。 */\n getMyPermissions: (request: Request, args: { resourceKeys: string[] }) => Promise<Record<string, PermissionView>>\n /** 文言の部分上書き(既定は日本語)。 */\n labels?: PartialAuthzAdminLabels\n}\n\nconst isResponse = (e: unknown): e is Response => e instanceof Response\n\n/** action 内の例外を 403(認可拒否のみ)/ 400(検証等)へ変換する。 */\nfunction toActionError(e: unknown) {\n if (isResponse(e)) throw e\n if (e instanceof AuthzDeniedError) throw new Response(e.message, { status: 403 })\n return data({ error: e instanceof Error ? e.message : \"エラーが発生しました\" }, { status: 400 })\n}\n\nexport function createAuthzAdminServer(opts: CreateAuthzAdminServerOptions) {\n const store = opts.store\n const RES = opts.resourceKey ?? \"authz_admin\"\n const labels: AuthzAdminLabels = resolveLabels(opts.labels)\n // 未解決ユーザー(userId==null)を境界で 1 回だけ deny。これ以降の userId は非 null 保証。\n // 管理リソースは public を付与しない前提だが、防御的に拒否する(監査/自己権限計算に実 id が必須)。\n const requirePermission = async (request: Request, query: PermissionQuery): Promise<{ userId: string | number }> => {\n const { userId } = await opts.requirePermission(request, query)\n if (userId == null) {\n throw new AuthzDeniedError({ appKey: \"\", resourceKey: query.resourceKey, action: query.action, reason: \"unresolved-user\", userId: null })\n }\n return { userId }\n }\n\n /** レイアウトガード: requireUser(302) → requirePermission(read, 403)。userId を返す(1 回だけ実行)。 */\n async function layoutGuard(request: Request): Promise<{ userId: string | number }> {\n await opts.requireUser(request)\n try {\n return await requirePermission(request, { resourceKey: RES, action: \"read\" })\n } catch (e) {\n if (e instanceof AuthzDeniedError) throw new Response(`Forbidden: ${RES}`, { status: 403 })\n throw e\n }\n }\n /** 自己権限(インジケータ表示用)。 */\n const loadMyPermissions = (request: Request) => opts.getMyPermissions(request, { resourceKeys: [RES] })\n\n // ---- データ取得(ガード無し)。ガード済みの userId を受け取る(resources/grants は未使用)。 ----\n const rolesData = async (userId?: string | number): Promise<AuthzRolesData> => {\n const [roles, self] = await Promise.all([store.listRoles(), store.getSelfAdminContext(Number(userId))])\n return { roles, selfAdminRoleIds: self.selfAdminRoleIds, labels }\n }\n const resourcesData = async (): Promise<AuthzResourcesData> => ({ resources: await store.listResources(), labels })\n const grantsData = async (): Promise<AuthzGrantsData> => {\n const [grants, roles, resources] = await Promise.all([store.listGrants(), store.listRoles(), store.listResources()])\n return { grants, roles, resources, labels }\n }\n const userRolesData = async (userId?: string | number): Promise<AuthzUserRolesData> => {\n const [assignments, roles, users, self] = await Promise.all([store.listUserRoles(), store.listRoles(), store.listUsers(), store.getSelfAdminContext(Number(userId))])\n return { assignments, roles, users, actorUserId: self.actorUserId, selfAdminRoleIds: self.selfAdminRoleIds, labels }\n }\n\n return {\n /** 露出: スプラットマウント(app.ts)がガードを 1 回だけ行うために使う。 */\n labels,\n resourceKey: RES,\n layoutGuard,\n loadMyPermissions,\n\n /** /authz レイアウト: requireUser(302) → requirePermission(read, 403) → 自己権限取得。 */\n layout: {\n async loader({ request }: Req): Promise<AuthzLayoutData> {\n await layoutGuard(request)\n return { myPermissions: await loadMyPermissions(request), labels, adminResourceKey: RES }\n },\n },\n\n /** /authz index → roles へ。 */\n index: {\n loader() {\n throw redirect(\"/authz/roles\")\n },\n },\n\n roles: {\n data: rolesData,\n async loader({ request }: Req): Promise<AuthzRolesData> {\n const { userId } = await requirePermission(request, { resourceKey: RES, action: \"read\" })\n return rolesData(userId)\n },\n async action({ request }: Req) {\n const form = await request.formData()\n const intent = String(form.get(\"_action\"))\n try {\n switch (intent) {\n case \"create\": {\n const { userId } = await requirePermission(request, { resourceKey: RES, action: \"create\" })\n const roleKey = String(form.get(\"roleKey\") ?? \"\").trim()\n const name = String(form.get(\"name\") ?? \"\").trim()\n if (!(roleKey && name)) return data({ error: \"role_key と name は必須です\" }, { status: 400 })\n await store.createRole({ roleKey, name, description: String(form.get(\"description\") ?? \"\").trim() || null }, String(userId))\n return { ok: true }\n }\n case \"save\": {\n const { userId } = await requirePermission(request, { resourceKey: RES, action: \"update\" })\n const roleKey = String(form.get(\"roleKey\") ?? \"\").trim()\n const name = String(form.get(\"name\") ?? \"\").trim()\n if (!(roleKey && name)) return data({ error: \"roleKey と name は必須です\" }, { status: 400 })\n await store.updateRole(Number(form.get(\"id\")), { roleKey, name, description: String(form.get(\"description\") ?? \"\").trim() || null }, String(userId))\n return { ok: true }\n }\n case \"toggle\": {\n const { userId } = await requirePermission(request, { resourceKey: RES, action: \"update\" })\n await store.setRoleActive(Number(form.get(\"id\")), form.get(\"isActive\") === \"true\", String(userId))\n return { ok: true }\n }\n case \"delete\": {\n await requirePermission(request, { resourceKey: RES, action: \"delete\" })\n await store.deleteRole(Number(form.get(\"id\")))\n return { ok: true }\n }\n default:\n return data({ error: \"unknown action\" }, { status: 400 })\n }\n } catch (e) {\n return toActionError(e)\n }\n },\n },\n\n resources: {\n data: resourcesData,\n async loader({ request }: Req): Promise<AuthzResourcesData> {\n await requirePermission(request, { resourceKey: RES, action: \"read\" })\n return resourcesData()\n },\n async action({ request }: Req) {\n const form = await request.formData()\n const intent = String(form.get(\"_action\"))\n try {\n switch (intent) {\n case \"create\": {\n const { userId } = await requirePermission(request, { resourceKey: RES, action: \"create\" })\n const appKey = String(form.get(\"appKey\") ?? \"\").trim()\n const resourceKey = String(form.get(\"resourceKey\") ?? \"\").trim()\n const name = String(form.get(\"name\") ?? \"\").trim()\n if (!(appKey && resourceKey && name)) return data({ error: \"app_key / resource_key / name は必須です\" }, { status: 400 })\n await store.createResource({ appKey, resourceKey, name, description: String(form.get(\"description\") ?? \"\").trim() || null }, String(userId))\n return { ok: true }\n }\n case \"save\": {\n const { userId } = await requirePermission(request, { resourceKey: RES, action: \"update\" })\n const name = String(form.get(\"name\") ?? \"\").trim()\n if (!name) return data({ error: \"name は必須です\" }, { status: 400 })\n await store.updateResource(Number(form.get(\"id\")), { name, description: String(form.get(\"description\") ?? \"\").trim() || null }, String(userId))\n return { ok: true }\n }\n case \"delete\": {\n await requirePermission(request, { resourceKey: RES, action: \"delete\" })\n await store.deleteResource(Number(form.get(\"id\")))\n return { ok: true }\n }\n default:\n return data({ error: \"unknown action\" }, { status: 400 })\n }\n } catch (e) {\n return toActionError(e)\n }\n },\n },\n\n grants: {\n data: grantsData,\n async loader({ request }: Req): Promise<AuthzGrantsData> {\n await requirePermission(request, { resourceKey: RES, action: \"read\" })\n return grantsData()\n },\n async action({ request }: Req) {\n const form = await request.formData()\n const intent = String(form.get(\"_action\"))\n try {\n switch (intent) {\n case \"create\": {\n const { userId } = await requirePermission(request, { resourceKey: RES, action: \"create\" })\n const roleId = Number(form.get(\"roleId\"))\n const resourceId = Number(form.get(\"resourceId\"))\n if (!(roleId && resourceId)) return data({ error: \"ロールとリソースを選択してください\" }, { status: 400 })\n const rawAction = String(form.get(\"action\") ?? \"\")\n if (!(AUTHZ_ACTIONS as readonly string[]).includes(rawAction)) return data({ error: \"無効な action です\" }, { status: 400 })\n const action = rawAction as AuthzAction\n await store.createGrant({ roleId, resourceId, action, rowScope: String(form.get(\"rowScope\") ?? \"\"), columnScope: String(form.get(\"columnScope\") ?? \"\") }, String(userId))\n return { ok: true }\n }\n case \"save\": {\n const { userId } = await requirePermission(request, { resourceKey: RES, action: \"update\" })\n const rawAction = String(form.get(\"action\") ?? \"\")\n if (!(AUTHZ_ACTIONS as readonly string[]).includes(rawAction)) return data({ error: \"無効な action です\" }, { status: 400 })\n const action = rawAction as AuthzAction\n await store.updateGrant(Number(form.get(\"id\")), { action, rowScope: String(form.get(\"rowScope\") ?? \"\"), columnScope: String(form.get(\"columnScope\") ?? \"\") }, String(userId))\n return { ok: true }\n }\n case \"delete\": {\n await requirePermission(request, { resourceKey: RES, action: \"delete\" })\n await store.deleteGrant(Number(form.get(\"id\")))\n return { ok: true }\n }\n default:\n return data({ error: \"unknown action\" }, { status: 400 })\n }\n } catch (e) {\n return toActionError(e)\n }\n },\n },\n\n userRoles: {\n data: userRolesData,\n async loader({ request }: Req): Promise<AuthzUserRolesData> {\n const { userId } = await requirePermission(request, { resourceKey: RES, action: \"read\" })\n return userRolesData(userId)\n },\n async action({ request }: Req) {\n const form = await request.formData()\n const intent = String(form.get(\"_action\"))\n try {\n switch (intent) {\n case \"assign\": {\n const { userId: actor } = await requirePermission(request, { resourceKey: RES, action: \"create\" })\n const userId = Number(form.get(\"userId\"))\n const roleId = Number(form.get(\"roleId\"))\n if (!(userId && roleId)) return data({ error: \"ユーザーとロールを選択してください\" }, { status: 400 })\n await store.assignUserRole(userId, roleId, String(actor))\n return { ok: true }\n }\n case \"remove\": {\n await requirePermission(request, { resourceKey: RES, action: \"delete\" })\n await store.removeUserRole(Number(form.get(\"userId\")), Number(form.get(\"roleId\")))\n return { ok: true }\n }\n default:\n return data({ error: \"unknown action\" }, { status: 400 })\n }\n } catch (e) {\n return toActionError(e)\n }\n },\n },\n }\n}\n","/** Authz admin UI strings (i18n). Defaults are English; override per-section via `createAuthzAdminRoutes(..., { labels })`. */\nexport type AuthzAdminLabels = {\n title: string\n myPermission: string\n tabs: { roles: string; resources: string; role_permissions: string; user_roles: string }\n common: { add: string; save: string; delete: string; remove: string; assign: string; grant: string; select: string; active: string; inactive: string; optional: string }\n roles: { heading: string; note: string; roleKey: string; name: string; description: string; activeHeader: string; empty: string; newHeading: string; hintRoleKey: string }\n resources: { heading: string; note: string; appKey: string; resourceKey: string; name: string; description: string; empty: string; newHeading: string; hintAppKey: string; hintResourceKey: string; hintDailyReport: string }\n grants: {\n heading: string\n note: string\n role: string\n resource: string\n action: string\n rowScope: string\n columnScope: string\n empty: string\n newHeading: string\n rowScopeHint: string\n columnScopeHint: string\n rowScopePlaceholder: string\n columnScopePlaceholder: string\n nullRows: string\n nullCols: string\n selectPlaceholder: string\n }\n userRoles: { heading: string; user: string; role: string; empty: string; newHeading: string; selectPlaceholder: string }\n error: { forbiddenTitle: string; forbiddenBody: string; genericTitlePrefix: string; genericTitle: string; genericBody: string }\n warn: { selfRoleDisable: string; selfRoleDelete: string; selfAssignmentRemove: string }\n}\n\nexport const defaultAuthzAdminLabels: AuthzAdminLabels = {\n title: \"Authorization (RBAC)\",\n myPermission: \"Your permissions\",\n tabs: { roles: \"Roles\", resources: \"Resources\", role_permissions: \"Permissions\", user_roles: \"User assignments\" },\n common: { add: \"Add\", save: \"Save\", delete: \"Delete\", remove: \"Remove\", assign: \"Assign\", grant: \"Grant\", select: \"Select…\", active: \"○ Enabled\", inactive: \"× Disabled\", optional: \"optional\" },\n roles: {\n heading: \"Roles (TMRole)\",\n note: \"Edit name / description inline and click Save (role_key is an immutable identifier).\",\n roleKey: \"role_key\",\n name: \"name\",\n description: \"description\",\n activeHeader: \"Active\",\n empty: \"No roles\",\n newHeading: \"New role\",\n hintRoleKey: \"e.g. admin\",\n },\n resources: {\n heading: \"Resources (TMResource)\",\n note: \"Edit name / description inline and click Save (app_key / resource_key are immutable identifiers).\",\n appKey: \"app_key\",\n resourceKey: \"resource_key\",\n name: \"name\",\n description: \"description\",\n empty: \"No resources\",\n newHeading: \"New resource\",\n hintAppKey: \"e.g. quants\",\n hintResourceKey: \"e.g. daily_report\",\n hintDailyReport: \"optional\",\n },\n grants: {\n heading: \"Permissions (TDRolePermission)\",\n note: \"Empty row_scope / column_scope = all rows / all columns (NULL). JSON must satisfy the §3.2 contract.\",\n role: \"role\",\n resource: \"resource\",\n action: \"action\",\n rowScope: \"row_scope\",\n columnScope: \"column_scope\",\n empty: \"No permissions\",\n newHeading: \"Grant a permission\",\n rowScopeHint: \"JSON / empty = all rows\",\n columnScopeHint: \"JSON / empty = all columns\",\n rowScopePlaceholder: \"empty = all rows (NULL)\",\n columnScopePlaceholder: \"empty = all columns (NULL)\",\n nullRows: \"NULL (all rows)\",\n nullCols: \"NULL (all columns)\",\n selectPlaceholder: \"Select…\",\n },\n userRoles: { heading: \"User assignments (TDUserRole)\", user: \"user\", role: \"role\", empty: \"No assignments\", newHeading: \"Assign a role\", selectPlaceholder: \"Select…\" },\n error: {\n forbiddenTitle: \"Access denied\",\n forbiddenBody: \"You don't have permission to view this screen. Ask an administrator to grant access.\",\n genericTitlePrefix: \"Error\",\n genericTitle: \"An error occurred\",\n genericBody: \"An unexpected error occurred. Please try again later.\",\n },\n warn: {\n selfRoleDisable: \"This role backs your own authorization-admin access. Disabling it may lock you out of this screen. Continue?\",\n selfRoleDelete: \"This role backs your own authorization-admin access. Deleting it may lock you out of this screen. Continue?\",\n selfAssignmentRemove: \"This assignment backs your own authorization-admin access. Removing it may lock you out of this screen. Continue?\",\n },\n}\n\nexport type PartialAuthzAdminLabels = {\n title?: string\n myPermission?: string\n tabs?: Partial<AuthzAdminLabels[\"tabs\"]>\n common?: Partial<AuthzAdminLabels[\"common\"]>\n roles?: Partial<AuthzAdminLabels[\"roles\"]>\n resources?: Partial<AuthzAdminLabels[\"resources\"]>\n grants?: Partial<AuthzAdminLabels[\"grants\"]>\n userRoles?: Partial<AuthzAdminLabels[\"userRoles\"]>\n error?: Partial<AuthzAdminLabels[\"error\"]>\n warn?: Partial<AuthzAdminLabels[\"warn\"]>\n}\n\n/** Shallow per-section merge over the English defaults. */\nexport function resolveLabels(over?: PartialAuthzAdminLabels): AuthzAdminLabels {\n const d = defaultAuthzAdminLabels\n if (!over) return d\n return {\n title: over.title ?? d.title,\n myPermission: over.myPermission ?? d.myPermission,\n tabs: { ...d.tabs, ...over.tabs },\n common: { ...d.common, ...over.common },\n roles: { ...d.roles, ...over.roles },\n resources: { ...d.resources, ...over.resources },\n grants: { ...d.grants, ...over.grants },\n userRoles: { ...d.userRoles, ...over.userRoles },\n error: { ...d.error, ...over.error },\n warn: { ...d.warn, ...over.warn },\n }\n}\n","/** 認可管理UI 共有のプレゼンテーション部品・スタイル。 */\nimport type { CSSProperties, ReactNode } from \"react\"\n\nexport const ui: Record<string, CSSProperties> = {\n page: { padding: \"1.25rem\", maxWidth: 1280, margin: \"0 auto\", color: \"#0f172a\" },\n tableContainer: { width: \"100%\", overflowX: \"auto\", marginBottom: \"1rem\", WebkitOverflowScrolling: \"touch\" },\n table: { borderCollapse: \"collapse\", width: \"100%\", fontSize: \"0.9rem\" },\n th: { textAlign: \"left\", borderBottom: \"2px solid #e2e8f0\", padding: \"0.45rem 0.65rem\", fontSize: \"0.78rem\", color: \"#475569\", fontWeight: 600, textTransform: \"uppercase\", letterSpacing: \"0.03em\" },\n td: { borderBottom: \"1px solid #f1f5f9\", padding: \"0.5rem 0.65rem\", verticalAlign: \"middle\" },\n input: { padding: \"0.4rem 0.55rem\", border: \"1px solid #cbd5e1\", borderRadius: 6, fontSize: \"0.9rem\", background: \"#fff\", width: \"100%\", boxSizing: \"border-box\" },\n select: { padding: \"0.4rem 0.55rem\", border: \"1px solid #cbd5e1\", borderRadius: 6, fontSize: \"0.9rem\", background: \"#fff\", width: \"100%\", boxSizing: \"border-box\" },\n 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\" },\n button: { padding: \"0.3rem 0.7rem\", border: \"1px solid #cbd5e1\", borderRadius: 6, background: \"#fff\", cursor: \"pointer\", fontSize: \"0.82rem\", color: \"#334155\" },\n save: { padding: \"0.3rem 0.7rem\", border: \"1px solid #2563eb\", borderRadius: 6, background: \"#eff6ff\", cursor: \"pointer\", fontSize: \"0.82rem\", color: \"#2563eb\", fontWeight: 600 },\n danger: { padding: \"0.3rem 0.7rem\", border: \"1px solid #fecaca\", borderRadius: 6, background: \"#fff\", cursor: \"pointer\", fontSize: \"0.82rem\", color: \"#dc2626\" },\n 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\" },\n 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\" },\n code: { fontFamily: \"ui-monospace, SFMono-Regular, Menlo, monospace\", fontSize: \"0.78rem\", color: \"#334155\", wordBreak: \"break-all\" },\n muted: { color: \"#94a3b8\" },\n h2: { fontSize: \"1.05rem\", margin: \"0 0 0.35rem\", fontWeight: 700 },\n h3: { fontSize: \"0.92rem\", margin: \"1.25rem 0 0\", color: \"#334155\", fontWeight: 600 },\n note: { color: \"#64748b\", fontSize: \"0.82rem\", margin: \"0 0 0.75rem\" },\n empty: { color: \"#94a3b8\", padding: \"0.75rem 0.65rem\" },\n}\n\n/**\n * ラベルを上、コントロールを下に縦積みするフィールド(重なり防止・一貫レイアウト)。\n * コントロール側は `aria-label` を持つ前提なので `<div>` で構成する。\n */\nexport function Field({ label, hint, children }: { label: string; hint?: string; children: ReactNode }) {\n return (\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: \"0.3rem\" }}>\n <span style={{ fontSize: \"0.8rem\", color: \"#475569\", fontWeight: 600 }}>\n {label}\n {hint ? <span style={{ fontWeight: 400, color: \"#94a3b8\" }}> — {hint}</span> : null}\n </span>\n {children}\n </div>\n )\n}\n\n/** エラー表示(role=\"alert\")。 */\nexport function ErrorAlert({ message }: { message?: string }) {\n if (!message) return null\n return (\n <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\" }}>\n {message}\n </p>\n )\n}\n","/**\n * 認可管理 UI のプレゼンテーション部品(client-safe)。\n * loader データ(行 + ラベル + 自己管理者ヒント)を `useLoaderData` で受け取り描画する。\n * DB/ストアには一切依存しない(サーバ結線は admin/server.ts)。\n */\nimport { AUTHZ_ACTIONS, type AuthzAssignment, type AuthzGrant, type AuthzResource, type AuthzRole, type AuthzUser } from \"@aiquants/authz-core\"\nimport { SelectBox } from \"@aiquants/select-box\"\nimport { useState } from \"react\"\nimport { Form, isRouteErrorResponse, NavLink, Outlet, useActionData, useLoaderData, useRouteError } from \"react-router\"\nimport { MyPermissionIndicator } from \"../MyPermissionIndicator\"\nimport type { PermissionView } from \"../server\"\nimport { type AuthzAdminLabels, type PartialAuthzAdminLabels, resolveLabels } from \"./labels\"\nimport { ErrorAlert, Field, ui } from \"./ui\"\n\ntype WithLabels = { labels: AuthzAdminLabels }\ntype ActionError = { error?: string } | undefined\nconst actionError = (d: ActionError) => d?.error\n\n// ============================ Layout ============================\n\nexport type AuthzLayoutData = WithLabels & { myPermissions: Record<string, PermissionView>; adminResourceKey: string; basePath?: string }\n\n/** ヘッダ(タイトル + あなたの権限) + タブ。中身は children(splat) か Outlet(ネスト)。 */\nfunction AuthzLayoutShell({ children }: { children: React.ReactNode }) {\n const { myPermissions, labels, adminResourceKey, basePath } = useLoaderData() as AuthzLayoutData\n const base = basePath ?? \"/authz\"\n const tabs: ReadonlyArray<readonly [string, string]> = [\n [\"roles\", labels.tabs.roles],\n [\"resources\", labels.tabs.resources],\n [\"role_permissions\", labels.tabs.role_permissions],\n [\"user_roles\", labels.tabs.user_roles],\n ]\n return (\n <div className=\"authz-admin\" style={ui.page}>\n <header style={{ display: \"flex\", alignItems: \"baseline\", justifyContent: \"space-between\", gap: \"1rem\", flexWrap: \"wrap\" }}>\n <h1 style={{ fontSize: \"1.3rem\", margin: 0, fontWeight: 700 }}>{labels.title}</h1>\n <span style={{ fontSize: \"0.82rem\", color: \"#475569\", display: \"inline-flex\", alignItems: \"center\", gap: \"0.4rem\" }}>\n {labels.myPermission}: <MyPermissionIndicator permission={myPermissions[adminResourceKey]} />\n </span>\n </header>\n <nav style={{ display: \"flex\", gap: \"0.25rem\", borderBottom: \"1px solid #e2e8f0\", margin: \"0.9rem 0 1.25rem\" }}>\n {tabs.map(([key, label]) => (\n <NavLink\n key={key}\n to={`${base}/${key}`}\n style={({ isActive }) => ({\n padding: \"0.5rem 0.9rem\",\n textDecoration: \"none\",\n color: isActive ? \"#2563eb\" : \"#475569\",\n borderBottom: isActive ? \"2px solid #2563eb\" : \"2px solid transparent\",\n marginBottom: -1,\n fontWeight: isActive ? 700 : 500,\n fontSize: \"0.92rem\",\n })}>\n {label}\n </NavLink>\n ))}\n </nav>\n {children}\n </div>\n )\n}\n\n/** ネストルート用レイアウト(子は Outlet)。`routes.ts` でネスト構成にする場合に使う。 */\nexport function AuthzLayout() {\n return (\n <AuthzLayoutShell>\n <Outlet />\n </AuthzLayoutShell>\n )\n}\n\n/**\n * 認可管理 UI のエラー境界。ErrorBoundary は loader データを読めないため、ラベルは\n * `makeAuthzErrorBoundary(labels)` で注入する(アプリは自分のロケールで生成する)。\n * 既定の `AuthzErrorBoundary` は英語(パッケージ既定)。\n */\nexport function makeAuthzErrorBoundary(over?: PartialAuthzAdminLabels): () => React.ReactElement {\n const L = resolveLabels(over).error\n return function AuthzErrorBoundary() {\n const error = useRouteError()\n const routeError = isRouteErrorResponse(error) ? error : null\n const is403 = routeError?.status === 403\n const title = is403 ? L.forbiddenTitle : routeError ? `${L.genericTitlePrefix} (${routeError.status})` : L.genericTitle\n const message = is403 ? L.forbiddenBody : routeError ? (typeof routeError.data === \"string\" && routeError.data ? routeError.data : routeError.statusText) : L.genericBody\n return (\n <div style={ui.page}>\n <div role=\"alert\" style={{ maxWidth: 480, margin: \"3rem auto\", padding: \"1.5rem\", border: \"1px solid #fecaca\", borderRadius: 12, background: \"#fef2f2\" }}>\n <h1 style={{ fontSize: \"1.1rem\", fontWeight: 700, color: \"#b91c1c\", margin: \"0 0 0.5rem\" }}>{title}</h1>\n <p style={{ color: \"#7f1d1d\", fontSize: \"0.9rem\", margin: 0, lineHeight: 1.7 }}>{message}</p>\n </div>\n </div>\n )\n }\n}\n\n/** 英語(既定ラベル)のエラー境界。i18n したい場合は {@link makeAuthzErrorBoundary} を使う。 */\nexport const AuthzErrorBoundary = makeAuthzErrorBoundary()\n\n/** 自分の管理権限を支える対象への破壊操作前に警告(キャンセルで送信中止)。 */\nconst confirmGuard = (active: boolean, message: string) => (e: React.MouseEvent) => {\n if (active && !window.confirm(message)) e.preventDefault()\n}\n\n// ============================ Roles ============================\n\nexport type AuthzRolesData = WithLabels & { roles: AuthzRole[]; selfAdminRoleIds?: number[] }\n\nexport function AuthzRolesView() {\n const { roles, selfAdminRoleIds, labels } = useLoaderData() as AuthzRolesData\n const L = labels.roles\n const C = labels.common\n const selfAdmin = new Set(selfAdminRoleIds ?? [])\n return (\n <section>\n <h2 style={ui.h2}>{L.heading}</h2>\n <ErrorAlert message={actionError(useActionData() as ActionError)} />\n <p style={ui.note}>{L.note}</p>\n <div style={ui.tableContainer}>\n <table style={ui.table}>\n <thead>\n <tr>\n <th style={{ ...ui.th, width: \"20%\" }}>{L.roleKey}</th>\n <th style={{ ...ui.th, width: \"25%\" }}>{L.name}</th>\n <th style={{ ...ui.th, width: \"35%\" }}>{L.description}</th>\n <th style={{ ...ui.th, width: \"10%\" }}>{L.activeHeader}</th>\n <th style={{ ...ui.th, width: \"10%\" }} />\n </tr>\n </thead>\n <tbody>\n {roles.map((r) => (\n <tr key={r.id}>\n <td style={ui.td}>\n {r.roleKey === \"@authenticated\" || r.roleKey === \"@anonymous\" ? <span style={ui.code}>{r.roleKey}</span> : <input name=\"roleKey\" defaultValue={r.roleKey} form={`save-role-${r.id}`} aria-label={`roleKey-${r.id}`} required style={ui.input} />}\n </td>\n <td style={ui.td}>\n <input name=\"name\" defaultValue={r.name} form={`save-role-${r.id}`} aria-label={`name-${r.id}`} required style={ui.input} />\n </td>\n <td style={ui.td}>\n <input name=\"description\" defaultValue={r.description ?? \"\"} form={`save-role-${r.id}`} aria-label={`description-${r.id}`} style={ui.input} />\n </td>\n <td style={ui.td}>\n <Form method=\"post\" style={{ display: \"inline\" }}>\n <input type=\"hidden\" name=\"_action\" value=\"toggle\" />\n <input type=\"hidden\" name=\"id\" value={r.id} />\n <input type=\"hidden\" name=\"isActive\" value={String(!r.isActive)} />\n <button type=\"submit\" style={ui.button} onClick={r.isActive ? confirmGuard(selfAdmin.has(r.id), labels.warn.selfRoleDisable) : undefined}>\n {r.isActive ? C.active : C.inactive}\n </button>\n </Form>\n </td>\n <td style={{ ...ui.td, whiteSpace: \"nowrap\" }}>\n <Form method=\"post\" id={`save-role-${r.id}`} style={{ display: \"inline\" }}>\n <input type=\"hidden\" name=\"_action\" value=\"save\" />\n <input type=\"hidden\" name=\"id\" value={r.id} />\n <button type=\"submit\" style={ui.save}>\n {C.save}\n </button>\n </Form>\n <Form method=\"post\" style={{ display: \"inline\", marginLeft: \"0.4rem\" }}>\n <input type=\"hidden\" name=\"_action\" value=\"delete\" />\n <input type=\"hidden\" name=\"id\" value={r.id} />\n <button type=\"submit\" style={ui.danger} onClick={confirmGuard(selfAdmin.has(r.id), labels.warn.selfRoleDelete)}>\n {C.delete}\n </button>\n </Form>\n </td>\n </tr>\n ))}\n {roles.length === 0 ? (\n <tr>\n <td style={ui.empty} colSpan={5}>\n {L.empty}\n </td>\n </tr>\n ) : null}\n </tbody>\n </table>\n </div>\n\n <h3 style={ui.h3}>{L.newHeading}</h3>\n <Form method=\"post\" style={ui.card}>\n <input type=\"hidden\" name=\"_action\" value=\"create\" />\n <Field label={L.roleKey} hint={L.hintRoleKey}>\n <input name=\"roleKey\" aria-label=\"role_key\" required style={ui.input} />\n </Field>\n <Field label={L.name}>\n <input name=\"name\" aria-label=\"name\" required style={ui.input} />\n </Field>\n <Field label={L.description} hint={C.optional}>\n <input name=\"description\" aria-label=\"description\" style={ui.input} />\n </Field>\n <button type=\"submit\" style={ui.primary}>\n {C.add}\n </button>\n </Form>\n </section>\n )\n}\n\n// ============================ Resources ============================\n\nexport type AuthzResourcesData = WithLabels & { resources: AuthzResource[] }\n\nexport function AuthzResourcesView() {\n const { resources, labels } = useLoaderData() as AuthzResourcesData\n const L = labels.resources\n const C = labels.common\n return (\n <section>\n <h2 style={ui.h2}>{L.heading}</h2>\n <ErrorAlert message={actionError(useActionData() as ActionError)} />\n <p style={ui.note}>{L.note}</p>\n <div style={ui.tableContainer}>\n <table style={ui.table}>\n <thead>\n <tr>\n <th style={{ ...ui.th, width: \"15%\" }}>{L.appKey}</th>\n <th style={{ ...ui.th, width: \"20%\" }}>{L.resourceKey}</th>\n <th style={{ ...ui.th, width: \"25%\" }}>{L.name}</th>\n <th style={{ ...ui.th, width: \"30%\" }}>{L.description}</th>\n <th style={{ ...ui.th, width: \"10%\" }} />\n </tr>\n </thead>\n <tbody>\n {resources.map((r) => (\n <tr key={r.id}>\n <td style={ui.td}>\n <span style={ui.code}>{r.appKey}</span>\n </td>\n <td style={ui.td}>\n <span style={ui.code}>{r.resourceKey}</span>\n </td>\n <td style={ui.td}>\n <input name=\"name\" defaultValue={r.name} form={`save-res-${r.id}`} aria-label={`name-${r.id}`} required style={ui.input} />\n </td>\n <td style={ui.td}>\n <input name=\"description\" defaultValue={r.description ?? \"\"} form={`save-res-${r.id}`} aria-label={`description-${r.id}`} style={ui.input} />\n </td>\n <td style={{ ...ui.td, whiteSpace: \"nowrap\" }}>\n <Form method=\"post\" id={`save-res-${r.id}`} style={{ display: \"inline\" }}>\n <input type=\"hidden\" name=\"_action\" value=\"save\" />\n <input type=\"hidden\" name=\"id\" value={r.id} />\n <button type=\"submit\" style={ui.save}>\n {C.save}\n </button>\n </Form>\n <Form method=\"post\" style={{ display: \"inline\", marginLeft: \"0.4rem\" }}>\n <input type=\"hidden\" name=\"_action\" value=\"delete\" />\n <input type=\"hidden\" name=\"id\" value={r.id} />\n <button type=\"submit\" style={ui.danger}>\n {C.delete}\n </button>\n </Form>\n </td>\n </tr>\n ))}\n {resources.length === 0 ? (\n <tr>\n <td style={ui.empty} colSpan={5}>\n {L.empty}\n </td>\n </tr>\n ) : null}\n </tbody>\n </table>\n </div>\n\n <h3 style={ui.h3}>{L.newHeading}</h3>\n <Form method=\"post\" style={ui.card}>\n <input type=\"hidden\" name=\"_action\" value=\"create\" />\n <Field label={L.appKey} hint={L.hintAppKey}>\n <input name=\"appKey\" aria-label=\"app_key\" required style={ui.input} />\n </Field>\n <Field label={L.resourceKey} hint={L.hintResourceKey}>\n <input name=\"resourceKey\" aria-label=\"resource_key\" required style={ui.input} />\n </Field>\n <Field label={L.name}>\n <input name=\"name\" aria-label=\"name\" required style={ui.input} />\n </Field>\n <Field label={L.description} hint={C.optional}>\n <input name=\"description\" aria-label=\"description\" style={ui.input} />\n </Field>\n <button type=\"submit\" style={ui.primary}>\n {C.add}\n </button>\n </Form>\n </section>\n )\n}\n\n// ============================ Grants (role_permissions) ============================\n\nexport type AuthzGrantsData = WithLabels & { grants: AuthzGrant[]; roles: Array<{ id: number; roleKey: string }>; resources: Array<{ id: number; appKey: string; resourceKey: string }> }\n\nfunction GrantRow({ g, labels }: { g: AuthzGrant; labels: AuthzAdminLabels }) {\n const C = labels.common\n const [action, setAction] = useState<{ label: string; value: string }>({ label: g.action, value: g.action })\n\n return (\n <tr>\n <td style={ui.td}>\n <span style={ui.code}>{g.roleKey}</span>\n </td>\n <td style={ui.td}>\n <span style={ui.code}>\n {g.appKey}:{g.resourceKey}\n </span>\n </td>\n <td style={ui.td}>\n {g.roleKey === \"@anonymous\" ? (\n <span style={ui.code}>{g.action}</span>\n ) : (\n <>\n <input type=\"hidden\" name=\"action\" value={action.value} form={`save-grant-${g.id}`} />\n <SelectBox\n options={AUTHZ_ACTIONS.map((a) => ({ label: a, value: a }))}\n value={action}\n onChange={(val) => {\n if (val) setAction(val as { label: string; value: string })\n }}\n />\n </>\n )}\n </td>\n <td style={ui.td}>\n <textarea name=\"rowScope\" defaultValue={g.rowScope ?? \"\"} form={`save-grant-${g.id}`} aria-label={`row_scope-${g.id}`} rows={2} placeholder={labels.grants.rowScopePlaceholder} style={ui.textarea} />\n </td>\n <td style={ui.td}>\n <textarea name=\"columnScope\" defaultValue={g.columnScope ?? \"\"} form={`save-grant-${g.id}`} aria-label={`column_scope-${g.id}`} rows={2} placeholder={labels.grants.columnScopePlaceholder} style={ui.textarea} />\n </td>\n <td style={{ ...ui.td, whiteSpace: \"nowrap\" }}>\n <Form method=\"post\" id={`save-grant-${g.id}`} style={{ display: \"inline\" }}>\n <input type=\"hidden\" name=\"_action\" value=\"save\" />\n <input type=\"hidden\" name=\"id\" value={g.id} />\n <button type=\"submit\" style={ui.save}>\n {C.save}\n </button>\n </Form>\n <Form method=\"post\" style={{ display: \"inline\", marginLeft: \"0.4rem\" }}>\n <input type=\"hidden\" name=\"_action\" value=\"delete\" />\n <input type=\"hidden\" name=\"id\" value={g.id} />\n <button type=\"submit\" style={ui.danger}>\n {C.delete}\n </button>\n </Form>\n </td>\n </tr>\n )\n}\n\nexport function AuthzGrantsView() {\n const { grants, roles, resources, labels } = useLoaderData() as AuthzGrantsData\n const L = labels.grants\n const C = labels.common\n\n const roleOptions = roles.map((r) => ({ label: r.roleKey, value: r.id }))\n const resourceOptions = resources.map((r) => ({ label: `${r.appKey}:${r.resourceKey}`, value: r.id }))\n const actionOptions = AUTHZ_ACTIONS.map((a) => ({ label: a, value: a }))\n\n const [selectedRole, setSelectedRole] = useState<{ label: string; value: number } | undefined>(undefined)\n const [selectedResource, setSelectedResource] = useState<{ label: string; value: number } | undefined>(undefined)\n const [selectedAction, setSelectedAction] = useState<{ label: string; value: string } | undefined>({ label: \"read\", value: \"read\" })\n\n return (\n <section>\n <h2 style={ui.h2}>{L.heading}</h2>\n <p style={ui.note}>{L.note}</p>\n <ErrorAlert message={actionError(useActionData() as ActionError)} />\n <div style={ui.tableContainer}>\n <table style={ui.table}>\n <thead>\n <tr>\n <th style={{ ...ui.th, width: \"15%\" }}>{L.role}</th>\n <th style={{ ...ui.th, width: \"20%\" }}>{L.resource}</th>\n <th style={{ ...ui.th, width: \"15%\" }}>{L.action}</th>\n <th style={{ ...ui.th, width: \"20%\" }}>{L.rowScope}</th>\n <th style={{ ...ui.th, width: \"20%\" }}>{L.columnScope}</th>\n <th style={{ ...ui.th, width: \"10%\" }} />\n </tr>\n </thead>\n <tbody>\n {grants.map((g) => (\n <GrantRow key={g.id} g={g} labels={labels} />\n ))}\n {grants.length === 0 ? (\n <tr>\n <td style={ui.empty} colSpan={6}>\n {L.empty}\n </td>\n </tr>\n ) : null}\n </tbody>\n </table>\n </div>\n\n <h3 style={ui.h3}>{L.newHeading}</h3>\n <Form method=\"post\" style={ui.card}>\n <input type=\"hidden\" name=\"_action\" value=\"create\" />\n <input type=\"hidden\" name=\"roleId\" value={selectedRole?.value ?? \"\"} />\n <input type=\"hidden\" name=\"resourceId\" value={selectedResource?.value ?? \"\"} />\n <input type=\"hidden\" name=\"action\" value={selectedAction?.value ?? \"\"} />\n\n <Field label={L.role}>\n <SelectBox options={roleOptions} value={selectedRole} onChange={(val) => setSelectedRole((val || undefined) as { label: string; value: number } | undefined)} placeholder={L.selectPlaceholder} />\n </Field>\n <Field label={L.resource}>\n <SelectBox options={resourceOptions} value={selectedResource} onChange={(val) => setSelectedResource((val || undefined) as { label: string; value: number } | undefined)} placeholder={L.selectPlaceholder} />\n </Field>\n <Field label={L.action}>\n <SelectBox options={actionOptions} value={selectedAction} onChange={(val) => setSelectedAction((val || undefined) as { label: string; value: string } | undefined)} />\n </Field>\n <Field label={L.rowScope} hint={L.rowScopeHint}>\n <textarea name=\"rowScope\" aria-label=\"row_scope\" rows={2} style={ui.textarea} placeholder='{\"filters\":[{\"field\":\"部門CD\",\"op\":\"in\",\"values\":[\"A\"]}]}' />\n </Field>\n <Field label={L.columnScope} hint={L.columnScopeHint}>\n <textarea name=\"columnScope\" aria-label=\"column_scope\" rows={2} style={ui.textarea} placeholder='{\"mode\":\"deny\",\"columns\":[\"金額\"]}' />\n </Field>\n <button type=\"submit\" style={ui.primary}>\n {C.grant}\n </button>\n </Form>\n </section>\n )\n}\n\n// ============================ User roles ============================\n\nexport type AuthzUserRolesData = WithLabels & { assignments: AuthzAssignment[]; roles: Array<{ id: number; roleKey: string }>; users: AuthzUser[]; actorUserId?: number; selfAdminRoleIds?: number[] }\n\nexport function AuthzUserRolesView() {\n const { assignments, roles, users, actorUserId, selfAdminRoleIds, labels } = useLoaderData() as AuthzUserRolesData\n const L = labels.userRoles\n const C = labels.common\n const selfAdmin = new Set(selfAdminRoleIds ?? [])\n\n const userOptions = users.map((u) => ({ label: `${u.email}(${u.displayName})`, value: u.id }))\n const roleOptions = roles.filter((r) => r.roleKey !== \"@authenticated\" && r.roleKey !== \"@anonymous\").map((r) => ({ label: r.roleKey, value: r.id }))\n\n const [selectedUser, setSelectedUser] = useState<{ label: string; value: number } | undefined>(undefined)\n const [selectedRole, setSelectedRole] = useState<{ label: string; value: number } | undefined>(undefined)\n\n return (\n <section>\n <h2 style={ui.h2}>{L.heading}</h2>\n <ErrorAlert message={actionError(useActionData() as ActionError)} />\n <div style={ui.tableContainer}>\n <table style={ui.table}>\n <thead>\n <tr>\n <th style={{ ...ui.th, width: \"45%\" }}>{L.user}</th>\n <th style={{ ...ui.th, width: \"45%\" }}>{L.role}</th>\n <th style={{ ...ui.th, width: \"10%\" }} />\n </tr>\n </thead>\n <tbody>\n {assignments.map((a) => (\n <tr key={`${a.userId}-${a.roleId}`}>\n <td style={ui.td}>\n {a.email}\n <span style={ui.muted}>({a.displayName})</span>\n </td>\n <td style={ui.td}>{a.roleKey}</td>\n <td style={ui.td}>\n <Form method=\"post\" style={{ display: \"inline\" }}>\n <input type=\"hidden\" name=\"_action\" value=\"remove\" />\n <input type=\"hidden\" name=\"userId\" value={a.userId} />\n <input type=\"hidden\" name=\"roleId\" value={a.roleId} />\n <button type=\"submit\" style={ui.danger} onClick={confirmGuard(a.userId === actorUserId && selfAdmin.has(a.roleId), labels.warn.selfAssignmentRemove)}>\n {C.remove}\n </button>\n </Form>\n </td>\n </tr>\n ))}\n {assignments.length === 0 ? (\n <tr>\n <td style={ui.empty} colSpan={3}>\n {L.empty}\n </td>\n </tr>\n ) : null}\n </tbody>\n </table>\n </div>\n\n <h3 style={ui.h3}>{L.newHeading}</h3>\n <Form method=\"post\" style={ui.card}>\n <input type=\"hidden\" name=\"_action\" value=\"assign\" />\n <input type=\"hidden\" name=\"userId\" value={selectedUser?.value ?? \"\"} />\n <input type=\"hidden\" name=\"roleId\" value={selectedRole?.value ?? \"\"} />\n <Field label={L.user}>\n <SelectBox options={userOptions} value={selectedUser} onChange={(val) => setSelectedUser((val || undefined) as { label: string; value: number } | undefined)} placeholder={L.selectPlaceholder} />\n </Field>\n <Field label={L.role}>\n <SelectBox options={roleOptions} value={selectedRole} onChange={(val) => setSelectedRole((val || undefined) as { label: string; value: number } | undefined)} placeholder={L.selectPlaceholder} />\n </Field>\n <button type=\"submit\" style={ui.primary}>\n {C.assign}\n </button>\n </Form>\n </section>\n )\n}\n\n// ============================ Single-file (splat) app view ============================\n\nconst SEGMENT_VIEWS: Record<string, () => React.ReactElement> = {\n roles: AuthzRolesView,\n resources: AuthzResourcesView,\n role_permissions: AuthzGrantsView,\n user_roles: AuthzUserRolesView,\n}\n\n/**\n * スプラット(`authz/*`)1 ルートで認可管理 UI 全体を描画するコンポーネント(store 非依存)。\n * loader が返す `segment` に応じて該当タブのビューを描画する。レイアウト殻と各ビューは同一の\n * loader データ(セグメントデータ + myPermissions + labels をトップレベルに統合)を読む。\n */\nexport function AuthzAdminAppView() {\n const { segment } = useLoaderData() as { segment: string }\n const View = SEGMENT_VIEWS[segment] ?? AuthzRolesView\n return (\n <AuthzLayoutShell>\n <View />\n </AuthzLayoutShell>\n )\n}\n","import type { PermissionView } from \"./server\"\n\nexport type PermState = \"full\" | \"partial\" | \"none\"\n\nexport type UsePermission = {\n canRead: boolean\n canWrite: boolean\n canDelete: boolean\n /** read: none(×) / partial(△, row|col restricted) / full(○). */\n readState: PermState\n /** write = create ∪ update: full(○ both) / partial(△ one) / none(×). */\n writeState: PermState\n deleteState: PermState\n}\n\n/**\n * Derive ○△× display states from a {@link PermissionView}. Pure (safe to call in render);\n * named `usePermission` for ergonomic call-sites.\n */\nexport function usePermission(view: PermissionView | null | undefined): UsePermission {\n const readState: PermState = !view?.read ? \"none\" : view.readPartial ? \"partial\" : \"full\"\n const writeState: PermState = view?.create && view?.update ? \"full\" : view?.create || view?.update ? \"partial\" : \"none\"\n const deleteState: PermState = view?.delete ? \"full\" : \"none\"\n return {\n canRead: !!view?.read,\n canWrite: !!view?.write,\n canDelete: !!view?.delete,\n readState,\n writeState,\n deleteState,\n }\n}\n","import type { PermissionView } from \"./server\"\nimport { type PermState, usePermission } from \"./usePermission\"\n\nexport type MyPermissionIndicatorProps = {\n permission: PermissionView | null | undefined\n labels?: { read?: string; write?: string; delete?: string }\n /** Show a \"(部分)\" hint when read is partial. Default true. */\n showScopeSummary?: boolean\n className?: string\n}\n\nconst STATE_STYLE: Record<PermState, { bg: string; text: string; border: string }> = {\n full: { bg: \"#ecfdf5\", text: \"#047857\", border: \"#a7f3d0\" },\n partial: { bg: \"#fffbeb\", text: \"#b45309\", border: \"#fde68a\" },\n none: { bg: \"#f8fafc\", text: \"#94a3b8\", border: \"#cbd5e1\" },\n}\n\nfunction PermIcon({ state }: { state: PermState }) {\n if (state === \"full\") {\n return (\n <svg style={{ width: \"0.85rem\", height: \"0.85rem\", flexShrink: 0 }} fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={3} aria-hidden=\"true\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M5 13l4 4L19 7\" />\n </svg>\n )\n }\n if (state === \"partial\") {\n return (\n <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\">\n <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\" />\n </svg>\n )\n }\n return (\n <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\">\n <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\" />\n </svg>\n )\n}\n\nexport function MyPermissionIndicator({ permission, labels, showScopeSummary = true, className = \"authz-permission-indicator\" }: MyPermissionIndicatorProps) {\n const p = usePermission(permission)\n const l = { read: labels?.read ?? \"閲覧\", write: labels?.write ?? \"編集\", delete: labels?.delete ?? \"削除\" }\n\n const renderBadge = (key: \"read\" | \"write\" | \"delete\", state: PermState, label: string) => {\n const style = STATE_STYLE[state]\n return (\n <span\n data-perm={key}\n data-state={state}\n title={`${label}: ${state}`}\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n gap: \"0.25rem\",\n padding: \"0.2rem 0.5rem\",\n borderRadius: \"100px\",\n fontSize: \"0.75rem\",\n fontWeight: 600,\n backgroundColor: style.bg,\n color: style.text,\n border: `1px solid ${style.border}`,\n lineHeight: 1,\n userSelect: \"none\",\n }}>\n <PermIcon state={state} />\n <span>{label}</span>\n </span>\n )\n }\n\n return (\n <span\n className={className}\n data-resource={permission?.resourceKey ?? \"\"}\n style={{\n display: \"inline-flex\",\n gap: \"0.35rem\",\n alignItems: \"center\",\n verticalAlign: \"middle\",\n }}>\n {renderBadge(\"read\", p.readState, l.read)}\n {renderBadge(\"write\", p.writeState, l.write)}\n {renderBadge(\"delete\", p.deleteState, l.delete)}\n {showScopeSummary && p.readState === \"partial\" ? (\n <span\n data-perm=\"scope\"\n style={{\n fontSize: \"0.7rem\",\n color: \"#b45309\",\n backgroundColor: \"#fef3c7\",\n padding: \"0.15rem 0.35rem\",\n borderRadius: \"4px\",\n fontWeight: 600,\n }}>\n 部分制限\n </span>\n ) : null}\n </span>\n )\n}\n","import { type AuthzAction, can, createRequirePermission, type DenyInfo, type EffectivePermission, type GuardResult } from \"@aiquants/authz-core\"\nimport { redirect } from \"react-router\"\n\ntype Awaitable<T> = T | Promise<T>\nexport type AuthzUserId = string | number\n\nexport type AuthzConfig = {\n /** Stable app identifier (e.g. \"quants\"). Bound into every permission query. */\n appKey: string\n /** Resolve the acting user id from the request (cookie/session/openid → TDUsers.id). */\n resolveUserId: (request: Request) => Awaitable<AuthzUserId | null | undefined>\n /** Load effective permissions for (user, app, resource) — typically via @aiquants/authz-drizzle. */\n getEffectivePermissions: (args: { userId: AuthzUserId | null; appKey: string; resourceKey: string }) => Awaitable<EffectivePermission | null | undefined>\n /** Default deny handler. If omitted, denies throw AuthzDeniedError (403). */\n onDeny?: (info: DenyInfo) => void\n}\n\nexport type RequirePermissionOptions = {\n /** When set, denials `throw redirect(failureRedirect)` instead of throwing 403. */\n failureRedirect?: string\n}\n\n/** Serializable per-resource permission summary for UI (loader → component). */\nexport type PermissionView = {\n resourceKey: string\n read: boolean\n create: boolean\n update: boolean\n delete: boolean\n /** create ∪ update */\n write: boolean\n /** read granted but row and/or column restricted (→ △ partial). */\n readPartial: boolean\n actions: AuthzAction[]\n}\n\n/** Map an EffectivePermission to a serializable {@link PermissionView}. */\nexport function toPermissionView(resourceKey: string, perm: EffectivePermission | null | undefined): PermissionView {\n const read = can(perm, \"read\")\n const create = can(perm, \"create\")\n const update = can(perm, \"update\")\n const del = can(perm, \"delete\")\n const readScope = perm?.scopeByAction.read\n const readPartial = read && !!readScope && (readScope.rowScope !== null || readScope.columnScope !== null)\n return {\n resourceKey,\n read,\n create,\n update,\n delete: del,\n write: create || update,\n readPartial,\n actions: perm ? Array.from(perm.actions) : [],\n }\n}\n\n/**\n * React Router adapter. Binds `appKey` and the DI deps, exposing:\n * - `requirePermission(request, {resourceKey, action}, options?)` → `{ userId, scope }` on allow\n * (apply row WHERE / column mask with the returned scope); denies throw 403 or redirect.\n * - `getMyPermissions(request, {resourceKeys})` → `Record<resourceKey, PermissionView>` for the UI.\n */\nexport function createAuthz(config: AuthzConfig) {\n async function requirePermission(request: Request, query: { resourceKey: string; action: AuthzAction }, options?: RequirePermissionOptions): Promise<GuardResult<AuthzUserId>> {\n const onDeny: ((info: DenyInfo) => void) | undefined = options?.failureRedirect\n ? () => {\n throw redirect(options.failureRedirect as string)\n }\n : config.onDeny\n const guard = createRequirePermission<Request, AuthzUserId>({\n resolveUserId: config.resolveUserId,\n getEffectivePermissions: config.getEffectivePermissions,\n onDeny,\n })\n return guard(request, { appKey: config.appKey, resourceKey: query.resourceKey, action: query.action })\n }\n\n async function getMyPermissions(request: Request, query: { resourceKeys: string[] }): Promise<Record<string, PermissionView>> {\n const userId = await config.resolveUserId(request)\n const out: Record<string, PermissionView> = {}\n for (const resourceKey of query.resourceKeys) {\n const perm = await config.getEffectivePermissions({ userId: userId ?? null, appKey: config.appKey, resourceKey })\n out[resourceKey] = toPermissionView(resourceKey, perm)\n }\n return out\n }\n\n return { requirePermission, getMyPermissions }\n}\n"],"mappings":"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","names":["index_exports","__export","AuthzAdminAppView","AuthzErrorBoundary","AuthzGrantsView","AuthzLayout","AuthzResourcesView","AuthzRolesView","AuthzUserRolesView","ErrorAlert","Field","MyPermissionIndicator","createAuthz","createAuthzAdminApp","createAuthzAdminServer","defaultAuthzAdminLabels","makeAuthzErrorBoundary","resolveLabels","toPermissionView","ui","usePermission","__toCommonJS","import_react_router","import_authz_core","import_react_router","defaultAuthzAdminLabels","resolveLabels","over","d","isResponse","e","toActionError","createAuthzAdminServer","opts","store","RES","labels","resolveLabels","requirePermission","request","query","userId","layoutGuard","loadMyPermissions","rolesData","roles","self","resourcesData","grantsData","grants","resources","userRolesData","assignments","users","form","intent","roleKey","name","appKey","resourceKey","roleId","resourceId","rawAction","action","actor","segmentOf","params","createAuthzAdminApp","opts","server","createAuthzAdminServer","basePath","SEGMENTS","segmentData","actions","loader","args","segment","userId","myPermissions","segData","action","act","import_jsx_runtime","ui","Field","label","hint","children","ErrorAlert","message","import_authz_core","import_select_box","import_react","import_react_router","usePermission","view","readState","writeState","deleteState","import_jsx_runtime","STATE_STYLE","PermIcon","state","MyPermissionIndicator","permission","labels","showScopeSummary","className","p","usePermission","l","renderBadge","key","label","style","import_jsx_runtime","actionError","d","AuthzLayoutShell","children","myPermissions","labels","adminResourceKey","basePath","base","tabs","ui","MyPermissionIndicator","key","label","isActive","AuthzLayout","makeAuthzErrorBoundary","over","L","resolveLabels","error","routeError","is403","title","message","AuthzErrorBoundary","confirmGuard","active","e","AuthzRolesView","roles","selfAdminRoleIds","C","selfAdmin","ErrorAlert","r","Field","AuthzResourcesView","resources","GrantRow","g","action","setAction","a","val","AuthzGrantsView","grants","roleOptions","resourceOptions","actionOptions","selectedRole","setSelectedRole","selectedResource","setSelectedResource","selectedAction","setSelectedAction","AuthzUserRolesView","assignments","users","actorUserId","userOptions","u","selectedUser","setSelectedUser","SEGMENT_VIEWS","AuthzAdminAppView","segment","View","import_authz_core","import_react_router","toPermissionView","resourceKey","perm","read","create","update","del","readScope","readPartial","createAuthz","config","requirePermission","request","query","options","onDeny","getMyPermissions","userId","out"]}
|