@jskit-ai/users-core 0.1.4

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 (148) hide show
  1. package/package.descriptor.mjs +464 -0
  2. package/package.json +35 -0
  3. package/src/server/UsersCoreServiceProvider.js +74 -0
  4. package/src/server/accountNotifications/accountNotificationsActions.js +39 -0
  5. package/src/server/accountNotifications/accountNotificationsService.js +41 -0
  6. package/src/server/accountNotifications/bootAccountNotificationsRoutes.js +41 -0
  7. package/src/server/accountNotifications/registerAccountNotifications.js +39 -0
  8. package/src/server/accountPreferences/accountPreferencesActions.js +39 -0
  9. package/src/server/accountPreferences/accountPreferencesService.js +41 -0
  10. package/src/server/accountPreferences/bootAccountPreferencesRoutes.js +41 -0
  11. package/src/server/accountPreferences/registerAccountPreferences.js +39 -0
  12. package/src/server/accountProfile/accountProfileActions.js +137 -0
  13. package/src/server/accountProfile/accountProfileService.js +124 -0
  14. package/src/server/accountProfile/avatarService.js +141 -0
  15. package/src/server/accountProfile/avatarStorageService.js +132 -0
  16. package/src/server/accountProfile/bootAccountProfileRoutes.js +166 -0
  17. package/src/server/accountProfile/registerAccountProfile.js +62 -0
  18. package/src/server/accountProfile/registerAvatarMultipartSupport.js +43 -0
  19. package/src/server/accountSecurity/accountSecurityActions.js +144 -0
  20. package/src/server/accountSecurity/accountSecurityService.js +103 -0
  21. package/src/server/accountSecurity/bootAccountSecurityRoutes.js +183 -0
  22. package/src/server/accountSecurity/registerAccountSecurity.js +31 -0
  23. package/src/server/common/README.md +21 -0
  24. package/src/server/common/contributors/README.md +11 -0
  25. package/src/server/common/contributors/workspaceActionContextContributor.js +79 -0
  26. package/src/server/common/contributors/workspaceAuthPolicyContextResolver.js +34 -0
  27. package/src/server/common/contributors/workspaceRouteVisibilityResolver.js +79 -0
  28. package/src/server/common/diTokens.js +21 -0
  29. package/src/server/common/formatters/README.md +11 -0
  30. package/src/server/common/formatters/accountAvatarFormatter.js +42 -0
  31. package/src/server/common/formatters/accountSecurityStatusFormatter.js +71 -0
  32. package/src/server/common/formatters/accountSettingsResponseFormatter.js +62 -0
  33. package/src/server/common/formatters/workspaceFormatter.js +46 -0
  34. package/src/server/common/registerCommonRepositories.js +45 -0
  35. package/src/server/common/registerSharedApi.js +9 -0
  36. package/src/server/common/repositories/README.md +24 -0
  37. package/src/server/common/repositories/repositoryUtils.js +50 -0
  38. package/src/server/common/repositories/userProfilesRepository.js +251 -0
  39. package/src/server/common/repositories/userSettingsRepository.js +179 -0
  40. package/src/server/common/repositories/workspaceInvitesRepository.js +172 -0
  41. package/src/server/common/repositories/workspaceMembershipsRepository.js +157 -0
  42. package/src/server/common/repositories/workspacesRepository.js +183 -0
  43. package/src/server/common/routes/README.md +11 -0
  44. package/src/server/common/services/README.md +12 -0
  45. package/src/server/common/services/accountContextService.js +31 -0
  46. package/src/server/common/services/authProfileSyncService.js +128 -0
  47. package/src/server/common/services/workspaceContextService.js +270 -0
  48. package/src/server/common/support/deepFreeze.js +17 -0
  49. package/src/server/common/support/realtimeServiceEvents.js +94 -0
  50. package/src/server/common/support/resolveActionUser.js +11 -0
  51. package/src/server/common/support/workspaceRoutePaths.js +17 -0
  52. package/src/server/common/validators/README.md +11 -0
  53. package/src/server/common/validators/authenticatedUserValidator.js +42 -0
  54. package/src/server/common/validators/routeParamsValidator.js +62 -0
  55. package/src/server/consoleSettings/bootConsoleSettingsRoutes.js +64 -0
  56. package/src/server/consoleSettings/consoleService.js +36 -0
  57. package/src/server/consoleSettings/consoleSettingsActions.js +55 -0
  58. package/src/server/consoleSettings/consoleSettingsRepository.js +111 -0
  59. package/src/server/consoleSettings/consoleSettingsService.js +40 -0
  60. package/src/server/consoleSettings/registerConsoleSettings.js +57 -0
  61. package/src/server/registerWorkspaceBootstrap.js +36 -0
  62. package/src/server/registerWorkspaceCore.js +95 -0
  63. package/src/server/support/resolveWorkspace.js +16 -0
  64. package/src/server/support/workspaceActionSurfaces.js +135 -0
  65. package/src/server/support/workspaceInvitationsPolicy.js +45 -0
  66. package/src/server/support/workspaceRouteInput.js +22 -0
  67. package/src/server/workspaceBootstrapContributor.js +401 -0
  68. package/src/server/workspaceDirectory/bootWorkspaceDirectoryRoutes.js +73 -0
  69. package/src/server/workspaceDirectory/registerWorkspaceDirectory.js +19 -0
  70. package/src/server/workspaceDirectory/workspaceDirectoryActions.js +65 -0
  71. package/src/server/workspaceMembers/bootWorkspaceMembers.js +238 -0
  72. package/src/server/workspaceMembers/registerWorkspaceMembers.js +112 -0
  73. package/src/server/workspaceMembers/workspaceMembersActions.js +186 -0
  74. package/src/server/workspaceMembers/workspaceMembersService.js +210 -0
  75. package/src/server/workspacePendingInvitations/bootWorkspacePendingInvitations.js +63 -0
  76. package/src/server/workspacePendingInvitations/registerWorkspacePendingInvitations.js +128 -0
  77. package/src/server/workspacePendingInvitations/workspacePendingInvitationsActions.js +74 -0
  78. package/src/server/workspacePendingInvitations/workspacePendingInvitationsService.js +137 -0
  79. package/src/server/workspaceSettings/bootWorkspaceSettings.js +77 -0
  80. package/src/server/workspaceSettings/registerWorkspaceSettings.js +67 -0
  81. package/src/server/workspaceSettings/workspaceSettingsActions.js +72 -0
  82. package/src/server/workspaceSettings/workspaceSettingsRepository.js +135 -0
  83. package/src/server/workspaceSettings/workspaceSettingsService.js +65 -0
  84. package/src/shared/events/usersEvents.js +19 -0
  85. package/src/shared/index.js +91 -0
  86. package/src/shared/operationMessages.js +16 -0
  87. package/src/shared/resources/consoleSettingsFields.js +55 -0
  88. package/src/shared/resources/consoleSettingsResource.js +139 -0
  89. package/src/shared/resources/resolveGlobalArrayRegistry.js +6 -0
  90. package/src/shared/resources/userProfileResource.js +148 -0
  91. package/src/shared/resources/userSettingsFields.js +71 -0
  92. package/src/shared/resources/userSettingsResource.js +416 -0
  93. package/src/shared/resources/workspaceMembersResource.js +352 -0
  94. package/src/shared/resources/workspacePendingInvitationsResource.js +87 -0
  95. package/src/shared/resources/workspaceResource.js +149 -0
  96. package/src/shared/resources/workspaceSettingsFields.js +60 -0
  97. package/src/shared/resources/workspaceSettingsResource.js +178 -0
  98. package/src/shared/roles.js +136 -0
  99. package/src/shared/settings.js +31 -0
  100. package/src/shared/support/usersApiPaths.js +34 -0
  101. package/src/shared/support/usersVisibility.js +45 -0
  102. package/src/shared/support/workspacePathModel.js +145 -0
  103. package/src/shared/tenancyMode.js +35 -0
  104. package/src/shared/tenancyProfile.js +73 -0
  105. package/templates/config/workspaceRoles.js +30 -0
  106. package/templates/migrations/users_core_console_owner.cjs +39 -0
  107. package/templates/migrations/users_core_initial.cjs +118 -0
  108. package/templates/migrations/users_core_profile_username.cjs +98 -0
  109. package/templates/packages/main/src/shared/resources/consoleSettingsFields.js +11 -0
  110. package/templates/packages/main/src/shared/resources/userSettingsFields.js +138 -0
  111. package/templates/packages/main/src/shared/resources/workspaceSettingsFields.js +105 -0
  112. package/test/authProfileSyncService.test.js +119 -0
  113. package/test/avatarService.test.js +114 -0
  114. package/test/avatarStorageService.test.js +61 -0
  115. package/test/consoleService.test.js +57 -0
  116. package/test/consoleSettingsService.test.js +86 -0
  117. package/test/exportsContract.test.js +38 -0
  118. package/test/registerAvatarMultipartSupport.test.js +64 -0
  119. package/test/registerServiceRealtimeEvents.test.js +160 -0
  120. package/test/registerWorkspaceDirectory.test.js +26 -0
  121. package/test/registerWorkspaceSettings.test.js +44 -0
  122. package/test/resourcesCanonical.test.js +90 -0
  123. package/test/roles.test.js +74 -0
  124. package/test/settingsFieldRegistriesSingleton.test.js +24 -0
  125. package/test/tenancyProfile.test.js +67 -0
  126. package/test/userSettingsResource.test.js +31 -0
  127. package/test/usersApiPaths.test.js +31 -0
  128. package/test/usersRouteRequestInputValidator.test.js +556 -0
  129. package/test/usersRouteResources.test.js +113 -0
  130. package/test/usersRouteValidators.test.js +49 -0
  131. package/test/usersVisibility.test.js +22 -0
  132. package/test/workspaceActionContextContributor.test.js +251 -0
  133. package/test/workspaceActionSurfaces.test.js +105 -0
  134. package/test/workspaceAuthPolicyContextResolver.test.js +119 -0
  135. package/test/workspaceBootstrapContributor.test.js +466 -0
  136. package/test/workspaceInvitationsPolicy.test.js +71 -0
  137. package/test/workspaceInvitesRepository.test.js +111 -0
  138. package/test/workspaceMembersService.test.js +400 -0
  139. package/test/workspacePathModel.test.js +93 -0
  140. package/test/workspacePendingInvitationsResource.test.js +38 -0
  141. package/test/workspacePendingInvitationsService.test.js +151 -0
  142. package/test/workspaceRouteVisibilityResolver.test.js +83 -0
  143. package/test/workspaceService.test.js +480 -0
  144. package/test/workspaceSettingsActions.test.js +42 -0
  145. package/test/workspaceSettingsRepository.test.js +156 -0
  146. package/test/workspaceSettingsResource.test.js +156 -0
  147. package/test/workspaceSettingsService.test.js +120 -0
  148. package/test-support/registerDefaultSettingsFields.js +3 -0
