@jskit-ai/users-core 0.1.32 → 0.1.35

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 (48) hide show
  1. package/package.descriptor.mjs +16 -245
  2. package/package.json +7 -7
  3. package/src/server/UsersCoreServiceProvider.js +4 -28
  4. package/src/server/UsersWorkspacesServiceProvider.js +44 -0
  5. package/src/server/accountNotifications/accountNotificationsService.js +3 -3
  6. package/src/server/accountNotifications/registerAccountNotifications.js +1 -1
  7. package/src/server/accountPreferences/accountPreferencesService.js +3 -3
  8. package/src/server/accountPreferences/registerAccountPreferences.js +1 -1
  9. package/src/server/accountProfile/accountProfileActions.js +8 -2
  10. package/src/server/accountProfile/accountProfileService.js +10 -10
  11. package/src/server/accountProfile/avatarService.js +9 -9
  12. package/src/server/accountProfile/bootAccountProfileRoutes.js +5 -3
  13. package/src/server/accountProfile/registerAccountProfile.js +2 -2
  14. package/src/server/accountSecurity/accountSecurityService.js +3 -3
  15. package/src/server/accountSecurity/registerAccountSecurity.js +1 -1
  16. package/src/server/common/contributors/workspaceActionContextContributor.js +24 -17
  17. package/src/server/common/registerCommonRepositories.js +3 -22
  18. package/src/server/common/repositories/userSettingsRepository.js +1 -12
  19. package/src/server/common/repositories/{userProfilesRepository.js → usersRepository.js} +1 -1
  20. package/src/server/common/services/accountContextService.js +4 -4
  21. package/src/server/common/services/authProfileSyncService.js +10 -10
  22. package/src/server/registerUsersBootstrap.js +22 -0
  23. package/src/server/registerUsersCore.js +30 -0
  24. package/src/server/registerWorkspaceBootstrap.js +3 -6
  25. package/src/server/registerWorkspaceCore.js +5 -17
  26. package/src/server/registerWorkspaceRepositories.js +26 -0
  27. package/src/server/usersBootstrapContributor.js +248 -0
  28. package/src/server/workspaceBootstrapContributor.js +65 -259
  29. package/src/shared/roles.js +31 -6
  30. package/src/shared/settings.js +1 -2
  31. package/templates/migrations/users_core_generic_initial.cjs +69 -0
  32. package/test/authProfileSyncService.test.js +3 -3
  33. package/test/avatarService.test.js +2 -2
  34. package/test/registerUsersCore.test.js +42 -0
  35. package/test/roles.test.js +90 -5
  36. package/test/usersBootstrapContributor.test.js +172 -0
  37. package/test/usersRouteRequestInputValidator.test.js +7 -390
  38. package/test/workspaceActionContextContributor.test.js +98 -5
  39. package/test/workspaceBootstrapContributor.test.js +34 -346
  40. package/test/workspaceMembersService.test.js +4 -2
  41. package/test/workspaceService.test.js +12 -8
  42. package/test/workspaceSettingsResource.test.js +4 -2
  43. package/test-support/registerDefaultSettingsFields.js +1 -1
  44. package/templates/config/workspaceRoles.js +0 -30
  45. package/templates/migrations/users_core_initial.cjs +0 -123
  46. package/templates/migrations/users_core_workspace_settings_single_name_source.cjs +0 -71
  47. package/templates/migrations/users_core_workspaces_drop_color.cjs +0 -85
  48. package/templates/packages/main/src/shared/resources/workspaceSettingsFields.js +0 -197
