@jskit-ai/users-core 0.1.48 → 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.
- package/package.descriptor.mjs +7 -7
- package/package.json +7 -17
- package/src/server/common/services/authProfileSyncService.js +28 -7
- package/src/server/common/support/realtimeServiceEvents.js +1 -59
- package/src/server/profileSyncLifecycleContributorRegistry.js +56 -0
- package/src/server/registerUsersBootstrap.js +0 -1
- package/src/server/registerUsersCore.js +2 -14
- package/src/server/usersBootstrapContributor.js +2 -64
- package/src/shared/index.js +2 -99
- package/src/shared/settings.js +1 -119
- package/test/authProfileSyncService.test.js +19 -10
- package/test/registerServiceRealtimeEvents.test.js +0 -86
- package/test/registerUsersCore.test.js +6 -15
- package/test/repositoryContracts.test.js +1 -9
- package/test/resourcesCanonical.test.js +0 -16
- package/test/settingsFieldRegistriesSingleton.test.js +0 -5
- package/test/usersBootstrapContributor.test.js +2 -26
- package/test/usersRouteResources.test.js +0 -16
- package/src/server/UsersWorkspacesServiceProvider.js +0 -44
- package/src/server/common/contributors/workspaceActionContextContributor.js +0 -88
- package/src/server/common/contributors/workspaceAuthPolicyContextResolver.js +0 -34
- package/src/server/common/contributors/workspaceRouteVisibilityResolver.js +0 -78
- package/src/server/common/formatters/workspaceFormatter.js +0 -53
- package/src/server/common/repositories/workspaceInvitesRepository.js +0 -208
- package/src/server/common/repositories/workspaceMembershipsRepository.js +0 -190
- package/src/server/common/repositories/workspacesRepository.js +0 -202
- package/src/server/common/services/workspaceContextService.js +0 -281
- package/src/server/common/support/workspaceRoutePaths.js +0 -17
- package/src/server/common/validators/routeParamsValidator.js +0 -62
- package/src/server/registerWorkspaceBootstrap.js +0 -27
- package/src/server/registerWorkspaceCore.js +0 -73
- package/src/server/registerWorkspaceRepositories.js +0 -26
- package/src/server/support/resolveWorkspace.js +0 -16
- package/src/server/support/workspaceActionSurfaces.js +0 -118
- package/src/server/support/workspaceInvitationsPolicy.js +0 -45
- package/src/server/support/workspaceRouteInput.js +0 -22
- package/src/server/workspaceBootstrapContributor.js +0 -212
- package/src/server/workspaceDirectory/bootWorkspaceDirectoryRoutes.js +0 -133
- package/src/server/workspaceDirectory/registerWorkspaceDirectory.js +0 -19
- package/src/server/workspaceDirectory/workspaceDirectoryActions.js +0 -133
- package/src/server/workspaceMembers/bootWorkspaceMembers.js +0 -236
- package/src/server/workspaceMembers/registerWorkspaceMembers.js +0 -108
- package/src/server/workspaceMembers/workspaceMembersActions.js +0 -186
- package/src/server/workspaceMembers/workspaceMembersService.js +0 -222
- package/src/server/workspacePendingInvitations/bootWorkspacePendingInvitations.js +0 -62
- package/src/server/workspacePendingInvitations/registerWorkspacePendingInvitations.js +0 -119
- package/src/server/workspacePendingInvitations/workspacePendingInvitationsActions.js +0 -74
- package/src/server/workspacePendingInvitations/workspacePendingInvitationsService.js +0 -138
- package/src/server/workspaceSettings/bootWorkspaceSettings.js +0 -76
- package/src/server/workspaceSettings/registerWorkspaceSettings.js +0 -62
- package/src/server/workspaceSettings/workspaceSettingsActions.js +0 -72
- package/src/server/workspaceSettings/workspaceSettingsRepository.js +0 -154
- package/src/server/workspaceSettings/workspaceSettingsService.js +0 -66
- package/src/shared/resources/workspaceMembersResource.js +0 -354
- package/src/shared/resources/workspacePendingInvitationsResource.js +0 -82
- package/src/shared/resources/workspaceResource.js +0 -176
- package/src/shared/resources/workspaceSettingsFields.js +0 -59
- package/src/shared/resources/workspaceSettingsResource.js +0 -169
- package/src/shared/roles.js +0 -161
- package/src/shared/support/usersApiPaths.js +0 -43
- package/src/shared/support/usersVisibility.js +0 -42
- package/src/shared/support/workspacePathModel.js +0 -145
- package/src/shared/tenancyMode.js +0 -35
- package/src/shared/tenancyProfile.js +0 -73
- package/test/registerWorkspaceDirectory.test.js +0 -31
- package/test/registerWorkspaceSettings.test.js +0 -40
- package/test/roles.test.js +0 -159
- package/test/tenancyProfile.test.js +0 -67
- package/test/usersApiPaths.test.js +0 -49
- package/test/usersRouteValidators.test.js +0 -49
- package/test/usersVisibility.test.js +0 -27
- package/test/workspaceActionContextContributor.test.js +0 -344
- package/test/workspaceActionSurfaces.test.js +0 -85
- package/test/workspaceAuthPolicyContextResolver.test.js +0 -119
- package/test/workspaceBootstrapContributor.test.js +0 -154
- package/test/workspaceInvitationsPolicy.test.js +0 -71
- package/test/workspaceInvitesRepository.test.js +0 -111
- package/test/workspaceMembersService.test.js +0 -398
- package/test/workspacePathModel.test.js +0 -93
- package/test/workspacePendingInvitationsResource.test.js +0 -38
- package/test/workspacePendingInvitationsService.test.js +0 -151
- package/test/workspaceRouteVisibilityResolver.test.js +0 -83
- package/test/workspaceService.test.js +0 -546
- package/test/workspaceSettingsActions.test.js +0 -52
- package/test/workspaceSettingsRepository.test.js +0 -202
- package/test/workspaceSettingsResource.test.js +0 -169
- package/test/workspaceSettingsService.test.js +0 -140
package/package.descriptor.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export default Object.freeze({
|
|
2
2
|
packageVersion: 1,
|
|
3
3
|
packageId: "@jskit-ai/users-core",
|
|
4
|
-
version: "0.1.
|
|
4
|
+
version: "0.1.49",
|
|
5
5
|
kind: "runtime",
|
|
6
6
|
description: "Users/account runtime plus HTTP routes for account features.",
|
|
7
7
|
dependsOn: [
|
|
@@ -48,7 +48,7 @@ export default Object.freeze({
|
|
|
48
48
|
},
|
|
49
49
|
{
|
|
50
50
|
subpath: "./shared",
|
|
51
|
-
summary: "Exports shared users settings and
|
|
51
|
+
summary: "Exports shared users settings resources and defaults."
|
|
52
52
|
},
|
|
53
53
|
{
|
|
54
54
|
subpath: "./client",
|
|
@@ -128,11 +128,11 @@ export default Object.freeze({
|
|
|
128
128
|
mutations: {
|
|
129
129
|
dependencies: {
|
|
130
130
|
runtime: {
|
|
131
|
-
"@jskit-ai/auth-core": "0.1.
|
|
132
|
-
"@jskit-ai/database-runtime": "0.1.
|
|
133
|
-
"@jskit-ai/http-runtime": "0.1.
|
|
134
|
-
"@jskit-ai/kernel": "0.1.
|
|
135
|
-
"@jskit-ai/uploads-runtime": "0.1.
|
|
131
|
+
"@jskit-ai/auth-core": "0.1.38",
|
|
132
|
+
"@jskit-ai/database-runtime": "0.1.39",
|
|
133
|
+
"@jskit-ai/http-runtime": "0.1.38",
|
|
134
|
+
"@jskit-ai/kernel": "0.1.39",
|
|
135
|
+
"@jskit-ai/uploads-runtime": "0.1.17",
|
|
136
136
|
"@fastify/type-provider-typebox": "^6.1.0",
|
|
137
137
|
typebox: "^1.0.81"
|
|
138
138
|
},
|
package/package.json
CHANGED
|
@@ -1,33 +1,23 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jskit-ai/users-core",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.49",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"test": "node --test"
|
|
7
7
|
},
|
|
8
8
|
"exports": {
|
|
9
|
-
"./server/
|
|
10
|
-
"./server/support/workspaceRouteInput": "./src/server/support/workspaceRouteInput.js",
|
|
11
|
-
"./server/support/resolveWorkspace": "./src/server/support/resolveWorkspace.js",
|
|
12
|
-
"./server/validators/routeParamsValidator": "./src/server/common/validators/routeParamsValidator.js",
|
|
9
|
+
"./server/profileSyncLifecycleContributorRegistry": "./src/server/profileSyncLifecycleContributorRegistry.js",
|
|
13
10
|
"./shared/settings": "./src/shared/settings.js",
|
|
14
|
-
"./shared/tenancyProfile": "./src/shared/tenancyProfile.js",
|
|
15
|
-
"./shared/support/usersVisibility": "./src/shared/support/usersVisibility.js",
|
|
16
|
-
"./shared/support/workspacePathModel": "./src/shared/support/workspacePathModel.js",
|
|
17
|
-
"./shared/support/usersApiPaths": "./src/shared/support/usersApiPaths.js",
|
|
18
|
-
"./shared/resources/workspaceResource": "./src/shared/resources/workspaceResource.js",
|
|
19
|
-
"./shared/resources/workspaceSettingsResource": "./src/shared/resources/workspaceSettingsResource.js",
|
|
20
|
-
"./shared/resources/workspaceSettingsFields": "./src/shared/resources/workspaceSettingsFields.js",
|
|
21
11
|
"./shared/resources/userProfileResource": "./src/shared/resources/userProfileResource.js",
|
|
22
12
|
"./shared/resources/userSettingsFields": "./src/shared/resources/userSettingsFields.js",
|
|
23
13
|
"./shared/resources/userSettingsResource": "./src/shared/resources/userSettingsResource.js"
|
|
24
14
|
},
|
|
25
15
|
"dependencies": {
|
|
26
|
-
"@jskit-ai/auth-core": "0.1.
|
|
27
|
-
"@jskit-ai/database-runtime": "0.1.
|
|
28
|
-
"@jskit-ai/http-runtime": "0.1.
|
|
29
|
-
"@jskit-ai/kernel": "0.1.
|
|
30
|
-
"@jskit-ai/uploads-runtime": "0.1.
|
|
16
|
+
"@jskit-ai/auth-core": "0.1.38",
|
|
17
|
+
"@jskit-ai/database-runtime": "0.1.39",
|
|
18
|
+
"@jskit-ai/http-runtime": "0.1.38",
|
|
19
|
+
"@jskit-ai/kernel": "0.1.39",
|
|
20
|
+
"@jskit-ai/uploads-runtime": "0.1.17",
|
|
31
21
|
"@fastify/type-provider-typebox": "^6.1.0",
|
|
32
22
|
"typebox": "^1.0.81"
|
|
33
23
|
}
|
|
@@ -54,7 +54,17 @@ function requireSynchronizedProfile(profile) {
|
|
|
54
54
|
throw new Error("Profile synchronization failed.");
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
function
|
|
57
|
+
function normalizeLifecycleContributors(entries = []) {
|
|
58
|
+
if (!Array.isArray(entries)) {
|
|
59
|
+
return [];
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return entries.filter(
|
|
63
|
+
(entry) => entry && typeof entry === "object" && typeof entry.afterIdentityProfileSynced === "function"
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function createService({ usersRepository, lifecycleContributors = [], userSettingsRepository = null } = {}) {
|
|
58
68
|
if (!usersRepository || typeof usersRepository.findByIdentity !== "function") {
|
|
59
69
|
throw new Error("authProfileSyncService requires usersRepository.findByIdentity().");
|
|
60
70
|
}
|
|
@@ -68,6 +78,8 @@ function createService({ usersRepository, workspaceProvisioningService = null, u
|
|
|
68
78
|
throw new Error("authProfileSyncService requires userSettingsRepository.ensureForUserId().");
|
|
69
79
|
}
|
|
70
80
|
|
|
81
|
+
const normalizedLifecycleContributors = normalizeLifecycleContributors(lifecycleContributors);
|
|
82
|
+
|
|
71
83
|
async function findByIdentity(identityLike, options = {}) {
|
|
72
84
|
const normalized = buildNormalizedIdentityKey(identityLike);
|
|
73
85
|
return usersRepository.findByIdentity(
|
|
@@ -99,21 +111,30 @@ function createService({ usersRepository, workspaceProvisioningService = null, u
|
|
|
99
111
|
const runSync = async (trx = null) => {
|
|
100
112
|
const operationOptions = trx ? { ...options, trx } : options;
|
|
101
113
|
const existing = await findByIdentity(normalized, operationOptions);
|
|
114
|
+
let created = false;
|
|
102
115
|
if (!profileNeedsUpdate(existing, normalized)) {
|
|
103
116
|
const synchronizedProfile = requireSynchronizedProfile(existing);
|
|
104
117
|
await userSettingsRepository.ensureForUserId(synchronizedProfile.id, operationOptions);
|
|
118
|
+
for (const contributor of normalizedLifecycleContributors) {
|
|
119
|
+
await contributor.afterIdentityProfileSynced({
|
|
120
|
+
profile: synchronizedProfile,
|
|
121
|
+
created,
|
|
122
|
+
options: operationOptions
|
|
123
|
+
});
|
|
124
|
+
}
|
|
105
125
|
return synchronizedProfile;
|
|
106
126
|
}
|
|
107
127
|
|
|
108
128
|
const upserted = await upsertByIdentity(normalized, operationOptions);
|
|
109
129
|
const synchronizedProfile = requireSynchronizedProfile(upserted);
|
|
110
130
|
await userSettingsRepository.ensureForUserId(synchronizedProfile.id, operationOptions);
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
131
|
+
created = !existing;
|
|
132
|
+
for (const contributor of normalizedLifecycleContributors) {
|
|
133
|
+
await contributor.afterIdentityProfileSynced({
|
|
134
|
+
profile: synchronizedProfile,
|
|
135
|
+
created,
|
|
136
|
+
options: operationOptions
|
|
137
|
+
});
|
|
117
138
|
}
|
|
118
139
|
|
|
119
140
|
return synchronizedProfile;
|
|
@@ -5,12 +5,6 @@ function resolveActorScopedEntityId({ options } = {}) {
|
|
|
5
5
|
return normalizeRecordId(options?.context?.actor?.id, { fallback: "" });
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
-
function resolveWorkspaceSlugPayload({ args } = {}) {
|
|
9
|
-
return {
|
|
10
|
-
workspaceSlug: String(args?.[0]?.slug || "").trim()
|
|
11
|
-
};
|
|
12
|
-
}
|
|
13
|
-
|
|
14
8
|
const ACCOUNT_SETTINGS_AND_BOOTSTRAP_EVENTS = deepFreeze([
|
|
15
9
|
{
|
|
16
10
|
type: "entity.changed",
|
|
@@ -36,56 +30,4 @@ const ACCOUNT_SETTINGS_AND_BOOTSTRAP_EVENTS = deepFreeze([
|
|
|
36
30
|
}
|
|
37
31
|
]);
|
|
38
32
|
|
|
39
|
-
|
|
40
|
-
workspaceEntity,
|
|
41
|
-
workspaceOperation,
|
|
42
|
-
workspaceRealtimeEvent,
|
|
43
|
-
workspaceEntityId = ({ args }) => args?.[0]?.id,
|
|
44
|
-
bootstrapEntityId = ({ args }) => args?.[0]?.id,
|
|
45
|
-
bootstrapAudience = "event_scope"
|
|
46
|
-
} = {}) {
|
|
47
|
-
const normalizedWorkspaceEntity = String(workspaceEntity || "").trim();
|
|
48
|
-
const normalizedWorkspaceOperation = String(workspaceOperation || "")
|
|
49
|
-
.trim()
|
|
50
|
-
.toLowerCase();
|
|
51
|
-
const normalizedWorkspaceRealtimeEvent = String(workspaceRealtimeEvent || "").trim();
|
|
52
|
-
if (!normalizedWorkspaceEntity || !normalizedWorkspaceOperation || !normalizedWorkspaceRealtimeEvent) {
|
|
53
|
-
throw new Error(
|
|
54
|
-
"createWorkspaceEntityAndBootstrapEvents requires workspaceEntity, workspaceOperation, and workspaceRealtimeEvent."
|
|
55
|
-
);
|
|
56
|
-
}
|
|
57
|
-
if (typeof workspaceEntityId !== "function") {
|
|
58
|
-
throw new Error("createWorkspaceEntityAndBootstrapEvents requires workspaceEntityId to be a function.");
|
|
59
|
-
}
|
|
60
|
-
if (typeof bootstrapEntityId !== "function") {
|
|
61
|
-
throw new Error("createWorkspaceEntityAndBootstrapEvents requires bootstrapEntityId to be a function.");
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
return deepFreeze([
|
|
65
|
-
{
|
|
66
|
-
type: "entity.changed",
|
|
67
|
-
source: "workspace",
|
|
68
|
-
entity: normalizedWorkspaceEntity,
|
|
69
|
-
operation: normalizedWorkspaceOperation,
|
|
70
|
-
entityId: (payload = {}) => normalizeRecordId(workspaceEntityId(payload), { fallback: "" }),
|
|
71
|
-
realtime: {
|
|
72
|
-
event: normalizedWorkspaceRealtimeEvent,
|
|
73
|
-
payload: resolveWorkspaceSlugPayload,
|
|
74
|
-
audience: "event_scope"
|
|
75
|
-
}
|
|
76
|
-
},
|
|
77
|
-
{
|
|
78
|
-
type: "entity.changed",
|
|
79
|
-
source: "users",
|
|
80
|
-
entity: "bootstrap",
|
|
81
|
-
operation: "updated",
|
|
82
|
-
entityId: (payload = {}) => normalizeRecordId(bootstrapEntityId(payload), { fallback: "" }),
|
|
83
|
-
realtime: {
|
|
84
|
-
event: "users.bootstrap.changed",
|
|
85
|
-
audience: bootstrapAudience
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
]);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
export { ACCOUNT_SETTINGS_AND_BOOTSTRAP_EVENTS, createWorkspaceEntityAndBootstrapEvents };
|
|
33
|
+
export { ACCOUNT_SETTINGS_AND_BOOTSTRAP_EVENTS };
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { registerTaggedSingleton, resolveTaggedEntries } from "@jskit-ai/kernel/server/registries";
|
|
2
|
+
|
|
3
|
+
const PROFILE_SYNC_LIFECYCLE_CONTRIBUTOR_TAG = "jskit.users.profileSync.lifecycleContributors";
|
|
4
|
+
|
|
5
|
+
function normalizeProfileSyncLifecycleContributor(entry) {
|
|
6
|
+
if (typeof entry === "function") {
|
|
7
|
+
return Object.freeze({
|
|
8
|
+
contributorId: String(entry.name || "anonymous"),
|
|
9
|
+
order: 0,
|
|
10
|
+
afterIdentityProfileSynced: entry
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
if (!entry || typeof entry !== "object" || typeof entry.afterIdentityProfileSynced !== "function") {
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const contributorId = String(entry.contributorId || "anonymous");
|
|
19
|
+
const order = Number.isFinite(entry.order) ? Number(entry.order) : 0;
|
|
20
|
+
|
|
21
|
+
return Object.freeze({
|
|
22
|
+
...entry,
|
|
23
|
+
contributorId,
|
|
24
|
+
order,
|
|
25
|
+
afterIdentityProfileSynced: entry.afterIdentityProfileSynced
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function registerProfileSyncLifecycleContributor(app, token, factory) {
|
|
30
|
+
registerTaggedSingleton(app, token, factory, PROFILE_SYNC_LIFECYCLE_CONTRIBUTOR_TAG, {
|
|
31
|
+
context: "registerProfileSyncLifecycleContributor"
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function resolveProfileSyncLifecycleContributors(scope) {
|
|
36
|
+
return resolveTaggedEntries(scope, PROFILE_SYNC_LIFECYCLE_CONTRIBUTOR_TAG)
|
|
37
|
+
.map((entry, index) => ({
|
|
38
|
+
contributor: normalizeProfileSyncLifecycleContributor(entry),
|
|
39
|
+
index
|
|
40
|
+
}))
|
|
41
|
+
.filter((entry) => Boolean(entry.contributor))
|
|
42
|
+
.sort((left, right) => {
|
|
43
|
+
if (left.contributor.order !== right.contributor.order) {
|
|
44
|
+
return left.contributor.order - right.contributor.order;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return left.index - right.index;
|
|
48
|
+
})
|
|
49
|
+
.map((entry) => entry.contributor);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export {
|
|
53
|
+
PROFILE_SYNC_LIFECYCLE_CONTRIBUTOR_TAG,
|
|
54
|
+
registerProfileSyncLifecycleContributor,
|
|
55
|
+
resolveProfileSyncLifecycleContributors
|
|
56
|
+
};
|
|
@@ -12,7 +12,6 @@ function registerUsersBootstrap(app) {
|
|
|
12
12
|
usersRepository: scope.make("usersRepository"),
|
|
13
13
|
userSettingsRepository: scope.make("userSettingsRepository"),
|
|
14
14
|
appConfig: resolveAppConfig(scope),
|
|
15
|
-
tenancyProfile: scope.make("users.tenancy.profile"),
|
|
16
15
|
authService: scope.make("authService")
|
|
17
16
|
});
|
|
18
17
|
});
|
|
@@ -1,30 +1,18 @@
|
|
|
1
|
-
import { resolveAppConfig } from "@jskit-ai/kernel/server/support";
|
|
2
|
-
import { resolveTenancyProfile } from "../shared/tenancyProfile.js";
|
|
3
1
|
import { createService as createAuthProfileSyncService } from "./common/services/authProfileSyncService.js";
|
|
4
|
-
import {
|
|
2
|
+
import { resolveProfileSyncLifecycleContributors } from "./profileSyncLifecycleContributorRegistry.js";
|
|
5
3
|
|
|
6
4
|
function registerUsersCore(app) {
|
|
7
5
|
if (!app || typeof app.singleton !== "function") {
|
|
8
6
|
throw new Error("registerUsersCore requires application singleton().");
|
|
9
7
|
}
|
|
10
8
|
|
|
11
|
-
registerUsersCoreActionSurfaceSources(app);
|
|
12
|
-
|
|
13
9
|
app.singleton("users.profile.sync.service", (scope) => {
|
|
14
10
|
return createAuthProfileSyncService({
|
|
15
11
|
usersRepository: scope.make("usersRepository"),
|
|
16
12
|
userSettingsRepository: scope.make("userSettingsRepository"),
|
|
17
|
-
|
|
18
|
-
typeof scope.has === "function" && scope.has("users.workspace.service")
|
|
19
|
-
? scope.make("users.workspace.service")
|
|
20
|
-
: null
|
|
13
|
+
lifecycleContributors: resolveProfileSyncLifecycleContributors(scope)
|
|
21
14
|
});
|
|
22
15
|
});
|
|
23
|
-
|
|
24
|
-
app.singleton("users.tenancy.profile", (scope) => {
|
|
25
|
-
const appConfig = resolveAppConfig(scope);
|
|
26
|
-
return resolveTenancyProfile(appConfig);
|
|
27
|
-
});
|
|
28
16
|
}
|
|
29
17
|
|
|
30
18
|
export { registerUsersCore };
|
|
@@ -2,15 +2,6 @@ import { AppError } from "@jskit-ai/kernel/server/runtime";
|
|
|
2
2
|
import { requireServiceMethod } from "@jskit-ai/kernel/shared/actions/actionContributorHelpers";
|
|
3
3
|
import { normalizeLowerText, normalizeText } from "@jskit-ai/kernel/shared/actions/textNormalization";
|
|
4
4
|
import { normalizeObject } from "@jskit-ai/kernel/shared/support/normalize";
|
|
5
|
-
import {
|
|
6
|
-
TENANCY_MODE_NONE,
|
|
7
|
-
TENANCY_MODE_PERSONAL,
|
|
8
|
-
TENANCY_MODE_WORKSPACES,
|
|
9
|
-
WORKSPACE_SLUG_POLICY_NONE,
|
|
10
|
-
WORKSPACE_SLUG_POLICY_IMMUTABLE_USERNAME,
|
|
11
|
-
WORKSPACE_SLUG_POLICY_USER_SELECTED,
|
|
12
|
-
resolveTenancyProfile
|
|
13
|
-
} from "../shared/tenancyProfile.js";
|
|
14
5
|
import { accountAvatarFormatter } from "./common/formatters/accountAvatarFormatter.js";
|
|
15
6
|
import { authenticatedUserValidator } from "./common/validators/authenticatedUserValidator.js";
|
|
16
7
|
import { userSettingsFields } from "../shared/resources/userSettingsFields.js";
|
|
@@ -56,10 +47,8 @@ function normalizeBoolean(value, fallback) {
|
|
|
56
47
|
return fallback;
|
|
57
48
|
}
|
|
58
49
|
|
|
59
|
-
function resolveAppState(appConfig = {}
|
|
50
|
+
function resolveAppState(appConfig = {}) {
|
|
60
51
|
const features = {
|
|
61
|
-
workspaceSwitching: normalizeBoolean(appConfig.workspaceSwitching, false),
|
|
62
|
-
workspaceInvites: workspaceInvitationsEnabled === true,
|
|
63
52
|
assistantEnabled: normalizeBoolean(appConfig.assistantEnabled, false),
|
|
64
53
|
assistantRequiredPermission: normalizeText(appConfig.assistantRequiredPermission),
|
|
65
54
|
socialEnabled: normalizeBoolean(appConfig.socialEnabled, false),
|
|
@@ -71,54 +60,14 @@ function resolveAppState(appConfig = {}, { workspaceInvitationsEnabled = false }
|
|
|
71
60
|
};
|
|
72
61
|
}
|
|
73
62
|
|
|
74
|
-
function
|
|
75
|
-
const normalizedValue = normalizeLowerText(value);
|
|
76
|
-
if (
|
|
77
|
-
normalizedValue === WORKSPACE_SLUG_POLICY_IMMUTABLE_USERNAME ||
|
|
78
|
-
normalizedValue === WORKSPACE_SLUG_POLICY_USER_SELECTED
|
|
79
|
-
) {
|
|
80
|
-
return normalizedValue;
|
|
81
|
-
}
|
|
82
|
-
return WORKSPACE_SLUG_POLICY_NONE;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
function isSupportedTenancyMode(value = "") {
|
|
86
|
-
return value === TENANCY_MODE_NONE || value === TENANCY_MODE_PERSONAL || value === TENANCY_MODE_WORKSPACES;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
function resolveBootstrapTenancyProfile(tenancyProfile = null, appConfig = {}) {
|
|
90
|
-
const fallback = resolveTenancyProfile(appConfig);
|
|
91
|
-
const source = tenancyProfile && typeof tenancyProfile === "object" ? tenancyProfile : fallback;
|
|
92
|
-
const mode = isSupportedTenancyMode(source?.mode) ? source.mode : fallback.mode;
|
|
93
|
-
const workspace = source?.workspace && typeof source.workspace === "object" ? source.workspace : fallback.workspace;
|
|
94
|
-
|
|
95
|
-
return Object.freeze({
|
|
96
|
-
mode,
|
|
97
|
-
workspace: Object.freeze({
|
|
98
|
-
enabled: workspace.enabled === true,
|
|
99
|
-
autoProvision: workspace.autoProvision === true,
|
|
100
|
-
allowSelfCreate: workspace.allowSelfCreate === true,
|
|
101
|
-
slugPolicy: normalizeSlugPolicy(workspace.slugPolicy)
|
|
102
|
-
})
|
|
103
|
-
});
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
function createAnonymousBootstrapPayload({ appState, tenancyProfile, surfaceAccess = {} }) {
|
|
63
|
+
function createAnonymousBootstrapPayload({ appState, surfaceAccess = {} }) {
|
|
107
64
|
return {
|
|
108
65
|
session: {
|
|
109
66
|
authenticated: false
|
|
110
67
|
},
|
|
111
68
|
profile: null,
|
|
112
|
-
tenancy: tenancyProfile,
|
|
113
69
|
app: appState,
|
|
114
|
-
workspaces: [],
|
|
115
|
-
pendingInvites: [],
|
|
116
|
-
activeWorkspace: null,
|
|
117
|
-
membership: null,
|
|
118
|
-
requestedWorkspace: null,
|
|
119
|
-
permissions: [],
|
|
120
70
|
surfaceAccess: normalizeObject(surfaceAccess),
|
|
121
|
-
workspaceSettings: null,
|
|
122
71
|
userSettings: null,
|
|
123
72
|
requestMeta: {
|
|
124
73
|
hasRequest: false
|
|
@@ -151,12 +100,10 @@ function createUsersBootstrapContributor({
|
|
|
151
100
|
usersRepository,
|
|
152
101
|
userSettingsRepository,
|
|
153
102
|
appConfig = {},
|
|
154
|
-
tenancyProfile = null,
|
|
155
103
|
authService
|
|
156
104
|
} = {}) {
|
|
157
105
|
const contributorId = "users.bootstrap";
|
|
158
106
|
const appState = resolveAppState(appConfig);
|
|
159
|
-
const resolvedTenancyProfile = resolveBootstrapTenancyProfile(tenancyProfile, appConfig);
|
|
160
107
|
|
|
161
108
|
requireServiceMethod(usersRepository, "findById", contributorId, {
|
|
162
109
|
serviceLabel: "usersRepository"
|
|
@@ -187,7 +134,6 @@ function createUsersBootstrapContributor({
|
|
|
187
134
|
const inheritedSurfaceAccess = normalizeObject(existingPayload?.surfaceAccess);
|
|
188
135
|
let payload = createAnonymousBootstrapPayload({
|
|
189
136
|
appState,
|
|
190
|
-
tenancyProfile: resolvedTenancyProfile,
|
|
191
137
|
surfaceAccess: inheritedSurfaceAccess
|
|
192
138
|
});
|
|
193
139
|
|
|
@@ -205,16 +151,8 @@ function createUsersBootstrapContributor({
|
|
|
205
151
|
email: latestProfile.email,
|
|
206
152
|
avatar: accountAvatarFormatter(latestProfile, userSettings)
|
|
207
153
|
},
|
|
208
|
-
tenancy: resolvedTenancyProfile,
|
|
209
154
|
app: appState,
|
|
210
|
-
workspaces: [],
|
|
211
|
-
pendingInvites: [],
|
|
212
|
-
activeWorkspace: null,
|
|
213
|
-
membership: null,
|
|
214
|
-
requestedWorkspace: null,
|
|
215
|
-
permissions: [],
|
|
216
155
|
surfaceAccess: inheritedSurfaceAccess,
|
|
217
|
-
workspaceSettings: null,
|
|
218
156
|
userSettings: mapUserSettingsBootstrap(userSettings),
|
|
219
157
|
requestMeta: {
|
|
220
158
|
hasRequest: Boolean(request)
|
package/src/shared/index.js
CHANGED
|
@@ -1,107 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
OWNER_ROLE_ID,
|
|
3
|
-
ADMIN_ROLE_ID,
|
|
4
|
-
MEMBER_ROLE_ID,
|
|
5
|
-
resolveRolePermissions,
|
|
6
|
-
listRoleDescriptors,
|
|
7
|
-
hasPermission
|
|
8
|
-
} from "./roles.js";
|
|
9
|
-
|
|
10
|
-
import {
|
|
11
|
-
DEFAULT_WORKSPACE_DARK_PALETTE,
|
|
12
|
-
DEFAULT_WORKSPACE_LIGHT_PALETTE,
|
|
13
|
-
DEFAULT_WORKSPACE_COLOR,
|
|
14
|
-
DEFAULT_USER_SETTINGS,
|
|
15
|
-
coerceWorkspaceColor,
|
|
16
|
-
coerceWorkspaceThemeColor,
|
|
17
|
-
coerceWorkspaceSecondaryColor,
|
|
18
|
-
coerceWorkspaceSurfaceColor,
|
|
19
|
-
coerceWorkspaceSurfaceVariantColor,
|
|
20
|
-
normalizeWorkspaceHexColor,
|
|
21
|
-
normalizeWorkspaceThemeMode,
|
|
22
|
-
resolveWorkspaceThemeDefaultPalette,
|
|
23
|
-
resolveWorkspaceThemePalettes,
|
|
24
|
-
WORKSPACE_THEME_MODE_DARK,
|
|
25
|
-
WORKSPACE_THEME_MODE_LIGHT,
|
|
26
|
-
resolveWorkspaceThemePalette
|
|
27
|
-
} from "./settings.js";
|
|
28
|
-
import {
|
|
29
|
-
TENANCY_MODE_NONE,
|
|
30
|
-
TENANCY_MODE_PERSONAL,
|
|
31
|
-
TENANCY_MODE_WORKSPACES,
|
|
32
|
-
normalizeTenancyMode,
|
|
33
|
-
WORKSPACE_SLUG_POLICY_NONE,
|
|
34
|
-
WORKSPACE_SLUG_POLICY_IMMUTABLE_USERNAME,
|
|
35
|
-
WORKSPACE_SLUG_POLICY_USER_SELECTED,
|
|
36
|
-
resolveTenancyProfile,
|
|
37
|
-
isWorkspacesTenancyMode
|
|
38
|
-
} from "./tenancyProfile.js";
|
|
1
|
+
import { DEFAULT_USER_SETTINGS } from "./settings.js";
|
|
39
2
|
|
|
40
3
|
const USERS_SHARED_API = Object.freeze({
|
|
41
|
-
|
|
42
|
-
ADMIN_ROLE_ID,
|
|
43
|
-
MEMBER_ROLE_ID,
|
|
44
|
-
resolveRolePermissions,
|
|
45
|
-
listRoleDescriptors,
|
|
46
|
-
hasPermission,
|
|
47
|
-
DEFAULT_WORKSPACE_LIGHT_PALETTE,
|
|
48
|
-
DEFAULT_WORKSPACE_DARK_PALETTE,
|
|
49
|
-
DEFAULT_WORKSPACE_COLOR,
|
|
50
|
-
DEFAULT_USER_SETTINGS,
|
|
51
|
-
coerceWorkspaceColor,
|
|
52
|
-
coerceWorkspaceThemeColor,
|
|
53
|
-
coerceWorkspaceSecondaryColor,
|
|
54
|
-
coerceWorkspaceSurfaceColor,
|
|
55
|
-
coerceWorkspaceSurfaceVariantColor,
|
|
56
|
-
WORKSPACE_THEME_MODE_LIGHT,
|
|
57
|
-
WORKSPACE_THEME_MODE_DARK,
|
|
58
|
-
normalizeWorkspaceThemeMode,
|
|
59
|
-
resolveWorkspaceThemeDefaultPalette,
|
|
60
|
-
resolveWorkspaceThemePalettes,
|
|
61
|
-
normalizeWorkspaceHexColor,
|
|
62
|
-
resolveWorkspaceThemePalette,
|
|
63
|
-
TENANCY_MODE_NONE,
|
|
64
|
-
TENANCY_MODE_PERSONAL,
|
|
65
|
-
TENANCY_MODE_WORKSPACES,
|
|
66
|
-
normalizeTenancyMode,
|
|
67
|
-
WORKSPACE_SLUG_POLICY_NONE,
|
|
68
|
-
WORKSPACE_SLUG_POLICY_IMMUTABLE_USERNAME,
|
|
69
|
-
WORKSPACE_SLUG_POLICY_USER_SELECTED,
|
|
70
|
-
resolveTenancyProfile,
|
|
71
|
-
isWorkspacesTenancyMode
|
|
4
|
+
DEFAULT_USER_SETTINGS
|
|
72
5
|
});
|
|
73
6
|
|
|
74
7
|
export {
|
|
75
|
-
OWNER_ROLE_ID,
|
|
76
|
-
ADMIN_ROLE_ID,
|
|
77
|
-
MEMBER_ROLE_ID,
|
|
78
|
-
resolveRolePermissions,
|
|
79
|
-
listRoleDescriptors,
|
|
80
|
-
hasPermission,
|
|
81
|
-
DEFAULT_WORKSPACE_LIGHT_PALETTE,
|
|
82
|
-
DEFAULT_WORKSPACE_DARK_PALETTE,
|
|
83
|
-
DEFAULT_WORKSPACE_COLOR,
|
|
84
8
|
DEFAULT_USER_SETTINGS,
|
|
85
|
-
coerceWorkspaceColor,
|
|
86
|
-
coerceWorkspaceThemeColor,
|
|
87
|
-
coerceWorkspaceSecondaryColor,
|
|
88
|
-
coerceWorkspaceSurfaceColor,
|
|
89
|
-
coerceWorkspaceSurfaceVariantColor,
|
|
90
|
-
WORKSPACE_THEME_MODE_LIGHT,
|
|
91
|
-
WORKSPACE_THEME_MODE_DARK,
|
|
92
|
-
normalizeWorkspaceThemeMode,
|
|
93
|
-
resolveWorkspaceThemeDefaultPalette,
|
|
94
|
-
resolveWorkspaceThemePalettes,
|
|
95
|
-
normalizeWorkspaceHexColor,
|
|
96
|
-
resolveWorkspaceThemePalette,
|
|
97
|
-
TENANCY_MODE_NONE,
|
|
98
|
-
TENANCY_MODE_PERSONAL,
|
|
99
|
-
TENANCY_MODE_WORKSPACES,
|
|
100
|
-
normalizeTenancyMode,
|
|
101
|
-
WORKSPACE_SLUG_POLICY_NONE,
|
|
102
|
-
WORKSPACE_SLUG_POLICY_IMMUTABLE_USERNAME,
|
|
103
|
-
WORKSPACE_SLUG_POLICY_USER_SELECTED,
|
|
104
|
-
resolveTenancyProfile,
|
|
105
|
-
isWorkspacesTenancyMode,
|
|
106
9
|
USERS_SHARED_API
|
|
107
10
|
};
|
package/src/shared/settings.js
CHANGED
|
@@ -1,23 +1,3 @@
|
|
|
1
|
-
const WORKSPACE_THEME_MODE_LIGHT = "light";
|
|
2
|
-
const WORKSPACE_THEME_MODE_DARK = "dark";
|
|
3
|
-
const HEX_COLOR_PATTERN = /^#[0-9A-Fa-f]{6}$/;
|
|
4
|
-
|
|
5
|
-
const DEFAULT_WORKSPACE_LIGHT_PALETTE = Object.freeze({
|
|
6
|
-
color: "#1867C0",
|
|
7
|
-
secondaryColor: "#48A9A6",
|
|
8
|
-
surfaceColor: "#FFFFFF",
|
|
9
|
-
surfaceVariantColor: "#424242"
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
const DEFAULT_WORKSPACE_DARK_PALETTE = Object.freeze({
|
|
13
|
-
color: "#2196F3",
|
|
14
|
-
secondaryColor: "#54B6B2",
|
|
15
|
-
surfaceColor: "#212121",
|
|
16
|
-
surfaceVariantColor: "#C8C8C8"
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
const DEFAULT_WORKSPACE_COLOR = DEFAULT_WORKSPACE_LIGHT_PALETTE.color;
|
|
20
|
-
|
|
21
1
|
const DEFAULT_USER_SETTINGS = Object.freeze({
|
|
22
2
|
theme: "system",
|
|
23
3
|
locale: "en",
|
|
@@ -32,104 +12,6 @@ const DEFAULT_USER_SETTINGS = Object.freeze({
|
|
|
32
12
|
passwordSignInEnabled: true,
|
|
33
13
|
passwordSetupRequired: false
|
|
34
14
|
});
|
|
35
|
-
|
|
36
|
-
function normalizeWorkspaceHexColor(value) {
|
|
37
|
-
const normalized = String(value || "").trim();
|
|
38
|
-
if (!HEX_COLOR_PATTERN.test(normalized)) {
|
|
39
|
-
return "";
|
|
40
|
-
}
|
|
41
|
-
return normalized.toUpperCase();
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
function coerceWorkspaceColor(value) {
|
|
45
|
-
return normalizeWorkspaceHexColor(value) || DEFAULT_WORKSPACE_COLOR;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
function normalizeWorkspaceThemeMode(value = "") {
|
|
49
|
-
const normalized = String(value || "").trim().toLowerCase();
|
|
50
|
-
if (normalized === WORKSPACE_THEME_MODE_DARK) {
|
|
51
|
-
return WORKSPACE_THEME_MODE_DARK;
|
|
52
|
-
}
|
|
53
|
-
return WORKSPACE_THEME_MODE_LIGHT;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
function resolveWorkspaceThemeDefaultPalette(mode = WORKSPACE_THEME_MODE_LIGHT) {
|
|
57
|
-
const normalizedMode = normalizeWorkspaceThemeMode(mode);
|
|
58
|
-
return normalizedMode === WORKSPACE_THEME_MODE_DARK
|
|
59
|
-
? DEFAULT_WORKSPACE_DARK_PALETTE
|
|
60
|
-
: DEFAULT_WORKSPACE_LIGHT_PALETTE;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
function coerceWorkspaceThemeColor(value, fallbackColor = DEFAULT_WORKSPACE_COLOR) {
|
|
64
|
-
return normalizeWorkspaceHexColor(value) || normalizeWorkspaceHexColor(fallbackColor) || DEFAULT_WORKSPACE_COLOR;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
function coerceWorkspaceSecondaryColor(value, { mode = WORKSPACE_THEME_MODE_LIGHT } = {}) {
|
|
68
|
-
return coerceWorkspaceThemeColor(value, resolveWorkspaceThemeDefaultPalette(mode).secondaryColor);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
function coerceWorkspaceSurfaceColor(value, { mode = WORKSPACE_THEME_MODE_LIGHT } = {}) {
|
|
72
|
-
return coerceWorkspaceThemeColor(value, resolveWorkspaceThemeDefaultPalette(mode).surfaceColor);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
function coerceWorkspaceSurfaceVariantColor(value, { mode = WORKSPACE_THEME_MODE_LIGHT } = {}) {
|
|
76
|
-
return coerceWorkspaceThemeColor(value, resolveWorkspaceThemeDefaultPalette(mode).surfaceVariantColor);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
function resolveWorkspaceThemePalette(input = {}, { mode = WORKSPACE_THEME_MODE_LIGHT } = {}) {
|
|
80
|
-
const source = input && typeof input === "object" ? input : {};
|
|
81
|
-
const normalizedMode = normalizeWorkspaceThemeMode(mode);
|
|
82
|
-
const paletteDefaults = resolveWorkspaceThemeDefaultPalette(normalizedMode);
|
|
83
|
-
|
|
84
|
-
if (normalizedMode === WORKSPACE_THEME_MODE_DARK) {
|
|
85
|
-
return Object.freeze({
|
|
86
|
-
color: coerceWorkspaceThemeColor(source.darkPrimaryColor, paletteDefaults.color),
|
|
87
|
-
secondaryColor: coerceWorkspaceThemeColor(source.darkSecondaryColor, paletteDefaults.secondaryColor),
|
|
88
|
-
surfaceColor: coerceWorkspaceThemeColor(source.darkSurfaceColor, paletteDefaults.surfaceColor),
|
|
89
|
-
surfaceVariantColor: coerceWorkspaceThemeColor(
|
|
90
|
-
source.darkSurfaceVariantColor,
|
|
91
|
-
paletteDefaults.surfaceVariantColor
|
|
92
|
-
)
|
|
93
|
-
});
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
return Object.freeze({
|
|
97
|
-
color: coerceWorkspaceThemeColor(source.lightPrimaryColor, paletteDefaults.color),
|
|
98
|
-
secondaryColor: coerceWorkspaceThemeColor(source.lightSecondaryColor, paletteDefaults.secondaryColor),
|
|
99
|
-
surfaceColor: coerceWorkspaceThemeColor(source.lightSurfaceColor, paletteDefaults.surfaceColor),
|
|
100
|
-
surfaceVariantColor: coerceWorkspaceThemeColor(
|
|
101
|
-
source.lightSurfaceVariantColor,
|
|
102
|
-
paletteDefaults.surfaceVariantColor
|
|
103
|
-
)
|
|
104
|
-
});
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
function resolveWorkspaceThemePalettes(input = {}) {
|
|
108
|
-
return Object.freeze({
|
|
109
|
-
light: resolveWorkspaceThemePalette(input, {
|
|
110
|
-
mode: WORKSPACE_THEME_MODE_LIGHT
|
|
111
|
-
}),
|
|
112
|
-
dark: resolveWorkspaceThemePalette(input, {
|
|
113
|
-
mode: WORKSPACE_THEME_MODE_DARK
|
|
114
|
-
})
|
|
115
|
-
});
|
|
116
|
-
}
|
|
117
|
-
|
|
118
15
|
export {
|
|
119
|
-
|
|
120
|
-
DEFAULT_WORKSPACE_LIGHT_PALETTE,
|
|
121
|
-
DEFAULT_WORKSPACE_COLOR,
|
|
122
|
-
DEFAULT_USER_SETTINGS,
|
|
123
|
-
coerceWorkspaceColor,
|
|
124
|
-
coerceWorkspaceThemeColor,
|
|
125
|
-
coerceWorkspaceSecondaryColor,
|
|
126
|
-
coerceWorkspaceSurfaceColor,
|
|
127
|
-
coerceWorkspaceSurfaceVariantColor,
|
|
128
|
-
normalizeWorkspaceHexColor,
|
|
129
|
-
normalizeWorkspaceThemeMode,
|
|
130
|
-
resolveWorkspaceThemeDefaultPalette,
|
|
131
|
-
resolveWorkspaceThemePalettes,
|
|
132
|
-
WORKSPACE_THEME_MODE_DARK,
|
|
133
|
-
WORKSPACE_THEME_MODE_LIGHT,
|
|
134
|
-
resolveWorkspaceThemePalette
|
|
16
|
+
DEFAULT_USER_SETTINGS
|
|
135
17
|
};
|