@@ -0,0 +1,238 @@
1
+ import { withStandardErrorResponses } from "@jskit-ai/http-runtime/shared/validators/errorResponses";
2
+ import { KERNEL_TOKENS } from "@jskit-ai/kernel/shared/support/tokens";
3
+ import { workspaceMembersResource } from "../../shared/resources/workspaceMembersResource.js";
4
+ import { resolveWorkspaceRoutePath } from "../common/support/workspaceRoutePaths.js";
5
+ import { USERS_WORKSPACE_INVITATIONS_ENABLED_TOKEN } from "../common/diTokens.js";
6
+ import {
7
+ routeParamsValidator,
8
+ workspaceSlugParamsValidator
9
+ } from "../common/validators/routeParamsValidator.js";
10
+ import { resolveDefaultWorkspaceRouteSurfaceIdFromAppConfig } from "../support/workspaceActionSurfaces.js";
11
+
12
+ function bootWorkspaceMembers(app) {
13
+ if (!app || typeof app.make !== "function") {
14
+ throw new Error("bootWorkspaceMembers requires application make().");
15
+ }
16
+
17
+ const router = app.make(KERNEL_TOKENS.HttpRouter);
18
+ const appConfig = typeof app.has === "function" && app.has("appConfig") ? app.make("appConfig") : {};
19
+ const workspaceInvitationsEnabled =
20
+ typeof app.has === "function" && app.has(USERS_WORKSPACE_INVITATIONS_ENABLED_TOKEN)
21
+ ? app.make(USERS_WORKSPACE_INVITATIONS_ENABLED_TOKEN) === true
22
+ : false;
23
+ const workspaceRouteSurfaceId = resolveDefaultWorkspaceRouteSurfaceIdFromAppConfig(appConfig);
24
+
25
+ router.register(
26
+ "GET",
27
+ resolveWorkspaceRoutePath("/roles"),
28
+ {
29
+ auth: "required",
30
+ surface: workspaceRouteSurfaceId,
31
+ visibility: "workspace",
32
+ contextPolicy: "required",
33
+ meta: {
34
+ tags: ["workspace"],
35
+ summary: "Get workspace role catalog by workspace slug"
36
+ },
37
+ paramsValidator: workspaceSlugParamsValidator,
38
+ responseValidators: withStandardErrorResponses({
39
+ 200: workspaceMembersResource.operations.rolesList.outputValidator
40
+ })
41
+ },
42
+ async function (request, reply) {
43
+ const response = await request.executeAction({
44
+ actionId: "workspace.roles.list",
45
+ input: {
46
+ workspaceSlug: request.input.params.workspaceSlug
47
+ }
48
+ });
49
+ reply.code(200).send(response);
50
+ }
51
+ );
52
+
53
+ router.register(
54
+ "GET",
55
+ resolveWorkspaceRoutePath("/members"),
56
+ {
57
+ auth: "required",
58
+ surface: workspaceRouteSurfaceId,
59
+ visibility: "workspace",
60
+ contextPolicy: "required",
61
+ meta: {
62
+ tags: ["workspace"],
63
+ summary: "List members by workspace slug"
64
+ },
65
+ paramsValidator: workspaceSlugParamsValidator,
66
+ responseValidators: withStandardErrorResponses({
67
+ 200: workspaceMembersResource.operations.membersList.outputValidator
68
+ })
69
+ },
70
+ async function (request, reply) {
71
+ const response = await request.executeAction({
72
+ actionId: "workspace.members.list",
73
+ input: {
74
+ workspaceSlug: request.input.params.workspaceSlug
75
+ }
76
+ });
77
+ reply.code(200).send(response);
78
+ }
79
+ );
80
+
81
+ router.register(
82
+ "PATCH",
83
+ resolveWorkspaceRoutePath("/members/:memberUserId/role"),
84
+ {
85
+ auth: "required",
86
+ surface: workspaceRouteSurfaceId,
87
+ visibility: "workspace",
88
+ contextPolicy: "required",
89
+ meta: {
90
+ tags: ["workspace"],
91
+ summary: "Update workspace member role by workspace slug"
92
+ },
93
+ paramsValidator: routeParamsValidator,
94
+ bodyValidator: workspaceMembersResource.operations.updateMemberRole.bodyValidator,
95
+ responseValidators: withStandardErrorResponses(
96
+ {
97
+ 200: workspaceMembersResource.operations.updateMemberRole.outputValidator
98
+ },
99
+ { includeValidation400: true }
100
+ )
101
+ },
102
+ async function (request, reply) {
103
+ const response = await request.executeAction({
104
+ actionId: "workspace.member.role.update",
105
+ input: {
106
+ workspaceSlug: request.input.params.workspaceSlug,
107
+ memberUserId: request.input.params.memberUserId,
108
+ roleId: request.input.body.roleId
109
+ }
110
+ });
111
+ reply.code(200).send(response);
112
+ }
113
+ );
114
+
115
+ router.register(
116
+ "DELETE",
117
+ resolveWorkspaceRoutePath("/members/:memberUserId"),
118
+ {
119
+ auth: "required",
120
+ surface: workspaceRouteSurfaceId,
121
+ visibility: "workspace",
122
+ contextPolicy: "required",
123
+ meta: {
124
+ tags: ["workspace"],
125
+ summary: "Remove workspace member by workspace slug"
126
+ },
127
+ paramsValidator: routeParamsValidator,
128
+ responseValidators: withStandardErrorResponses({
129
+ 200: workspaceMembersResource.operations.removeMember.outputValidator
130
+ })
131
+ },
132
+ async function (request, reply) {
133
+ const response = await request.executeAction({
134
+ actionId: "workspace.member.remove",
135
+ input: {
136
+ workspaceSlug: request.input.params.workspaceSlug,
137
+ memberUserId: request.input.params.memberUserId
138
+ }
139
+ });
140
+ reply.code(200).send(response);
141
+ }
142
+ );
143
+
144
+ if (workspaceInvitationsEnabled) {
145
+ router.register(
146
+ "GET",
147
+ resolveWorkspaceRoutePath("/invites"),
148
+ {
149
+ auth: "required",
150
+ surface: workspaceRouteSurfaceId,
151
+ visibility: "workspace",
152
+ contextPolicy: "required",
153
+ meta: {
154
+ tags: ["workspace"],
155
+ summary: "List workspace invites by workspace slug"
156
+ },
157
+ paramsValidator: workspaceSlugParamsValidator,
158
+ responseValidators: withStandardErrorResponses({
159
+ 200: workspaceMembersResource.operations.invitesList.outputValidator
160
+ })
161
+ },
162
+ async function (request, reply) {
163
+ const response = await request.executeAction({
164
+ actionId: "workspace.invites.list",
165
+ input: {
166
+ workspaceSlug: request.input.params.workspaceSlug
167
+ }
168
+ });
169
+ reply.code(200).send(response);
170
+ }
171
+ );
172
+
173
+ router.register(
174
+ "POST",
175
+ resolveWorkspaceRoutePath("/invites"),
176
+ {
177
+ auth: "required",
178
+ surface: workspaceRouteSurfaceId,
179
+ visibility: "workspace",
180
+ contextPolicy: "required",
181
+ meta: {
182
+ tags: ["workspace"],
183
+ summary: "Create workspace invite by workspace slug"
184
+ },
185
+ paramsValidator: workspaceSlugParamsValidator,
186
+ bodyValidator: workspaceMembersResource.operations.createInvite.bodyValidator,
187
+ responseValidators: withStandardErrorResponses(
188
+ {
189
+ 200: workspaceMembersResource.operations.createInvite.outputValidator
190
+ },
191
+ { includeValidation400: true }
192
+ )
193
+ },
194
+ async function (request, reply) {
195
+ const response = await request.executeAction({
196
+ actionId: "workspace.invite.create",
197
+ input: {
198
+ workspaceSlug: request.input.params.workspaceSlug,
199
+ email: request.input.body.email,
200
+ roleId: request.input.body.roleId
201
+ }
202
+ });
203
+ reply.code(200).send(response);
204
+ }
205
+ );
206
+
207
+ router.register(
208
+ "DELETE",
209
+ resolveWorkspaceRoutePath("/invites/:inviteId"),
210
+ {
211
+ auth: "required",
212
+ surface: workspaceRouteSurfaceId,
213
+ visibility: "workspace",
214
+ contextPolicy: "required",
215
+ meta: {
216
+ tags: ["workspace"],
217
+ summary: "Revoke workspace invite by workspace slug"
218
+ },
219
+ paramsValidator: routeParamsValidator,
220
+ responseValidators: withStandardErrorResponses({
221
+ 200: workspaceMembersResource.operations.revokeInvite.outputValidator
222
+ })
223
+ },
224
+ async function (request, reply) {
225
+ const response = await request.executeAction({
226
+ actionId: "workspace.invite.revoke",
227
+ input: {
228
+ workspaceSlug: request.input.params.workspaceSlug,
229
+ inviteId: request.input.params.inviteId
230
+ }
231
+ });
232
+ reply.code(200).send(response);
233
+ }
234
+ );
235
+ }
236
+ }
237
+
238
+ export { bootWorkspaceMembers };
@@ -0,0 +1,112 @@
1
+ import { withActionDefaults } from "@jskit-ai/kernel/shared/actions";
2
+ import { resolveAppConfig } from "@jskit-ai/kernel/server/support";
3
+ import {
4
+ WORKSPACE_MEMBERS_CHANGED_EVENT,
5
+ WORKSPACE_INVITES_CHANGED_EVENT
6
+ } from "../../shared/events/usersEvents.js";
7
+ import { deepFreeze } from "../common/support/deepFreeze.js";
8
+ import { createService as createWorkspaceMembersService } from "./workspaceMembersService.js";
9
+ import { workspaceMembersActions } from "./workspaceMembersActions.js";
10
+ import { createWorkspaceRoleCatalog } from "../../shared/roles.js";
11
+ import { USERS_WORKSPACE_INVITATIONS_ENABLED_TOKEN } from "../common/diTokens.js";
12
+ import { createWorkspaceEntityAndBootstrapEvents } from "../common/support/realtimeServiceEvents.js";
13
+
14
+ const USERS_WORKSPACE_MEMBERS_SERVICE_TOKEN = "users.workspace.members.service";
15
+
16
+ function resolveWorkspaceMembersInviteExpiresInMs(appConfig = {}) {
17
+ const inviteExpiresInMs = Number(appConfig?.workspaceMembers?.defaults?.inviteExpiresInMs);
18
+ if (!Number.isInteger(inviteExpiresInMs) || inviteExpiresInMs < 1) {
19
+ throw new TypeError("users.core requires appConfig.workspaceMembers.defaults.inviteExpiresInMs.");
20
+ }
21
+
22
+ return inviteExpiresInMs;
23
+ }
24
+
25
+ const INVITE_RECIPIENT_BOOTSTRAP_AUDIENCE = Object.freeze({
26
+ preset: "event_scope",
27
+ async userQuery({ knex, event } = {}) {
28
+ if (typeof knex !== "function") {
29
+ return [];
30
+ }
31
+
32
+ const inviteId = Number(event?.entityId);
33
+ if (!Number.isInteger(inviteId) || inviteId < 1) {
34
+ return [];
35
+ }
36
+
37
+ const row = await knex("workspace_invites as wi")
38
+ .join("user_profiles as up", "up.email", "wi.email")
39
+ .where("wi.id", inviteId)
40
+ .first("up.id as user_id");
41
+
42
+ const userId = Number(row?.user_id || 0);
43
+ if (!Number.isInteger(userId) || userId < 1) {
44
+ return [];
45
+ }
46
+
47
+ return [
48
+ {
49
+ userId
50
+ }
51
+ ];
52
+ }
53
+ });
54
+
55
+ function registerWorkspaceMembers(app) {
56
+ if (!app || typeof app.singleton !== "function" || typeof app.service !== "function" || typeof app.actions !== "function") {
57
+ throw new Error("registerWorkspaceMembers requires application singleton()/service()/actions().");
58
+ }
59
+
60
+ app.service(
61
+ USERS_WORKSPACE_MEMBERS_SERVICE_TOKEN,
62
+ (scope) => {
63
+ const appConfig = resolveAppConfig(scope);
64
+ return createWorkspaceMembersService({
65
+ workspaceMembershipsRepository: scope.make("workspaceMembershipsRepository"),
66
+ workspaceInvitesRepository: scope.make("workspaceInvitesRepository"),
67
+ inviteExpiresInMs: resolveWorkspaceMembersInviteExpiresInMs(appConfig),
68
+ roleCatalog: createWorkspaceRoleCatalog(appConfig),
69
+ workspaceInvitationsEnabled: scope.make(USERS_WORKSPACE_INVITATIONS_ENABLED_TOKEN) === true
70
+ });
71
+ },
72
+ {
73
+ events: deepFreeze({
74
+ updateMemberRole: createWorkspaceEntityAndBootstrapEvents({
75
+ workspaceEntity: "member",
76
+ workspaceOperation: "updated",
77
+ workspaceRealtimeEvent: WORKSPACE_MEMBERS_CHANGED_EVENT
78
+ }),
79
+ removeMember: createWorkspaceEntityAndBootstrapEvents({
80
+ workspaceEntity: "member",
81
+ workspaceOperation: "updated",
82
+ workspaceRealtimeEvent: WORKSPACE_MEMBERS_CHANGED_EVENT
83
+ }),
84
+ createInvite: createWorkspaceEntityAndBootstrapEvents({
85
+ workspaceEntity: "invite",
86
+ workspaceOperation: "created",
87
+ workspaceRealtimeEvent: WORKSPACE_INVITES_CHANGED_EVENT,
88
+ bootstrapEntityId: ({ result }) => result?.createdInviteId,
89
+ bootstrapAudience: INVITE_RECIPIENT_BOOTSTRAP_AUDIENCE
90
+ }),
91
+ revokeInvite: createWorkspaceEntityAndBootstrapEvents({
92
+ workspaceEntity: "invite",
93
+ workspaceOperation: "updated",
94
+ workspaceRealtimeEvent: WORKSPACE_INVITES_CHANGED_EVENT,
95
+ bootstrapEntityId: ({ result }) => result?.revokedInviteId,
96
+ bootstrapAudience: INVITE_RECIPIENT_BOOTSTRAP_AUDIENCE
97
+ })
98
+ })
99
+ }
100
+ );
101
+
102
+ app.actions(
103
+ withActionDefaults(workspaceMembersActions, {
104
+ domain: "workspace",
105
+ dependencies: {
106
+ workspaceMembersService: USERS_WORKSPACE_MEMBERS_SERVICE_TOKEN
107
+ }
108
+ })
109
+ );
110
+ }
111
+
112
+ export { registerWorkspaceMembers };
@@ -0,0 +1,186 @@
1
+ import { resolveWorkspace } from "../support/resolveWorkspace.js";
2
+ import { resolveActionUser } from "../common/support/resolveActionUser.js";
3
+ import { workspaceMembersResource } from "../../shared/resources/workspaceMembersResource.js";
4
+ import { workspaceSlugParamsValidator } from "../common/validators/routeParamsValidator.js";
5
+
6
+ const workspaceMembersActions = Object.freeze([
7
+ {
8
+ id: "workspace.roles.list",
9
+ version: 1,
10
+ kind: "query",
11
+ channels: ["api", "automation", "internal"],
12
+ surfacesFrom: "workspace",
13
+ permission: {
14
+ require: "all",
15
+ permissions: ["workspace.roles.view"]
16
+ },
17
+ inputValidator: workspaceSlugParamsValidator,
18
+ outputValidator: workspaceMembersResource.operations.rolesList.outputValidator,
19
+ idempotency: "none",
20
+ audit: {
21
+ actionName: "workspace.roles.list"
22
+ },
23
+ observability: {},
24
+ async execute(_input, context, deps) {
25
+ return deps.workspaceMembersService.listRoles({ context });
26
+ }
27
+ },
28
+ {
29
+ id: "workspace.members.list",
30
+ version: 1,
31
+ kind: "query",
32
+ channels: ["api", "automation", "internal"],
33
+ surfacesFrom: "workspace",
34
+ permission: {
35
+ require: "all",
36
+ permissions: ["workspace.members.view"]
37
+ },
38
+ inputValidator: workspaceSlugParamsValidator,
39
+ outputValidator: workspaceMembersResource.operations.membersList.outputValidator,
40
+ idempotency: "none",
41
+ audit: {
42
+ actionName: "workspace.members.list"
43
+ },
44
+ observability: {},
45
+ async execute(input, context, deps) {
46
+ return deps.workspaceMembersService.listMembers(resolveWorkspace(context, input), {
47
+ context
48
+ });
49
+ }
50
+ },
51
+ {
52
+ id: "workspace.member.role.update",
53
+ version: 1,
54
+ kind: "command",
55
+ channels: ["api", "automation", "internal"],
56
+ surfacesFrom: "workspace",
57
+ permission: {
58
+ require: "all",
59
+ permissions: ["workspace.members.manage"]
60
+ },
61
+ inputValidator: [workspaceSlugParamsValidator, workspaceMembersResource.operations.updateMemberRole.inputValidator],
62
+ outputValidator: workspaceMembersResource.operations.updateMemberRole.outputValidator,
63
+ idempotency: "optional",
64
+ audit: {
65
+ actionName: "workspace.member.role.update"
66
+ },
67
+ observability: {},
68
+ async execute(input, context, deps) {
69
+ return deps.workspaceMembersService.updateMemberRole(resolveWorkspace(context, input), {
70
+ memberUserId: input.memberUserId,
71
+ roleId: input.roleId
72
+ }, {
73
+ context
74
+ });
75
+ }
76
+ },
77
+ {
78
+ id: "workspace.member.remove",
79
+ version: 1,
80
+ kind: "command",
81
+ channels: ["api", "automation", "internal"],
82
+ surfacesFrom: "workspace",
83
+ permission: {
84
+ require: "all",
85
+ permissions: ["workspace.members.manage"]
86
+ },
87
+ inputValidator: [workspaceSlugParamsValidator, workspaceMembersResource.operations.removeMember.inputValidator],
88
+ outputValidator: workspaceMembersResource.operations.removeMember.outputValidator,
89
+ idempotency: "optional",
90
+ audit: {
91
+ actionName: "workspace.member.remove"
92
+ },
93
+ observability: {},
94
+ async execute(input, context, deps) {
95
+ return deps.workspaceMembersService.removeMember(resolveWorkspace(context, input), {
96
+ memberUserId: input.memberUserId
97
+ }, {
98
+ context
99
+ });
100
+ }
101
+ },
102
+ {
103
+ id: "workspace.invites.list",
104
+ version: 1,
105
+ kind: "query",
106
+ channels: ["api", "automation", "internal"],
107
+ surfacesFrom: "workspace",
108
+ permission: {
109
+ require: "all",
110
+ permissions: ["workspace.members.view"]
111
+ },
112
+ inputValidator: workspaceSlugParamsValidator,
113
+ outputValidator: workspaceMembersResource.operations.invitesList.outputValidator,
114
+ idempotency: "none",
115
+ audit: {
116
+ actionName: "workspace.invites.list"
117
+ },
118
+ observability: {},
119
+ async execute(input, context, deps) {
120
+ return deps.workspaceMembersService.listInvites(resolveWorkspace(context, input), {
121
+ context
122
+ });
123
+ }
124
+ },
125
+ {
126
+ id: "workspace.invite.create",
127
+ version: 1,
128
+ kind: "command",
129
+ channels: ["api", "assistant_tool", "automation", "internal"],
130
+ surfacesFrom: "workspace",
131
+ permission: {
132
+ require: "all",
133
+ permissions: ["workspace.members.invite"]
134
+ },
135
+ inputValidator: [workspaceSlugParamsValidator, workspaceMembersResource.operations.createInvite.bodyValidator],
136
+ outputValidator: workspaceMembersResource.operations.createInvite.outputValidator,
137
+ idempotency: "optional",
138
+ audit: {
139
+ actionName: "workspace.invite.create"
140
+ },
141
+ observability: {},
142
+ extensions: {
143
+ assistant: {
144
+ description: "Invite a person to the workspace."
145
+ }
146
+ },
147
+ async execute(input, context, deps) {
148
+ return deps.workspaceMembersService.createInvite(
149
+ resolveWorkspace(context, input),
150
+ resolveActionUser(context, input),
151
+ {
152
+ email: input.email,
153
+ roleId: input.roleId
154
+ },
155
+ {
156
+ context
157
+ }
158
+ );
159
+ }
160
+ },
161
+ {
162
+ id: "workspace.invite.revoke",
163
+ version: 1,
164
+ kind: "command",
165
+ channels: ["api", "automation", "internal"],
166
+ surfacesFrom: "workspace",
167
+ permission: {
168
+ require: "all",
169
+ permissions: ["workspace.invites.revoke"]
170
+ },
171
+ inputValidator: [workspaceSlugParamsValidator, workspaceMembersResource.operations.revokeInvite.inputValidator],
172
+ outputValidator: workspaceMembersResource.operations.revokeInvite.outputValidator,
173
+ idempotency: "optional",
174
+ audit: {
175
+ actionName: "workspace.invite.revoke"
176
+ },
177
+ observability: {},
178
+ async execute(input, context, deps) {
179
+ return deps.workspaceMembersService.revokeInvite(resolveWorkspace(context, input), input.inviteId, {
180
+ context
181
+ });
182
+ }
183
+ }
184
+ ]);
185
+
186
+ export { workspaceMembersActions };