@@ -0,0 +1,248 @@
1
+ import { AppError } from "@jskit-ai/kernel/server/runtime";
2
+ import { requireServiceMethod } from "@jskit-ai/kernel/shared/actions/actionContributorHelpers";
3
+ import { normalizeLowerText, normalizeText } from "@jskit-ai/kernel/shared/actions/textNormalization";
4
+ import {
5
+ TENANCY_MODE_NONE,
6
+ TENANCY_MODE_PERSONAL,
7
+ TENANCY_MODE_WORKSPACES,
8
+ WORKSPACE_SLUG_POLICY_NONE,
9
+ WORKSPACE_SLUG_POLICY_IMMUTABLE_USERNAME,
10
+ WORKSPACE_SLUG_POLICY_USER_SELECTED,
11
+ resolveTenancyProfile
12
+ } from "../shared/tenancyProfile.js";
13
+ import { accountAvatarFormatter } from "./common/formatters/accountAvatarFormatter.js";
14
+ import { authenticatedUserValidator } from "./common/validators/authenticatedUserValidator.js";
15
+ import { userSettingsFields } from "../shared/resources/userSettingsFields.js";
16
+
17
+ function getOAuthProviderCatalogPayload(authService) {
18
+ if (!authService || typeof authService.getOAuthProviderCatalog !== "function") {
19
+ return {
20
+ oauthProviders: [],
21
+ oauthDefaultProvider: null
22
+ };
23
+ }
24
+
25
+ const catalog = authService.getOAuthProviderCatalog();
26
+ const providers = Array.isArray(catalog?.providers)
27
+ ? catalog.providers
28
+ .map((provider) => ({
29
+ id: normalizeLowerText(provider?.id),
30
+ label: normalizeText(provider?.label)
31
+ }))
32
+ .filter((provider) => provider.id && provider.label)
33
+ : [];
34
+ const defaultProvider = normalizeLowerText(catalog?.defaultProvider);
35
+
36
+ return {
37
+ oauthProviders: providers,
38
+ oauthDefaultProvider: providers.some((provider) => provider.id === defaultProvider) ? defaultProvider : null
39
+ };
40
+ }
41
+
42
+ function normalizeBoolean(value, fallback) {
43
+ if (typeof value === "boolean") {
44
+ return value;
45
+ }
46
+ if (typeof value === "string") {
47
+ const normalized = normalizeLowerText(value);
48
+ if (normalized === "true") {
49
+ return true;
50
+ }
51
+ if (normalized === "false") {
52
+ return false;
53
+ }
54
+ }
55
+ return fallback;
56
+ }
57
+
58
+ function resolveAppState(appConfig = {}, { workspaceInvitationsEnabled = false } = {}) {
59
+ const features = {
60
+ workspaceSwitching: normalizeBoolean(appConfig.workspaceSwitching, false),
61
+ workspaceInvites: workspaceInvitationsEnabled === true,
62
+ assistantEnabled: normalizeBoolean(appConfig.assistantEnabled, false),
63
+ assistantRequiredPermission: normalizeText(appConfig.assistantRequiredPermission),
64
+ socialEnabled: normalizeBoolean(appConfig.socialEnabled, false),
65
+ socialFederationEnabled: normalizeBoolean(appConfig.socialFederationEnabled, false)
66
+ };
67
+
68
+ return {
69
+ features
70
+ };
71
+ }
72
+
73
+ function normalizeSlugPolicy(value = "") {
74
+ const normalizedValue = normalizeLowerText(value);
75
+ if (
76
+ normalizedValue === WORKSPACE_SLUG_POLICY_IMMUTABLE_USERNAME ||
77
+ normalizedValue === WORKSPACE_SLUG_POLICY_USER_SELECTED
78
+ ) {
79
+ return normalizedValue;
80
+ }
81
+ return WORKSPACE_SLUG_POLICY_NONE;
82
+ }
83
+
84
+ function isSupportedTenancyMode(value = "") {
85
+ return value === TENANCY_MODE_NONE || value === TENANCY_MODE_PERSONAL || value === TENANCY_MODE_WORKSPACES;
86
+ }
87
+
88
+ function resolveBootstrapTenancyProfile(tenancyProfile = null, appConfig = {}) {
89
+ const fallback = resolveTenancyProfile(appConfig);
90
+ const source = tenancyProfile && typeof tenancyProfile === "object" ? tenancyProfile : fallback;
91
+ const mode = isSupportedTenancyMode(source?.mode) ? source.mode : fallback.mode;
92
+ const workspace = source?.workspace && typeof source.workspace === "object" ? source.workspace : fallback.workspace;
93
+
94
+ return Object.freeze({
95
+ mode,
96
+ workspace: Object.freeze({
97
+ enabled: workspace.enabled === true,
98
+ autoProvision: workspace.autoProvision === true,
99
+ allowSelfCreate: workspace.allowSelfCreate === true,
100
+ slugPolicy: normalizeSlugPolicy(workspace.slugPolicy)
101
+ })
102
+ });
103
+ }
104
+
105
+ function createAnonymousBootstrapPayload({ appState, tenancyProfile }) {
106
+ return {
107
+ session: {
108
+ authenticated: false
109
+ },
110
+ profile: null,
111
+ tenancy: tenancyProfile,
112
+ app: appState,
113
+ workspaces: [],
114
+ pendingInvites: [],
115
+ activeWorkspace: null,
116
+ membership: null,
117
+ requestedWorkspace: null,
118
+ permissions: [],
119
+ surfaceAccess: {
120
+ consoleowner: false
121
+ },
122
+ workspaceSettings: null,
123
+ userSettings: null,
124
+ requestMeta: {
125
+ hasRequest: false
126
+ }
127
+ };
128
+ }
129
+
130
+ function mapUserSettingsBootstrap(settings = {}) {
131
+ const source = settings && typeof settings === "object" ? settings : {};
132
+ const mapped = {};
133
+
134
+ for (const field of userSettingsFields) {
135
+ if (field.includeInBootstrap === false) {
136
+ continue;
137
+ }
138
+ const rawValue = Object.hasOwn(source, field.key)
139
+ ? source[field.key]
140
+ : field.resolveDefault({
141
+ settings: source
142
+ });
143
+ mapped[field.key] = field.normalizeOutput(rawValue, {
144
+ settings: source
145
+ });
146
+ }
147
+
148
+ return mapped;
149
+ }
150
+
151
+ function createUsersBootstrapContributor({
152
+ usersRepository,
153
+ userSettingsRepository,
154
+ appConfig = {},
155
+ tenancyProfile = null,
156
+ authService,
157
+ consoleService = null
158
+ } = {}) {
159
+ const contributorId = "users.bootstrap";
160
+ const appState = resolveAppState(appConfig);
161
+ const resolvedTenancyProfile = resolveBootstrapTenancyProfile(tenancyProfile, appConfig);
162
+
163
+ requireServiceMethod(usersRepository, "findById", contributorId, {
164
+ serviceLabel: "usersRepository"
165
+ });
166
+ requireServiceMethod(userSettingsRepository, "ensureForUserId", contributorId, {
167
+ serviceLabel: "userSettingsRepository"
168
+ });
169
+
170
+ return Object.freeze({
171
+ contributorId,
172
+ async contribute({ request = null, reply = null } = {}) {
173
+ const authResult = await request.executeAction({
174
+ actionId: "auth.session.read"
175
+ });
176
+
177
+ if (authResult?.clearSession === true && typeof authService?.clearSessionCookies === "function") {
178
+ authService.clearSessionCookies(reply);
179
+ }
180
+ if (authResult?.session && typeof authService?.writeSessionCookies === "function") {
181
+ authService.writeSessionCookies(reply, authResult.session);
182
+ }
183
+ if (authResult?.transientFailure === true) {
184
+ throw new AppError(503, "Authentication service temporarily unavailable. Please retry.");
185
+ }
186
+
187
+ const normalizedUser = authenticatedUserValidator.normalize(authResult?.authenticated ? authResult?.profile : null);
188
+ let payload = createAnonymousBootstrapPayload({
189
+ appState,
190
+ tenancyProfile: resolvedTenancyProfile
191
+ });
192
+
193
+ if (normalizedUser) {
194
+ const latestProfile = (await usersRepository.findById(normalizedUser.id)) || normalizedUser;
195
+ const userSettings = await userSettingsRepository.ensureForUserId(latestProfile.id);
196
+
197
+ let seededConsoleOwnerUserId = 0;
198
+ if (
199
+ consoleService &&
200
+ typeof consoleService.ensureInitialConsoleMember === "function"
201
+ ) {
202
+ seededConsoleOwnerUserId = Number(await consoleService.ensureInitialConsoleMember(latestProfile.id));
203
+ }
204
+
205
+ payload = {
206
+ session: {
207
+ authenticated: true,
208
+ userId: latestProfile.id
209
+ },
210
+ profile: {
211
+ displayName: latestProfile.displayName,
212
+ email: latestProfile.email,
213
+ avatar: accountAvatarFormatter(latestProfile, userSettings)
214
+ },
215
+ tenancy: resolvedTenancyProfile,
216
+ app: appState,
217
+ workspaces: [],
218
+ pendingInvites: [],
219
+ activeWorkspace: null,
220
+ membership: null,
221
+ requestedWorkspace: null,
222
+ permissions: [],
223
+ surfaceAccess: {
224
+ consoleowner: seededConsoleOwnerUserId > 0 && seededConsoleOwnerUserId === Number(latestProfile.id)
225
+ },
226
+ workspaceSettings: null,
227
+ userSettings: mapUserSettingsBootstrap(userSettings),
228
+ requestMeta: {
229
+ hasRequest: Boolean(request)
230
+ }
231
+ };
232
+ }
233
+
234
+ const oauthCatalogPayload = getOAuthProviderCatalogPayload(authService);
235
+ const session = payload?.session && typeof payload.session === "object" ? payload.session : { authenticated: false };
236
+
237
+ return {
238
+ ...payload,
239
+ session: {
240
+ ...session,
241
+ ...oauthCatalogPayload
242
+ }
243
+ };
244
+ }
245
+ });
246
+ }
247
+
248
+ export { createUsersBootstrapContributor };
@@ -1,13 +1,7 @@
1
- import { AppError } from "@jskit-ai/kernel/server/runtime";
2
1
  import { requireServiceMethod } from "@jskit-ai/kernel/shared/actions/actionContributorHelpers";
