@aiquants/auth-react-router 0.5.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -10,6 +10,28 @@ pnpm add @aiquants/auth-core @aiquants/auth-react-router
10
10
 
11
11
  Peers: `react`, `react-router@^7`, `remix-auth@^4`, `remix-auth-oauth2@^3`, `react-icons`.
12
12
 
13
+ ## User admin shell: the self-permission badge
14
+
15
+ The admin shell (`createUserAdminApp`) renders a "your permissions" badge in its header. Two optional ports feed it,
16
+ and both are **fail-closed by design**:
17
+
18
+ ```ts
19
+ createUserAdminApp({
20
+ store, guards,
21
+ // resolves to a map of { canRead, canWrite, canDelete } per resource key.
22
+ // Any authz view carrying those three booleans satisfies it structurally — no import from an authz package.
23
+ getMyPermissions: (request) => myAuthz.getMyPermissions(request, { resourceKeys: ["authz_admin"] }),
24
+ // display names for those keys; unlisted keys render as the raw key
25
+ resourceLabels: { authz_admin: "ユーザー管理 UI" },
26
+ })
27
+ ```
28
+
29
+ - Query **the resource your guards actually check**. Asking about a different key makes the badge disagree with the
30
+ guard — the user is admitted but told they have no permission.
31
+ - If the port is absent, rejects, or returns no entries, the badge renders an explicit "unknown" state
32
+ (`data-testid="user-admin-permission-unavailable"`) and the failure is logged. It never renders a permissive value:
33
+ a badge that claims "editable" when the answer is unknown is worse than no badge at all.
34
+
13
35
  ## Wiring (single composition point — `app/services/auth/config.server.ts`)
14
36
 
