@jskit-ai/users-core 0.1.47 → 0.1.48
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 +8 -45
- package/package.json +7 -8
- package/src/server/UsersCoreServiceProvider.js +0 -4
- package/src/server/common/registerCommonRepositories.js +0 -5
- package/src/server/registerUsersBootstrap.js +1 -2
- package/src/server/support/workspaceActionSurfaces.js +1 -18
- package/src/server/usersBootstrapContributor.js +10 -23
- package/src/server/workspaceBootstrapContributor.js +1 -0
- package/templates/migrations/users_core_generic_initial.cjs +0 -16
- package/test/registerServiceRealtimeEvents.test.js +0 -8
- package/test/registerUsersCore.test.js +1 -5
- package/test/repositoryContracts.test.js +0 -2
- package/test/resourcesCanonical.test.js +1 -3
- package/test/settingsFieldRegistriesSingleton.test.js +0 -5
- package/test/usersBootstrapContributor.test.js +18 -12
- package/test/usersRouteRequestInputValidator.test.js +2 -43
- package/test/usersRouteResources.test.js +2 -4
- package/test/workspaceActionSurfaces.test.js +3 -23
- package/test-support/registerDefaultSettingsFields.js +0 -1
- 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/shared/resources/consoleSettingsFields.js +0 -54
- package/src/shared/resources/consoleSettingsResource.js +0 -119
- 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/package.descriptor.mjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
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.48",
|
|
5
5
|
kind: "runtime",
|
|
6
|
-
description: "Users/account runtime plus HTTP routes for account
|
|
6
|
+
description: "Users/account runtime plus HTTP routes for account features.",
|
|
7
7
|
dependsOn: [
|
|
8
8
|
"@jskit-ai/auth-core",
|
|
9
9
|
"@jskit-ai/database-runtime",
|
|
@@ -44,7 +44,7 @@ export default Object.freeze({
|
|
|
44
44
|
{
|
|
45
45
|
subpath: "./server",
|
|
46
46
|
summary:
|
|
47
|
-
"Exports UsersCoreServiceProvider
|
|
47
|
+
"Exports UsersCoreServiceProvider plus account feature route registration modules and action definitions."
|
|
48
48
|
},
|
|
49
49
|
{
|
|
50
50
|
subpath: "./shared",
|
|
@@ -121,16 +121,6 @@ export default Object.freeze({
|
|
|
121
121
|
method: "POST",
|
|
122
122
|
path: "/api/settings/security/logout-others",
|
|
123
123
|
summary: "Sign out from other active sessions."
|
|
124
|
-
},
|
|
125
|
-
{
|
|
126
|
-
method: "GET",
|
|
127
|
-
path: "/api/console/settings",
|
|
128
|
-
summary: "Get console settings."
|
|
129
|
-
},
|
|
130
|
-
{
|
|
131
|
-
method: "PATCH",
|
|
132
|
-
path: "/api/console/settings",
|
|
133
|
-
summary: "Update console settings."
|
|
134
124
|
}
|
|
135
125
|
]
|
|
136
126
|
}
|
|
@@ -138,11 +128,11 @@ export default Object.freeze({
|
|
|
138
128
|
mutations: {
|
|
139
129
|
dependencies: {
|
|
140
130
|
runtime: {
|
|
141
|
-
"@jskit-ai/auth-core": "0.1.
|
|
142
|
-
"@jskit-ai/database-runtime": "0.1.
|
|
143
|
-
"@jskit-ai/http-runtime": "0.1.
|
|
144
|
-
"@jskit-ai/kernel": "0.1.
|
|
145
|
-
"@jskit-ai/uploads-runtime": "0.1.
|
|
131
|
+
"@jskit-ai/auth-core": "0.1.37",
|
|
132
|
+
"@jskit-ai/database-runtime": "0.1.38",
|
|
133
|
+
"@jskit-ai/http-runtime": "0.1.37",
|
|
134
|
+
"@jskit-ai/kernel": "0.1.38",
|
|
135
|
+
"@jskit-ai/uploads-runtime": "0.1.16",
|
|
146
136
|
"@fastify/type-provider-typebox": "^6.1.0",
|
|
147
137
|
typebox: "^1.0.81"
|
|
148
138
|
},
|
|
@@ -171,23 +161,6 @@ export default Object.freeze({
|
|
|
171
161
|
category: "migration",
|
|
172
162
|
id: "users-core-profile-username-schema"
|
|
173
163
|
},
|
|
174
|
-
{
|
|
175
|
-
op: "install-migration",
|
|
176
|
-
from: "templates/migrations/users_core_console_owner.cjs",
|
|
177
|
-
toDir: "migrations",
|
|
178
|
-
extension: ".cjs",
|
|
179
|
-
reason: "Install console owner migration.",
|
|
180
|
-
category: "migration",
|
|
181
|
-
id: "users-core-console-owner-schema"
|
|
182
|
-
},
|
|
183
|
-
{
|
|
184
|
-
from: "templates/packages/main/src/shared/resources/consoleSettingsFields.js",
|
|
185
|
-
to: "packages/main/src/shared/resources/consoleSettingsFields.js",
|
|
186
|
-
preserveOnRemove: true,
|
|
187
|
-
reason: "Install app-owned console settings field definitions.",
|
|
188
|
-
category: "users-core",
|
|
189
|
-
id: "users-core-app-owned-console-settings-fields"
|
|
190
|
-
},
|
|
191
164
|
{
|
|
192
165
|
from: "templates/packages/main/src/shared/resources/userSettingsFields.js",
|
|
193
166
|
to: "packages/main/src/shared/resources/userSettingsFields.js",
|
|
@@ -207,16 +180,6 @@ export default Object.freeze({
|
|
|
207
180
|
category: "runtime-config",
|
|
208
181
|
id: "users-core-auth-profile-mode"
|
|
209
182
|
},
|
|
210
|
-
{
|
|
211
|
-
op: "append-text",
|
|
212
|
-
file: "packages/main/src/shared/index.js",
|
|
213
|
-
position: "top",
|
|
214
|
-
skipIfContains: "import \"./resources/consoleSettingsFields.js\";",
|
|
215
|
-
value: "import \"./resources/consoleSettingsFields.js\";\n",
|
|
216
|
-
reason: "Load app-owned console settings field definitions inside the main shared module.",
|
|
217
|
-
category: "users-core",
|
|
218
|
-
id: "users-core-main-shared-console-settings-field-import"
|
|
219
|
-
},
|
|
220
183
|
{
|
|
221
184
|
op: "append-text",
|
|
222
185
|
file: "packages/main/src/shared/index.js",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jskit-ai/users-core",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.48",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"test": "node --test"
|
|
@@ -20,15 +20,14 @@
|
|
|
20
20
|
"./shared/resources/workspaceSettingsFields": "./src/shared/resources/workspaceSettingsFields.js",
|
|
21
21
|
"./shared/resources/userProfileResource": "./src/shared/resources/userProfileResource.js",
|
|
22
22
|
"./shared/resources/userSettingsFields": "./src/shared/resources/userSettingsFields.js",
|
|
23
|
-
"./shared/resources/userSettingsResource": "./src/shared/resources/userSettingsResource.js"
|
|
24
|
-
"./shared/resources/consoleSettingsFields": "./src/shared/resources/consoleSettingsFields.js"
|
|
23
|
+
"./shared/resources/userSettingsResource": "./src/shared/resources/userSettingsResource.js"
|
|
25
24
|
},
|
|
26
25
|
"dependencies": {
|
|
27
|
-
"@jskit-ai/auth-core": "0.1.
|
|
28
|
-
"@jskit-ai/database-runtime": "0.1.
|
|
29
|
-
"@jskit-ai/http-runtime": "0.1.
|
|
30
|
-
"@jskit-ai/kernel": "0.1.
|
|
31
|
-
"@jskit-ai/uploads-runtime": "0.1.
|
|
26
|
+
"@jskit-ai/auth-core": "0.1.37",
|
|
27
|
+
"@jskit-ai/database-runtime": "0.1.38",
|
|
28
|
+
"@jskit-ai/http-runtime": "0.1.37",
|
|
29
|
+
"@jskit-ai/kernel": "0.1.38",
|
|
30
|
+
"@jskit-ai/uploads-runtime": "0.1.16",
|
|
32
31
|
"@fastify/type-provider-typebox": "^6.1.0",
|
|
33
32
|
"typebox": "^1.0.81"
|
|
34
33
|
}
|
|
@@ -3,7 +3,6 @@ import { bootAccountProfileRoutes } from "./accountProfile/bootAccountProfileRou
|
|
|
3
3
|
import { bootAccountPreferencesRoutes } from "./accountPreferences/bootAccountPreferencesRoutes.js";
|
|
4
4
|
import { bootAccountNotificationsRoutes } from "./accountNotifications/bootAccountNotificationsRoutes.js";
|
|
5
5
|
import { bootAccountSecurityRoutes } from "./accountSecurity/bootAccountSecurityRoutes.js";
|
|
6
|
-
import { bootConsoleSettingsRoutes } from "./consoleSettings/bootConsoleSettingsRoutes.js";
|
|
7
6
|
import { registerSharedApi } from "./common/registerSharedApi.js";
|
|
8
7
|
import { registerCommonRepositories } from "./common/registerCommonRepositories.js";
|
|
9
8
|
import { registerUsersCore } from "./registerUsersCore.js";
|
|
@@ -12,7 +11,6 @@ import { registerAccountPreferences } from "./accountPreferences/registerAccount
|
|
|
12
11
|
import { registerAccountNotifications } from "./accountNotifications/registerAccountNotifications.js";
|
|
13
12
|
import { registerAccountProfile } from "./accountProfile/registerAccountProfile.js";
|
|
14
13
|
import { registerAccountSecurity } from "./accountSecurity/registerAccountSecurity.js";
|
|
15
|
-
import { registerConsoleSettings } from "./consoleSettings/registerConsoleSettings.js";
|
|
16
14
|
|
|
17
15
|
class UsersCoreServiceProvider {
|
|
18
16
|
static id = "users.core";
|
|
@@ -29,7 +27,6 @@ class UsersCoreServiceProvider {
|
|
|
29
27
|
registerAccountPreferences(app);
|
|
30
28
|
registerAccountNotifications(app);
|
|
31
29
|
registerAccountSecurity(app);
|
|
32
|
-
registerConsoleSettings(app);
|
|
33
30
|
}
|
|
34
31
|
|
|
35
32
|
async boot(app) {
|
|
@@ -37,7 +34,6 @@ class UsersCoreServiceProvider {
|
|
|
37
34
|
bootAccountPreferencesRoutes(app);
|
|
38
35
|
bootAccountNotificationsRoutes(app);
|
|
39
36
|
bootAccountSecurityRoutes(app);
|
|
40
|
-
bootConsoleSettingsRoutes(app);
|
|
41
37
|
}
|
|
42
38
|
}
|
|
43
39
|
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { createRepository as createUsersRepository } from "./repositories/usersRepository.js";
|
|
2
2
|
import { createRepository as createUserSettingsRepository } from "./repositories/userSettingsRepository.js";
|
|
3
|
-
import { createRepository as createConsoleSettingsRepository } from "../consoleSettings/consoleSettingsRepository.js";
|
|
4
3
|
|
|
5
4
|
function registerCommonRepositories(app) {
|
|
6
5
|
if (!app || typeof app.singleton !== "function") {
|
|
@@ -16,10 +15,6 @@ function registerCommonRepositories(app) {
|
|
|
16
15
|
const knex = scope.make("jskit.database.knex");
|
|
17
16
|
return createUserSettingsRepository(knex);
|
|
18
17
|
});
|
|
19
|
-
app.singleton("consoleSettingsRepository", (scope) => {
|
|
20
|
-
const knex = scope.make("jskit.database.knex");
|
|
21
|
-
return createConsoleSettingsRepository(knex);
|
|
22
|
-
});
|
|
23
18
|
}
|
|
24
19
|
|
|
25
20
|
export { registerCommonRepositories };
|
|
@@ -13,8 +13,7 @@ function registerUsersBootstrap(app) {
|
|
|
13
13
|
userSettingsRepository: scope.make("userSettingsRepository"),
|
|
14
14
|
appConfig: resolveAppConfig(scope),
|
|
15
15
|
tenancyProfile: scope.make("users.tenancy.profile"),
|
|
16
|
-
authService: scope.make("authService")
|
|
17
|
-
consoleService: scope.has("consoleService") ? scope.make("consoleService") : null
|
|
16
|
+
authService: scope.make("authService")
|
|
18
17
|
});
|
|
19
18
|
});
|
|
20
19
|
}
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import { normalizeSurfaceId } from "@jskit-ai/kernel/shared/surface/registry";
|
|
2
|
-
import { isRecord
|
|
2
|
+
import { isRecord } from "@jskit-ai/kernel/shared/support/normalize";
|
|
3
3
|
import { resolveDefaultWorkspaceSurfaceId } from "../../shared/support/workspacePathModel.js";
|
|
4
4
|
|
|
5
|
-
const CONSOLE_OWNER_ACCESS_POLICY_ID = "console_owner";
|
|
6
|
-
|
|
7
5
|
function normalizeSurfaceIds(surfaceIds = []) {
|
|
8
6
|
const source = Array.isArray(surfaceIds) ? surfaceIds : [];
|
|
9
7
|
const seen = new Set();
|
|
@@ -25,15 +23,6 @@ function resolveWorkspaceSurfaceIdsFromAppConfig(appConfig = {}) {
|
|
|
25
23
|
return resolveSurfaceIdsFromAppConfig(appConfig, (definition) => definition.requiresWorkspace === true);
|
|
26
24
|
}
|
|
27
25
|
|
|
28
|
-
function resolveConsoleSurfaceIdsFromAppConfig(appConfig = {}) {
|
|
29
|
-
return resolveSurfaceIdsFromAppConfig(appConfig, (definition) => {
|
|
30
|
-
return (
|
|
31
|
-
definition.requiresWorkspace !== true &&
|
|
32
|
-
normalizeLowerText(definition.accessPolicyId) === CONSOLE_OWNER_ACCESS_POLICY_ID
|
|
33
|
-
);
|
|
34
|
-
});
|
|
35
|
-
}
|
|
36
|
-
|
|
37
26
|
function resolveSurfaceIdsFromAppConfig(appConfig = {}, predicate) {
|
|
38
27
|
const source = isRecord(appConfig?.surfaceDefinitions) ? appConfig.surfaceDefinitions : {};
|
|
39
28
|
const resolved = [];
|
|
@@ -93,11 +82,6 @@ function registerUsersCoreActionSurfaceSources(app) {
|
|
|
93
82
|
const appConfig = scope?.has?.("appConfig") ? scope.make("appConfig") : {};
|
|
94
83
|
return resolveWorkspaceSurfaceIdsFromAppConfig(appConfig);
|
|
95
84
|
});
|
|
96
|
-
|
|
97
|
-
app.actionSurfaceSource("console", ({ scope }) => {
|
|
98
|
-
const appConfig = scope?.has?.("appConfig") ? scope.make("appConfig") : {};
|
|
99
|
-
return resolveConsoleSurfaceIdsFromAppConfig(appConfig);
|
|
100
|
-
});
|
|
101
85
|
}
|
|
102
86
|
|
|
103
87
|
function materializeWorkspaceActionSurfacesFromAppConfig(actions = [], { appConfig = {} } = {}) {
|
|
@@ -127,7 +111,6 @@ function resolveDefaultWorkspaceRouteSurfaceIdFromAppConfig(appConfig = {}) {
|
|
|
127
111
|
|
|
128
112
|
export {
|
|
129
113
|
resolveWorkspaceSurfaceIdsFromAppConfig,
|
|
130
|
-
resolveConsoleSurfaceIdsFromAppConfig,
|
|
131
114
|
resolveDefaultWorkspaceRouteSurfaceIdFromAppConfig,
|
|
132
115
|
materializeWorkspaceActionSurfaces,
|
|
133
116
|
materializeWorkspaceActionSurfacesFromAppConfig,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
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
|
+
import { normalizeObject } from "@jskit-ai/kernel/shared/support/normalize";
|
|
4
5
|
import {
|
|
5
6
|
TENANCY_MODE_NONE,
|
|
6
7
|
TENANCY_MODE_PERSONAL,
|
|
@@ -13,7 +14,6 @@ import {
|
|
|
13
14
|
import { accountAvatarFormatter } from "./common/formatters/accountAvatarFormatter.js";
|
|
14
15
|
import { authenticatedUserValidator } from "./common/validators/authenticatedUserValidator.js";
|
|
15
16
|
import { userSettingsFields } from "../shared/resources/userSettingsFields.js";
|
|
16
|
-
import { normalizeRecordId } from "@jskit-ai/kernel/shared/support/normalize";
|
|
17
17
|
|
|
18
18
|
function getOAuthProviderCatalogPayload(authService) {
|
|
19
19
|
if (!authService || typeof authService.getOAuthProviderCatalog !== "function") {
|
|
@@ -103,7 +103,7 @@ function resolveBootstrapTenancyProfile(tenancyProfile = null, appConfig = {}) {
|
|
|
103
103
|
});
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
-
function createAnonymousBootstrapPayload({ appState, tenancyProfile }) {
|
|
106
|
+
function createAnonymousBootstrapPayload({ appState, tenancyProfile, surfaceAccess = {} }) {
|
|
107
107
|
return {
|
|
108
108
|
session: {
|
|
109
109
|
authenticated: false
|
|
@@ -117,9 +117,7 @@ function createAnonymousBootstrapPayload({ appState, tenancyProfile }) {
|
|
|
117
117
|
membership: null,
|
|
118
118
|
requestedWorkspace: null,
|
|
119
119
|
permissions: [],
|
|
120
|
-
surfaceAccess:
|
|
121
|
-
consoleowner: false
|
|
122
|
-
},
|
|
120
|
+
surfaceAccess: normalizeObject(surfaceAccess),
|
|
123
121
|
workspaceSettings: null,
|
|
124
122
|
userSettings: null,
|
|
125
123
|
requestMeta: {
|
|
@@ -154,8 +152,7 @@ function createUsersBootstrapContributor({
|
|
|
154
152
|
userSettingsRepository,
|
|
155
153
|
appConfig = {},
|
|
156
154
|
tenancyProfile = null,
|
|
157
|
-
authService
|
|
158
|
-
consoleService = null
|
|
155
|
+
authService
|
|
159
156
|
} = {}) {
|
|
160
157
|
const contributorId = "users.bootstrap";
|
|
161
158
|
const appState = resolveAppState(appConfig);
|
|
@@ -170,7 +167,8 @@ function createUsersBootstrapContributor({
|
|
|
170
167
|
|
|
171
168
|
return Object.freeze({
|
|
172
169
|
contributorId,
|
|
173
|
-
|
|
170
|
+
order: 100,
|
|
171
|
+
async contribute({ request = null, reply = null, payload: existingPayload = {} } = {}) {
|
|
174
172
|
const authResult = await request.executeAction({
|
|
175
173
|
actionId: "auth.session.read"
|
|
176
174
|
});
|
|
@@ -186,26 +184,17 @@ function createUsersBootstrapContributor({
|
|
|
186
184
|
}
|
|
187
185
|
|
|
188
186
|
const normalizedUser = authenticatedUserValidator.normalize(authResult?.authenticated ? authResult?.profile : null);
|
|
187
|
+
const inheritedSurfaceAccess = normalizeObject(existingPayload?.surfaceAccess);
|
|
189
188
|
let payload = createAnonymousBootstrapPayload({
|
|
190
189
|
appState,
|
|
191
|
-
tenancyProfile: resolvedTenancyProfile
|
|
190
|
+
tenancyProfile: resolvedTenancyProfile,
|
|
191
|
+
surfaceAccess: inheritedSurfaceAccess
|
|
192
192
|
});
|
|
193
193
|
|
|
194
194
|
if (normalizedUser) {
|
|
195
195
|
const latestProfile = (await usersRepository.findById(normalizedUser.id)) || normalizedUser;
|
|
196
196
|
const userSettings = await userSettingsRepository.ensureForUserId(latestProfile.id);
|
|
197
197
|
|
|
198
|
-
let seededConsoleOwnerUserId = null;
|
|
199
|
-
if (
|
|
200
|
-
consoleService &&
|
|
201
|
-
typeof consoleService.ensureInitialConsoleMember === "function"
|
|
202
|
-
) {
|
|
203
|
-
seededConsoleOwnerUserId = normalizeRecordId(
|
|
204
|
-
await consoleService.ensureInitialConsoleMember(latestProfile.id),
|
|
205
|
-
{ fallback: null }
|
|
206
|
-
);
|
|
207
|
-
}
|
|
208
|
-
|
|
209
198
|
payload = {
|
|
210
199
|
session: {
|
|
211
200
|
authenticated: true,
|
|
@@ -224,9 +213,7 @@ function createUsersBootstrapContributor({
|
|
|
224
213
|
membership: null,
|
|
225
214
|
requestedWorkspace: null,
|
|
226
215
|
permissions: [],
|
|
227
|
-
surfaceAccess:
|
|
228
|
-
consoleowner: Boolean(seededConsoleOwnerUserId) && seededConsoleOwnerUserId === String(latestProfile.id)
|
|
229
|
-
},
|
|
216
|
+
surfaceAccess: inheritedSurfaceAccess,
|
|
230
217
|
workspaceSettings: null,
|
|
231
218
|
userSettings: mapUserSettingsBootstrap(userSettings),
|
|
232
219
|
requestMeta: {
|
|
@@ -129,6 +129,7 @@ function createWorkspaceBootstrapContributor({
|
|
|
129
129
|
|
|
130
130
|
return Object.freeze({
|
|
131
131
|
contributorId,
|
|
132
|
+
order: 200,
|
|
132
133
|
async contribute({ request = null, query = {}, payload = {} } = {}) {
|
|
133
134
|
const normalizedUserId = normalizeRecordId(
|
|
134
135
|
payload?.session?.authenticated === true ? payload?.session?.userId : null,
|
|
@@ -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
|
};
|
|
@@ -3,7 +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
6
|
import { registerWorkspaceMembers } from "../src/server/workspaceMembers/registerWorkspaceMembers.js";
|
|
8
7
|
import { registerWorkspacePendingInvitations } from "../src/server/workspacePendingInvitations/registerWorkspacePendingInvitations.js";
|
|
9
8
|
|
|
@@ -59,13 +58,6 @@ test("account register functions publish account.settings.changed for update ope
|
|
|
59
58
|
assert.equal(notifications?.metadata?.events?.updateNotifications?.[1]?.realtime?.event, "users.bootstrap.changed");
|
|
60
59
|
});
|
|
61
60
|
|
|
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
61
|
test("workspace register functions publish members/invites/workspace-list realtime events", async () => {
|
|
70
62
|
const membersApp = createAppDouble();
|
|
71
63
|
registerWorkspaceMembers(membersApp.app);
|
|
@@ -2,7 +2,7 @@ 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 registers
|
|
5
|
+
test("registerUsersCore registers the workspace action surface alias when action runtime is available", () => {
|
|
6
6
|
const calls = [];
|
|
7
7
|
const app = {
|
|
8
8
|
singleton() {
|
|
@@ -23,10 +23,6 @@ test("registerUsersCore registers console and workspace action surface aliases w
|
|
|
23
23
|
{
|
|
24
24
|
sourceName: "workspace",
|
|
25
25
|
resolverType: "function"
|
|
26
|
-
},
|
|
27
|
-
{
|
|
28
|
-
sourceName: "console",
|
|
29
|
-
resolverType: "function"
|
|
30
26
|
}
|
|
31
27
|
]);
|
|
32
28
|
});
|
|
@@ -5,7 +5,6 @@ import { createRepository as createUserSettingsRepository } from "../src/server/
|
|
|
5
5
|
import { createRepository as createWorkspaceInvitesRepository } from "../src/server/common/repositories/workspaceInvitesRepository.js";
|
|
6
6
|
import { createRepository as createWorkspaceMembershipsRepository } from "../src/server/common/repositories/workspaceMembershipsRepository.js";
|
|
7
7
|
import { createRepository as createWorkspacesRepository } from "../src/server/common/repositories/workspacesRepository.js";
|
|
8
|
-
import { createRepository as createConsoleSettingsRepository } from "../src/server/consoleSettings/consoleSettingsRepository.js";
|
|
9
8
|
import { createRepository as createWorkspaceSettingsRepository } from "../src/server/workspaceSettings/workspaceSettingsRepository.js";
|
|
10
9
|
|
|
11
10
|
function createKnexStub() {
|
|
@@ -28,7 +27,6 @@ test("users-core repositories expose withTransaction", async () => {
|
|
|
28
27
|
createWorkspaceInvitesRepository(knex),
|
|
29
28
|
createWorkspaceMembershipsRepository(knex),
|
|
30
29
|
createWorkspacesRepository(knex),
|
|
31
|
-
createConsoleSettingsRepository(knex),
|
|
32
30
|
createWorkspaceSettingsRepository(knex)
|
|
33
31
|
];
|
|
34
32
|
|
|
@@ -9,7 +9,6 @@ import { workspaceResource } from "../src/shared/resources/workspaceResource.js"
|
|
|
9
9
|
import { workspaceSettingsResource } from "../src/shared/resources/workspaceSettingsResource.js";
|
|
10
10
|
import { userProfileResource } from "../src/shared/resources/userProfileResource.js";
|
|
11
11
|
import { userSettingsResource } from "../src/shared/resources/userSettingsResource.js";
|
|
12
|
-
import { consoleSettingsResource } from "../src/shared/resources/consoleSettingsResource.js";
|
|
13
12
|
|
|
14
13
|
function assertResourceOperationMessages(resource, operationName, label) {
|
|
15
14
|
const operation = resource?.operations?.[operationName];
|
|
@@ -34,8 +33,7 @@ test("users-core resources expose messages for all operations", () => {
|
|
|
34
33
|
workspace: workspaceResource,
|
|
35
34
|
workspaceSettings: workspaceSettingsResource,
|
|
36
35
|
userProfile: userProfileResource,
|
|
37
|
-
userSettings: userSettingsResource
|
|
38
|
-
consoleSettings: consoleSettingsResource
|
|
36
|
+
userSettings: userSettingsResource
|
|
39
37
|
};
|
|
40
38
|
|
|
41
39
|
for (const [label, resource] of Object.entries(resources)) {
|
|
@@ -8,7 +8,6 @@ async function importWithIdentity(url, identity) {
|
|
|
8
8
|
test("settings field registries stay shared across module identities", async () => {
|
|
9
9
|
const workspaceModuleUrl = new URL("../src/shared/resources/workspaceSettingsFields.js", import.meta.url);
|
|
10
10
|
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
11
|
|
|
13
12
|
const workspaceA = await importWithIdentity(workspaceModuleUrl, "workspace-a");
|
|
14
13
|
const workspaceB = await importWithIdentity(workspaceModuleUrl, "workspace-b");
|
|
@@ -17,8 +16,4 @@ test("settings field registries stay shared across module identities", async ()
|
|
|
17
16
|
const userA = await importWithIdentity(userModuleUrl, "user-a");
|
|
18
17
|
const userB = await importWithIdentity(userModuleUrl, "user-b");
|
|
19
18
|
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
19
|
});
|
|
@@ -33,9 +33,8 @@ function createUserSettings() {
|
|
|
33
33
|
};
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
test("users bootstrap contributor
|
|
36
|
+
test("users bootstrap contributor exposes the generic authenticated bootstrap payload", async () => {
|
|
37
37
|
const profile = createAuthenticatedProfile({ id: "12" });
|
|
38
|
-
const consoleOwnerSeeds = [];
|
|
39
38
|
const writtenSessions = [];
|
|
40
39
|
const contributor = createUsersBootstrapContributor({
|
|
41
40
|
usersRepository: {
|
|
@@ -60,12 +59,6 @@ test("users bootstrap contributor seeds the initial console owner and exposes ge
|
|
|
60
59
|
defaultProvider: "google"
|
|
61
60
|
};
|
|
62
61
|
}
|
|
63
|
-
},
|
|
64
|
-
consoleService: {
|
|
65
|
-
async ensureInitialConsoleMember(userId) {
|
|
66
|
-
consoleOwnerSeeds.push(Number(userId));
|
|
67
|
-
return String(userId || "");
|
|
68
|
-
}
|
|
69
62
|
}
|
|
70
63
|
});
|
|
71
64
|
|
|
@@ -82,10 +75,14 @@ test("users bootstrap contributor seeds the initial console owner and exposes ge
|
|
|
82
75
|
};
|
|
83
76
|
}
|
|
84
77
|
},
|
|
78
|
+
payload: {
|
|
79
|
+
surfaceAccess: {
|
|
80
|
+
consoleowner: true
|
|
81
|
+
}
|
|
82
|
+
},
|
|
85
83
|
reply
|
|
86
84
|
});
|
|
87
|
-
|
|
88
|
-
assert.deepEqual(consoleOwnerSeeds, [12]);
|
|
85
|
+
assert.equal(contributor.order, 100);
|
|
89
86
|
assert.equal(writtenSessions.length, 1);
|
|
90
87
|
assert.equal(writtenSessions[0].reply, reply);
|
|
91
88
|
assert.deepEqual(writtenSessions[0].session, {
|
|
@@ -93,7 +90,9 @@ test("users bootstrap contributor seeds the initial console owner and exposes ge
|
|
|
93
90
|
});
|
|
94
91
|
assert.equal(payload.session.authenticated, true);
|
|
95
92
|
assert.equal(payload.session.userId, "12");
|
|
96
|
-
assert.
|
|
93
|
+
assert.deepEqual(payload.surfaceAccess, {
|
|
94
|
+
consoleowner: true
|
|
95
|
+
});
|
|
97
96
|
assert.equal(payload.app.features.workspaceSwitching, false);
|
|
98
97
|
assert.deepEqual(payload.session.oauthProviders, [
|
|
99
98
|
{
|
|
@@ -149,6 +148,11 @@ test("users bootstrap contributor emits canonical tenancy profile for anonymous
|
|
|
149
148
|
};
|
|
150
149
|
}
|
|
151
150
|
},
|
|
151
|
+
payload: {
|
|
152
|
+
surfaceAccess: {
|
|
153
|
+
consoleowner: false
|
|
154
|
+
}
|
|
155
|
+
},
|
|
152
156
|
reply: {}
|
|
153
157
|
});
|
|
154
158
|
|
|
@@ -167,6 +171,8 @@ test("users bootstrap contributor emits canonical tenancy profile for anonymous
|
|
|
167
171
|
oauthDefaultProvider: null
|
|
168
172
|
});
|
|
169
173
|
assert.deepEqual(payload.workspaces, []);
|
|
170
|
-
assert.
|
|
174
|
+
assert.deepEqual(payload.surfaceAccess, {
|
|
175
|
+
consoleowner: false
|
|
176
|
+
});
|
|
171
177
|
assert.equal(payload.userSettings, null);
|
|
172
178
|
});
|
|
@@ -27,8 +27,7 @@ function findRoute(routes, { method, path }) {
|
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
async function registerRoutes({
|
|
30
|
-
authService = {}
|
|
31
|
-
consoleService = null
|
|
30
|
+
authService = {}
|
|
32
31
|
} = {}) {
|
|
33
32
|
const registeredRoutes = [];
|
|
34
33
|
const router = {
|
|
@@ -59,10 +58,6 @@ async function registerRoutes({
|
|
|
59
58
|
["actionExecutor", {}]
|
|
60
59
|
]);
|
|
61
60
|
|
|
62
|
-
if (consoleService) {
|
|
63
|
-
bindings.set("consoleService", consoleService);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
61
|
const app = {
|
|
67
62
|
has(token) {
|
|
68
63
|
return bindings.has(token);
|
|
@@ -92,13 +87,11 @@ function createActionRequest({ input = {}, executeAction, file = null }) {
|
|
|
92
87
|
};
|
|
93
88
|
}
|
|
94
89
|
|
|
95
|
-
test("users-core boot mounts account
|
|
90
|
+
test("users-core boot mounts account routes without workspace routes", async () => {
|
|
96
91
|
const routes = await registerRoutes();
|
|
97
92
|
|
|
98
93
|
assert.equal(findRoute(routes, { method: "GET", path: "/api/settings" })?.path, "/api/settings");
|
|
99
94
|
assert.equal(findRoute(routes, { method: "PATCH", path: "/api/settings/profile" })?.path, "/api/settings/profile");
|
|
100
|
-
assert.equal(findRoute(routes, { method: "GET", path: "/api/console/settings" })?.path, "/api/console/settings");
|
|
101
|
-
assert.equal(findRoute(routes, { method: "PATCH", path: "/api/console/settings" })?.path, "/api/console/settings");
|
|
102
95
|
assert.equal(findRoute(routes, { method: "GET", path: "/api/workspaces" }), null);
|
|
103
96
|
assert.equal(findRoute(routes, { method: "GET", path: "/api/w/:workspaceSlug/settings" }), null);
|
|
104
97
|
});
|
|
@@ -206,37 +199,3 @@ test("account route handlers build action input from request.input", async () =>
|
|
|
206
199
|
assert.deepEqual(calls[6].input, { provider: "github" });
|
|
207
200
|
assert.equal(calls[7].actionId, "settings.security.sessions.logout_others");
|
|
208
201
|
});
|
|
209
|
-
|
|
210
|
-
test("console settings route handlers use request.input payloads", async () => {
|
|
211
|
-
const routes = await registerRoutes();
|
|
212
|
-
const calls = [];
|
|
213
|
-
const executeAction = async (payload) => {
|
|
214
|
-
calls.push(payload);
|
|
215
|
-
return {
|
|
216
|
-
settings: {}
|
|
217
|
-
};
|
|
218
|
-
};
|
|
219
|
-
|
|
220
|
-
await findRoute(routes, { method: "GET", path: "/api/console/settings" }).handler(
|
|
221
|
-
createActionRequest({ executeAction }),
|
|
222
|
-
createReplyDouble()
|
|
223
|
-
);
|
|
224
|
-
|
|
225
|
-
await findRoute(routes, { method: "PATCH", path: "/api/console/settings" }).handler(
|
|
226
|
-
createActionRequest({
|
|
227
|
-
input: {
|
|
228
|
-
body: {}
|
|
229
|
-
},
|
|
230
|
-
executeAction
|
|
231
|
-
}),
|
|
232
|
-
createReplyDouble()
|
|
233
|
-
);
|
|
234
|
-
|
|
235
|
-
assert.equal(calls[0].actionId, "console.settings.read");
|
|
236
|
-
assert.deepEqual(calls[1], {
|
|
237
|
-
actionId: "console.settings.update",
|
|
238
|
-
input: {
|
|
239
|
-
payload: {}
|
|
240
|
-
}
|
|
241
|
-
});
|
|
242
|
-
});
|
|
@@ -5,7 +5,6 @@ import { existsSync } from "node:fs";
|
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
6
|
import { deriveResourceRequiredMetadata } from "@jskit-ai/kernel/_testable";
|
|
7
7
|
import "../test-support/registerDefaultSettingsFields.js";
|
|
8
|
-
import { consoleSettingsResource } from "../src/shared/resources/consoleSettingsResource.js";
|
|
9
8
|
import { userProfileResource } from "../src/shared/resources/userProfileResource.js";
|
|
10
9
|
import { userSettingsResource } from "../src/shared/resources/userSettingsResource.js";
|
|
11
10
|
import { workspaceMembersResource } from "../src/shared/resources/workspaceMembersResource.js";
|
|
@@ -47,13 +46,12 @@ function assertResourceShape(resource, label) {
|
|
|
47
46
|
assert.ok(Array.isArray(requiredMetadata.patch), `${label}.derivedRequired.patch must be an array.`);
|
|
48
47
|
}
|
|
49
48
|
|
|
50
|
-
test("workspace
|
|
49
|
+
test("workspace and account resources expose canonical validators", () => {
|
|
51
50
|
const resourcesByLabel = {
|
|
52
51
|
workspace: workspaceResource,
|
|
53
52
|
workspaceSettings: workspaceSettingsResource,
|
|
54
53
|
userProfile: userProfileResource,
|
|
55
|
-
userSettings: userSettingsResource
|
|
56
|
-
consoleSettings: consoleSettingsResource
|
|
54
|
+
userSettings: userSettingsResource
|
|
57
55
|
};
|
|
58
56
|
|
|
59
57
|
for (const [label, resource] of Object.entries(resourcesByLabel)) {
|