@jskit-ai/users-core 0.1.47 → 0.1.49

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 (104) hide show
  1. package/package.descriptor.mjs +9 -46
  2. package/package.json +8 -19
  3. package/src/server/UsersCoreServiceProvider.js +0 -4
  4. package/src/server/common/registerCommonRepositories.js +0 -5
  5. package/src/server/common/services/authProfileSyncService.js +28 -7
  6. package/src/server/common/support/realtimeServiceEvents.js +1 -59
  7. package/src/server/profileSyncLifecycleContributorRegistry.js +56 -0
  8. package/src/server/registerUsersBootstrap.js +1 -3
  9. package/src/server/registerUsersCore.js +2 -14
  10. package/src/server/usersBootstrapContributor.js +10 -85
  11. package/src/shared/index.js +2 -99
  12. package/src/shared/settings.js +1 -119
  13. package/templates/migrations/users_core_generic_initial.cjs +0 -16
  14. package/test/authProfileSyncService.test.js +19 -10
  15. package/test/registerServiceRealtimeEvents.test.js +0 -94
  16. package/test/registerUsersCore.test.js +6 -19
  17. package/test/repositoryContracts.test.js +1 -11
  18. package/test/resourcesCanonical.test.js +1 -19
  19. package/test/settingsFieldRegistriesSingleton.test.js +0 -10
  20. package/test/usersBootstrapContributor.test.js +20 -38
  21. package/test/usersRouteRequestInputValidator.test.js +2 -43
  22. package/test/usersRouteResources.test.js +2 -20
  23. package/test-support/registerDefaultSettingsFields.js +0 -1
  24. package/src/server/UsersWorkspacesServiceProvider.js +0 -44
  25. package/src/server/common/contributors/workspaceActionContextContributor.js +0 -88
  26. package/src/server/common/contributors/workspaceAuthPolicyContextResolver.js +0 -34
  27. package/src/server/common/contributors/workspaceRouteVisibilityResolver.js +0 -78
  28. package/src/server/common/formatters/workspaceFormatter.js +0 -53
  29. package/src/server/common/repositories/workspaceInvitesRepository.js +0 -208
  30. package/src/server/common/repositories/workspaceMembershipsRepository.js +0 -190
  31. package/src/server/common/repositories/workspacesRepository.js +0 -202
  32. package/src/server/common/services/workspaceContextService.js +0 -281
  33. package/src/server/common/support/workspaceRoutePaths.js +0 -17
  34. package/src/server/common/validators/routeParamsValidator.js +0 -62
  35. package/src/server/consoleSettings/bootConsoleSettingsRoutes.js +0 -63
  36. package/src/server/consoleSettings/consoleService.js +0 -36
  37. package/src/server/consoleSettings/consoleSettingsActions.js +0 -55
  38. package/src/server/consoleSettings/consoleSettingsRepository.js +0 -115
  39. package/src/server/consoleSettings/consoleSettingsService.js +0 -40
  40. package/src/server/consoleSettings/registerConsoleSettings.js +0 -56
  41. package/src/server/registerWorkspaceBootstrap.js +0 -27
  42. package/src/server/registerWorkspaceCore.js +0 -73
  43. package/src/server/registerWorkspaceRepositories.js +0 -26
  44. package/src/server/support/resolveWorkspace.js +0 -16
  45. package/src/server/support/workspaceActionSurfaces.js +0 -135
  46. package/src/server/support/workspaceInvitationsPolicy.js +0 -45
  47. package/src/server/support/workspaceRouteInput.js +0 -22
  48. package/src/server/workspaceBootstrapContributor.js +0 -211
  49. package/src/server/workspaceDirectory/bootWorkspaceDirectoryRoutes.js +0 -133
  50. package/src/server/workspaceDirectory/registerWorkspaceDirectory.js +0 -19
  51. package/src/server/workspaceDirectory/workspaceDirectoryActions.js +0 -133
  52. package/src/server/workspaceMembers/bootWorkspaceMembers.js +0 -236
  53. package/src/server/workspaceMembers/registerWorkspaceMembers.js +0 -108
  54. package/src/server/workspaceMembers/workspaceMembersActions.js +0 -186
  55. package/src/server/workspaceMembers/workspaceMembersService.js +0 -222
  56. package/src/server/workspacePendingInvitations/bootWorkspacePendingInvitations.js +0 -62
  57. package/src/server/workspacePendingInvitations/registerWorkspacePendingInvitations.js +0 -119
  58. package/src/server/workspacePendingInvitations/workspacePendingInvitationsActions.js +0 -74
  59. package/src/server/workspacePendingInvitations/workspacePendingInvitationsService.js +0 -138
  60. package/src/server/workspaceSettings/bootWorkspaceSettings.js +0 -76
  61. package/src/server/workspaceSettings/registerWorkspaceSettings.js +0 -62
  62. package/src/server/workspaceSettings/workspaceSettingsActions.js +0 -72
  63. package/src/server/workspaceSettings/workspaceSettingsRepository.js +0 -154
  64. package/src/server/workspaceSettings/workspaceSettingsService.js +0 -66
  65. package/src/shared/resources/consoleSettingsFields.js +0 -54
  66. package/src/shared/resources/consoleSettingsResource.js +0 -119
  67. package/src/shared/resources/workspaceMembersResource.js +0 -354
  68. package/src/shared/resources/workspacePendingInvitationsResource.js +0 -82
  69. package/src/shared/resources/workspaceResource.js +0 -176
  70. package/src/shared/resources/workspaceSettingsFields.js +0 -59
  71. package/src/shared/resources/workspaceSettingsResource.js +0 -169
  72. package/src/shared/roles.js +0 -161
  73. package/src/shared/support/usersApiPaths.js +0 -43
  74. package/src/shared/support/usersVisibility.js +0 -42
  75. package/src/shared/support/workspacePathModel.js +0 -145
  76. package/src/shared/tenancyMode.js +0 -35
  77. package/src/shared/tenancyProfile.js +0 -73
  78. package/templates/migrations/users_core_console_owner.cjs +0 -37
  79. package/templates/packages/main/src/shared/resources/consoleSettingsFields.js +0 -11
  80. package/test/consoleService.test.js +0 -57
  81. package/test/consoleSettingsService.test.js +0 -86
  82. package/test/registerWorkspaceDirectory.test.js +0 -31
  83. package/test/registerWorkspaceSettings.test.js +0 -40
  84. package/test/roles.test.js +0 -159
  85. package/test/tenancyProfile.test.js +0 -67
  86. package/test/usersApiPaths.test.js +0 -49
  87. package/test/usersRouteValidators.test.js +0 -49
  88. package/test/usersVisibility.test.js +0 -27
  89. package/test/workspaceActionContextContributor.test.js +0 -344
  90. package/test/workspaceActionSurfaces.test.js +0 -105
  91. package/test/workspaceAuthPolicyContextResolver.test.js +0 -119
  92. package/test/workspaceBootstrapContributor.test.js +0 -154
  93. package/test/workspaceInvitationsPolicy.test.js +0 -71
  94. package/test/workspaceInvitesRepository.test.js +0 -111
  95. package/test/workspaceMembersService.test.js +0 -398
  96. package/test/workspacePathModel.test.js +0 -93
  97. package/test/workspacePendingInvitationsResource.test.js +0 -38
  98. package/test/workspacePendingInvitationsService.test.js +0 -151
  99. package/test/workspaceRouteVisibilityResolver.test.js +0 -83
  100. package/test/workspaceService.test.js +0 -546
  101. package/test/workspaceSettingsActions.test.js +0 -52
  102. package/test/workspaceSettingsRepository.test.js +0 -202
  103. package/test/workspaceSettingsResource.test.js +0 -169
  104. package/test/workspaceSettingsService.test.js +0 -140
