@jskit-ai/users-core 0.1.172 → 0.1.174
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.json +41 -253
- package/patterns/user-administration-server/PATTERN.md +64 -0
- package/patterns/user-administration-server/example/packages/users/package.json +42 -0
- package/patterns/user-administration-server/example/packages/users/src/server/UsersFeature.js +13 -0
- package/patterns/user-administration-server/example/packages/users/src/shared/index.js +1 -0
- package/patterns/user-administration-server/example/packages/users-workspace/package.json +43 -0
- package/patterns/user-administration-server/example/packages/users-workspace/src/server/UsersWorkspaceFeature.js +22 -0
- package/patterns/user-administration-server/example/packages/users-workspace/src/shared/userResource.js +56 -0
- package/src/server/UsersExtensionsProvider.js +14 -0
- package/src/server/UsersFeature.js +119 -0
- package/src/server/UsersIdentityProvider.js +57 -0
- package/src/server/accountNotifications/accountNotificationsActions.js +17 -5
- package/src/server/accountNotifications/bootAccountNotificationsRoutes.js +4 -6
- package/src/server/accountPreferences/accountPreferencesActions.js +17 -5
- package/src/server/accountPreferences/bootAccountPreferencesRoutes.js +4 -6
- package/src/server/accountProfile/accountProfileActions.js +28 -14
- package/src/server/accountProfile/bootAccountProfileRoutes.js +11 -10
- package/src/server/accountSecurity/accountSecurityActions.js +27 -17
- package/src/server/accountSecurity/bootAccountSecurityRoutes.js +4 -7
- package/src/server/common/services/authProfileSyncService.js +11 -4
- package/src/server/common/support/realtimeServiceEvents.js +8 -11
- package/src/server/usersBootstrapContributor.js +4 -28
- package/src/server/usersExtensions.js +65 -0
- package/test/authProfileSyncService.test.js +2 -2
- package/test/exportsContract.test.js +6 -1
- package/test/featureRuntime.test.js +78 -0
- package/test/usersBootstrapContributor.test.js +1 -43
- package/test/usersPackageScaffoldContract.test.js +58 -204
- package/test/usersRouteRequestInputValidator.test.js +19 -43
- package/src/server/UsersCoreServiceProvider.js +0 -56
- package/src/server/accountNotifications/registerAccountNotifications.js +0 -37
- package/src/server/accountPreferences/registerAccountPreferences.js +0 -37
- package/src/server/accountProfile/registerAccountProfile.js +0 -56
- package/src/server/accountSecurity/registerAccountSecurity.js +0 -29
- package/src/server/common/registerCommonRepositories.js +0 -23
- package/src/server/common/registerSharedApi.js +0 -9
- package/src/server/profileSyncLifecycleContributorRegistry.js +0 -56
- package/src/server/registerUsersBootstrap.js +0 -20
- package/src/server/registerUsersCore.js +0 -22
- package/templates/packages/users/package.json +0 -82
- package/templates/packages/users/src/server/UsersProvider.js +0 -90
- package/templates/packages/users/src/server/actions.js +0 -68
- package/templates/packages/users/src/server/registerRoutes.js +0 -101
- package/templates/packages/users/src/server/repository.js +0 -51
- package/templates/packages/users/src/server/service.js +0 -32
- package/templates/packages/users-workspace/package.json +0 -83
- package/templates/packages/users-workspace/src/server/UsersProvider.js +0 -91
- package/templates/packages/users-workspace/src/server/actions.js +0 -77
- package/templates/packages/users-workspace/src/server/registerRoutes.js +0 -111
- package/test/providerLifecycle.test.js +0 -63
- package/test/registerCommonRepositories.test.js +0 -57
- package/test/registerServiceRealtimeEvents.test.js +0 -57
- package/test/registerUsersCore.test.js +0 -53
- /package/{templates/migrations → migrations}/users_core_generic_initial.cjs +0 -0
- /package/{templates/migrations → migrations}/users_core_profile_updated_at.cjs +0 -0
- /package/{templates/migrations → migrations}/users_core_profile_username.cjs +0 -0
- /package/{templates → patterns/user-administration-server/example}/packages/users/src/shared/userResource.js +0 -0
- /package/{templates/packages/users → patterns/user-administration-server/example/packages/users-workspace}/src/shared/index.js +0 -0
package/package.json
CHANGED
|
@@ -1,25 +1,27 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jskit-ai/users-core",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.174",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"test": "node --test"
|
|
7
7
|
},
|
|
8
8
|
"exports": {
|
|
9
|
-
"./server/
|
|
9
|
+
"./server/UsersFeature": "./src/server/UsersFeature.js",
|
|
10
|
+
"./server/UsersIdentityProvider": "./src/server/UsersIdentityProvider.js",
|
|
11
|
+
"./server/usersExtensions": "./src/server/usersExtensions.js",
|
|
10
12
|
"./shared/resources/userProfileResource": "./src/shared/resources/userProfileResource.js",
|
|
11
13
|
"./shared/resources/userSettingsResource": "./src/shared/resources/userSettingsResource.js"
|
|
12
14
|
},
|
|
13
15
|
"dependencies": {
|
|
14
|
-
"@jskit-ai/auth-core": "0.1.
|
|
15
|
-
"@jskit-ai/database-runtime": "0.1.
|
|
16
|
-
"@jskit-ai/http-runtime": "0.1.
|
|
17
|
-
"@jskit-ai/json-rest-api-core": "0.1.
|
|
18
|
-
"@jskit-ai/kernel": "0.1.
|
|
19
|
-
"@jskit-ai/resource-core": "0.1.
|
|
20
|
-
"@jskit-ai/resource-crud-core": "0.1.
|
|
21
|
-
"@jskit-ai/storage-runtime": "0.1.
|
|
22
|
-
"@jskit-ai/uploads-runtime": "0.1.
|
|
16
|
+
"@jskit-ai/auth-core": "0.1.159",
|
|
17
|
+
"@jskit-ai/database-runtime": "0.1.161",
|
|
18
|
+
"@jskit-ai/http-runtime": "0.1.159",
|
|
19
|
+
"@jskit-ai/json-rest-api-core": "0.1.105",
|
|
20
|
+
"@jskit-ai/kernel": "0.1.161",
|
|
21
|
+
"@jskit-ai/resource-core": "0.1.103",
|
|
22
|
+
"@jskit-ai/resource-crud-core": "0.1.103",
|
|
23
|
+
"@jskit-ai/storage-runtime": "0.1.158",
|
|
24
|
+
"@jskit-ai/uploads-runtime": "0.1.136",
|
|
23
25
|
"json-rest-schema": "^1.0.17"
|
|
24
26
|
},
|
|
25
27
|
"description": "Users/account runtime plus HTTP routes for account features.",
|
|
@@ -28,24 +30,35 @@
|
|
|
28
30
|
"capabilities": {
|
|
29
31
|
"provides": [
|
|
30
32
|
"users.core",
|
|
31
|
-
"users.
|
|
33
|
+
"users.identity",
|
|
34
|
+
"users.extensions"
|
|
32
35
|
],
|
|
33
36
|
"requires": [
|
|
37
|
+
"auth.extensions",
|
|
38
|
+
"auth.service",
|
|
34
39
|
"runtime.actions",
|
|
40
|
+
"runtime.bootstrap",
|
|
35
41
|
"runtime.database",
|
|
36
|
-
"
|
|
42
|
+
"runtime.http",
|
|
43
|
+
"runtime.json-rest-api",
|
|
37
44
|
"runtime.storage",
|
|
38
|
-
"runtime.uploads"
|
|
39
|
-
"auth.provider",
|
|
40
|
-
"auth.policy"
|
|
45
|
+
"runtime.uploads"
|
|
41
46
|
]
|
|
42
47
|
},
|
|
43
48
|
"runtime": {
|
|
44
49
|
"server": {
|
|
45
50
|
"providers": [
|
|
46
51
|
{
|
|
47
|
-
"entrypoint": "src/server/
|
|
48
|
-
"export": "
|
|
52
|
+
"entrypoint": "src/server/UsersExtensionsProvider.js",
|
|
53
|
+
"export": "UsersExtensionsProvider"
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"entrypoint": "src/server/UsersIdentityProvider.js",
|
|
57
|
+
"export": "UsersIdentityProvider"
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"entrypoint": "src/server/UsersFeature.js",
|
|
61
|
+
"export": "UsersFeature"
|
|
49
62
|
}
|
|
50
63
|
]
|
|
51
64
|
},
|
|
@@ -58,9 +71,7 @@
|
|
|
58
71
|
"tableOwnership": {
|
|
59
72
|
"tables": [
|
|
60
73
|
{
|
|
61
|
-
"tableName": "user_settings"
|
|
62
|
-
"provenance": "runtime-package",
|
|
63
|
-
"ownerKind": "package-runtime"
|
|
74
|
+
"tableName": "user_settings"
|
|
64
75
|
}
|
|
65
76
|
]
|
|
66
77
|
}
|
|
@@ -69,7 +80,7 @@
|
|
|
69
80
|
"surfaces": [
|
|
70
81
|
{
|
|
71
82
|
"subpath": "./server",
|
|
72
|
-
"summary": "Exports
|
|
83
|
+
"summary": "Exports the explicit users feature, account services, repositories, actions, and extension API."
|
|
73
84
|
},
|
|
74
85
|
{
|
|
75
86
|
"subpath": "./shared",
|
|
@@ -80,13 +91,11 @@
|
|
|
80
91
|
"summary": "Exports no runtime API today (reserved client entrypoint)."
|
|
81
92
|
}
|
|
82
93
|
],
|
|
83
|
-
"
|
|
84
|
-
"
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
"client": []
|
|
89
|
-
}
|
|
94
|
+
"capabilities": [
|
|
95
|
+
"users.core",
|
|
96
|
+
"users.identity",
|
|
97
|
+
"users.extensions"
|
|
98
|
+
]
|
|
90
99
|
},
|
|
91
100
|
"server": {
|
|
92
101
|
"routes": [
|
|
@@ -153,230 +162,9 @@
|
|
|
153
162
|
]
|
|
154
163
|
}
|
|
155
164
|
},
|
|
156
|
-
"
|
|
157
|
-
"
|
|
158
|
-
"
|
|
159
|
-
"@jskit-ai/auth-core": "0.1.157",
|
|
160
|
-
"@jskit-ai/crud-core": "0.1.170",
|
|
161
|
-
"@jskit-ai/database-runtime": "0.1.159",
|
|
162
|
-
"@jskit-ai/http-runtime": "0.1.157",
|
|
163
|
-
"@jskit-ai/json-rest-api-core": "0.1.103",
|
|
164
|
-
"@jskit-ai/kernel": "0.1.159",
|
|
165
|
-
"@jskit-ai/resource-core": "0.1.101",
|
|
166
|
-
"@jskit-ai/resource-crud-core": "0.1.101",
|
|
167
|
-
"@local/users": "file:packages/users",
|
|
168
|
-
"@jskit-ai/uploads-runtime": "0.1.134"
|
|
169
|
-
},
|
|
170
|
-
"dev": {}
|
|
171
|
-
},
|
|
172
|
-
"packageJson": {
|
|
173
|
-
"scripts": {}
|
|
174
|
-
},
|
|
175
|
-
"procfile": {},
|
|
176
|
-
"files": [
|
|
177
|
-
{
|
|
178
|
-
"op": "install-migration",
|
|
179
|
-
"from": "templates/migrations/users_core_generic_initial.cjs",
|
|
180
|
-
"toDir": "migrations",
|
|
181
|
-
"extension": ".cjs",
|
|
182
|
-
"reason": "Install users/account core schema migration.",
|
|
183
|
-
"category": "migration",
|
|
184
|
-
"id": "users-core-generic-initial-schema"
|
|
185
|
-
},
|
|
186
|
-
{
|
|
187
|
-
"op": "install-migration",
|
|
188
|
-
"from": "templates/migrations/users_core_profile_username.cjs",
|
|
189
|
-
"toDir": "migrations",
|
|
190
|
-
"extension": ".cjs",
|
|
191
|
-
"reason": "Install users profile username migration.",
|
|
192
|
-
"category": "migration",
|
|
193
|
-
"id": "users-core-profile-username-schema"
|
|
194
|
-
},
|
|
195
|
-
{
|
|
196
|
-
"op": "install-migration",
|
|
197
|
-
"from": "templates/migrations/users_core_profile_updated_at.cjs",
|
|
198
|
-
"toDir": "migrations",
|
|
199
|
-
"extension": ".cjs",
|
|
200
|
-
"reason": "Install users profile updated-at migration.",
|
|
201
|
-
"category": "migration",
|
|
202
|
-
"id": "users-core-profile-updated-at-schema"
|
|
203
|
-
},
|
|
204
|
-
{
|
|
205
|
-
"from": "templates/packages/users/package.json",
|
|
206
|
-
"to": "packages/users/package.json",
|
|
207
|
-
"ownership": "app",
|
|
208
|
-
"preserveOnRemove": true,
|
|
209
|
-
"reason": "Install app-owned users package manifest for non-workspace tenancy.",
|
|
210
|
-
"category": "users-core",
|
|
211
|
-
"id": "users-core-users-package-json-base",
|
|
212
|
-
"when": {
|
|
213
|
-
"config": "tenancyMode",
|
|
214
|
-
"notIn": [
|
|
215
|
-
"personal",
|
|
216
|
-
"workspaces"
|
|
217
|
-
]
|
|
218
|
-
}
|
|
219
|
-
},
|
|
220
|
-
{
|
|
221
|
-
"from": "templates/packages/users-workspace/package.json",
|
|
222
|
-
"to": "packages/users/package.json",
|
|
223
|
-
"ownership": "app",
|
|
224
|
-
"preserveOnRemove": true,
|
|
225
|
-
"reason": "Install app-owned users package manifest for workspace tenancy.",
|
|
226
|
-
"category": "users-core",
|
|
227
|
-
"id": "users-core-users-package-json-workspace",
|
|
228
|
-
"when": {
|
|
229
|
-
"config": "tenancyMode",
|
|
230
|
-
"in": [
|
|
231
|
-
"personal",
|
|
232
|
-
"workspaces"
|
|
233
|
-
]
|
|
234
|
-
}
|
|
235
|
-
},
|
|
236
|
-
{
|
|
237
|
-
"from": "templates/packages/users/src/server/UsersProvider.js",
|
|
238
|
-
"to": "packages/users/src/server/UsersProvider.js",
|
|
239
|
-
"ownership": "app",
|
|
240
|
-
"preserveOnRemove": true,
|
|
241
|
-
"reason": "Install app-owned users CRUD provider for non-workspace tenancy.",
|
|
242
|
-
"category": "users-core",
|
|
243
|
-
"id": "users-core-users-provider-base",
|
|
244
|
-
"when": {
|
|
245
|
-
"config": "tenancyMode",
|
|
246
|
-
"notIn": [
|
|
247
|
-
"personal",
|
|
248
|
-
"workspaces"
|
|
249
|
-
]
|
|
250
|
-
}
|
|
251
|
-
},
|
|
252
|
-
{
|
|
253
|
-
"from": "templates/packages/users-workspace/src/server/UsersProvider.js",
|
|
254
|
-
"to": "packages/users/src/server/UsersProvider.js",
|
|
255
|
-
"ownership": "app",
|
|
256
|
-
"preserveOnRemove": true,
|
|
257
|
-
"reason": "Install app-owned users CRUD provider for workspace tenancy.",
|
|
258
|
-
"category": "users-core",
|
|
259
|
-
"id": "users-core-users-provider-workspace",
|
|
260
|
-
"when": {
|
|
261
|
-
"config": "tenancyMode",
|
|
262
|
-
"in": [
|
|
263
|
-
"personal",
|
|
264
|
-
"workspaces"
|
|
265
|
-
]
|
|
266
|
-
}
|
|
267
|
-
},
|
|
268
|
-
{
|
|
269
|
-
"from": "templates/packages/users/src/server/actions.js",
|
|
270
|
-
"to": "packages/users/src/server/actions.js",
|
|
271
|
-
"ownership": "app",
|
|
272
|
-
"preserveOnRemove": true,
|
|
273
|
-
"reason": "Install app-owned users CRUD actions for non-workspace tenancy.",
|
|
274
|
-
"category": "users-core",
|
|
275
|
-
"id": "users-core-users-actions-base",
|
|
276
|
-
"when": {
|
|
277
|
-
"config": "tenancyMode",
|
|
278
|
-
"notIn": [
|
|
279
|
-
"personal",
|
|
280
|
-
"workspaces"
|
|
281
|
-
]
|
|
282
|
-
}
|
|
283
|
-
},
|
|
284
|
-
{
|
|
285
|
-
"from": "templates/packages/users-workspace/src/server/actions.js",
|
|
286
|
-
"to": "packages/users/src/server/actions.js",
|
|
287
|
-
"ownership": "app",
|
|
288
|
-
"preserveOnRemove": true,
|
|
289
|
-
"reason": "Install app-owned users CRUD actions for workspace tenancy.",
|
|
290
|
-
"category": "users-core",
|
|
291
|
-
"id": "users-core-users-actions-workspace",
|
|
292
|
-
"when": {
|
|
293
|
-
"config": "tenancyMode",
|
|
294
|
-
"in": [
|
|
295
|
-
"personal",
|
|
296
|
-
"workspaces"
|
|
297
|
-
]
|
|
298
|
-
}
|
|
299
|
-
},
|
|
300
|
-
{
|
|
301
|
-
"from": "templates/packages/users/src/server/registerRoutes.js",
|
|
302
|
-
"to": "packages/users/src/server/registerRoutes.js",
|
|
303
|
-
"ownership": "app",
|
|
304
|
-
"preserveOnRemove": true,
|
|
305
|
-
"reason": "Install app-owned users CRUD routes for non-workspace tenancy.",
|
|
306
|
-
"category": "users-core",
|
|
307
|
-
"id": "users-core-users-routes-base",
|
|
308
|
-
"when": {
|
|
309
|
-
"config": "tenancyMode",
|
|
310
|
-
"notIn": [
|
|
311
|
-
"personal",
|
|
312
|
-
"workspaces"
|
|
313
|
-
]
|
|
314
|
-
}
|
|
315
|
-
},
|
|
316
|
-
{
|
|
317
|
-
"from": "templates/packages/users-workspace/src/server/registerRoutes.js",
|
|
318
|
-
"to": "packages/users/src/server/registerRoutes.js",
|
|
319
|
-
"ownership": "app",
|
|
320
|
-
"preserveOnRemove": true,
|
|
321
|
-
"reason": "Install app-owned users CRUD routes for workspace tenancy.",
|
|
322
|
-
"category": "users-core",
|
|
323
|
-
"id": "users-core-users-routes-workspace",
|
|
324
|
-
"when": {
|
|
325
|
-
"config": "tenancyMode",
|
|
326
|
-
"in": [
|
|
327
|
-
"personal",
|
|
328
|
-
"workspaces"
|
|
329
|
-
]
|
|
330
|
-
}
|
|
331
|
-
},
|
|
332
|
-
{
|
|
333
|
-
"from": "templates/packages/users/src/server/repository.js",
|
|
334
|
-
"to": "packages/users/src/server/repository.js",
|
|
335
|
-
"ownership": "app",
|
|
336
|
-
"preserveOnRemove": true,
|
|
337
|
-
"reason": "Install app-owned users CRUD repository.",
|
|
338
|
-
"category": "users-core",
|
|
339
|
-
"id": "users-core-users-repository"
|
|
340
|
-
},
|
|
341
|
-
{
|
|
342
|
-
"from": "templates/packages/users/src/server/service.js",
|
|
343
|
-
"to": "packages/users/src/server/service.js",
|
|
344
|
-
"ownership": "app",
|
|
345
|
-
"preserveOnRemove": true,
|
|
346
|
-
"reason": "Install app-owned users CRUD service.",
|
|
347
|
-
"category": "users-core",
|
|
348
|
-
"id": "users-core-users-service"
|
|
349
|
-
},
|
|
350
|
-
{
|
|
351
|
-
"from": "templates/packages/users/src/shared/index.js",
|
|
352
|
-
"to": "packages/users/src/shared/index.js",
|
|
353
|
-
"ownership": "app",
|
|
354
|
-
"preserveOnRemove": true,
|
|
355
|
-
"reason": "Install app-owned users shared entrypoint.",
|
|
356
|
-
"category": "users-core",
|
|
357
|
-
"id": "users-core-users-shared-index"
|
|
358
|
-
},
|
|
359
|
-
{
|
|
360
|
-
"from": "templates/packages/users/src/shared/userResource.js",
|
|
361
|
-
"to": "packages/users/src/shared/userResource.js",
|
|
362
|
-
"ownership": "app",
|
|
363
|
-
"preserveOnRemove": true,
|
|
364
|
-
"reason": "Install app-owned users shared resource.",
|
|
365
|
-
"category": "users-core",
|
|
366
|
-
"id": "users-core-users-resource"
|
|
367
|
-
}
|
|
368
|
-
],
|
|
369
|
-
"text": [
|
|
370
|
-
{
|
|
371
|
-
"op": "append-text",
|
|
372
|
-
"file": "config/server.js",
|
|
373
|
-
"position": "bottom",
|
|
374
|
-
"skipIfContains": "config.auth.profileMode = \"users\";",
|
|
375
|
-
"value": "\nconfig.auth ||= {};\nconfig.auth.profileMode = \"users\";\n",
|
|
376
|
-
"reason": "Enable users-backed auth profile sync when users-core is installed.",
|
|
377
|
-
"category": "runtime-config",
|
|
378
|
-
"id": "users-core-auth-profile-mode"
|
|
379
|
-
}
|
|
165
|
+
"migrations": {
|
|
166
|
+
"directories": [
|
|
167
|
+
"migrations"
|
|
380
168
|
]
|
|
381
169
|
}
|
|
382
170
|
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: users/user-administration-server
|
|
3
|
+
title: User administration server package
|
|
4
|
+
summary: Expose user administration and workspace-scoped member operations through app-owned packages backed by JSKIT users runtime APIs.
|
|
5
|
+
keywords: account, admin, member, repository, resource, routes, service, user, workspace
|
|
6
|
+
requires: @jskit-ai/users-core, @jskit-ai/crud-core
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# User administration server package
|
|
10
|
+
|
|
11
|
+
## Use when
|
|
12
|
+
|
|
13
|
+
Use this pattern when an application needs app-specific administration of user
|
|
14
|
+
profiles or workspace members beyond the built-in account runtime.
|
|
15
|
+
|
|
16
|
+
## Do not use when
|
|
17
|
+
|
|
18
|
+
Do not use this pattern for self-service account settings, authentication
|
|
19
|
+
credentials, or an application that needs no administrative user listing.
|
|
20
|
+
|
|
21
|
+
## Product decisions
|
|
22
|
+
|
|
23
|
+
Choose global versus workspace scope, visible and editable fields, permission
|
|
24
|
+
policy, route surface, filters, and whether account deletion is part of the
|
|
25
|
+
product. Do not expose password/session data through the resource.
|
|
26
|
+
|
|
27
|
+
## Framework APIs
|
|
28
|
+
|
|
29
|
+
Use `@jskit-ai/users-core` for profile persistence and policies,
|
|
30
|
+
`defineCrudJsonApiFeature()` from `@jskit-ai/crud-core` for standard mechanics,
|
|
31
|
+
and the resource contracts from `@jskit-ai/resource-crud-core`.
|
|
32
|
+
|
|
33
|
+
## Invariants
|
|
34
|
+
|
|
35
|
+
- The public user id is the resource identity.
|
|
36
|
+
- Workspace operations are scoped before repository access.
|
|
37
|
+
- Permission checks happen before records or record existence are disclosed.
|
|
38
|
+
- Shared profile persistence remains owned by `@jskit-ai/users-core`.
|
|
39
|
+
- The resource is the field contract; the feature projects its repository,
|
|
40
|
+
service, actions, and routes without app-local ceremony.
|
|
41
|
+
|
|
42
|
+
## Example files
|
|
43
|
+
|
|
44
|
+
`example/packages/users/` is a global administration package.
|
|
45
|
+
`example/packages/users-workspace/` demonstrates the workspace route/action
|
|
46
|
+
boundary while reusing the same service contract. Copy only the composition
|
|
47
|
+
that matches the product and adapt it as ordinary application source.
|
|
48
|
+
|
|
49
|
+
## Variation points
|
|
50
|
+
|
|
51
|
+
Change scope, route surface, visible fields, filters, sorting, permission
|
|
52
|
+
policy, and user-facing language. Retain the core user identity contract.
|
|
53
|
+
|
|
54
|
+
## Verification
|
|
55
|
+
|
|
56
|
+
Test authorized and forbidden list/view/update operations, cross-workspace
|
|
57
|
+
isolation, missing records, null/cleared fields, filtering, and pagination.
|
|
58
|
+
|
|
59
|
+
## Avoid
|
|
60
|
+
|
|
61
|
+
- copying authentication credential tables into the user resource
|
|
62
|
+
- trusting route scope without repository scope
|
|
63
|
+
- adding app-local mechanics already provided by `defineCrudJsonApiFeature()`
|
|
64
|
+
- generator metadata or field questionnaires
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@app/users",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"description": "App-local read-only user administration feature.",
|
|
5
|
+
"private": true,
|
|
6
|
+
"type": "module",
|
|
7
|
+
"exports": {
|
|
8
|
+
"./server/UsersFeature": "./src/server/UsersFeature.js",
|
|
9
|
+
"./shared": "./src/shared/index.js"
|
|
10
|
+
},
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"@jskit-ai/crud-core": "0.1.172",
|
|
13
|
+
"@jskit-ai/resource-crud-core": "0.1.103"
|
|
14
|
+
},
|
|
15
|
+
"jskit": {
|
|
16
|
+
"kind": "runtime",
|
|
17
|
+
"capabilities": {
|
|
18
|
+
"provides": [
|
|
19
|
+
"app.users"
|
|
20
|
+
],
|
|
21
|
+
"requires": [
|
|
22
|
+
"runtime.http",
|
|
23
|
+
"runtime.json-rest-api",
|
|
24
|
+
"runtime.actions",
|
|
25
|
+
"runtime.database"
|
|
26
|
+
]
|
|
27
|
+
},
|
|
28
|
+
"runtime": {
|
|
29
|
+
"server": {
|
|
30
|
+
"providers": [
|
|
31
|
+
{
|
|
32
|
+
"entrypoint": "src/server/UsersFeature.js",
|
|
33
|
+
"export": "UsersFeature"
|
|
34
|
+
}
|
|
35
|
+
]
|
|
36
|
+
},
|
|
37
|
+
"client": {
|
|
38
|
+
"providers": []
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { defineCrudJsonApiFeature } from "@jskit-ai/crud-core/server/defineCrudJsonApiFeature";
|
|
2
|
+
import { resource } from "../shared/userResource.js";
|
|
3
|
+
|
|
4
|
+
const UsersFeature = defineCrudJsonApiFeature({
|
|
5
|
+
resource,
|
|
6
|
+
id: "app.users",
|
|
7
|
+
capability: "app.users",
|
|
8
|
+
surface: "home",
|
|
9
|
+
ownershipFilter: "public",
|
|
10
|
+
relativePath: "/users"
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
export { UsersFeature };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { resource } from "./userResource.js";
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@app/users-workspace",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"description": "App-local workspace-scoped read-only user administration feature.",
|
|
5
|
+
"private": true,
|
|
6
|
+
"type": "module",
|
|
7
|
+
"exports": {
|
|
8
|
+
"./server/UsersWorkspaceFeature": "./src/server/UsersWorkspaceFeature.js",
|
|
9
|
+
"./shared": "./src/shared/index.js"
|
|
10
|
+
},
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"@jskit-ai/crud-core": "0.1.172",
|
|
13
|
+
"@jskit-ai/resource-crud-core": "0.1.103",
|
|
14
|
+
"@jskit-ai/workspaces-core": "0.1.139"
|
|
15
|
+
},
|
|
16
|
+
"jskit": {
|
|
17
|
+
"kind": "runtime",
|
|
18
|
+
"capabilities": {
|
|
19
|
+
"provides": [
|
|
20
|
+
"app.users-workspace"
|
|
21
|
+
],
|
|
22
|
+
"requires": [
|
|
23
|
+
"runtime.http",
|
|
24
|
+
"runtime.json-rest-api",
|
|
25
|
+
"runtime.actions",
|
|
26
|
+
"runtime.database"
|
|
27
|
+
]
|
|
28
|
+
},
|
|
29
|
+
"runtime": {
|
|
30
|
+
"server": {
|
|
31
|
+
"providers": [
|
|
32
|
+
{
|
|
33
|
+
"entrypoint": "src/server/UsersWorkspaceFeature.js",
|
|
34
|
+
"export": "UsersWorkspaceFeature"
|
|
35
|
+
}
|
|
36
|
+
]
|
|
37
|
+
},
|
|
38
|
+
"client": {
|
|
39
|
+
"providers": []
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { defineCrudJsonApiFeature } from "@jskit-ai/crud-core/server/defineCrudJsonApiFeature";
|
|
2
|
+
import { buildWorkspaceInputFromRouteParams } from "@jskit-ai/workspaces-core/server/support/workspaceRouteInput";
|
|
3
|
+
import { workspaceSlugParamsValidator } from "@jskit-ai/workspaces-core/server/validators/routeParamsValidator";
|
|
4
|
+
import { resource } from "../shared/userResource.js";
|
|
5
|
+
|
|
6
|
+
const UsersWorkspaceFeature = defineCrudJsonApiFeature({
|
|
7
|
+
resource,
|
|
8
|
+
id: "app.users-workspace",
|
|
9
|
+
capability: "app.users-workspace",
|
|
10
|
+
surface: "admin",
|
|
11
|
+
ownershipFilter: "workspace",
|
|
12
|
+
relativePath: "/users",
|
|
13
|
+
scope: {
|
|
14
|
+
routeBase: "/w/:workspaceSlug",
|
|
15
|
+
actionInputValidator: workspaceSlugParamsValidator,
|
|
16
|
+
routeParamsValidator: workspaceSlugParamsValidator,
|
|
17
|
+
inputKeys: ["workspaceSlug"],
|
|
18
|
+
input: (request) => buildWorkspaceInputFromRouteParams(request.input.params)
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
export { UsersWorkspaceFeature };
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { defineCrudResource } from "@jskit-ai/resource-crud-core/shared/crudResource";
|
|
2
|
+
|
|
3
|
+
const resource = defineCrudResource({
|
|
4
|
+
namespace: "users",
|
|
5
|
+
tableName: "users",
|
|
6
|
+
crudOperations: ["list", "view"],
|
|
7
|
+
schema: {
|
|
8
|
+
name: {
|
|
9
|
+
type: "string",
|
|
10
|
+
required: true,
|
|
11
|
+
minLength: 1,
|
|
12
|
+
maxLength: 160,
|
|
13
|
+
actualField: "display_name",
|
|
14
|
+
search: true,
|
|
15
|
+
operations: { output: { required: false } }
|
|
16
|
+
},
|
|
17
|
+
email: {
|
|
18
|
+
type: "string",
|
|
19
|
+
required: true,
|
|
20
|
+
search: true,
|
|
21
|
+
operations: { output: { required: false } }
|
|
22
|
+
},
|
|
23
|
+
username: {
|
|
24
|
+
type: "string",
|
|
25
|
+
required: true,
|
|
26
|
+
search: true,
|
|
27
|
+
operations: { output: { required: false } }
|
|
28
|
+
},
|
|
29
|
+
createdAt: {
|
|
30
|
+
type: "dateTime",
|
|
31
|
+
required: true,
|
|
32
|
+
storage: { writeSerializer: "datetime-utc" },
|
|
33
|
+
operations: { output: { required: true } }
|
|
34
|
+
},
|
|
35
|
+
updatedAt: {
|
|
36
|
+
type: "dateTime",
|
|
37
|
+
required: true,
|
|
38
|
+
storage: { writeSerializer: "datetime-utc" },
|
|
39
|
+
operations: { output: { required: true } }
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
searchSchema: {
|
|
43
|
+
id: { type: "id", actualField: "id" },
|
|
44
|
+
q: {
|
|
45
|
+
type: "string",
|
|
46
|
+
oneOf: ["name", "email", "username"],
|
|
47
|
+
filterOperator: "like",
|
|
48
|
+
splitBy: " ",
|
|
49
|
+
matchAll: true
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
defaultSort: ["name", "email"],
|
|
53
|
+
autofilter: "public"
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
export { resource };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { defineProvider } from "@jskit-ai/kernel/shared/capabilities";
|
|
2
|
+
import { createUsersExtensions } from "./usersExtensions.js";
|
|
3
|
+
|
|
4
|
+
const UsersExtensionsProvider = defineProvider({
|
|
5
|
+
id: "users.extensions",
|
|
6
|
+
provides: {
|
|
7
|
+
extensions: "users.extensions"
|
|
8
|
+
},
|
|
9
|
+
setup() {
|
|
10
|
+
return { extensions: createUsersExtensions() };
|
|
11
|
+
}
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
export { UsersExtensionsProvider };
|