@aooth/arbac-moost 0.2.2 → 0.2.4
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.
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { r as AoothArbacClaims, t as ArbacUserProvider } from "../user.provider-
|
|
1
|
+
import { r as AoothArbacClaims, t as ArbacUserProvider } from "../user.provider-D0cJ_iMd.mjs";
|
|
2
2
|
import { TAtscriptAnnotatedType, TAtscriptTypeObject, TMetadataMap, TValidatorOptions, Validator } from "@atscript/typescript/utils";
|
|
3
3
|
import { AoothUserCredentials } from "@aooth/user/atscript-db/model.as";
|
|
4
4
|
/**
|
package/dist/atscript/index.mjs
CHANGED
|
@@ -475,7 +475,7 @@ var AoothArbacUserCredentials = class {
|
|
|
475
475
|
throwFeatureDisabled("JSON Schema", "jsonSchema", "emit.jsonSchema");
|
|
476
476
|
}
|
|
477
477
|
};
|
|
478
|
-
$ak("db.index.fulltext", "db.index.plain", "db.index.unique", "db.view.joins", "expect.pattern");
|
|
479
|
-
$nr("aooth.auth.metadata", "aooth.user.email", "aooth.user.phone", "arbac.attenuate.attr", "arbac.attenuate.role", "arbac.attribute", "arbac.role", "arbac.userId", "db.agg.avg", "db.agg.count", "db.agg.countDistinct", "db.agg.max", "db.agg.min", "db.agg.sum", "db.alias", "db.amount.currency.ref", "db.column", "db.column.collate", "db.column.derived", "db.column.dimension", "db.column.filterable", "db.column.measure", "db.column.precision", "db.column.renamed", "db.column.searchable", "db.column.sortable", "db.column.version", "db.column.version.exempt", "db.compute", "db.default", "db.default.increment", "db.default.now", "db.default.uuid", "db.depth.limit", "db.encrypted", "db.http.path", "db.ignore", "db.index.fulltext", "db.index.geo", "db.index.plain", "db.index.unique", "db.json", "db.onUpdate.inc", "db.onUpdate.now", "db.patch.strategy", "db.rel.FK", "db.rel.filter", "db.rel.filterable", "db.rel.from", "db.rel.onDelete", "db.rel.onUpdate", "db.rel.to", "db.rel.via", "db.schema", "db.search.filter", "db.search.vector", "db.search.vector.threshold", "db.sort.nulls", "db.space", "db.sync.method", "db.table", "db.table.filterable", "db.table.preferredId.uniqueIndex", "db.table.renamed", "db.table.sortable", "db.unit.ref", "db.view", "db.view.filter", "db.view.for", "db.view.having", "db.view.joins", "db.view.materialized", "db.view.renamed", "db.writeOnly", "meta.default", "meta.id", "meta.readonly", "meta.required");
|
|
478
|
+
$ak("db.index.fulltext", "db.index.fulltext.language", "db.index.fulltext.match", "db.index.plain", "db.index.unique", "db.view.joins", "expect.pattern");
|
|
479
|
+
$nr("aooth.auth.metadata", "aooth.user.email", "aooth.user.phone", "arbac.attenuate.attr", "arbac.attenuate.role", "arbac.attribute", "arbac.role", "arbac.userId", "db.agg.avg", "db.agg.count", "db.agg.countDistinct", "db.agg.max", "db.agg.min", "db.agg.sum", "db.alias", "db.amount.currency.ref", "db.column", "db.column.collate", "db.column.derived", "db.column.dimension", "db.column.filterable", "db.column.measure", "db.column.precision", "db.column.renamed", "db.column.searchable", "db.column.sortable", "db.column.version", "db.column.version.exempt", "db.compute", "db.default", "db.default.increment", "db.default.now", "db.default.uuid", "db.depth.limit", "db.encrypted", "db.http.path", "db.ignore", "db.index.fulltext", "db.index.fulltext.language", "db.index.fulltext.match", "db.index.geo", "db.index.plain", "db.index.unique", "db.json", "db.onUpdate.inc", "db.onUpdate.now", "db.patch.strategy", "db.rel.FK", "db.rel.filter", "db.rel.filterable", "db.rel.from", "db.rel.onDelete", "db.rel.onUpdate", "db.rel.to", "db.rel.via", "db.schema", "db.search.filter", "db.search.vector", "db.search.vector.threshold", "db.sort.nulls", "db.space", "db.sync.method", "db.table", "db.table.filterable", "db.table.preferredId.uniqueIndex", "db.table.renamed", "db.table.sortable", "db.unit.ref", "db.view", "db.view.filter", "db.view.for", "db.view.having", "db.view.joins", "db.view.materialized", "db.view.renamed", "db.writeOnly", "meta.default", "meta.id", "meta.readonly", "meta.required");
|
|
480
480
|
defineAnnotatedType("object", AoothArbacUserCredentials).prop("id", $f(AoothUserCredentials, "id")).prop("username", $f(AoothUserCredentials, "username")).prop("version", $f(AoothUserCredentials, "version")).prop("password", $f(AoothUserCredentials, "password")).prop("account", $f(AoothUserCredentials, "account")).prop("mfa", $f(AoothUserCredentials, "mfa")).prop("trustedDevices", $f(AoothUserCredentials, "trustedDevices")).prop("seenDevices", $f(AoothUserCredentials, "seenDevices")).prop("roles", defineAnnotatedType("array").of(defineAnnotatedType().designType("string").tags("string").$type).annotate("arbac.role", true).$type);
|
|
481
481
|
export { AoothArbacUserCredentials, ArbacUserRecordCache, AtscriptArbacUserProvider, extractAttenuation, getAoothUserHandleSpec, getArbacAttenuationSpec, validateAttenuationTargets };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { _ as ProjectionOf, a as conjoinArbacDbScopes, b as TArbacMeta, c as ArbacDbScope, d as extractUsedControlValues, f as applyAllowedFieldsAndSet, g as OwnFieldKey, h as NavTarget, i as ConjoinArbacDbScopesOptions, l as AsArbacDbController, m as NavRelationKey, n as ArbacUserProviderToken, o as RefForeignKey, p as ControlsOf, r as AoothArbacClaims, s as RefTableSource, t as ArbacUserProvider, u as enforceControlsPolicy, v as ARBAC_DELEGATED_AUTH, x as getArbacMate, y as ArbacDelegatedAuth } from "./user.provider-
|
|
1
|
+
import { _ as ProjectionOf, a as conjoinArbacDbScopes, b as TArbacMeta, c as ArbacDbScope, d as extractUsedControlValues, f as applyAllowedFieldsAndSet, g as OwnFieldKey, h as NavTarget, i as ConjoinArbacDbScopesOptions, l as AsArbacDbController, m as NavRelationKey, n as ArbacUserProviderToken, o as RefForeignKey, p as ControlsOf, r as AoothArbacClaims, s as RefTableSource, t as ArbacUserProvider, u as enforceControlsPolicy, v as ARBAC_DELEGATED_AUTH, x as getArbacMate, y as ArbacDelegatedAuth } from "./user.provider-D0cJ_iMd.mjs";
|
|
2
2
|
import { Arbac, Arbac as Arbac$1, TArbacCompiledRule, TArbacEvalResult, TArbacEvalResult as TArbacEvalResult$1, TArbacRole, TArbacRoleForResource, TArbacRule, arbacPatternToRegex } from "@aooth/arbac-core";
|
|
3
3
|
import { ControlGate, ControlGate as ControlGate$1, TProjection, TScopeFieldRules, TScopeFilter, conjoinScopeFilters } from "@aooth/arbac";
|
|
4
|
-
import { TAuthGuardDef } from "@moostjs/event-http";
|
|
4
|
+
import { HttpError, TAuthGuardDef } from "@moostjs/event-http";
|
|
5
5
|
import { EventContext } from "@wooksjs/event-core";
|
|
6
6
|
import { FilterExpr, TDbRemoveGuardContext, TDbWriteCheckContext, TDbWriteGuardContext, TDeleteOptions, TMetaResponse, TRowResolveOptions, TWriteOptions, UniqueryControls } from "@atscript/db";
|
|
7
7
|
import { AsDbReadableController, AsJsonValueHelpController, AsValueHelpController, TDbActionScopeContext, TDbControlsType, TDbIndexFieldPaths, TDbRequestContext, ValueHelpSelect } from "@atscript/moost-db";
|
|
@@ -224,6 +224,37 @@ export interface ArbacEvaluateOptions {
|
|
|
224
224
|
*/
|
|
225
225
|
table?: VisibilityTableSource;
|
|
226
226
|
}
|
|
227
|
+
/** The current user as ARBAC sees it — what `useArbac().principal()` returns. */
|
|
228
|
+
export interface ArbacPrincipal<TUserAttrs extends object = object> {
|
|
229
|
+
/** The user id the `ArbacUserProvider` resolved for this event. */
|
|
230
|
+
userId: string;
|
|
231
|
+
/**
|
|
232
|
+
* The roles the user HOLDS (`ArbacUserProvider.getRoles`), before
|
|
233
|
+
* credential attenuation. Don't authorize on it — an attenuated credential
|
|
234
|
+
* may act with fewer roles; use {@link effectiveRoles} or `evaluate()`.
|
|
235
|
+
*/
|
|
236
|
+
roles: string[];
|
|
237
|
+
/**
|
|
238
|
+
* The roles this request acts with: {@link roles} narrowed by the
|
|
239
|
+
* credential's attenuation (`roles ∩ attenuation.roles`; all held roles when
|
|
240
|
+
* the attenuation names none). A claimed role the user does not hold is
|
|
241
|
+
* never included, even with `allowUnheldRoles` — that "view as" mode only
|
|
242
|
+
* ever narrows through `evaluate()`. Use this for role checks in app code.
|
|
243
|
+
*/
|
|
244
|
+
effectiveRoles: string[];
|
|
245
|
+
/** The user's attributes (`ArbacUserProvider.getAttrs`), loaded on the first call. */
|
|
246
|
+
attrs: () => Promise<TUserAttrs>;
|
|
247
|
+
/**
|
|
248
|
+
* The credential's restrict-only attenuation
|
|
249
|
+
* (`ArbacUserProvider.getAttenuation`), when it narrows the user's
|
|
250
|
+
* authority; absent otherwise.
|
|
251
|
+
*/
|
|
252
|
+
attenuation?: {
|
|
253
|
+
roles?: string[];
|
|
254
|
+
attrs?: Record<string, unknown>;
|
|
255
|
+
allowUnheldRoles?: boolean;
|
|
256
|
+
};
|
|
257
|
+
}
|
|
227
258
|
interface ArbacBindings {
|
|
228
259
|
getScopes: <TScope extends object>() => TScope[] | undefined;
|
|
229
260
|
setScopes: <TScope extends object>(scope: TScope[] | undefined) => void;
|
|
@@ -246,6 +277,14 @@ interface ArbacBindings {
|
|
|
246
277
|
scopes?: TScope[];
|
|
247
278
|
userId: string;
|
|
248
279
|
}>;
|
|
280
|
+
/**
|
|
281
|
+
* The current principal — user id, held and effective roles, lazy
|
|
282
|
+
* attributes and credential attenuation — read through the
|
|
283
|
+
* `ArbacUserProvider`, the same source `evaluate()` uses. Loaded fresh on
|
|
284
|
+
* every call (like `evaluate()`), so a role change applies immediately.
|
|
285
|
+
* Decide on `effectiveRoles` (or `evaluate()`), never on `roles`.
|
|
286
|
+
*/
|
|
287
|
+
principal: <TUserAttrs extends object = object>() => Promise<ArbacPrincipal<TUserAttrs>>;
|
|
249
288
|
resource: string;
|
|
250
289
|
action: string;
|
|
251
290
|
isPublic: boolean;
|
|
@@ -576,9 +615,41 @@ export declare function isScopedFieldVisible(scopes: ArbacDbScope[], path: strin
|
|
|
576
615
|
* caller's readable rows match the query; the action itself is authorized
|
|
577
616
|
* by its source controller on every batch.
|
|
578
617
|
*
|
|
618
|
+
* A read endpoint (`query`, `pages`, `geo`, `one`) under a moost-db write
|
|
619
|
+
* handler (`insert`, `update`, `replace`, `remove`, `removeComposite`) is
|
|
620
|
+
* served only inside {@link readBackUnderReadGrant} (since 0.2.4), under the
|
|
621
|
+
* read grant it installs — otherwise a 403, never the write grant. moost-db's
|
|
622
|
+
* insert read-back (`Prefer: return=representation`) then answers the plain
|
|
623
|
+
* insert result.
|
|
624
|
+
*
|
|
579
625
|
* @since 0.1.72
|
|
580
626
|
*/
|
|
581
627
|
export declare function prepareArbacRequest(ctx: TDbRequestContext, readable?: VisibilityTableSource): Promise<void>;
|
|
628
|
+
/**
|
|
629
|
+
* Read back the row `id` after a write, exactly as `GET /one/:id` would
|
|
630
|
+
* answer the caller (since 0.2.4) — the body of
|
|
631
|
+
* `AsArbacDbController._readRepresentation`, and the way for a write handler
|
|
632
|
+
* override to answer the written row:
|
|
633
|
+
*
|
|
634
|
+
* ```ts
|
|
635
|
+
* await super.update(payload);
|
|
636
|
+
* return readBackUnderReadGrant(id, () => this.getOne(String(id), ""));
|
|
637
|
+
* ```
|
|
638
|
+
*
|
|
639
|
+
* `read` calls the controller's `/one` handler: `getOne` for a scalar `id`,
|
|
640
|
+
* `getOneComposite` for a key object. The caller's grant on that handler is
|
|
641
|
+
* evaluated (its `@ArbacResource` / `@ArbacAction`, credential attenuation
|
|
642
|
+
* included) and installed as the request's scopes while `read` runs — its
|
|
643
|
+
* row filter, projection and controls apply, and an overridden handler body
|
|
644
|
+
* runs too — then the write's scopes are restored.
|
|
645
|
+
*
|
|
646
|
+
* Answers `undefined` instead of the row when: the caller has no grant on
|
|
647
|
+
* that handler; the handler carries method-level interceptors (they would
|
|
648
|
+
* not run on a direct call); `read` answers or throws an `HttpError` (e.g.
|
|
649
|
+
* the row is outside the read filter → 404); or anything else fails (logged
|
|
650
|
+
* as a warning, never answered — the write is already committed).
|
|
651
|
+
*/
|
|
652
|
+
export declare function readBackUnderReadGrant<R>(id: unknown, read: () => Promise<R>): Promise<Exclude<R, HttpError> | undefined>;
|
|
582
653
|
/**
|
|
583
654
|
* `authorizeForm` for the ARBAC DB controllers: a form is served iff the
|
|
584
655
|
* caller may run at least one of the actions that take it as input — each
|
package/dist/index.mjs
CHANGED
|
@@ -21,6 +21,15 @@ function getOrCreate(map, key, create) {
|
|
|
21
21
|
function hasSelfOrAncestor(set, path) {
|
|
22
22
|
return set.has(path) || findAncestorInSet(path, set) !== void 0;
|
|
23
23
|
}
|
|
24
|
+
/**
|
|
25
|
+
* A key object (a composite id, read by `getOneComposite`) — a plain object.
|
|
26
|
+
* A class instance such as a MongoDB `ObjectId` is a scalar id: `String(id)`.
|
|
27
|
+
*/
|
|
28
|
+
function isKeyObject(id) {
|
|
29
|
+
if (id === null || typeof id !== "object") return false;
|
|
30
|
+
const proto = Object.getPrototypeOf(id);
|
|
31
|
+
return proto === Object.prototype || proto === null;
|
|
32
|
+
}
|
|
24
33
|
/** A patch (`update` / `updateMany`) — only the keys it carries are written. */
|
|
25
34
|
function isPatchAction(action) {
|
|
26
35
|
return action === "update" || action === "updateMany";
|
|
@@ -871,6 +880,11 @@ async function loadPrincipal(user) {
|
|
|
871
880
|
};
|
|
872
881
|
}
|
|
873
882
|
const arbacDeps = cachedBy((_controller, ctx) => Promise.all([useControllerContext(ctx).instantiate(ArbacUserProviderToken), useControllerContext(ctx).instantiate(MoostArbac)]));
|
|
883
|
+
/** Load the current principal through the controller's user provider (fresh, no memo). */
|
|
884
|
+
async function loadCurrentPrincipal(ctx) {
|
|
885
|
+
const [user] = await arbacDeps(useControllerContext(ctx).getController(), ctx);
|
|
886
|
+
return loadPrincipal(user);
|
|
887
|
+
}
|
|
874
888
|
const principalKey = key("arbac.principal");
|
|
875
889
|
function isHttpEvent(ctx) {
|
|
876
890
|
return ctx.has(eventTypeKey) && ctx.get(eventTypeKey) === "http";
|
|
@@ -1044,11 +1058,23 @@ const useArbac = (_ctx) => {
|
|
|
1044
1058
|
allowed: true
|
|
1045
1059
|
};
|
|
1046
1060
|
};
|
|
1061
|
+
const principal = async () => {
|
|
1062
|
+
const p = await loadCurrentPrincipal(ctx);
|
|
1063
|
+
const claimed = p.attenuate?.roles;
|
|
1064
|
+
return {
|
|
1065
|
+
userId: p.userId,
|
|
1066
|
+
roles: p.roles,
|
|
1067
|
+
effectiveRoles: claimed ? p.roles.filter((r) => claimed.includes(r)) : p.roles,
|
|
1068
|
+
attrs: () => p.attrs(p.userId),
|
|
1069
|
+
...p.attenuate && { attenuation: p.attenuate }
|
|
1070
|
+
};
|
|
1071
|
+
};
|
|
1047
1072
|
return {
|
|
1048
1073
|
getScopes,
|
|
1049
1074
|
setScopes,
|
|
1050
1075
|
evaluate,
|
|
1051
1076
|
evaluateOrThrow,
|
|
1077
|
+
principal,
|
|
1052
1078
|
resource,
|
|
1053
1079
|
action,
|
|
1054
1080
|
isPublic
|
|
@@ -2586,10 +2612,11 @@ function cachedRequestScopes() {
|
|
|
2586
2612
|
*/
|
|
2587
2613
|
async function resolveRequestScopes() {
|
|
2588
2614
|
const ctx = current();
|
|
2615
|
+
const prior = resolved();
|
|
2616
|
+
if (prior?.readBack) return prior.scopes;
|
|
2589
2617
|
const arbac = useArbac(ctx);
|
|
2590
2618
|
const cachedScopes = arbac.getScopes();
|
|
2591
2619
|
const fromInterceptor = cachedScopes && scopesOwnedBy(cachedScopes, arbac.resource, arbac.action) ? cachedScopes : void 0;
|
|
2592
|
-
const prior = resolved();
|
|
2593
2620
|
if (prior && prior.resource === arbac.resource && prior.action === arbac.action && prior.source === fromInterceptor) return prior.scopes;
|
|
2594
2621
|
const scopes = normalizeScopes(fromInterceptor !== void 0 ? {
|
|
2595
2622
|
allowed: true,
|
|
@@ -2667,6 +2694,13 @@ function isScopedFieldVisible(scopes, path, source) {
|
|
|
2667
2694
|
* caller's readable rows match the query; the action itself is authorized
|
|
2668
2695
|
* by its source controller on every batch.
|
|
2669
2696
|
*
|
|
2697
|
+
* A read endpoint (`query`, `pages`, `geo`, `one`) under a moost-db write
|
|
2698
|
+
* handler (`insert`, `update`, `replace`, `remove`, `removeComposite`) is
|
|
2699
|
+
* served only inside {@link readBackUnderReadGrant} (since 0.2.4), under the
|
|
2700
|
+
* read grant it installs — otherwise a 403, never the write grant. moost-db's
|
|
2701
|
+
* insert read-back (`Prefer: return=representation`) then answers the plain
|
|
2702
|
+
* insert result.
|
|
2703
|
+
*
|
|
2670
2704
|
* @since 0.1.72
|
|
2671
2705
|
*/
|
|
2672
2706
|
async function prepareArbacRequest(ctx, readable) {
|
|
@@ -2678,10 +2712,67 @@ async function prepareArbacRequest(ctx, readable) {
|
|
|
2678
2712
|
await authorizeDelegatedQueryTarget();
|
|
2679
2713
|
return;
|
|
2680
2714
|
}
|
|
2715
|
+
if (READ_ENDPOINTS.has(ctx.endpoint) && !resolved()?.readBack && underWriteHandler()) {
|
|
2716
|
+
const { resource, action } = useArbac();
|
|
2717
|
+
throw insufficientPrivileges(resource, action);
|
|
2718
|
+
}
|
|
2681
2719
|
const scopes = await resolveRequestScopes();
|
|
2682
2720
|
if (ctx.endpoint === "insert" && ctx.onConflict === "ignore") resolved().insertIgnore = true;
|
|
2683
2721
|
if (READ_ENDPOINTS.has(ctx.endpoint)) enforceRelationGates(await resolveRequestRelations(scopes, ctx.controls, readable, ctx.filter), visibilityFor(scopes, readable));
|
|
2684
2722
|
}
|
|
2723
|
+
/** moost-db's write handler methods — a read under one of them must be a read-back. */
|
|
2724
|
+
const WRITE_HANDLERS = new Set([...WRITE_CRUD_OPS].flatMap((op) => DB_CRUD_HANDLERS[op]));
|
|
2725
|
+
function underWriteHandler() {
|
|
2726
|
+
const method = useControllerContext().getMethod();
|
|
2727
|
+
return method !== void 0 && WRITE_HANDLERS.has(method);
|
|
2728
|
+
}
|
|
2729
|
+
/**
|
|
2730
|
+
* Read back the row `id` after a write, exactly as `GET /one/:id` would
|
|
2731
|
+
* answer the caller (since 0.2.4) — the body of
|
|
2732
|
+
* `AsArbacDbController._readRepresentation`, and the way for a write handler
|
|
2733
|
+
* override to answer the written row:
|
|
2734
|
+
*
|
|
2735
|
+
* ```ts
|
|
2736
|
+
* await super.update(payload);
|
|
2737
|
+
* return readBackUnderReadGrant(id, () => this.getOne(String(id), ""));
|
|
2738
|
+
* ```
|
|
2739
|
+
*
|
|
2740
|
+
* `read` calls the controller's `/one` handler: `getOne` for a scalar `id`,
|
|
2741
|
+
* `getOneComposite` for a key object. The caller's grant on that handler is
|
|
2742
|
+
* evaluated (its `@ArbacResource` / `@ArbacAction`, credential attenuation
|
|
2743
|
+
* included) and installed as the request's scopes while `read` runs — its
|
|
2744
|
+
* row filter, projection and controls apply, and an overridden handler body
|
|
2745
|
+
* runs too — then the write's scopes are restored.
|
|
2746
|
+
*
|
|
2747
|
+
* Answers `undefined` instead of the row when: the caller has no grant on
|
|
2748
|
+
* that handler; the handler carries method-level interceptors (they would
|
|
2749
|
+
* not run on a direct call); `read` answers or throws an `HttpError` (e.g.
|
|
2750
|
+
* the row is outside the read filter → 404); or anything else fails (logged
|
|
2751
|
+
* as a warning, never answered — the write is already committed).
|
|
2752
|
+
*/
|
|
2753
|
+
async function readBackUnderReadGrant(id, read) {
|
|
2754
|
+
const ctx = current();
|
|
2755
|
+
const prior = resolved();
|
|
2756
|
+
if (!prior) return void 0;
|
|
2757
|
+
try {
|
|
2758
|
+
const instance = useControllerContext(ctx).getController();
|
|
2759
|
+
const method = isKeyObject(id) ? "getOneComposite" : "getOne";
|
|
2760
|
+
if (getMoostMate().read(instance, method)?.interceptors?.length) return void 0;
|
|
2761
|
+
const ids = resolveHandlerArbacIds(instance, method);
|
|
2762
|
+
const [outcome] = await evaluateHandlerOutcomes([ids]);
|
|
2763
|
+
const scopes = normalizeScopes(outcome);
|
|
2764
|
+
if (!scopes) return void 0;
|
|
2765
|
+
storeResolved(ctx, ids, void 0, scopes);
|
|
2766
|
+
ctx.get(requestScopesKey).readBack = true;
|
|
2767
|
+
const row = await read();
|
|
2768
|
+
return row instanceof HttpError ? void 0 : row;
|
|
2769
|
+
} catch (error) {
|
|
2770
|
+
if (!(error instanceof HttpError)) useLogger("arbac", ctx).warn(`Read-back of the written row failed: ${String(error)}`);
|
|
2771
|
+
return;
|
|
2772
|
+
} finally {
|
|
2773
|
+
ctx.set(requestScopesKey, prior);
|
|
2774
|
+
}
|
|
2775
|
+
}
|
|
2685
2776
|
/**
|
|
2686
2777
|
* `authorizeForm` for the ARBAC DB controllers: a form is served iff the
|
|
2687
2778
|
* caller may run at least one of the actions that take it as input — each
|
|
@@ -3188,6 +3279,15 @@ let AsArbacDbController = class AsArbacDbController extends AsDbController {
|
|
|
3188
3279
|
return prepareArbacRequest(ctx, this.readable);
|
|
3189
3280
|
}
|
|
3190
3281
|
/**
|
|
3282
|
+
* The read-back of `Prefer: return=representation` on `POST /` (since
|
|
3283
|
+
* 0.2.4; opt in with `returnRepresentation()`): this controller's own
|
|
3284
|
+
* `/one` handler under the caller's grant on it — see
|
|
3285
|
+
* {@link readBackUnderReadGrant}.
|
|
3286
|
+
*/
|
|
3287
|
+
_readRepresentation(id) {
|
|
3288
|
+
return readBackUnderReadGrant(id, () => isKeyObject(id) ? this.getOneComposite(textKey(id), "") : this.getOne(String(id), ""));
|
|
3289
|
+
}
|
|
3290
|
+
/**
|
|
3191
3291
|
* The request filter ∧ the union of the scopes' `filter`s. Computed
|
|
3192
3292
|
* synchronously, but typed with moost-db's async-capable contract
|
|
3193
3293
|
* (`FilterExpr | Promise<FilterExpr>`) so a subclass may override it
|
|
@@ -3375,6 +3475,10 @@ let AsArbacDbController = class AsArbacDbController extends AsDbController {
|
|
|
3375
3475
|
}
|
|
3376
3476
|
};
|
|
3377
3477
|
AsArbacDbController = __decorate([Inherit()], AsArbacDbController);
|
|
3478
|
+
/** A key object as `GET /one?…` receives it — every value as text. */
|
|
3479
|
+
function textKey(id) {
|
|
3480
|
+
return Object.fromEntries(Object.entries(id).map(([k, v]) => [k, String(v)]));
|
|
3481
|
+
}
|
|
3378
3482
|
const preservedFieldsCache = /* @__PURE__ */ new WeakMap();
|
|
3379
3483
|
/**
|
|
3380
3484
|
* Test-friendly internal helper — exported for unit tests and helper
|
|
@@ -3796,4 +3900,4 @@ async function useArbacDbScope() {
|
|
|
3796
3900
|
})
|
|
3797
3901
|
};
|
|
3798
3902
|
}
|
|
3799
|
-
export { ARBAC_DELEGATED_AUTH, Arbac, ArbacAction, ArbacAuthorize, ArbacResource, ArbacUserProvider, ArbacUserProviderToken, AsArbacDbController, AsArbacDbReadableController, AsArbacJsonValueHelpController, AsArbacValueHelpController, MoostArbac, applyAllowedFieldsAndSet, applyArbacControls, applyArbacMetaOverlay, applyArbacProjection, applyArbacRelationScopes, arbacActionRowScope, arbacAllowedActions, arbacAuthorizeInterceptor, arbacPatternToRegex, arbacRelationFilter, arbacRowFilter, authorizeArbacForm, buildScopeVisibility, cachedRequestScopes, checkArbacWrite, collectMethodNames, collectWithGrantNames, collectWritableFields, conjoinArbacDbScopes, conjoinScopeFilters, enforceControlsPolicy, extractUsedControlValues, getArbacMate, getArbacScopes, guardArbacRemove, guardArbacWrite, isMetaFieldVisible, isScopedFieldVisible, metaAlwaysVisibleFields, prepareArbacRequest, pruneMetaByVisibility, registerArbacDbTarget, requestFieldVisible, requireRequestScopes, resolveHandlerArbacIds, resolveRequestScopes, unionScopeProjection, useArbac, useArbacDbScope };
|
|
3903
|
+
export { ARBAC_DELEGATED_AUTH, Arbac, ArbacAction, ArbacAuthorize, ArbacResource, ArbacUserProvider, ArbacUserProviderToken, AsArbacDbController, AsArbacDbReadableController, AsArbacJsonValueHelpController, AsArbacValueHelpController, MoostArbac, applyAllowedFieldsAndSet, applyArbacControls, applyArbacMetaOverlay, applyArbacProjection, applyArbacRelationScopes, arbacActionRowScope, arbacAllowedActions, arbacAuthorizeInterceptor, arbacPatternToRegex, arbacRelationFilter, arbacRowFilter, authorizeArbacForm, buildScopeVisibility, cachedRequestScopes, checkArbacWrite, collectMethodNames, collectWithGrantNames, collectWritableFields, conjoinArbacDbScopes, conjoinScopeFilters, enforceControlsPolicy, extractUsedControlValues, getArbacMate, getArbacScopes, guardArbacRemove, guardArbacWrite, isMetaFieldVisible, isScopedFieldVisible, metaAlwaysVisibleFields, prepareArbacRequest, pruneMetaByVisibility, readBackUnderReadGrant, registerArbacDbTarget, requestFieldVisible, requireRequestScopes, resolveHandlerArbacIds, resolveRequestScopes, unionScopeProjection, useArbac, useArbacDbScope };
|
|
@@ -268,6 +268,13 @@ declare class AsArbacDbController<T extends TAtscriptAnnotatedType = TAtscriptAn
|
|
|
268
268
|
* is resolved for the requested relations.
|
|
269
269
|
*/
|
|
270
270
|
protected prepareRequest(ctx: TDbRequestContext): Promise<void>;
|
|
271
|
+
/**
|
|
272
|
+
* The read-back of `Prefer: return=representation` on `POST /` (since
|
|
273
|
+
* 0.2.4; opt in with `returnRepresentation()`): this controller's own
|
|
274
|
+
* `/one` handler under the caller's grant on it — see
|
|
275
|
+
* {@link readBackUnderReadGrant}.
|
|
276
|
+
*/
|
|
277
|
+
protected _readRepresentation(id: unknown): Promise<TAtscriptDataType<T> | undefined>;
|
|
271
278
|
/**
|
|
272
279
|
* The request filter ∧ the union of the scopes' `filter`s. Computed
|
|
273
280
|
* synchronously, but typed with moost-db's async-capable contract
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aooth/arbac-moost",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.4",
|
|
4
4
|
"description": "Moost RBAC integration for aoothjs (migrated from @moostjs/arbac)",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"abac",
|
|
@@ -60,30 +60,30 @@
|
|
|
60
60
|
"access": "public"
|
|
61
61
|
},
|
|
62
62
|
"dependencies": {
|
|
63
|
-
"@uniqu/core": "^0.
|
|
64
|
-
"@aooth/arbac": "0.2.
|
|
65
|
-
"@aooth/user": "0.2.
|
|
66
|
-
"@aooth/arbac-core": "0.2.
|
|
63
|
+
"@uniqu/core": "^0.2.0",
|
|
64
|
+
"@aooth/arbac": "0.2.4",
|
|
65
|
+
"@aooth/user": "0.2.4",
|
|
66
|
+
"@aooth/arbac-core": "0.2.4"
|
|
67
67
|
},
|
|
68
68
|
"devDependencies": {
|
|
69
|
-
"@atscript/core": "^0.2.
|
|
70
|
-
"@atscript/db": "^0.1.
|
|
71
|
-
"@atscript/db-sql-tools": "^0.1.
|
|
72
|
-
"@atscript/db-sqlite": "^0.1.
|
|
73
|
-
"@atscript/moost-db": "^0.1.
|
|
74
|
-
"@atscript/typescript": "^0.2.
|
|
75
|
-
"@moostjs/event-http": "^0.7.
|
|
69
|
+
"@atscript/core": "^0.2.4",
|
|
70
|
+
"@atscript/db": "^0.1.169",
|
|
71
|
+
"@atscript/db-sql-tools": "^0.1.169",
|
|
72
|
+
"@atscript/db-sqlite": "^0.1.169",
|
|
73
|
+
"@atscript/moost-db": "^0.1.169",
|
|
74
|
+
"@atscript/typescript": "^0.2.4",
|
|
75
|
+
"@moostjs/event-http": "^0.7.2",
|
|
76
76
|
"@types/better-sqlite3": "^7.6.13",
|
|
77
77
|
"better-sqlite3": "^12.6.2",
|
|
78
|
-
"unplugin-atscript": "^0.2.
|
|
78
|
+
"unplugin-atscript": "^0.2.4"
|
|
79
79
|
},
|
|
80
80
|
"peerDependencies": {
|
|
81
|
-
"@atscript/db": "^0.1.
|
|
82
|
-
"@atscript/moost-db": "^0.1.
|
|
83
|
-
"@atscript/typescript": "^0.2.
|
|
84
|
-
"@moostjs/event-http": "^0.7.
|
|
81
|
+
"@atscript/db": "^0.1.169",
|
|
82
|
+
"@atscript/moost-db": "^0.1.169",
|
|
83
|
+
"@atscript/typescript": "^0.2.4",
|
|
84
|
+
"@moostjs/event-http": "^0.7.2",
|
|
85
85
|
"@wooksjs/event-core": "^0.8.0",
|
|
86
|
-
"moost": "^0.7.
|
|
86
|
+
"moost": "^0.7.2"
|
|
87
87
|
},
|
|
88
88
|
"peerDependenciesMeta": {
|
|
89
89
|
"@atscript/db": {
|