@@ -1,10 +1,6 @@
1
1
  import assert from "node:assert/strict";
2
2
  import test from "node:test";
3
3
  import { createUsersBootstrapContributor } from "../src/server/usersBootstrapContributor.js";
4
- import {
5
- TENANCY_MODE_PERSONAL,
6
- WORKSPACE_SLUG_POLICY_IMMUTABLE_USERNAME
7
- } from "../src/shared/tenancyProfile.js";
8
4
 
9
5
  function createAuthenticatedProfile(overrides = {}) {
10
6
  return {
@@ -33,9 +29,8 @@ function createUserSettings() {
33
29
  };
34
30
  }
35
31
 
36
- test("users bootstrap contributor seeds the initial console owner and exposes generic app payload", async () => {
32
+ test("users bootstrap contributor exposes the generic authenticated bootstrap payload", async () => {
37
33
  const profile = createAuthenticatedProfile({ id: "12" });
38
- const consoleOwnerSeeds = [];
39
34
  const writtenSessions = [];
40
35
  const contributor = createUsersBootstrapContributor({
41
36
  usersRepository: {
@@ -60,12 +55,6 @@ test("users bootstrap contributor seeds the initial console owner and exposes ge
60
55
  defaultProvider: "google"
61
56
  };
62
57
  }
63
- },
64
- consoleService: {
65
- async ensureInitialConsoleMember(userId) {
66
- consoleOwnerSeeds.push(Number(userId));
67
- return String(userId || "");
68
- }
69
58
  }
70
59
  });
71
60
 
@@ -82,10 +71,14 @@ test("users bootstrap contributor seeds the initial console owner and exposes ge
82
71
  };
83
72
  }
84
73
  },
74
+ payload: {
75
+ surfaceAccess: {
76
+ consoleowner: true
77
+ }
78
+ },
85
79
  reply
86
80
  });