3
- import { normalizeLowerText, normalizeText } from "@jskit-ai/kernel/shared/actions/textNormalization";
2
+ import { normalizeLowerText } from "@jskit-ai/kernel/shared/actions/textNormalization";
4
3
  import {
5
4
  TENANCY_MODE_NONE,
6
- TENANCY_MODE_PERSONAL,
7
- TENANCY_MODE_WORKSPACES,
8
- WORKSPACE_SLUG_POLICY_NONE,
9
- WORKSPACE_SLUG_POLICY_IMMUTABLE_USERNAME,
10
- WORKSPACE_SLUG_POLICY_USER_SELECTED,
11
5
  resolveTenancyProfile
12
6
  } from "../shared/tenancyProfile.js";
13
7
  import { workspacePendingInvitationsResource } from "../shared/resources/workspacePendingInvitationsResource.js";
@@ -16,9 +10,6 @@ import {
16
10
  mapWorkspaceSettingsPublic,
17
11
  mapWorkspaceSummary
18
12
  } from "./common/formatters/workspaceFormatter.js";
19
- import { accountAvatarFormatter } from "./common/formatters/accountAvatarFormatter.js";
20
- import { authenticatedUserValidator } from "./common/validators/authenticatedUserValidator.js";
21
- import { userSettingsFields } from "../shared/resources/userSettingsFields.js";
22
13
 
