@almadar/runtime 6.46.0 → 6.47.0
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/dist/OrbitalServerRuntime.js +68 -20
- package/dist/index.js +1 -1
- package/package.json +3 -3
|
@@ -8,7 +8,7 @@ import { createLogger } from '@almadar/logger';
|
|
|
8
8
|
import * as nodeModule from 'module';
|
|
9
9
|
import { evaluateListenPayloadExpr, evaluateGuard, evaluate } from '@almadar/evaluator';
|
|
10
10
|
import { DEFAULT_VIEWER, buildResolvedTraitConfigs, isInlineTrait, isEntityCall, applyListenPayloadMapping, personaFromIdentityRow, normalizeUserContext, isRuntimeEntity } from '@almadar/core';
|
|
11
|
-
import { ownerFieldsFromSchema, identityEntityName } from '@almadar/core/mock';
|
|
11
|
+
import { ownerFieldsFromSchema, identityEntityName, entityAccessPolicies } from '@almadar/core/mock';
|
|
12
12
|
|
|
13
13
|
// src/identity/routing.ts
|
|
14
14
|
function eventRouteKey(eventName, eventId) {
|
|
@@ -33,6 +33,41 @@ function buildSourceMatcher(src, listenerOrbital) {
|
|
|
33
33
|
const wantedTrait = src.trait;
|
|
34
34
|
return (source) => !!source && source.orbital === wantedOrbital && source.trait === wantedTrait;
|
|
35
35
|
}
|
|
36
|
+
function applyRowAccess(rows, policy, filter, bindings) {
|
|
37
|
+
if (policy === void 0 && filter === void 0) {
|
|
38
|
+
return rows;
|
|
39
|
+
}
|
|
40
|
+
const predicates = [policy, filter].filter((p) => p !== void 0);
|
|
41
|
+
return rows.filter((entity) => {
|
|
42
|
+
const ctx = createContextFromBindings(
|
|
43
|
+
{ entity, payload: bindings.payload, current: entity, user: bindings.user, config: bindings.config },
|
|
44
|
+
false
|
|
45
|
+
);
|
|
46
|
+
return predicates.every((predicate) => {
|
|
47
|
+
try {
|
|
48
|
+
return Boolean(evaluate(predicate, ctx));
|
|
49
|
+
} catch {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
function checkMutationAccess(row, policy, bindings) {
|
|
56
|
+
if (policy === void 0) {
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
const ctx = createContextFromBindings(
|
|
60
|
+
{ entity: row, payload: bindings.payload, current: row, user: bindings.user, config: bindings.config },
|
|
61
|
+
false
|
|
62
|
+
);
|
|
63
|
+
try {
|
|
64
|
+
return Boolean(evaluate(policy, ctx));
|
|
65
|
+
} catch {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// src/OrbitalServerRuntime.ts
|
|
36
71
|
var _resolvedNodeRequire = null;
|
|
37
72
|
function nodeRequire(modulePath) {
|
|
38
73
|
if (!_resolvedNodeRequire) {
|
|
@@ -1316,8 +1351,15 @@ var OrbitalServerRuntime = class {
|
|
|
1316
1351
|
if (action === "create" || action === "update") {
|
|
1317
1352
|
this.validateRelationCardinality(type, data || {});
|
|
1318
1353
|
}
|
|
1354
|
+
const accessBindings = { user: bindingsRef?.user, payload: bindingsRef?.payload, config: bindingsRef?.config };
|
|
1355
|
+
const mutationPolicy = this.resolvedSchema ? entityAccessPolicies(this.resolvedSchema, type)?.[action === "create" ? "create" : action === "update" ? "update" : "delete"] : void 0;
|
|
1319
1356
|
switch (action) {
|
|
1320
1357
|
case "create": {
|
|
1358
|
+
if (!checkMutationAccess(data || {}, mutationPolicy, accessBindings)) {
|
|
1359
|
+
throw new Error(
|
|
1360
|
+
`@create denied: the declared access policy for '${type}' rejected this row`
|
|
1361
|
+
);
|
|
1362
|
+
}
|
|
1321
1363
|
const { id } = await this.persistence.create(type, data || {});
|
|
1322
1364
|
resultData = { id, ...data || {} };
|
|
1323
1365
|
break;
|
|
@@ -1325,6 +1367,14 @@ var OrbitalServerRuntime = class {
|
|
|
1325
1367
|
case "update":
|
|
1326
1368
|
if (data?.id || entityId) {
|
|
1327
1369
|
const updateId = data?.id || entityId;
|
|
1370
|
+
if (mutationPolicy !== void 0) {
|
|
1371
|
+
const existing = await this.persistence.getById(type, updateId);
|
|
1372
|
+
if (!existing || !checkMutationAccess(existing, mutationPolicy, accessBindings)) {
|
|
1373
|
+
throw new Error(
|
|
1374
|
+
`@update denied: the declared access policy for '${type}' rejected this row`
|
|
1375
|
+
);
|
|
1376
|
+
}
|
|
1377
|
+
}
|
|
1328
1378
|
await this.persistence.update(type, updateId, data || {});
|
|
1329
1379
|
const updated = await this.persistence.getById(type, updateId);
|
|
1330
1380
|
resultData = updated || { id: updateId, ...data || {} };
|
|
@@ -1335,6 +1385,14 @@ var OrbitalServerRuntime = class {
|
|
|
1335
1385
|
const nestedId = typeof data === "object" && data !== null ? data.id : void 0;
|
|
1336
1386
|
const deleteId = directId ?? nestedId ?? entityId;
|
|
1337
1387
|
if (deleteId) {
|
|
1388
|
+
if (mutationPolicy !== void 0) {
|
|
1389
|
+
const existing = await this.persistence.getById(type, deleteId);
|
|
1390
|
+
if (!existing || !checkMutationAccess(existing, mutationPolicy, accessBindings)) {
|
|
1391
|
+
throw new Error(
|
|
1392
|
+
`@delete denied: the declared access policy for '${type}' rejected this row`
|
|
1393
|
+
);
|
|
1394
|
+
}
|
|
1395
|
+
}
|
|
1338
1396
|
await this.enforceOnDeleteRules(type, deleteId);
|
|
1339
1397
|
await this.persistence.delete(type, deleteId);
|
|
1340
1398
|
resultData = { id: deleteId, deleted: true };
|
|
@@ -1423,9 +1481,11 @@ var OrbitalServerRuntime = class {
|
|
|
1423
1481
|
try {
|
|
1424
1482
|
let result = null;
|
|
1425
1483
|
let total = 0;
|
|
1484
|
+
const readPolicy = this.resolvedSchema ? entityAccessPolicies(this.resolvedSchema, fetchEntityType)?.read : void 0;
|
|
1485
|
+
const accessBindings = { user: bindingsRef?.user, payload: bindingsRef?.payload, config: bindingsRef?.config };
|
|
1426
1486
|
if (options?.id) {
|
|
1427
1487
|
const entity = await this.persistence.getById(fetchEntityType, options.id);
|
|
1428
|
-
if (entity) {
|
|
1488
|
+
if (entity && applyRowAccess([entity], readPolicy, void 0, accessBindings).length > 0) {
|
|
1429
1489
|
if (options?.include && options.include.length > 0) {
|
|
1430
1490
|
await this.populateRelations([entity], fetchEntityType, options.include);
|
|
1431
1491
|
}
|
|
@@ -1435,24 +1495,12 @@ var OrbitalServerRuntime = class {
|
|
|
1435
1495
|
}
|
|
1436
1496
|
} else {
|
|
1437
1497
|
let entities = await this.persistence.list(fetchEntityType);
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
);
|
|
1445
|
-
try {
|
|
1446
|
-
return Boolean(evaluate(predicate, ctx));
|
|
1447
|
-
} catch (err) {
|
|
1448
|
-
effectLog.error("fetch:filter-eval-error", {
|
|
1449
|
-
entityType: fetchEntityType,
|
|
1450
|
-
error: err instanceof Error ? err : String(err)
|
|
1451
|
-
});
|
|
1452
|
-
return false;
|
|
1453
|
-
}
|
|
1454
|
-
});
|
|
1455
|
-
}
|
|
1498
|
+
entities = applyRowAccess(
|
|
1499
|
+
entities,
|
|
1500
|
+
readPolicy,
|
|
1501
|
+
options?.filter !== void 0 && options.filter !== null ? options.filter : void 0,
|
|
1502
|
+
accessBindings
|
|
1503
|
+
);
|
|
1456
1504
|
total = entities.length;
|
|
1457
1505
|
if (options?.offset && options.offset > 0) {
|
|
1458
1506
|
entities = entities.slice(options.offset);
|
package/dist/index.js
CHANGED
|
@@ -424,7 +424,7 @@ function createServerEffectHandlers(opts) {
|
|
|
424
424
|
const predicate = options.filter;
|
|
425
425
|
entities = entities.filter((entity) => {
|
|
426
426
|
const ctx = createContextFromBindings(
|
|
427
|
-
{ entity, payload: bindings?.payload, current: entity },
|
|
427
|
+
{ entity, payload: bindings?.payload, current: entity, user: bindings?.user, config: bindings?.config },
|
|
428
428
|
false
|
|
429
429
|
);
|
|
430
430
|
try {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@almadar/runtime",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.47.0",
|
|
4
4
|
"description": "Interpreted runtime for Almadar orbital applications (OrbitalServerRuntime)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -52,11 +52,11 @@
|
|
|
52
52
|
"access": "public"
|
|
53
53
|
},
|
|
54
54
|
"dependencies": {
|
|
55
|
-
"@almadar/core": "^10.
|
|
55
|
+
"@almadar/core": "^10.45.0",
|
|
56
56
|
"@almadar/evaluator": "^2.38.0",
|
|
57
57
|
"@almadar/logger": "^1.10.0",
|
|
58
58
|
"@almadar/server": "^2.30.0",
|
|
59
|
-
"@almadar/std": "^16.
|
|
59
|
+
"@almadar/std": "^16.155.0"
|
|
60
60
|
},
|
|
61
61
|
"peerDependencies": {
|
|
62
62
|
"express": "^5.0.0"
|