@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.
- package/package.descriptor.mjs +9 -46
- package/package.json +8 -19
- package/src/server/UsersCoreServiceProvider.js +0 -4
- package/src/server/common/registerCommonRepositories.js +0 -5
- 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 +1 -3
- package/src/server/registerUsersCore.js +2 -14
- package/src/server/usersBootstrapContributor.js +10 -85
- package/src/shared/index.js +2 -99
- package/src/shared/settings.js +1 -119
- package/templates/migrations/users_core_generic_initial.cjs +0 -16
- package/test/authProfileSyncService.test.js +19 -10
- package/test/registerServiceRealtimeEvents.test.js +0 -94
- package/test/registerUsersCore.test.js +6 -19
- package/test/repositoryContracts.test.js +1 -11
- package/test/resourcesCanonical.test.js +1 -19
- package/test/settingsFieldRegistriesSingleton.test.js +0 -10
- package/test/usersBootstrapContributor.test.js +20 -38
- package/test/usersRouteRequestInputValidator.test.js +2 -43
- package/test/usersRouteResources.test.js +2 -20
- package/test-support/registerDefaultSettingsFields.js +0 -1
- 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/consoleSettings/bootConsoleSettingsRoutes.js +0 -63
- package/src/server/consoleSettings/consoleService.js +0 -36
- package/src/server/consoleSettings/consoleSettingsActions.js +0 -55
- package/src/server/consoleSettings/consoleSettingsRepository.js +0 -115
- package/src/server/consoleSettings/consoleSettingsService.js +0 -40
- package/src/server/consoleSettings/registerConsoleSettings.js +0 -56
- 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 -135
- package/src/server/support/workspaceInvitationsPolicy.js +0 -45
- package/src/server/support/workspaceRouteInput.js +0 -22
- package/src/server/workspaceBootstrapContributor.js +0 -211
- 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/consoleSettingsFields.js +0 -54
- package/src/shared/resources/consoleSettingsResource.js +0 -119
- 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/templates/migrations/users_core_console_owner.cjs +0 -37
- package/templates/packages/main/src/shared/resources/consoleSettingsFields.js +0 -11
- package/test/consoleService.test.js +0 -57
- package/test/consoleSettingsService.test.js +0 -86
- 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 -105
- 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/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
|
};
|
|
@@ -42,28 +42,12 @@ exports.up = async function up(knex) {
|
|
|
42
42
|
});
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
const hasConsoleSettingsTable = await knex.schema.hasTable("console_settings");
|
|
46
|
-
if (!hasConsoleSettingsTable) {
|
|
47
|
-
await knex.schema.createTable("console_settings", (table) => {
|
|
48
|
-
table.bigInteger("id").primary();
|
|
49
|
-
table.bigInteger("owner_user_id").unsigned().nullable().references("id").inTable("users").onDelete("SET NULL");
|
|
50
|
-
table.timestamp("created_at", { useTz: false }).notNullable().defaultTo(knex.fn.now());
|
|
51
|
-
table.timestamp("updated_at", { useTz: false }).notNullable().defaultTo(knex.fn.now());
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
await knex("console_settings").insert({
|
|
55
|
-
id: 1,
|
|
56
|
-
created_at: knex.fn.now(),
|
|
57
|
-
updated_at: knex.fn.now()
|
|
58
|
-
});
|
|
59
|
-
}
|
|
60
45
|
};
|
|
61
46
|
|
|
62
47
|
/**
|
|
63
48
|
* @param {import('knex').Knex} knex
|
|
64
49
|
*/
|
|
65
50
|
exports.down = async function down(knex) {
|
|
66
|
-
await knex.schema.dropTableIfExists("console_settings");
|
|
67
51
|
await knex.schema.dropTableIfExists("user_settings");
|
|
68
52
|
await knex.schema.dropTableIfExists("users");
|
|
69
53
|
};
|
|
@@ -2,7 +2,7 @@ import assert from "node:assert/strict";
|
|
|
2
2
|
import test from "node:test";
|
|
3
3
|
import { createService } from "../src/server/common/services/authProfileSyncService.js";
|
|
4
4
|
|
|
5
|
-
test("authProfileSyncService.syncIdentityProfile uses shared transaction for profile upsert and
|
|
5
|
+
test("authProfileSyncService.syncIdentityProfile uses shared transaction for profile upsert and lifecycle contributors", async () => {
|
|
6
6
|
const calls = [];
|
|
7
7
|
const transaction = { trxId: "tx-1" };
|
|
8
8
|
|
|
@@ -33,11 +33,14 @@ test("authProfileSyncService.syncIdentityProfile uses shared transaction for pro
|
|
|
33
33
|
return { userId: Number(userId) };
|
|
34
34
|
}
|
|
35
35
|
},
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
36
|
+
lifecycleContributors: [
|
|
37
|
+
{
|
|
38
|
+
contributorId: "test.lifecycle",
|
|
39
|
+
async afterIdentityProfileSynced({ created, options = {} } = {}) {
|
|
40
|
+
calls.push({ step: "lifecycle", created, trx: options.trx || null });
|
|
41
|
+
}
|
|
39
42
|
}
|
|
40
|
-
|
|
43
|
+
]
|
|
41
44
|
});
|
|
42
45
|
|
|
43
46
|
const profile = await service.syncIdentityProfile({
|
|
@@ -52,7 +55,8 @@ test("authProfileSyncService.syncIdentityProfile uses shared transaction for pro
|
|
|
52
55
|
assert.equal(calls[1].step, "find");
|
|
53
56
|
assert.equal(calls[2].step, "upsert");
|
|
54
57
|
assert.equal(calls[3].step, "ensureUserSettings");
|
|
55
|
-
assert.equal(calls[4].step, "
|
|
58
|
+
assert.equal(calls[4].step, "lifecycle");
|
|
59
|
+
assert.equal(calls[4].created, true);
|
|
56
60
|
assert.equal(calls[1].trx, transaction);
|
|
57
61
|
assert.equal(calls[2].trx, transaction);
|
|
58
62
|
assert.equal(calls[3].trx, transaction);
|
|
@@ -87,11 +91,16 @@ test("authProfileSyncService.syncIdentityProfile skips write path when profile i
|
|
|
87
91
|
return { userId: "7" };
|
|
88
92
|
}
|
|
89
93
|
},
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
94
|
+
lifecycleContributors: [
|
|
95
|
+
{
|
|
96
|
+
contributorId: "test.lifecycle",
|
|
97
|
+
async afterIdentityProfileSynced({ created } = {}) {
|
|
98
|
+
if (created) {
|
|
99
|
+
provisionCalls += 1;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
93
102
|
}
|
|
94
|
-
|
|
103
|
+
]
|
|
95
104
|
});
|
|
96
105
|
|
|
97
106
|
const profile = await service.syncIdentityProfile({
|
|
@@ -3,9 +3,6 @@ import test from "node:test";
|
|
|
3
3
|
import { registerAccountProfile } from "../src/server/accountProfile/registerAccountProfile.js";
|
|
4
4
|
import { registerAccountPreferences } from "../src/server/accountPreferences/registerAccountPreferences.js";
|
|
5
5
|
import { registerAccountNotifications } from "../src/server/accountNotifications/registerAccountNotifications.js";
|
|
6
|
-
import { registerConsoleSettings } from "../src/server/consoleSettings/registerConsoleSettings.js";
|
|
7
|
-
import { registerWorkspaceMembers } from "../src/server/workspaceMembers/registerWorkspaceMembers.js";
|
|
8
|
-
import { registerWorkspacePendingInvitations } from "../src/server/workspacePendingInvitations/registerWorkspacePendingInvitations.js";
|
|
9
6
|
|
|
10
7
|
function createAppDouble() {
|
|
11
8
|
const serviceCalls = [];
|
|
@@ -58,94 +55,3 @@ test("account register functions publish account.settings.changed for update ope
|
|
|
58
55
|
assert.equal(notifications?.metadata?.events?.updateNotifications?.[0]?.realtime?.event, "account.settings.changed");
|
|
59
56
|
assert.equal(notifications?.metadata?.events?.updateNotifications?.[1]?.realtime?.event, "users.bootstrap.changed");
|
|
60
57
|
});
|
|
61
|
-
|
|
62
|
-
test("console settings register publishes console.settings.changed", () => {
|
|
63
|
-
const payload = createAppDouble();
|
|
64
|
-
registerConsoleSettings(payload.app);
|
|
65
|
-
const consoleSettings = findServiceCall(payload.serviceCalls, "users.console.settings.service");
|
|
66
|
-
assert.equal(consoleSettings?.metadata?.events?.updateSettings?.[0]?.realtime?.event, "console.settings.changed");
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
test("workspace register functions publish members/invites/workspace-list realtime events", async () => {
|
|
70
|
-
const membersApp = createAppDouble();
|
|
71
|
-
registerWorkspaceMembers(membersApp.app);
|
|
72
|
-
const members = findServiceCall(membersApp.serviceCalls, "users.workspace.members.service");
|
|
73
|
-
assert.equal(members?.metadata?.events?.updateMemberRole?.[0]?.realtime?.event, "workspace.members.changed");
|
|
74
|
-
assert.equal(members?.metadata?.events?.updateMemberRole?.[1]?.realtime?.event, "users.bootstrap.changed");
|
|
75
|
-
assert.equal(members?.metadata?.events?.removeMember?.[0]?.realtime?.event, "workspace.members.changed");
|
|
76
|
-
assert.equal(members?.metadata?.events?.removeMember?.[1]?.realtime?.event, "users.bootstrap.changed");
|
|
77
|
-
assert.equal(members?.metadata?.events?.createInvite?.[0]?.realtime?.event, "workspace.invites.changed");
|
|
78
|
-
assert.equal(members?.metadata?.events?.createInvite?.[1]?.realtime?.event, "users.bootstrap.changed");
|
|
79
|
-
assert.equal(members?.metadata?.events?.createInvite?.[1]?.entityId?.({ result: { createdInviteId: "91" } }), "91");
|
|
80
|
-
assert.equal(members?.metadata?.events?.createInvite?.[1]?.realtime?.audience?.preset, "event_scope");
|
|
81
|
-
assert.equal(typeof members?.metadata?.events?.createInvite?.[1]?.realtime?.audience?.userQuery, "function");
|
|
82
|
-
const createInviteAudienceQueryResult = await members?.metadata?.events?.createInvite?.[1]?.realtime?.audience?.userQuery({
|
|
83
|
-
knex() {
|
|
84
|
-
return {
|
|
85
|
-
join() {
|
|
86
|
-
return this;
|
|
87
|
-
},
|
|
88
|
-
where(field, value) {
|
|
89
|
-
assert.equal(field, "wi.id");
|
|
90
|
-
assert.equal(value, "91");
|
|
91
|
-
return this;
|
|
92
|
-
},
|
|
93
|
-
async first() {
|
|
94
|
-
return {
|
|
95
|
-
user_id: 55
|
|
96
|
-
};
|
|
97
|
-
}
|
|
98
|
-
};
|
|
99
|
-
},
|
|
100
|
-
event: {
|
|
101
|
-
entityId: "91"
|
|
102
|
-
}
|
|
103
|
-
});
|
|
104
|
-
assert.deepEqual(createInviteAudienceQueryResult, [{ userId: "55" }]);
|
|
105
|
-
assert.equal(members?.metadata?.events?.revokeInvite?.[0]?.realtime?.event, "workspace.invites.changed");
|
|
106
|
-
assert.equal(members?.metadata?.events?.revokeInvite?.[1]?.realtime?.event, "users.bootstrap.changed");
|
|
107
|
-
assert.equal(members?.metadata?.events?.revokeInvite?.[1]?.entityId?.({ result: { revokedInviteId: "19" } }), "19");
|
|
108
|
-
assert.equal(members?.metadata?.events?.revokeInvite?.[1]?.realtime?.audience?.preset, "event_scope");
|
|
109
|
-
assert.equal(typeof members?.metadata?.events?.revokeInvite?.[1]?.realtime?.audience?.userQuery, "function");
|
|
110
|
-
|
|
111
|
-
const pendingApp = createAppDouble();
|
|
112
|
-
registerWorkspacePendingInvitations(pendingApp.app);
|
|
113
|
-
const pending = findServiceCall(pendingApp.serviceCalls, "users.workspace.pending-invitations.service");
|
|
114
|
-
const acceptInviteEvents = Array.isArray(pending?.metadata?.events?.acceptInviteByToken)
|
|
115
|
-
? pending.metadata.events.acceptInviteByToken
|
|
116
|
-
: [];
|
|
117
|
-
const acceptInviteRealtimeEvents = acceptInviteEvents.map((entry) => entry?.realtime?.event).filter(Boolean);
|
|
118
|
-
assert.ok(acceptInviteRealtimeEvents.includes("workspace.invitations.pending.changed"));
|
|
119
|
-
assert.ok(acceptInviteRealtimeEvents.includes("users.bootstrap.changed"));
|
|
120
|
-
assert.ok(acceptInviteRealtimeEvents.includes("workspaces.changed"));
|
|
121
|
-
assert.ok(acceptInviteRealtimeEvents.includes("workspace.members.changed"));
|
|
122
|
-
assert.ok(acceptInviteRealtimeEvents.includes("workspace.invites.changed"));
|
|
123
|
-
|
|
124
|
-
const acceptedMembersChange = acceptInviteEvents.find(
|
|
125
|
-
(entry) => entry?.realtime?.event === "workspace.members.changed"
|
|
126
|
-
);
|
|
127
|
-
assert.equal(acceptedMembersChange?.entityId?.({ result: { workspaceId: "9" } }), "9");
|
|
128
|
-
assert.deepEqual(
|
|
129
|
-
acceptedMembersChange?.realtime?.audience?.({
|
|
130
|
-
event: {
|
|
131
|
-
entityId: "9"
|
|
132
|
-
}
|
|
133
|
-
}),
|
|
134
|
-
{
|
|
135
|
-
workspaceId: "9"
|
|
136
|
-
}
|
|
137
|
-
);
|
|
138
|
-
|
|
139
|
-
const acceptedInvitesChange = acceptInviteEvents.find(
|
|
140
|
-
(entry) => entry?.realtime?.event === "workspace.invites.changed"
|
|
141
|
-
);
|
|
142
|
-
assert.equal(acceptedInvitesChange?.entityId?.({ result: { workspaceId: "9" } }), "9");
|
|
143
|
-
|
|
144
|
-
const refuseInviteEvents = Array.isArray(pending?.metadata?.events?.refuseInviteByToken)
|
|
145
|
-
? pending.metadata.events.refuseInviteByToken
|
|
146
|
-
: [];
|
|
147
|
-
const refuseInviteRealtimeEvents = refuseInviteEvents.map((entry) => entry?.realtime?.event).filter(Boolean);
|
|
148
|
-
assert.ok(refuseInviteRealtimeEvents.includes("workspace.invitations.pending.changed"));
|
|
149
|
-
assert.ok(refuseInviteRealtimeEvents.includes("users.bootstrap.changed"));
|
|
150
|
-
assert.ok(refuseInviteRealtimeEvents.includes("workspace.invites.changed"));
|
|
151
|
-
});
|
|
@@ -2,32 +2,19 @@ import assert from "node:assert/strict";
|
|
|
2
2
|
import test from "node:test";
|
|
3
3
|
import { registerUsersCore } from "../src/server/registerUsersCore.js";
|
|
4
4
|
|
|
5
|
-
test("registerUsersCore
|
|
6
|
-
const
|
|
5
|
+
test("registerUsersCore only binds users-core singletons", () => {
|
|
6
|
+
const singletonTokens = [];
|
|
7
7
|
const app = {
|
|
8
|
-
singleton() {
|
|
9
|
-
|
|
10
|
-
},
|
|
11
|
-
actionSurfaceSource(sourceName, resolver) {
|
|
12
|
-
calls.push({
|
|
13
|
-
sourceName: String(sourceName || ""),
|
|
14
|
-
resolverType: typeof resolver
|
|
15
|
-
});
|
|
8
|
+
singleton(token) {
|
|
9
|
+
singletonTokens.push(String(token || ""));
|
|
16
10
|
return this;
|
|
17
11
|
}
|
|
18
12
|
};
|
|
19
13
|
|
|
20
14
|
registerUsersCore(app);
|
|
21
15
|
|
|
22
|
-
assert.deepEqual(
|
|
23
|
-
|
|
24
|
-
sourceName: "workspace",
|
|
25
|
-
resolverType: "function"
|
|
26
|
-
},
|
|
27
|
-
{
|
|
28
|
-
sourceName: "console",
|
|
29
|
-
resolverType: "function"
|
|
30
|
-
}
|
|
16
|
+
assert.deepEqual(singletonTokens.sort(), [
|
|
17
|
+
"users.profile.sync.service"
|
|
31
18
|
]);
|
|
32
19
|
});
|
|
33
20
|
|
|
@@ -2,11 +2,6 @@ import assert from "node:assert/strict";
|
|
|
2
2
|
import test from "node:test";
|
|
3
3
|
import { createRepository as createUsersRepository } from "../src/server/common/repositories/usersRepository.js";
|
|
4
4
|
import { createRepository as createUserSettingsRepository } from "../src/server/common/repositories/userSettingsRepository.js";
|
|
5
|
-
import { createRepository as createWorkspaceInvitesRepository } from "../src/server/common/repositories/workspaceInvitesRepository.js";
|
|
6
|
-
import { createRepository as createWorkspaceMembershipsRepository } from "../src/server/common/repositories/workspaceMembershipsRepository.js";
|
|
7
|
-
import { createRepository as createWorkspacesRepository } from "../src/server/common/repositories/workspacesRepository.js";
|
|
8
|
-
import { createRepository as createConsoleSettingsRepository } from "../src/server/consoleSettings/consoleSettingsRepository.js";
|
|
9
|
-
import { createRepository as createWorkspaceSettingsRepository } from "../src/server/workspaceSettings/workspaceSettingsRepository.js";
|
|
10
5
|
|
|
11
6
|
function createKnexStub() {
|
|
12
7
|
const knex = Object.assign(() => {
|
|
@@ -24,12 +19,7 @@ test("users-core repositories expose withTransaction", async () => {
|
|
|
24
19
|
const knex = createKnexStub();
|
|
25
20
|
const repositories = [
|
|
26
21
|
createUsersRepository(knex),
|
|
27
|
-
createUserSettingsRepository(knex)
|
|
28
|
-
createWorkspaceInvitesRepository(knex),
|
|
29
|
-
createWorkspaceMembershipsRepository(knex),
|
|
30
|
-
createWorkspacesRepository(knex),
|
|
31
|
-
createConsoleSettingsRepository(knex),
|
|
32
|
-
createWorkspaceSettingsRepository(knex)
|
|
22
|
+
createUserSettingsRepository(knex)
|
|
33
23
|
];
|
|
34
24
|
|
|
35
25
|
for (const repository of repositories) {
|
|
@@ -4,12 +4,8 @@ import path from "node:path";
|
|
|
4
4
|
import { existsSync } from "node:fs";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
6
|
import "../test-support/registerDefaultSettingsFields.js";
|
|
7
|
-
import { workspaceMembersResource } from "../src/shared/resources/workspaceMembersResource.js";
|
|
8
|
-
import { workspaceResource } from "../src/shared/resources/workspaceResource.js";
|
|
9
|
-
import { workspaceSettingsResource } from "../src/shared/resources/workspaceSettingsResource.js";
|
|
10
7
|
import { userProfileResource } from "../src/shared/resources/userProfileResource.js";
|
|
11
8
|
import { userSettingsResource } from "../src/shared/resources/userSettingsResource.js";
|
|
12
|
-
import { consoleSettingsResource } from "../src/shared/resources/consoleSettingsResource.js";
|
|
13
9
|
|
|
14
10
|
function assertResourceOperationMessages(resource, operationName, label) {
|
|
15
11
|
const operation = resource?.operations?.[operationName];
|
|
@@ -31,11 +27,8 @@ function assertResourceOperationMessages(resource, operationName, label) {
|
|
|
31
27
|
|
|
32
28
|
test("users-core resources expose messages for all operations", () => {
|
|
33
29
|
const resources = {
|
|
34
|
-
workspace: workspaceResource,
|
|
35
|
-
workspaceSettings: workspaceSettingsResource,
|
|
36
30
|
userProfile: userProfileResource,
|
|
37
|
-
userSettings: userSettingsResource
|
|
38
|
-
consoleSettings: consoleSettingsResource
|
|
31
|
+
userSettings: userSettingsResource
|
|
39
32
|
};
|
|
40
33
|
|
|
41
34
|
for (const [label, resource] of Object.entries(resources)) {
|
|
@@ -46,18 +39,7 @@ test("users-core resources expose messages for all operations", () => {
|
|
|
46
39
|
});
|
|
47
40
|
|
|
48
41
|
test("users-core specialized resource operations expose messages and validators", () => {
|
|
49
|
-
const workspaceMembersOperationSpecs = [
|
|
50
|
-
{ label: "workspaceMembers.rolesList", operation: workspaceMembersResource.operations.rolesList },
|
|
51
|
-
{ label: "workspaceMembers.membersList", operation: workspaceMembersResource.operations.membersList },
|
|
52
|
-
{ label: "workspaceMembers.updateMemberRole", operation: workspaceMembersResource.operations.updateMemberRole },
|
|
53
|
-
{ label: "workspaceMembers.removeMember", operation: workspaceMembersResource.operations.removeMember },
|
|
54
|
-
{ label: "workspaceMembers.invitesList", operation: workspaceMembersResource.operations.invitesList },
|
|
55
|
-
{ label: "workspaceMembers.createInvite", operation: workspaceMembersResource.operations.createInvite },
|
|
56
|
-
{ label: "workspaceMembers.revokeInvite", operation: workspaceMembersResource.operations.revokeInvite },
|
|
57
|
-
{ label: "workspaceMembers.redeemInvite", operation: workspaceMembersResource.operations.redeemInvite }
|
|
58
|
-
];
|
|
59
42
|
const operationSpecs = [
|
|
60
|
-
...workspaceMembersOperationSpecs,
|
|
61
43
|
{ label: "userProfile.avatarUpload", operation: userProfileResource.operations.avatarUpload },
|
|
62
44
|
{ label: "userProfile.avatarDelete", operation: userProfileResource.operations.avatarDelete },
|
|
63
45
|
{ label: "userSettings.passwordChange", operation: userSettingsResource.operations.passwordChange },
|
|
@@ -6,19 +6,9 @@ async function importWithIdentity(url, identity) {
|
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
test("settings field registries stay shared across module identities", async () => {
|
|
9
|
-
const workspaceModuleUrl = new URL("../src/shared/resources/workspaceSettingsFields.js", import.meta.url);
|
|
10
9
|
const userModuleUrl = new URL("../src/shared/resources/userSettingsFields.js", import.meta.url);
|
|
11
|
-
const consoleModuleUrl = new URL("../src/shared/resources/consoleSettingsFields.js", import.meta.url);
|
|
12
|
-
|
|
13
|
-
const workspaceA = await importWithIdentity(workspaceModuleUrl, "workspace-a");
|
|
14
|
-
const workspaceB = await importWithIdentity(workspaceModuleUrl, "workspace-b");
|
|
15
|
-
assert.equal(workspaceA.workspaceSettingsFields, workspaceB.workspaceSettingsFields);
|
|
16
10
|
|
|
17
11
|
const userA = await importWithIdentity(userModuleUrl, "user-a");
|
|
18
12
|
const userB = await importWithIdentity(userModuleUrl, "user-b");
|
|
19
13
|
assert.equal(userA.userSettingsFields, userB.userSettingsFields);
|
|
20
|
-
|
|
21
|
-
const consoleA = await importWithIdentity(consoleModuleUrl, "console-a");
|
|
22
|
-
const consoleB = await importWithIdentity(consoleModuleUrl, "console-b");
|
|
23
|
-
assert.equal(consoleA.consoleSettingsFields, consoleB.consoleSettingsFields);
|
|
24
14
|
});
|