@generazioneai/authz 0.0.3 → 0.0.5
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/enforce/index.d.ts +4 -0
- package/dist/enforce/index.d.ts.map +1 -0
- package/dist/enforce/index.js +21 -0
- package/dist/enforce/index.js.map +1 -0
- package/dist/enforce/prisma-extension.d.ts +25 -0
- package/dist/enforce/prisma-extension.d.ts.map +1 -0
- package/dist/enforce/prisma-extension.js +79 -0
- package/dist/enforce/prisma-extension.js.map +1 -0
- package/dist/enforce/run-unscoped.d.ts +2 -0
- package/dist/enforce/run-unscoped.d.ts.map +1 -0
- package/dist/enforce/run-unscoped.js +14 -0
- package/dist/enforce/run-unscoped.js.map +1 -0
- package/dist/enforce/scoped-repository.d.ts +10 -0
- package/dist/enforce/scoped-repository.d.ts.map +1 -0
- package/dist/enforce/scoped-repository.js +26 -0
- package/dist/enforce/scoped-repository.js.map +1 -0
- package/dist/nest/authorize.decorator.d.ts +3 -0
- package/dist/nest/authorize.decorator.d.ts.map +1 -0
- package/dist/nest/authorize.decorator.js +15 -0
- package/dist/nest/authorize.decorator.js.map +1 -0
- package/dist/nest/authz-context.interceptor.d.ts.map +1 -1
- package/dist/nest/authz-context.interceptor.js +4 -1
- package/dist/nest/authz-context.interceptor.js.map +1 -1
- package/dist/nest/global-authz.guard.d.ts +34 -0
- package/dist/nest/global-authz.guard.d.ts.map +1 -0
- package/dist/nest/global-authz.guard.js +82 -0
- package/dist/nest/global-authz.guard.js.map +1 -0
- package/dist/nest/index.d.ts +3 -0
- package/dist/nest/index.d.ts.map +1 -1
- package/dist/nest/index.js +3 -0
- package/dist/nest/index.js.map +1 -1
- package/dist/nest/internal-auth.interceptor.d.ts +20 -0
- package/dist/nest/internal-auth.interceptor.d.ts.map +1 -1
- package/dist/nest/internal-auth.interceptor.js +38 -2
- package/dist/nest/internal-auth.interceptor.js.map +1 -1
- package/dist/nest/public.decorator.d.ts +3 -0
- package/dist/nest/public.decorator.d.ts.map +1 -0
- package/dist/nest/public.decorator.js +10 -0
- package/dist/nest/public.decorator.js.map +1 -0
- package/dist/snapshot/ability-builder.d.ts +23 -0
- package/dist/snapshot/ability-builder.d.ts.map +1 -0
- package/dist/snapshot/ability-builder.js +40 -0
- package/dist/snapshot/ability-builder.js.map +1 -0
- package/dist/snapshot/distributed-lock.d.ts +19 -0
- package/dist/snapshot/distributed-lock.d.ts.map +1 -0
- package/dist/snapshot/distributed-lock.js +37 -0
- package/dist/snapshot/distributed-lock.js.map +1 -0
- package/dist/snapshot/index.d.ts +7 -0
- package/dist/snapshot/index.d.ts.map +1 -0
- package/dist/snapshot/index.js +26 -0
- package/dist/snapshot/index.js.map +1 -0
- package/dist/snapshot/l1-cache.d.ts +16 -0
- package/dist/snapshot/l1-cache.d.ts.map +1 -0
- package/dist/snapshot/l1-cache.js +43 -0
- package/dist/snapshot/l1-cache.js.map +1 -0
- package/dist/snapshot/perm-hash.d.ts +3 -0
- package/dist/snapshot/perm-hash.d.ts.map +1 -0
- package/dist/snapshot/perm-hash.js +33 -0
- package/dist/snapshot/perm-hash.js.map +1 -0
- package/dist/snapshot/snapshot.envelope.d.ts +36 -0
- package/dist/snapshot/snapshot.envelope.d.ts.map +1 -0
- package/dist/snapshot/snapshot.envelope.js +23 -0
- package/dist/snapshot/snapshot.envelope.js.map +1 -0
- package/dist/snapshot/snapshot.store.d.ts +24 -0
- package/dist/snapshot/snapshot.store.d.ts.map +1 -0
- package/dist/snapshot/snapshot.store.js +78 -0
- package/dist/snapshot/snapshot.store.js.map +1 -0
- package/package.json +19 -4
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/enforce/index.ts"],"names":[],"mappings":"AACA,cAAc,oBAAoB,CAAC;AACnC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,qBAAqB,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
// @generazioneai/authz/enforce — Step 3 query-level enforcement (no NestJS runtime dep).
|
|
18
|
+
__exportStar(require("./prisma-extension"), exports);
|
|
19
|
+
__exportStar(require("./run-unscoped"), exports);
|
|
20
|
+
__exportStar(require("./scoped-repository"), exports);
|
|
21
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/enforce/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,yFAAyF;AACzF,qDAAmC;AACnC,iDAA+B;AAC/B,sDAAoC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { ResourceRegistry } from '../resource-registry';
|
|
2
|
+
export type EnforceMode = 'off' | 'shadow' | 'enforce';
|
|
3
|
+
export interface AuthzExtensionOptions {
|
|
4
|
+
mode?: EnforceMode;
|
|
5
|
+
/** called in shadow mode with what WOULD be restricted (metrics/logging). */
|
|
6
|
+
onShadow?: (info: {
|
|
7
|
+
model: string;
|
|
8
|
+
operation: string;
|
|
9
|
+
subject: string;
|
|
10
|
+
}) => void;
|
|
11
|
+
}
|
|
12
|
+
export declare function createAuthzPrismaExtension(registry: ResourceRegistry, opts?: AuthzExtensionOptions): {
|
|
13
|
+
name: string;
|
|
14
|
+
query: {
|
|
15
|
+
$allModels: {
|
|
16
|
+
$allOperations({ model, operation, args, query }: {
|
|
17
|
+
model: string;
|
|
18
|
+
operation: string;
|
|
19
|
+
args: any;
|
|
20
|
+
query: (a: any) => Promise<unknown>;
|
|
21
|
+
}): Promise<unknown>;
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
//# sourceMappingURL=prisma-extension.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prisma-extension.d.ts","sourceRoot":"","sources":["../../src/enforce/prisma-extension.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAE7D,MAAM,MAAM,WAAW,GAAG,KAAK,GAAG,QAAQ,GAAG,SAAS,CAAC;AAiBvD,MAAM,WAAW,qBAAqB;IACpC,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,6EAA6E;IAC7E,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;CAClF;AAED,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,gBAAgB,EAAE,IAAI,GAAE,qBAA0B;;;;8DAOvC;gBAAE,KAAK,EAAE,MAAM,CAAC;gBAAC,SAAS,EAAE,MAAM,CAAC;gBAAC,IAAI,EAAE,GAAG,CAAC;gBAAC,KAAK,EAAE,CAAC,CAAC,EAAE,GAAG,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;aAAE;;;EAyCnJ"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createAuthzPrismaExtension = createAuthzPrismaExtension;
|
|
4
|
+
// Step 3 — Prisma Client extension that enforces the request's CASL ability on EVERY
|
|
5
|
+
// query (the safety net: impossible to bypass from inside the service). Reads the ability
|
|
6
|
+
// from ALS, looks up the model's Subject in the registry, and ANDs accessibleBy(ability,
|
|
7
|
+
// action)[Subject] into the where (reads/updates/deletes) or stamps tenancy on creates.
|
|
8
|
+
//
|
|
9
|
+
// Mode (AUTHZ_ENFORCE_MODE, default 'off'):
|
|
10
|
+
// off → passthrough (no behaviour change — safe to ship).
|
|
11
|
+
// shadow → compute but DON'T apply; log would-restrict (readiness measurement).
|
|
12
|
+
// enforce → apply (fail-closed: no ALS context / no ability → throw).
|
|
13
|
+
const prisma_1 = require("@casl/prisma");
|
|
14
|
+
const als_1 = require("../context/als");
|
|
15
|
+
const READ = new Set(['findUnique', 'findUniqueOrThrow', 'findFirst', 'findFirstOrThrow', 'findMany', 'count', 'aggregate', 'groupBy']);
|
|
16
|
+
const UPDATE = new Set(['update', 'updateMany', 'upsert']);
|
|
17
|
+
const DELETE = new Set(['delete', 'deleteMany']);
|
|
18
|
+
const CREATE = new Set(['create', 'createMany', 'createManyAndReturn']);
|
|
19
|
+
function opToAction(op) {
|
|
20
|
+
if (READ.has(op))
|
|
21
|
+
return 'read';
|
|
22
|
+
if (CREATE.has(op))
|
|
23
|
+
return 'create';
|
|
24
|
+
if (UPDATE.has(op))
|
|
25
|
+
return 'update';
|
|
26
|
+
if (DELETE.has(op))
|
|
27
|
+
return 'delete';
|
|
28
|
+
return 'manage';
|
|
29
|
+
}
|
|
30
|
+
const lowerFirst = (s) => (s ? s.charAt(0).toLowerCase() + s.slice(1) : s);
|
|
31
|
+
function createAuthzPrismaExtension(registry, opts = {}) {
|
|
32
|
+
const mode = opts.mode ?? process.env.AUTHZ_ENFORCE_MODE ?? 'off';
|
|
33
|
+
return {
|
|
34
|
+
name: 'skillera-authz-enforce',
|
|
35
|
+
query: {
|
|
36
|
+
$allModels: {
|
|
37
|
+
async $allOperations({ model, operation, args, query }) {
|
|
38
|
+
if (mode === 'off')
|
|
39
|
+
return query(args);
|
|
40
|
+
const ctx = als_1.authzAls.getStore();
|
|
41
|
+
if (!ctx) {
|
|
42
|
+
if (mode === 'enforce')
|
|
43
|
+
throw new Error(`[authz] UNSCOPED_QUERY ${model}.${operation} — no request context`);
|
|
44
|
+
return query(args);
|
|
45
|
+
}
|
|
46
|
+
if (ctx.unscoped)
|
|
47
|
+
return query(args); // runUnscoped escape hatch (system tasks)
|
|
48
|
+
if (!ctx.ability) {
|
|
49
|
+
if (mode === 'enforce')
|
|
50
|
+
throw new Error(`[authz] no ability in context for ${model}.${operation}`);
|
|
51
|
+
return query(args);
|
|
52
|
+
}
|
|
53
|
+
const manifest = registry.get(model) ?? registry.byPrismaModel(lowerFirst(model));
|
|
54
|
+
if (!manifest)
|
|
55
|
+
return query(args); // unmanaged model → not scoped
|
|
56
|
+
const subject = manifest.subject;
|
|
57
|
+
const action = opToAction(operation);
|
|
58
|
+
if (mode === 'shadow') {
|
|
59
|
+
opts.onShadow?.({ model, operation, subject });
|
|
60
|
+
return query(args);
|
|
61
|
+
}
|
|
62
|
+
// enforce
|
|
63
|
+
if (CREATE.has(operation)) {
|
|
64
|
+
const t = manifest.tenancy;
|
|
65
|
+
if (t && t.kind === 'single' && ctx.tenantId && args?.data) {
|
|
66
|
+
const stamp = (d) => ({ [t.field]: ctx.tenantId, ...d });
|
|
67
|
+
args = { ...args, data: Array.isArray(args.data) ? args.data.map(stamp) : stamp(args.data) };
|
|
68
|
+
}
|
|
69
|
+
return query(args);
|
|
70
|
+
}
|
|
71
|
+
const scopeWhere = (0, prisma_1.accessibleBy)(ctx.ability, action)[subject];
|
|
72
|
+
args = { ...args, where: args?.where ? { AND: [args.where, scopeWhere] } : scopeWhere };
|
|
73
|
+
return query(args);
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=prisma-extension.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prisma-extension.js","sourceRoot":"","sources":["../../src/enforce/prisma-extension.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-unscoped.d.ts","sourceRoot":"","sources":["../../src/enforce/run-unscoped.ts"],"names":[],"mappings":"AAMA,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAI7D"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.runUnscoped = runUnscoped;
|
|
4
|
+
// Step 3 DEC-S3.17 — escape hatch for legitimate system work that must bypass scoping
|
|
5
|
+
// (seeds, cross-tenant admin jobs, the snapshot builder itself). Sets ctx.unscoped so the
|
|
6
|
+
// Prisma extension lets queries through. Requires an explicit reason (lint-enforced, Step 8).
|
|
7
|
+
const als_1 = require("../context/als");
|
|
8
|
+
const authz_context_1 = require("../context/authz-context");
|
|
9
|
+
function runUnscoped(reason, fn) {
|
|
10
|
+
const current = als_1.authzAls.getStore();
|
|
11
|
+
const ctx = { ...(current ?? authz_context_1.EMPTY_CTX), unscoped: true, unscopedReason: reason };
|
|
12
|
+
return als_1.authzAls.run(ctx, fn);
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=run-unscoped.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-unscoped.js","sourceRoot":"","sources":["../../src/enforce/run-unscoped.ts"],"names":[],"mappings":";;AAMA,kCAIC;AAVD,sFAAsF;AACtF,0FAA0F;AAC1F,8FAA8F;AAC9F,wCAA0C;AAC1C,4DAAwE;AAExE,SAAgB,WAAW,CAAI,MAAc,EAAE,EAAW;IACxD,MAAM,OAAO,GAAG,cAAQ,CAAC,QAAQ,EAAE,CAAC;IACpC,MAAM,GAAG,GAAiB,EAAE,GAAG,CAAC,OAAO,IAAI,yBAAS,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,cAAc,EAAE,MAAM,EAAE,CAAC;IAChG,OAAO,cAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;AAC/B,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { AuthzContext } from '../context/authz-context';
|
|
2
|
+
export declare class ScopedRepository<TDelegate> {
|
|
3
|
+
private readonly delegate;
|
|
4
|
+
constructor(delegate: TDelegate);
|
|
5
|
+
/** Current request context (throws if missing — enforcement is never accidental). */
|
|
6
|
+
protected ctx(): AuthzContext;
|
|
7
|
+
/** The underlying (extension-scoped) Prisma delegate. */
|
|
8
|
+
get scoped(): TDelegate;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=scoped-repository.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scoped-repository.d.ts","sourceRoot":"","sources":["../../src/enforce/scoped-repository.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAE7D,qBAAa,gBAAgB,CAAC,SAAS;IACzB,OAAO,CAAC,QAAQ,CAAC,QAAQ;gBAAR,QAAQ,EAAE,SAAS;IAEhD,qFAAqF;IACrF,SAAS,CAAC,GAAG,IAAI,YAAY;IAM7B,yDAAyD;IACzD,IAAI,MAAM,IAAI,SAAS,CAGtB;CACF"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ScopedRepository = void 0;
|
|
4
|
+
// Step 3 DX wrapper — services inject a ScopedRepository instead of the raw Prisma
|
|
5
|
+
// delegate. The Prisma extension already enforces scope on every query; this surface
|
|
6
|
+
// makes the intent explicit and asserts a request context is present.
|
|
7
|
+
const als_1 = require("../context/als");
|
|
8
|
+
class ScopedRepository {
|
|
9
|
+
constructor(delegate) {
|
|
10
|
+
this.delegate = delegate;
|
|
11
|
+
}
|
|
12
|
+
/** Current request context (throws if missing — enforcement is never accidental). */
|
|
13
|
+
ctx() {
|
|
14
|
+
const c = als_1.authzAls.getStore();
|
|
15
|
+
if (!c)
|
|
16
|
+
throw new Error('[authz] ScopedRepository used outside a request context');
|
|
17
|
+
return c;
|
|
18
|
+
}
|
|
19
|
+
/** The underlying (extension-scoped) Prisma delegate. */
|
|
20
|
+
get scoped() {
|
|
21
|
+
this.ctx();
|
|
22
|
+
return this.delegate;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
exports.ScopedRepository = ScopedRepository;
|
|
26
|
+
//# sourceMappingURL=scoped-repository.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scoped-repository.js","sourceRoot":"","sources":["../../src/enforce/scoped-repository.ts"],"names":[],"mappings":";;;AAAA,mFAAmF;AACnF,qFAAqF;AACrF,sEAAsE;AACtE,wCAA0C;AAG1C,MAAa,gBAAgB;IAC3B,YAA6B,QAAmB;QAAnB,aAAQ,GAAR,QAAQ,CAAW;IAAG,CAAC;IAEpD,qFAAqF;IAC3E,GAAG;QACX,MAAM,CAAC,GAAG,cAAQ,CAAC,QAAQ,EAAE,CAAC;QAC9B,IAAI,CAAC,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,yDAAyD,CAAC,CAAC;QACnF,OAAO,CAAC,CAAC;IACX,CAAC;IAED,yDAAyD;IACzD,IAAI,MAAM;QACR,IAAI,CAAC,GAAG,EAAE,CAAC;QACX,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;CACF;AAfD,4CAeC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authorize.decorator.d.ts","sourceRoot":"","sources":["../../src/nest/authorize.decorator.ts"],"names":[],"mappings":"AAMA,OAAO,EAAe,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAGnE,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,eAAe,CAE1E"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Authorize = Authorize;
|
|
4
|
+
// Step 6 — declare the permission a route requires. Read by GlobalAuthzGuard.
|
|
5
|
+
//
|
|
6
|
+
// @Authorize('read', 'JuridicalIndividual')
|
|
7
|
+
// @Get() findAll() { ... }
|
|
8
|
+
//
|
|
9
|
+
// Mode-gated by the guard (AUTHZ_ENFORCE_MODE): in 'off' this metadata is inert.
|
|
10
|
+
const common_1 = require("@nestjs/common");
|
|
11
|
+
const global_authz_guard_1 = require("./global-authz.guard");
|
|
12
|
+
function Authorize(action, subject) {
|
|
13
|
+
return (0, common_1.SetMetadata)(global_authz_guard_1.AUTHZ_REQUIREMENT_KEY, { action, subject });
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=authorize.decorator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authorize.decorator.js","sourceRoot":"","sources":["../../src/nest/authorize.decorator.ts"],"names":[],"mappings":";;AASA,8BAEC;AAXD,8EAA8E;AAC9E,EAAE;AACF,8CAA8C;AAC9C,6BAA6B;AAC7B,EAAE;AACF,iFAAiF;AACjF,2CAAmE;AACnE,6DAAoF;AAEpF,SAAgB,SAAS,CAAC,MAAc,EAAE,OAAe;IACvD,OAAO,IAAA,oBAAW,EAAC,0CAAqB,EAAE,EAAE,MAAM,EAAE,OAAO,EAA6B,CAAC,CAAC;AAC5F,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"authz-context.interceptor.d.ts","sourceRoot":"","sources":["../../src/nest/authz-context.interceptor.ts"],"names":[],"mappings":"AAMA,OAAO,EAEL,KAAK,WAAW,EAChB,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACrB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,UAAU,
|
|
1
|
+
{"version":3,"file":"authz-context.interceptor.d.ts","sourceRoot":"","sources":["../../src/nest/authz-context.interceptor.ts"],"names":[],"mappings":"AAMA,OAAO,EAEL,KAAK,WAAW,EAChB,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACrB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,UAAU,EAAuB,MAAM,MAAM,CAAC;AAKvD,qBACa,uBAAwB,YAAW,eAAe;IAC7D,SAAS,CAAC,OAAO,EAAE,gBAAgB,EAAE,IAAI,EAAE,WAAW,GAAG,UAAU,CAAC,OAAO,CAAC;CA0B7E"}
|
|
@@ -37,7 +37,10 @@ let AuthzContextInterceptor = class AuthzContextInterceptor {
|
|
|
37
37
|
},
|
|
38
38
|
ability: null,
|
|
39
39
|
};
|
|
40
|
-
|
|
40
|
+
// Run the whole handler inside ALS so downstream signed .send() calls — even those
|
|
41
|
+
// after an await — see the context. The callback returns a promise (lastValueFrom)
|
|
42
|
+
// so the store stays bound across awaits; a sync subscribe loses it at the first await.
|
|
43
|
+
return (0, rxjs_1.from)(als_1.authzAls.run(ctx, () => (0, rxjs_1.lastValueFrom)(next.handle())));
|
|
41
44
|
}
|
|
42
45
|
};
|
|
43
46
|
exports.AuthzContextInterceptor = AuthzContextInterceptor;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"authz-context.interceptor.js","sourceRoot":"","sources":["../../src/nest/authz-context.interceptor.ts"],"names":[],"mappings":";;;;;;;;;AAAA,6DAA6D;AAC7D,EAAE;AACF,0FAA0F;AAC1F,yFAAyF;AACzF,6FAA6F;AAC7F,4FAA4F;AAC5F,2CAKwB;AACxB,+
|
|
1
|
+
{"version":3,"file":"authz-context.interceptor.js","sourceRoot":"","sources":["../../src/nest/authz-context.interceptor.ts"],"names":[],"mappings":";;;;;;;;;AAAA,6DAA6D;AAC7D,EAAE;AACF,0FAA0F;AAC1F,yFAAyF;AACzF,6FAA6F;AAC7F,4FAA4F;AAC5F,2CAKwB;AACxB,+BAAuD;AACvD,wCAA0C;AAKnC,IAAM,uBAAuB,GAA7B,MAAM,uBAAuB;IAClC,SAAS,CAAC,OAAyB,EAAE,IAAiB;QACpD,IAAI,OAAO,CAAC,OAAO,EAAE,KAAK,MAAM;YAAE,OAAO,IAAI,CAAC,MAAM,EAAE,CAAC;QAEvD,MAAM,GAAG,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,UAAU,EAAsB,CAAC;QACpE,IAAI,CAAC,GAAG,EAAE,MAAM;YAAE,OAAO,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,4CAA4C;QAEpF,MAAM,GAAG,GAAiB;YACxB,MAAM,EAAE,GAAG,CAAC,MAAM;YAClB,YAAY,EAAE,GAAG,CAAC,YAAY;YAC9B,qBAAqB,EAAE,GAAG,CAAC,qBAAqB;YAChD,QAAQ,EAAE,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,iBAAiB;YAC/C,MAAM,EAAE,GAAG,CAAC,MAAM;YAClB,QAAQ,EAAE,GAAG,CAAC,QAAQ;YACtB,SAAS,EAAE,EAAE,iBAAiB,EAAE,EAAE,EAAE,gBAAgB,EAAE,EAAE,EAAE,0BAA0B,EAAE,EAAE,EAAE;YAC1F,YAAY,EAAE;gBACZ,QAAQ,EAAE,EAAE,gBAAgB,EAAE,EAAE,EAAE,oBAAoB,EAAE,EAAE,EAAE;gBAC5D,QAAQ,EAAE,EAAE,gBAAgB,EAAE,EAAE,EAAE,oBAAoB,EAAE,EAAE,EAAE;aAC7D;YACD,OAAO,EAAE,IAA0C;SACpD,CAAC;QAEF,mFAAmF;QACnF,mFAAmF;QACnF,wFAAwF;QACxF,OAAO,IAAA,WAAI,EAAC,cAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC,IAAA,oBAAa,EAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC;IACrE,CAAC;CACF,CAAA;AA3BY,0DAAuB;kCAAvB,uBAAuB;IADnC,IAAA,mBAAU,GAAE;GACA,uBAAuB,CA2BnC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { type CanActivate, type ExecutionContext } from '@nestjs/common';
|
|
2
|
+
import type { Reflector } from '@nestjs/core';
|
|
3
|
+
import type { AuthzContext } from '../context/authz-context';
|
|
4
|
+
export type EnforceMode = 'off' | 'shadow' | 'enforce';
|
|
5
|
+
export declare const AUTHZ_REQUIREMENT_KEY = "skillera:authz:requirement";
|
|
6
|
+
export declare const PUBLIC_KEY = "skillera:authz:public";
|
|
7
|
+
export interface AuthzRequirement {
|
|
8
|
+
action: string;
|
|
9
|
+
subject: string;
|
|
10
|
+
}
|
|
11
|
+
/** Resolves the ability + context for an HTTP request (gateway-specific impl supplies it). */
|
|
12
|
+
export interface AbilityResolver {
|
|
13
|
+
resolve(req: unknown): Promise<AuthzContext | null>;
|
|
14
|
+
}
|
|
15
|
+
export interface GlobalAuthzGuardOptions {
|
|
16
|
+
mode?: EnforceMode;
|
|
17
|
+
/**
|
|
18
|
+
* Fallback requirement source, consulted when a route has no @Authorize.
|
|
19
|
+
* Lets a host reuse pre-existing route metadata (e.g. the gateway's legacy
|
|
20
|
+
* @CheckPolicies) instead of re-decorating every endpoint. Returns null when
|
|
21
|
+
* the route genuinely has no requirement (→ default-deny still applies).
|
|
22
|
+
*/
|
|
23
|
+
requirementResolver?: (context: ExecutionContext, reflector: Reflector) => AuthzRequirement | null;
|
|
24
|
+
}
|
|
25
|
+
export declare class GlobalAuthzGuard implements CanActivate {
|
|
26
|
+
private readonly reflector;
|
|
27
|
+
private readonly resolver;
|
|
28
|
+
private readonly logger;
|
|
29
|
+
private readonly mode;
|
|
30
|
+
private readonly requirementResolver?;
|
|
31
|
+
constructor(reflector: Reflector, resolver: AbilityResolver, opts?: GlobalAuthzGuardOptions | EnforceMode);
|
|
32
|
+
canActivate(context: ExecutionContext): Promise<boolean>;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=global-authz.guard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"global-authz.guard.d.ts","sourceRoot":"","sources":["../../src/nest/global-authz.guard.ts"],"names":[],"mappings":"AAYA,OAAO,EAIL,KAAK,WAAW,EAChB,KAAK,gBAAgB,EACtB,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE9C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAE7D,MAAM,MAAM,WAAW,GAAG,KAAK,GAAG,QAAQ,GAAG,SAAS,CAAC;AACvD,eAAO,MAAM,qBAAqB,+BAA+B,CAAC;AAClE,eAAO,MAAM,UAAU,0BAA0B,CAAC;AAElD,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,8FAA8F;AAC9F,MAAM,WAAW,eAAe;IAC9B,OAAO,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAAC;CACrD;AAED,MAAM,WAAW,uBAAuB;IACtC,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB;;;;;OAKG;IACH,mBAAmB,CAAC,EAAE,CAAC,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,SAAS,KAAK,gBAAgB,GAAG,IAAI,CAAC;CACpG;AAED,qBACa,gBAAiB,YAAW,WAAW;IAMhD,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAN3B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA6B;IACpD,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAc;IACnC,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAC,CAAiD;gBAGnE,SAAS,EAAE,SAAS,EACpB,QAAQ,EAAE,eAAe,EAC1C,IAAI,GAAE,uBAAuB,GAAG,WAAgB;IAQ5C,WAAW,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAC;CAwC/D"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.GlobalAuthzGuard = exports.PUBLIC_KEY = exports.AUTHZ_REQUIREMENT_KEY = void 0;
|
|
13
|
+
// Step 6 — gateway route-level enforcement (default-deny).
|
|
14
|
+
//
|
|
15
|
+
// Resolves the request's CASL ability (via a pluggable AbilityResolver — at the gateway,
|
|
16
|
+
// that fetches the user's permission snapshot from Redis/skillID), then checks the route's
|
|
17
|
+
// @Authorize(action, subject) requirement. Runs the rest of the request inside authzAls.run
|
|
18
|
+
// so the signing client / downstream propagation see the context.
|
|
19
|
+
//
|
|
20
|
+
// Mode (AUTHZ_ENFORCE_MODE, default 'off'):
|
|
21
|
+
// off → allow (no resolution, zero behaviour change).
|
|
22
|
+
// shadow → resolve + log would-deny, but ALLOW.
|
|
23
|
+
// enforce → default-deny: a route with no @Authorize and no @Public → 403; otherwise
|
|
24
|
+
// allow iff ability.can(action, subject).
|
|
25
|
+
const common_1 = require("@nestjs/common");
|
|
26
|
+
const als_1 = require("../context/als");
|
|
27
|
+
exports.AUTHZ_REQUIREMENT_KEY = 'skillera:authz:requirement';
|
|
28
|
+
exports.PUBLIC_KEY = 'skillera:authz:public';
|
|
29
|
+
let GlobalAuthzGuard = class GlobalAuthzGuard {
|
|
30
|
+
constructor(reflector, resolver, opts = {}) {
|
|
31
|
+
this.reflector = reflector;
|
|
32
|
+
this.resolver = resolver;
|
|
33
|
+
this.logger = new common_1.Logger('GlobalAuthz');
|
|
34
|
+
// Back-compat: a bare mode string is still accepted.
|
|
35
|
+
const o = typeof opts === 'string' ? { mode: opts } : opts;
|
|
36
|
+
this.mode = o.mode ?? process.env.AUTHZ_ENFORCE_MODE ?? 'off';
|
|
37
|
+
this.requirementResolver = o.requirementResolver;
|
|
38
|
+
}
|
|
39
|
+
async canActivate(context) {
|
|
40
|
+
if (this.mode === 'off' || context.getType() !== 'http')
|
|
41
|
+
return true;
|
|
42
|
+
const isPublic = this.reflector.getAllAndOverride(exports.PUBLIC_KEY, [context.getHandler(), context.getClass()]);
|
|
43
|
+
if (isPublic)
|
|
44
|
+
return true;
|
|
45
|
+
const requirement = this.reflector.getAllAndOverride(exports.AUTHZ_REQUIREMENT_KEY, [
|
|
46
|
+
context.getHandler(),
|
|
47
|
+
context.getClass(),
|
|
48
|
+
]) ?? this.requirementResolver?.(context, this.reflector) ?? undefined;
|
|
49
|
+
const req = context.switchToHttp().getRequest();
|
|
50
|
+
const ctx = await this.resolver.resolve(req);
|
|
51
|
+
// Make the ability/context available downstream (signing client, etc.) for this request.
|
|
52
|
+
if (ctx) {
|
|
53
|
+
const als = als_1.authzAls.getStore();
|
|
54
|
+
if (als)
|
|
55
|
+
Object.assign(als, ctx);
|
|
56
|
+
else
|
|
57
|
+
req._authzCtx = ctx;
|
|
58
|
+
}
|
|
59
|
+
// Default-deny: a protected route MUST declare @Authorize (or @Public).
|
|
60
|
+
if (!requirement) {
|
|
61
|
+
if (this.mode === 'shadow') {
|
|
62
|
+
this.logger.warn(`shadow would-deny: ${req?.method} ${req?.url} has no @Authorize`);
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
throw new common_1.ForbiddenException('authz: endpoint has no permission requirement (@Authorize) declared');
|
|
66
|
+
}
|
|
67
|
+
const allowed = !!ctx?.ability?.can(requirement.action, requirement.subject);
|
|
68
|
+
if (allowed)
|
|
69
|
+
return true;
|
|
70
|
+
if (this.mode === 'shadow') {
|
|
71
|
+
this.logger.warn(`shadow would-deny ${requirement.action}:${requirement.subject} for user=${ctx?.userId ?? '?'} (${req?.method} ${req?.url})`);
|
|
72
|
+
return true;
|
|
73
|
+
}
|
|
74
|
+
throw new common_1.ForbiddenException(`authz: missing permission ${requirement.action}:${requirement.subject}`);
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
exports.GlobalAuthzGuard = GlobalAuthzGuard;
|
|
78
|
+
exports.GlobalAuthzGuard = GlobalAuthzGuard = __decorate([
|
|
79
|
+
(0, common_1.Injectable)(),
|
|
80
|
+
__metadata("design:paramtypes", [Function, Object, Object])
|
|
81
|
+
], GlobalAuthzGuard);
|
|
82
|
+
//# sourceMappingURL=global-authz.guard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"global-authz.guard.js","sourceRoot":"","sources":["../../src/nest/global-authz.guard.ts"],"names":[],"mappings":"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"}
|
package/dist/nest/index.d.ts
CHANGED
|
@@ -3,4 +3,7 @@ export * from './nats-scoped-client.proxy';
|
|
|
3
3
|
export * from './internal-auth.interceptor';
|
|
4
4
|
export * from './authz-context.middleware';
|
|
5
5
|
export * from './authz-context.interceptor';
|
|
6
|
+
export * from './global-authz.guard';
|
|
7
|
+
export * from './public.decorator';
|
|
8
|
+
export * from './authorize.decorator';
|
|
6
9
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/nest/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/nest/index.ts"],"names":[],"mappings":"AAGA,cAAc,gCAAgC,CAAC;AAC/C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,6BAA6B,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/nest/index.ts"],"names":[],"mappings":"AAGA,cAAc,gCAAgC,CAAC;AAC/C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC"}
|
package/dist/nest/index.js
CHANGED
|
@@ -22,4 +22,7 @@ __exportStar(require("./nats-scoped-client.proxy"), exports);
|
|
|
22
22
|
__exportStar(require("./internal-auth.interceptor"), exports);
|
|
23
23
|
__exportStar(require("./authz-context.middleware"), exports);
|
|
24
24
|
__exportStar(require("./authz-context.interceptor"), exports);
|
|
25
|
+
__exportStar(require("./global-authz.guard"), exports);
|
|
26
|
+
__exportStar(require("./public.decorator"), exports);
|
|
27
|
+
__exportStar(require("./authorize.decorator"), exports);
|
|
25
28
|
//# sourceMappingURL=index.js.map
|
package/dist/nest/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/nest/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,yFAAyF;AACzF,mFAAmF;AACnF,iCAAiC;AACjC,iEAA+C;AAC/C,6DAA2C;AAC3C,8DAA4C;AAC5C,6DAA2C;AAC3C,8DAA4C"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/nest/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,yFAAyF;AACzF,mFAAmF;AACnF,iCAAiC;AACjC,iEAA+C;AAC/C,6DAA2C;AAC3C,8DAA4C;AAC5C,6DAA2C;AAC3C,8DAA4C;AAC5C,uDAAqC;AACrC,qDAAmC;AACnC,wDAAsC"}
|
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
import { type CallHandler, type ExecutionContext, type NestInterceptor } from '@nestjs/common';
|
|
2
2
|
import type { Reflector } from '@nestjs/core';
|
|
3
3
|
import { Observable } from 'rxjs';
|
|
4
|
+
import type { AuthzContext } from '../context/authz-context';
|
|
4
5
|
import { type VerificationKey } from '../nats/internal-token';
|
|
5
6
|
import type { ReplayCache } from '../nats/replay-cache';
|
|
7
|
+
import type { AbilityRule, SnapshotEnvelope } from '../snapshot/snapshot.envelope';
|
|
6
8
|
export type InternalAuthMode = 'off' | 'shadow' | 'enforce';
|
|
9
|
+
/** Step 4 — fetch a snapshot envelope by the JWT `snap` claim. */
|
|
10
|
+
export interface SnapshotFetcher {
|
|
11
|
+
getBySnapId(snapId: string): Promise<SnapshotEnvelope | null>;
|
|
12
|
+
}
|
|
7
13
|
export interface InternalAuthOptions {
|
|
8
14
|
jwks: VerificationKey;
|
|
9
15
|
replay: ReplayCache;
|
|
@@ -14,6 +20,14 @@ export interface InternalAuthOptions {
|
|
|
14
20
|
mode?: InternalAuthMode;
|
|
15
21
|
/** Compare the token cmd against the NATS subject. Default true. */
|
|
16
22
|
strictCmd?: boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Step 4 runtime hydration. When both are provided and the token carries a `snap`
|
|
25
|
+
* claim, the verified context's ability is rehydrated from the Redis snapshot so the
|
|
26
|
+
* Prisma extension can scope queries. `hydrate` is injected (createPrismaAbility) so
|
|
27
|
+
* this module stays free of a static @casl/prisma dependency.
|
|
28
|
+
*/
|
|
29
|
+
snapshotStore?: SnapshotFetcher;
|
|
30
|
+
hydrate?: (rules: AbilityRule[]) => AuthzContext['ability'];
|
|
17
31
|
}
|
|
18
32
|
export declare class InternalAuthInterceptor implements NestInterceptor {
|
|
19
33
|
private readonly opts;
|
|
@@ -23,6 +37,12 @@ export declare class InternalAuthInterceptor implements NestInterceptor {
|
|
|
23
37
|
intercept(context: ExecutionContext, next: CallHandler): Observable<unknown>;
|
|
24
38
|
/** Returns the ALS context on success; in shadow mode returns null on failure (pass). */
|
|
25
39
|
private verify;
|
|
40
|
+
/**
|
|
41
|
+
* Step 4 — rehydrate the ability from the Redis snapshot named by the `snap` claim.
|
|
42
|
+
* Missing/evicted snapshot in enforce → throw (fail-closed: the gateway must rebuild);
|
|
43
|
+
* in shadow → leave ability null (the request runs unscoped, logged elsewhere).
|
|
44
|
+
*/
|
|
45
|
+
private hydrateSnapshot;
|
|
26
46
|
private stripToken;
|
|
27
47
|
private tryGetSubject;
|
|
28
48
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"internal-auth.interceptor.d.ts","sourceRoot":"","sources":["../../src/nest/internal-auth.interceptor.ts"],"names":[],"mappings":"AAcA,OAAO,EAGL,KAAK,WAAW,EAChB,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACrB,MAAM,gBAAgB,CAAC;AAExB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,UAAU,
|
|
1
|
+
{"version":3,"file":"internal-auth.interceptor.d.ts","sourceRoot":"","sources":["../../src/nest/internal-auth.interceptor.ts"],"names":[],"mappings":"AAcA,OAAO,EAGL,KAAK,WAAW,EAChB,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACrB,MAAM,gBAAgB,CAAC;AAExB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAuB,MAAM,MAAM,CAAC;AAGvD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAOL,KAAK,eAAe,EACrB,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAGnF,MAAM,MAAM,gBAAgB,GAAG,KAAK,GAAG,QAAQ,GAAG,SAAS,CAAC;AAE5D,kEAAkE;AAClE,MAAM,WAAW,eAAe;IAC9B,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC;CAC/D;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,eAAe,CAAC;IACtB,MAAM,EAAE,WAAW,CAAC;IACpB,0DAA0D;IAC1D,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,SAAS,CAAC;IACrB,qEAAqE;IACrE,IAAI,CAAC,EAAE,gBAAgB,CAAC;IACxB,oEAAoE;IACpE,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;;;OAKG;IACH,aAAa,CAAC,EAAE,eAAe,CAAC;IAChC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,EAAE,KAAK,YAAY,CAAC,SAAS,CAAC,CAAC;CAC7D;AA8BD,qBACa,uBAAwB,YAAW,eAAe;IAIjD,OAAO,CAAC,QAAQ,CAAC,IAAI;IAHjC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA8B;IACrD,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAmB;gBAEX,IAAI,EAAE,mBAAmB;IAKtD,SAAS,CAAC,OAAO,EAAE,gBAAgB,EAAE,IAAI,EAAE,WAAW,GAAG,UAAU,CAAC,OAAO,CAAC;IAgC5E,yFAAyF;YAC3E,MAAM;IAqCpB;;;;OAIG;YACW,eAAe;IAsB7B,OAAO,CAAC,UAAU;IAKlB,OAAO,CAAC,aAAa;CAItB"}
|
|
@@ -84,7 +84,11 @@ let InternalAuthInterceptor = class InternalAuthInterceptor {
|
|
|
84
84
|
return next.handle();
|
|
85
85
|
}
|
|
86
86
|
return (0, rxjs_1.from)(this.verify(context)).pipe((0, operators_1.mergeMap)((authCtx) => authCtx
|
|
87
|
-
?
|
|
87
|
+
? // Run the WHOLE handler inside the ALS context. The callback must return a
|
|
88
|
+
// promise (lastValueFrom) so the store stays bound across every await — a
|
|
89
|
+
// sync `run(ctx, () => obs.subscribe())` loses context at the first await,
|
|
90
|
+
// leaving the Prisma extension unscoped (request/response RPC: single value).
|
|
91
|
+
(0, rxjs_1.from)(als_1.authzAls.run(authCtx, () => (0, rxjs_1.lastValueFrom)(next.handle())))
|
|
88
92
|
: next.handle()));
|
|
89
93
|
}
|
|
90
94
|
/** Returns the ALS context on success; in shadow mode returns null on failure (pass). */
|
|
@@ -110,7 +114,9 @@ let InternalAuthInterceptor = class InternalAuthInterceptor {
|
|
|
110
114
|
}
|
|
111
115
|
if (!first)
|
|
112
116
|
throw new internal_token_1.InternalAuthError('replay', `jti '${claims.jti}' already used`);
|
|
113
|
-
|
|
117
|
+
const authCtx = claimsToContext(claims);
|
|
118
|
+
await this.hydrateSnapshot(authCtx, claims);
|
|
119
|
+
return authCtx;
|
|
114
120
|
}
|
|
115
121
|
catch (e) {
|
|
116
122
|
const reason = e instanceof internal_token_1.InternalAuthError ? e.reason : 'sig';
|
|
@@ -122,6 +128,36 @@ let InternalAuthInterceptor = class InternalAuthInterceptor {
|
|
|
122
128
|
throw new microservices_1.RpcException({ code: 'INTERNAL_AUTH', reason, message: e.message });
|
|
123
129
|
}
|
|
124
130
|
}
|
|
131
|
+
/**
|
|
132
|
+
* Step 4 — rehydrate the ability from the Redis snapshot named by the `snap` claim.
|
|
133
|
+
* Missing/evicted snapshot in enforce → throw (fail-closed: the gateway must rebuild);
|
|
134
|
+
* in shadow → leave ability null (the request runs unscoped, logged elsewhere).
|
|
135
|
+
*/
|
|
136
|
+
async hydrateSnapshot(ctx, claims) {
|
|
137
|
+
if (!this.opts.snapshotStore || !this.opts.hydrate)
|
|
138
|
+
return; // hydration not wired
|
|
139
|
+
if (!claims.snap) {
|
|
140
|
+
if (this.mode === 'enforce')
|
|
141
|
+
throw new internal_token_1.InternalAuthError('missing', 'token has no snap claim');
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
const env = await this.opts.snapshotStore.getBySnapId(claims.snap);
|
|
145
|
+
if (!env) {
|
|
146
|
+
if (this.mode === 'enforce')
|
|
147
|
+
throw new internal_token_1.InternalAuthError('backend', `snapshot '${claims.snap}' not found (evicted/expired)`);
|
|
148
|
+
this.logger.warn(`shadow: snapshot '${claims.snap}' not found — running unscoped`);
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
if (claims.ph && env.permHash !== claims.ph) {
|
|
152
|
+
// Stale token vs rebuilt snapshot; treat as a revocation signal.
|
|
153
|
+
if (this.mode === 'enforce')
|
|
154
|
+
throw new internal_token_1.InternalAuthError('hash', 'permHash mismatch (snapshot rebuilt/revoked)');
|
|
155
|
+
this.logger.warn(`shadow: permHash mismatch snap='${claims.snap}'`);
|
|
156
|
+
}
|
|
157
|
+
ctx.ability = this.opts.hydrate(env.rules);
|
|
158
|
+
ctx.connected = env.connected;
|
|
159
|
+
ctx.accreditedAs = env.accreditedAs;
|
|
160
|
+
}
|
|
125
161
|
stripToken(context) {
|
|
126
162
|
const data = context.switchToRpc().getData();
|
|
127
163
|
if (data && internal_token_1.INTERNAL_JWT_FIELD in data)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"internal-auth.interceptor.js","sourceRoot":"","sources":["../../src/nest/internal-auth.interceptor.ts"],"names":[],"mappings":";AAAA,uFAAuF;AACvF,yFAAyF;AACzF,eAAe;AACf,EAAE;AACF,mDAAmD;AACnD,qGAAqG;AACrG,EAAE;AACF,6DAA6D;AAC7D,0FAA0F;AAC1F,8FAA8F;AAC9F,0FAA0F;AAC1F,4EAA4E;AAC5E,8FAA8F;;;;;;;;;;;;AAE9F,2CAMwB;AACxB,yDAAqD;AAErD,+
|
|
1
|
+
{"version":3,"file":"internal-auth.interceptor.js","sourceRoot":"","sources":["../../src/nest/internal-auth.interceptor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"public.decorator.d.ts","sourceRoot":"","sources":["../../src/nest/public.decorator.ts"],"names":[],"mappings":"AACA,OAAO,EAAe,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAGnE,wBAAgB,MAAM,IAAI,eAAe,CAExC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Public = Public;
|
|
4
|
+
// Step 6 — opt a route out of default-deny (login, health, public pages).
|
|
5
|
+
const common_1 = require("@nestjs/common");
|
|
6
|
+
const global_authz_guard_1 = require("./global-authz.guard");
|
|
7
|
+
function Public() {
|
|
8
|
+
return (0, common_1.SetMetadata)(global_authz_guard_1.PUBLIC_KEY, true);
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=public.decorator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"public.decorator.js","sourceRoot":"","sources":["../../src/nest/public.decorator.ts"],"names":[],"mappings":";;AAIA,wBAEC;AAND,0EAA0E;AAC1E,2CAAmE;AACnE,6DAAkD;AAElD,SAAgB,MAAM;IACpB,OAAO,IAAA,oBAAW,EAAC,+BAAU,EAAE,IAAI,CAAC,CAAC;AACvC,CAAC"}
|