@byline/admin 2.3.3 → 2.4.1

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 (177) hide show
  1. package/dist/abilities.js +5 -24
  2. package/dist/index.js +8 -30
  3. package/dist/lib/assert-admin-actor.js +13 -74
  4. package/dist/lib/create-command.js +6 -16
  5. package/dist/modules/admin-account/commands.js +35 -24
  6. package/dist/modules/admin-account/components/change-password.d.ts +8 -0
  7. package/dist/modules/admin-account/components/change-password.js +192 -0
  8. package/dist/modules/admin-account/components/change-password.module.js +8 -0
  9. package/dist/modules/admin-account/components/change-password_module.css +27 -0
  10. package/dist/modules/admin-account/components/container.d.ts +29 -0
  11. package/dist/modules/admin-account/components/container.js +298 -0
  12. package/dist/modules/admin-account/components/container.module.js +28 -0
  13. package/dist/modules/admin-account/components/container_module.css +106 -0
  14. package/dist/modules/admin-account/components/update.d.ts +8 -0
  15. package/dist/modules/admin-account/components/update.js +207 -0
  16. package/dist/modules/admin-account/components/update.module.js +8 -0
  17. package/dist/modules/admin-account/components/update_module.css +27 -0
  18. package/dist/modules/admin-account/errors.js +14 -45
  19. package/dist/modules/admin-account/index.js +4 -34
  20. package/dist/modules/admin-account/schemas.js +25 -59
  21. package/dist/modules/admin-account/service.js +56 -61
  22. package/dist/modules/admin-permissions/abilities.js +6 -24
  23. package/dist/modules/admin-permissions/commands.js +42 -28
  24. package/dist/modules/admin-permissions/components/inspector.d.ts +4 -0
  25. package/dist/modules/admin-permissions/components/inspector.js +284 -0
  26. package/dist/modules/admin-permissions/components/inspector.module.js +56 -0
  27. package/dist/modules/admin-permissions/components/inspector_module.css +238 -0
  28. package/dist/modules/admin-permissions/dto.js +3 -16
  29. package/dist/modules/admin-permissions/errors.js +14 -27
  30. package/dist/modules/admin-permissions/index.js +6 -26
  31. package/dist/modules/admin-permissions/repository.js +1 -8
  32. package/dist/modules/admin-permissions/schemas.js +33 -70
  33. package/dist/modules/admin-permissions/service.js +88 -92
  34. package/dist/modules/admin-roles/abilities.js +8 -30
  35. package/dist/modules/admin-roles/commands.js +89 -55
  36. package/dist/modules/admin-roles/components/create.d.ts +7 -0
  37. package/dist/modules/admin-roles/components/create.js +177 -0
  38. package/dist/modules/admin-roles/components/create.module.js +8 -0
  39. package/dist/modules/admin-roles/components/create_module.css +27 -0
  40. package/dist/modules/admin-roles/components/permissions.d.ts +10 -0
  41. package/dist/modules/admin-roles/components/permissions.js +303 -0
  42. package/dist/modules/admin-roles/components/permissions.module.js +44 -0
  43. package/dist/modules/admin-roles/components/permissions_module.css +192 -0
  44. package/dist/modules/admin-roles/components/update.d.ts +8 -0
  45. package/dist/modules/admin-roles/components/update.js +166 -0
  46. package/dist/modules/admin-roles/components/update.module.js +8 -0
  47. package/dist/modules/admin-roles/components/update_module.css +27 -0
  48. package/dist/modules/admin-roles/dto.js +3 -16
  49. package/dist/modules/admin-roles/errors.js +16 -40
  50. package/dist/modules/admin-roles/index.js +6 -26
  51. package/dist/modules/admin-roles/repository.js +1 -8
  52. package/dist/modules/admin-roles/schemas.js +41 -71
  53. package/dist/modules/admin-roles/service.js +79 -82
  54. package/dist/modules/admin-users/abilities.js +9 -38
  55. package/dist/modules/admin-users/commands.js +92 -50
  56. package/dist/modules/admin-users/components/create.d.ts +8 -0
  57. package/dist/modules/admin-users/components/create.js +268 -0
  58. package/dist/modules/admin-users/components/create.module.js +10 -0
  59. package/dist/modules/admin-users/components/create_module.css +45 -0
  60. package/dist/modules/admin-users/components/roles.d.ts +11 -0
  61. package/dist/modules/admin-users/components/roles.js +148 -0
  62. package/dist/modules/admin-users/components/roles.module.js +18 -0
  63. package/dist/modules/admin-users/components/roles_module.css +75 -0
  64. package/dist/modules/admin-users/components/set-password.d.ts +8 -0
  65. package/dist/modules/admin-users/components/set-password.js +170 -0
  66. package/dist/modules/admin-users/components/set-password.module.js +9 -0
  67. package/dist/modules/admin-users/components/set-password_module.css +31 -0
  68. package/dist/modules/admin-users/components/update.d.ts +8 -0
  69. package/dist/modules/admin-users/components/update.js +254 -0
  70. package/dist/modules/admin-users/components/update.module.js +9 -0
  71. package/dist/modules/admin-users/components/update_module.css +34 -0
  72. package/dist/modules/admin-users/dto.js +3 -18
  73. package/dist/modules/admin-users/errors.js +17 -43
  74. package/dist/modules/admin-users/index.js +7 -27
  75. package/dist/modules/admin-users/repository.js +1 -8
  76. package/dist/modules/admin-users/schemas.js +44 -75
  77. package/dist/modules/admin-users/seed-super-admin.js +9 -34
  78. package/dist/modules/admin-users/service.js +76 -91
  79. package/dist/modules/auth/components/sign-in-form.d.ts +12 -0
  80. package/dist/modules/auth/components/sign-in-form.js +115 -0
  81. package/dist/modules/auth/components/sign-in-form.module.js +12 -0
  82. package/dist/modules/auth/components/sign-in-form_module.css +41 -0
  83. package/dist/modules/auth/index.js +3 -24
  84. package/dist/modules/auth/jwt-session-provider.js +179 -149
  85. package/dist/modules/auth/password.js +11 -53
  86. package/dist/modules/auth/phc.js +21 -54
  87. package/dist/modules/auth/refresh-tokens-repository.js +1 -8
  88. package/dist/modules/auth/resolve-actor.js +6 -28
  89. package/dist/services/admin-services-context.d.ts +16 -0
  90. package/dist/services/admin-services-context.js +13 -0
  91. package/dist/services/admin-services-types.d.ts +129 -0
  92. package/dist/services/admin-services-types.js +1 -0
  93. package/dist/store.js +1 -8
  94. package/dist/vendor/noble-argon2/_blake.js +277 -45
  95. package/dist/vendor/noble-argon2/_md.js +81 -136
  96. package/dist/vendor/noble-argon2/_u64.js +65 -67
  97. package/dist/vendor/noble-argon2/argon2.js +181 -342
  98. package/dist/vendor/noble-argon2/blake2.js +252 -327
  99. package/dist/vendor/noble-argon2/utils.js +110 -490
  100. package/dist/vendor/noble-argon2/utils.js.LICENSE.txt +1 -0
  101. package/package.json +89 -10
  102. package/src/abilities.ts +32 -0
  103. package/src/declarations.d.ts +4 -0
  104. package/src/index.ts +39 -0
  105. package/src/lib/assert-admin-actor.ts +90 -0
  106. package/src/lib/create-command.ts +109 -0
  107. package/src/modules/admin-account/commands.ts +76 -0
  108. package/src/modules/admin-account/components/change-password.module.css +40 -0
  109. package/src/modules/admin-account/components/change-password.tsx +232 -0
  110. package/src/modules/admin-account/components/container.module.css +158 -0
  111. package/src/modules/admin-account/components/container.tsx +229 -0
  112. package/src/modules/admin-account/components/update.module.css +40 -0
  113. package/src/modules/admin-account/components/update.tsx +263 -0
  114. package/src/modules/admin-account/errors.ts +75 -0
  115. package/src/modules/admin-account/index.ts +60 -0
  116. package/src/modules/admin-account/schemas.ts +84 -0
  117. package/src/modules/admin-account/service.ts +92 -0
  118. package/src/modules/admin-permissions/abilities.ts +46 -0
  119. package/src/modules/admin-permissions/commands.ts +103 -0
  120. package/src/modules/admin-permissions/components/inspector.module.css +326 -0
  121. package/src/modules/admin-permissions/components/inspector.tsx +298 -0
  122. package/src/modules/admin-permissions/dto.ts +28 -0
  123. package/src/modules/admin-permissions/errors.ts +57 -0
  124. package/src/modules/admin-permissions/index.ts +72 -0
  125. package/src/modules/admin-permissions/repository.ts +49 -0
  126. package/src/modules/admin-permissions/schemas.ts +128 -0
  127. package/src/modules/admin-permissions/service.ts +137 -0
  128. package/src/modules/admin-roles/abilities.ts +62 -0
  129. package/src/modules/admin-roles/commands.ts +161 -0
  130. package/src/modules/admin-roles/components/create.module.css +40 -0
  131. package/src/modules/admin-roles/components/create.tsx +218 -0
  132. package/src/modules/admin-roles/components/permissions.module.css +279 -0
  133. package/src/modules/admin-roles/components/permissions.tsx +396 -0
  134. package/src/modules/admin-roles/components/update.module.css +40 -0
  135. package/src/modules/admin-roles/components/update.tsx +218 -0
  136. package/src/modules/admin-roles/dto.ts +30 -0
  137. package/src/modules/admin-roles/errors.ts +76 -0
  138. package/src/modules/admin-roles/index.ts +81 -0
  139. package/src/modules/admin-roles/repository.ts +96 -0
  140. package/src/modules/admin-roles/schemas.ts +139 -0
  141. package/src/modules/admin-roles/service.ts +136 -0
  142. package/src/modules/admin-users/abilities.ts +76 -0
  143. package/src/modules/admin-users/commands.ts +157 -0
  144. package/src/modules/admin-users/components/create.module.css +63 -0
  145. package/src/modules/admin-users/components/create.tsx +323 -0
  146. package/src/modules/admin-users/components/roles.module.css +119 -0
  147. package/src/modules/admin-users/components/roles.tsx +172 -0
  148. package/src/modules/admin-users/components/set-password.module.css +46 -0
  149. package/src/modules/admin-users/components/set-password.tsx +199 -0
  150. package/src/modules/admin-users/components/update.module.css +49 -0
  151. package/src/modules/admin-users/components/update.tsx +328 -0
  152. package/src/modules/admin-users/dto.ts +39 -0
  153. package/src/modules/admin-users/errors.ts +84 -0
  154. package/src/modules/admin-users/index.ts +91 -0
  155. package/src/modules/admin-users/repository.ts +161 -0
  156. package/src/modules/admin-users/schemas.ts +168 -0
  157. package/src/modules/admin-users/seed-super-admin.ts +102 -0
  158. package/src/modules/admin-users/service.ts +166 -0
  159. package/src/modules/auth/components/sign-in-form.module.css +62 -0
  160. package/src/modules/auth/components/sign-in-form.tsx +132 -0
  161. package/src/modules/auth/index.ts +31 -0
  162. package/src/modules/auth/jwt-session-provider.ts +301 -0
  163. package/src/modules/auth/password.ts +94 -0
  164. package/src/modules/auth/phc.ts +121 -0
  165. package/src/modules/auth/refresh-tokens-repository.ts +74 -0
  166. package/src/modules/auth/resolve-actor.ts +42 -0
  167. package/src/services/admin-services-context.tsx +52 -0
  168. package/src/services/admin-services-types.ts +177 -0
  169. package/src/store.ts +32 -0
  170. package/src/vendor/noble-argon2/LICENSE +21 -0
  171. package/src/vendor/noble-argon2/README.md +87 -0
  172. package/src/vendor/noble-argon2/_blake.ts +58 -0
  173. package/src/vendor/noble-argon2/_md.ts +223 -0
  174. package/src/vendor/noble-argon2/_u64.ts +118 -0
  175. package/src/vendor/noble-argon2/argon2.ts +668 -0
  176. package/src/vendor/noble-argon2/blake2.ts +583 -0
  177. package/src/vendor/noble-argon2/utils.ts +849 -0