87
-
88
- assert.deepEqual(consoleOwnerSeeds, [12]);
81
+ assert.equal(contributor.order, 100);
89
82
  assert.equal(writtenSessions.length, 1);
90
83
  assert.equal(writtenSessions[0].reply, reply);
91
84
  assert.deepEqual(writtenSessions[0].session, {
@@ -93,8 +86,10 @@ test("users bootstrap contributor seeds the initial console owner and exposes ge
93
86
  });
94
87
  assert.equal(payload.session.authenticated, true);
95
88
  assert.equal(payload.session.userId, "12");
96
- assert.equal(payload.surfaceAccess.consoleowner, true);
97
- assert.equal(payload.app.features.workspaceSwitching, false);
89
+ assert.deepEqual(payload.surfaceAccess, {
90
+ consoleowner: true
91
+ });
92
+ assert.equal(payload.app.features.assistantEnabled, false);
98
93
  assert.deepEqual(payload.session.oauthProviders, [
99
94
  {
100
95
  id: "google",
@@ -102,12 +97,11 @@ test("users bootstrap contributor seeds the initial console owner and exposes ge
102
97
  }
103
98
  ]);
104
99
  assert.equal(payload.session.oauthDefaultProvider, "google");
105
- assert.deepEqual(payload.workspaces, []);
106
100
  assert.deepEqual(payload.userSettings, {});
107
101
  assert.equal(payload.requestMeta.hasRequest, true);
108
102
  });
109
103
 
