velocious 1.0.445 → 1.0.446
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/build/database/record/index.js +37 -37
- package/build/environment-handlers/node/cli/commands/generate/base-models.js +67 -1
- package/build/environment-handlers/node/cli/commands/generate/frontend-models.js +169 -0
- package/build/frontend-model-controller.js +44 -12
- package/build/frontend-model-resource/base-resource.js +519 -129
- package/build/frontend-models/base.js +324 -118
- package/build/frontend-models/websocket-channel.js +39 -3
- package/build/src/database/record/index.d.ts +37 -37
- package/build/src/database/record/index.d.ts.map +1 -1
- package/build/src/database/record/index.js +38 -38
- package/build/src/environment-handlers/node/cli/commands/generate/base-models.d.ts +13 -0
- package/build/src/environment-handlers/node/cli/commands/generate/base-models.d.ts.map +1 -1
- package/build/src/environment-handlers/node/cli/commands/generate/base-models.js +59 -2
- package/build/src/environment-handlers/node/cli/commands/generate/frontend-models.d.ts +74 -0
- package/build/src/environment-handlers/node/cli/commands/generate/frontend-models.d.ts.map +1 -1
- package/build/src/environment-handlers/node/cli/commands/generate/frontend-models.js +155 -1
- package/build/src/frontend-model-controller.d.ts +2 -1
- package/build/src/frontend-model-controller.d.ts.map +1 -1
- package/build/src/frontend-model-controller.js +38 -14
- package/build/src/frontend-model-resource/base-resource.d.ts +196 -21
- package/build/src/frontend-model-resource/base-resource.d.ts.map +1 -1
- package/build/src/frontend-model-resource/base-resource.js +467 -112
- package/build/src/frontend-models/base.d.ts +77 -4
- package/build/src/frontend-models/base.d.ts.map +1 -1
- package/build/src/frontend-models/base.js +278 -116
- package/build/src/frontend-models/websocket-channel.d.ts +8 -0
- package/build/src/frontend-models/websocket-channel.d.ts.map +1 -1
- package/build/src/frontend-models/websocket-channel.js +35 -4
- package/package.json +1 -1
- package/src/database/record/index.js +37 -37
- package/src/environment-handlers/node/cli/commands/generate/base-models.js +67 -1
- package/src/environment-handlers/node/cli/commands/generate/frontend-models.js +169 -0
- package/src/frontend-model-controller.js +44 -12
- package/src/frontend-model-resource/base-resource.js +519 -129
- package/src/frontend-models/base.js +324 -118
- package/src/frontend-models/websocket-channel.js +39 -3
|
@@ -61,7 +61,11 @@ export default class FrontendModelWebsocketChannel extends VelociousWebsocketCha
|
|
|
61
61
|
if (!ModelClass) return false
|
|
62
62
|
|
|
63
63
|
const ability = await configuration.resolveAbility?.({
|
|
64
|
-
params
|
|
64
|
+
// Forward the subscriber's params (e.g. authenticationToken) so token-authenticated clients
|
|
65
|
+
// resolve the same ability they would over HTTP. Without this only session/cookie auth on the
|
|
66
|
+
// upgrade request works, and param-based auth (like a scanner passing an authenticationToken)
|
|
67
|
+
// is dropped — leaving such subscribers with a guest ability and no read rule.
|
|
68
|
+
params: {...this.params, model: modelName},
|
|
65
69
|
request: /**
|
|
66
70
|
* Narrows the runtime value to the documented type.
|
|
67
71
|
@type {import("../http-server/client/request.js").default} */ (this._syntheticRequest()),
|
|
@@ -116,6 +120,15 @@ export default class FrontendModelWebsocketChannel extends VelociousWebsocketCha
|
|
|
116
120
|
const hasEventFilters = this._hasEventFilterParams()
|
|
117
121
|
|
|
118
122
|
if (!this._hasProjectionParams() && !hasEventFilters) {
|
|
123
|
+
// Even unfiltered subscriptions must respect the subscriber's ability. A create/update carries
|
|
124
|
+
// the record, so only deliver it when the record is within the authenticated ability's scope.
|
|
125
|
+
// Destroys (and bodies without a usable id) carry no record, so pass them through unchanged.
|
|
126
|
+
if (body && typeof body === "object" && (body.action === "create" || body.action === "update") && body.id !== undefined && body.id !== null) {
|
|
127
|
+
const FrontendModelController = await this._frontendModelControllerClass()
|
|
128
|
+
|
|
129
|
+
if (!await this._eventIsAccessible(body.id, FrontendModelController)) return
|
|
130
|
+
}
|
|
131
|
+
|
|
119
132
|
this.sendMessage(body, meta)
|
|
120
133
|
return
|
|
121
134
|
}
|
|
@@ -343,6 +356,25 @@ export default class FrontendModelWebsocketChannel extends VelociousWebsocketCha
|
|
|
343
356
|
return controller
|
|
344
357
|
}
|
|
345
358
|
|
|
359
|
+
/**
|
|
360
|
+
* Whether the broadcast record is within the subscriber's authenticated ability scope. Used to gate
|
|
361
|
+
* unfiltered/unprojected create/update delivery so a scoped token never receives a record it cannot read.
|
|
362
|
+
* @param {string | number} id - Event record id.
|
|
363
|
+
* @param {typeof import("../frontend-model-controller.js").default} FrontendModelController - Server-side frontend-model controller class.
|
|
364
|
+
* @returns {Promise<boolean>} True when the record is readable by this subscription.
|
|
365
|
+
*/
|
|
366
|
+
async _eventIsAccessible(id, FrontendModelController) {
|
|
367
|
+
const controller = this._frontendModelController(FrontendModelController)
|
|
368
|
+
|
|
369
|
+
await controller.ensureFrontendModelClassInitialized()
|
|
370
|
+
|
|
371
|
+
const ModelClass = controller.frontendModelClass()
|
|
372
|
+
const primaryKey = ModelClass.primaryKey()
|
|
373
|
+
const query = controller.frontendModelAuthorizedQuery("find").where({[ModelClass.tableName()]: {[primaryKey]: id}})
|
|
374
|
+
|
|
375
|
+
return Boolean(await query.first())
|
|
376
|
+
}
|
|
377
|
+
|
|
346
378
|
/**
|
|
347
379
|
* Runs matched event filter keys for event id.
|
|
348
380
|
* @param {string | number} id - Event record id.
|
|
@@ -389,7 +421,9 @@ export default class FrontendModelWebsocketChannel extends VelociousWebsocketCha
|
|
|
389
421
|
const primaryKey = ModelClass.primaryKey()
|
|
390
422
|
const where = controller.frontendModelWhere()
|
|
391
423
|
const joins = controller.frontendModelJoins()
|
|
392
|
-
|
|
424
|
+
// Start from the subscriber's authorized scope so a filter can only ever match records the
|
|
425
|
+
// subscription's ability permits to read.
|
|
426
|
+
let query = controller.frontendModelAuthorizedQuery("find").where({[ModelClass.tableName()]: {[primaryKey]: id}})
|
|
393
427
|
|
|
394
428
|
if (where) controller.applyFrontendModelWhere({query, where})
|
|
395
429
|
if (joins) controller.applyFrontendModelJoins({joins, query})
|
|
@@ -414,7 +448,9 @@ export default class FrontendModelWebsocketChannel extends VelociousWebsocketCha
|
|
|
414
448
|
|
|
415
449
|
const ModelClass = controller.frontendModelClass()
|
|
416
450
|
const primaryKey = ModelClass.primaryKey()
|
|
417
|
-
|
|
451
|
+
// Reload through the subscriber's authorized scope so projected records are only ever sent for
|
|
452
|
+
// rows the subscription's ability permits to read.
|
|
453
|
+
let query = controller.frontendModelAuthorizedQuery("find").where({[ModelClass.tableName()]: {[primaryKey]: id}})
|
|
418
454
|
const preload = controller.frontendModelPreload()
|
|
419
455
|
|
|
420
456
|
if (preload) query = query.preload(preload)
|