@@ -0,0 +1,136 @@
1
+ /**
2
+ * This Source Code is subject to the terms of the Mozilla Public
3
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
4
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
5
+ *
6
+ * Copyright (c) Infonomic Company Limited
7
+ */
8
+
9
+ import { toAdminRole } from './dto.js'
10
+ import {
11
+ ERR_ADMIN_ROLE_MACHINE_NAME_IN_USE,
12
+ ERR_ADMIN_ROLE_NOT_FOUND,
13
+ ERR_ADMIN_ROLE_USER_NOT_FOUND,
14
+ } from './errors.js'
15
+ import type { AdminStore } from '../../store.js'
16
+ import type {
17
+ AdminRoleListResponse,
18
+ AdminRoleResponse,
19
+ CreateAdminRoleRequest,
20
+ DeleteAdminRoleRequest,
21
+ GetAdminRoleRequest,
22
+ GetRolesForUserRequest,
23
+ ReorderAdminRolesRequest,
24
+ SetRolesForUserRequest,
25
+ UpdateAdminRoleRequest,
26
+ UserRolesResponse,
27
+ } from './schemas.js'
28
+
29
+ /**
30
+ * Business logic for administering admin roles.
31
+ *
32
+ * Owns four concerns the repository deliberately avoids:
33
+ *
34
+ * 1. **Domain invariants.** `machine_name` uniqueness pre-check on
35
+ * create — the unique index is the ultimate backstop, but the
36
+ * pre-check produces a clean domain error rather than a raw
37
+ * Postgres code.
38
+ * 2. **DTO shaping.** Raw rows are shaped through `toAdminRole` so
39
+ * the response contract is owned in one place.
40
+ * 3. **Optimistic-concurrency plumbing.** The repo gates writes on
41
+ * `expectedVid`; the service threads it from the validated request
42
+ * shape. Version conflicts surface as
43
+ * `AdminRolesError(VERSION_CONFLICT)` from the adapter; the service
44
+ * does not catch them.
45
+ * 4. **Cross-table validation.** The user-roles editor validates the
46
+ * user and every referenced role exists before mutating the join
47
+ * table — clean errors over raw FK violations.
48
+ *
49
+ * Roles do not need a self-target invariant the way users do
50
+ * (no "self-delete" concept), so role-CRUD service methods are
51
+ * actor-agnostic and the ability check at the command boundary is the
52
+ * only authorisation.
53
+ */
54
+ export class AdminRolesService {
55
+ readonly #store: AdminStore
56
+
57
+ constructor(deps: { store: AdminStore }) {
58
+ this.#store = deps.store
59
+ }
60
+
61
+ async listRoles(): Promise<AdminRoleListResponse> {
62
+ const rows = await this.#store.adminRoles.list()
63
+ return { roles: rows.map(toAdminRole) }
64
+ }
65
+
66
+ async getRole(request: GetAdminRoleRequest): Promise<AdminRoleResponse> {
67
+ const row = await this.#store.adminRoles.getById(request.id)
68
+ if (!row) throw ERR_ADMIN_ROLE_NOT_FOUND()
69
+ return toAdminRole(row)
70
+ }
71
+
72
+ async createRole(request: CreateAdminRoleRequest): Promise<AdminRoleResponse> {
73
+ // Pre-check for machine_name conflict so the common case returns a
74
+ // domain-specific error rather than the raw unique-violation code.
75
+ const existing = await this.#store.adminRoles.getByMachineName(request.machine_name)
76
+ if (existing) throw ERR_ADMIN_ROLE_MACHINE_NAME_IN_USE()
77
+
78
+ const row = await this.#store.adminRoles.create({
79
+ name: request.name,
80
+ machine_name: request.machine_name,
81
+ description: request.description ?? null,
82
+ order: request.order,
83
+ })
84
+ return toAdminRole(row)
85
+ }
86
+
87
+ async updateRole(request: UpdateAdminRoleRequest): Promise<AdminRoleResponse> {
88
+ const current = await this.#store.adminRoles.getById(request.id)
89
+ if (!current) throw ERR_ADMIN_ROLE_NOT_FOUND()
90
+ const row = await this.#store.adminRoles.update(request.id, request.vid, request.patch)
91
+ return toAdminRole(row)
92
+ }
93
+
94
+ async deleteRole(request: DeleteAdminRoleRequest): Promise<void> {
95
+ const exists = await this.#store.adminRoles.getById(request.id)
96
+ if (!exists) throw ERR_ADMIN_ROLE_NOT_FOUND()
97
+ await this.#store.adminRoles.delete(request.id, request.vid)
98
+ }
99
+
100
+ async reorderRoles(request: ReorderAdminRolesRequest): Promise<void> {
101
+ await this.#store.adminRoles.reorder(request.ids)
102
+ }
103
+
104
+ async getRolesForUser(request: GetRolesForUserRequest): Promise<UserRolesResponse> {
105
+ const user = await this.#store.adminUsers.getById(request.userId)
106
+ if (!user) throw ERR_ADMIN_ROLE_USER_NOT_FOUND()
107
+ const rows = await this.#store.adminRoles.listRolesForUser(request.userId)
108
+ return { userId: request.userId, roles: rows.map(toAdminRole) }
109
+ }
110
+
111
+ async setRolesForUser(request: SetRolesForUserRequest): Promise<UserRolesResponse> {
112
+ const user = await this.#store.adminUsers.getById(request.userId)
113
+ if (!user) throw ERR_ADMIN_ROLE_USER_NOT_FOUND()
114
+
115
+ // Validate every referenced role exists. N round-trips, but role
116
+ // assignment payloads are small by design (typically < 10 roles)
117
+ // and surfacing a clean `notFound` beats a raw FK violation.
118
+ if (request.roleIds.length > 0) {
119
+ const found = await Promise.all(
120
+ request.roleIds.map((id) => this.#store.adminRoles.getById(id))
121
+ )
122
+ const missing = request.roleIds.filter((_, i) => found[i] == null)
123
+ if (missing.length > 0) {
124
+ throw ERR_ADMIN_ROLE_NOT_FOUND({
125
+ message: `One or more referenced roles do not exist: ${missing.join(', ')}`,
126
+ })
127
+ }
128
+ }
129
+
130
+ await this.#store.adminRoles.setRolesForUser(request.userId, request.roleIds)
131
+ // Return the freshly stored set, shaped — saves the editor a second
132
+ // round-trip and guards against any normalisation the repo might apply.
133
+ const stored = await this.#store.adminRoles.listRolesForUser(request.userId)
134
+ return { userId: request.userId, roles: stored.map(toAdminRole) }
135
+ }
136
+ }
@@ -0,0 +1,76 @@
1
+ /**
2
+ * This Source Code is subject to the terms of the Mozilla Public
3
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
4
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
5
+ *
6
+ * Copyright (c) Infonomic Company Limited
7
+ */
8
+
9
+ import type { AbilityRegistry } from '@byline/auth'
10
+
11
+ /**
12
+ * Ability keys for the admin-users module.
13
+ *
14
+ * Dot-notation rather than Modulus' colon-notation — keeps one consistent
15
+ * hierarchy across the whole platform alongside `collections.<path>.<verb>`
16
+ * from core.
17
+ *
18
+ * `changePassword` is split out from `update` deliberately: setting
19
+ * someone else's password is a higher-trust operation than editing their
20
+ * profile fields, and the role editor UI benefits from naming it
21
+ * explicitly. A role can grant `update` without implicitly granting
22
+ * `changePassword`.
23
+ *
24
+ * Self-service (changing *own* password, email, etc.) does **not** use
25
+ * any of these keys. That flow lives in the separate `account` module
26
+ * where the actor is the target by definition; the `admin.users.*` keys
27
+ * are strictly for administering other admin users.
28
+ */
29
+ export const ADMIN_USERS_ABILITIES = {
30
+ read: 'admin.users.read',
31
+ create: 'admin.users.create',
32
+ update: 'admin.users.update',
33
+ delete: 'admin.users.delete',
34
+ changePassword: 'admin.users.changePassword',
35
+ } as const
36
+
37
+ export type AdminUsersAbilityKey =
38
+ (typeof ADMIN_USERS_ABILITIES)[keyof typeof ADMIN_USERS_ABILITIES]
39
+
40
+ /**
41
+ * Register every admin-users ability with the framework's `AbilityRegistry`.
42
+ * Called from `registerAdminAbilities(registry)` at package level, which
43
+ * the webapp wires into `initBylineCore()`.
44
+ */
45
+ export function registerAdminUsersAbilities(registry: AbilityRegistry): void {
46
+ registry.register({
47
+ key: ADMIN_USERS_ABILITIES.read,
48
+ label: 'Read admin users',
49
+ group: 'admin.users',
50
+ source: 'admin',
51
+ })
52
+ registry.register({
53
+ key: ADMIN_USERS_ABILITIES.create,
54
+ label: 'Create admin users',
55
+ group: 'admin.users',
56
+ source: 'admin',
57
+ })
58
+ registry.register({
59
+ key: ADMIN_USERS_ABILITIES.update,
60
+ label: 'Update admin users',
61
+ group: 'admin.users',
62
+ source: 'admin',
63
+ })
64
+ registry.register({
65
+ key: ADMIN_USERS_ABILITIES.delete,
66
+ label: 'Delete admin users',
67
+ group: 'admin.users',
68
+ source: 'admin',
69
+ })
70
+ registry.register({
71
+ key: ADMIN_USERS_ABILITIES.changePassword,
72
+ label: "Change an admin user's password",
73
+ group: 'admin.users',
74
+ source: 'admin',
75
+ })
76
+ }
@@ -0,0 +1,157 @@
1
+ /**
2
+ * This Source Code is subject to the terms of the Mozilla Public
3
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
4
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
5
+ *
6
+ * Copyright (c) Infonomic Company Limited
7
+ */
8
+
9
+ import { type Command, createCommand } from '../../lib/create-command.js'
10
+ import { ADMIN_USERS_ABILITIES } from './abilities.js'
11
+ import {
12
+ adminUserListResponseSchema,
13
+ adminUserResponseSchema,
14
+ createAdminUserRequestSchema,
15
+ deleteAdminUserRequestSchema,
16
+ disableAdminUserRequestSchema,
17
+ enableAdminUserRequestSchema,
18
+ getAdminUserRequestSchema,
19
+ listAdminUsersRequestSchema,
20
+ okResponseSchema,
21
+ setAdminUserPasswordRequestSchema,
22
+ updateAdminUserRequestSchema,
23
+ } from './schemas.js'
24
+ import { AdminUsersService } from './service.js'
25
+ import type { AdminStore } from '../../store.js'
26
+ import type {
27
+ AdminUserListResponse,
28
+ AdminUserResponse,
29
+ CreateAdminUserRequest,
30
+ DeleteAdminUserRequest,
31
+ DisableAdminUserRequest,
32
+ EnableAdminUserRequest,
33
+ GetAdminUserRequest,
34
+ ListAdminUsersRequest,
35
+ OkResponse,
36
+ SetAdminUserPasswordRequest,
37
+ UpdateAdminUserRequest,
38
+ } from './schemas.js'
39
+
40
+ /**
41
+ * Transport-agnostic commands for the admin-users module.
42
+ *
43
+ * Each command is built through `createCommand`, which folds the four
44
+ * standard steps (Zod-validate input → assert admin actor + ability →
45
+ * call the service → Zod-validate output) into a single declaration.
46
+ * The wrapper preserves the historical `(context, input, deps)` call
47
+ * signature so server fns keep working without change.
48
+ *
49
+ * The `deps` argument holds the `AdminStore`. The webapp wraps these in
50
+ * server fns that supply `deps` from the application's singleton store;
51
+ * scripts and tests construct their own store and pass it in directly.
52
+ */
53
+
54
+ export interface AdminUsersCommandDeps {
55
+ store: AdminStore
56
+ }
57
+
58
+ function serviceOf(deps: AdminUsersCommandDeps): AdminUsersService {
59
+ return new AdminUsersService({ repo: deps.store.adminUsers })
60
+ }
61
+
62
+ export const listAdminUsersCommand: Command<
63
+ ListAdminUsersRequest,
64
+ AdminUserListResponse,
65
+ AdminUsersCommandDeps
66
+ > = createCommand({
67
+ method: 'listAdminUsers',
68
+ auth: { ability: ADMIN_USERS_ABILITIES.read },
69
+ schemas: { input: listAdminUsersRequestSchema, output: adminUserListResponseSchema },
70
+ handler: ({ input, deps }) => serviceOf(deps).listUsers(input),
71
+ })
72
+
73
+ export const getAdminUserCommand: Command<
74
+ GetAdminUserRequest,
75
+ AdminUserResponse,
76
+ AdminUsersCommandDeps
77
+ > = createCommand({
78
+ method: 'getAdminUser',
79
+ auth: { ability: ADMIN_USERS_ABILITIES.read },
80
+ schemas: { input: getAdminUserRequestSchema, output: adminUserResponseSchema },
81
+ handler: ({ input, deps }) => serviceOf(deps).getUser(input),
82
+ })
83
+
84
+ export const createAdminUserCommand: Command<
85
+ CreateAdminUserRequest,
86
+ AdminUserResponse,
87
+ AdminUsersCommandDeps
88
+ > = createCommand({
89
+ method: 'createAdminUser',
90
+ auth: { ability: ADMIN_USERS_ABILITIES.create },
91
+ schemas: { input: createAdminUserRequestSchema, output: adminUserResponseSchema },
92
+ handler: ({ input, deps }) => serviceOf(deps).createUser(input),
93
+ })
94
+
95
+ export const updateAdminUserCommand: Command<
96
+ UpdateAdminUserRequest,
97
+ AdminUserResponse,
98
+ AdminUsersCommandDeps
99
+ > = createCommand({
100
+ method: 'updateAdminUser',
101
+ auth: { ability: ADMIN_USERS_ABILITIES.update },
102
+ schemas: { input: updateAdminUserRequestSchema, output: adminUserResponseSchema },
103
+ handler: ({ input, deps }) => serviceOf(deps).updateUser(input),
104
+ })
105
+
106
+ export const setAdminUserPasswordCommand: Command<
107
+ SetAdminUserPasswordRequest,
108
+ AdminUserResponse,
109
+ AdminUsersCommandDeps
110
+ > = createCommand({
111
+ method: 'setAdminUserPassword',
112
+ auth: { ability: ADMIN_USERS_ABILITIES.changePassword },
113
+ schemas: { input: setAdminUserPasswordRequestSchema, output: adminUserResponseSchema },
114
+ handler: ({ input, deps }) => serviceOf(deps).setPassword(input),
115
+ })
116
+
117
+ export const enableAdminUserCommand: Command<
118
+ EnableAdminUserRequest,
119
+ OkResponse,
120
+ AdminUsersCommandDeps
121
+ > = createCommand({
122
+ method: 'enableAdminUser',
123
+ auth: { ability: ADMIN_USERS_ABILITIES.update },
124
+ schemas: { input: enableAdminUserRequestSchema, output: okResponseSchema },
125
+ handler: async ({ input, deps }) => {
126
+ await serviceOf(deps).enableUser(input)
127
+ return { ok: true } as const
128
+ },
129
+ })
130
+
131
+ export const disableAdminUserCommand: Command<
132
+ DisableAdminUserRequest,
133
+ OkResponse,
134
+ AdminUsersCommandDeps
135
+ > = createCommand({
136
+ method: 'disableAdminUser',
137
+ auth: { ability: ADMIN_USERS_ABILITIES.update },
138
+ schemas: { input: disableAdminUserRequestSchema, output: okResponseSchema },
139
+ handler: async ({ input, deps, actor }) => {
140
+ await serviceOf(deps).disableUser(actor, input)
141
+ return { ok: true } as const
142
+ },
143
+ })
144
+
145
+ export const deleteAdminUserCommand: Command<
146
+ DeleteAdminUserRequest,
147
+ OkResponse,
148
+ AdminUsersCommandDeps
149
+ > = createCommand({
150
+ method: 'deleteAdminUser',
151
+ auth: { ability: ADMIN_USERS_ABILITIES.delete },
152
+ schemas: { input: deleteAdminUserRequestSchema, output: okResponseSchema },
153
+ handler: async ({ input, deps, actor }) => {
154
+ await serviceOf(deps).deleteUser(actor, input)
155
+ return { ok: true } as const
156
+ },
157
+ })
@@ -0,0 +1,63 @@
1
+ /**
2
+ * CreateAdminUser — drawer form for creating a new admin user.
3
+ *
4
+ * Override handles:
5
+ * .byline-user-create-wrap — outer container
6
+ * .byline-user-create-form — vertical-stack form element
7
+ * .byline-user-create-grid — two-column name grid (collapses on mobile)
8
+ * .byline-user-create-flags — checkbox stack (enabled / verified / super)
9
+ * .byline-user-create-actions — Cancel/Save row
10
+ * .byline-user-create-action — buttons in the actions row
11
+ */
12
+
13
+ .wrap,
14
+ :global(.byline-user-create-wrap) {
15
+ display: flex;
16
+ flex-direction: column;
17
+ gap: var(--spacing-8);
18
+ padding: var(--spacing-4);
19
+ margin-top: var(--spacing-4);
20
+ }
21
+
22
+ .form,
23
+ :global(.byline-user-create-form) {
24
+ display: flex;
25
+ flex-direction: column;
26
+ gap: var(--spacing-16);
27
+ padding-top: var(--spacing-8);
28
+ }
29
+
30
+ .grid,
31
+ :global(.byline-user-create-grid) {
32
+ display: grid;
33
+ grid-template-columns: 1fr;
34
+ gap: var(--spacing-16);
35
+ }
36
+
37
+ @media (min-width: 40rem) {
38
+ .grid,
39
+ :global(.byline-user-create-grid) {
40
+ grid-template-columns: 1fr 1fr;
41
+ }
42
+ }
43
+
44
+ .flags,
45
+ :global(.byline-user-create-flags) {
46
+ display: flex;
47
+ flex-direction: column;
48
+ gap: var(--spacing-8);
49
+ }
50
+
51
+ .actions,
52
+ :global(.byline-user-create-actions) {
53
+ display: flex;
54
+ align-items: center;
55
+ justify-content: flex-end;
56
+ gap: var(--spacing-8);
57
+ margin-top: var(--spacing-16);
58
+ }
59
+
60
+ .action,
61
+ :global(.byline-user-create-action) {
62
+ min-width: 4rem;
63
+ }