110
- test("users bootstrap contributor emits canonical tenancy profile for anonymous bootstrap", async () => {
104
+ test("users bootstrap contributor emits anonymous bootstrap payload without workspace fields", async () => {
111
105
  const contributor = createUsersBootstrapContributor({
112
106
  usersRepository: {
113
107
  async findById() {
@@ -119,15 +113,6 @@ test("users bootstrap contributor emits canonical tenancy profile for anonymous
119
113
  return createUserSettings();
120
114
  }
121
115
  },
122
- tenancyProfile: {
123
- mode: TENANCY_MODE_PERSONAL,
124
- workspace: {
125
- enabled: true,
126
- autoProvision: true,
127
- allowSelfCreate: false,
128
- slugPolicy: WORKSPACE_SLUG_POLICY_IMMUTABLE_USERNAME
129
- }
130
- },
131
116
  appConfig: {
132
117
  tenancyMode: "none"
133
118
  },
@@ -149,24 +134,21 @@ test("users bootstrap contributor emits canonical tenancy profile for anonymous
149
134
  };
150
135
  }
151
136
  },
137
+ payload: {
138
+ surfaceAccess: {
139
+ consoleowner: false
140
+ }
141
+ },
152
142
  reply: {}
153
143
  });
154
144
 
155
- assert.deepEqual(payload.tenancy, {
156
- mode: TENANCY_MODE_PERSONAL,
157
- workspace: {
158
- enabled: true,
159
- autoProvision: true,
160
- allowSelfCreate: false,
161
- slugPolicy: WORKSPACE_SLUG_POLICY_IMMUTABLE_USERNAME
162
- }
163
- });
164
145
  assert.deepEqual(payload.session, {
165
146
  authenticated: false,
166
147
  oauthProviders: [],
167
148
  oauthDefaultProvider: null
168
149
  });
169
- assert.deepEqual(payload.workspaces, []);
170
- assert.equal(payload.surfaceAccess.consoleowner, false);
150
+ assert.deepEqual(payload.surfaceAccess, {
151
+ consoleowner: false
152
+ });
171
153
  assert.equal(payload.userSettings, null);
172
154
  });
@@ -27,8 +27,7 @@ function findRoute(routes, { method, path }) {
27
27
  }
28
28
 
29
29
  async function registerRoutes({
30
- authService = {},
31
- consoleService = null
30
+ authService = {}
32
31
  } = {}) {
33
32
  const registeredRoutes = [];
34
33
  const router = {
@@ -59,10 +58,6 @@ async function registerRoutes({
59
58
  ["actionExecutor", {}]
60
59
  ]);
61
60
 
62
- if (consoleService) {
63
- bindings.set("consoleService", consoleService);
64
- }
65
-
66
61
  const app = {
67
62
  has(token) {
68
63
  return bindings.has(token);
@@ -92,13 +87,11 @@ function createActionRequest({ input = {}, executeAction, file = null }) {
92
87
  };
93
88
  }
94
89
 
95
- test("users-core boot mounts account and console routes without workspace routes", async () => {
90
+ test("users-core boot mounts account routes without workspace routes", async () => {
96
91
  const routes = await registerRoutes();
97
92
 
98
93
  assert.equal(findRoute(routes, { method: "GET", path: "/api/settings" })?.path, "/api/settings");
99
94
  assert.equal(findRoute(routes, { method: "PATCH", path: "/api/settings/profile" })?.path, "/api/settings/profile");
100
- assert.equal(findRoute(routes, { method: "GET", path: "/api/console/settings" })?.path, "/api/console/settings");
101
- assert.equal(findRoute(routes, { method: "PATCH", path: "/api/console/settings" })?.path, "/api/console/settings");
102
95
  assert.equal(findRoute(routes, { method: "GET", path: "/api/workspaces" }), null);
103
96
  assert.equal(findRoute(routes, { method: "GET", path: "/api/w/:workspaceSlug/settings" }), null);
104
97
  });
@@ -206,37 +199,3 @@ test("account route handlers build action input from request.input", async () =>
206
199
  assert.deepEqual(calls[6].input, { provider: "github" });
207
200
  assert.equal(calls[7].actionId, "settings.security.sessions.logout_others");
208
201
  });
209
-
210
- test("console settings route handlers use request.input payloads", async () => {
211
- const routes = await registerRoutes();
212
- const calls = [];
213
- const executeAction = async (payload) => {
214
- calls.push(payload);
215
- return {
216
- settings: {}
217
- };
218
- };
219
-
220
- await findRoute(routes, { method: "GET", path: "/api/console/settings" }).handler(
221
- createActionRequest({ executeAction }),
222
- createReplyDouble()
223
- );
224
-
225
- await findRoute(routes, { method: "PATCH", path: "/api/console/settings" }).handler(
226
- createActionRequest({
227
- input: {
228
- body: {}
229
- },
230
- executeAction
231
- }),
232
- createReplyDouble()
233
- );
234
-
235
- assert.equal(calls[0].actionId, "console.settings.read");
236
- assert.deepEqual(calls[1], {
237
- actionId: "console.settings.update",
238
- input: {
239
- payload: {}
240
- }
241
- });
242
- });
@@ -5,12 +5,8 @@ import { existsSync } from "node:fs";
5
5
  import { fileURLToPath } from "node:url";
6
6
  import { deriveResourceRequiredMetadata } from "@jskit-ai/kernel/_testable";
7
7
  import "../test-support/registerDefaultSettingsFields.js";
8
- import { consoleSettingsResource } from "../src/shared/resources/consoleSettingsResource.js";
9
8
  import { userProfileResource } from "../src/shared/resources/userProfileResource.js";
10
9
  import { userSettingsResource } from "../src/shared/resources/userSettingsResource.js";
11
- import { workspaceMembersResource } from "../src/shared/resources/workspaceMembersResource.js";
12
- import { workspaceResource } from "../src/shared/resources/workspaceResource.js";
13
- import { workspaceSettingsResource } from "../src/shared/resources/workspaceSettingsResource.js";
14
10
 
15
11
  function assertResourceShape(resource, label) {
16
12
  assert.ok(resource, `${label} resource must exist.`);
@@ -47,13 +43,10 @@ function assertResourceShape(resource, label) {
47
43
  assert.ok(Array.isArray(requiredMetadata.patch), `${label}.derivedRequired.patch must be an array.`);
48
44
  }
49
45
 
50
- test("workspace/settings/console resources expose canonical validators", () => {
46
+ test("workspace and account resources expose canonical validators", () => {
51
47
  const resourcesByLabel = {
52
- workspace: workspaceResource,
53
- workspaceSettings: workspaceSettingsResource,
54
48
  userProfile: userProfileResource,
55
- userSettings: userSettingsResource,
56
- consoleSettings: consoleSettingsResource
49
+ userSettings: userSettingsResource
57
50
  };
58
51
 
59
52
  for (const [label, resource] of Object.entries(resourcesByLabel)) {
@@ -62,18 +55,7 @@ test("workspace/settings/console resources expose canonical validators", () => {
62
55
  });
63
56
 
64
57
  test("specialized settings and invite operations expose canonical validators", () => {
65
- const workspaceMembersOperationSpecs = [
66
- { label: "workspaceMembers.rolesList", operation: workspaceMembersResource.operations.rolesList },
67
- { label: "workspaceMembers.membersList", operation: workspaceMembersResource.operations.membersList },
68
- { label: "workspaceMembers.updateMemberRole", operation: workspaceMembersResource.operations.updateMemberRole },
69
- { label: "workspaceMembers.removeMember", operation: workspaceMembersResource.operations.removeMember },
70
- { label: "workspaceMembers.invitesList", operation: workspaceMembersResource.operations.invitesList },
71
- { label: "workspaceMembers.createInvite", operation: workspaceMembersResource.operations.createInvite },
72
- { label: "workspaceMembers.revokeInvite", operation: workspaceMembersResource.operations.revokeInvite },
73
- { label: "workspaceMembers.redeemInvite", operation: workspaceMembersResource.operations.redeemInvite }
74
- ];
75
58
  const operationSpecs = [
76
- ...workspaceMembersOperationSpecs,
77
59
  { label: "userProfile.avatarUpload", operation: userProfileResource.operations.avatarUpload },
78
60
  { label: "userProfile.avatarDelete", operation: userProfileResource.operations.avatarDelete },
79
61
  { label: "userSettings.passwordChange", operation: userSettingsResource.operations.passwordChange },
@@ -1,3 +1,2 @@
1
1
  import "../../workspaces-core/templates/packages/main/src/shared/resources/workspaceSettingsFields.js";
2
- import "../templates/packages/main/src/shared/resources/consoleSettingsFields.js";
3
2
  import "../templates/packages/main/src/shared/resources/userSettingsFields.js";
@@ -1,44 +0,0 @@
1
- import { bootWorkspaceDirectoryRoutes } from "./workspaceDirectory/bootWorkspaceDirectoryRoutes.js";
2
- import { registerWorkspaceDirectory } from "./workspaceDirectory/registerWorkspaceDirectory.js";
3
- import {
4
- registerWorkspacePendingInvitations
5
- } from "./workspacePendingInvitations/registerWorkspacePendingInvitations.js";
6
- import { bootWorkspacePendingInvitations } from "./workspacePendingInvitations/bootWorkspacePendingInvitations.js";
7
- import { registerWorkspaceMembers } from "./workspaceMembers/registerWorkspaceMembers.js";
8
- import { bootWorkspaceMembers } from "./workspaceMembers/bootWorkspaceMembers.js";
9
- import { registerWorkspaceSettings } from "./workspaceSettings/registerWorkspaceSettings.js";
10
- import { bootWorkspaceSettings } from "./workspaceSettings/bootWorkspaceSettings.js";
11
- import { registerWorkspaceRepositories } from "./registerWorkspaceRepositories.js";
12
- import { registerWorkspaceCore } from "./registerWorkspaceCore.js";
13
- import { registerWorkspaceBootstrap } from "./registerWorkspaceBootstrap.js";
14
-
15
- class UsersWorkspacesServiceProvider {
16
- static id = "workspaces.core";
17
-
18
- static dependsOn = ["users.core"];
19
-
20
- register(app) {
21
- registerWorkspaceRepositories(app);
22
- registerWorkspaceCore(app);
23
- registerWorkspaceBootstrap(app);
24
- registerWorkspaceDirectory(app);
25
- registerWorkspaceMembers(app);
26
- registerWorkspaceSettings(app);
27
- registerWorkspacePendingInvitations(app);
28
- }
29
-
30
- async boot(app) {
31
- if (app.make("users.workspace.enabled") !== true) {
32
- return;
33
- }
34
-
35
- bootWorkspaceDirectoryRoutes(app);
36
- if (app.make("users.workspace.invitations.enabled") === true) {
37
- bootWorkspacePendingInvitations(app);
38
- }
39
- bootWorkspaceSettings(app);
40
- bootWorkspaceMembers(app);
41
- }
42
- }
43
-
44
- export { UsersWorkspacesServiceProvider };
@@ -1,88 +0,0 @@
1
- import {
2
- normalizeObject,
3
- requireServiceMethod
4
- } from "@jskit-ai/kernel/shared/actions/actionContributorHelpers";
5
- import { normalizeSurfaceId } from "@jskit-ai/kernel/shared/surface/registry";
6
- import {
7
- checkRouteVisibility,
8
- USERS_ROUTE_VISIBILITY_PUBLIC,
9
- USERS_ROUTE_VISIBILITY_WORKSPACE,
10
- USERS_ROUTE_VISIBILITY_WORKSPACE_USER
11
- } from "../../../shared/support/usersVisibility.js";
12
- import { resolveActionUser } from "../support/resolveActionUser.js";
13
- const WORKSPACE_VISIBILITY_ACTION_CONTEXT_SET = new Set([
14
- USERS_ROUTE_VISIBILITY_WORKSPACE,
15
- USERS_ROUTE_VISIBILITY_WORKSPACE_USER
16
- ]);
17
-
18
- function normalizeWorkspaceSurfaceIds(surfaceIds = []) {
19
- const source = Array.isArray(surfaceIds) ? surfaceIds : [];
20
- const normalized = new Set();
21
-
22
- for (const entry of source) {
23
- const surfaceId = normalizeSurfaceId(entry);
24
- if (!surfaceId) {
25
- continue;
26
- }
27
- normalized.add(surfaceId);
28
- }
29
-
30
- return normalized;
31
- }
32
-
33
- function createWorkspaceActionContextContributor({ workspaceService, workspaceSurfaceIds = [] } = {}) {
34
- const contributorId = "users.workspace.context";
35
- const workspaceSurfaceIdSet = normalizeWorkspaceSurfaceIds(workspaceSurfaceIds);
36
-
37
- requireServiceMethod(workspaceService, "resolveWorkspaceContextForUserBySlug", contributorId);
38
-
39
- return Object.freeze({
40
- contributorId,
41
- async contribute({ definition = null, input, context, request } = {}) {
42
- const payload = normalizeObject(input);
43
- if (!Object.hasOwn(payload, "workspaceSlug")) {
44
- return {};
45
- }
46
-
47
- const actionSurfaces = Array.isArray(definition?.surfaces) ? definition.surfaces : [];
48
- const hasWorkspaceActionSurface = actionSurfaces.some((surfaceId) => workspaceSurfaceIdSet.has(surfaceId));
49
- const routeSurfaceId = normalizeSurfaceId(request?.routeOptions?.config?.surface);
50
- const hasWorkspaceSurface = workspaceSurfaceIdSet.has(routeSurfaceId);
51
- const routeVisibilityInput =
52
- request && request.routeOptions && request.routeOptions.config
53
- ? request.routeOptions.config.visibility
54
- : USERS_ROUTE_VISIBILITY_PUBLIC;
55
- const routeVisibility = checkRouteVisibility(routeVisibilityInput);
56
- const hasWorkspaceRouteVisibility = WORKSPACE_VISIBILITY_ACTION_CONTEXT_SET.has(routeVisibility);
57
- if (!hasWorkspaceActionSurface && !hasWorkspaceRouteVisibility && !hasWorkspaceSurface) {
58
- return {};
59
- }
60
-
61
- const resolvedWorkspaceContext = await workspaceService.resolveWorkspaceContextForUserBySlug(
62
- resolveActionUser(context, payload),
63
- payload.workspaceSlug,
64
- { request }
65
- );
66
-
67
- const contribution = {
68
- requestMeta: {
69
- resolvedWorkspaceContext
70
- }
71
- };
72
-
73
- if (!context?.workspace) {
74
- contribution.workspace = resolvedWorkspaceContext.workspace;
75
- }
76
- if (!context?.membership) {
77
- contribution.membership = resolvedWorkspaceContext.membership;
78
- }
79
- if (!Array.isArray(context?.permissions) || context.permissions.length < 1) {
80
- contribution.permissions = resolvedWorkspaceContext.permissions;
81
- }
82
-
83
- return contribution;
84
- }
85
- });
86
- }
87
-
88
- export { createWorkspaceActionContextContributor };
@@ -1,34 +0,0 @@
1
- import { normalizeText } from "@jskit-ai/kernel/shared/support/normalize";
2
-
3
- function createWorkspaceAuthPolicyContextResolver({ workspaceService } = {}) {
4
- if (!workspaceService || typeof workspaceService.resolveWorkspaceContextForUserBySlug !== "function") {
5
- throw new Error(
6
- "workspace auth policy context resolver requires workspaceService.resolveWorkspaceContextForUserBySlug()."
7
- );
8
- }
9
-
10
- return async function resolveWorkspaceAuthPolicyContext({ request, actor, meta } = {}) {
11
- const contextPolicy = normalizeText(meta?.contextPolicy || "none").toLowerCase() || "none";
12
- const permission = normalizeText(meta?.permission);
13
- if (contextPolicy === "none" && !permission) {
14
- return {};
15
- }
16
-
17
- const workspaceSlug = normalizeText(request?.params?.workspaceSlug).toLowerCase();
18
- if (!workspaceSlug || !actor) {
19
- return {};
20
- }
21
-
22
- const resolvedWorkspaceContext = await workspaceService.resolveWorkspaceContextForUserBySlug(actor, workspaceSlug, {
23
- request
24
- });
25
-
26
- return {
27
- workspace: resolvedWorkspaceContext?.workspace || null,
28
- membership: resolvedWorkspaceContext?.membership || null,
29
- permissions: Array.isArray(resolvedWorkspaceContext?.permissions) ? resolvedWorkspaceContext.permissions : []
30
- };
31
- };
32
- }
33
-
34
- export { createWorkspaceAuthPolicyContextResolver };
@@ -1,78 +0,0 @@
1
- import { normalizeOpaqueId, normalizeRecordId, normalizeText } from "@jskit-ai/kernel/shared/support/normalize";
2
-
3
- function buildVisibilityContribution({ visibility, scopeOwnerId = null, userId = null } = {}) {
4
- const requiresActorScope = visibility === "workspace_user";
5
- const contribution = {
6
- scopeKind: requiresActorScope ? "workspace_user" : "workspace",
7
- requiresActorScope
8
- };
9
-
10
- if (scopeOwnerId) {
11
- contribution.scopeOwnerId = scopeOwnerId;
12
- }
13
- if (requiresActorScope && userId != null) {
14
- contribution.userId = userId;
15
- }
16
-
17
- return contribution;
18
- }
19
-
20
- function createWorkspaceRouteVisibilityResolver({ workspaceService } = {}) {
21
- if (!workspaceService || typeof workspaceService.resolveWorkspaceContextForUserBySlug !== "function") {
22
- throw new Error("workspace route visibility resolver requires workspaceService.resolveWorkspaceContextForUserBySlug().");
23
- }
24
-
25
- return Object.freeze({
26
- resolverId: "users.workspace.visibility",
27
- async resolve({ visibility, context, request, input } = {}) {
28
- if (visibility !== "workspace" && visibility !== "workspace_user") {
29
- return {};
30
- }
31
-
32
- const actor = context?.actor || request?.user || null;
33
- const userId = normalizeOpaqueId(actor?.id);
34
- const workspace =
35
- context?.workspace || context?.requestMeta?.resolvedWorkspaceContext?.workspace || request?.workspace || null;
36
- const scopeOwnerId = normalizeRecordId(workspace?.id, { fallback: null });
37
- if (!scopeOwnerId) {
38
- const workspaceSlug = normalizeText(input?.workspaceSlug).toLowerCase();
39
-
40
- if (!workspaceSlug || !actor) {
41
- return visibility === "workspace_user"
42
- ? buildVisibilityContribution({
43
- visibility,
44
- userId
45
- })
46
- : {};
47
- }
48
-
49
- const resolvedWorkspaceContext = await workspaceService.resolveWorkspaceContextForUserBySlug(actor, workspaceSlug, {
50
- request
51
- });
52
- const resolvedWorkspaceOwnerId = normalizeRecordId(resolvedWorkspaceContext?.workspace?.id, { fallback: null });
53
- if (!resolvedWorkspaceOwnerId) {
54
- return visibility === "workspace_user"
55
- ? buildVisibilityContribution({
56
- visibility,
57
- userId
58
- })
59
- : {};
60
- }
61
-
62
- return buildVisibilityContribution({
63
- visibility,
64
- scopeOwnerId: resolvedWorkspaceOwnerId,
65
- userId
66
- });
67
- }
68
-
69
- return buildVisibilityContribution({
70
- visibility,
71
- scopeOwnerId,
72
- userId
73
- });
74
- }
75
- });
76
- }
77
-
78
- export { createWorkspaceRouteVisibilityResolver };
@@ -1,53 +0,0 @@
1
- import { resolveWorkspaceThemePalettes } from "../../../shared/settings.js";
2
- import { normalizeLowerText, normalizeText } from "@jskit-ai/kernel/shared/actions/textNormalization";
3
- import { normalizeRecordId } from "@jskit-ai/kernel/shared/support/normalize";
4
-
5
- function mapWorkspaceSummary(workspace, membership) {
6
- return {
7
- id: normalizeRecordId(workspace.id, { fallback: "" }),
8
- slug: normalizeText(workspace.slug),
9
- name: normalizeText(workspace.name),
10
- avatarUrl: normalizeText(workspace.avatarUrl),
11
- roleSid: normalizeLowerText(membership?.roleSid || "member") || "member",
12
- isAccessible: normalizeLowerText(membership?.status || "active") === "active"
13
- };
14
- }
15
-
16
- function mapWorkspaceSettingsPublic(workspaceSettings, { workspaceInvitationsEnabled = true } = {}) {
17
- const source = workspaceSettings && typeof workspaceSettings === "object" ? workspaceSettings : {};
18
- const invitesAvailable = workspaceInvitationsEnabled === true;
19
- const invitesEnabled = invitesAvailable && source.invitesEnabled !== false;
20
- const themePalettes = resolveWorkspaceThemePalettes(source);
21
-
22
- return {
23
- lightPrimaryColor: themePalettes.light.color,
24
- lightSecondaryColor: themePalettes.light.secondaryColor,
25
- lightSurfaceColor: themePalettes.light.surfaceColor,
26
- lightSurfaceVariantColor: themePalettes.light.surfaceVariantColor,
27
- darkPrimaryColor: themePalettes.dark.color,
28
- darkSecondaryColor: themePalettes.dark.secondaryColor,
29
- darkSurfaceColor: themePalettes.dark.surfaceColor,
30
- darkSurfaceVariantColor: themePalettes.dark.surfaceVariantColor,
31
- invitesEnabled,
32
- invitesAvailable,
33
- invitesEffective: invitesAvailable && invitesEnabled
34
- };
35
- }
36
-
37
- function mapMembershipSummary(membership, workspace) {
38
- if (!membership) {
39
- return null;
40
- }
41
-
42
- return {
43
- workspaceId: normalizeRecordId(workspace?.id || membership.workspaceId, { fallback: "" }),
44
- roleSid: normalizeLowerText(membership.roleSid || "member") || "member",
45
- status: normalizeLowerText(membership.status || "active") || "active"
46
- };
47
- }
48
-
49
- export {
50
- mapMembershipSummary,
51
- mapWorkspaceSettingsPublic,
52
- mapWorkspaceSummary
53
- };