@aooth/arbac-moost 0.1.65 → 0.1.67
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-DDwcuUsU.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
|
//#region src/atscript/auto-provider.d.ts
|
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as ArbacDbScope, c as enforceControlsPolicy, d as NavRelationKey, f as NavTarget, i as conjoinArbacDbScopes, l as extractUsedControlValues, m as ProjectionOf, n as ArbacUserProviderToken, o as AsArbacDbController, p as OwnFieldKey, r as AoothArbacClaims, s as applyAllowedFieldsAndSet, t as ArbacUserProvider, u as ControlsOf } from "./user.provider-
|
|
1
|
+
import { a as ArbacDbScope, c as enforceControlsPolicy, d as NavRelationKey, f as NavTarget, i as conjoinArbacDbScopes, l as extractUsedControlValues, m as ProjectionOf, n as ArbacUserProviderToken, o as AsArbacDbController, p as OwnFieldKey, r as AoothArbacClaims, s as applyAllowedFieldsAndSet, t as ArbacUserProvider, u as ControlsOf } from "./user.provider-DDwcuUsU.mjs";
|
|
2
2
|
import { Arbac, Arbac as Arbac$1, TArbacCompiledRule, TArbacEvalResult, TArbacRole, TArbacRoleForResource, TArbacRule, arbacPatternToRegex } from "@aooth/arbac-core";
|
|
3
3
|
import { TAuthGuardDef } from "@moostjs/event-http";
|
|
4
4
|
import { EventContext } from "@wooksjs/event-core";
|
|
@@ -129,11 +129,8 @@ declare class AsArbacDbReadableController<T extends TAtscriptAnnotatedType = TAt
|
|
|
129
129
|
*/
|
|
130
130
|
protected applyMetaOverlay(meta: TMetaResponse): Promise<TMetaResponse>;
|
|
131
131
|
/**
|
|
132
|
-
* Scope-aware field
|
|
133
|
-
* {@link AsArbacDbController.hasField}
|
|
134
|
-
* read-scope projection union answers `false`, so `validateInsights` rejects
|
|
135
|
-
* `$select` / filter / sort references to it with the identical
|
|
136
|
-
* `Unknown field "x"` 400 a nonexistent field gets.
|
|
132
|
+
* Scope-aware field visibility — same contract as
|
|
133
|
+
* {@link AsArbacDbController.hasField}.
|
|
137
134
|
*/
|
|
138
135
|
protected hasField(path: string): boolean;
|
|
139
136
|
}
|
package/dist/index.mjs
CHANGED
|
@@ -5,6 +5,7 @@ import { current, key } from "@wooksjs/event-core";
|
|
|
5
5
|
import { Inherit, Injectable, TInterceptorPriority, defineBeforeInterceptor, getConstructor, getMoostMate, useControllerContext, useLogger } from "moost";
|
|
6
6
|
import { conjoinScopeFilters, intersectControlsPolicy, isFieldAllowed, mergeScopeFilters, restrictProjection, unionControlsPolicy, unionProjections } from "@aooth/arbac";
|
|
7
7
|
import { AsDbController, AsDbReadableController } from "@atscript/moost-db";
|
|
8
|
+
import { groupByFields } from "@uniqu/core";
|
|
8
9
|
//#region src/attenuation.ts
|
|
9
10
|
/**
|
|
10
11
|
* Conjoin the full-authority scopes (`userScopes`, the ceiling) and the
|
|
@@ -716,9 +717,9 @@ let AsArbacDbController = class AsArbacDbController extends AsDbController {
|
|
|
716
717
|
* controls of a request. Runs after the base validator (which checks the
|
|
717
718
|
* controls DTO shape) and BEFORE the query/aggregation pipeline executes.
|
|
718
719
|
*
|
|
719
|
-
*
|
|
720
|
-
*
|
|
721
|
-
*
|
|
720
|
+
* Reads the scopes the route-level authorize interceptor cached via
|
|
721
|
+
* `arbac.setScopes(...)` — validation runs before `transformFilter`, so
|
|
722
|
+
* this hook never re-evaluates ARBAC.
|
|
722
723
|
*
|
|
723
724
|
* On a violation we throw `HttpError(403)`. moost-db's `query` / `pages` /
|
|
724
725
|
* `getOne` handlers do NOT wrap `validateParsed` in try/catch, so the
|
|
@@ -735,18 +736,12 @@ let AsArbacDbController = class AsArbacDbController extends AsDbController {
|
|
|
735
736
|
return applyArbacMetaOverlay(meta, metaAlwaysVisibleFields(this, this.readable));
|
|
736
737
|
}
|
|
737
738
|
/**
|
|
738
|
-
*
|
|
739
|
-
*
|
|
740
|
-
*
|
|
741
|
-
*
|
|
742
|
-
*
|
|
743
|
-
*
|
|
744
|
-
* as an existence/value oracle. Identifier fields stay visible (reads
|
|
745
|
-
* always return them — see {@link MetaVisibility.alwaysVisible}), and paths
|
|
746
|
-
* under a `with`-granted relation pass through to the sub-scope's own
|
|
747
|
-
* enforcement. Scopes were cached by the route-level authorize interceptor
|
|
748
|
-
* before validation runs (`useArbac` setScopes), so the union reflects the
|
|
749
|
-
* exact action being executed.
|
|
739
|
+
* Scope-aware field visibility (BUG-3 twin of the `/meta` pruning above): a
|
|
740
|
+
* field outside the read-scope projection union answers `false`, which
|
|
741
|
+
* moost-db's visibility hook turns into the same `Unknown field "x"` 400 a
|
|
742
|
+
* nonexistent field gets at every gated query position — see the docs'
|
|
743
|
+
* "Column-scope security floor". Identifiers stay visible; paths under a
|
|
744
|
+
* `with`-granted relation pass through to the sub-scope's own enforcement.
|
|
750
745
|
*/
|
|
751
746
|
hasField(path) {
|
|
752
747
|
return super.hasField(path) && isScopedFieldVisible(readCachedScopes(), path, metaAlwaysVisibleFields(this, this.readable));
|
|
@@ -808,7 +803,7 @@ function enforceControlsPolicy(policy, controls) {
|
|
|
808
803
|
if (Array.isArray(used) && used.length === 0) continue;
|
|
809
804
|
if (gate === false) throw new HttpError(403, `Control "${key}" is not allowed for your role`);
|
|
810
805
|
if (Array.isArray(gate)) {
|
|
811
|
-
const usedValues = extractUsedControlValues(key, used);
|
|
806
|
+
const usedValues = extractUsedControlValues(key, used, controls);
|
|
812
807
|
for (const v of usedValues) if (!gate.includes(v)) throw new HttpError(403, `Control "${key}=${v}" is not allowed for your role`);
|
|
813
808
|
}
|
|
814
809
|
}
|
|
@@ -824,13 +819,16 @@ function enforceControlsPolicy(policy, controls) {
|
|
|
824
819
|
* - `$with` — array of `{ name, … }` objects (per `TypedWithRelation`,
|
|
825
820
|
* see `@uniqu/core` parser at `parseWithSegment`); we extract `name`.
|
|
826
821
|
* Bare strings are tolerated for forward compatibility.
|
|
827
|
-
* - `$groupBy` — array of column names (strings).
|
|
822
|
+
* - `$groupBy` — array of column names (strings). With `controls` given,
|
|
823
|
+
* a calendar-bucket alias (`$select: [{ $bucket, $field, $as }]`) is
|
|
824
|
+
* mapped to its source `$field` (`groupByFields` from `@uniqu/core`),
|
|
825
|
+
* so the whitelist is checked against the column actually grouped on.
|
|
828
826
|
*
|
|
829
827
|
* For unknown controls we return an empty array; the caller then enforces
|
|
830
828
|
* `false`-only semantics (controlled by `unionControlsPolicy`'s whitelist
|
|
831
829
|
* gate, which throws if a non-whitelistable control receives a string[]).
|
|
832
830
|
*/
|
|
833
|
-
function extractUsedControlValues(key, value) {
|
|
831
|
+
function extractUsedControlValues(key, value, controls) {
|
|
834
832
|
if (!Array.isArray(value)) return [];
|
|
835
833
|
if (key === "$with") {
|
|
836
834
|
const out = [];
|
|
@@ -838,7 +836,10 @@ function extractUsedControlValues(key, value) {
|
|
|
838
836
|
else if (typeof entry?.name === "string") out.push(entry.name);
|
|
839
837
|
return out;
|
|
840
838
|
}
|
|
841
|
-
if (key === "$groupBy") return
|
|
839
|
+
if (key === "$groupBy") return controls ? groupByFields({
|
|
840
|
+
$select: controls.$select,
|
|
841
|
+
$groupBy: value
|
|
842
|
+
}) : value.filter((x) => typeof x === "string");
|
|
842
843
|
return [];
|
|
843
844
|
}
|
|
844
845
|
/**
|
|
@@ -925,11 +926,8 @@ let AsArbacDbReadableController = class AsArbacDbReadableController extends AsDb
|
|
|
925
926
|
return applyArbacMetaOverlay(meta, metaAlwaysVisibleFields(this, this.readable));
|
|
926
927
|
}
|
|
927
928
|
/**
|
|
928
|
-
* Scope-aware field
|
|
929
|
-
* {@link AsArbacDbController.hasField}
|
|
930
|
-
* read-scope projection union answers `false`, so `validateInsights` rejects
|
|
931
|
-
* `$select` / filter / sort references to it with the identical
|
|
932
|
-
* `Unknown field "x"` 400 a nonexistent field gets.
|
|
929
|
+
* Scope-aware field visibility — same contract as
|
|
930
|
+
* {@link AsArbacDbController.hasField}.
|
|
933
931
|
*/
|
|
934
932
|
hasField(path) {
|
|
935
933
|
return super.hasField(path) && isScopedFieldVisible(readCachedScopes(), path, metaAlwaysVisibleFields(this, this.readable));
|
|
@@ -152,9 +152,9 @@ declare class AsArbacDbController<T extends TAtscriptAnnotatedType = TAtscriptAn
|
|
|
152
152
|
* controls of a request. Runs after the base validator (which checks the
|
|
153
153
|
* controls DTO shape) and BEFORE the query/aggregation pipeline executes.
|
|
154
154
|
*
|
|
155
|
-
*
|
|
156
|
-
*
|
|
157
|
-
*
|
|
155
|
+
* Reads the scopes the route-level authorize interceptor cached via
|
|
156
|
+
* `arbac.setScopes(...)` — validation runs before `transformFilter`, so
|
|
157
|
+
* this hook never re-evaluates ARBAC.
|
|
158
158
|
*
|
|
159
159
|
* On a violation we throw `HttpError(403)`. moost-db's `query` / `pages` /
|
|
160
160
|
* `getOne` handlers do NOT wrap `validateParsed` in try/catch, so the
|
|
@@ -163,18 +163,12 @@ declare class AsArbacDbController<T extends TAtscriptAnnotatedType = TAtscriptAn
|
|
|
163
163
|
protected validateControls(controls: Record<string, unknown>, type: "query" | "pages" | "getOne"): string | undefined;
|
|
164
164
|
protected applyMetaOverlay(meta: TMetaResponse): Promise<TMetaResponse>;
|
|
165
165
|
/**
|
|
166
|
-
*
|
|
167
|
-
*
|
|
168
|
-
*
|
|
169
|
-
*
|
|
170
|
-
*
|
|
171
|
-
*
|
|
172
|
-
* as an existence/value oracle. Identifier fields stay visible (reads
|
|
173
|
-
* always return them — see {@link MetaVisibility.alwaysVisible}), and paths
|
|
174
|
-
* under a `with`-granted relation pass through to the sub-scope's own
|
|
175
|
-
* enforcement. Scopes were cached by the route-level authorize interceptor
|
|
176
|
-
* before validation runs (`useArbac` setScopes), so the union reflects the
|
|
177
|
-
* exact action being executed.
|
|
166
|
+
* Scope-aware field visibility (BUG-3 twin of the `/meta` pruning above): a
|
|
167
|
+
* field outside the read-scope projection union answers `false`, which
|
|
168
|
+
* moost-db's visibility hook turns into the same `Unknown field "x"` 400 a
|
|
169
|
+
* nonexistent field gets at every gated query position — see the docs'
|
|
170
|
+
* "Column-scope security floor". Identifiers stay visible; paths under a
|
|
171
|
+
* `with`-granted relation pass through to the sub-scope's own enforcement.
|
|
178
172
|
*/
|
|
179
173
|
protected hasField(path: string): boolean;
|
|
180
174
|
protected onWrite(action: "insert" | "insertMany" | "replace" | "replaceMany" | "update" | "updateMany", data: unknown): Promise<unknown>;
|
|
@@ -212,13 +206,16 @@ declare function enforceControlsPolicy(policy: Record<string, ControlGate>, cont
|
|
|
212
206
|
* - `$with` — array of `{ name, … }` objects (per `TypedWithRelation`,
|
|
213
207
|
* see `@uniqu/core` parser at `parseWithSegment`); we extract `name`.
|
|
214
208
|
* Bare strings are tolerated for forward compatibility.
|
|
215
|
-
* - `$groupBy` — array of column names (strings).
|
|
209
|
+
* - `$groupBy` — array of column names (strings). With `controls` given,
|
|
210
|
+
* a calendar-bucket alias (`$select: [{ $bucket, $field, $as }]`) is
|
|
211
|
+
* mapped to its source `$field` (`groupByFields` from `@uniqu/core`),
|
|
212
|
+
* so the whitelist is checked against the column actually grouped on.
|
|
216
213
|
*
|
|
217
214
|
* For unknown controls we return an empty array; the caller then enforces
|
|
218
215
|
* `false`-only semantics (controlled by `unionControlsPolicy`'s whitelist
|
|
219
216
|
* gate, which throws if a non-whitelistable control receives a string[]).
|
|
220
217
|
*/
|
|
221
|
-
declare function extractUsedControlValues(key: string, value: unknown): string[];
|
|
218
|
+
declare function extractUsedControlValues(key: string, value: unknown, controls?: Record<string, unknown>): string[];
|
|
222
219
|
/**
|
|
223
220
|
* Test-friendly internal helper — exported for unit tests and helper
|
|
224
221
|
* composition; regular consumers should not call this directly.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aooth/arbac-moost",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.67",
|
|
4
4
|
"description": "Moost RBAC integration for aoothjs (migrated from @moostjs/arbac)",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"abac",
|
|
@@ -60,26 +60,26 @@
|
|
|
60
60
|
"access": "public"
|
|
61
61
|
},
|
|
62
62
|
"dependencies": {
|
|
63
|
-
"@
|
|
64
|
-
"@aooth/arbac
|
|
65
|
-
"@aooth/user": "0.1.
|
|
63
|
+
"@uniqu/core": "^0.1.10",
|
|
64
|
+
"@aooth/arbac": "0.1.67",
|
|
65
|
+
"@aooth/user": "0.1.67",
|
|
66
|
+
"@aooth/arbac-core": "0.1.67"
|
|
66
67
|
},
|
|
67
68
|
"devDependencies": {
|
|
68
69
|
"@atscript/core": "^0.1.93",
|
|
69
|
-
"@atscript/db": "^0.1.
|
|
70
|
-
"@atscript/db-sql-tools": "^0.1.
|
|
71
|
-
"@atscript/db-sqlite": "^0.1.
|
|
72
|
-
"@atscript/moost-db": "^0.1.
|
|
70
|
+
"@atscript/db": "^0.1.133",
|
|
71
|
+
"@atscript/db-sql-tools": "^0.1.133",
|
|
72
|
+
"@atscript/db-sqlite": "^0.1.133",
|
|
73
|
+
"@atscript/moost-db": "^0.1.133",
|
|
73
74
|
"@atscript/typescript": "^0.1.93",
|
|
74
75
|
"@moostjs/event-http": "^0.6.37",
|
|
75
76
|
"@types/better-sqlite3": "^7.6.13",
|
|
76
|
-
"@uniqu/core": "^0.1.8",
|
|
77
77
|
"better-sqlite3": "^12.6.2",
|
|
78
78
|
"unplugin-atscript": "^0.1.93"
|
|
79
79
|
},
|
|
80
80
|
"peerDependencies": {
|
|
81
|
-
"@atscript/db": "^0.1.
|
|
82
|
-
"@atscript/moost-db": "^0.1.
|
|
81
|
+
"@atscript/db": "^0.1.133",
|
|
82
|
+
"@atscript/moost-db": "^0.1.133",
|
|
83
83
|
"@atscript/typescript": "^0.1.93",
|
|
84
84
|
"@moostjs/event-http": "^0.6.37",
|
|
85
85
|
"@wooksjs/event-core": "^0.7.23",
|