@jini-ai/user-management 0.2.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.
Files changed (190) hide show
  1. package/CHANGELOG.md +77 -0
  2. package/LICENSE +201 -0
  3. package/README.md +104 -0
  4. package/dist/admin/adapters/http.d.ts +29 -0
  5. package/dist/admin/adapters/http.js +69 -0
  6. package/dist/admin/adapters/memory.d.ts +61 -0
  7. package/dist/admin/adapters/memory.js +217 -0
  8. package/dist/admin/auth.module.d.ts +30 -0
  9. package/dist/admin/auth.module.js +12 -0
  10. package/dist/admin/conformance/index.d.ts +56 -0
  11. package/dist/admin/conformance/index.js +156 -0
  12. package/dist/admin/controllers/auth.controller.d.ts +23 -0
  13. package/dist/admin/controllers/auth.controller.js +33 -0
  14. package/dist/admin/controllers/controller-store.d.ts +18 -0
  15. package/dist/admin/controllers/controller-store.js +23 -0
  16. package/dist/admin/controllers/members.controller.d.ts +33 -0
  17. package/dist/admin/controllers/members.controller.js +119 -0
  18. package/dist/admin/controllers/roles.controller.d.ts +47 -0
  19. package/dist/admin/controllers/roles.controller.js +282 -0
  20. package/dist/admin/controllers/users.controller.d.ts +53 -0
  21. package/dist/admin/controllers/users.controller.js +220 -0
  22. package/dist/admin/index.d.ts +21 -0
  23. package/dist/admin/index.js +15 -0
  24. package/dist/admin/members.module.d.ts +34 -0
  25. package/dist/admin/members.module.js +13 -0
  26. package/dist/admin/messages.en.d.ts +37 -0
  27. package/dist/admin/messages.en.js +21 -0
  28. package/dist/admin/models.d.ts +133 -0
  29. package/dist/admin/models.js +2 -0
  30. package/dist/admin/people.rules.d.ts +29 -0
  31. package/dist/admin/people.rules.js +51 -0
  32. package/dist/admin/ports.d.ts +187 -0
  33. package/dist/admin/ports.js +17 -0
  34. package/dist/admin/react/components/DestructiveDialog.d.ts +5 -0
  35. package/dist/admin/react/components/DestructiveDialog.js +6 -0
  36. package/dist/admin/react/components/MemberRow.d.ts +5 -0
  37. package/dist/admin/react/components/MemberRow.js +8 -0
  38. package/dist/admin/react/components/MembersConfirmation.d.ts +2 -0
  39. package/dist/admin/react/components/MembersConfirmation.js +8 -0
  40. package/dist/admin/react/components/PermissionPanel.d.ts +5 -0
  41. package/dist/admin/react/components/PermissionPanel.js +9 -0
  42. package/dist/admin/react/components/PolicyRow.d.ts +5 -0
  43. package/dist/admin/react/components/PolicyRow.js +11 -0
  44. package/dist/admin/react/components/RoleRow.d.ts +5 -0
  45. package/dist/admin/react/components/RoleRow.js +10 -0
  46. package/dist/admin/react/components/UserRow.d.ts +5 -0
  47. package/dist/admin/react/components/UserRow.js +8 -0
  48. package/dist/admin/react/components/UsersConfirmation.d.ts +3 -0
  49. package/dist/admin/react/components/UsersConfirmation.js +9 -0
  50. package/dist/admin/react/hooks/AuthBinding.hooks.d.ts +39 -0
  51. package/dist/admin/react/hooks/AuthBinding.hooks.js +21 -0
  52. package/dist/admin/react/hooks/LoginPage.hooks.d.ts +54 -0
  53. package/dist/admin/react/hooks/LoginPage.hooks.js +23 -0
  54. package/dist/admin/react/hooks/MembersBinding.hooks.d.ts +35 -0
  55. package/dist/admin/react/hooks/MembersBinding.hooks.js +21 -0
  56. package/dist/admin/react/hooks/MembersPage.hooks.d.ts +99 -0
  57. package/dist/admin/react/hooks/MembersPage.hooks.js +38 -0
  58. package/dist/admin/react/hooks/PeopleController.hooks.d.ts +18 -0
  59. package/dist/admin/react/hooks/PeopleController.hooks.js +20 -0
  60. package/dist/admin/react/hooks/PermissionPanel.hooks.d.ts +30 -0
  61. package/dist/admin/react/hooks/PermissionPanel.hooks.js +15 -0
  62. package/dist/admin/react/hooks/PoliciesTab.hooks.d.ts +47 -0
  63. package/dist/admin/react/hooks/PoliciesTab.hooks.js +26 -0
  64. package/dist/admin/react/hooks/RolesBinding.hooks.d.ts +39 -0
  65. package/dist/admin/react/hooks/RolesBinding.hooks.js +23 -0
  66. package/dist/admin/react/hooks/RolesController.hooks.d.ts +43 -0
  67. package/dist/admin/react/hooks/RolesController.hooks.js +25 -0
  68. package/dist/admin/react/hooks/RolesPage.hooks.d.ts +105 -0
  69. package/dist/admin/react/hooks/RolesPage.hooks.js +33 -0
  70. package/dist/admin/react/hooks/RolesTab.hooks.d.ts +35 -0
  71. package/dist/admin/react/hooks/RolesTab.hooks.js +19 -0
  72. package/dist/admin/react/hooks/UsersBinding.hooks.d.ts +36 -0
  73. package/dist/admin/react/hooks/UsersBinding.hooks.js +21 -0
  74. package/dist/admin/react/hooks/UsersPage.hooks.d.ts +106 -0
  75. package/dist/admin/react/hooks/UsersPage.hooks.js +22 -0
  76. package/dist/admin/react/hooks/UsersTab.hooks.d.ts +101 -0
  77. package/dist/admin/react/hooks/UsersTab.hooks.js +53 -0
  78. package/dist/admin/react/index.d.ts +203 -0
  79. package/dist/admin/react/index.js +32 -0
  80. package/dist/admin/react/pages/LoginPage.d.ts +3 -0
  81. package/dist/admin/react/pages/LoginPage.js +13 -0
  82. package/dist/admin/react/pages/MembersPage.d.ts +3 -0
  83. package/dist/admin/react/pages/MembersPage.js +19 -0
  84. package/dist/admin/react/pages/RolesPage.d.ts +3 -0
  85. package/dist/admin/react/pages/RolesPage.js +19 -0
  86. package/dist/admin/react/pages/UsersPage.d.ts +3 -0
  87. package/dist/admin/react/pages/UsersPage.js +19 -0
  88. package/dist/admin/react/tabs/AuthTab.d.ts +4 -0
  89. package/dist/admin/react/tabs/AuthTab.js +8 -0
  90. package/dist/admin/react/tabs/MembersTab.d.ts +4 -0
  91. package/dist/admin/react/tabs/MembersTab.js +9 -0
  92. package/dist/admin/react/tabs/PoliciesTab.d.ts +4 -0
  93. package/dist/admin/react/tabs/PoliciesTab.js +9 -0
  94. package/dist/admin/react/tabs/RolesTab.d.ts +4 -0
  95. package/dist/admin/react/tabs/RolesTab.js +9 -0
  96. package/dist/admin/react/tabs/UsersTab.d.ts +4 -0
  97. package/dist/admin/react/tabs/UsersTab.js +9 -0
  98. package/dist/admin/roles.module.d.ts +48 -0
  99. package/dist/admin/roles.module.js +15 -0
  100. package/dist/admin/rules.d.ts +32 -0
  101. package/dist/admin/rules.js +32 -0
  102. package/dist/admin/users.module.d.ts +39 -0
  103. package/dist/admin/users.module.js +14 -0
  104. package/dist/core/builtin-permissions.d.ts +10 -0
  105. package/dist/core/builtin-permissions.js +402 -0
  106. package/dist/core/index.d.ts +6 -0
  107. package/dist/core/index.js +9 -0
  108. package/dist/core/permissions.d.ts +40 -0
  109. package/dist/core/permissions.js +52 -0
  110. package/dist/core/ports.d.ts +237 -0
  111. package/dist/core/ports.js +2 -0
  112. package/dist/core/runtime-ports.d.ts +8 -0
  113. package/dist/core/runtime-ports.js +2 -0
  114. package/dist/core/types.d.ts +224 -0
  115. package/dist/core/types.js +93 -0
  116. package/dist/react/auth/Login.d.ts +9 -0
  117. package/dist/react/auth/Login.js +8 -0
  118. package/dist/react/auth/hooks/use-login.hooks.d.ts +22 -0
  119. package/dist/react/auth/hooks/use-login.hooks.js +24 -0
  120. package/dist/react/errors.d.ts +10 -0
  121. package/dist/react/errors.js +13 -0
  122. package/dist/react/index.d.ts +18 -0
  123. package/dist/react/index.js +9 -0
  124. package/dist/react/members/Members.d.ts +6 -0
  125. package/dist/react/members/Members.js +38 -0
  126. package/dist/react/members/hooks/use-members.hooks.d.ts +32 -0
  127. package/dist/react/members/hooks/use-members.hooks.js +120 -0
  128. package/dist/react/members/rules.d.ts +26 -0
  129. package/dist/react/members/rules.js +35 -0
  130. package/dist/react/models.d.ts +50 -0
  131. package/dist/react/models.js +2 -0
  132. package/dist/react/ports.d.ts +157 -0
  133. package/dist/react/ports.js +2 -0
  134. package/dist/react/roles/Roles.d.ts +100 -0
  135. package/dist/react/roles/Roles.hooks.d.ts +17 -0
  136. package/dist/react/roles/Roles.hooks.js +40 -0
  137. package/dist/react/roles/Roles.js +150 -0
  138. package/dist/react/roles/hooks/use-roles.hooks.d.ts +80 -0
  139. package/dist/react/roles/hooks/use-roles.hooks.js +303 -0
  140. package/dist/react/roles/rules.d.ts +35 -0
  141. package/dist/react/roles/rules.js +31 -0
  142. package/dist/react/roles/text.d.ts +27 -0
  143. package/dist/react/roles/text.js +13 -0
  144. package/dist/react/testing.d.ts +51 -0
  145. package/dist/react/testing.js +275 -0
  146. package/dist/react/users/Users.d.ts +72 -0
  147. package/dist/react/users/Users.js +129 -0
  148. package/dist/react/users/hooks/use-reset-password-fields.hooks.d.ts +16 -0
  149. package/dist/react/users/hooks/use-reset-password-fields.hooks.js +21 -0
  150. package/dist/react/users/hooks/use-users.hooks.d.ts +77 -0
  151. package/dist/react/users/hooks/use-users.hooks.js +286 -0
  152. package/dist/react/users/rules.d.ts +33 -0
  153. package/dist/react/users/rules.js +61 -0
  154. package/dist/server/admin-crud-service.d.ts +295 -0
  155. package/dist/server/admin-crud-service.js +561 -0
  156. package/dist/server/agent-tool-input.d.ts +58 -0
  157. package/dist/server/agent-tool-input.js +158 -0
  158. package/dist/server/agent-tool-registrations.d.ts +51 -0
  159. package/dist/server/agent-tool-registrations.js +417 -0
  160. package/dist/server/agent-tools.d.ts +88 -0
  161. package/dist/server/agent-tools.js +229 -0
  162. package/dist/server/auth-service.d.ts +107 -0
  163. package/dist/server/auth-service.js +170 -0
  164. package/dist/server/authorize.d.ts +92 -0
  165. package/dist/server/authorize.js +96 -0
  166. package/dist/server/grant-service.d.ts +219 -0
  167. package/dist/server/grant-service.js +419 -0
  168. package/dist/server/hasher.d.ts +64 -0
  169. package/dist/server/hasher.js +53 -0
  170. package/dist/server/identity-transaction.d.ts +9 -0
  171. package/dist/server/identity-transaction.js +8 -0
  172. package/dist/server/index.d.ts +18 -0
  173. package/dist/server/index.js +20 -0
  174. package/dist/server/messages.d.ts +7 -0
  175. package/dist/server/messages.js +5 -0
  176. package/dist/server/password-policy.d.ts +59 -0
  177. package/dist/server/password-policy.js +66 -0
  178. package/dist/server/permission-migrations.d.ts +84 -0
  179. package/dist/server/permission-migrations.js +77 -0
  180. package/dist/server/repo.memory-transactions.d.ts +16 -0
  181. package/dist/server/repo.memory-transactions.js +79 -0
  182. package/dist/server/repo.memory.d.ts +186 -0
  183. package/dist/server/repo.memory.js +230 -0
  184. package/dist/server/seed.d.ts +56 -0
  185. package/dist/server/seed.js +435 -0
  186. package/dist/server/session-tokens.d.ts +10 -0
  187. package/dist/server/session-tokens.js +12 -0
  188. package/dist/server/username.d.ts +14 -0
  189. package/dist/server/username.js +14 -0
  190. package/package.json +144 -0