15
37
  ```ts
package/dist/admin.d.mts CHANGED
@@ -1,5 +1,4 @@
1
1
  import { AuthUser, AuthGroup, AuthGroupMember, AuthAllowlistEntry } from '@aiquants/auth-core';
2
- import { LoaderFunctionArgs, ActionFunctionArgs } from 'react-router';
3
2
  import React__default from 'react';
4
3
 
5
4
  /**
@@ -166,6 +165,15 @@ declare function createInMemoryUserAdminStore(initial?: {
166
165
  * independent of any particular authorization library.
167
166
  * 操作が行う CRUD 種別。特定の認可ライブラリに依存しないよう素の文字列 union で表現する。
168
167
  */
168
+ /**
169
+ * The only route-args field this module reads. React Router's full `LoaderFunctionArgs` satisfies it, so
170
+ * route wiring is unchanged — but declaring the minimum keeps callers (and tests) from fabricating fields
171
+ * that are never looked at.
172
+ * このモジュールが実際に読むルート引数の全て。React Router の完全な引数はこれを満たすため結線は不変。
173
+ */
174
+ type RouteArgs = {
175
+ request: Request;
176
+ };
169
177
  type UserAdminAccess = "read" | "create" | "update" | "delete";
170
178
  /**
171
179
  * Access guard the user-admin surface is mounted behind. Deny by throwing
@@ -187,6 +195,19 @@ type UserAdminGuards = {
187
195
  intent: string;
188
196
  }) => Promise<void> | void;
189
197
  };
198
+ /**
199
+ * Neutral per-resource permission summary the admin shell renders in its header badge.
200
+ * 管理シェルのヘッダーバッジが描画する、リソース単位の中立な権限サマリ。
201
+ *
202
+ * この形はこのパッケージ自身の契約であり、特定の認可ライブラリの型を import しない
203
+ * (`AGENTS.md` のクロスパッケージ・ハードコード禁止)。`canRead` / `canWrite` / `canDelete` を持つ
204
+ * ビューであれば構造的にそのまま渡せる。
205
+ */
206
+ type UserAdminPermission = {
207
+ canRead: boolean;
208
+ canWrite: boolean;
209
+ canDelete: boolean;
210
+ };
190
211
  type UserAdminAppConfig = {
191
212
  store: UserAdminStore;
192
213
  /** セクション単位の部分上書き。既定は英語 (`defaultUserAdminLabels`)。 */
@@ -196,6 +217,21 @@ type UserAdminAppConfig = {
196
217
  * 必須。省略を許すとユーザー名簿と全更新操作が無防備に露出するため、型で強制する。
197
218
  */
198
219
  guards: UserAdminGuards;
220
+ /**
221
+ * Per-request self-permission lookup for the header annotation. Resolving to a map of
222
+ * {@link UserAdminPermission} shows the badge; rejecting shows an explicit "unknown" badge — never a
223
+ * permissive one. Any authz library whose view carries `canRead` / `canWrite` / `canDelete` satisfies it.
224
+ * ヘッダー注釈に自分の実効権限を表示するためのリクエスト別権限取得関数。失敗時は「権限不明」表示。
225
+ */
226
+ getMyPermissions?: (request: Request) => Promise<Record<string, UserAdminPermission | undefined>>;
227
+ /**
228
+ * Display names for the resource keys the badge shows, e.g. `{ authz_admin: "ユーザー管理 UI" }`.
229
+ * バッジに出すリソースキーの表示名。未指定のキーはキー文字列をそのまま表示。
230
+ *
231
+ * 表示名をこのパッケージ側に埋め込むと、別パッケージのリソースキーを名指しすることになる
232
+ * (`AGENTS.md` のクロスパッケージ・ハードコード禁止)。中立な差し込み口として受け取る。
233
+ */
234
+ resourceLabels?: Record<string, string>;
199
235
  };
200
236
  /**
201
237
  * Creates React Router loader & action handler for user administration.
@@ -204,15 +240,17 @@ type UserAdminAppConfig = {
204
240
  * `config.guards` は必須。loader / action の双方が、処理を始める前にガードを通過させる。
205
241
  */
206
242
  declare function createUserAdminApp(config: UserAdminAppConfig): {
207
- loader: ({ request }: LoaderFunctionArgs) => Promise<{
243
+ loader: ({ request }: RouteArgs) => Promise<{
244
+ resourceLabels: Record<string, string> | undefined;
208
245
  segment: string;
209
246
  users: AuthUser[];
210
247
  groups: AuthGroup[];
211
248
  groupMembers: AuthGroupMember[];
212
249
  allowlist: AuthAllowlistEntry[];
250
+ myPermissions: Record<string, UserAdminPermission | undefined> | null;
213
251
  labels: UserAdminLabels;
214
252
  }>;
215
- action: ({ request }: ActionFunctionArgs) => Promise<{
253
+ action: ({ request }: RouteArgs) => Promise<{
216
254
  ok: boolean;
217
255
  error?: undefined;
218
256
  } | {
@@ -265,4 +303,4 @@ type AuthUserAdminAppViewProps = UserAdminShellProps;
265
303
  */
266
304
  declare function AuthUserAdminAppView({ renderHeader }?: AuthUserAdminAppViewProps): React__default.JSX.Element;
267
305
 
268
- export { AllowlistView, AuthUserAdminAppView, type AuthUserAdminAppViewProps, GroupMembersView, GroupsView, type PartialUserAdminLabels, type UserAdminAccess, type UserAdminAppConfig, type UserAdminGuards, type UserAdminLabels, type UserAdminLoaderData, UserAdminShell, type UserAdminShellProps, type UserAdminStore, UsersView, createInMemoryUserAdminStore, createUserAdminApp, defaultUserAdminLabels, jaUserAdminLabels, resolveUserAdminLabels };
306
+ export { AllowlistView, AuthUserAdminAppView, type AuthUserAdminAppViewProps, GroupMembersView, GroupsView, type PartialUserAdminLabels, type UserAdminAccess, type UserAdminAppConfig, type UserAdminGuards, type UserAdminLabels, type UserAdminLoaderData, type UserAdminPermission, UserAdminShell, type UserAdminShellProps, type UserAdminStore, UsersView, createInMemoryUserAdminStore, createUserAdminApp, defaultUserAdminLabels, jaUserAdminLabels, resolveUserAdminLabels };
package/dist/admin.d.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  import { AuthUser, AuthGroup, AuthGroupMember, AuthAllowlistEntry } from '@aiquants/auth-core';
2
- import { LoaderFunctionArgs, ActionFunctionArgs } from 'react-router';
3
2
  import React__default from 'react';
4
3
 
5
4
  /**
@@ -166,6 +165,15 @@ declare function createInMemoryUserAdminStore(initial?: {
166
165
  * independent of any particular authorization library.
167
166
  * 操作が行う CRUD 種別。特定の認可ライブラリに依存しないよう素の文字列 union で表現する。
168
167
  */
168
+ /**
169
+ * The only route-args field this module reads. React Router's full `LoaderFunctionArgs` satisfies it, so
170
+ * route wiring is unchanged — but declaring the minimum keeps callers (and tests) from fabricating fields
171
+ * that are never looked at.
172
+ * このモジュールが実際に読むルート引数の全て。React Router の完全な引数はこれを満たすため結線は不変。
173
+ */
174
+ type RouteArgs = {
175
+ request: Request;
176
+ };
169
177
  type UserAdminAccess = "read" | "create" | "update" | "delete";
170
178
  /**
171
179
  * Access guard the user-admin surface is mounted behind. Deny by throwing
@@ -187,6 +195,19 @@ type UserAdminGuards = {
187
195
  intent: string;
188
196
  }) => Promise<void> | void;
189
197
  };
198
+ /**
199
+ * Neutral per-resource permission summary the admin shell renders in its header badge.
200
+ * 管理シェルのヘッダーバッジが描画する、リソース単位の中立な権限サマリ。
201
+ *
202
+ * この形はこのパッケージ自身の契約であり、特定の認可ライブラリの型を import しない
203
+ * (`AGENTS.md` のクロスパッケージ・ハードコード禁止)。`canRead` / `canWrite` / `canDelete` を持つ
204
+ * ビューであれば構造的にそのまま渡せる。
205
+ */
206
+ type UserAdminPermission = {
207
+ canRead: boolean;
208
+ canWrite: boolean;
209
+ canDelete: boolean;
210
+ };
190
211
  type UserAdminAppConfig = {
191
212
  store: UserAdminStore;
192
213
  /** セクション単位の部分上書き。既定は英語 (`defaultUserAdminLabels`)。 */
@@ -196,6 +217,21 @@ type UserAdminAppConfig = {
196
217
  * 必須。省略を許すとユーザー名簿と全更新操作が無防備に露出するため、型で強制する。
197
218
  */
198
219
  guards: UserAdminGuards;
220
+ /**
221
+ * Per-request self-permission lookup for the header annotation. Resolving to a map of
222
+ * {@link UserAdminPermission} shows the badge; rejecting shows an explicit "unknown" badge — never a
223
+ * permissive one. Any authz library whose view carries `canRead` / `canWrite` / `canDelete` satisfies it.
224
+ * ヘッダー注釈に自分の実効権限を表示するためのリクエスト別権限取得関数。失敗時は「権限不明」表示。
225
+ */
226
+ getMyPermissions?: (request: Request) => Promise<Record<string, UserAdminPermission | undefined>>;
227
+ /**
228
+ * Display names for the resource keys the badge shows, e.g. `{ authz_admin: "ユーザー管理 UI" }`.
229
+ * バッジに出すリソースキーの表示名。未指定のキーはキー文字列をそのまま表示。
230
+ *
231
+ * 表示名をこのパッケージ側に埋め込むと、別パッケージのリソースキーを名指しすることになる
232
+ * (`AGENTS.md` のクロスパッケージ・ハードコード禁止)。中立な差し込み口として受け取る。
233
+ */
234
+ resourceLabels?: Record<string, string>;
199
235
  };
200
236
  /**
201
237
  * Creates React Router loader & action handler for user administration.
@@ -204,15 +240,17 @@ type UserAdminAppConfig = {
204
240
  * `config.guards` は必須。loader / action の双方が、処理を始める前にガードを通過させる。
205
241
  */
206
242
  declare function createUserAdminApp(config: UserAdminAppConfig): {
207
- loader: ({ request }: LoaderFunctionArgs) => Promise<{
243
+ loader: ({ request }: RouteArgs) => Promise<{
244
+ resourceLabels: Record<string, string> | undefined;
208
245
  segment: string;
209
246
  users: AuthUser[];
210
247
  groups: AuthGroup[];
211
248
  groupMembers: AuthGroupMember[];
212
249
  allowlist: AuthAllowlistEntry[];
250
+ myPermissions: Record<string, UserAdminPermission | undefined> | null;
213
251
  labels: UserAdminLabels;
214
252
  }>;
215
- action: ({ request }: ActionFunctionArgs) => Promise<{
253
+ action: ({ request }: RouteArgs) => Promise<{
216
254
  ok: boolean;
217
255
  error?: undefined;
218
256
  } | {
@@ -265,4 +303,4 @@ type AuthUserAdminAppViewProps = UserAdminShellProps;
265
303
  */
266
304
  declare function AuthUserAdminAppView({ renderHeader }?: AuthUserAdminAppViewProps): React__default.JSX.Element;
267
305
 
268
- export { AllowlistView, AuthUserAdminAppView, type AuthUserAdminAppViewProps, GroupMembersView, GroupsView, type PartialUserAdminLabels, type UserAdminAccess, type UserAdminAppConfig, type UserAdminGuards, type UserAdminLabels, type UserAdminLoaderData, UserAdminShell, type UserAdminShellProps, type UserAdminStore, UsersView, createInMemoryUserAdminStore, createUserAdminApp, defaultUserAdminLabels, jaUserAdminLabels, resolveUserAdminLabels };
306
+ export { AllowlistView, AuthUserAdminAppView, type AuthUserAdminAppViewProps, GroupMembersView, GroupsView, type PartialUserAdminLabels, type UserAdminAccess, type UserAdminAppConfig, type UserAdminGuards, type UserAdminLabels, type UserAdminLoaderData, type UserAdminPermission, UserAdminShell, type UserAdminShellProps, type UserAdminStore, UsersView, createInMemoryUserAdminStore, createUserAdminApp, defaultUserAdminLabels, jaUserAdminLabels, resolveUserAdminLabels };
package/dist/admin.js CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";var G=Object.defineProperty;var T=Object.getOwnPropertyDescriptor;var F=Object.getOwnPropertyNames;var K=Object.prototype.hasOwnProperty;var $=(i,s)=>{for(var t in s)G(i,t,{get:s[t],enumerable:!0})},W=(i,s,t,d)=>{if(s&&typeof s=="object"||typeof s=="function")for(let c of F(s))!K.call(i,c)&&c!==t&&G(i,c,{get:()=>s[c],enumerable:!(d=T(s,c))||d.enumerable});return i};var q=i=>W(G({},"__esModule",{value:!0}),i);var X={};$(X,{AllowlistView:()=>N,AuthUserAdminAppView:()=>J,GroupMembersView:()=>P,GroupsView:()=>E,UserAdminShell:()=>z,UsersView:()=>M,createInMemoryUserAdminStore:()=>O,createUserAdminApp:()=>Q,defaultUserAdminLabels:()=>x,jaUserAdminLabels:()=>j,resolveUserAdminLabels:()=>R});module.exports=q(X);var x={title:"Users & Groups",heading:"\u{1F464} User administration",tabs:{users:"\u{1F464} Users",groups:"\u{1F465} Groups",groupMembers:"\u{1F517} Members",allowlist:"\u2709\uFE0F Allowlist"},usersView:{title:"Users",searchPlaceholder:"Search by name or email...",addUser:"\uFF0B Add user",editUser:"Edit user",id:"ID",displayName:"Name",email:"Email",status:"Status",active:"Active",inactive:"Inactive",actions:"Actions",edit:"Edit",activate:"Activate",deactivate:"Deactivate",empty:"No matching users",save:"Save",cancel:"Cancel"},groupsView:{title:"Groups",searchPlaceholder:"Search by group name or key...",addGroup:"\uFF0B Add group",editGroup:"Edit group",id:"ID",groupKey:"Group key",name:"Name",description:"Description",memberCount:"Members",status:"Status",actions:"Actions",edit:"Edit",delete:"Delete",confirmDelete:"Delete this group?",noDescription:"No description",groupKeyPlaceholder:"e.g. dev-team",namePlaceholder:"e.g. Development team",empty:"No groups registered",save:"Save",cancel:"Cancel"},groupMembersView:{selectGroup:"Select a group",selectPrompt:"Select a group to manage its members",actionAdd:"Add",actionRemove:"Remove"},allowlistView:{title:"Sign-in allowlist",addEntry:"\uFF0B Add pattern",pattern:"Pattern (e.g. @example.com or user@example.com)",type:"Type",emailType:"Exact email match",domainType:"Domain match",emailTypeShort:"Email",domainTypeShort:"Domain",description:"Description",actions:"Actions",readOnly:"Read-only",delete:"Delete",empty:"No allowlist entries registered",save:"Add",cancel:"Cancel"}},j={title:"\u30E6\u30FC\u30B6\u30FC\u30FB\u30B0\u30EB\u30FC\u30D7\u7BA1\u7406",heading:"\u{1F464} \u30E6\u30FC\u30B6\u30FC\u7BA1\u7406",tabs:{users:"\u{1F464} \u30E6\u30FC\u30B6\u30FC\u4E00\u89A7",groups:"\u{1F465} \u30E6\u30FC\u30B6\u30FC\u30B0\u30EB\u30FC\u30D7",groupMembers:"\u{1F517} \u30B0\u30EB\u30FC\u30D7\u30E1\u30F3\u30D0\u30FC",allowlist:"\u2709\uFE0F \u30A2\u30AF\u30BB\u30B9\u8A31\u53EF\u30EA\u30B9\u30C8"},usersView:{title:"\u30E6\u30FC\u30B6\u30FC\u7BA1\u7406",searchPlaceholder:"\u8868\u793A\u540D\u3084 Email \u3067\u691C\u7D22...",addUser:"\uFF0B \u30E6\u30FC\u30B6\u30FC\u8FFD\u52A0",editUser:"\u30E6\u30FC\u30B6\u30FC\u306E\u7DE8\u96C6",id:"ID",displayName:"\u8868\u793A\u540D",email:"\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9",status:"\u30B9\u30C6\u30FC\u30BF\u30B9",active:"\u6709\u52B9",inactive:"\u7121\u52B9",actions:"\u64CD\u4F5C",edit:"\u7DE8\u96C6",activate:"\u6709\u52B9\u5316",deactivate:"\u7121\u52B9\u5316",empty:"\u8A72\u5F53\u3059\u308B\u30E6\u30FC\u30B6\u30FC\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093",save:"\u4FDD\u5B58",cancel:"\u30AD\u30E3\u30F3\u30BB\u30EB"},groupsView:{title:"\u30E6\u30FC\u30B6\u30FC\u30B0\u30EB\u30FC\u30D7\u7BA1\u7406",searchPlaceholder:"\u30B0\u30EB\u30FC\u30D7\u540D\u3084\u30AD\u30FC\u3067\u691C\u7D22...",addGroup:"\uFF0B \u30B0\u30EB\u30FC\u30D7\u4F5C\u6210",editGroup:"\u30B0\u30EB\u30FC\u30D7\u306E\u7DE8\u96C6",id:"ID",groupKey:"\u30B0\u30EB\u30FC\u30D7\u30AD\u30FC",name:"\u30B0\u30EB\u30FC\u30D7\u540D",description:"\u8AAC\u660E",memberCount:"\u30E1\u30F3\u30D0\u30FC\u6570",status:"\u30B9\u30C6\u30FC\u30BF\u30B9",actions:"\u64CD\u4F5C",edit:"\u7DE8\u96C6",delete:"\u524A\u9664",confirmDelete:"\u3053\u306E\u30B0\u30EB\u30FC\u30D7\u3092\u524A\u9664\u3057\u3066\u3082\u3088\u308D\u3057\u3044\u3067\u3059\u304B\uFF1F",noDescription:"\u8AAC\u660E\u306A\u3057",groupKeyPlaceholder:"\u4F8B: dev-team",namePlaceholder:"\u4F8B: \u958B\u767A\u30C1\u30FC\u30E0",empty:"\u30B0\u30EB\u30FC\u30D7\u304C\u767B\u9332\u3055\u308C\u3066\u3044\u307E\u305B\u3093",save:"\u4FDD\u5B58",cancel:"\u30AD\u30E3\u30F3\u30BB\u30EB"},groupMembersView:{selectGroup:"\u30B0\u30EB\u30FC\u30D7\u9078\u629E",selectPrompt:"\u30B0\u30EB\u30FC\u30D7\u3092\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044",actionAdd:"\u8FFD\u52A0",actionRemove:"\u9664\u5916"},allowlistView:{title:"\u30A2\u30AF\u30BB\u30B9\u8A31\u53EF\u30EA\u30B9\u30C8 (Allowlist)",addEntry:"\uFF0B \u8A31\u53EF\u30D1\u30BF\u30FC\u30F3\u8FFD\u52A0",pattern:"\u30D1\u30BF\u30FC\u30F3 (\u4F8B: @example.com \u307E\u305F\u306F user@example.com)",type:"\u7A2E\u5225",emailType:"\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9\u5B8C\u5168\u4E00\u81F4",domainType:"\u30C9\u30E1\u30A4\u30F3\u4E00\u81F4",emailTypeShort:"Email \u5B8C\u5168\u4E00\u81F4",domainTypeShort:"\u30C9\u30E1\u30A4\u30F3\u4E00\u81F4",description:"\u8AAC\u660E / \u5099\u8003",actions:"\u64CD\u4F5C",readOnly:"\u5909\u66F4\u4E0D\u53EF",delete:"\u524A\u9664",empty:"\u30A2\u30ED\u30EF\u30EA\u30B9\u30C8\u30A8\u30F3\u30C8\u30EA\u304C\u767B\u9332\u3055\u308C\u3066\u3044\u307E\u305B\u3093",save:"\u767B\u9332",cancel:"\u30AD\u30E3\u30F3\u30BB\u30EB"}};function R(i){let s=x;return i?{title:i.title??s.title,heading:i.heading??s.heading,tabs:{...s.tabs,...i.tabs},usersView:{...s.usersView,...i.usersView},groupsView:{...s.groupsView,...i.groupsView},groupMembersView:{...s.groupMembersView,...i.groupMembersView},allowlistView:{...s.allowlistView,...i.allowlistView}}:s}function O(i){let s=i?.users??[{id:1,email:"admin@example.com",displayName:"\u30B7\u30B9\u30C6\u30E0\u7BA1\u7406\u8005",isActive:!0},{id:2,email:"user1@example.com",displayName:"\u958B\u767A \u592A\u90CE",isActive:!0},{id:3,email:"user2@example.com",displayName:"\u55B6\u696D \u82B1\u5B50",isActive:!0}],t=i?.groups??[{id:1,groupKey:"dev-team",name:"\u958B\u767A\u30C1\u30FC\u30E0",description:"\u30B7\u30B9\u30C6\u30E0\u958B\u767A\u62C5\u5F53\u30B0\u30EB\u30FC\u30D7",isActive:!0},{id:2,groupKey:"sales-dept",name:"\u55B6\u696D\u90E8",description:"\u55B6\u696D\u30BD\u30EA\u30E5\u30FC\u30B7\u30E7\u30F3\u62C5\u5F53",isActive:!0}],d=i?.groupMembers??[{id:1,groupId:1,userId:2},{id:2,groupId:2,userId:3}],c=i?.allowlist??[{id:1,pattern:"admin@example.com",type:"email",description:"\u521D\u671F\u7BA1\u7406\u8005"},{id:2,pattern:"@example.com",type:"domain",description:"\u793E\u5185\u30C9\u30E1\u30A4\u30F3"}];return{async listUsers(){return[...s]},async createUser(o){let r={id:Math.max(...s.map(a=>a.id),0)+1,email:o.email,displayName:o.displayName,isActive:!0};return s.push(r),r},async updateUser(o,r){let a=s.findIndex(n=>n.id===o);if(a===-1)throw new Error(`User not found: ${o}`);return s[a]={...s[a],displayName:r.displayName,email:r.email},s[a]},async toggleUserActive(o,r){let a=s.findIndex(n=>n.id===o);if(a===-1)throw new Error(`User not found: ${o}`);return s[a]={...s[a],isActive:r},s[a]},async listGroups(){return[...t]},async createGroup(o){let r={id:Math.max(...t.map(a=>a.id),0)+1,groupKey:o.groupKey,name:o.name,description:o.description,isActive:!0};return t.push(r),r},async updateGroup(o,r){let a=t.findIndex(n=>n.id===o);if(a===-1)throw new Error(`Group not found: ${o}`);return t[a]={...t[a],name:r.name,description:r.description},t[a]},async deleteGroup(o){t=t.filter(r=>r.id!==o),d=d.filter(r=>r.groupId!==o)},async listGroupMembers(){return[...d]},async addGroupMember(o,r){let a=d.find(l=>l.groupId===o&&l.userId===r);if(a)return a;let n={id:Math.max(...d.map(l=>l.id),0)+1,groupId:o,userId:r};return d.push(n),n},async removeGroupMember(o,r){d=d.filter(a=>!(a.groupId===o&&a.userId===r))},async listAllowlist(){return[...c]},async addAllowlistEntry(o){let r={id:Math.max(...c.map(a=>a.id),0)+1,pattern:o.pattern,type:o.type,description:o.description};return c.push(r),r},async removeAllowlistEntry(o){c=c.filter(r=>r.id!==o)}}}var _=new Map([["createUser","create"],["updateUser","update"],["toggleUserActive","update"],["createGroup","create"],["updateGroup","update"],["deleteGroup","delete"],["addGroupMember","create"],["removeGroupMember","delete"],["addAllowlistEntry","create"],["removeAllowlistEntry","delete"]]);function h(i,s){let t=i.get(s),d=Number(t);if(t===null||String(t).trim()===""||!Number.isInteger(d)||d<=0)throw new Error(`Invalid or missing "${s}"`);return d}function w(i,s){let t=String(i.get(s)??"").trim();if(t==="")throw new Error(`Invalid or missing "${s}"`);return t}function I(i,s){let t=String(i.get(s)??"").trim();return t===""?void 0:t}function Q(i){let s=R(i.labels);async function t({request:o}){await i.guards.requireAccess(o,{action:"read",intent:"loader"});let a=new URL(o.url).pathname.split("/").filter(Boolean),n=a[a.length-1]??"users",[l,y,u,v]=await Promise.all([i.store.listUsers(),i.store.listGroups(),i.store.listGroupMembers(),i.store.listAllowlist()]);return{segment:["groups","group_members","allowlist"].includes(n)?n:"users",users:l,groups:y,groupMembers:u,allowlist:v,labels:s}}async function d({request:o}){let r=await o.formData(),a=String(r.get("intent")??""),n=_.get(a);if(!n)return{ok:!1,error:`Unknown intent: ${a}`};await i.guards.requireAccess(o,{action:n,intent:a});try{return await c(a,r)}catch(l){if(l instanceof Response)throw l;return{ok:!1,error:l instanceof Error?l.message:String(l)}}}async function c(o,r){if(o==="createUser")return await i.store.createUser({displayName:w(r,"displayName"),email:w(r,"email")}),{ok:!0};if(o==="updateUser")return await i.store.updateUser(h(r,"userId"),{displayName:w(r,"displayName"),email:w(r,"email")}),{ok:!0};if(o==="toggleUserActive"){let a=String(r.get("isActive")??"");if(a!=="true"&&a!=="false")throw new Error('Invalid or missing "isActive"');return await i.store.toggleUserActive(h(r,"userId"),a==="true"),{ok:!0}}if(o==="createGroup")return await i.store.createGroup({groupKey:w(r,"groupKey"),name:w(r,"name"),description:I(r,"description")}),{ok:!0};if(o==="updateGroup")return await i.store.updateGroup(h(r,"groupId"),{name:w(r,"name"),description:I(r,"description")}),{ok:!0};if(o==="deleteGroup")return await i.store.deleteGroup(h(r,"groupId")),{ok:!0};if(o==="addGroupMember")return await i.store.addGroupMember(h(r,"groupId"),h(r,"userId")),{ok:!0};if(o==="removeGroupMember")return await i.store.removeGroupMember(h(r,"groupId"),h(r,"userId")),{ok:!0};if(o==="addAllowlistEntry"){let a=r.get("type")==="domain"?"domain":"email";return await i.store.addAllowlistEntry({pattern:w(r,"pattern"),type:a,description:I(r,"description")}),{ok:!0}}return o==="removeAllowlistEntry"?(await i.store.removeAllowlistEntry(h(r,"entryId")),{ok:!0}):{ok:!1,error:`Unknown intent: ${o}`}}return{loader:t,action:d}}var C=require("react-router");var f=require("react/jsx-runtime");function z({children:i,renderHeader:s}){let t=(0,C.useLoaderData)(),d=t?.segment??"users",c=t?.labels??x,o=[{key:"users",label:c.tabs.users,href:"/users"},{key:"groups",label:c.tabs.groups,href:"/users/groups"},{key:"group_members",label:c.tabs.groupMembers,href:"/users/group_members"},{key:"allowlist",label:c.tabs.allowlist,href:"/users/allowlist"}],r=(0,f.jsx)("div",{style:{display:"flex",alignItems:"center",gap:"0.5rem"},"data-testid":"user-admin-header-annotation",children:(0,f.jsx)("span",{style:{fontSize:"0.75rem",backgroundColor:"#e0f2fe",color:"#0369a1",padding:"2px 8px",borderRadius:"12px",fontWeight:600},children:c.heading})});return(0,f.jsxs)("div",{"data-testid":"user-admin-shell",style:{width:"100%",minHeight:"100vh",backgroundColor:"#f8fafc",padding:"1.5rem",boxSizing:"border-box"},children:[s?s({title:c.title,annotation:r}):(0,f.jsxs)("div",{style:{marginBottom:"1.5rem",display:"flex",justifyContent:"space-between",alignItems:"center"},children:[(0,f.jsx)("h1",{style:{margin:0,fontSize:"1.5rem",fontWeight:700,color:"#0f172a"},children:c.title}),r]}),(0,f.jsx)("div",{style:{display:"flex",gap:"0.5rem",marginBottom:"1.2rem",borderBottom:"2px solid #e2e8f0",paddingBottom:"0.5rem"},children:o.map(a=>{let n=d===a.key;return(0,f.jsx)(C.Link,{to:a.href,"data-testid":`user-admin-tab-${a.key}`,style:{padding:"0.5rem 1rem",borderRadius:"6px 6px 0 0",fontSize:"0.88rem",fontWeight:n?700:500,color:n?"#0284c7":"#64748b",backgroundColor:n?"#ffffff":"transparent",textDecoration:"none",borderBottom:n?"3px solid #0284c7":"3px solid transparent",transition:"all 0.15s ease"},children:a.label},a.key)})}),(0,f.jsx)("main",{children:i})]})}var g=require("react"),b=require("react-router");var e=require("react/jsx-runtime");function U({fetcher:i}){let s=i.data;return s?.ok!==!1||!s.error?null:(0,e.jsx)("div",{"data-testid":"user-admin-action-error",role:"alert",style:{padding:"0.7rem 1rem",borderRadius:"6px",border:"1px solid #fecaca",backgroundColor:"#fef2f2",color:"#b91c1c",fontSize:"0.85rem"},children:s.error})}function M(){let i=(0,b.useLoaderData)(),s=(0,b.useFetcher)(),t=i.labels??x,[d,c]=(0,g.useState)(""),[o,r]=(0,g.useState)(null),[a,n]=(0,g.useState)(!1),[l,y]=(0,g.useState)(""),[u,v]=(0,g.useState)(""),A=i.users.filter(p=>p.displayName.toLowerCase().includes(d.toLowerCase())||p.email.toLowerCase().includes(d.toLowerCase())),S=p=>{s.submit({intent:"toggleUserActive",userId:String(p.id),isActive:String(!p.isActive)},{method:"post"})},k=p=>{p.preventDefault(),l&&u&&(s.submit({intent:"createUser",displayName:l,email:u},{method:"post"}),y(""),v(""),n(!1))},V=p=>{p.preventDefault(),o&&(s.submit({intent:"updateUser",userId:String(o.id),displayName:o.displayName,email:o.email},{method:"post"}),r(null))};return(0,e.jsxs)("section",{"data-testid":"users-view-section",style:{display:"flex",flexDirection:"column",gap:"1rem"},children:[(0,e.jsx)(U,{fetcher:s}),(0,e.jsxs)("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",backgroundColor:"#ffffff",padding:"1rem",borderRadius:"8px",border:"1px solid #e2e8f0"},children:[(0,e.jsx)("input",{type:"text",placeholder:t.usersView.searchPlaceholder,value:d,onChange:p=>c(p.target.value),"data-testid":"users-search-input",style:{padding:"6px 12px",borderRadius:"6px",border:"1px solid #cbd5e1",fontSize:"0.85rem",width:"260px"}}),(0,e.jsx)("button",{type:"button",onClick:()=>n(!0),"data-testid":"users-add-button",style:{padding:"6px 14px",borderRadius:"6px",backgroundColor:"#0284c7",color:"#ffffff",border:"none",fontSize:"0.85rem",fontWeight:600,cursor:"pointer"},children:t.usersView.addUser})]}),(0,e.jsx)("div",{style:{backgroundColor:"#ffffff",borderRadius:"8px",border:"1px solid #e2e8f0",overflow:"hidden"},children:(0,e.jsxs)("table",{style:{width:"100%",borderCollapse:"collapse",fontSize:"0.85rem",textAlign:"left"},children:[(0,e.jsx)("thead",{children:(0,e.jsxs)("tr",{style:{backgroundColor:"#f8fafc",borderBottom:"1px solid #e2e8f0",color:"#475569"},children:[(0,e.jsx)("th",{style:{padding:"10px 14px"},children:t.usersView.id}),(0,e.jsx)("th",{style:{padding:"10px 14px"},children:t.usersView.displayName}),(0,e.jsx)("th",{style:{padding:"10px 14px"},children:t.usersView.email}),(0,e.jsx)("th",{style:{padding:"10px 14px"},children:t.usersView.status}),(0,e.jsx)("th",{style:{padding:"10px 14px",textAlign:"right"},children:t.usersView.actions})]})}),(0,e.jsxs)("tbody",{children:[A.map(p=>(0,e.jsxs)("tr",{style:{borderBottom:"1px solid #f1f5f9"},"data-testid":`user-row-${p.id}`,children:[(0,e.jsxs)("td",{style:{padding:"10px 14px",color:"#64748b"},children:["#",p.id]}),(0,e.jsx)("td",{style:{padding:"10px 14px",fontWeight:600,color:"#0f172a"},children:p.displayName}),(0,e.jsx)("td",{style:{padding:"10px 14px",color:"#475569"},children:p.email}),(0,e.jsx)("td",{style:{padding:"10px 14px"},children:(0,e.jsx)("span",{style:{fontSize:"0.75rem",padding:"2px 8px",borderRadius:"10px",backgroundColor:p.isActive?"#dcfce7":"#fee2e2",color:p.isActive?"#15803d":"#b91c1c",fontWeight:600},children:p.isActive?t.usersView.active:t.usersView.inactive})}),(0,e.jsxs)("td",{style:{padding:"10px 14px",textAlign:"right"},children:[(0,e.jsx)("button",{type:"button",onClick:()=>r(p),"data-testid":`edit-user-btn-${p.id}`,style:{padding:"3px 8px",borderRadius:"4px",border:"1px solid #cbd5e1",backgroundColor:"#ffffff",fontSize:"0.78rem",cursor:"pointer",marginRight:"6px"},children:t.usersView.edit}),(0,e.jsx)("button",{type:"button",onClick:()=>S(p),"data-testid":`toggle-user-btn-${p.id}`,style:{padding:"3px 8px",borderRadius:"4px",border:"1px solid #cbd5e1",backgroundColor:"#ffffff",fontSize:"0.78rem",cursor:"pointer",color:p.isActive?"#b91c1c":"#15803d"},children:p.isActive?t.usersView.deactivate:t.usersView.activate})]})]},p.id)),A.length===0&&(0,e.jsx)("tr",{children:(0,e.jsx)("td",{colSpan:5,style:{padding:"2rem",textAlign:"center",color:"#94a3b8"},children:t.usersView.empty})})]})]})}),a&&(0,e.jsx)("div",{style:{position:"fixed",inset:0,backgroundColor:"rgba(0,0,0,0.4)",display:"flex",justifyContent:"center",alignItems:"center",zIndex:100},"data-testid":"user-create-modal",children:(0,e.jsxs)("form",{onSubmit:k,style:{backgroundColor:"#ffffff",padding:"1.5rem",borderRadius:"8px",width:"360px",boxShadow:"0 10px 25px rgba(0,0,0,0.15)"},children:[(0,e.jsx)("h3",{style:{margin:"0 0 1rem 0",fontSize:"1.1rem"},children:t.usersView.addUser}),(0,e.jsxs)("div",{style:{marginBottom:"1rem"},children:[(0,e.jsx)("label",{htmlFor:"create-user-display-name-input",style:{display:"block",fontSize:"0.8rem",color:"#475569",marginBottom:"4px"},children:t.usersView.displayName}),(0,e.jsx)("input",{id:"create-user-display-name-input",type:"text",value:l,onChange:p=>y(p.target.value),required:!0,"data-testid":"create-user-display-name",style:{width:"100%",padding:"6px",borderRadius:"4px",border:"1px solid #cbd5e1",boxSizing:"border-box"}})]}),(0,e.jsxs)("div",{style:{marginBottom:"1.2rem"},children:[(0,e.jsx)("label",{htmlFor:"create-user-email-input",style:{display:"block",fontSize:"0.8rem",color:"#475569",marginBottom:"4px"},children:t.usersView.email}),(0,e.jsx)("input",{id:"create-user-email-input",type:"email",value:u,onChange:p=>v(p.target.value),required:!0,"data-testid":"create-user-email",style:{width:"100%",padding:"6px",borderRadius:"4px",border:"1px solid #cbd5e1",boxSizing:"border-box"}})]}),(0,e.jsxs)("div",{style:{display:"flex",justifyContent:"flex-end",gap:"0.5rem"},children:[(0,e.jsx)("button",{type:"button",onClick:()=>n(!1),style:{padding:"6px 12px",borderRadius:"4px",border:"1px solid #cbd5e1",backgroundColor:"#ffffff",cursor:"pointer"},children:"\u30AD\u30E3\u30F3\u30BB\u30EB"}),(0,e.jsx)("button",{type:"submit","data-testid":"submit-create-user",style:{padding:"6px 12px",borderRadius:"4px",backgroundColor:"#0284c7",color:"#ffffff",border:"none",cursor:"pointer"},children:"\u4F5C\u6210"})]})]})}),o&&(0,e.jsx)("div",{style:{position:"fixed",inset:0,backgroundColor:"rgba(0,0,0,0.4)",display:"flex",justifyContent:"center",alignItems:"center",zIndex:100},"data-testid":"user-edit-modal",children:(0,e.jsxs)("form",{onSubmit:V,style:{backgroundColor:"#ffffff",padding:"1.5rem",borderRadius:"8px",width:"360px",boxShadow:"0 10px 25px rgba(0,0,0,0.15)"},children:[(0,e.jsx)("h3",{style:{margin:"0 0 1rem 0",fontSize:"1.1rem"},children:t.usersView.editUser}),(0,e.jsxs)("div",{style:{marginBottom:"1rem"},children:[(0,e.jsx)("label",{htmlFor:"edit-user-display-name-input",style:{display:"block",fontSize:"0.8rem",color:"#475569",marginBottom:"4px"},children:t.usersView.displayName}),(0,e.jsx)("input",{id:"edit-user-display-name-input",type:"text",value:o.displayName,onChange:p=>r({...o,displayName:p.target.value}),required:!0,"data-testid":"edit-user-display-name",style:{width:"100%",padding:"6px",borderRadius:"4px",border:"1px solid #cbd5e1",boxSizing:"border-box"}})]}),(0,e.jsxs)("div",{style:{marginBottom:"1.2rem"},children:[(0,e.jsx)("label",{htmlFor:"edit-user-email-input",style:{display:"block",fontSize:"0.8rem",color:"#475569",marginBottom:"4px"},children:t.usersView.email}),(0,e.jsx)("input",{id:"edit-user-email-input",type:"email",value:o.email,onChange:p=>r({...o,email:p.target.value}),required:!0,"data-testid":"edit-user-email",style:{width:"100%",padding:"6px",borderRadius:"4px",border:"1px solid #cbd5e1",boxSizing:"border-box"}})]}),(0,e.jsxs)("div",{style:{display:"flex",justifyContent:"flex-end",gap:"0.5rem"},children:[(0,e.jsx)("button",{type:"button",onClick:()=>r(null),style:{padding:"6px 12px",borderRadius:"4px",border:"1px solid #cbd5e1",backgroundColor:"#ffffff",cursor:"pointer"},children:t.usersView.cancel}),(0,e.jsx)("button",{type:"submit","data-testid":"submit-edit-user",style:{padding:"6px 12px",borderRadius:"4px",backgroundColor:"#0284c7",color:"#ffffff",border:"none",cursor:"pointer"},children:t.usersView.save})]})]})})]})}function E(){let i=(0,b.useLoaderData)(),s=(0,b.useFetcher)(),t=i.labels??x,[d,c]=(0,g.useState)(""),[o,r]=(0,g.useState)(!1),[a,n]=(0,g.useState)(null),[l,y]=(0,g.useState)(""),[u,v]=(0,g.useState)(""),[A,S]=(0,g.useState)(""),k=i.groups.filter(m=>m.name.toLowerCase().includes(d.toLowerCase())||m.groupKey.toLowerCase().includes(d.toLowerCase())),V=m=>{m.preventDefault(),l&&u&&(s.submit({intent:"createGroup",groupKey:l,name:u,description:A},{method:"post"}),y(""),v(""),S(""),r(!1))},p=m=>{m.preventDefault(),a&&(s.submit({intent:"updateGroup",groupId:String(a.id),name:a.name,description:a.description??""},{method:"post"}),n(null))},L=m=>{window.confirm(t.groupsView.confirmDelete)&&s.submit({intent:"deleteGroup",groupId:String(m)},{method:"post"})};return(0,e.jsxs)("section",{"data-testid":"groups-view-section",style:{display:"flex",flexDirection:"column",gap:"1rem"},children:[(0,e.jsx)(U,{fetcher:s}),(0,e.jsxs)("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",backgroundColor:"#ffffff",padding:"1rem",borderRadius:"8px",border:"1px solid #e2e8f0"},children:[(0,e.jsx)("input",{type:"text",placeholder:t.groupsView.searchPlaceholder,value:d,onChange:m=>c(m.target.value),"data-testid":"groups-search-input",style:{padding:"6px 12px",borderRadius:"6px",border:"1px solid #cbd5e1",fontSize:"0.85rem",width:"260px"}}),(0,e.jsx)("button",{type:"button",onClick:()=>r(!0),"data-testid":"groups-add-button",style:{padding:"6px 14px",borderRadius:"6px",backgroundColor:"#4338ca",color:"#ffffff",border:"none",fontSize:"0.85rem",fontWeight:600,cursor:"pointer"},children:t.groupsView.addGroup})]}),(0,e.jsx)("div",{style:{display:"grid",gridTemplateColumns:"repeat(auto-fill, minmax(280px, 1fr))",gap:"1rem"},children:k.map(m=>{let B=i.groupMembers.filter(D=>D.groupId===m.id).length;return(0,e.jsxs)("div",{style:{backgroundColor:"#ffffff",borderRadius:"8px",border:"1px solid #e2e8f0",padding:"1rem",display:"flex",flexDirection:"column",justifyContent:"space-between"},"data-testid":`group-card-${m.id}`,children:[(0,e.jsxs)("div",{children:[(0,e.jsxs)("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:"0.5rem"},children:[(0,e.jsx)("h4",{style:{margin:0,fontSize:"1rem",color:"#0f172a"},children:m.name}),(0,e.jsx)("span",{style:{fontSize:"0.72rem",backgroundColor:"#e0e7ff",color:"#4338ca",padding:"2px 6px",borderRadius:"4px",fontFamily:"monospace"},children:m.groupKey})]}),(0,e.jsx)("p",{style:{margin:"0 0 0.8rem 0",fontSize:"0.82rem",color:"#64748b",minHeight:"2.4em"},children:m.description||t.groupsView.noDescription})]}),(0,e.jsxs)("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",borderTop:"1px solid #f1f5f9",paddingTop:"0.6rem"},children:[(0,e.jsxs)("span",{style:{fontSize:"0.78rem",color:"#475569"},children:["\u{1F465} \u30E1\u30F3\u30D0\u30FC: ",(0,e.jsx)("strong",{children:B})," \u4EBA"]}),(0,e.jsxs)("div",{children:[(0,e.jsx)("button",{type:"button",onClick:()=>n(m),"data-testid":`edit-group-btn-${m.id}`,style:{padding:"3px 8px",borderRadius:"4px",border:"1px solid #cbd5e1",backgroundColor:"#ffffff",fontSize:"0.75rem",cursor:"pointer",marginRight:"4px"},children:t.usersView.edit}),(0,e.jsx)("button",{type:"button",onClick:()=>L(m.id),"data-testid":`delete-group-btn-${m.id}`,style:{padding:"3px 8px",borderRadius:"4px",border:"1px solid #fee2e2",backgroundColor:"#fff5f5",color:"#b91c1c",fontSize:"0.75rem",cursor:"pointer"},children:"\u524A\u9664"})]})]})]},m.id)})}),o&&(0,e.jsx)("div",{style:{position:"fixed",inset:0,backgroundColor:"rgba(0,0,0,0.4)",display:"flex",justifyContent:"center",alignItems:"center",zIndex:100},"data-testid":"group-create-modal",children:(0,e.jsxs)("form",{onSubmit:V,style:{backgroundColor:"#ffffff",padding:"1.5rem",borderRadius:"8px",width:"360px",boxShadow:"0 10px 25px rgba(0,0,0,0.15)"},children:[(0,e.jsx)("h3",{style:{margin:"0 0 1rem 0",fontSize:"1.1rem"},children:t.groupsView.addGroup}),(0,e.jsxs)("div",{style:{marginBottom:"1rem"},children:[(0,e.jsx)("label",{htmlFor:"create-group-key-input",style:{display:"block",fontSize:"0.8rem",color:"#475569",marginBottom:"4px"},children:t.groupsView.groupKey}),(0,e.jsx)("input",{id:"create-group-key-input",type:"text",value:l,onChange:m=>y(m.target.value),placeholder:t.groupsView.groupKeyPlaceholder,required:!0,"data-testid":"create-group-key",style:{width:"100%",padding:"6px",borderRadius:"4px",border:"1px solid #cbd5e1",boxSizing:"border-box"}})]}),(0,e.jsxs)("div",{style:{marginBottom:"1rem"},children:[(0,e.jsx)("label",{htmlFor:"create-group-name-input",style:{display:"block",fontSize:"0.8rem",color:"#475569",marginBottom:"4px"},children:t.groupsView.name}),(0,e.jsx)("input",{id:"create-group-name-input",type:"text",value:u,onChange:m=>v(m.target.value),placeholder:t.groupsView.namePlaceholder,required:!0,"data-testid":"create-group-name",style:{width:"100%",padding:"6px",borderRadius:"4px",border:"1px solid #cbd5e1",boxSizing:"border-box"}})]}),(0,e.jsxs)("div",{style:{marginBottom:"1.2rem"},children:[(0,e.jsx)("label",{htmlFor:"create-group-desc-input",style:{display:"block",fontSize:"0.8rem",color:"#475569",marginBottom:"4px"},children:t.groupsView.description}),(0,e.jsx)("textarea",{id:"create-group-desc-input",value:A,onChange:m=>S(m.target.value),"data-testid":"create-group-description",style:{width:"100%",padding:"6px",borderRadius:"4px",border:"1px solid #cbd5e1",boxSizing:"border-box",height:"60px"}})]}),(0,e.jsxs)("div",{style:{display:"flex",justifyContent:"flex-end",gap:"0.5rem"},children:[(0,e.jsx)("button",{type:"button",onClick:()=>r(!1),style:{padding:"6px 12px",borderRadius:"4px",border:"1px solid #cbd5e1",backgroundColor:"#ffffff",cursor:"pointer"},children:"\u30AD\u30E3\u30F3\u30BB\u30EB"}),(0,e.jsx)("button",{type:"submit","data-testid":"submit-create-group",style:{padding:"6px 12px",borderRadius:"4px",backgroundColor:"#4338ca",color:"#ffffff",border:"none",cursor:"pointer"},children:"\u4F5C\u6210"})]})]})}),a&&(0,e.jsx)("div",{style:{position:"fixed",inset:0,backgroundColor:"rgba(0,0,0,0.4)",display:"flex",justifyContent:"center",alignItems:"center",zIndex:100},"data-testid":"group-edit-modal",children:(0,e.jsxs)("form",{onSubmit:p,style:{backgroundColor:"#ffffff",padding:"1.5rem",borderRadius:"8px",width:"360px",boxShadow:"0 10px 25px rgba(0,0,0,0.15)"},children:[(0,e.jsx)("h3",{style:{margin:"0 0 1rem 0",fontSize:"1.1rem"},children:t.groupsView.editGroup}),(0,e.jsxs)("div",{style:{marginBottom:"1rem"},children:[(0,e.jsx)("label",{htmlFor:"edit-group-name-input",style:{display:"block",fontSize:"0.8rem",color:"#475569",marginBottom:"4px"},children:t.groupsView.name}),(0,e.jsx)("input",{id:"edit-group-name-input",type:"text",value:a.name,onChange:m=>n({...a,name:m.target.value}),required:!0,"data-testid":"edit-group-name",style:{width:"100%",padding:"6px",borderRadius:"4px",border:"1px solid #cbd5e1",boxSizing:"border-box"}})]}),(0,e.jsxs)("div",{style:{marginBottom:"1.2rem"},children:[(0,e.jsx)("label",{htmlFor:"edit-group-desc-input",style:{display:"block",fontSize:"0.8rem",color:"#475569",marginBottom:"4px"},children:t.groupsView.description}),(0,e.jsx)("textarea",{id:"edit-group-desc-input",value:a.description??"",onChange:m=>n({...a,description:m.target.value}),"data-testid":"edit-group-description",style:{width:"100%",padding:"6px",borderRadius:"4px",border:"1px solid #cbd5e1",boxSizing:"border-box",height:"60px"}})]}),(0,e.jsxs)("div",{style:{display:"flex",justifyContent:"flex-end",gap:"0.5rem"},children:[(0,e.jsx)("button",{type:"button",onClick:()=>n(null),style:{padding:"6px 12px",borderRadius:"4px",border:"1px solid #cbd5e1",backgroundColor:"#ffffff",cursor:"pointer"},children:t.groupsView.cancel}),(0,e.jsx)("button",{type:"submit","data-testid":"submit-edit-group",style:{padding:"6px 12px",borderRadius:"4px",backgroundColor:"#4338ca",color:"#ffffff",border:"none",cursor:"pointer"},children:t.groupsView.save})]})]})})]})}function P(){let i=(0,b.useLoaderData)(),s=(0,b.useFetcher)(),t=i.labels??x,[d,c]=(0,g.useState)(i.groups[0]?.id??0),o=i.groups.find(n=>n.id===d),r=new Set(i.groupMembers.filter(n=>n.groupId===d).map(n=>n.userId)),a=(n,l)=>{l?s.submit({intent:"removeGroupMember",groupId:String(d),userId:String(n)},{method:"post"}):s.submit({intent:"addGroupMember",groupId:String(d),userId:String(n)},{method:"post"})};return(0,e.jsxs)("section",{"data-testid":"group-members-view-section",style:{display:"grid",gridTemplateColumns:"240px 1fr",gap:"1.2rem"},children:[(0,e.jsx)(U,{fetcher:s}),(0,e.jsxs)("div",{style:{backgroundColor:"#ffffff",padding:"1rem",borderRadius:"8px",border:"1px solid #e2e8f0"},children:[(0,e.jsx)("h4",{style:{margin:"0 0 0.8rem 0",fontSize:"0.9rem",color:"#475569"},children:t.groupMembersView.selectGroup}),(0,e.jsx)("div",{style:{display:"flex",flexDirection:"column",gap:"0.4rem"},children:i.groups.map(n=>{let l=n.id===d;return(0,e.jsx)("button",{type:"button",onClick:()=>c(n.id),"data-testid":`select-group-btn-${n.id}`,style:{textAlign:"left",padding:"8px 10px",borderRadius:"6px",border:l?"1px solid #6366f1":"1px solid #e2e8f0",backgroundColor:l?"#e0e7ff":"#ffffff",color:l?"#3730a3":"#0f172a",cursor:"pointer",fontWeight:l?600:400,fontSize:"0.85rem"},children:n.name},n.id)})})]}),(0,e.jsx)("div",{style:{backgroundColor:"#ffffff",padding:"1.2rem",borderRadius:"8px",border:"1px solid #e2e8f0"},children:o?(0,e.jsxs)(e.Fragment,{children:[(0,e.jsxs)("div",{style:{marginBottom:"1rem",borderBottom:"1px solid #e2e8f0",paddingBottom:"0.8rem"},children:[(0,e.jsxs)("h3",{style:{margin:0,fontSize:"1.1rem",color:"#0f172a"},children:[o.name," \u306E\u6240\u5C5E\u30E1\u30F3\u30D0\u30FC"]}),(0,e.jsxs)("span",{style:{fontSize:"0.8rem",color:"#64748b"},children:["\u30B0\u30EB\u30FC\u30D7\u30AD\u30FC: ",o.groupKey]})]}),(0,e.jsx)("div",{style:{display:"flex",flexDirection:"column",gap:"0.5rem"},children:i.users.map(n=>{let l=r.has(n.id);return(0,e.jsxs)("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",padding:"8px 12px",borderRadius:"6px",border:"1px solid #f1f5f9",backgroundColor:l?"#f0fdf4":"#ffffff"},"data-testid":`member-row-${n.id}`,children:[(0,e.jsxs)("div",{children:[(0,e.jsx)("span",{style:{fontWeight:600,fontSize:"0.88rem",color:"#0f172a",marginRight:"8px"},children:n.displayName}),(0,e.jsxs)("span",{style:{fontSize:"0.78rem",color:"#64748b"},children:["(",n.email,")"]})]}),(0,e.jsx)("button",{type:"button",onClick:()=>a(n.id,l),"data-testid":`toggle-member-btn-${n.id}`,style:{padding:"4px 12px",borderRadius:"4px",border:l?"1px solid #b91c1c":"1px solid #0284c7",backgroundColor:l?"#ffffff":"#0284c7",color:l?"#b91c1c":"#ffffff",fontSize:"0.78rem",fontWeight:600,cursor:"pointer"},children:l?t.groupMembersView.actionRemove:t.groupMembersView.actionAdd})]},n.id)})})]}):(0,e.jsx)("div",{style:{color:"#94a3b8",textAlign:"center",padding:"2rem"},children:t.groupMembersView.selectPrompt})})]})}function N(){let i=(0,b.useLoaderData)(),s=(0,b.useFetcher)(),t=i.labels??x,[d,c]=(0,g.useState)(""),[o,r]=(0,g.useState)("email"),[a,n]=(0,g.useState)(""),l=u=>{u.preventDefault(),d&&(s.submit({intent:"addAllowlistEntry",pattern:d,type:o,description:a},{method:"post"}),c(""),n(""))},y=u=>{s.submit({intent:"removeAllowlistEntry",entryId:String(u)},{method:"post"})};return(0,e.jsxs)("section",{"data-testid":"allowlist-view-section",style:{display:"flex",flexDirection:"column",gap:"1.2rem"},children:[(0,e.jsx)(U,{fetcher:s}),(0,e.jsxs)("form",{onSubmit:l,style:{backgroundColor:"#ffffff",padding:"1.2rem",borderRadius:"8px",border:"1px solid #e2e8f0",display:"flex",flexWrap:"wrap",gap:"0.8rem",alignItems:"flex-end"},children:[(0,e.jsxs)("div",{style:{flex:2,minWidth:"220px"},children:[(0,e.jsx)("label",{htmlFor:"allowlist-pattern-input-field",style:{display:"block",fontSize:"0.78rem",color:"#475569",marginBottom:"4px"},children:t.allowlistView.pattern}),(0,e.jsx)("input",{id:"allowlist-pattern-input-field",type:"text",value:d,onChange:u=>c(u.target.value),required:!0,"data-testid":"allowlist-pattern-input",style:{width:"100%",padding:"6px 10px",borderRadius:"6px",border:"1px solid #cbd5e1",fontSize:"0.85rem",boxSizing:"border-box"}})]}),(0,e.jsxs)("div",{style:{flex:1,minWidth:"140px"},children:[(0,e.jsx)("label",{htmlFor:"allowlist-type-select-field",style:{display:"block",fontSize:"0.78rem",color:"#475569",marginBottom:"4px"},children:t.allowlistView.type}),(0,e.jsxs)("select",{id:"allowlist-type-select-field",value:o,onChange:u=>r(u.target.value),"data-testid":"allowlist-type-select",style:{width:"100%",padding:"6px 10px",borderRadius:"6px",border:"1px solid #cbd5e1",fontSize:"0.85rem",boxSizing:"border-box"},children:[(0,e.jsx)("option",{value:"email",children:t.allowlistView.emailType}),(0,e.jsx)("option",{value:"domain",children:t.allowlistView.domainType})]})]}),(0,e.jsxs)("div",{style:{flex:2,minWidth:"200px"},children:[(0,e.jsx)("label",{htmlFor:"allowlist-desc-input-field",style:{display:"block",fontSize:"0.78rem",color:"#475569",marginBottom:"4px"},children:t.allowlistView.description}),(0,e.jsx)("input",{id:"allowlist-desc-input-field",type:"text",value:a,onChange:u=>n(u.target.value),"data-testid":"allowlist-desc-input",style:{width:"100%",padding:"6px 10px",borderRadius:"6px",border:"1px solid #cbd5e1",fontSize:"0.85rem",boxSizing:"border-box"}})]}),(0,e.jsx)("button",{type:"submit","data-testid":"submit-allowlist-add",style:{padding:"7px 16px",borderRadius:"6px",backgroundColor:"#047857",color:"#ffffff",border:"none",fontSize:"0.85rem",fontWeight:600,cursor:"pointer"},children:t.allowlistView.addEntry})]}),(0,e.jsx)("div",{style:{backgroundColor:"#ffffff",borderRadius:"8px",border:"1px solid #e2e8f0",overflow:"hidden"},children:(0,e.jsxs)("table",{style:{width:"100%",borderCollapse:"collapse",fontSize:"0.85rem",textAlign:"left"},children:[(0,e.jsx)("thead",{children:(0,e.jsxs)("tr",{style:{backgroundColor:"#f8fafc",borderBottom:"1px solid #e2e8f0",color:"#475569"},children:[(0,e.jsx)("th",{style:{padding:"10px 14px"},children:"ID"}),(0,e.jsx)("th",{style:{padding:"10px 14px"},children:t.allowlistView.pattern}),(0,e.jsx)("th",{style:{padding:"10px 14px"},children:t.allowlistView.type}),(0,e.jsx)("th",{style:{padding:"10px 14px"},children:t.allowlistView.description}),(0,e.jsx)("th",{style:{padding:"10px 14px",textAlign:"right"},children:t.allowlistView.actions})]})}),(0,e.jsxs)("tbody",{children:[i.allowlist.map(u=>(0,e.jsxs)("tr",{style:{borderBottom:"1px solid #f1f5f9"},"data-testid":`allowlist-row-${u.id}`,children:[(0,e.jsxs)("td",{style:{padding:"10px 14px",color:"#64748b"},children:["#",u.id]}),(0,e.jsx)("td",{style:{padding:"10px 14px",fontWeight:600,color:"#0f172a",fontFamily:"monospace"},children:u.pattern}),(0,e.jsx)("td",{style:{padding:"10px 14px"},children:(0,e.jsx)("span",{style:{fontSize:"0.75rem",padding:"2px 8px",borderRadius:"10px",backgroundColor:u.type==="email"?"#e0f2fe":"#fef3c7",color:u.type==="email"?"#0369a1":"#b45309",fontWeight:600},children:u.type==="email"?t.allowlistView.emailTypeShort:t.allowlistView.domainTypeShort})}),(0,e.jsx)("td",{style:{padding:"10px 14px",color:"#475569"},children:u.description||"-"}),(0,e.jsx)("td",{style:{padding:"10px 14px",textAlign:"right"},children:u.readOnly?(0,e.jsx)("span",{"data-testid":`readonly-allowlist-${u.id}`,style:{fontSize:"0.75rem",color:"#94a3b8"},children:t.allowlistView.readOnly}):(0,e.jsx)("button",{type:"button",onClick:()=>y(u.id),"data-testid":`remove-allowlist-btn-${u.id}`,style:{padding:"3px 8px",borderRadius:"4px",border:"1px solid #fee2e2",backgroundColor:"#fff5f5",color:"#b91c1c",fontSize:"0.78rem",cursor:"pointer"},children:"\u524A\u9664"})})]},u.id)),i.allowlist.length===0&&(0,e.jsx)("tr",{children:(0,e.jsx)("td",{colSpan:5,style:{padding:"2rem",textAlign:"center",color:"#94a3b8"},children:t.allowlistView.empty})})]})]})})]})}var H={users:M,groups:E,group_members:P,allowlist:N};function J({renderHeader:i}={}){let t=(0,b.useLoaderData)()?.segment??"users",d=H[t]??M;return(0,e.jsx)(z,{renderHeader:i,children:(0,e.jsx)(d,{})})}0&&(module.exports={AllowlistView,AuthUserAdminAppView,GroupMembersView,GroupsView,UserAdminShell,UsersView,createInMemoryUserAdminStore,createUserAdminApp,defaultUserAdminLabels,jaUserAdminLabels,resolveUserAdminLabels});
1
+ "use strict";var R=Object.defineProperty;var F=Object.getOwnPropertyDescriptor;var W=Object.getOwnPropertyNames;var $=Object.prototype.hasOwnProperty;var q=(r,i)=>{for(var t in i)R(r,t,{get:i[t],enumerable:!0})},K=(r,i,t,d)=>{if(i&&typeof i=="object"||typeof i=="function")for(let m of W(i))!$.call(r,m)&&m!==t&&R(r,m,{get:()=>i[m],enumerable:!(d=F(i,m))||d.enumerable});return r};var j=r=>K(R({},"__esModule",{value:!0}),r);var Y={};q(Y,{AllowlistView:()=>L,AuthUserAdminAppView:()=>X,GroupMembersView:()=>N,GroupsView:()=>E,UserAdminShell:()=>P,UsersView:()=>z,createInMemoryUserAdminStore:()=>_,createUserAdminApp:()=>Q,defaultUserAdminLabels:()=>v,jaUserAdminLabels:()=>O,resolveUserAdminLabels:()=>G});module.exports=j(Y);var v={title:"Users & Groups",heading:"\u{1F464} User administration",tabs:{users:"\u{1F464} Users",groups:"\u{1F465} Groups",groupMembers:"\u{1F517} Members",allowlist:"\u2709\uFE0F Allowlist"},usersView:{title:"Users",searchPlaceholder:"Search by name or email...",addUser:"\uFF0B Add user",editUser:"Edit user",id:"ID",displayName:"Name",email:"Email",status:"Status",active:"Active",inactive:"Inactive",actions:"Actions",edit:"Edit",activate:"Activate",deactivate:"Deactivate",empty:"No matching users",save:"Save",cancel:"Cancel"},groupsView:{title:"Groups",searchPlaceholder:"Search by group name or key...",addGroup:"\uFF0B Add group",editGroup:"Edit group",id:"ID",groupKey:"Group key",name:"Name",description:"Description",memberCount:"Members",status:"Status",actions:"Actions",edit:"Edit",delete:"Delete",confirmDelete:"Delete this group?",noDescription:"No description",groupKeyPlaceholder:"e.g. dev-team",namePlaceholder:"e.g. Development team",empty:"No groups registered",save:"Save",cancel:"Cancel"},groupMembersView:{selectGroup:"Select a group",selectPrompt:"Select a group to manage its members",actionAdd:"Add",actionRemove:"Remove"},allowlistView:{title:"Sign-in allowlist",addEntry:"\uFF0B Add pattern",pattern:"Pattern (e.g. @example.com or user@example.com)",type:"Type",emailType:"Exact email match",domainType:"Domain match",emailTypeShort:"Email",domainTypeShort:"Domain",description:"Description",actions:"Actions",readOnly:"Read-only",delete:"Delete",empty:"No allowlist entries registered",save:"Add",cancel:"Cancel"}},O={title:"\u30E6\u30FC\u30B6\u30FC\u30FB\u30B0\u30EB\u30FC\u30D7\u7BA1\u7406",heading:"\u{1F464} \u30E6\u30FC\u30B6\u30FC\u7BA1\u7406",tabs:{users:"\u{1F464} \u30E6\u30FC\u30B6\u30FC\u4E00\u89A7",groups:"\u{1F465} \u30E6\u30FC\u30B6\u30FC\u30B0\u30EB\u30FC\u30D7",groupMembers:"\u{1F517} \u30B0\u30EB\u30FC\u30D7\u30E1\u30F3\u30D0\u30FC",allowlist:"\u2709\uFE0F \u30A2\u30AF\u30BB\u30B9\u8A31\u53EF\u30EA\u30B9\u30C8"},usersView:{title:"\u30E6\u30FC\u30B6\u30FC\u7BA1\u7406",searchPlaceholder:"\u8868\u793A\u540D\u3084 Email \u3067\u691C\u7D22...",addUser:"\uFF0B \u30E6\u30FC\u30B6\u30FC\u8FFD\u52A0",editUser:"\u30E6\u30FC\u30B6\u30FC\u306E\u7DE8\u96C6",id:"ID",displayName:"\u8868\u793A\u540D",email:"\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9",status:"\u30B9\u30C6\u30FC\u30BF\u30B9",active:"\u6709\u52B9",inactive:"\u7121\u52B9",actions:"\u64CD\u4F5C",edit:"\u7DE8\u96C6",activate:"\u6709\u52B9\u5316",deactivate:"\u7121\u52B9\u5316",empty:"\u8A72\u5F53\u3059\u308B\u30E6\u30FC\u30B6\u30FC\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093",save:"\u4FDD\u5B58",cancel:"\u30AD\u30E3\u30F3\u30BB\u30EB"},groupsView:{title:"\u30E6\u30FC\u30B6\u30FC\u30B0\u30EB\u30FC\u30D7\u7BA1\u7406",searchPlaceholder:"\u30B0\u30EB\u30FC\u30D7\u540D\u3084\u30AD\u30FC\u3067\u691C\u7D22...",addGroup:"\uFF0B \u30B0\u30EB\u30FC\u30D7\u4F5C\u6210",editGroup:"\u30B0\u30EB\u30FC\u30D7\u306E\u7DE8\u96C6",id:"ID",groupKey:"\u30B0\u30EB\u30FC\u30D7\u30AD\u30FC",name:"\u30B0\u30EB\u30FC\u30D7\u540D",description:"\u8AAC\u660E",memberCount:"\u30E1\u30F3\u30D0\u30FC\u6570",status:"\u30B9\u30C6\u30FC\u30BF\u30B9",actions:"\u64CD\u4F5C",edit:"\u7DE8\u96C6",delete:"\u524A\u9664",confirmDelete:"\u3053\u306E\u30B0\u30EB\u30FC\u30D7\u3092\u524A\u9664\u3057\u3066\u3082\u3088\u308D\u3057\u3044\u3067\u3059\u304B\uFF1F",noDescription:"\u8AAC\u660E\u306A\u3057",groupKeyPlaceholder:"\u4F8B: dev-team",namePlaceholder:"\u4F8B: \u958B\u767A\u30C1\u30FC\u30E0",empty:"\u30B0\u30EB\u30FC\u30D7\u304C\u767B\u9332\u3055\u308C\u3066\u3044\u307E\u305B\u3093",save:"\u4FDD\u5B58",cancel:"\u30AD\u30E3\u30F3\u30BB\u30EB"},groupMembersView:{selectGroup:"\u30B0\u30EB\u30FC\u30D7\u9078\u629E",selectPrompt:"\u30B0\u30EB\u30FC\u30D7\u3092\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044",actionAdd:"\u8FFD\u52A0",actionRemove:"\u9664\u5916"},allowlistView:{title:"\u30A2\u30AF\u30BB\u30B9\u8A31\u53EF\u30EA\u30B9\u30C8 (Allowlist)",addEntry:"\uFF0B \u8A31\u53EF\u30D1\u30BF\u30FC\u30F3\u8FFD\u52A0",pattern:"\u30D1\u30BF\u30FC\u30F3 (\u4F8B: @example.com \u307E\u305F\u306F user@example.com)",type:"\u7A2E\u5225",emailType:"\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9\u5B8C\u5168\u4E00\u81F4",domainType:"\u30C9\u30E1\u30A4\u30F3\u4E00\u81F4",emailTypeShort:"Email \u5B8C\u5168\u4E00\u81F4",domainTypeShort:"\u30C9\u30E1\u30A4\u30F3\u4E00\u81F4",description:"\u8AAC\u660E / \u5099\u8003",actions:"\u64CD\u4F5C",readOnly:"\u5909\u66F4\u4E0D\u53EF",delete:"\u524A\u9664",empty:"\u30A2\u30ED\u30EF\u30EA\u30B9\u30C8\u30A8\u30F3\u30C8\u30EA\u304C\u767B\u9332\u3055\u308C\u3066\u3044\u307E\u305B\u3093",save:"\u767B\u9332",cancel:"\u30AD\u30E3\u30F3\u30BB\u30EB"}};function G(r){let i=v;return r?{title:r.title??i.title,heading:r.heading??i.heading,tabs:{...i.tabs,...r.tabs},usersView:{...i.usersView,...r.usersView},groupsView:{...i.groupsView,...r.groupsView},groupMembersView:{...i.groupMembersView,...r.groupMembersView},allowlistView:{...i.allowlistView,...r.allowlistView}}:i}function _(r){let i=r?.users??[{id:1,email:"admin@example.com",displayName:"\u30B7\u30B9\u30C6\u30E0\u7BA1\u7406\u8005",isActive:!0},{id:2,email:"user1@example.com",displayName:"\u958B\u767A \u592A\u90CE",isActive:!0},{id:3,email:"user2@example.com",displayName:"\u55B6\u696D \u82B1\u5B50",isActive:!0}],t=r?.groups??[{id:1,groupKey:"dev-team",name:"\u958B\u767A\u30C1\u30FC\u30E0",description:"\u30B7\u30B9\u30C6\u30E0\u958B\u767A\u62C5\u5F53\u30B0\u30EB\u30FC\u30D7",isActive:!0},{id:2,groupKey:"sales-dept",name:"\u55B6\u696D\u90E8",description:"\u55B6\u696D\u30BD\u30EA\u30E5\u30FC\u30B7\u30E7\u30F3\u62C5\u5F53",isActive:!0}],d=r?.groupMembers??[{id:1,groupId:1,userId:2},{id:2,groupId:2,userId:3}],m=r?.allowlist??[{id:1,pattern:"admin@example.com",type:"email",description:"\u521D\u671F\u7BA1\u7406\u8005"},{id:2,pattern:"@example.com",type:"domain",description:"\u793E\u5185\u30C9\u30E1\u30A4\u30F3"}];return{async listUsers(){return[...i]},async createUser(s){let o={id:Math.max(...i.map(n=>n.id),0)+1,email:s.email,displayName:s.displayName,isActive:!0};return i.push(o),o},async updateUser(s,o){let n=i.findIndex(a=>a.id===s);if(n===-1)throw new Error(`User not found: ${s}`);return i[n]={...i[n],displayName:o.displayName,email:o.email},i[n]},async toggleUserActive(s,o){let n=i.findIndex(a=>a.id===s);if(n===-1)throw new Error(`User not found: ${s}`);return i[n]={...i[n],isActive:o},i[n]},async listGroups(){return[...t]},async createGroup(s){let o={id:Math.max(...t.map(n=>n.id),0)+1,groupKey:s.groupKey,name:s.name,description:s.description,isActive:!0};return t.push(o),o},async updateGroup(s,o){let n=t.findIndex(a=>a.id===s);if(n===-1)throw new Error(`Group not found: ${s}`);return t[n]={...t[n],name:o.name,description:o.description},t[n]},async deleteGroup(s){t=t.filter(o=>o.id!==s),d=d.filter(o=>o.groupId!==s)},async listGroupMembers(){return[...d]},async addGroupMember(s,o){let n=d.find(l=>l.groupId===s&&l.userId===o);if(n)return n;let a={id:Math.max(...d.map(l=>l.id),0)+1,groupId:s,userId:o};return d.push(a),a},async removeGroupMember(s,o){d=d.filter(n=>!(n.groupId===s&&n.userId===o))},async listAllowlist(){return[...m]},async addAllowlistEntry(s){let o={id:Math.max(...m.map(n=>n.id),0)+1,pattern:s.pattern,type:s.type,description:s.description};return m.push(o),o},async removeAllowlistEntry(s){m=m.filter(o=>o.id!==s)}}}var H=new Map([["createUser","create"],["updateUser","update"],["toggleUserActive","update"],["createGroup","create"],["updateGroup","update"],["deleteGroup","delete"],["addGroupMember","create"],["removeGroupMember","delete"],["addAllowlistEntry","create"],["removeAllowlistEntry","delete"]]);function A(r,i){let t=r.get(i),d=Number(t);if(t===null||String(t).trim()===""||!Number.isInteger(d)||d<=0)throw new Error(`Invalid or missing "${i}"`);return d}function S(r,i){let t=String(r.get(i)??"").trim();if(t==="")throw new Error(`Invalid or missing "${i}"`);return t}function I(r,i){let t=String(r.get(i)??"").trim();return t===""?void 0:t}function Q(r){let i=G(r.labels);async function t({request:s}){await r.guards.requireAccess(s,{action:"read",intent:"loader"});let n=new URL(s.url).pathname.split("/").filter(Boolean),a=n[n.length-1]??"users",[l,x,u,w,g]=await Promise.all([r.store.listUsers(),r.store.listGroups(),r.store.listGroupMembers(),r.store.listAllowlist(),r.getMyPermissions?r.getMyPermissions(s).catch(y=>(console.error("[@aiquants/auth-react-router] getMyPermissions failed; rendering the permission badge as unknown:",y),null)):Promise.resolve(null)]);return{resourceLabels:r.resourceLabels,segment:["groups","group_members","allowlist"].includes(a)?a:"users",users:l,groups:x,groupMembers:u,allowlist:w,myPermissions:g,labels:i}}async function d({request:s}){let o=await s.formData(),n=String(o.get("intent")??""),a=H.get(n);if(!a)return{ok:!1,error:`Unknown intent: ${n}`};await r.guards.requireAccess(s,{action:a,intent:n});try{return await m(n,o)}catch(l){if(l instanceof Response)throw l;return{ok:!1,error:l instanceof Error?l.message:String(l)}}}async function m(s,o){if(s==="createUser")return await r.store.createUser({displayName:S(o,"displayName"),email:S(o,"email")}),{ok:!0};if(s==="updateUser")return await r.store.updateUser(A(o,"userId"),{displayName:S(o,"displayName"),email:S(o,"email")}),{ok:!0};if(s==="toggleUserActive"){let n=String(o.get("isActive")??"");if(n!=="true"&&n!=="false")throw new Error('Invalid or missing "isActive"');return await r.store.toggleUserActive(A(o,"userId"),n==="true"),{ok:!0}}if(s==="createGroup")return await r.store.createGroup({groupKey:S(o,"groupKey"),name:S(o,"name"),description:I(o,"description")}),{ok:!0};if(s==="updateGroup")return await r.store.updateGroup(A(o,"groupId"),{name:S(o,"name"),description:I(o,"description")}),{ok:!0};if(s==="deleteGroup")return await r.store.deleteGroup(A(o,"groupId")),{ok:!0};if(s==="addGroupMember")return await r.store.addGroupMember(A(o,"groupId"),A(o,"userId")),{ok:!0};if(s==="removeGroupMember")return await r.store.removeGroupMember(A(o,"groupId"),A(o,"userId")),{ok:!0};if(s==="addAllowlistEntry"){let n=o.get("type")==="domain"?"domain":"email";return await r.store.addAllowlistEntry({pattern:S(o,"pattern"),type:n,description:I(o,"description")}),{ok:!0}}return s==="removeAllowlistEntry"?(await r.store.removeAllowlistEntry(A(o,"entryId")),{ok:!0}):{ok:!1,error:`Unknown intent: ${s}`}}return{loader:t,action:d}}var C=require("react-router");var b=require("react/jsx-runtime");function M({label:r,summary:i}){return(0,b.jsxs)("span",{style:{display:"inline-flex",alignItems:"center",gap:"0.18rem",fontSize:"0.65rem",padding:"0.08rem 0.35rem",borderRadius:"9999px",backgroundColor:i.bgColor,color:i.color,border:`1px solid ${i.borderColor}`,fontWeight:600,lineHeight:"1.2"},children:[(0,b.jsxs)("span",{children:[r,":"]}),(0,b.jsx)("span",{children:i.text})]})}function P({children:r,renderHeader:i}){let t=(0,C.useLoaderData)(),d=t?.segment??"users",m=t?.labels??v,s=t?.myPermissions??null,o=t?.resourceLabels??{},n=g=>Object.hasOwn(o,g)?o[g]:g,a=[{key:"users",label:m.tabs.users,href:"/users"},{key:"groups",label:m.tabs.groups,href:"/users/groups"},{key:"group_members",label:m.tabs.groupMembers,href:"/users/group_members"},{key:"allowlist",label:m.tabs.allowlist,href:"/users/allowlist"}],l=Object.entries(s??{}),x=g=>g?.canWrite?{text:"\u7DE8\u96C6\u53EF",color:"#047857",bgColor:"#ecfdf5",borderColor:"#a7f3d0"}:g?.canRead?{text:"\u95B2\u89A7\u306E\u307F",color:"#1d4ed8",bgColor:"#eff6ff",borderColor:"#bfdbfe"}:{text:"\u6A29\u9650\u306A\u3057",color:"#64748b",bgColor:"#f1f5f9",borderColor:"#cbd5e1"},u={text:"\u6A29\u9650\u4E0D\u660E",color:"#92400e",bgColor:"#fffbeb",borderColor:"#fde68a"},w=(0,b.jsxs)("div",{style:{display:"flex",alignItems:"center",gap:"0.4rem"},"data-testid":"user-admin-header-annotation",children:[(0,b.jsx)("span",{style:{fontSize:"0.75rem",backgroundColor:"#e0f2fe",color:"#0369a1",padding:"2px 8px",borderRadius:"12px",fontWeight:600},children:m.heading}),(0,b.jsxs)("div",{style:{display:"inline-flex",alignItems:"center",gap:"0.25rem",fontSize:"0.68rem",color:"#475569"},"data-testid":"user-admin-permissions-badge",children:[(0,b.jsx)("span",{style:{fontWeight:600,color:"#334155"},children:"\u3042\u306A\u305F\u306E\u6A29\u9650:"}),(0,b.jsx)("span",{style:{display:"inline-flex",alignItems:"center",gap:"0.18rem"},children:l.length===0?(0,b.jsx)("span",{"data-testid":"user-admin-permission-unavailable",children:(0,b.jsx)(M,{label:m.heading,summary:u})}):l.map(([g,y])=>(0,b.jsx)(M,{label:n(g),summary:x(y)},g))})]})]});return(0,b.jsxs)("div",{"data-testid":"user-admin-shell",style:{width:"100%",minHeight:"100vh",backgroundColor:"#f8fafc",padding:"1.5rem",boxSizing:"border-box"},children:[i?i({title:m.title,annotation:w}):(0,b.jsxs)("div",{style:{marginBottom:"1.5rem",display:"flex",justifyContent:"space-between",alignItems:"center"},children:[(0,b.jsx)("h1",{style:{margin:0,fontSize:"1.5rem",fontWeight:700,color:"#0f172a"},children:m.title}),w]}),(0,b.jsx)("div",{style:{display:"flex",gap:"0.5rem",marginBottom:"1.2rem",borderBottom:"2px solid #e2e8f0",paddingBottom:"0.5rem"},children:a.map(g=>{let y=d===g.key;return(0,b.jsx)(C.Link,{to:g.href,"data-testid":`user-admin-tab-${g.key}`,style:{padding:"0.5rem 1rem",borderRadius:"6px 6px 0 0",fontSize:"0.88rem",fontWeight:y?700:500,color:y?"#0284c7":"#64748b",backgroundColor:y?"#ffffff":"transparent",textDecoration:"none",borderBottom:y?"3px solid #0284c7":"3px solid transparent",transition:"all 0.15s ease"},children:g.label},g.key)})}),(0,b.jsx)("main",{children:r})]})}var f=require("react"),h=require("react-router");var e=require("react/jsx-runtime");function U({fetcher:r}){let i=r.data;return i?.ok!==!1||!i.error?null:(0,e.jsx)("div",{"data-testid":"user-admin-action-error",role:"alert",style:{padding:"0.7rem 1rem",borderRadius:"6px",border:"1px solid #fecaca",backgroundColor:"#fef2f2",color:"#b91c1c",fontSize:"0.85rem"},children:i.error})}function z(){let r=(0,h.useLoaderData)(),i=(0,h.useFetcher)(),t=r.labels??v,[d,m]=(0,f.useState)(""),[s,o]=(0,f.useState)(null),[n,a]=(0,f.useState)(!1),[l,x]=(0,f.useState)(""),[u,w]=(0,f.useState)(""),g=r.users.filter(p=>p.displayName.toLowerCase().includes(d.toLowerCase())||p.email.toLowerCase().includes(d.toLowerCase())),y=p=>{i.submit({intent:"toggleUserActive",userId:String(p.id),isActive:String(!p.isActive)},{method:"post"})},k=p=>{p.preventDefault(),l&&u&&(i.submit({intent:"createUser",displayName:l,email:u},{method:"post"}),x(""),w(""),a(!1))},V=p=>{p.preventDefault(),s&&(i.submit({intent:"updateUser",userId:String(s.id),displayName:s.displayName,email:s.email},{method:"post"}),o(null))};return(0,e.jsxs)("section",{"data-testid":"users-view-section",style:{display:"flex",flexDirection:"column",gap:"1rem"},children:[(0,e.jsx)(U,{fetcher:i}),(0,e.jsxs)("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",backgroundColor:"#ffffff",padding:"1rem",borderRadius:"8px",border:"1px solid #e2e8f0"},children:[(0,e.jsx)("input",{type:"text",placeholder:t.usersView.searchPlaceholder,value:d,onChange:p=>m(p.target.value),"data-testid":"users-search-input",style:{padding:"6px 12px",borderRadius:"6px",border:"1px solid #cbd5e1",fontSize:"0.85rem",width:"260px"}}),(0,e.jsx)("button",{type:"button",onClick:()=>a(!0),"data-testid":"users-add-button",style:{padding:"6px 14px",borderRadius:"6px",backgroundColor:"#0284c7",color:"#ffffff",border:"none",fontSize:"0.85rem",fontWeight:600,cursor:"pointer"},children:t.usersView.addUser})]}),(0,e.jsx)("div",{style:{backgroundColor:"#ffffff",borderRadius:"8px",border:"1px solid #e2e8f0",overflow:"hidden"},children:(0,e.jsxs)("table",{style:{width:"100%",borderCollapse:"collapse",fontSize:"0.85rem",textAlign:"left"},children:[(0,e.jsx)("thead",{children:(0,e.jsxs)("tr",{style:{backgroundColor:"#f8fafc",borderBottom:"1px solid #e2e8f0",color:"#475569"},children:[(0,e.jsx)("th",{style:{padding:"10px 14px"},children:t.usersView.id}),(0,e.jsx)("th",{style:{padding:"10px 14px"},children:t.usersView.displayName}),(0,e.jsx)("th",{style:{padding:"10px 14px"},children:t.usersView.email}),(0,e.jsx)("th",{style:{padding:"10px 14px"},children:t.usersView.status}),(0,e.jsx)("th",{style:{padding:"10px 14px",textAlign:"right"},children:t.usersView.actions})]})}),(0,e.jsxs)("tbody",{children:[g.map(p=>(0,e.jsxs)("tr",{style:{borderBottom:"1px solid #f1f5f9"},"data-testid":`user-row-${p.id}`,children:[(0,e.jsxs)("td",{style:{padding:"10px 14px",color:"#64748b"},children:["#",p.id]}),(0,e.jsx)("td",{style:{padding:"10px 14px",fontWeight:600,color:"#0f172a"},children:p.displayName}),(0,e.jsx)("td",{style:{padding:"10px 14px",color:"#475569"},children:p.email}),(0,e.jsx)("td",{style:{padding:"10px 14px"},children:(0,e.jsx)("span",{style:{fontSize:"0.75rem",padding:"2px 8px",borderRadius:"10px",backgroundColor:p.isActive?"#dcfce7":"#fee2e2",color:p.isActive?"#15803d":"#b91c1c",fontWeight:600},children:p.isActive?t.usersView.active:t.usersView.inactive})}),(0,e.jsxs)("td",{style:{padding:"10px 14px",textAlign:"right"},children:[(0,e.jsx)("button",{type:"button",onClick:()=>o(p),"data-testid":`edit-user-btn-${p.id}`,style:{padding:"3px 8px",borderRadius:"4px",border:"1px solid #cbd5e1",backgroundColor:"#ffffff",fontSize:"0.78rem",cursor:"pointer",marginRight:"6px"},children:t.usersView.edit}),(0,e.jsx)("button",{type:"button",onClick:()=>y(p),"data-testid":`toggle-user-btn-${p.id}`,style:{padding:"3px 8px",borderRadius:"4px",border:"1px solid #cbd5e1",backgroundColor:"#ffffff",fontSize:"0.78rem",cursor:"pointer",color:p.isActive?"#b91c1c":"#15803d"},children:p.isActive?t.usersView.deactivate:t.usersView.activate})]})]},p.id)),g.length===0&&(0,e.jsx)("tr",{children:(0,e.jsx)("td",{colSpan:5,style:{padding:"2rem",textAlign:"center",color:"#94a3b8"},children:t.usersView.empty})})]})]})}),n&&(0,e.jsx)("div",{style:{position:"fixed",inset:0,backgroundColor:"rgba(0,0,0,0.4)",display:"flex",justifyContent:"center",alignItems:"center",zIndex:100},"data-testid":"user-create-modal",children:(0,e.jsxs)("form",{onSubmit:k,style:{backgroundColor:"#ffffff",padding:"1.5rem",borderRadius:"8px",width:"360px",boxShadow:"0 10px 25px rgba(0,0,0,0.15)"},children:[(0,e.jsx)("h3",{style:{margin:"0 0 1rem 0",fontSize:"1.1rem"},children:t.usersView.addUser}),(0,e.jsxs)("div",{style:{marginBottom:"1rem"},children:[(0,e.jsx)("label",{htmlFor:"create-user-display-name-input",style:{display:"block",fontSize:"0.8rem",color:"#475569",marginBottom:"4px"},children:t.usersView.displayName}),(0,e.jsx)("input",{id:"create-user-display-name-input",type:"text",value:l,onChange:p=>x(p.target.value),required:!0,"data-testid":"create-user-display-name",style:{width:"100%",padding:"6px",borderRadius:"4px",border:"1px solid #cbd5e1",boxSizing:"border-box"}})]}),(0,e.jsxs)("div",{style:{marginBottom:"1.2rem"},children:[(0,e.jsx)("label",{htmlFor:"create-user-email-input",style:{display:"block",fontSize:"0.8rem",color:"#475569",marginBottom:"4px"},children:t.usersView.email}),(0,e.jsx)("input",{id:"create-user-email-input",type:"email",value:u,onChange:p=>w(p.target.value),required:!0,"data-testid":"create-user-email",style:{width:"100%",padding:"6px",borderRadius:"4px",border:"1px solid #cbd5e1",boxSizing:"border-box"}})]}),(0,e.jsxs)("div",{style:{display:"flex",justifyContent:"flex-end",gap:"0.5rem"},children:[(0,e.jsx)("button",{type:"button",onClick:()=>a(!1),style:{padding:"6px 12px",borderRadius:"4px",border:"1px solid #cbd5e1",backgroundColor:"#ffffff",cursor:"pointer"},children:"\u30AD\u30E3\u30F3\u30BB\u30EB"}),(0,e.jsx)("button",{type:"submit","data-testid":"submit-create-user",style:{padding:"6px 12px",borderRadius:"4px",backgroundColor:"#0284c7",color:"#ffffff",border:"none",cursor:"pointer"},children:"\u4F5C\u6210"})]})]})}),s&&(0,e.jsx)("div",{style:{position:"fixed",inset:0,backgroundColor:"rgba(0,0,0,0.4)",display:"flex",justifyContent:"center",alignItems:"center",zIndex:100},"data-testid":"user-edit-modal",children:(0,e.jsxs)("form",{onSubmit:V,style:{backgroundColor:"#ffffff",padding:"1.5rem",borderRadius:"8px",width:"360px",boxShadow:"0 10px 25px rgba(0,0,0,0.15)"},children:[(0,e.jsx)("h3",{style:{margin:"0 0 1rem 0",fontSize:"1.1rem"},children:t.usersView.editUser}),(0,e.jsxs)("div",{style:{marginBottom:"1rem"},children:[(0,e.jsx)("label",{htmlFor:"edit-user-display-name-input",style:{display:"block",fontSize:"0.8rem",color:"#475569",marginBottom:"4px"},children:t.usersView.displayName}),(0,e.jsx)("input",{id:"edit-user-display-name-input",type:"text",value:s.displayName,onChange:p=>o({...s,displayName:p.target.value}),required:!0,"data-testid":"edit-user-display-name",style:{width:"100%",padding:"6px",borderRadius:"4px",border:"1px solid #cbd5e1",boxSizing:"border-box"}})]}),(0,e.jsxs)("div",{style:{marginBottom:"1.2rem"},children:[(0,e.jsx)("label",{htmlFor:"edit-user-email-input",style:{display:"block",fontSize:"0.8rem",color:"#475569",marginBottom:"4px"},children:t.usersView.email}),(0,e.jsx)("input",{id:"edit-user-email-input",type:"email",value:s.email,onChange:p=>o({...s,email:p.target.value}),required:!0,"data-testid":"edit-user-email",style:{width:"100%",padding:"6px",borderRadius:"4px",border:"1px solid #cbd5e1",boxSizing:"border-box"}})]}),(0,e.jsxs)("div",{style:{display:"flex",justifyContent:"flex-end",gap:"0.5rem"},children:[(0,e.jsx)("button",{type:"button",onClick:()=>o(null),style:{padding:"6px 12px",borderRadius:"4px",border:"1px solid #cbd5e1",backgroundColor:"#ffffff",cursor:"pointer"},children:t.usersView.cancel}),(0,e.jsx)("button",{type:"submit","data-testid":"submit-edit-user",style:{padding:"6px 12px",borderRadius:"4px",backgroundColor:"#0284c7",color:"#ffffff",border:"none",cursor:"pointer"},children:t.usersView.save})]})]})})]})}function E(){let r=(0,h.useLoaderData)(),i=(0,h.useFetcher)(),t=r.labels??v,[d,m]=(0,f.useState)(""),[s,o]=(0,f.useState)(!1),[n,a]=(0,f.useState)(null),[l,x]=(0,f.useState)(""),[u,w]=(0,f.useState)(""),[g,y]=(0,f.useState)(""),k=r.groups.filter(c=>c.name.toLowerCase().includes(d.toLowerCase())||c.groupKey.toLowerCase().includes(d.toLowerCase())),V=c=>{c.preventDefault(),l&&u&&(i.submit({intent:"createGroup",groupKey:l,name:u,description:g},{method:"post"}),x(""),w(""),y(""),o(!1))},p=c=>{c.preventDefault(),n&&(i.submit({intent:"updateGroup",groupId:String(n.id),name:n.name,description:n.description??""},{method:"post"}),a(null))},B=c=>{window.confirm(t.groupsView.confirmDelete)&&i.submit({intent:"deleteGroup",groupId:String(c)},{method:"post"})};return(0,e.jsxs)("section",{"data-testid":"groups-view-section",style:{display:"flex",flexDirection:"column",gap:"1rem"},children:[(0,e.jsx)(U,{fetcher:i}),(0,e.jsxs)("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",backgroundColor:"#ffffff",padding:"1rem",borderRadius:"8px",border:"1px solid #e2e8f0"},children:[(0,e.jsx)("input",{type:"text",placeholder:t.groupsView.searchPlaceholder,value:d,onChange:c=>m(c.target.value),"data-testid":"groups-search-input",style:{padding:"6px 12px",borderRadius:"6px",border:"1px solid #cbd5e1",fontSize:"0.85rem",width:"260px"}}),(0,e.jsx)("button",{type:"button",onClick:()=>o(!0),"data-testid":"groups-add-button",style:{padding:"6px 14px",borderRadius:"6px",backgroundColor:"#4338ca",color:"#ffffff",border:"none",fontSize:"0.85rem",fontWeight:600,cursor:"pointer"},children:t.groupsView.addGroup})]}),(0,e.jsx)("div",{style:{display:"grid",gridTemplateColumns:"repeat(auto-fill, minmax(280px, 1fr))",gap:"1rem"},children:k.map(c=>{let D=r.groupMembers.filter(T=>T.groupId===c.id).length;return(0,e.jsxs)("div",{style:{backgroundColor:"#ffffff",borderRadius:"8px",border:"1px solid #e2e8f0",padding:"1rem",display:"flex",flexDirection:"column",justifyContent:"space-between"},"data-testid":`group-card-${c.id}`,children:[(0,e.jsxs)("div",{children:[(0,e.jsxs)("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:"0.5rem"},children:[(0,e.jsx)("h4",{style:{margin:0,fontSize:"1rem",color:"#0f172a"},children:c.name}),(0,e.jsx)("span",{style:{fontSize:"0.72rem",backgroundColor:"#e0e7ff",color:"#4338ca",padding:"2px 6px",borderRadius:"4px",fontFamily:"monospace"},children:c.groupKey})]}),(0,e.jsx)("p",{style:{margin:"0 0 0.8rem 0",fontSize:"0.82rem",color:"#64748b",minHeight:"2.4em"},children:c.description||t.groupsView.noDescription})]}),(0,e.jsxs)("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",borderTop:"1px solid #f1f5f9",paddingTop:"0.6rem"},children:[(0,e.jsxs)("span",{style:{fontSize:"0.78rem",color:"#475569"},children:["\u{1F465} \u30E1\u30F3\u30D0\u30FC: ",(0,e.jsx)("strong",{children:D})," \u4EBA"]}),(0,e.jsxs)("div",{children:[(0,e.jsx)("button",{type:"button",onClick:()=>a(c),"data-testid":`edit-group-btn-${c.id}`,style:{padding:"3px 8px",borderRadius:"4px",border:"1px solid #cbd5e1",backgroundColor:"#ffffff",fontSize:"0.75rem",cursor:"pointer",marginRight:"4px"},children:t.usersView.edit}),(0,e.jsx)("button",{type:"button",onClick:()=>B(c.id),"data-testid":`delete-group-btn-${c.id}`,style:{padding:"3px 8px",borderRadius:"4px",border:"1px solid #fee2e2",backgroundColor:"#fff5f5",color:"#b91c1c",fontSize:"0.75rem",cursor:"pointer"},children:"\u524A\u9664"})]})]})]},c.id)})}),s&&(0,e.jsx)("div",{style:{position:"fixed",inset:0,backgroundColor:"rgba(0,0,0,0.4)",display:"flex",justifyContent:"center",alignItems:"center",zIndex:100},"data-testid":"group-create-modal",children:(0,e.jsxs)("form",{onSubmit:V,style:{backgroundColor:"#ffffff",padding:"1.5rem",borderRadius:"8px",width:"360px",boxShadow:"0 10px 25px rgba(0,0,0,0.15)"},children:[(0,e.jsx)("h3",{style:{margin:"0 0 1rem 0",fontSize:"1.1rem"},children:t.groupsView.addGroup}),(0,e.jsxs)("div",{style:{marginBottom:"1rem"},children:[(0,e.jsx)("label",{htmlFor:"create-group-key-input",style:{display:"block",fontSize:"0.8rem",color:"#475569",marginBottom:"4px"},children:t.groupsView.groupKey}),(0,e.jsx)("input",{id:"create-group-key-input",type:"text",value:l,onChange:c=>x(c.target.value),placeholder:t.groupsView.groupKeyPlaceholder,required:!0,"data-testid":"create-group-key",style:{width:"100%",padding:"6px",borderRadius:"4px",border:"1px solid #cbd5e1",boxSizing:"border-box"}})]}),(0,e.jsxs)("div",{style:{marginBottom:"1rem"},children:[(0,e.jsx)("label",{htmlFor:"create-group-name-input",style:{display:"block",fontSize:"0.8rem",color:"#475569",marginBottom:"4px"},children:t.groupsView.name}),(0,e.jsx)("input",{id:"create-group-name-input",type:"text",value:u,onChange:c=>w(c.target.value),placeholder:t.groupsView.namePlaceholder,required:!0,"data-testid":"create-group-name",style:{width:"100%",padding:"6px",borderRadius:"4px",border:"1px solid #cbd5e1",boxSizing:"border-box"}})]}),(0,e.jsxs)("div",{style:{marginBottom:"1.2rem"},children:[(0,e.jsx)("label",{htmlFor:"create-group-desc-input",style:{display:"block",fontSize:"0.8rem",color:"#475569",marginBottom:"4px"},children:t.groupsView.description}),(0,e.jsx)("textarea",{id:"create-group-desc-input",value:g,onChange:c=>y(c.target.value),"data-testid":"create-group-description",style:{width:"100%",padding:"6px",borderRadius:"4px",border:"1px solid #cbd5e1",boxSizing:"border-box",height:"60px"}})]}),(0,e.jsxs)("div",{style:{display:"flex",justifyContent:"flex-end",gap:"0.5rem"},children:[(0,e.jsx)("button",{type:"button",onClick:()=>o(!1),style:{padding:"6px 12px",borderRadius:"4px",border:"1px solid #cbd5e1",backgroundColor:"#ffffff",cursor:"pointer"},children:"\u30AD\u30E3\u30F3\u30BB\u30EB"}),(0,e.jsx)("button",{type:"submit","data-testid":"submit-create-group",style:{padding:"6px 12px",borderRadius:"4px",backgroundColor:"#4338ca",color:"#ffffff",border:"none",cursor:"pointer"},children:"\u4F5C\u6210"})]})]})}),n&&(0,e.jsx)("div",{style:{position:"fixed",inset:0,backgroundColor:"rgba(0,0,0,0.4)",display:"flex",justifyContent:"center",alignItems:"center",zIndex:100},"data-testid":"group-edit-modal",children:(0,e.jsxs)("form",{onSubmit:p,style:{backgroundColor:"#ffffff",padding:"1.5rem",borderRadius:"8px",width:"360px",boxShadow:"0 10px 25px rgba(0,0,0,0.15)"},children:[(0,e.jsx)("h3",{style:{margin:"0 0 1rem 0",fontSize:"1.1rem"},children:t.groupsView.editGroup}),(0,e.jsxs)("div",{style:{marginBottom:"1rem"},children:[(0,e.jsx)("label",{htmlFor:"edit-group-name-input",style:{display:"block",fontSize:"0.8rem",color:"#475569",marginBottom:"4px"},children:t.groupsView.name}),(0,e.jsx)("input",{id:"edit-group-name-input",type:"text",value:n.name,onChange:c=>a({...n,name:c.target.value}),required:!0,"data-testid":"edit-group-name",style:{width:"100%",padding:"6px",borderRadius:"4px",border:"1px solid #cbd5e1",boxSizing:"border-box"}})]}),(0,e.jsxs)("div",{style:{marginBottom:"1.2rem"},children:[(0,e.jsx)("label",{htmlFor:"edit-group-desc-input",style:{display:"block",fontSize:"0.8rem",color:"#475569",marginBottom:"4px"},children:t.groupsView.description}),(0,e.jsx)("textarea",{id:"edit-group-desc-input",value:n.description??"",onChange:c=>a({...n,description:c.target.value}),"data-testid":"edit-group-description",style:{width:"100%",padding:"6px",borderRadius:"4px",border:"1px solid #cbd5e1",boxSizing:"border-box",height:"60px"}})]}),(0,e.jsxs)("div",{style:{display:"flex",justifyContent:"flex-end",gap:"0.5rem"},children:[(0,e.jsx)("button",{type:"button",onClick:()=>a(null),style:{padding:"6px 12px",borderRadius:"4px",border:"1px solid #cbd5e1",backgroundColor:"#ffffff",cursor:"pointer"},children:t.groupsView.cancel}),(0,e.jsx)("button",{type:"submit","data-testid":"submit-edit-group",style:{padding:"6px 12px",borderRadius:"4px",backgroundColor:"#4338ca",color:"#ffffff",border:"none",cursor:"pointer"},children:t.groupsView.save})]})]})})]})}function N(){let r=(0,h.useLoaderData)(),i=(0,h.useFetcher)(),t=r.labels??v,[d,m]=(0,f.useState)(r.groups[0]?.id??0),s=r.groups.find(a=>a.id===d),o=new Set(r.groupMembers.filter(a=>a.groupId===d).map(a=>a.userId)),n=(a,l)=>{l?i.submit({intent:"removeGroupMember",groupId:String(d),userId:String(a)},{method:"post"}):i.submit({intent:"addGroupMember",groupId:String(d),userId:String(a)},{method:"post"})};return(0,e.jsxs)("section",{"data-testid":"group-members-view-section",style:{display:"grid",gridTemplateColumns:"240px 1fr",gap:"1.2rem"},children:[(0,e.jsx)(U,{fetcher:i}),(0,e.jsxs)("div",{style:{backgroundColor:"#ffffff",padding:"1rem",borderRadius:"8px",border:"1px solid #e2e8f0"},children:[(0,e.jsx)("h4",{style:{margin:"0 0 0.8rem 0",fontSize:"0.9rem",color:"#475569"},children:t.groupMembersView.selectGroup}),(0,e.jsx)("div",{style:{display:"flex",flexDirection:"column",gap:"0.4rem"},children:r.groups.map(a=>{let l=a.id===d;return(0,e.jsx)("button",{type:"button",onClick:()=>m(a.id),"data-testid":`select-group-btn-${a.id}`,style:{textAlign:"left",padding:"8px 10px",borderRadius:"6px",border:l?"1px solid #6366f1":"1px solid #e2e8f0",backgroundColor:l?"#e0e7ff":"#ffffff",color:l?"#3730a3":"#0f172a",cursor:"pointer",fontWeight:l?600:400,fontSize:"0.85rem"},children:a.name},a.id)})})]}),(0,e.jsx)("div",{style:{backgroundColor:"#ffffff",padding:"1.2rem",borderRadius:"8px",border:"1px solid #e2e8f0"},children:s?(0,e.jsxs)(e.Fragment,{children:[(0,e.jsxs)("div",{style:{marginBottom:"1rem",borderBottom:"1px solid #e2e8f0",paddingBottom:"0.8rem"},children:[(0,e.jsxs)("h3",{style:{margin:0,fontSize:"1.1rem",color:"#0f172a"},children:[s.name," \u306E\u6240\u5C5E\u30E1\u30F3\u30D0\u30FC"]}),(0,e.jsxs)("span",{style:{fontSize:"0.8rem",color:"#64748b"},children:["\u30B0\u30EB\u30FC\u30D7\u30AD\u30FC: ",s.groupKey]})]}),(0,e.jsx)("div",{style:{display:"flex",flexDirection:"column",gap:"0.5rem"},children:r.users.map(a=>{let l=o.has(a.id);return(0,e.jsxs)("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",padding:"8px 12px",borderRadius:"6px",border:"1px solid #f1f5f9",backgroundColor:l?"#f0fdf4":"#ffffff"},"data-testid":`member-row-${a.id}`,children:[(0,e.jsxs)("div",{children:[(0,e.jsx)("span",{style:{fontWeight:600,fontSize:"0.88rem",color:"#0f172a",marginRight:"8px"},children:a.displayName}),(0,e.jsxs)("span",{style:{fontSize:"0.78rem",color:"#64748b"},children:["(",a.email,")"]})]}),(0,e.jsx)("button",{type:"button",onClick:()=>n(a.id,l),"data-testid":`toggle-member-btn-${a.id}`,style:{padding:"4px 12px",borderRadius:"4px",border:l?"1px solid #b91c1c":"1px solid #0284c7",backgroundColor:l?"#ffffff":"#0284c7",color:l?"#b91c1c":"#ffffff",fontSize:"0.78rem",fontWeight:600,cursor:"pointer"},children:l?t.groupMembersView.actionRemove:t.groupMembersView.actionAdd})]},a.id)})})]}):(0,e.jsx)("div",{style:{color:"#94a3b8",textAlign:"center",padding:"2rem"},children:t.groupMembersView.selectPrompt})})]})}function L(){let r=(0,h.useLoaderData)(),i=(0,h.useFetcher)(),t=r.labels??v,[d,m]=(0,f.useState)(""),[s,o]=(0,f.useState)("email"),[n,a]=(0,f.useState)(""),l=u=>{u.preventDefault(),d&&(i.submit({intent:"addAllowlistEntry",pattern:d,type:s,description:n},{method:"post"}),m(""),a(""))},x=u=>{i.submit({intent:"removeAllowlistEntry",entryId:String(u)},{method:"post"})};return(0,e.jsxs)("section",{"data-testid":"allowlist-view-section",style:{display:"flex",flexDirection:"column",gap:"1.2rem"},children:[(0,e.jsx)(U,{fetcher:i}),(0,e.jsxs)("form",{onSubmit:l,style:{backgroundColor:"#ffffff",padding:"1.2rem",borderRadius:"8px",border:"1px solid #e2e8f0",display:"flex",flexWrap:"wrap",gap:"0.8rem",alignItems:"flex-end"},children:[(0,e.jsxs)("div",{style:{flex:2,minWidth:"220px"},children:[(0,e.jsx)("label",{htmlFor:"allowlist-pattern-input-field",style:{display:"block",fontSize:"0.78rem",color:"#475569",marginBottom:"4px"},children:t.allowlistView.pattern}),(0,e.jsx)("input",{id:"allowlist-pattern-input-field",type:"text",value:d,onChange:u=>m(u.target.value),required:!0,"data-testid":"allowlist-pattern-input",style:{width:"100%",padding:"6px 10px",borderRadius:"6px",border:"1px solid #cbd5e1",fontSize:"0.85rem",boxSizing:"border-box"}})]}),(0,e.jsxs)("div",{style:{flex:1,minWidth:"140px"},children:[(0,e.jsx)("label",{htmlFor:"allowlist-type-select-field",style:{display:"block",fontSize:"0.78rem",color:"#475569",marginBottom:"4px"},children:t.allowlistView.type}),(0,e.jsxs)("select",{id:"allowlist-type-select-field",value:s,onChange:u=>o(u.target.value),"data-testid":"allowlist-type-select",style:{width:"100%",padding:"6px 10px",borderRadius:"6px",border:"1px solid #cbd5e1",fontSize:"0.85rem",boxSizing:"border-box"},children:[(0,e.jsx)("option",{value:"email",children:t.allowlistView.emailType}),(0,e.jsx)("option",{value:"domain",children:t.allowlistView.domainType})]})]}),(0,e.jsxs)("div",{style:{flex:2,minWidth:"200px"},children:[(0,e.jsx)("label",{htmlFor:"allowlist-desc-input-field",style:{display:"block",fontSize:"0.78rem",color:"#475569",marginBottom:"4px"},children:t.allowlistView.description}),(0,e.jsx)("input",{id:"allowlist-desc-input-field",type:"text",value:n,onChange:u=>a(u.target.value),"data-testid":"allowlist-desc-input",style:{width:"100%",padding:"6px 10px",borderRadius:"6px",border:"1px solid #cbd5e1",fontSize:"0.85rem",boxSizing:"border-box"}})]}),(0,e.jsx)("button",{type:"submit","data-testid":"submit-allowlist-add",style:{padding:"7px 16px",borderRadius:"6px",backgroundColor:"#047857",color:"#ffffff",border:"none",fontSize:"0.85rem",fontWeight:600,cursor:"pointer"},children:t.allowlistView.addEntry})]}),(0,e.jsx)("div",{style:{backgroundColor:"#ffffff",borderRadius:"8px",border:"1px solid #e2e8f0",overflow:"hidden"},children:(0,e.jsxs)("table",{style:{width:"100%",borderCollapse:"collapse",fontSize:"0.85rem",textAlign:"left"},children:[(0,e.jsx)("thead",{children:(0,e.jsxs)("tr",{style:{backgroundColor:"#f8fafc",borderBottom:"1px solid #e2e8f0",color:"#475569"},children:[(0,e.jsx)("th",{style:{padding:"10px 14px"},children:"ID"}),(0,e.jsx)("th",{style:{padding:"10px 14px"},children:t.allowlistView.pattern}),(0,e.jsx)("th",{style:{padding:"10px 14px"},children:t.allowlistView.type}),(0,e.jsx)("th",{style:{padding:"10px 14px"},children:t.allowlistView.description}),(0,e.jsx)("th",{style:{padding:"10px 14px",textAlign:"right"},children:t.allowlistView.actions})]})}),(0,e.jsxs)("tbody",{children:[r.allowlist.map(u=>(0,e.jsxs)("tr",{style:{borderBottom:"1px solid #f1f5f9"},"data-testid":`allowlist-row-${u.id}`,children:[(0,e.jsxs)("td",{style:{padding:"10px 14px",color:"#64748b"},children:["#",u.id]}),(0,e.jsx)("td",{style:{padding:"10px 14px",fontWeight:600,color:"#0f172a",fontFamily:"monospace"},children:u.pattern}),(0,e.jsx)("td",{style:{padding:"10px 14px"},children:(0,e.jsx)("span",{style:{fontSize:"0.75rem",padding:"2px 8px",borderRadius:"10px",backgroundColor:u.type==="email"?"#e0f2fe":"#fef3c7",color:u.type==="email"?"#0369a1":"#b45309",fontWeight:600},children:u.type==="email"?t.allowlistView.emailTypeShort:t.allowlistView.domainTypeShort})}),(0,e.jsx)("td",{style:{padding:"10px 14px",color:"#475569"},children:u.description||"-"}),(0,e.jsx)("td",{style:{padding:"10px 14px",textAlign:"right"},children:u.readOnly?(0,e.jsx)("span",{"data-testid":`readonly-allowlist-${u.id}`,style:{fontSize:"0.75rem",color:"#94a3b8"},children:t.allowlistView.readOnly}):(0,e.jsx)("button",{type:"button",onClick:()=>x(u.id),"data-testid":`remove-allowlist-btn-${u.id}`,style:{padding:"3px 8px",borderRadius:"4px",border:"1px solid #fee2e2",backgroundColor:"#fff5f5",color:"#b91c1c",fontSize:"0.78rem",cursor:"pointer"},children:"\u524A\u9664"})})]},u.id)),r.allowlist.length===0&&(0,e.jsx)("tr",{children:(0,e.jsx)("td",{colSpan:5,style:{padding:"2rem",textAlign:"center",color:"#94a3b8"},children:t.allowlistView.empty})})]})]})})]})}var J={users:z,groups:E,group_members:N,allowlist:L};function X({renderHeader:r}={}){let t=(0,h.useLoaderData)()?.segment??"users",d=J[t]??z;return(0,e.jsx)(P,{renderHeader:r,children:(0,e.jsx)(d,{})})}0&&(module.exports={AllowlistView,AuthUserAdminAppView,GroupMembersView,GroupsView,UserAdminShell,UsersView,createInMemoryUserAdminStore,createUserAdminApp,defaultUserAdminLabels,jaUserAdminLabels,resolveUserAdminLabels});
2
2
  //# sourceMappingURL=admin.js.map