@spinajs/rbac-http 2.0.480 → 2.0.482
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/lib/cjs/controllers/GrantsController.d.ts +6 -4
- package/lib/cjs/controllers/GrantsController.d.ts.map +1 -1
- package/lib/cjs/controllers/GrantsController.js +20 -5
- package/lib/cjs/controllers/GrantsController.js.map +1 -1
- package/lib/cjs/decorators.d.ts +4 -1
- package/lib/cjs/decorators.d.ts.map +1 -1
- package/lib/cjs/decorators.js +100 -27
- package/lib/cjs/decorators.js.map +1 -1
- package/lib/cjs/middlewares.d.ts +1 -0
- package/lib/cjs/middlewares.d.ts.map +1 -1
- package/lib/cjs/middlewares.js +19 -1
- package/lib/cjs/middlewares.js.map +1 -1
- package/lib/cjs/policies/AllowGuest.d.ts +4 -1
- package/lib/cjs/policies/AllowGuest.d.ts.map +1 -1
- package/lib/cjs/policies/AllowGuest.js +4 -1
- package/lib/cjs/policies/AllowGuest.js.map +1 -1
- package/lib/cjs/policies/RbacPolicy.d.ts.map +1 -1
- package/lib/cjs/policies/RbacPolicy.js +20 -4
- package/lib/cjs/policies/RbacPolicy.js.map +1 -1
- package/lib/mjs/controllers/GrantsController.d.ts +6 -4
- package/lib/mjs/controllers/GrantsController.d.ts.map +1 -1
- package/lib/mjs/controllers/GrantsController.js +21 -6
- package/lib/mjs/controllers/GrantsController.js.map +1 -1
- package/lib/mjs/decorators.d.ts +4 -1
- package/lib/mjs/decorators.d.ts.map +1 -1
- package/lib/mjs/decorators.js +100 -27
- package/lib/mjs/decorators.js.map +1 -1
- package/lib/mjs/middlewares.d.ts +1 -0
- package/lib/mjs/middlewares.d.ts.map +1 -1
- package/lib/mjs/middlewares.js +20 -2
- package/lib/mjs/middlewares.js.map +1 -1
- package/lib/mjs/policies/AllowGuest.d.ts +4 -1
- package/lib/mjs/policies/AllowGuest.d.ts.map +1 -1
- package/lib/mjs/policies/AllowGuest.js +4 -1
- package/lib/mjs/policies/AllowGuest.js.map +1 -1
- package/lib/mjs/policies/RbacPolicy.d.ts.map +1 -1
- package/lib/mjs/policies/RbacPolicy.js +20 -4
- package/lib/mjs/policies/RbacPolicy.js.map +1 -1
- package/lib/tsconfig.cjs.tsbuildinfo +1 -1
- package/lib/tsconfig.mjs.tsbuildinfo +1 -1
- package/package.json +13 -11
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { BaseController, Ok } from '@spinajs/http';
|
|
2
|
-
import { AccessControl } from '@spinajs/rbac';
|
|
2
|
+
import { AccessControl, User as RbacUser } from '@spinajs/rbac';
|
|
3
3
|
import { IGrantsMap } from '../interfaces.js';
|
|
4
4
|
/**
|
|
5
5
|
* RBAC grants management.
|
|
@@ -10,11 +10,13 @@ export declare class GrantsController extends BaseController {
|
|
|
10
10
|
protected AC: AccessControl;
|
|
11
11
|
/**
|
|
12
12
|
* Get RBAC grants
|
|
13
|
-
* Returns the
|
|
13
|
+
* Returns the RBAC grants for the requesting user's own role(s) only — not
|
|
14
|
+
* the full cross-role matrix, which would leak the entire access-control
|
|
15
|
+
* policy to any authenticated user.
|
|
14
16
|
* @security cookieAuth
|
|
15
|
-
* @returns {IGrantsMap} RBAC grants map keyed by role name
|
|
17
|
+
* @returns {IGrantsMap} RBAC grants map keyed by the caller's role name(s)
|
|
16
18
|
* @response 401 Unauthorized — valid session cookie required
|
|
17
19
|
*/
|
|
18
|
-
getGrants(): Ok<IGrantsMap>;
|
|
20
|
+
getGrants(user: RbacUser): Ok<IGrantsMap>;
|
|
19
21
|
}
|
|
20
22
|
//# sourceMappingURL=GrantsController.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GrantsController.d.ts","sourceRoot":"","sources":["../../../src/controllers/GrantsController.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAiB,EAAE,EAAU,MAAM,eAAe,CAAC;AAC1E,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"GrantsController.d.ts","sourceRoot":"","sources":["../../../src/controllers/GrantsController.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAiB,EAAE,EAAU,MAAM,eAAe,CAAC;AAC1E,OAAO,EAAE,aAAa,EAAE,IAAI,IAAI,QAAQ,EAAE,MAAM,eAAe,CAAC;AAIhE,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE9C;;;;GAIG;AACH,qBAEa,gBAAiB,SAAQ,cAAc;IAGhD,SAAS,CAAC,EAAE,EAAE,aAAa,CAAC;IAE5B;;;;;;;;OAQG;IAEI,SAAS,CAAS,IAAI,EAAE,QAAQ,GAAG,EAAE,CAAC,UAAU,CAAC;CAc3D"}
|
|
@@ -8,12 +8,16 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
8
8
|
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
9
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
10
|
};
|
|
11
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
+
};
|
|
11
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
15
|
exports.GrantsController = void 0;
|
|
13
16
|
const http_1 = require("@spinajs/http");
|
|
14
17
|
const rbac_1 = require("@spinajs/rbac");
|
|
15
18
|
const di_1 = require("@spinajs/di");
|
|
16
19
|
const AuthorizedPolicy_js_1 = require("../policies/AuthorizedPolicy.js");
|
|
20
|
+
const decorators_js_1 = require("../decorators.js");
|
|
17
21
|
/**
|
|
18
22
|
* RBAC grants management.
|
|
19
23
|
* Provides access to the current RBAC access-control grants configuration.
|
|
@@ -22,13 +26,23 @@ const AuthorizedPolicy_js_1 = require("../policies/AuthorizedPolicy.js");
|
|
|
22
26
|
let GrantsController = class GrantsController extends http_1.BaseController {
|
|
23
27
|
/**
|
|
24
28
|
* Get RBAC grants
|
|
25
|
-
* Returns the
|
|
29
|
+
* Returns the RBAC grants for the requesting user's own role(s) only — not
|
|
30
|
+
* the full cross-role matrix, which would leak the entire access-control
|
|
31
|
+
* policy to any authenticated user.
|
|
26
32
|
* @security cookieAuth
|
|
27
|
-
* @returns {IGrantsMap} RBAC grants map keyed by role name
|
|
33
|
+
* @returns {IGrantsMap} RBAC grants map keyed by the caller's role name(s)
|
|
28
34
|
* @response 401 Unauthorized — valid session cookie required
|
|
29
35
|
*/
|
|
30
|
-
getGrants() {
|
|
31
|
-
|
|
36
|
+
getGrants(user) {
|
|
37
|
+
const allGrants = this.AC.getGrants();
|
|
38
|
+
const roles = user?.Role ?? [];
|
|
39
|
+
const filtered = {};
|
|
40
|
+
for (const role of roles) {
|
|
41
|
+
if (allGrants[role]) {
|
|
42
|
+
filtered[role] = allGrants[role];
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return new http_1.Ok(filtered);
|
|
32
46
|
}
|
|
33
47
|
};
|
|
34
48
|
exports.GrantsController = GrantsController;
|
|
@@ -38,8 +52,9 @@ __decorate([
|
|
|
38
52
|
], GrantsController.prototype, "AC", void 0);
|
|
39
53
|
__decorate([
|
|
40
54
|
(0, http_1.Get)(),
|
|
55
|
+
__param(0, (0, decorators_js_1.User)()),
|
|
41
56
|
__metadata("design:type", Function),
|
|
42
|
-
__metadata("design:paramtypes", []),
|
|
57
|
+
__metadata("design:paramtypes", [rbac_1.User]),
|
|
43
58
|
__metadata("design:returntype", http_1.Ok)
|
|
44
59
|
], GrantsController.prototype, "getGrants", null);
|
|
45
60
|
exports.GrantsController = GrantsController = __decorate([
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GrantsController.js","sourceRoot":"","sources":["../../../src/controllers/GrantsController.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"GrantsController.js","sourceRoot":"","sources":["../../../src/controllers/GrantsController.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,wCAA0E;AAC1E,wCAAgE;AAChE,oCAAyC;AACzC,yEAAmE;AACnE,oDAAwC;AAGxC;;;;GAIG;AAGI,IAAM,gBAAgB,GAAtB,MAAM,gBAAiB,SAAQ,qBAAc;IAKhD;;;;;;;;OAQG;IAEI,SAAS,CAAS,IAAc;QACnC,MAAM,SAAS,GAAG,IAAI,CAAC,EAAE,CAAC,SAAS,EAAgB,CAAC;QACpD,MAAM,KAAK,GAAG,IAAI,EAAE,IAAI,IAAI,EAAE,CAAC;QAE/B,MAAM,QAAQ,GAAe,EAAE,CAAC;QAChC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACvB,IAAI,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;gBAClB,QAAQ,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;YACrC,CAAC;QACL,CAAC;QAED,OAAO,IAAI,SAAE,CAAC,QAAQ,CAAC,CAAC;IAC5B,CAAC;CAEJ,CAAA;AA7BY,4CAAgB;AAGf;IADT,IAAA,eAAU,EAAC,oBAAa,CAAC;8BACZ,oBAAa;4CAAC;AAYrB;IADN,IAAA,UAAG,GAAE;IACY,WAAA,IAAA,oBAAI,GAAE,CAAA;;qCAAO,WAAQ;oCAAG,SAAE;iDAY3C;2BA3BQ,gBAAgB;IAF5B,IAAA,eAAQ,EAAC,QAAQ,CAAC;IAClB,IAAA,aAAM,EAAC,sCAAgB,CAAC;GACZ,gBAAgB,CA6B5B"}
|
package/lib/cjs/decorators.d.ts
CHANGED
|
@@ -10,7 +10,10 @@ export declare function setRbacMetadata(target: any, callback: (meta: IRbacDescr
|
|
|
10
10
|
* Assign resource for controller
|
|
11
11
|
*
|
|
12
12
|
* @param resource - name of resource
|
|
13
|
-
* @param permission - default permission
|
|
13
|
+
* @param permission - default permission. When omitted, the base controller's
|
|
14
|
+
* permission is kept ( `readOwn` if there is nothing to
|
|
15
|
+
* inherit ), so renaming a resource in a subclass does not
|
|
16
|
+
* silently change what it grants.
|
|
14
17
|
*/
|
|
15
18
|
export declare function Resource(resource: string, permission?: PermissionType[]): any;
|
|
16
19
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"decorators.d.ts","sourceRoot":"","sources":["../../src/decorators.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAkC,MAAM,iBAAiB,CAAC;AAGlF,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"decorators.d.ts","sourceRoot":"","sources":["../../src/decorators.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAkC,MAAM,iBAAiB,CAAC;AAGlF,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAI/C;;;GAGG;AACH,eAAO,MAAM,yBAAyB,eAAiD,CAAC;AAuFxF,wBAAgB,eAAe,CAAC,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,eAAe,KAAK,IAAI,QAMrF;AAYD;;;;;;;;GAQG;AACH,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,cAAc,EAAE,OAevE;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,UAAU,GAAE,cAAc,EAAgB,OAgBpE;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,0GAalC;AAED;;GAEG;AACH,wBAAgB,IAAI,0GAEnB;AAED;;GAEG;AACH,wBAAgB,WAAW,0GAE1B;AAED,wBAAgB,OAAO,0GAEtB"}
|
package/lib/cjs/decorators.js
CHANGED
|
@@ -10,36 +10,94 @@ exports.FromSession = FromSession;
|
|
|
10
10
|
exports.Session = Session;
|
|
11
11
|
const http_1 = require("@spinajs/http");
|
|
12
12
|
const RbacPolicy_js_1 = require("./policies/RbacPolicy.js");
|
|
13
|
+
const di_1 = require("@spinajs/di");
|
|
13
14
|
/**
|
|
14
15
|
* Global symbol so external packages (e.g. http-swagger) can read the RBAC
|
|
15
16
|
* descriptor via Reflect metadata without importing rbac-http.
|
|
16
17
|
*/
|
|
17
18
|
exports.ACL_CONTROLLER_DESCRIPTOR = Symbol.for('ACL_CONTROLLER_DESCRIPTOR_SYMBOL');
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
19
|
+
/**
|
|
20
|
+
* Permission a controller gets when neither it nor any ancestor declares one
|
|
21
|
+
* ( eg. a controller using route level `@Permission` only ).
|
|
22
|
+
*/
|
|
23
|
+
const DEFAULT_CONTROLLER_PERMISSION = ['readOwn'];
|
|
24
|
+
/**
|
|
25
|
+
* NOTE: `Permission` starts EMPTY here, unlike the documented default, and
|
|
26
|
+
* `rbacDescriptor()` fills the default in afterwards. The collapse in
|
|
27
|
+
* `getInheritedDescriptor` seeds itself with this object and CONCATENATES
|
|
28
|
+
* arrays, so seeding `['readOwn']` would make every subclass inherit
|
|
29
|
+
* `['readOwn', ...parent permission]` - granting more than the parent, which is
|
|
30
|
+
* the one direction a permission list must never drift in.
|
|
31
|
+
*/
|
|
32
|
+
function createDefaultRbacDescriptor() {
|
|
33
|
+
return {
|
|
34
|
+
Resource: '',
|
|
35
|
+
Routes: new Map(),
|
|
36
|
+
Permission: [],
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* The descriptor OWNED by the decorated class, pre-populated with everything it
|
|
41
|
+
* inherits.
|
|
42
|
+
*
|
|
43
|
+
* `Reflect.getMetadata` walks the prototype chain, so a controller subclass used
|
|
44
|
+
* to find - and mutate - its parent's descriptor: an application declaring
|
|
45
|
+
* `@Resource` on a subclass rewrote the ACL resource and permissions of the
|
|
46
|
+
* package controller it extends. `getInheritedDescriptor` stores own metadata
|
|
47
|
+
* per class instead, keyed by identity.
|
|
48
|
+
*
|
|
49
|
+
* Stored on the prototype ( `target.prototype || target` covers both the class
|
|
50
|
+
* and the member decorator forms ) because that is where RbacPolicy and
|
|
51
|
+
* http-swagger reach it from, off a controller INSTANCE.
|
|
52
|
+
*/
|
|
53
|
+
function rbacDescriptor(target) {
|
|
54
|
+
const controller = target.prototype || target;
|
|
55
|
+
// True only for the very first decorator that touches THIS class, since
|
|
56
|
+
// getInheritedDescriptor stores own metadata as soon as it is called.
|
|
57
|
+
const isFirstDecorator = !Reflect.getOwnMetadata(exports.ACL_CONTROLLER_DESCRIPTOR, controller);
|
|
58
|
+
// Decided BEFORE the collapse, and on the existence of an ancestor descriptor
|
|
59
|
+
// rather than on the collapsed value: an empty permission list is a
|
|
60
|
+
// declaration ( eg. `@Resource('r', [])` grants nothing ), so a subclass that
|
|
61
|
+
// inherits one must keep it. Standing the default in whenever the list came
|
|
62
|
+
// out empty would hand that subclass readOwn - MORE than its base grants.
|
|
63
|
+
const inherits = hasInheritedDescriptor(controller);
|
|
64
|
+
const metadata = (0, di_1.getInheritedDescriptor)(controller, exports.ACL_CONTROLLER_DESCRIPTOR, createDefaultRbacDescriptor);
|
|
65
|
+
// Nothing to inherit - see createDefaultRbacDescriptor for why the default
|
|
66
|
+
// cannot simply be part of the seed. Only on creation, so that a later
|
|
67
|
+
// decorator cannot refill a list this class deliberately emptied.
|
|
68
|
+
if (isFirstDecorator && !inherits) {
|
|
69
|
+
metadata.Permission = [...DEFAULT_CONTROLLER_PERMISSION];
|
|
27
70
|
}
|
|
71
|
+
return metadata;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* True when something ABOVE `controller` in the prototype chain owns an ACL
|
|
75
|
+
* descriptor - ie. when the collapse has a real ancestor to take values from.
|
|
76
|
+
*
|
|
77
|
+
* Mirrors the walk inside `getInheritedDescriptor`, starting one level up
|
|
78
|
+
* because `controller`'s own descriptor is what the caller is about to create.
|
|
79
|
+
* Keyed by identity, never by class name, and undecorated classes in between
|
|
80
|
+
* are simply passed over since they own no metadata.
|
|
81
|
+
*/
|
|
82
|
+
function hasInheritedDescriptor(controller) {
|
|
83
|
+
let current = Object.getPrototypeOf(controller);
|
|
84
|
+
while (current && current !== Object.prototype && current !== Function.prototype) {
|
|
85
|
+
if (Reflect.getOwnMetadata(exports.ACL_CONTROLLER_DESCRIPTOR, current)) {
|
|
86
|
+
return true;
|
|
87
|
+
}
|
|
88
|
+
current = Object.getPrototypeOf(current);
|
|
89
|
+
}
|
|
90
|
+
return false;
|
|
91
|
+
}
|
|
92
|
+
function setRbacMetadata(target, callback) {
|
|
93
|
+
const metadata = rbacDescriptor(target);
|
|
28
94
|
if (callback) {
|
|
29
95
|
callback(metadata);
|
|
30
96
|
}
|
|
31
97
|
}
|
|
32
98
|
function descriptor(callback) {
|
|
33
99
|
return (target, propertyKey, indexOrDescriptor) => {
|
|
34
|
-
|
|
35
|
-
if (!metadata) {
|
|
36
|
-
metadata = {
|
|
37
|
-
Resource: '',
|
|
38
|
-
Routes: new Map(),
|
|
39
|
-
Permission: ['readOwn'],
|
|
40
|
-
};
|
|
41
|
-
Reflect.defineMetadata(exports.ACL_CONTROLLER_DESCRIPTOR, metadata, target.prototype || target);
|
|
42
|
-
}
|
|
100
|
+
const metadata = rbacDescriptor(target);
|
|
43
101
|
if (callback) {
|
|
44
102
|
callback(metadata, target, propertyKey, indexOrDescriptor);
|
|
45
103
|
}
|
|
@@ -49,12 +107,24 @@ function descriptor(callback) {
|
|
|
49
107
|
* Assign resource for controller
|
|
50
108
|
*
|
|
51
109
|
* @param resource - name of resource
|
|
52
|
-
* @param permission - default permission
|
|
110
|
+
* @param permission - default permission. When omitted, the base controller's
|
|
111
|
+
* permission is kept ( `readOwn` if there is nothing to
|
|
112
|
+
* inherit ), so renaming a resource in a subclass does not
|
|
113
|
+
* silently change what it grants.
|
|
53
114
|
*/
|
|
54
|
-
function Resource(resource, permission
|
|
115
|
+
function Resource(resource, permission) {
|
|
55
116
|
return descriptor((metadata) => {
|
|
56
117
|
metadata.Resource = resource;
|
|
57
|
-
|
|
118
|
+
// ASSIGNED, never merged, and only when the argument was actually passed.
|
|
119
|
+
// Assigning is what lets an application NARROW a package controller -
|
|
120
|
+
// concatenating would grant the union of both lists, and a longer
|
|
121
|
+
// permission list grants more. Omitting the argument says nothing about
|
|
122
|
+
// permissions, so whatever was collapsed from the base controller stands.
|
|
123
|
+
// Copied because the array belongs to the call site, which is free to keep
|
|
124
|
+
// mutating it.
|
|
125
|
+
if (permission) {
|
|
126
|
+
metadata.Permission = [...permission];
|
|
127
|
+
}
|
|
58
128
|
});
|
|
59
129
|
}
|
|
60
130
|
/**
|
|
@@ -66,12 +136,15 @@ function Resource(resource, permission = ['readOwn']) {
|
|
|
66
136
|
function Permission(permission = ['readOwn']) {
|
|
67
137
|
return descriptor((metadata, target, propertyKey) => {
|
|
68
138
|
if (propertyKey) {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
139
|
+
// Always set, never guarded by `has()`: routes are inherited per member
|
|
140
|
+
// name now, so a guard would make a subclass's @Permission on an inherited
|
|
141
|
+
// route silently do nothing and leave the package controller's permission
|
|
142
|
+
// in force. Setting a FRESH entry is also what keeps the inherited entries
|
|
143
|
+
// - which the collapse shares by reference with the parent - from being
|
|
144
|
+
// rewritten here.
|
|
145
|
+
metadata.Routes.set(propertyKey, {
|
|
146
|
+
Permission: permission,
|
|
147
|
+
});
|
|
75
148
|
}
|
|
76
149
|
(0, http_1.Policy)(RbacPolicy_js_1.RbacPolicy)(target, propertyKey, undefined);
|
|
77
150
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"decorators.js","sourceRoot":"","sources":["../../src/decorators.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"decorators.js","sourceRoot":"","sources":["../../src/decorators.ts"],"names":[],"mappings":";;;AAkGA,0CAMC;AAqBD,4BAeC;AAQD,gCAgBC;AAUD,kDAaC;AAKD,oBAEC;AAKD,kCAEC;AAED,0BAEC;AA5MD,wCAA0I;AAC1I,4DAAsD;AAEtD,oCAAqD;AAGrD;;;GAGG;AACU,QAAA,yBAAyB,GAAG,MAAM,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAC;AAExF;;;GAGG;AACH,MAAM,6BAA6B,GAAqB,CAAC,SAAS,CAAC,CAAC;AAEpE;;;;;;;GAOG;AACH,SAAS,2BAA2B;IAClC,OAAO;QACL,QAAQ,EAAE,EAAE;QACZ,MAAM,EAAE,IAAI,GAAG,EAA0C;QACzD,UAAU,EAAE,EAAE;KACf,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,SAAS,cAAc,CAAC,MAAW;IACjC,MAAM,UAAU,GAAG,MAAM,CAAC,SAAS,IAAI,MAAM,CAAC;IAE9C,wEAAwE;IACxE,sEAAsE;IACtE,MAAM,gBAAgB,GAAG,CAAC,OAAO,CAAC,cAAc,CAAC,iCAAyB,EAAE,UAAU,CAAC,CAAC;IAExF,8EAA8E;IAC9E,oEAAoE;IACpE,8EAA8E;IAC9E,4EAA4E;IAC5E,0EAA0E;IAC1E,MAAM,QAAQ,GAAG,sBAAsB,CAAC,UAAU,CAAC,CAAC;IAEpD,MAAM,QAAQ,GAAG,IAAA,2BAAsB,EAAkB,UAAU,EAAE,iCAAyB,EAAE,2BAA2B,CAAC,CAAC;IAE7H,2EAA2E;IAC3E,uEAAuE;IACvE,kEAAkE;IAClE,IAAI,gBAAgB,IAAI,CAAC,QAAQ,EAAE,CAAC;QAClC,QAAQ,CAAC,UAAU,GAAG,CAAC,GAAG,6BAA6B,CAAC,CAAC;IAC3D,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,sBAAsB,CAAC,UAAkB;IAChD,IAAI,OAAO,GAAkB,MAAM,CAAC,cAAc,CAAC,UAAU,CAAkB,CAAC;IAEhF,OAAO,OAAO,IAAI,OAAO,KAAK,MAAM,CAAC,SAAS,IAAI,OAAO,KAAK,QAAQ,CAAC,SAAS,EAAE,CAAC;QACjF,IAAI,OAAO,CAAC,cAAc,CAAC,iCAAyB,EAAE,OAAO,CAAC,EAAE,CAAC;YAC/D,OAAO,IAAI,CAAC;QACd,CAAC;QAED,OAAO,GAAG,MAAM,CAAC,cAAc,CAAC,OAAO,CAAkB,CAAC;IAC5D,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAgB,eAAe,CAAC,MAAW,EAAE,QAAyC;IACpF,MAAM,QAAQ,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;IAExC,IAAI,QAAQ,EAAE,CAAC;QACb,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACrB,CAAC;AACH,CAAC;AAED,SAAS,UAAU,CAAC,QAA0I;IAC5J,OAAO,CAAC,MAAW,EAAE,WAA4B,EAAE,iBAA8C,EAAE,EAAE;QACnG,MAAM,QAAQ,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;QAExC,IAAI,QAAQ,EAAE,CAAC;YACb,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,iBAAiB,CAAC,CAAC;QAC7D,CAAC;IACH,CAAC,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,SAAgB,QAAQ,CAAC,QAAgB,EAAE,UAA6B;IACtE,OAAO,UAAU,CAAC,CAAC,QAAyB,EAAE,EAAE;QAC9C,QAAQ,CAAC,QAAQ,GAAG,QAAQ,CAAC;QAE7B,0EAA0E;QAC1E,sEAAsE;QACtE,kEAAkE;QAClE,wEAAwE;QACxE,0EAA0E;QAC1E,2EAA2E;QAC3E,eAAe;QACf,IAAI,UAAU,EAAE,CAAC;YACf,QAAQ,CAAC,UAAU,GAAG,CAAC,GAAG,UAAU,CAAC,CAAC;QACxC,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;GAKG;AACH,SAAgB,UAAU,CAAC,aAA+B,CAAC,SAAS,CAAC;IACnE,OAAO,UAAU,CAAC,CAAC,QAAyB,EAAE,MAAW,EAAE,WAAmB,EAAE,EAAE;QAChF,IAAI,WAAW,EAAE,CAAC;YAChB,wEAAwE;YACxE,2EAA2E;YAC3E,0EAA0E;YAC1E,2EAA2E;YAC3E,wEAAwE;YACxE,kBAAkB;YAClB,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,WAAW,EAAE;gBAC/B,UAAU,EAAE,UAAU;aACvB,CAAC,CAAC;QACL,CAAC;QAED,IAAA,aAAM,EAAC,0BAAU,CAAC,CAAC,MAAM,EAAE,WAAW,EAAE,SAAS,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;GAOG;AACH,SAAgB,mBAAmB;IACjC,OAAO,IAAA,iBAAU,EACf,KAAM,SAAQ,sBAAe;QACpB,SAAS,CAAC,MAAc,EAAE,WAAwB;YACvD,OAAO,IAAI,CAAC;QACd,CAAC;QACM,KAAK,CAAC,QAAQ,CAAC,GAAoB,EAAE,IAAsB,EAAE,MAAc,EAAE,WAAwB;YACzG,GAAgB,CAAC,OAAO,CAAC,wBAAwB,GAAG,IAAI,CAAC;QAC5D,CAAC;QACM,KAAK,CAAC,UAAU,CAAC,SAAmB,EAAE,MAAc,EAAE,WAAwB,IAAkB,CAAC;QACjG,KAAK,CAAC,OAAO,CAAC,IAAqB,EAAE,IAAsB,EAAE,MAAc,EAAE,WAAwB,IAAkB,CAAC;KAChI,CACF,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAgB,IAAI;IAClB,OAAO,IAAA,YAAK,EAAC,IAAA,gBAAS,EAAC,SAAS,CAAC,CAAC,CAAC;AACrC,CAAC;AAED;;GAEG;AACH,SAAgB,WAAW;IACzB,OAAO,IAAA,YAAK,EAAC,IAAA,gBAAS,EAAC,YAAY,CAAC,CAAC,CAAC;AACxC,CAAC;AAED,SAAgB,OAAO;IACrB,OAAO,IAAA,YAAK,EAAC,IAAA,gBAAS,EAAC,mBAAmB,CAAC,CAAC,CAAC;AAC/C,CAAC"}
|
package/lib/cjs/middlewares.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ import * as express from 'express';
|
|
|
4
4
|
import { Request as sRequest, ServerMiddleware } from '@spinajs/http';
|
|
5
5
|
export declare class RbacMiddleware extends ServerMiddleware {
|
|
6
6
|
protected CoockieSecret: string;
|
|
7
|
+
protected SessionCookieConfig: any;
|
|
7
8
|
protected SessionProvider: SessionProvider;
|
|
8
9
|
resolve(): Promise<void>;
|
|
9
10
|
before(): (req: sRequest, res: express.Response, next: express.NextFunction) => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"middlewares.d.ts","sourceRoot":"","sources":["../../src/middlewares.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,eAAe,
|
|
1
|
+
{"version":3,"file":"middlewares.d.ts","sourceRoot":"","sources":["../../src/middlewares.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,eAAe,EAA6B,MAAM,eAAe,CAAC;AAErF,OAAO,kBAAkB,CAAC;AAC1B,OAAO,KAAK,OAAO,MAAM,SAAS,CAAC;AAGnC,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEtE,qBACa,cAAe,SAAQ,gBAAgB;IAElD,SAAS,CAAC,aAAa,EAAE,MAAM,CAAC;IAGhC,SAAS,CAAC,mBAAmB,EAAE,GAAG,CAAC;IAGnC,SAAS,CAAC,eAAe,EAAE,eAAe,CAAC;IAE9B,OAAO;IAMb,MAAM,IAAI,CAAC,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,OAAO,CAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,CAAC,YAAY,KAAK,IAAI;IAyDpF,KAAK,IAAI,CAAC,CAAC,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,OAAO,CAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,CAAC,YAAY,KAAK,IAAI,CAAC,GAAG,IAAI;CAGpG"}
|
package/lib/cjs/middlewares.js
CHANGED
|
@@ -56,7 +56,7 @@ let RbacMiddleware = class RbacMiddleware extends http_1.ServerMiddleware {
|
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
58
|
before() {
|
|
59
|
-
return async (req,
|
|
59
|
+
return async (req, res, next) => {
|
|
60
60
|
try {
|
|
61
61
|
let session = null;
|
|
62
62
|
if (req.cookies?.ssid) {
|
|
@@ -83,6 +83,20 @@ let RbacMiddleware = class RbacMiddleware extends http_1.ServerMiddleware {
|
|
|
83
83
|
req.storage.ActiveRole = sessionActiveRole && req.storage.User.Role.includes(sessionActiveRole)
|
|
84
84
|
? sessionActiveRole
|
|
85
85
|
: req.storage.User.Role?.[0];
|
|
86
|
+
// Sliding renewal: touch the session on every authenticated request.
|
|
87
|
+
// The store recomputes Expiration via the configured strategy and
|
|
88
|
+
// returns true only when it actually changed (sliding modes); under
|
|
89
|
+
// absolute expiration it returns false and performs no write, so we
|
|
90
|
+
// leave the cookie untouched.
|
|
91
|
+
const renewed = await this.SessionProvider.touch(session);
|
|
92
|
+
if (renewed) {
|
|
93
|
+
res.cookie('ssid', session.SessionId, {
|
|
94
|
+
signed: true,
|
|
95
|
+
httpOnly: true,
|
|
96
|
+
maxAge: (0, rbac_1.sessionCookieMaxAge)(session),
|
|
97
|
+
...this.SessionCookieConfig,
|
|
98
|
+
});
|
|
99
|
+
}
|
|
86
100
|
}
|
|
87
101
|
else {
|
|
88
102
|
req.storage.User = di_1.DI.resolve('RbacGuestUserFactory');
|
|
@@ -104,6 +118,10 @@ __decorate([
|
|
|
104
118
|
(0, configuration_1.Config)('http.cookie.secret'),
|
|
105
119
|
__metadata("design:type", String)
|
|
106
120
|
], RbacMiddleware.prototype, "CoockieSecret", void 0);
|
|
121
|
+
__decorate([
|
|
122
|
+
(0, configuration_1.Config)('rbac.session.cookie', {}),
|
|
123
|
+
__metadata("design:type", Object)
|
|
124
|
+
], RbacMiddleware.prototype, "SessionCookieConfig", void 0);
|
|
107
125
|
__decorate([
|
|
108
126
|
(0, di_1.Autoinject)(),
|
|
109
127
|
__metadata("design:type", rbac_1.SessionProvider)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"middlewares.js","sourceRoot":"","sources":["../../src/middlewares.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,
|
|
1
|
+
{"version":3,"file":"middlewares.js","sourceRoot":"","sources":["../../src/middlewares.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { BasePolicy, IController, IRoute, Request as sRequest } from '@spinajs/http';
|
|
2
2
|
/**
|
|
3
|
-
* Policy
|
|
3
|
+
* Policy that ALLOWS guest users through. Access is only refused when the
|
|
4
|
+
* request has no user/session at all, or when the guest account itself has
|
|
5
|
+
* been globally disabled (IsActive === false). Use BlockGuest for the opposite
|
|
6
|
+
* behavior (reject guests, require a real logged-in user).
|
|
4
7
|
*/
|
|
5
8
|
export declare class AllowGuest extends BasePolicy {
|
|
6
9
|
isEnabled(_action: IRoute, _instance: IController): boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AllowGuest.d.ts","sourceRoot":"","sources":["../../../src/policies/AllowGuest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,eAAe,CAAC;AAGrF
|
|
1
|
+
{"version":3,"file":"AllowGuest.d.ts","sourceRoot":"","sources":["../../../src/policies/AllowGuest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,eAAe,CAAC;AAGrF;;;;;GAKG;AACH,qBAAa,UAAW,SAAQ,UAAU;IACjC,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,WAAW,GAAG,OAAO;IAKrD,OAAO,CAAC,GAAG,EAAE,QAAQ;CAenC"}
|
|
@@ -4,7 +4,10 @@ exports.AllowGuest = void 0;
|
|
|
4
4
|
const http_1 = require("@spinajs/http");
|
|
5
5
|
const exceptions_1 = require("@spinajs/exceptions");
|
|
6
6
|
/**
|
|
7
|
-
* Policy
|
|
7
|
+
* Policy that ALLOWS guest users through. Access is only refused when the
|
|
8
|
+
* request has no user/session at all, or when the guest account itself has
|
|
9
|
+
* been globally disabled (IsActive === false). Use BlockGuest for the opposite
|
|
10
|
+
* behavior (reject guests, require a real logged-in user).
|
|
8
11
|
*/
|
|
9
12
|
class AllowGuest extends http_1.BasePolicy {
|
|
10
13
|
isEnabled(_action, _instance) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AllowGuest.js","sourceRoot":"","sources":["../../../src/policies/AllowGuest.ts"],"names":[],"mappings":";;;AAAA,wCAAqF;AACrF,oDAAsE;AAEtE
|
|
1
|
+
{"version":3,"file":"AllowGuest.js","sourceRoot":"","sources":["../../../src/policies/AllowGuest.ts"],"names":[],"mappings":";;;AAAA,wCAAqF;AACrF,oDAAsE;AAEtE;;;;;GAKG;AACH,MAAa,UAAW,SAAQ,iBAAU;IACjC,SAAS,CAAC,OAAe,EAAE,SAAsB;QACtD,0BAA0B;QAC1B,OAAO,IAAI,CAAC;IACd,CAAC;IAEM,KAAK,CAAC,OAAO,CAAC,GAAa;QAChC,IAAI,CAAC,GAAG,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;YACtC,MAAM,IAAI,iCAAoB,CAAC,oCAAoC,CAAC,CAAC;QACvE,CAAC;QAED,MAAM,IAAI,GAAG,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC;QAC9B,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,oDAAoD;YACpD,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACnB,MAAM,IAAI,sBAAS,CAAC,2BAA2B,CAAC,CAAC;YACnD,CAAC;QACH,CAAC;QAED,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC3B,CAAC;CACF;AArBD,gCAqBC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RbacPolicy.d.ts","sourceRoot":"","sources":["../../../src/policies/RbacPolicy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,EAAe,OAAO,IAAI,QAAQ,EAAE,MAAM,eAAe,CAAC;AAKlG,OAAO,
|
|
1
|
+
{"version":3,"file":"RbacPolicy.d.ts","sourceRoot":"","sources":["../../../src/policies/RbacPolicy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,EAAe,OAAO,IAAI,QAAQ,EAAE,MAAM,eAAe,CAAC;AAKlG,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAErC;;GAEG;AACH,qBAAa,UAAW,SAAQ,UAAU;IACxC,SAAS,CAAC,EAAE,EAAE,aAAa,CAAC;;IAQrB,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,WAAW,GAAG,OAAO;IAKrD,OAAO,CAAC,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW;CA4C1E;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,UAAU,CAG7G;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAQvG;AAED,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAQ3G"}
|
|
@@ -22,12 +22,28 @@ class RbacPolicy extends http_1.BasePolicy {
|
|
|
22
22
|
}
|
|
23
23
|
async execute(req, action, instance) {
|
|
24
24
|
const descriptor = Reflect.getMetadata(decorators_js_1.ACL_CONTROLLER_DESCRIPTOR, instance);
|
|
25
|
+
// Guard BEFORE dereferencing: RbacPolicy applied to a route/controller with
|
|
26
|
+
// no ACL metadata (e.g. @Policy(RbacPolicy) without @Resource/@Permission)
|
|
27
|
+
// must produce the descriptive server error, not a raw TypeError 500 from
|
|
28
|
+
// reading `.Permission` / `.Routes` off undefined.
|
|
29
|
+
if (!descriptor) {
|
|
30
|
+
throw new http_1.ServerError(`no route permission or resources assigned`);
|
|
31
|
+
}
|
|
25
32
|
let permission = descriptor.Permission ?? [];
|
|
26
33
|
if (descriptor.Routes.has(String(action.Method))) {
|
|
27
|
-
//
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
34
|
+
// SECURITY: PermissionScope must NEVER be taken from a client-supplied
|
|
35
|
+
// header. The ORM rbac query middleware uses PermissionScope to decide
|
|
36
|
+
// which own/any grant to enforce and, on a scope it does not recognise or
|
|
37
|
+
// that does not match the query type, it SKIPS row-level enforcement
|
|
38
|
+
// entirely. Letting the client set it therefore allowed any authenticated
|
|
39
|
+
// user holding only *Own grants to send `x-permission-scope: <anything>`
|
|
40
|
+
// and read/update/delete every row (owner-field WHERE restriction never
|
|
41
|
+
// applied). With no scope set, the middleware falls back to the correct
|
|
42
|
+
// query-derived scope (QUERY_TO_PERMISSION), which is the secure default.
|
|
43
|
+
//
|
|
44
|
+
// If a route ever needs an explicit scope it must be derived server-side
|
|
45
|
+
// from the route's declared permission, not from the request, e.g.:
|
|
46
|
+
// req.storage.PermissionScope = descriptor.Routes.get(String(action.Method))!.Permission?.[0];
|
|
31
47
|
permission = descriptor.Routes.get(String(action.Method)).Permission ?? [];
|
|
32
48
|
}
|
|
33
49
|
// check if route has its own permission
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RbacPolicy.js","sourceRoot":"","sources":["../../../src/policies/RbacPolicy.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"RbacPolicy.js","sourceRoot":"","sources":["../../../src/policies/RbacPolicy.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { BaseController, Ok } from '@spinajs/http';
|
|
2
|
-
import { AccessControl } from '@spinajs/rbac';
|
|
2
|
+
import { AccessControl, User as RbacUser } from '@spinajs/rbac';
|
|
3
3
|
import { IGrantsMap } from '../interfaces.js';
|
|
4
4
|
/**
|
|
5
5
|
* RBAC grants management.
|
|
@@ -10,11 +10,13 @@ export declare class GrantsController extends BaseController {
|
|
|
10
10
|
protected AC: AccessControl;
|
|
11
11
|
/**
|
|
12
12
|
* Get RBAC grants
|
|
13
|
-
* Returns the
|
|
13
|
+
* Returns the RBAC grants for the requesting user's own role(s) only — not
|
|
14
|
+
* the full cross-role matrix, which would leak the entire access-control
|
|
15
|
+
* policy to any authenticated user.
|
|
14
16
|
* @security cookieAuth
|
|
15
|
-
* @returns {IGrantsMap} RBAC grants map keyed by role name
|
|
17
|
+
* @returns {IGrantsMap} RBAC grants map keyed by the caller's role name(s)
|
|
16
18
|
* @response 401 Unauthorized — valid session cookie required
|
|
17
19
|
*/
|
|
18
|
-
getGrants(): Ok<IGrantsMap>;
|
|
20
|
+
getGrants(user: RbacUser): Ok<IGrantsMap>;
|
|
19
21
|
}
|
|
20
22
|
//# sourceMappingURL=GrantsController.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GrantsController.d.ts","sourceRoot":"","sources":["../../../src/controllers/GrantsController.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAiB,EAAE,EAAU,MAAM,eAAe,CAAC;AAC1E,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"GrantsController.d.ts","sourceRoot":"","sources":["../../../src/controllers/GrantsController.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAiB,EAAE,EAAU,MAAM,eAAe,CAAC;AAC1E,OAAO,EAAE,aAAa,EAAE,IAAI,IAAI,QAAQ,EAAE,MAAM,eAAe,CAAC;AAIhE,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE9C;;;;GAIG;AACH,qBAEa,gBAAiB,SAAQ,cAAc;IAGhD,SAAS,CAAC,EAAE,EAAE,aAAa,CAAC;IAE5B;;;;;;;;OAQG;IAEI,SAAS,CAAS,IAAI,EAAE,QAAQ,GAAG,EAAE,CAAC,UAAU,CAAC;CAc3D"}
|
|
@@ -7,10 +7,14 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
7
7
|
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
8
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
9
|
};
|
|
10
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
11
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
12
|
+
};
|
|
10
13
|
import { BaseController, BasePath, Get, Ok, Policy } from '@spinajs/http';
|
|
11
|
-
import { AccessControl } from '@spinajs/rbac';
|
|
14
|
+
import { AccessControl, User as RbacUser } from '@spinajs/rbac';
|
|
12
15
|
import { Autoinject } from '@spinajs/di';
|
|
13
16
|
import { AuthorizedPolicy } from '../policies/AuthorizedPolicy.js';
|
|
17
|
+
import { User } from '../decorators.js';
|
|
14
18
|
/**
|
|
15
19
|
* RBAC grants management.
|
|
16
20
|
* Provides access to the current RBAC access-control grants configuration.
|
|
@@ -19,13 +23,23 @@ import { AuthorizedPolicy } from '../policies/AuthorizedPolicy.js';
|
|
|
19
23
|
let GrantsController = class GrantsController extends BaseController {
|
|
20
24
|
/**
|
|
21
25
|
* Get RBAC grants
|
|
22
|
-
* Returns the
|
|
26
|
+
* Returns the RBAC grants for the requesting user's own role(s) only — not
|
|
27
|
+
* the full cross-role matrix, which would leak the entire access-control
|
|
28
|
+
* policy to any authenticated user.
|
|
23
29
|
* @security cookieAuth
|
|
24
|
-
* @returns {IGrantsMap} RBAC grants map keyed by role name
|
|
30
|
+
* @returns {IGrantsMap} RBAC grants map keyed by the caller's role name(s)
|
|
25
31
|
* @response 401 Unauthorized — valid session cookie required
|
|
26
32
|
*/
|
|
27
|
-
getGrants() {
|
|
28
|
-
|
|
33
|
+
getGrants(user) {
|
|
34
|
+
const allGrants = this.AC.getGrants();
|
|
35
|
+
const roles = user?.Role ?? [];
|
|
36
|
+
const filtered = {};
|
|
37
|
+
for (const role of roles) {
|
|
38
|
+
if (allGrants[role]) {
|
|
39
|
+
filtered[role] = allGrants[role];
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return new Ok(filtered);
|
|
29
43
|
}
|
|
30
44
|
};
|
|
31
45
|
__decorate([
|
|
@@ -34,8 +48,9 @@ __decorate([
|
|
|
34
48
|
], GrantsController.prototype, "AC", void 0);
|
|
35
49
|
__decorate([
|
|
36
50
|
Get(),
|
|
51
|
+
__param(0, User()),
|
|
37
52
|
__metadata("design:type", Function),
|
|
38
|
-
__metadata("design:paramtypes", []),
|
|
53
|
+
__metadata("design:paramtypes", [RbacUser]),
|
|
39
54
|
__metadata("design:returntype", Ok)
|
|
40
55
|
], GrantsController.prototype, "getGrants", null);
|
|
41
56
|
GrantsController = __decorate([
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GrantsController.js","sourceRoot":"","sources":["../../../src/controllers/GrantsController.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"GrantsController.js","sourceRoot":"","sources":["../../../src/controllers/GrantsController.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,GAAG,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAC1E,OAAO,EAAE,aAAa,EAAE,IAAI,IAAI,QAAQ,EAAE,MAAM,eAAe,CAAC;AAChE,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AACnE,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAGxC;;;;GAIG;AAGI,IAAM,gBAAgB,GAAtB,MAAM,gBAAiB,SAAQ,cAAc;IAKhD;;;;;;;;OAQG;IAEI,SAAS,CAAS,IAAc;QACnC,MAAM,SAAS,GAAG,IAAI,CAAC,EAAE,CAAC,SAAS,EAAgB,CAAC;QACpD,MAAM,KAAK,GAAG,IAAI,EAAE,IAAI,IAAI,EAAE,CAAC;QAE/B,MAAM,QAAQ,GAAe,EAAE,CAAC;QAChC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACvB,IAAI,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;gBAClB,QAAQ,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;YACrC,CAAC;QACL,CAAC;QAED,OAAO,IAAI,EAAE,CAAC,QAAQ,CAAC,CAAC;IAC5B,CAAC;CAEJ,CAAA;AA1Ba;IADT,UAAU,CAAC,aAAa,CAAC;8BACZ,aAAa;4CAAC;AAYrB;IADN,GAAG,EAAE;IACY,WAAA,IAAI,EAAE,CAAA;;qCAAO,QAAQ;oCAAG,EAAE;iDAY3C;AA3BQ,gBAAgB;IAF5B,QAAQ,CAAC,QAAQ,CAAC;IAClB,MAAM,CAAC,gBAAgB,CAAC;GACZ,gBAAgB,CA6B5B"}
|
package/lib/mjs/decorators.d.ts
CHANGED
|
@@ -10,7 +10,10 @@ export declare function setRbacMetadata(target: any, callback: (meta: IRbacDescr
|
|
|
10
10
|
* Assign resource for controller
|
|
11
11
|
*
|
|
12
12
|
* @param resource - name of resource
|
|
13
|
-
* @param permission - default permission
|
|
13
|
+
* @param permission - default permission. When omitted, the base controller's
|
|
14
|
+
* permission is kept ( `readOwn` if there is nothing to
|
|
15
|
+
* inherit ), so renaming a resource in a subclass does not
|
|
16
|
+
* silently change what it grants.
|
|
14
17
|
*/
|
|
15
18
|
export declare function Resource(resource: string, permission?: PermissionType[]): any;
|
|
16
19
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"decorators.d.ts","sourceRoot":"","sources":["../../src/decorators.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAkC,MAAM,iBAAiB,CAAC;AAGlF,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"decorators.d.ts","sourceRoot":"","sources":["../../src/decorators.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAkC,MAAM,iBAAiB,CAAC;AAGlF,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAI/C;;;GAGG;AACH,eAAO,MAAM,yBAAyB,eAAiD,CAAC;AAuFxF,wBAAgB,eAAe,CAAC,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,eAAe,KAAK,IAAI,QAMrF;AAYD;;;;;;;;GAQG;AACH,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,cAAc,EAAE,OAevE;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,UAAU,GAAE,cAAc,EAAgB,OAgBpE;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,0GAalC;AAED;;GAEG;AACH,wBAAgB,IAAI,0GAEnB;AAED;;GAEG;AACH,wBAAgB,WAAW,0GAE1B;AAED,wBAAgB,OAAO,0GAEtB"}
|