@@ -0,0 +1,51 @@
1
+ import type { AdminUser, AdminIdentityUser, AdminRole, AdminPolicy, AdminPolicyPermission, AdminMember } from "./models.js";
2
+ import type { LoginPort, UsersPort, RolesPort, MembersPort } from "./ports.js";
3
+ export interface FakeLoginPortOptions {
4
+ user?: AdminUser | undefined;
5
+ loginError?: Error | undefined;
6
+ }
7
+ export declare function createFakeLoginPort(_required: Record<string, never>, options?: FakeLoginPortOptions): LoginPort;
8
+ export interface FakeUsersPortOptions {
9
+ users?: AdminIdentityUser[] | undefined;
10
+ roles?: AdminRole[] | undefined;
11
+ policies?: AdminPolicy[] | undefined;
12
+ meId?: string | undefined;
13
+ canManageUserTrash?: boolean | undefined;
14
+ createUserError?: Error | undefined;
15
+ updateUserError?: Error | undefined;
16
+ toggleStatusError?: Error | undefined;
17
+ resetPasswordError?: Error | undefined;
18
+ assignRoleError?: Error | undefined;
19
+ attachPolicyError?: Error | undefined;
20
+ deleteUserError?: Error | undefined;
21
+ }
22
+ export declare function createFakeUsersPort(_required: Record<string, never>, options?: FakeUsersPortOptions): UsersPort & {
23
+ readonly users: AdminIdentityUser[];
24
+ };
25
+ export interface FakeRolesPortOptions {
26
+ roles?: AdminRole[] | undefined;
27
+ policies?: AdminPolicy[] | undefined;
28
+ createRoleError?: Error | undefined;
29
+ updateRoleError?: Error | undefined;
30
+ deleteRoleError?: Error | undefined;
31
+ createPolicyError?: Error | undefined;
32
+ updatePolicyError?: Error | undefined;
33
+ deletePolicyError?: Error | undefined;
34
+ writePermissionError?: Error | undefined;
35
+ listPermissionsError?: Error | undefined;
36
+ removePermissionError?: Error | undefined;
37
+ initialPolicyPermissions?: AdminPolicyPermission[] | undefined;
38
+ }
39
+ export declare function createFakeRolesPort(_required: Record<string, never>, options?: FakeRolesPortOptions): RolesPort & {
40
+ readonly roles: AdminRole[];
41
+ readonly policies: AdminPolicy[];
42
+ readonly policyPermissions: AdminPolicyPermission[];
43
+ };
44
+ export interface FakeMembersPortOptions {
45
+ members?: AdminMember[] | undefined;
46
+ }
47
+ export declare function createFakeMembersPort(_required: Record<string, never>, options?: FakeMembersPortOptions): MembersPort & {
48
+ readonly members: AdminMember[];
49
+ readonly magicLinkRequests: string[];
50
+ };
51
+ //# sourceMappingURL=testing.d.ts.map
@@ -0,0 +1,275 @@
1
+ const FAKE_USER = { id: "fake-user-1", username: "fake-admin" };
2
+ export function createFakeLoginPort(_required, options = {}) {
3
+ return {
4
+ async login() {
5
+ if (options.loginError)
6
+ throw options.loginError;
7
+ return { user: options.user ?? FAKE_USER };
8
+ },
9
+ };
10
+ }
11
+ const FAKE_WORKSPACE_ID = "fake-ws";
12
+ function fakeUser(overrides = {}) {
13
+ return {
14
+ principalId: overrides.principalId ?? "fake-user-1",
15
+ workspaceId: FAKE_WORKSPACE_ID,
16
+ username: "fake",
17
+ status: "active",
18
+ createdAt: new Date(0).toISOString(),
19
+ roleIds: [],
20
+ policyIds: [],
21
+ ...overrides,
22
+ };
23
+ }
24
+ export function createFakeUsersPort(_required, options = {}) {
25
+ const users = [...(options.users ?? [])];
26
+ const roles = [...(options.roles ?? [])];
27
+ const policies = [...(options.policies ?? [])];
28
+ function requireUser(principalId) {
29
+ const found = users.find((u) => u.principalId === principalId);
30
+ if (!found)
31
+ throw new Error(`fake user not found: ${principalId}`);
32
+ return found;
33
+ }
34
+ function replaceUser(updated) {
35
+ const index = users.findIndex((u) => u.principalId === updated.principalId);
36
+ users[index] = updated;
37
+ return updated;
38
+ }
39
+ const meId = options.meId ?? users[0]?.principalId ?? "fake-user-1";
40
+ const canManageUserTrash = options.canManageUserTrash ?? true;
41
+ return {
42
+ users,
43
+ async me() {
44
+ return { user: { id: meId }, canManageUserTrash };
45
+ },
46
+ async listUsers() {
47
+ return { users: [...users] };
48
+ },
49
+ async listRoles() {
50
+ return { roles: [...roles] };
51
+ },
52
+ async listPolicies() {
53
+ return { policies: [...policies] };
54
+ },
55
+ async createUser(input, opts) {
56
+ if (options.createUserError)
57
+ throw options.createUserError;
58
+ const created = fakeUser({
59
+ principalId: `fake-user-${users.length + 1}`,
60
+ username: input.username,
61
+ email: opts?.email,
62
+ });
63
+ users.push(created);
64
+ return { user: created };
65
+ },
66
+ async updateUser(target, opts) {
67
+ if (options.updateUserError)
68
+ throw options.updateUserError;
69
+ const current = requireUser(target.principalId);
70
+ return { user: replaceUser({ ...current, ...opts }) };
71
+ },
72
+ async disableUser({ principalId }) {
73
+ if (options.toggleStatusError)
74
+ throw options.toggleStatusError;
75
+ const current = requireUser(principalId);
76
+ return { user: replaceUser({ ...current, status: "disabled" }) };
77
+ },
78
+ async enableUser({ principalId }) {
79
+ if (options.toggleStatusError)
80
+ throw options.toggleStatusError;
81
+ const current = requireUser(principalId);
82
+ return { user: replaceUser({ ...current, status: "active" }) };
83
+ },
84
+ async resetUserPassword() {
85
+ if (options.resetPasswordError)
86
+ throw options.resetPasswordError;
87
+ },
88
+ async assignRole(input) {
89
+ if (options.assignRoleError)
90
+ throw options.assignRoleError;
91
+ const current = requireUser(input.principalId);
92
+ replaceUser({ ...current, roleIds: [...current.roleIds, input.roleId] });
93
+ return { assignment: {} };
94
+ },
95
+ async attachPolicy(input) {
96
+ if (options.attachPolicyError)
97
+ throw options.attachPolicyError;
98
+ const current = requireUser(input.principalId);
99
+ replaceUser({ ...current, policyIds: [...current.policyIds, input.policyId] });
100
+ return { attachment: {} };
101
+ },
102
+ async deleteUser({ principalId }) {
103
+ if (options.deleteUserError)
104
+ throw options.deleteUserError;
105
+ requireUser(principalId);
106
+ const index = users.findIndex((u) => u.principalId === principalId);
107
+ users.splice(index, 1);
108
+ },
109
+ };
110
+ }
111
+ function fakeRole(overrides = {}) {
112
+ return {
113
+ id: overrides.id ?? "fake-role-1",
114
+ workspaceId: FAKE_WORKSPACE_ID,
115
+ name: "Fake role",
116
+ isBuiltin: false,
117
+ ...overrides,
118
+ };
119
+ }
120
+ function fakePolicy(overrides = {}) {
121
+ return {
122
+ id: overrides.id ?? "fake-policy-1",
123
+ workspaceId: FAKE_WORKSPACE_ID,
124
+ name: "Fake policy",
125
+ isBuiltin: false,
126
+ isFrozen: false,
127
+ ...overrides,
128
+ };
129
+ }
130
+ export function createFakeRolesPort(_required, options = {}) {
131
+ const roles = [...(options.roles ?? [])];
132
+ const policies = [...(options.policies ?? [])];
133
+ const policyPermissions = [...(options.initialPolicyPermissions ?? [])];
134
+ function requireRole(roleId) {
135
+ const found = roles.find((r) => r.id === roleId);
136
+ if (!found)
137
+ throw new Error(`fake role not found: ${roleId}`);
138
+ return found;
139
+ }
140
+ function requirePolicy(policyId) {
141
+ const found = policies.find((p) => p.id === policyId);
142
+ if (!found)
143
+ throw new Error(`fake policy not found: ${policyId}`);
144
+ return found;
145
+ }
146
+ return {
147
+ roles,
148
+ policies,
149
+ policyPermissions,
150
+ async listRoles() {
151
+ return { roles: [...roles] };
152
+ },
153
+ async listPolicies() {
154
+ return { policies: [...policies] };
155
+ },
156
+ async createRole({ name }) {
157
+ if (options.createRoleError)
158
+ throw options.createRoleError;
159
+ const created = fakeRole({ id: `fake-role-${roles.length + 1}`, name });
160
+ roles.push(created);
161
+ return { role: created };
162
+ },
163
+ async updateRole(input) {
164
+ if (options.updateRoleError)
165
+ throw options.updateRoleError;
166
+ const index = roles.findIndex((r) => r.id === input.roleId);
167
+ if (index < 0)
168
+ throw new Error(`fake role not found: ${input.roleId}`);
169
+ const updated = { ...roles[index], name: input.name };
170
+ roles[index] = updated;
171
+ return { role: updated };
172
+ },
173
+ async deleteRole({ roleId }) {
174
+ if (options.deleteRoleError)
175
+ throw options.deleteRoleError;
176
+ requireRole(roleId);
177
+ const index = roles.findIndex((r) => r.id === roleId);
178
+ roles.splice(index, 1);
179
+ },
180
+ async createPolicy(input, opts) {
181
+ if (options.createPolicyError)
182
+ throw options.createPolicyError;
183
+ const created = fakePolicy({
184
+ id: `fake-policy-${policies.length + 1}`,
185
+ name: input.name,
186
+ description: opts?.description,
187
+ });
188
+ policies.push(created);
189
+ return { policy: created };
190
+ },
191
+ async updatePolicy(target, opts) {
192
+ if (options.updatePolicyError)
193
+ throw options.updatePolicyError;
194
+ const index = policies.findIndex((p) => p.id === target.policyId);
195
+ if (index < 0)
196
+ throw new Error(`fake policy not found: ${target.policyId}`);
197
+ const current = policies[index];
198
+ // Optional updates must retain the required name when it is omitted or undefined.
199
+ const updated = { ...current, ...opts, name: opts?.name ?? current.name };
200
+ policies[index] = updated;
201
+ return { policy: updated };
202
+ },
203
+ async deletePolicy({ policyId }) {
204
+ if (options.deletePolicyError)
205
+ throw options.deletePolicyError;
206
+ requirePolicy(policyId);
207
+ const index = policies.findIndex((p) => p.id === policyId);
208
+ policies.splice(index, 1);
209
+ },
210
+ async writePolicyPermission(input, opts) {
211
+ if (options.writePermissionError)
212
+ throw options.writePermissionError;
213
+ requirePolicy(input.policyId);
214
+ const created = {
215
+ id: `fake-perm-${policyPermissions.length + 1}`,
216
+ workspaceId: FAKE_WORKSPACE_ID,
217
+ policyId: input.policyId,
218
+ permission: input.permission,
219
+ resourceType: opts?.resourceType ?? null,
220
+ constraintJson: null,
221
+ };
222
+ policyPermissions.push(created);
223
+ return { policyPermission: created };
224
+ },
225
+ async listPolicyPermissions({ policyId }) {
226
+ if (options.listPermissionsError)
227
+ throw options.listPermissionsError;
228
+ requirePolicy(policyId);
229
+ return { policyPermissions: policyPermissions.filter((row) => row.policyId === policyId) };
230
+ },
231
+ async removePolicyPermission(input) {
232
+ if (options.removePermissionError)
233
+ throw options.removePermissionError;
234
+ requirePolicy(input.policyId);
235
+ const index = policyPermissions.findIndex((row) => row.id === input.policyPermissionId && row.policyId === input.policyId);
236
+ if (index < 0) {
237
+ throw new Error(`policy permission '${input.policyPermissionId}' was not found on policy '${input.policyId}'`);
238
+ }
239
+ policyPermissions.splice(index, 1);
240
+ },
241
+ };
242
+ }
243
+ export function createFakeMembersPort(_required, options = {}) {
244
+ const members = [...(options.members ?? [])];
245
+ const magicLinkRequests = [];
246
+ function findOrThrow(id) {
247
+ const member = members.find((m) => m.id === id);
248
+ if (!member)
249
+ throw new Error(`fake member not found: ${id}`);
250
+ return member;
251
+ }
252
+ return {
253
+ members,
254
+ magicLinkRequests,
255
+ async listMembers() {
256
+ return { members: [...members] };
257
+ },
258
+ async getMember({ id }) {
259
+ return { member: findOrThrow(id) };
260
+ },
261
+ async disableMember({ id }) {
262
+ const index = members.findIndex((m) => m.id === id);
263
+ if (index < 0)
264
+ throw new Error(`fake member not found: ${id}`);
265
+ const updated = { ...members[index], status: "disabled" };
266
+ members[index] = updated;
267
+ return { member: updated };
268
+ },
269
+ async requestMemberMagicLink({ email }) {
270
+ magicLinkRequests.push(email);
271
+ return { delivered: true };
272
+ },
273
+ };
274
+ }
275
+ //# sourceMappingURL=testing.js.map
@@ -0,0 +1,72 @@
1
+ import type { Translate } from "@jini-ai/ui/panel-kit";
2
+ import { type Dispatch, type SetStateAction } from "react";
3
+ import type { AdminIdentityUser, AdminPolicy, AdminRole } from "../models.js";
4
+ import { useUsers, type UsersDependencies, type UsersOptions } from "./hooks/use-users.hooks.js";
5
+ export interface UsersProps extends UsersDependencies, UsersOptions {
6
+ useUsersHook?: typeof useUsers | undefined;
7
+ openOwnPasswordReset?: boolean | undefined;
8
+ }
9
+ export interface GrantOption {
10
+ id: string;
11
+ name: string;
12
+ isBuiltin: boolean;
13
+ }
14
+ export interface GrantSelectController {
15
+ options: GrantOption[];
16
+ pendingId: string;
17
+ setPendingId: Dispatch<SetStateAction<string>>;
18
+ submit: (required: {
19
+ principalId: string;
20
+ }) => Promise<void>;
21
+ }
22
+ export interface UserManageController {
23
+ error: string | null;
24
+ saving: boolean;
25
+ email: {
26
+ value: string;
27
+ set: Dispatch<SetStateAction<string>>;
28
+ saving: boolean;
29
+ save: (required: {
30
+ principalId: string;
31
+ }) => Promise<void>;
32
+ };
33
+ roleGrant: GrantSelectController;
34
+ policyGrant: GrantSelectController;
35
+ }
36
+ export interface UserManagePanelProps {
37
+ principalId: string;
38
+ manage: UserManageController;
39
+ t: (key: string) => string;
40
+ }
41
+ export declare function UserManagePanel({ principalId, manage, t }: UserManagePanelProps): import("react").JSX.Element;
42
+ export interface UserRowActionsController {
43
+ expandedId: string | null;
44
+ toggleExpanded: (user: AdminIdentityUser) => void;
45
+ savingId: string | null;
46
+ requestDisable: (user: AdminIdentityUser) => void;
47
+ toggleStatus: (user: AdminIdentityUser) => Promise<void>;
48
+ openResetPassword: (user: AdminIdentityUser) => void;
49
+ canDelete: boolean;
50
+ requestDelete: (user: AdminIdentityUser) => void;
51
+ }
52
+ export interface UserRowProps {
53
+ user: AdminIdentityUser;
54
+ roleById: ReadonlyMap<string, AdminRole>;
55
+ policyById: ReadonlyMap<string, AdminPolicy>;
56
+ actions: UserRowActionsController;
57
+ manage: UserManageController;
58
+ agentBase: string;
59
+ t: (key: string) => string;
60
+ translate: Translate;
61
+ }
62
+ export interface UsersTableProps {
63
+ users: AdminIdentityUser[];
64
+ roles: AdminRole[];
65
+ policies: AdminPolicy[];
66
+ actions: UserRowActionsController;
67
+ manage: UserManageController;
68
+ t: (key: string) => string;
69
+ translate: Translate;
70
+ }
71
+ export declare function Users({ useUsersHook, port, translate: injectedTranslate, queryScope, openOwnPasswordReset, onOwnPasswordResetClosed }: UsersProps): import("react").JSX.Element;
72
+ //# sourceMappingURL=Users.d.ts.map
@@ -0,0 +1,129 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { Fragment } from "react";
3
+ import { RowMenu, ConfirmDialog } from "@jini-ai/admin/react";
4
+ import { agentHandle } from "@jini-ai/agentic";
5
+ import { buildAgentListHandles } from "@jini-ai/ui/panel-kit";
6
+ import { formatGrantLabel, userRowMenuItems } from "./rules.js";
7
+ import { useUsers } from "./hooks/use-users.hooks.js";
8
+ import { InfoTip } from "@jini-ai/ui/admin-widgets";
9
+ import { useResetPasswordFields } from "./hooks/use-reset-password-fields.hooks.js";
10
+ function NewUserForm({ username, setUsername, email, setEmail, password, setPassword, saving, formError, onCreate, t }) {
11
+ return (_jsxs("form", { onSubmit: onCreate, className: "notice integrations-form form-measure", children: [formError ? _jsx("span", { className: "save-error", children: formError }) : null, _jsxs("label", { children: [t("Username"), _jsx("input", { value: username, onChange: (e) => setUsername(e.target.value), required: true, ...agentHandle({ handle: "users-new-username" }, { role: "field", label: t("The new user's username") }) })] }), _jsxs("label", { children: [t("Email (optional)"), _jsx("input", { type: "email", value: email, onChange: (e) => setEmail(e.target.value), ...agentHandle({ handle: "users-new-email" }, { role: "field", label: t("The new user's email address") }) })] }), _jsxs("label", { children: [t("Password"), _jsx("input", { type: "password", autoComplete: "new-password", value: password, onChange: (e) => setPassword(e.target.value), required: true, minLength: 1, ...agentHandle({ handle: "users-new-password" }, {
12
+ role: "field",
13
+ label: t("The new user's password — a credential field, so only a human can fill it"),
14
+ }) })] }), _jsx("button", { type: "submit", disabled: saving, ...agentHandle({ handle: "users-new-submit" }, { role: "button", label: t("Create this operator account") }), children: saving ? t("Creating…") : t("Create user") })] }));
15
+ }
16
+ function GrantSelect({ principalId, label, placeholder, submitLabel, grant, saving, agentBase, t }) {
17
+ return (_jsxs("label", { children: [label, _jsxs("span", { className: "editor-actions", children: [_jsxs("select", { value: grant.pendingId, onChange: (e) => grant.setPendingId(e.target.value), ...agentHandle({ handle: `${agentBase}-select` }, {
18
+ role: "field",
19
+ label: t(`${label} — set with page.select_option, not click`),
20
+ }), children: [_jsx("option", { value: "", children: placeholder }), grant.options.map((option) => (_jsxs("option", { value: option.id, children: [option.name, option.isBuiltin ? ` ${t("(built-in)")}` : ""] }, option.id)))] }), _jsx("button", { type: "button", disabled: !grant.pendingId || saving, onClick: () => grant.submit({ principalId }), ...agentHandle({ handle: `${agentBase}-submit` }, { role: "button", label: t(`${submitLabel} the selected option to this user`) }), children: saving ? t("Saving…") : submitLabel })] })] }));
21
+ }
22
+ export function UserManagePanel({ principalId, manage, t }) {
23
+ return (_jsx("tr", { children: _jsx("td", { colSpan: 6, children: _jsxs("div", { className: "notice integrations-form", children: [manage.error ? _jsx("span", { className: "save-error", children: manage.error }) : null, _jsxs("label", { children: [t("Email"), _jsxs("span", { className: "editor-actions", children: [_jsx("input", { type: "email", value: manage.email.value, onChange: (e) => manage.email.set(e.target.value), placeholder: t("(none)"), ...agentHandle({ handle: "user-manage-email" }, { role: "field", label: t("This user's email address") }) }), _jsx("button", { type: "button", disabled: manage.email.saving, onClick: () => manage.email.save({ principalId }), ...agentHandle({ handle: "user-manage-email-save" }, { role: "button", label: t("Save this user's email address") }), children: manage.email.saving ? t("Saving…") : t("Save email") })] })] }), _jsx(GrantSelect, { principalId: principalId, label: t("Assign role"), placeholder: t("Select a role…"), submitLabel: t("Assign"), grant: manage.roleGrant, saving: manage.saving, agentBase: "user-manage-role", t: t }), _jsx(GrantSelect, { principalId: principalId, label: t("Attach policy"), placeholder: t("Select a policy…"), submitLabel: t("Attach"), grant: manage.policyGrant, saving: manage.saving, agentBase: "user-manage-policy", t: t })] }) }) }));
24
+ }
25
+ function UserRow({ user, roleById, policyById, actions, manage, agentBase, t, translate }) {
26
+ const roleLabel = formatGrantLabel({ ids: user.roleIds, byId: roleById });
27
+ const policyLabel = formatGrantLabel({ ids: user.policyIds, byId: policyById });
28
+ return (_jsxs(_Fragment, { children: [_jsxs("tr", { children: [_jsx("td", { children: _jsx("button", { type: "button", className: "link-button", onClick: () => actions.toggleExpanded(user), "aria-expanded": actions.expandedId === user.principalId, ...agentHandle({ handle: `${agentBase}-manage` }, {
29
+ role: "button",
30
+ label: t("Open this user's Manage panel — edit email, assign a role, attach a policy"),
31
+ }), children: user.username }) }), _jsx("td", { children: user.email ?? _jsx("span", { className: "muted-cell", children: "\u2014" }) }), _jsx("td", { children: _jsx("span", { className: `status status-${user.status}`, children: t(user.status) }) }), _jsx("td", { children: roleLabel !== null ? t(roleLabel) : _jsx("span", { className: "muted-cell", children: t("none") }) }), _jsx("td", { children: policyLabel !== null ? policyLabel : _jsx("span", { className: "muted-cell", children: t("none") }) }), _jsx("td", { children: _jsx(RowMenu, { triggerLabel: `${t("Actions for user")} "${user.username}"`, agentHandle: `${agentBase}-menu`, items: userRowMenuItems({
32
+ user,
33
+ toggleSaving: actions.savingId === user.principalId,
34
+ handlers: {
35
+ onRequestDisable: actions.requestDisable,
36
+ onEnable: (u) => void actions.toggleStatus(u),
37
+ onManage: actions.toggleExpanded,
38
+ onResetPassword: actions.openResetPassword,
39
+ onRequestDelete: actions.requestDelete,
40
+ },
41
+ translate,
42
+ canDelete: actions.canDelete,
43
+ }) }) })] }), actions.expandedId === user.principalId ? (_jsx(UserManagePanel, { principalId: user.principalId, manage: manage, t: t })) : null] }));
44
+ }
45
+ function UsersTable({ users, roles, policies, actions, manage, t, translate }) {
46
+ if (users.length === 0) {
47
+ return (_jsx("div", { className: "card", children: _jsxs("div", { className: "empty-state", children: [_jsx("p", { children: t("No users yet.") }), _jsx("p", { className: "page-description", children: t("Create your first operator account to get started.") })] }) }));
48
+ }
49
+ const roleById = new Map(roles.map((role) => [role.id, role]));
50
+ const policyById = new Map(policies.map((policy) => [policy.id, policy]));
51
+ const rowHandles = buildAgentListHandles({ prefix: "users-row", ids: users.map((user) => user.principalId) });
52
+ return (_jsx("div", { className: "table-scroll", children: _jsxs("table", { className: "list-table", children: [_jsx("thead", { children: _jsxs("tr", { children: [_jsx("th", { children: t("Username") }), _jsx("th", { children: t("Email") }), _jsx("th", { children: t("Status") }), _jsx("th", { children: t("Roles") }), _jsx("th", { children: t("Policies") }), _jsx("th", { children: t("More") })] }) }), _jsx("tbody", { children: users.map((user, index) => (_jsx(Fragment, { children: _jsx(UserRow, { user: user, roleById: roleById, policyById: policyById, actions: actions, manage: manage, agentBase: rowHandles[index], t: t, translate: translate }) }, user.principalId))) })] }) }));
53
+ }
54
+ function UserDisableDialog({ confirmingDisable, setConfirmingDisable, toggleSavingId, confirmDisable, t }) {
55
+ return (_jsx(ConfirmDialog, { cancelLabel: t("Cancel"), open: confirmingDisable !== null, agentHandle: "users-disable", title: t("Disable this user?"), body: confirmingDisable ? (_jsxs("p", { children: [t("Disable"), " \"", confirmingDisable.username, "\"? ", t("They will not be able to sign in until re-enabled.")] })) : null, confirmLabel: t("Disable"), tone: "warning", pending: confirmingDisable !== null && toggleSavingId === confirmingDisable.principalId, onConfirm: confirmDisable, onCancel: () => setConfirmingDisable(null) }));
56
+ }
57
+ function UserDeleteDialog({ confirmingDelete, setConfirmingDelete, deleteSaving, confirmDelete, t }) {
58
+ return (_jsx(ConfirmDialog, { cancelLabel: t("Cancel"), open: confirmingDelete !== null, agentHandle: "users-delete", title: t("Delete this user?"), body: confirmingDelete ? (_jsxs("p", { children: [t("Delete"), " \"", confirmingDelete.username, "\"?", " ", t("They will be signed out and moved to the Trash. You can restore them there; they are deleted permanently after 60 days.")] })) : null, confirmLabel: t("Move to trash"), tone: "danger", pending: deleteSaving, onConfirm: confirmDelete, onCancel: () => setConfirmingDelete(null) }));
59
+ }
60
+ function EyeIcon() {
61
+ return (_jsxs("svg", { viewBox: "0 0 18 18", fill: "none", stroke: "currentColor", strokeWidth: 1.5, "aria-hidden": "true", children: [_jsx("path", { d: "M1.5 9S4.5 4 9 4s7.5 5 7.5 5-3 5-7.5 5-7.5-5-7.5-5Z", strokeLinejoin: "round" }), _jsx("circle", { cx: "9", cy: "9", r: "2" })] }));
62
+ }
63
+ function EyeOffIcon() {
64
+ return (_jsxs("svg", { viewBox: "0 0 18 18", fill: "none", stroke: "currentColor", strokeWidth: 1.5, "aria-hidden": "true", children: [_jsx("path", { d: "M1.5 9S4.5 4 9 4s7.5 5 7.5 5-3 5-7.5 5-7.5-5-7.5-5Z", strokeLinejoin: "round" }), _jsx("circle", { cx: "9", cy: "9", r: "2" }), _jsx("path", { d: "M3 3 15 15", strokeLinecap: "round" })] }));
65
+ }
66
+ function RevealablePasswordField({ id, label, value, onChange, visible, onToggleVisible, agentBase, t }) {
67
+ const toggleLabel = visible ? t("Hide password") : t("Show password");
68
+ return (_jsxs("div", { className: "field", children: [_jsx("label", { className: "field-label", htmlFor: id, children: label }), _jsxs("span", { className: "editor-actions", children: [_jsx("input", { id: id, type: visible ? "text" : "password", autoComplete: "new-password", value: value, onChange: (e) => onChange(e.target.value), style: { flex: "1 1 auto", minWidth: 0 }, ...agentHandle({ handle: agentBase }, {
69
+ role: "field",
70
+ label: t(`${label} — a credential field, so only a human can fill it`),
71
+ }) }), _jsx("button", { type: "button", className: "link-button", "aria-label": toggleLabel, "aria-pressed": visible, title: toggleLabel, onClick: onToggleVisible, ...agentHandle({ handle: `${agentBase}-reveal` }, { role: "button", label: t(`Show or hide the ${label.toLowerCase()} field's characters`) }), children: _jsx("span", { style: { display: "inline-flex", width: 16, height: 16 }, children: visible ? _jsx(EyeOffIcon, {}) : _jsx(EyeIcon, {}) }) })] })] }));
72
+ }
73
+ function resolveResetPasswordFieldsHook(override) {
74
+ return override ?? useResetPasswordFields;
75
+ }
76
+ function UserResetPasswordDialog({ resetPasswordFor, setResetPasswordFor, newPassword, setNewPassword, passwordError, setPasswordError, passwordSaving, confirmResetPassword, t, useFields: useFieldsProp, }) {
77
+ const useFields = resolveResetPasswordFieldsHook(useFieldsProp);
78
+ const fields = useFields({ resetPasswordFor, newPassword });
79
+ function handleConfirm() {
80
+ if (fields.mismatch)
81
+ return;
82
+ void confirmResetPassword();
83
+ }
84
+ return (_jsx(ConfirmDialog, { cancelLabel: t("Cancel"), open: resetPasswordFor !== null, agentHandle: "users-reset-password", title: t("Reset password?"), body: resetPasswordFor ? (_jsxs(_Fragment, { children: [_jsxs("p", { children: [t("Set a new password for"), " \"", resetPasswordFor.username, "\".", " ", t("Every active session for this user will be signed out.")] }), _jsx(RevealablePasswordField, { id: "users-reset-password-input", label: t("New password"), value: newPassword, onChange: setNewPassword, visible: fields.showNewPassword, onToggleVisible: fields.toggleShowNewPassword, agentBase: "users-reset-password", t: t }), _jsx(RevealablePasswordField, { id: "users-reset-password-confirm-input", label: t("Confirm new password"), value: fields.confirmPassword, onChange: fields.setConfirmPassword, visible: fields.showConfirmPassword, onToggleVisible: fields.toggleShowConfirmPassword, agentBase: "users-reset-password-retype", t: t }), fields.mismatch ? (_jsx("p", { className: "save-error", role: "alert", children: t("Passwords do not match.") })) : passwordError ? (_jsx("p", { className: "save-error", role: "alert", children: passwordError })) : null] })) : null, confirmLabel: t("Reset password"), tone: "warning", pending: passwordSaving, onConfirm: handleConfirm, onCancel: () => {
85
+ setResetPasswordFor(null);
86
+ setNewPassword("");
87
+ setPasswordError(null);
88
+ } }));
89
+ }
90
+ function UsersPageHeader({ formOpen, setFormOpen, t }) {
91
+ return (_jsxs("div", { className: "page-header", ...agentHandle({ handle: "users-header" }, { role: "region", label: t("Users header — page title and the New user button") }), children: [_jsxs("div", { className: "page-header-text", children: [_jsx("p", { className: "page-kicker", children: t("People") }), _jsxs("h1", { className: "page-title", children: [t("Users"), _jsx(InfoTip, { label: t("No 'forgot password' email yet. If someone is locked out, the owner can reset their password here."), agentHandle: "users-reset-password-info" })] }), _jsx("p", { className: "page-description", children: t("Operator accounts with access to this admin — assign roles and policies, or disable access.") })] }), _jsx("div", { className: "page-actions", children: _jsx("button", { className: formOpen ? "btn-secondary" : undefined, onClick: () => setFormOpen((v) => !v), ...agentHandle({ handle: "users-new-toggle" }, { role: "button", label: t("Open or close the new-user form") }), children: formOpen ? t("Cancel") : t("New user") }) })] }));
92
+ }
93
+ function UsersNotices({ toggleError, notice }) {
94
+ return (_jsxs(_Fragment, { children: [toggleError ? _jsx("div", { className: "notice error", children: toggleError }) : null, notice ? _jsx("div", { className: "notice", children: notice }) : null] }));
95
+ }
96
+ export function Users({ useUsersHook = useUsers, port, translate: injectedTranslate, queryScope, openOwnPasswordReset, onOwnPasswordResetClosed }) {
97
+ const { users, roles, policies, error, formOpen, setFormOpen, username, setUsername, email, setEmail, password, setPassword, saving, formError, onCreate, expandedId, toggleExpanded, pendingRoleId, setPendingRoleId, pendingPolicyId, setPendingPolicyId, grantSaving, grantError, onAssignRole, onAttachPolicy, editEmail, setEditEmail, emailSaving, onSaveEmail, toggleSavingId, toggleError, notice, confirmingDisable, setConfirmingDisable, requestDisable, confirmDisable, onToggleStatus, resetPasswordFor, setResetPasswordFor, newPassword, setNewPassword, passwordSaving, passwordError, setPasswordError, openResetPassword, confirmResetPassword, canManageUserTrash, confirmingDelete, setConfirmingDelete, requestDelete, deleteSaving, confirmDelete, t, translate, } = useUsersHook({ port, translate: injectedTranslate, queryScope }, { openOwnPasswordReset, onOwnPasswordResetClosed });
98
+ if (error)
99
+ return _jsx("div", { className: "notice error", children: error });
100
+ if (!users || !roles || !policies)
101
+ return _jsx("div", { className: "notice", children: t("Loading users…") });
102
+ return (_jsxs("div", { className: "page", children: [_jsx(UsersPageHeader, { formOpen: formOpen, setFormOpen: setFormOpen, t: t }), formOpen ? (_jsx(NewUserForm, { username: username, setUsername: setUsername, email: email, setEmail: setEmail, password: password, setPassword: setPassword, saving: saving, formError: formError, onCreate: onCreate, t: t })) : null, _jsx(UsersNotices, { toggleError: toggleError, notice: notice }), _jsx(UsersTable, { users: users, roles: roles, policies: policies, actions: {
103
+ expandedId,
104
+ toggleExpanded,
105
+ savingId: toggleSavingId,
106
+ requestDisable,
107
+ toggleStatus: onToggleStatus,
108
+ openResetPassword,
109
+ canDelete: canManageUserTrash,
110
+ requestDelete,
111
+ }, manage: {
112
+ error: grantError,
113
+ saving: grantSaving,
114
+ email: { value: editEmail, set: setEditEmail, saving: emailSaving, save: onSaveEmail },
115
+ roleGrant: {
116
+ options: roles,
117
+ pendingId: pendingRoleId,
118
+ setPendingId: setPendingRoleId,
119
+ submit: onAssignRole,
120
+ },
121
+ policyGrant: {
122
+ options: policies,
123
+ pendingId: pendingPolicyId,
124
+ setPendingId: setPendingPolicyId,
125
+ submit: onAttachPolicy,
126
+ },
127
+ }, t: t, translate: translate }), _jsx(UserDisableDialog, { confirmingDisable: confirmingDisable, setConfirmingDisable: setConfirmingDisable, toggleSavingId: toggleSavingId, confirmDisable: confirmDisable, t: t }), _jsx(UserDeleteDialog, { confirmingDelete: confirmingDelete, setConfirmingDelete: setConfirmingDelete, deleteSaving: deleteSaving, confirmDelete: confirmDelete, t: t }), _jsx(UserResetPasswordDialog, { resetPasswordFor: resetPasswordFor, setResetPasswordFor: setResetPasswordFor, newPassword: newPassword, setNewPassword: setNewPassword, passwordError: passwordError, setPasswordError: setPasswordError, passwordSaving: passwordSaving, confirmResetPassword: confirmResetPassword, t: t })] }));
128
+ }
129
+ //# sourceMappingURL=Users.js.map
@@ -0,0 +1,16 @@
1
+ import type { AdminIdentityUser } from "../../models.js";
2
+ export interface ResetPasswordFieldsInput {
3
+ resetPasswordFor: AdminIdentityUser | null;
4
+ newPassword: string;
5
+ }
6
+ export interface ResetPasswordFieldsController {
7
+ confirmPassword: string;
8
+ setConfirmPassword: (value: string) => void;
9
+ mismatch: boolean;
10
+ showNewPassword: boolean;
11
+ toggleShowNewPassword: () => void;
12
+ showConfirmPassword: boolean;
13
+ toggleShowConfirmPassword: () => void;
14
+ }
15
+ export declare function useResetPasswordFields({ resetPasswordFor, newPassword }: ResetPasswordFieldsInput): ResetPasswordFieldsController;
16
+ //# sourceMappingURL=use-reset-password-fields.hooks.d.ts.map
@@ -0,0 +1,21 @@
1
+ import { useEffect, useState } from "react";
2
+ export function useResetPasswordFields({ resetPasswordFor, newPassword }) {
3
+ const [confirmPassword, setConfirmPassword] = useState("");
4
+ const [showNewPassword, setShowNewPassword] = useState(false);
5
+ const [showConfirmPassword, setShowConfirmPassword] = useState(false);
6
+ useEffect(() => {
7
+ setConfirmPassword("");
8
+ setShowNewPassword(false);
9
+ setShowConfirmPassword(false);
10
+ }, [resetPasswordFor?.principalId]);
11
+ return {
12
+ confirmPassword,
13
+ setConfirmPassword,
14
+ mismatch: newPassword !== confirmPassword,
15
+ showNewPassword,
16
+ toggleShowNewPassword: () => setShowNewPassword((visible) => !visible),
17
+ showConfirmPassword,
18
+ toggleShowConfirmPassword: () => setShowConfirmPassword((visible) => !visible),
19
+ };
20
+ }
21
+ //# sourceMappingURL=use-reset-password-fields.hooks.js.map
@@ -0,0 +1,77 @@
1
+ import type { Translate } from "@jini-ai/ui/panel-kit";
2
+ import { type Dispatch, type FormEvent, type SetStateAction } from "react";
3
+ import { type AdminIdentityUser, type AdminPolicy, type AdminRole } from "../../models.js";
4
+ import type { UsersPort } from "../../ports.js";
5
+ export interface UsersController {
6
+ users: AdminIdentityUser[] | null;
7
+ roles: AdminRole[] | null;
8
+ policies: AdminPolicy[] | null;
9
+ error: string | null;
10
+ formOpen: boolean;
11
+ setFormOpen: Dispatch<SetStateAction<boolean>>;
12
+ username: string;
13
+ setUsername: Dispatch<SetStateAction<string>>;
14
+ email: string;
15
+ setEmail: Dispatch<SetStateAction<string>>;
16
+ password: string;
17
+ setPassword: Dispatch<SetStateAction<string>>;
18
+ saving: boolean;
19
+ formError: string | null;
20
+ onCreate: (e: FormEvent) => Promise<void>;
21
+ expandedId: string | null;
22
+ toggleExpanded: (user: AdminIdentityUser) => void;
23
+ pendingRoleId: string;
24
+ setPendingRoleId: Dispatch<SetStateAction<string>>;
25
+ pendingPolicyId: string;
26
+ setPendingPolicyId: Dispatch<SetStateAction<string>>;
27
+ grantSaving: boolean;
28
+ grantError: string | null;
29
+ onAssignRole: (required: {
30
+ principalId: string;
31
+ }) => Promise<void>;
32
+ onAttachPolicy: (required: {
33
+ principalId: string;
34
+ }) => Promise<void>;
35
+ editEmail: string;
36
+ setEditEmail: Dispatch<SetStateAction<string>>;
37
+ emailSaving: boolean;
38
+ onSaveEmail: (required: {
39
+ principalId: string;
40
+ }) => Promise<void>;
41
+ toggleSavingId: string | null;
42
+ toggleError: string | null;
43
+ notice: string | null;
44
+ confirmingDisable: AdminIdentityUser | null;
45
+ setConfirmingDisable: Dispatch<SetStateAction<AdminIdentityUser | null>>;
46
+ requestDisable: (user: AdminIdentityUser) => void;
47
+ confirmDisable: () => Promise<void>;
48
+ onToggleStatus: (user: AdminIdentityUser) => Promise<void>;
49
+ resetPasswordFor: AdminIdentityUser | null;
50
+ setResetPasswordFor: Dispatch<SetStateAction<AdminIdentityUser | null>>;
51
+ newPassword: string;
52
+ setNewPassword: Dispatch<SetStateAction<string>>;
53
+ passwordSaving: boolean;
54
+ passwordError: string | null;
55
+ setPasswordError: Dispatch<SetStateAction<string | null>>;
56
+ openResetPassword: (user: AdminIdentityUser) => void;
57
+ confirmResetPassword: () => Promise<void>;
58
+ canManageUserTrash: boolean;
59
+ confirmingDelete: AdminIdentityUser | null;
60
+ setConfirmingDelete: Dispatch<SetStateAction<AdminIdentityUser | null>>;
61
+ requestDelete: (user: AdminIdentityUser) => void;
62
+ deleteSaving: boolean;
63
+ confirmDelete: () => Promise<void>;
64
+ t: (key: string) => string;
65
+ translate: Translate;
66
+ }
67
+ export interface UsersDependencies {
68
+ port: UsersPort;
69
+ translate: Translate;
70
+ queryScope: string;
71
+ }
72
+ export interface UsersOptions {
73
+ openOwnPasswordReset?: boolean | undefined;
74
+ onOwnPasswordResetClosed?: (() => void) | undefined;
75
+ }
76
+ export declare function useUsers({ port, translate, queryScope }: UsersDependencies, { openOwnPasswordReset, onOwnPasswordResetClosed }?: UsersOptions): UsersController;
77
+ //# sourceMappingURL=use-users.hooks.d.ts.map