23
14
  const REQUESTED_WORKSPACE_STATUS_RESOLVED = "resolved";
24
15
  const REQUESTED_WORKSPACE_STATUS_NOT_FOUND = "not_found";
@@ -31,47 +22,6 @@ function normalizePendingInvites(invites) {
31
22
  }).pendingInvites;
32
23
  }
33
24
 
34
- function getOAuthProviderCatalogPayload(authService) {
35
- if (!authService || typeof authService.getOAuthProviderCatalog !== "function") {
36
- return {
37
- oauthProviders: [],
38
- oauthDefaultProvider: null
39
- };
40
- }
41
-
42
- const catalog = authService.getOAuthProviderCatalog();
43
- const providers = Array.isArray(catalog?.providers)
44
- ? catalog.providers
45
- .map((provider) => ({
46
- id: normalizeLowerText(provider?.id),
47
- label: normalizeText(provider?.label)
48
- }))
49
- .filter((provider) => provider.id && provider.label)
50
- : [];
51
- const defaultProvider = normalizeLowerText(catalog?.defaultProvider);
52
-
53
- return {
54
- oauthProviders: providers,
55
- oauthDefaultProvider: providers.some((provider) => provider.id === defaultProvider) ? defaultProvider : null
56
- };
57
- }
58
-
59
- function normalizeBoolean(value, fallback) {
60
- if (typeof value === "boolean") {
61
- return value;
62
- }
63
- if (typeof value === "string") {
64
- const normalized = normalizeLowerText(value);
65
- if (normalized === "true") {
66
- return true;
67
- }
68
- if (normalized === "false") {
69
- return false;
70
- }
71
- }
72
- return fallback;
73
- }
74
-
75
25
  function normalizeQueryPayload(value = {}) {
76
26
  if (!value || typeof value !== "object" || Array.isArray(value)) {
77
27
  return {};
@@ -137,111 +87,28 @@ function resolveRequestedWorkspaceStatusFromError(error) {
137
87
  return "";
138
88
  }
139
89
 
140
- function resolveAppState(appConfig = {}, { workspaceInvitationsEnabled = true } = {}) {
141
- const features = {
142
- workspaceSwitching: normalizeBoolean(appConfig.workspaceSwitching, true),
143
- workspaceInvites: workspaceInvitationsEnabled === true,
144
- assistantEnabled: normalizeBoolean(appConfig.assistantEnabled, false),
145
- assistantRequiredPermission: normalizeText(appConfig.assistantRequiredPermission),
146
- socialEnabled: normalizeBoolean(appConfig.socialEnabled, false),
147
- socialFederationEnabled: normalizeBoolean(appConfig.socialFederationEnabled, false)
148
- };
149
-
150
- return {
151
- features
152
- };
153
- }
154
-
155
- function normalizeSlugPolicy(value = "") {
156
- const normalizedValue = normalizeLowerText(value);
157
- if (
158
- normalizedValue === WORKSPACE_SLUG_POLICY_IMMUTABLE_USERNAME ||
159
- normalizedValue === WORKSPACE_SLUG_POLICY_USER_SELECTED
160
- ) {
161
- return normalizedValue;
162
- }
163
- return WORKSPACE_SLUG_POLICY_NONE;
164
- }
165
-
166
- function isSupportedTenancyMode(value = "") {
167
- return value === TENANCY_MODE_NONE || value === TENANCY_MODE_PERSONAL || value === TENANCY_MODE_WORKSPACES;
168
- }
169
-
170
90
  function resolveBootstrapTenancyProfile(tenancyProfile = null, appConfig = {}) {
171
91
  const fallback = resolveTenancyProfile(appConfig);
172
- const source = tenancyProfile && typeof tenancyProfile === "object" ? tenancyProfile : fallback;
173
- const mode = isSupportedTenancyMode(source?.mode) ? source.mode : fallback.mode;
174
- const workspace = source?.workspace && typeof source.workspace === "object" ? source.workspace : fallback.workspace;
175
-
176
92
  return Object.freeze({
177
- mode,
93
+ mode: fallback.mode,
178
94
  workspace: Object.freeze({
179
- enabled: workspace.enabled === true,
180
- autoProvision: workspace.autoProvision === true,
181
- allowSelfCreate: workspace.allowSelfCreate === true,
182
- slugPolicy: normalizeSlugPolicy(workspace.slugPolicy)
95
+ enabled: fallback.workspace.enabled === true,
96
+ autoProvision: fallback.workspace.autoProvision === true,
97
+ allowSelfCreate: fallback.workspace.allowSelfCreate === true,
98
+ slugPolicy: fallback.workspace.slugPolicy
183
99
  })
184
100
  });
185
101
  }
186
102
 
187
- function createAnonymousBootstrapPayload({ appState, tenancyProfile }) {
188
- return {
189
- session: {
190
- authenticated: false
191
- },
192
- profile: null,
193
- tenancy: tenancyProfile,
194
- app: appState,
195
- workspaces: [],
196
- pendingInvites: [],
197
- activeWorkspace: null,
198
- membership: null,
199
- requestedWorkspace: null,
200
- permissions: [],
201
- surfaceAccess: {
202
- consoleowner: false
203
- },
204
- workspaceSettings: null,
205
- userSettings: null
206
- };
207
- }
208
-
209
- function mapUserSettingsBootstrap(settings = {}) {
210
- const source = settings && typeof settings === "object" ? settings : {};
211
- const mapped = {};
212
-
213
- for (const field of userSettingsFields) {
214
- if (field.includeInBootstrap === false) {
215
- continue;
216
- }
217
- const rawValue = Object.hasOwn(source, field.key)
218
- ? source[field.key]
219
- : field.resolveDefault({
220
- settings: source
221
- });
222
- mapped[field.key] = field.normalizeOutput(rawValue, {
223
- settings: source
224
- });
225
- }
226
-
227
- return mapped;
228
- }
229
-
230
103
  function createWorkspaceBootstrapContributor({
231
104
  workspaceService,
232
105
  workspacePendingInvitationsService,
233
- userProfilesRepository,
234
- userSettingsRepository,
106
+ usersRepository,
235
107
  workspaceInvitationsEnabled = false,
236
108
  appConfig = {},
237
- tenancyProfile = null,
238
- authService,
239
- consoleService = null
109
+ tenancyProfile = null
240
110
  } = {}) {
241
- const contributorId = "users.bootstrap";
242
- const appState = resolveAppState(appConfig, {
243
- workspaceInvitationsEnabled
244
- });
111
+ const contributorId = "users.workspace.bootstrap";
245
112
  const resolvedTenancyProfile = resolveBootstrapTenancyProfile(tenancyProfile, appConfig);
246
113
 
247
114
  requireServiceMethod(workspaceService, "listWorkspacesForUser", contributorId, {
@@ -255,144 +122,83 @@ function createWorkspaceBootstrapContributor({
255
122
  serviceLabel: "workspacePendingInvitationsService"
256
123
  });
257
124
  }
258
- requireServiceMethod(userProfilesRepository, "findByIdentity", contributorId, {
259
- serviceLabel: "userProfilesRepository"
260
- });
261
- requireServiceMethod(userSettingsRepository, "ensureForUserId", contributorId, {
262
- serviceLabel: "userSettingsRepository"
125
+ requireServiceMethod(usersRepository, "findById", contributorId, {
126
+ serviceLabel: "usersRepository"
263
127
  });
264
128
 
265
129
  return Object.freeze({
266
130
  contributorId,
267
- async contribute({ request = null, reply = null, query = {} } = {}) {
268
- const authResult = await request.executeAction({
269
- actionId: "auth.session.read"
270
- });
131
+ async contribute({ request = null, query = {}, payload = {} } = {}) {
132
+ const normalizedUserId = Number(payload?.session?.authenticated === true ? payload?.session?.userId : 0);
133
+ const normalizedWorkspaceSlug = resolveBootstrapWorkspaceSlug({ query, request });
134
+ if (!normalizedUserId) {
135
+ if (!normalizedWorkspaceSlug || resolvedTenancyProfile.mode === TENANCY_MODE_NONE) {
136
+ return {};
137
+ }
271
138
 
272
- if (authResult?.clearSession === true && typeof authService?.clearSessionCookies === "function") {
273
- authService.clearSessionCookies(reply);
274
- }
275
- if (authResult?.session && typeof authService?.writeSessionCookies === "function") {
276
- authService.writeSessionCookies(reply, authResult.session);
277
- }
278
- if (authResult?.transientFailure === true) {
279
- throw new AppError(503, "Authentication service temporarily unavailable. Please retry.");
139
+ return {
140
+ requestedWorkspace: createRequestedWorkspacePayload(
141
+ normalizedWorkspaceSlug,
142
+ REQUESTED_WORKSPACE_STATUS_UNAUTHENTICATED
143
+ )
144
+ };
280
145
  }
281
- let seededConsoleOwnerUserId = 0;
282
- if (
283
- authResult?.authenticated &&
284
- authResult?.profile?.id != null &&
285
- consoleService &&
286
- typeof consoleService.ensureInitialConsoleMember === "function"
287
- ) {
288
- seededConsoleOwnerUserId = Number(await consoleService.ensureInitialConsoleMember(authResult.profile.id));
146
+
147
+ const latestProfile = await usersRepository.findById(normalizedUserId);
148
+ if (!latestProfile) {
149
+ return {};
289
150
  }
290
151
 
291
- const user = authResult?.authenticated ? authResult.profile : null;
292
- const normalizedUser = authenticatedUserValidator.normalize(user);
293
152
  const pendingInvites =
294
- workspaceInvitationsEnabled && normalizedUser
153
+ workspaceInvitationsEnabled
295
154
  ? normalizePendingInvites(
296
- await workspacePendingInvitationsService.listPendingInvitesForUser(normalizedUser, {
155
+ await workspacePendingInvitationsService.listPendingInvitesForUser(latestProfile, {
297
156
  context: {
298
- actor: normalizedUser
157
+ actor: latestProfile
299
158
  }
300
159
  })
301
160
  )
302
161
  : [];
303
- const normalizedWorkspaceSlug = resolveBootstrapWorkspaceSlug({ query, request });
304
- let payload = createAnonymousBootstrapPayload({
305
- appState,
306
- tenancyProfile: resolvedTenancyProfile
307
- });
308
- if (normalizedWorkspaceSlug && !normalizedUser) {
309
- payload = {
310
- ...payload,
311
- requestedWorkspace: createRequestedWorkspacePayload(
162
+ const workspaces = await workspaceService.listWorkspacesForUser(latestProfile, { request });
163
+ let workspaceContext = null;
164
+ let requestedWorkspace = null;
165
+ if (normalizedWorkspaceSlug && resolvedTenancyProfile.mode !== TENANCY_MODE_NONE) {
166
+ try {
167
+ workspaceContext = await workspaceService.resolveWorkspaceContextForUserBySlug(
168
+ latestProfile,
312
169
  normalizedWorkspaceSlug,
313
- REQUESTED_WORKSPACE_STATUS_UNAUTHENTICATED
314
- )
315
- };
316
- }
317
-
318
- if (normalizedUser) {
319
- const latestProfile =
320
- (await userProfilesRepository.findByIdentity({
321
- provider: normalizedUser.authProvider,
322
- providerUserId: normalizedUser.authProviderUserSid
323
- })) || normalizedUser;
324
-
325
- const workspaces = await workspaceService.listWorkspacesForUser(latestProfile, { request });
326
- let workspaceContext = null;
327
- let requestedWorkspace = null;
328
- if (normalizedWorkspaceSlug && resolvedTenancyProfile.mode !== TENANCY_MODE_NONE) {
329
- try {
330
- workspaceContext = await workspaceService.resolveWorkspaceContextForUserBySlug(
331
- latestProfile,
332
- normalizedWorkspaceSlug,
333
- { request }
334
- );
335
- requestedWorkspace = createRequestedWorkspacePayload(
336
- normalizedWorkspaceSlug,
337
- REQUESTED_WORKSPACE_STATUS_RESOLVED
338
- );
339
- } catch (error) {
340
- const requestedWorkspaceStatus = resolveRequestedWorkspaceStatusFromError(error);
341
- if (!requestedWorkspaceStatus) {
342
- throw error;
343
- }
344
- requestedWorkspace = createRequestedWorkspacePayload(normalizedWorkspaceSlug, requestedWorkspaceStatus);
170
+ { request }
171
+ );
172
+ requestedWorkspace = createRequestedWorkspacePayload(
173
+ normalizedWorkspaceSlug,
174
+ REQUESTED_WORKSPACE_STATUS_RESOLVED
175
+ );
176
+ } catch (error) {
177
+ const requestedWorkspaceStatus = resolveRequestedWorkspaceStatusFromError(error);
178
+ if (!requestedWorkspaceStatus) {
179
+ throw error;
345
180
  }
181
+ requestedWorkspace = createRequestedWorkspacePayload(normalizedWorkspaceSlug, requestedWorkspaceStatus);
346
182
  }
347
-
348
- const userSettings = await userSettingsRepository.ensureForUserId(latestProfile.id);
349
- payload = {
350
- session: {
351
- authenticated: true,
352
- userId: latestProfile.id
353
- },
354
- profile: {
355
- displayName: latestProfile.displayName,
356
- email: latestProfile.email,
357
- avatar: accountAvatarFormatter(latestProfile, userSettings)
358
- },
359
- tenancy: resolvedTenancyProfile,
360
- app: appState,
361
- workspaces: [...workspaces],
362
- pendingInvites,
363
- activeWorkspace: workspaceContext
364
- ? mapWorkspaceSummary(workspaceContext.workspace, {
365
- roleSid: workspaceContext.membership?.roleSid,
366
- status: workspaceContext.membership?.status
367
- })
368
- : null,
369
- membership: mapMembershipSummary(workspaceContext?.membership, workspaceContext?.workspace),
370
- requestedWorkspace,
371
- permissions: workspaceContext ? [...workspaceContext.permissions] : [],
372
- surfaceAccess: {
373
- consoleowner: seededConsoleOwnerUserId > 0 && seededConsoleOwnerUserId === Number(latestProfile.id)
374
- },
375
- workspaceSettings: workspaceContext
376
- ? mapWorkspaceSettingsPublic(workspaceContext.workspaceSettings, {
377
- workspaceInvitationsEnabled
378
- })
379
- : null,
380
- userSettings: mapUserSettingsBootstrap(userSettings),
381
- requestMeta: {
382
- hasRequest: Boolean(request)
383
- }
384
- };
385
183
  }
386
184
 
387
- const oauthCatalogPayload = getOAuthProviderCatalogPayload(authService);
388
- const session = payload?.session && typeof payload.session === "object" ? payload.session : { authenticated: false };
389
-
390
185
  return {
391
- ...payload,
392
- session: {
393
- ...session,
394
- ...oauthCatalogPayload
395
- }
186
+ workspaces: [...workspaces],
187
+ pendingInvites,
188
+ activeWorkspace: workspaceContext
189
+ ? mapWorkspaceSummary(workspaceContext.workspace, {
190
+ roleSid: workspaceContext.membership?.roleSid,
191
+ status: workspaceContext.membership?.status
192
+ })
193
+ : null,
194
+ membership: mapMembershipSummary(workspaceContext?.membership, workspaceContext?.workspace),
195
+ requestedWorkspace,
196
+ permissions: workspaceContext ? [...workspaceContext.permissions] : [],
197
+ workspaceSettings: workspaceContext
198
+ ? mapWorkspaceSettingsPublic(workspaceContext.workspaceSettings, {
199
+ workspaceInvitationsEnabled
200
+ })
201
+ : null
396
202
  };
397
203
  }
398
204
  });