@dudousxd/nestjs-authz 0.8.0 → 0.9.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/CHANGELOG.md +115 -0
- package/README.md +279 -0
- package/dist/authz.guard.d.ts +48 -0
- package/dist/authz.guard.d.ts.map +1 -0
- package/dist/authz.guard.js +144 -0
- package/dist/authz.guard.js.map +1 -0
- package/dist/can-endpoint.controller.d.ts +0 -19
- package/dist/can-endpoint.controller.d.ts.map +1 -1
- package/dist/can-endpoint.controller.js +18 -9
- package/dist/can-endpoint.controller.js.map +1 -1
- package/dist/decision-provider.d.ts +25 -16
- package/dist/decision-provider.d.ts.map +1 -1
- package/dist/decision-provider.js +11 -1
- package/dist/decision-provider.js.map +1 -1
- package/dist/decisions.d.ts +24 -0
- package/dist/decisions.d.ts.map +1 -0
- package/dist/decisions.js +87 -0
- package/dist/decisions.js.map +1 -0
- package/dist/decorator/roles.decorator.d.ts +6 -12
- package/dist/decorator/roles.decorator.d.ts.map +1 -1
- package/dist/decorator/roles.decorator.js +13 -15
- package/dist/decorator/roles.decorator.js.map +1 -1
- package/dist/diagnostics.d.ts +15 -5
- package/dist/diagnostics.d.ts.map +1 -1
- package/dist/diagnostics.js +3 -1
- package/dist/diagnostics.js.map +1 -1
- package/dist/errors/exceptions.d.ts +0 -8
- package/dist/errors/exceptions.d.ts.map +1 -1
- package/dist/errors/exceptions.js +0 -14
- package/dist/errors/exceptions.js.map +1 -1
- package/dist/gate.d.ts +83 -209
- package/dist/gate.d.ts.map +1 -1
- package/dist/gate.js +209 -577
- package/dist/gate.js.map +1 -1
- package/dist/helpers.d.ts +46 -0
- package/dist/helpers.d.ts.map +1 -0
- package/dist/helpers.js +89 -0
- package/dist/helpers.js.map +1 -0
- package/dist/index.d.ts +28 -21
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +30 -13
- package/dist/index.js.map +1 -1
- package/dist/links.d.ts +39 -0
- package/dist/links.d.ts.map +1 -0
- package/dist/links.js +57 -0
- package/dist/links.js.map +1 -0
- package/dist/module.d.ts +23 -22
- package/dist/module.d.ts.map +1 -1
- package/dist/module.js +129 -158
- package/dist/module.js.map +1 -1
- package/dist/official.d.ts +39 -0
- package/dist/official.d.ts.map +1 -0
- package/dist/official.js +44 -0
- package/dist/official.js.map +1 -0
- package/dist/permission-cache.d.ts +18 -9
- package/dist/permission-cache.d.ts.map +1 -1
- package/dist/permission-cache.js +87 -24
- package/dist/permission-cache.js.map +1 -1
- package/dist/permission-matcher.d.ts +13 -0
- package/dist/permission-matcher.d.ts.map +1 -1
- package/dist/permission-matcher.js +38 -2
- package/dist/permission-matcher.js.map +1 -1
- package/dist/permission-provider.d.ts +11 -0
- package/dist/permission-provider.d.ts.map +1 -1
- package/dist/policies/authz-policy.d.ts +42 -0
- package/dist/policies/authz-policy.d.ts.map +1 -0
- package/dist/policies/authz-policy.js +80 -0
- package/dist/policies/authz-policy.js.map +1 -0
- package/dist/policies/gate.policy.d.ts +18 -0
- package/dist/policies/gate.policy.d.ts.map +1 -0
- package/dist/policies/gate.policy.js +37 -0
- package/dist/policies/gate.policy.js.map +1 -0
- package/dist/policies/index.d.ts +5 -0
- package/dist/policies/index.d.ts.map +1 -0
- package/dist/policies/index.js +5 -0
- package/dist/policies/index.js.map +1 -0
- package/dist/policies/permission.policy.d.ts +27 -0
- package/dist/policies/permission.policy.d.ts.map +1 -0
- package/dist/policies/permission.policy.js +61 -0
- package/dist/policies/permission.policy.js.map +1 -0
- package/dist/policies/role.policy.d.ts +27 -0
- package/dist/policies/role.policy.d.ts.map +1 -0
- package/dist/policies/role.policy.js +51 -0
- package/dist/policies/role.policy.js.map +1 -0
- package/dist/policy-index.d.ts +51 -0
- package/dist/policy-index.d.ts.map +1 -0
- package/dist/policy-index.js +135 -0
- package/dist/policy-index.js.map +1 -0
- package/dist/rbac.d.ts +92 -0
- package/dist/rbac.d.ts.map +1 -0
- package/dist/rbac.js +293 -0
- package/dist/rbac.js.map +1 -0
- package/dist/resource-resolver.d.ts +15 -17
- package/dist/resource-resolver.d.ts.map +1 -1
- package/dist/resource-resolver.js +8 -8
- package/dist/resource-resolver.js.map +1 -1
- package/dist/runtime.d.ts +31 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +40 -0
- package/dist/runtime.js.map +1 -0
- package/dist/tokens.d.ts +4 -8
- package/dist/tokens.d.ts.map +1 -1
- package/dist/tokens.js +4 -8
- package/dist/tokens.js.map +1 -1
- package/dist/types.d.ts +52 -169
- package/dist/types.d.ts.map +1 -1
- package/package.json +19 -10
- package/skills/authz-enforcement/SKILL.md +67 -131
- package/skills/authz-policies/SKILL.md +43 -117
- package/skills/authz-query-scopes/SKILL.md +16 -9
- package/skills/authz-rbac-seams/SKILL.md +39 -12
- package/skills/authz-setup/SKILL.md +45 -106
- package/dist/decorator/can.decorator.d.ts +0 -29
- package/dist/decorator/can.decorator.d.ts.map +0 -1
- package/dist/decorator/can.decorator.js +0 -23
- package/dist/decorator/can.decorator.js.map +0 -1
- package/dist/decorator/policy.decorator.d.ts +0 -18
- package/dist/decorator/policy.decorator.d.ts.map +0 -1
- package/dist/decorator/policy.decorator.js +0 -28
- package/dist/decorator/policy.decorator.js.map +0 -1
- package/dist/guard/can.guard.d.ts +0 -31
- package/dist/guard/can.guard.d.ts.map +0 -1
- package/dist/guard/can.guard.js +0 -92
- package/dist/guard/can.guard.js.map +0 -1
- package/dist/guard/roles.guard.d.ts +0 -21
- package/dist/guard/roles.guard.d.ts.map +0 -1
- package/dist/guard/roles.guard.js +0 -50
- package/dist/guard/roles.guard.js.map +0 -1
- package/dist/policy-registry.d.ts +0 -46
- package/dist/policy-registry.d.ts.map +0 -1
- package/dist/policy-registry.js +0 -101
- package/dist/policy-registry.js.map +0 -1
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
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;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
+
};
|
|
10
|
+
import { Policy } from '@nestjs/authorization';
|
|
11
|
+
import { AuthzRbac } from '../rbac.js';
|
|
12
|
+
import { AuthzPolicy, superAdminBefore } from './authz-policy.js';
|
|
13
|
+
/**
|
|
14
|
+
* Persisted (and user-object) roles as an official policy.
|
|
15
|
+
*
|
|
16
|
+
* ```ts
|
|
17
|
+
* @Can(RolePolicy, 'has', roles('admin', 'editor')) // any of
|
|
18
|
+
* @Can(RolePolicy, 'hasAll', roles('admin', 'editor')) // all of
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* Roles come from `user.roles` / `user.role` (or `resolveRoles`) and from the RBAC
|
|
22
|
+
* adapter's role store, scoped to the current tenant. Honors `superAdmin`.
|
|
23
|
+
*/
|
|
24
|
+
let RolePolicy = class RolePolicy extends AuthzPolicy {
|
|
25
|
+
rbac;
|
|
26
|
+
constructor(rbac) {
|
|
27
|
+
super();
|
|
28
|
+
this.rbac = rbac;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Asks only `superAdmin`: the abilities here name roles, not a resource, so the
|
|
32
|
+
* external decision point is not consulted.
|
|
33
|
+
*/
|
|
34
|
+
before(user, ability) {
|
|
35
|
+
return superAdminBefore(user, ability);
|
|
36
|
+
}
|
|
37
|
+
/** The user holds any of `roles`. */
|
|
38
|
+
has(user, ...roles) {
|
|
39
|
+
return this.rbac.hasAnyRole(user, roles);
|
|
40
|
+
}
|
|
41
|
+
/** The user holds every one of `roles`. */
|
|
42
|
+
hasAll(user, ...roles) {
|
|
43
|
+
return this.rbac.hasAllRoles(user, roles);
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
RolePolicy = __decorate([
|
|
47
|
+
Policy(),
|
|
48
|
+
__metadata("design:paramtypes", [AuthzRbac])
|
|
49
|
+
], RolePolicy);
|
|
50
|
+
export { RolePolicy };
|
|
51
|
+
//# sourceMappingURL=role.policy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"role.policy.js","sourceRoot":"","sources":["../../src/policies/role.policy.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAC/C,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAElE;;;;;;;;;;GAUG;AAEI,IAAM,UAAU,GAAhB,MAAM,UAAW,SAAQ,WAAW;IACZ;IAA7B,YAA6B,IAAe;QAC1C,KAAK,EAAE,CAAC;QADmB,SAAI,GAAJ,IAAI,CAAW;IAE5C,CAAC;IAED;;;OAGG;IACM,MAAM,CAAC,IAAa,EAAE,OAAe;QAC5C,OAAO,gBAAgB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACzC,CAAC;IAED,qCAAqC;IACrC,GAAG,CAAC,IAAa,EAAE,GAAG,KAAe;QACnC,OAAO,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAC3C,CAAC;IAED,2CAA2C;IAC3C,MAAM,CAAC,IAAa,EAAE,GAAG,KAAe;QACtC,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAC5C,CAAC;CACF,CAAA;AAtBY,UAAU;IADtB,MAAM,EAAE;qCAE4B,SAAS;GADjC,UAAU,CAsBtB"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { type Type } from '@nestjs/common';
|
|
2
|
+
import { DiscoveryService, ModuleRef, ModulesContainer } from '@nestjs/core';
|
|
3
|
+
/** One official policy of the application, as the extras see it. */
|
|
4
|
+
export interface IndexedPolicy {
|
|
5
|
+
policy: Type<unknown>;
|
|
6
|
+
/** The instance the official registry uses (an `overrideProvider` replacement in tests). */
|
|
7
|
+
instance: object;
|
|
8
|
+
/** The resource linked with `@PolicyFor`, if any. */
|
|
9
|
+
resource: Type<unknown> | undefined;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* The application's official `@Policy()` providers and their resource links. Read-only:
|
|
13
|
+
* the official `PolicyRegistry` owns registration; this only looks them up for the
|
|
14
|
+
* extras (resource → policy, `scope()`, ability listings).
|
|
15
|
+
*/
|
|
16
|
+
export declare class PolicyIndex {
|
|
17
|
+
private readonly discovery;
|
|
18
|
+
private readonly moduleRef;
|
|
19
|
+
private readonly modules;
|
|
20
|
+
/** The last scan, reused while the container's shape (modules, providers) is unchanged. */
|
|
21
|
+
private cache;
|
|
22
|
+
constructor(discovery: DiscoveryService, moduleRef: ModuleRef, modules: ModulesContainer);
|
|
23
|
+
/**
|
|
24
|
+
* Every official policy registered as a provider, built-ins included. Rescanned when a
|
|
25
|
+
* module or provider is added (a lazy module) or a policy was not instantiated yet.
|
|
26
|
+
*/
|
|
27
|
+
all(): IndexedPolicy[];
|
|
28
|
+
/** Cheap fingerprint of the container: module count and each module's provider count. */
|
|
29
|
+
private signature;
|
|
30
|
+
/** Official policies about a resource (built-ins left out). */
|
|
31
|
+
resourcePolicies(): IndexedPolicy[];
|
|
32
|
+
/** The policy class linked to a resource class. */
|
|
33
|
+
policyFor(resource: Type<unknown>): Type<unknown> | undefined;
|
|
34
|
+
/** The policy class for a resource instance (by its constructor), or for a class. */
|
|
35
|
+
policyOf(resource: object): Type<unknown> | undefined;
|
|
36
|
+
/** Linked policy classes defining `ability`, for a check that names no resource. */
|
|
37
|
+
linkedPoliciesWith(ability: string): Type<unknown>[];
|
|
38
|
+
/** The policy instance the app uses for `policy`, or `undefined` when it is not registered. */
|
|
39
|
+
instanceOf(policy: Type<unknown>): object | undefined;
|
|
40
|
+
/**
|
|
41
|
+
* Abilities of each resource policy that take no argument after the user (arity
|
|
42
|
+
* `<= 1`, e.g. `create(user)`), safe to check without a record. `before`, `scope` and
|
|
43
|
+
* the constructor are not abilities.
|
|
44
|
+
*/
|
|
45
|
+
classAbilities(): Array<{
|
|
46
|
+
policy: Type<unknown>;
|
|
47
|
+
resource: Type<unknown> | undefined;
|
|
48
|
+
abilities: string[];
|
|
49
|
+
}>;
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=policy-index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"policy-index.d.ts","sourceRoot":"","sources":["../src/policy-index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,IAAI,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAO7E,oEAAoE;AACpE,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;IACtB,4FAA4F;IAC5F,QAAQ,EAAE,MAAM,CAAC;IACjB,qDAAqD;IACrD,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG,SAAS,CAAC;CACrC;AAED;;;;GAIG;AACH,qBACa,WAAW;IAKpB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,OAAO;IAN1B,2FAA2F;IAC3F,OAAO,CAAC,KAAK,CAA+D;gBAGzD,SAAS,EAAE,gBAAgB,EAC3B,SAAS,EAAE,SAAS,EACpB,OAAO,EAAE,gBAAgB;IAG5C;;;OAGG;IACH,GAAG,IAAI,aAAa,EAAE;IA6BtB,yFAAyF;IACzF,OAAO,CAAC,SAAS;IAMjB,+DAA+D;IAC/D,gBAAgB,IAAI,aAAa,EAAE;IAInC,mDAAmD;IACnD,SAAS,CAAC,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,SAAS;IAI7D,qFAAqF;IACrF,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,SAAS;IAKrD,oFAAoF;IACpF,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,EAAE;IAMpD,+FAA+F;IAC/F,UAAU,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG,MAAM,GAAG,SAAS;IAUrD;;;;OAIG;IACH,cAAc,IAAI,KAAK,CAAC;QACtB,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QACtB,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG,SAAS,CAAC;QACpC,SAAS,EAAE,MAAM,EAAE,CAAC;KACrB,CAAC;CAeH"}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
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;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
+
};
|
|
10
|
+
import { Injectable } from '@nestjs/common';
|
|
11
|
+
import { DiscoveryService, ModuleRef, ModulesContainer } from '@nestjs/core';
|
|
12
|
+
import { getPolicyResource, policyForResource, policyLinks } from './links.js';
|
|
13
|
+
import { isOfficialPolicy } from './official.js';
|
|
14
|
+
/** Built-in policies that are not about a resource; left out of ability listings. */
|
|
15
|
+
const BUILT_IN = new Set(['RolePolicy', 'PermissionPolicy', 'GatePolicy']);
|
|
16
|
+
/**
|
|
17
|
+
* The application's official `@Policy()` providers and their resource links. Read-only:
|
|
18
|
+
* the official `PolicyRegistry` owns registration; this only looks them up for the
|
|
19
|
+
* extras (resource → policy, `scope()`, ability listings).
|
|
20
|
+
*/
|
|
21
|
+
let PolicyIndex = class PolicyIndex {
|
|
22
|
+
discovery;
|
|
23
|
+
moduleRef;
|
|
24
|
+
modules;
|
|
25
|
+
/** The last scan, reused while the container's shape (modules, providers) is unchanged. */
|
|
26
|
+
cache;
|
|
27
|
+
constructor(discovery, moduleRef, modules) {
|
|
28
|
+
this.discovery = discovery;
|
|
29
|
+
this.moduleRef = moduleRef;
|
|
30
|
+
this.modules = modules;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Every official policy registered as a provider, built-ins included. Rescanned when a
|
|
34
|
+
* module or provider is added (a lazy module) or a policy was not instantiated yet.
|
|
35
|
+
*/
|
|
36
|
+
all() {
|
|
37
|
+
const signature = this.signature();
|
|
38
|
+
if (this.cache?.signature === signature)
|
|
39
|
+
return this.cache.policies;
|
|
40
|
+
const seen = new Set();
|
|
41
|
+
const out = [];
|
|
42
|
+
let complete = true;
|
|
43
|
+
for (const wrapper of this.discovery.getProviders()) {
|
|
44
|
+
const token = wrapper.token;
|
|
45
|
+
const key = isOfficialPolicy(token)
|
|
46
|
+
? token
|
|
47
|
+
: !wrapper.isFactory && isOfficialPolicy(wrapper.metatype)
|
|
48
|
+
? wrapper.metatype
|
|
49
|
+
: undefined;
|
|
50
|
+
if (!key || seen.has(key))
|
|
51
|
+
continue;
|
|
52
|
+
if (!wrapper.instance || typeof wrapper.instance !== 'object') {
|
|
53
|
+
complete = false;
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
seen.add(key);
|
|
57
|
+
out.push({
|
|
58
|
+
policy: key,
|
|
59
|
+
instance: wrapper.instance,
|
|
60
|
+
resource: getPolicyResource(key),
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
this.cache = complete ? { signature, policies: out } : undefined;
|
|
64
|
+
return out;
|
|
65
|
+
}
|
|
66
|
+
/** Cheap fingerprint of the container: module count and each module's provider count. */
|
|
67
|
+
signature() {
|
|
68
|
+
let out = String(this.modules.size);
|
|
69
|
+
for (const module of this.modules.values())
|
|
70
|
+
out += `,${module.providers.size}`;
|
|
71
|
+
return out;
|
|
72
|
+
}
|
|
73
|
+
/** Official policies about a resource (built-ins left out). */
|
|
74
|
+
resourcePolicies() {
|
|
75
|
+
return this.all().filter((p) => !BUILT_IN.has(p.policy.name));
|
|
76
|
+
}
|
|
77
|
+
/** The policy class linked to a resource class. */
|
|
78
|
+
policyFor(resource) {
|
|
79
|
+
return policyForResource(resource);
|
|
80
|
+
}
|
|
81
|
+
/** The policy class for a resource instance (by its constructor), or for a class. */
|
|
82
|
+
policyOf(resource) {
|
|
83
|
+
if (typeof resource === 'function')
|
|
84
|
+
return policyForResource(resource);
|
|
85
|
+
return policyForResource(resource.constructor);
|
|
86
|
+
}
|
|
87
|
+
/** Linked policy classes defining `ability`, for a check that names no resource. */
|
|
88
|
+
linkedPoliciesWith(ability) {
|
|
89
|
+
return policyLinks()
|
|
90
|
+
.map((l) => l.policy)
|
|
91
|
+
.filter((p) => typeof p.prototype[ability] === 'function');
|
|
92
|
+
}
|
|
93
|
+
/** The policy instance the app uses for `policy`, or `undefined` when it is not registered. */
|
|
94
|
+
instanceOf(policy) {
|
|
95
|
+
const indexed = this.all().find((p) => p.policy === policy);
|
|
96
|
+
if (indexed)
|
|
97
|
+
return indexed.instance;
|
|
98
|
+
try {
|
|
99
|
+
return this.moduleRef.get(policy, { strict: false });
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
return undefined;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Abilities of each resource policy that take no argument after the user (arity
|
|
107
|
+
* `<= 1`, e.g. `create(user)`), safe to check without a record. `before`, `scope` and
|
|
108
|
+
* the constructor are not abilities.
|
|
109
|
+
*/
|
|
110
|
+
classAbilities() {
|
|
111
|
+
return this.resourcePolicies().map(({ policy, instance, resource }) => {
|
|
112
|
+
const abilities = new Set();
|
|
113
|
+
let proto = Object.getPrototypeOf(instance);
|
|
114
|
+
while (proto && proto !== Object.prototype) {
|
|
115
|
+
for (const name of Object.getOwnPropertyNames(proto)) {
|
|
116
|
+
if (name === 'constructor' || name === 'before' || name === 'scope')
|
|
117
|
+
continue;
|
|
118
|
+
const member = instance[name];
|
|
119
|
+
if (typeof member === 'function' && member.length <= 1)
|
|
120
|
+
abilities.add(name);
|
|
121
|
+
}
|
|
122
|
+
proto = Object.getPrototypeOf(proto);
|
|
123
|
+
}
|
|
124
|
+
return { policy, resource, abilities: [...abilities] };
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
PolicyIndex = __decorate([
|
|
129
|
+
Injectable(),
|
|
130
|
+
__metadata("design:paramtypes", [DiscoveryService,
|
|
131
|
+
ModuleRef,
|
|
132
|
+
ModulesContainer])
|
|
133
|
+
], PolicyIndex);
|
|
134
|
+
export { PolicyIndex };
|
|
135
|
+
//# sourceMappingURL=policy-index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"policy-index.js","sourceRoot":"","sources":["../src/policy-index.ts"],"names":[],"mappings":"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"}
|
package/dist/rbac.d.ts
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { type OnModuleInit } from '@nestjs/common';
|
|
2
|
+
import { ModuleRef } from '@nestjs/core';
|
|
3
|
+
import type { ContextAccessor } from './context-accessor.js';
|
|
4
|
+
import type { DecisionProvider } from './decision-provider.js';
|
|
5
|
+
import { PermissionCache } from './permission-cache.js';
|
|
6
|
+
import type { PermissionProvider } from './permission-provider.js';
|
|
7
|
+
import { type RoleProvider } from './role-provider.js';
|
|
8
|
+
import type { AuthzModuleOptions, Resource, User } from './types.js';
|
|
9
|
+
/**
|
|
10
|
+
* Roles and permissions of a user, from the persisted RBAC seams (`ROLE_PROVIDER`,
|
|
11
|
+
* `PERMISSION_PROVIDER`, registered by the TypeORM / MikroORM / Prisma / Drizzle adapters)
|
|
12
|
+
* and from the user object itself (`user.roles` / `user.role`); the optional external
|
|
13
|
+
* decision point (`DECISION_PROVIDER`); and the ambient user for `Gate` calls made without
|
|
14
|
+
* one. Shared by `RolePolicy`, `PermissionPolicy`, `AuthzPolicy` and the `Gate`.
|
|
15
|
+
*
|
|
16
|
+
* Within one request (a nestjs-context store), a user's permissions and provider roles
|
|
17
|
+
* are fetched once, however many checks run, in guards and in handlers alike.
|
|
18
|
+
*/
|
|
19
|
+
export declare class AuthzRbac implements OnModuleInit {
|
|
20
|
+
private readonly context?;
|
|
21
|
+
private readonly moduleRef?;
|
|
22
|
+
private readonly permissionProvider?;
|
|
23
|
+
private readonly roleProvider?;
|
|
24
|
+
private readonly decisionProvider?;
|
|
25
|
+
private readonly roleResolver;
|
|
26
|
+
private readonly resolveUser;
|
|
27
|
+
private readonly lookups;
|
|
28
|
+
private authentication;
|
|
29
|
+
constructor(options: AuthzModuleOptions | undefined, context?: ContextAccessor | undefined, moduleRef?: ModuleRef | undefined, permissionProvider?: PermissionProvider | undefined, roleProvider?: RoleProvider | undefined, decisionProvider?: DecisionProvider | undefined);
|
|
30
|
+
/**
|
|
31
|
+
* Finds `@nestjs/authentication`'s `AuthenticationContext` when that optional peer is
|
|
32
|
+
* installed and its module is imported. The class is the DI token, so the package is
|
|
33
|
+
* loaded only here, and its absence is not an error.
|
|
34
|
+
*/
|
|
35
|
+
onModuleInit(): Promise<void>;
|
|
36
|
+
/**
|
|
37
|
+
* A provider registered by any module: the injected one, else a non-strict lookup,
|
|
38
|
+
* memoized, so a global RBAC module or a root-level accessor is found too.
|
|
39
|
+
*/
|
|
40
|
+
private lookup;
|
|
41
|
+
/** @internal The nestjs-context accessor, when one is registered. */
|
|
42
|
+
contextAccessor(): ContextAccessor | undefined;
|
|
43
|
+
/** The persisted permission seam, when an RBAC adapter registered one. */
|
|
44
|
+
permissions(): PermissionProvider | undefined;
|
|
45
|
+
/** The persisted role seam, when an RBAC adapter registered one. */
|
|
46
|
+
roles(): RoleProvider | undefined;
|
|
47
|
+
/** The external decision point (Cerbos, OPA, …), when one is registered. */
|
|
48
|
+
decisions(): DecisionProvider | undefined;
|
|
49
|
+
/**
|
|
50
|
+
* The user for a `Gate` call made without one:
|
|
51
|
+
*
|
|
52
|
+
* 1. `@nestjs/authentication`'s `AuthenticationContext.user`, when that optional peer is
|
|
53
|
+
* installed and its scope is active (a call it handles, or `AuthenticationContext.run()`):
|
|
54
|
+
* its answer is final, so a `null` there is a guest;
|
|
55
|
+
* 2. else, with no authentication scope at all, nestjs-context's user ref, hydrated by
|
|
56
|
+
* `resolveUser` when configured (once per `type:id` per request);
|
|
57
|
+
* 3. else `null` (a guest).
|
|
58
|
+
*/
|
|
59
|
+
currentUser(): Promise<User>;
|
|
60
|
+
/**
|
|
61
|
+
* `AuthenticationContext.user` (`null` for an anonymous call) when its scope is active;
|
|
62
|
+
* `undefined` without the package or outside its scope. A version that hides the scope is
|
|
63
|
+
* read as before: a user is an answer, `null` is not.
|
|
64
|
+
*/
|
|
65
|
+
private authenticatedUser;
|
|
66
|
+
/** The nestjs-context store for the current request, or `undefined` when there is none. */
|
|
67
|
+
private requestStore;
|
|
68
|
+
/**
|
|
69
|
+
* The per-request {@link PermissionCache} on the nestjs-context store, so every check
|
|
70
|
+
* in one request shares a single `getPermissions` and `getRoles` fetch per user.
|
|
71
|
+
* `undefined` without a store.
|
|
72
|
+
*/
|
|
73
|
+
requestCache(): PermissionCache | undefined;
|
|
74
|
+
/**
|
|
75
|
+
* The user's role names: the role resolver's (the user object) and the role provider's,
|
|
76
|
+
* the latter fetched through `cache` (the request's, by default).
|
|
77
|
+
*/
|
|
78
|
+
rolesOf(user: User, cache?: PermissionCache | undefined): Promise<Set<string>>;
|
|
79
|
+
/** True when the user holds any of `roles`. A guest holds none. */
|
|
80
|
+
hasAnyRole(user: User, roles: readonly string[], cache?: PermissionCache | undefined): Promise<boolean>;
|
|
81
|
+
/** True when the user holds every one of `roles`. */
|
|
82
|
+
hasAllRoles(user: User, roles: readonly string[]): Promise<boolean>;
|
|
83
|
+
/**
|
|
84
|
+
* True when the permission seam grants `permission` to `user`. With `getPermissions`,
|
|
85
|
+
* wildcard grants apply (`posts.*` satisfies `posts.update`, `*` anything), fetched
|
|
86
|
+
* once per `cache` (the request's, by default). A set the provider marks
|
|
87
|
+
* `exhaustivePermissions` answers on its own; otherwise a miss still asks the
|
|
88
|
+
* exact-match `hasPermission`. A guest, or no seam, is never granted.
|
|
89
|
+
*/
|
|
90
|
+
grants(user: User, permission: string, resource?: Resource, cache?: PermissionCache | undefined): Promise<boolean>;
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=rbac.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rbac.d.ts","sourceRoot":"","sources":["../src/rbac.ts"],"names":[],"mappings":"AACA,OAAO,EAAsB,KAAK,YAAY,EAAY,MAAM,gBAAgB,CAAC;AACjF,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,KAAK,EAAE,eAAe,EAAgB,MAAM,uBAAuB,CAAC;AAC3E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAExD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AACnE,OAAO,EAAE,KAAK,YAAY,EAA0C,MAAM,oBAAoB,CAAC;AAQ/F,OAAO,KAAK,EAAE,kBAAkB,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAsBrE;;;;;;;;;GASG;AACH,qBACa,SAAU,YAAW,YAAY;IAQD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC;IACtD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC;IAGvC,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAC;IACD,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC;IAC1B,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAC;IAb3E,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAe;IAC5C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAoC;IAChE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAyC;IACjE,OAAO,CAAC,cAAc,CAAwC;gBAGlB,OAAO,EAAE,kBAAkB,GAAG,SAAS,EACvB,OAAO,CAAC,EAAE,eAAe,YAAA,EACtD,SAAS,CAAC,EAAE,SAAS,YAAA,EAGjC,kBAAkB,CAAC,EAAE,kBAAkB,YAAA,EACJ,YAAY,CAAC,EAAE,YAAY,YAAA,EACvB,gBAAgB,CAAC,EAAE,gBAAgB,YAAA;IAM7F;;;;OAIG;IACG,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAoBnC;;;OAGG;IACH,OAAO,CAAC,MAAM;IAcd,qEAAqE;IACrE,eAAe,IAAI,eAAe,GAAG,SAAS;IAI9C,0EAA0E;IAC1E,WAAW,IAAI,kBAAkB,GAAG,SAAS;IAI7C,oEAAoE;IACpE,KAAK,IAAI,YAAY,GAAG,SAAS;IAIjC,4EAA4E;IAC5E,SAAS,IAAI,gBAAgB,GAAG,SAAS;IAIzC;;;;;;;;;OASG;IACG,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;IA4BlC;;;;OAIG;IACH,OAAO,CAAC,iBAAiB;IAczB,2FAA2F;IAC3F,OAAO,CAAC,YAAY;IAYpB;;;;OAIG;IACH,YAAY,IAAI,eAAe,GAAG,SAAS;IAU3C;;;OAGG;IACG,OAAO,CACX,IAAI,EAAE,IAAI,EACV,KAAK,GAAE,eAAe,GAAG,SAA+B,GACvD,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAiBvB,mEAAmE;IAC7D,UAAU,CACd,IAAI,EAAE,IAAI,EACV,KAAK,EAAE,SAAS,MAAM,EAAE,EACxB,KAAK,CAAC,EAAE,eAAe,GAAG,SAAS,GAClC,OAAO,CAAC,OAAO,CAAC;IAMnB,qDAAqD;IAC/C,WAAW,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC;IAMzE;;;;;;OAMG;IACG,MAAM,CACV,IAAI,EAAE,IAAI,EACV,UAAU,EAAE,MAAM,EAClB,QAAQ,CAAC,EAAE,QAAQ,EACnB,KAAK,GAAE,eAAe,GAAG,SAA+B,GACvD,OAAO,CAAC,OAAO,CAAC;CAgBpB"}
|
package/dist/rbac.js
ADDED
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
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;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
+
};
|
|
10
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
11
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
12
|
+
};
|
|
13
|
+
import { InjectCapability } from '@dudousxd/nestjs-diagnostics/nestjs';
|
|
14
|
+
import { Inject, Injectable, Optional } from '@nestjs/common';
|
|
15
|
+
import { ModuleRef } from '@nestjs/core';
|
|
16
|
+
import { PermissionCache } from './permission-cache.js';
|
|
17
|
+
import { permissionSatisfied } from './permission-matcher.js';
|
|
18
|
+
import { defaultRoleResolver } from './role-provider.js';
|
|
19
|
+
import { AUTHZ_MODULE_OPTIONS, CONTEXT_ACCESSOR, DECISION_PROVIDER, PERMISSION_PROVIDER, ROLE_PROVIDER, } from './tokens.js';
|
|
20
|
+
/**
|
|
21
|
+
* Key of the per-request {@link PermissionCache} on the nestjs-context store. `Symbol.for`
|
|
22
|
+
* so every copy of this module shares it.
|
|
23
|
+
*/
|
|
24
|
+
const REQUEST_PERMISSION_CACHE = Symbol.for('@dudousxd/nestjs-authz:request-permission-cache');
|
|
25
|
+
/** Key under which the per-request `resolveUser` results are stashed on the context store. */
|
|
26
|
+
const REQUEST_USERS = Symbol.for('@dudousxd/nestjs-authz:request-users');
|
|
27
|
+
/**
|
|
28
|
+
* Roles and permissions of a user, from the persisted RBAC seams (`ROLE_PROVIDER`,
|
|
29
|
+
* `PERMISSION_PROVIDER`, registered by the TypeORM / MikroORM / Prisma / Drizzle adapters)
|
|
30
|
+
* and from the user object itself (`user.roles` / `user.role`); the optional external
|
|
31
|
+
* decision point (`DECISION_PROVIDER`); and the ambient user for `Gate` calls made without
|
|
32
|
+
* one. Shared by `RolePolicy`, `PermissionPolicy`, `AuthzPolicy` and the `Gate`.
|
|
33
|
+
*
|
|
34
|
+
* Within one request (a nestjs-context store), a user's permissions and provider roles
|
|
35
|
+
* are fetched once, however many checks run, in guards and in handlers alike.
|
|
36
|
+
*/
|
|
37
|
+
let AuthzRbac = class AuthzRbac {
|
|
38
|
+
context;
|
|
39
|
+
moduleRef;
|
|
40
|
+
permissionProvider;
|
|
41
|
+
roleProvider;
|
|
42
|
+
decisionProvider;
|
|
43
|
+
roleResolver;
|
|
44
|
+
resolveUser;
|
|
45
|
+
lookups = new Map();
|
|
46
|
+
authentication;
|
|
47
|
+
constructor(options, context, moduleRef, permissionProvider, roleProvider, decisionProvider) {
|
|
48
|
+
this.context = context;
|
|
49
|
+
this.moduleRef = moduleRef;
|
|
50
|
+
this.permissionProvider = permissionProvider;
|
|
51
|
+
this.roleProvider = roleProvider;
|
|
52
|
+
this.decisionProvider = decisionProvider;
|
|
53
|
+
this.roleResolver = options?.resolveRoles ?? defaultRoleResolver;
|
|
54
|
+
this.resolveUser = options?.resolveUser;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Finds `@nestjs/authentication`'s `AuthenticationContext` when that optional peer is
|
|
58
|
+
* installed and its module is imported. The class is the DI token, so the package is
|
|
59
|
+
* loaded only here, and its absence is not an error.
|
|
60
|
+
*/
|
|
61
|
+
async onModuleInit() {
|
|
62
|
+
if (!this.moduleRef || this.authentication)
|
|
63
|
+
return;
|
|
64
|
+
let token;
|
|
65
|
+
try {
|
|
66
|
+
const specifier = '@nestjs/authentication';
|
|
67
|
+
token = (await import(specifier))
|
|
68
|
+
.AuthenticationContext;
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
if (typeof token !== 'function')
|
|
74
|
+
return;
|
|
75
|
+
try {
|
|
76
|
+
this.authentication = this.moduleRef.get(token, {
|
|
77
|
+
strict: false,
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
this.authentication = undefined;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* A provider registered by any module: the injected one, else a non-strict lookup,
|
|
86
|
+
* memoized, so a global RBAC module or a root-level accessor is found too.
|
|
87
|
+
*/
|
|
88
|
+
lookup(token, injected) {
|
|
89
|
+
if (injected)
|
|
90
|
+
return injected;
|
|
91
|
+
const memo = this.lookups.get(token);
|
|
92
|
+
if (memo)
|
|
93
|
+
return memo.value;
|
|
94
|
+
let value;
|
|
95
|
+
try {
|
|
96
|
+
value = this.moduleRef?.get(token, { strict: false });
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
value = undefined;
|
|
100
|
+
}
|
|
101
|
+
this.lookups.set(token, { value });
|
|
102
|
+
return value;
|
|
103
|
+
}
|
|
104
|
+
/** @internal The nestjs-context accessor, when one is registered. */
|
|
105
|
+
contextAccessor() {
|
|
106
|
+
return this.lookup(CONTEXT_ACCESSOR, this.context);
|
|
107
|
+
}
|
|
108
|
+
/** The persisted permission seam, when an RBAC adapter registered one. */
|
|
109
|
+
permissions() {
|
|
110
|
+
return this.lookup(PERMISSION_PROVIDER, this.permissionProvider);
|
|
111
|
+
}
|
|
112
|
+
/** The persisted role seam, when an RBAC adapter registered one. */
|
|
113
|
+
roles() {
|
|
114
|
+
return this.lookup(ROLE_PROVIDER, this.roleProvider);
|
|
115
|
+
}
|
|
116
|
+
/** The external decision point (Cerbos, OPA, …), when one is registered. */
|
|
117
|
+
decisions() {
|
|
118
|
+
return this.lookup(DECISION_PROVIDER, this.decisionProvider);
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* The user for a `Gate` call made without one:
|
|
122
|
+
*
|
|
123
|
+
* 1. `@nestjs/authentication`'s `AuthenticationContext.user`, when that optional peer is
|
|
124
|
+
* installed and its scope is active (a call it handles, or `AuthenticationContext.run()`):
|
|
125
|
+
* its answer is final, so a `null` there is a guest;
|
|
126
|
+
* 2. else, with no authentication scope at all, nestjs-context's user ref, hydrated by
|
|
127
|
+
* `resolveUser` when configured (once per `type:id` per request);
|
|
128
|
+
* 3. else `null` (a guest).
|
|
129
|
+
*/
|
|
130
|
+
async currentUser() {
|
|
131
|
+
const authenticated = this.authenticatedUser();
|
|
132
|
+
if (authenticated !== undefined)
|
|
133
|
+
return authenticated;
|
|
134
|
+
const context = this.contextAccessor();
|
|
135
|
+
if (!context)
|
|
136
|
+
return null;
|
|
137
|
+
const ref = context.userRef();
|
|
138
|
+
if (ref === undefined)
|
|
139
|
+
return null;
|
|
140
|
+
const resolveUser = this.resolveUser;
|
|
141
|
+
if (!resolveUser)
|
|
142
|
+
return ref;
|
|
143
|
+
const hydrate = async () => (await resolveUser(ref)) ?? null;
|
|
144
|
+
const store = this.requestStore();
|
|
145
|
+
if (!store)
|
|
146
|
+
return hydrate();
|
|
147
|
+
let users = store[REQUEST_USERS];
|
|
148
|
+
if (!(users instanceof Map)) {
|
|
149
|
+
users = new Map();
|
|
150
|
+
store[REQUEST_USERS] = users;
|
|
151
|
+
}
|
|
152
|
+
const key = `${ref.type}:${typeof ref.id}:${ref.id}`;
|
|
153
|
+
const cached = users.get(key);
|
|
154
|
+
if (cached)
|
|
155
|
+
return cached;
|
|
156
|
+
const pending = hydrate();
|
|
157
|
+
users.set(key, pending);
|
|
158
|
+
pending.catch(() => users.delete(key));
|
|
159
|
+
return pending;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* `AuthenticationContext.user` (`null` for an anonymous call) when its scope is active;
|
|
163
|
+
* `undefined` without the package or outside its scope. A version that hides the scope is
|
|
164
|
+
* read as before: a user is an answer, `null` is not.
|
|
165
|
+
*/
|
|
166
|
+
authenticatedUser() {
|
|
167
|
+
const authentication = this.authentication;
|
|
168
|
+
if (!authentication)
|
|
169
|
+
return undefined;
|
|
170
|
+
try {
|
|
171
|
+
const scope = authentication.scope;
|
|
172
|
+
if (scope && typeof scope === 'object' && 'current' in scope) {
|
|
173
|
+
return scope.current === undefined ? undefined : (authentication.user ?? null);
|
|
174
|
+
}
|
|
175
|
+
return authentication.user ?? undefined;
|
|
176
|
+
}
|
|
177
|
+
catch {
|
|
178
|
+
return undefined;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
/** The nestjs-context store for the current request, or `undefined` when there is none. */
|
|
182
|
+
requestStore() {
|
|
183
|
+
const context = this.contextAccessor();
|
|
184
|
+
if (!context || typeof context.get !== 'function')
|
|
185
|
+
return undefined;
|
|
186
|
+
let store;
|
|
187
|
+
try {
|
|
188
|
+
store = context.get();
|
|
189
|
+
}
|
|
190
|
+
catch {
|
|
191
|
+
store = undefined;
|
|
192
|
+
}
|
|
193
|
+
return store;
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* The per-request {@link PermissionCache} on the nestjs-context store, so every check
|
|
197
|
+
* in one request shares a single `getPermissions` and `getRoles` fetch per user.
|
|
198
|
+
* `undefined` without a store.
|
|
199
|
+
*/
|
|
200
|
+
requestCache() {
|
|
201
|
+
const store = this.requestStore();
|
|
202
|
+
if (!store)
|
|
203
|
+
return undefined;
|
|
204
|
+
const existing = store[REQUEST_PERMISSION_CACHE];
|
|
205
|
+
if (existing instanceof PermissionCache)
|
|
206
|
+
return existing;
|
|
207
|
+
const cache = new PermissionCache();
|
|
208
|
+
store[REQUEST_PERMISSION_CACHE] = cache;
|
|
209
|
+
return cache;
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* The user's role names: the role resolver's (the user object) and the role provider's,
|
|
213
|
+
* the latter fetched through `cache` (the request's, by default).
|
|
214
|
+
*/
|
|
215
|
+
async rolesOf(user, cache = this.requestCache()) {
|
|
216
|
+
const out = new Set();
|
|
217
|
+
if (user == null)
|
|
218
|
+
return out;
|
|
219
|
+
const fromResolver = await this.roleResolver(user);
|
|
220
|
+
if (Array.isArray(fromResolver)) {
|
|
221
|
+
for (const r of fromResolver)
|
|
222
|
+
if (typeof r === 'string')
|
|
223
|
+
out.add(r);
|
|
224
|
+
}
|
|
225
|
+
const provider = this.roles();
|
|
226
|
+
if (provider) {
|
|
227
|
+
const fromProvider = await (cache ? cache.getRoles(provider, user) : provider.getRoles(user));
|
|
228
|
+
if (Array.isArray(fromProvider)) {
|
|
229
|
+
for (const r of fromProvider)
|
|
230
|
+
if (typeof r === 'string')
|
|
231
|
+
out.add(r);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
return out;
|
|
235
|
+
}
|
|
236
|
+
/** True when the user holds any of `roles`. A guest holds none. */
|
|
237
|
+
async hasAnyRole(user, roles, cache) {
|
|
238
|
+
if (user == null || roles.length === 0)
|
|
239
|
+
return false;
|
|
240
|
+
const held = await this.rolesOf(user, cache ?? this.requestCache());
|
|
241
|
+
return roles.some((r) => held.has(r));
|
|
242
|
+
}
|
|
243
|
+
/** True when the user holds every one of `roles`. */
|
|
244
|
+
async hasAllRoles(user, roles) {
|
|
245
|
+
if (user == null || roles.length === 0)
|
|
246
|
+
return false;
|
|
247
|
+
const held = await this.rolesOf(user);
|
|
248
|
+
return roles.every((r) => held.has(r));
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* True when the permission seam grants `permission` to `user`. With `getPermissions`,
|
|
252
|
+
* wildcard grants apply (`posts.*` satisfies `posts.update`, `*` anything), fetched
|
|
253
|
+
* once per `cache` (the request's, by default). A set the provider marks
|
|
254
|
+
* `exhaustivePermissions` answers on its own; otherwise a miss still asks the
|
|
255
|
+
* exact-match `hasPermission`. A guest, or no seam, is never granted.
|
|
256
|
+
*/
|
|
257
|
+
async grants(user, permission, resource, cache = this.requestCache()) {
|
|
258
|
+
if (user == null)
|
|
259
|
+
return false;
|
|
260
|
+
const provider = this.permissions();
|
|
261
|
+
if (!provider)
|
|
262
|
+
return false;
|
|
263
|
+
if (typeof provider.getPermissions === 'function') {
|
|
264
|
+
const satisfied = cache
|
|
265
|
+
? await cache.satisfies(provider, user, permission)
|
|
266
|
+
: await (async () => {
|
|
267
|
+
const granted = await provider.getPermissions?.(user);
|
|
268
|
+
return granted == null ? undefined : permissionSatisfied(granted, permission);
|
|
269
|
+
})();
|
|
270
|
+
if (satisfied === true)
|
|
271
|
+
return true;
|
|
272
|
+
if (satisfied === false && provider.exhaustivePermissions === true)
|
|
273
|
+
return false;
|
|
274
|
+
}
|
|
275
|
+
return (await provider.hasPermission(user, permission, resource)) === true;
|
|
276
|
+
}
|
|
277
|
+
};
|
|
278
|
+
AuthzRbac = __decorate([
|
|
279
|
+
Injectable(),
|
|
280
|
+
__param(0, Optional()),
|
|
281
|
+
__param(0, Inject(AUTHZ_MODULE_OPTIONS)),
|
|
282
|
+
__param(1, InjectCapability('context', 'accessor')),
|
|
283
|
+
__param(2, Optional()),
|
|
284
|
+
__param(3, Optional()),
|
|
285
|
+
__param(3, Inject(PERMISSION_PROVIDER)),
|
|
286
|
+
__param(4, Optional()),
|
|
287
|
+
__param(4, Inject(ROLE_PROVIDER)),
|
|
288
|
+
__param(5, Optional()),
|
|
289
|
+
__param(5, Inject(DECISION_PROVIDER)),
|
|
290
|
+
__metadata("design:paramtypes", [Object, Object, ModuleRef, Object, Object, Object])
|
|
291
|
+
], AuthzRbac);
|
|
292
|
+
export { AuthzRbac };
|
|
293
|
+
//# sourceMappingURL=rbac.js.map
|
package/dist/rbac.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rbac.js","sourceRoot":"","sources":["../src/rbac.ts"],"names":[],"mappings":"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"}
|