@nextage/era-lib 1.0.218 → 1.0.219
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/build/utils/auth-directive.d.ts +38 -0
- package/build/utils/auth-directive.d.ts.map +1 -0
- package/build/utils/auth-directive.js +54 -0
- package/build/utils/auth-directive.js.map +1 -0
- package/build/utils/express.d.ts +8 -2
- package/build/utils/express.d.ts.map +1 -1
- package/build/utils/express.js +14 -5
- package/build/utils/express.js.map +1 -1
- package/build/utils/index.d.ts +1 -0
- package/build/utils/index.d.ts.map +1 -1
- package/build/utils/index.js +1 -0
- package/build/utils/index.js.map +1 -1
- package/build/utils/scope.d.ts +63 -0
- package/build/utils/scope.d.ts.map +1 -1
- package/build/utils/scope.js +85 -0
- package/build/utils/scope.js.map +1 -1
- package/build/utils/tenancy.d.ts.map +1 -1
- package/build/utils/tenancy.js +4 -3
- package/build/utils/tenancy.js.map +1 -1
- package/build/utils/tenant.d.ts +25 -0
- package/build/utils/tenant.d.ts.map +1 -1
- package/build/utils/tenant.js +33 -0
- package/build/utils/tenant.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/*********************************************************************************************
|
|
2
|
+
* *
|
|
3
|
+
* The `@auth` directives of ERA - the framework directive, fed with the EFFECTIVE roles. *
|
|
4
|
+
* *
|
|
5
|
+
* The framework directive checks `user.hasRole(requires)`, that is `roles[]`: the roles of *
|
|
6
|
+
* the organization the user BELONGS to. On an organization reached through a grant those *
|
|
7
|
+
* are the wrong roles. These directives keep the framework's check - authenticated, active, *
|
|
8
|
+
* one of the required roles - and hand it the roles that actually hold, computed by the *
|
|
9
|
+
* single rule in `scope.ts` (`effectiveRoles`). *
|
|
10
|
+
* *
|
|
11
|
+
* Two of them, because the two kinds of service ask two different questions: *
|
|
12
|
+
* *
|
|
13
|
+
* tenantAuthDirective - a request that works inside ONE organization, the selected one *
|
|
14
|
+
* or the user's own (app-srv): the roles there decide. *
|
|
15
|
+
* reachableAuthDirective - a request whose operations NAME their organization in the *
|
|
16
|
+
* arguments (auth-srv): the directive cannot know it, so it only *
|
|
17
|
+
* asks whether the role holds SOMEWHERE, and the operation *
|
|
18
|
+
* decides on its own organization with `assertOrgRole`. *
|
|
19
|
+
* *
|
|
20
|
+
*********************************************************************************************/
|
|
21
|
+
/**
|
|
22
|
+
* `@auth` for a service whose requests work inside one organization: the roles that hold there.
|
|
23
|
+
*/
|
|
24
|
+
export declare const tenantAuthDirective: {
|
|
25
|
+
name: string;
|
|
26
|
+
typeDefs: string;
|
|
27
|
+
transformer: (schema: import("graphql").GraphQLSchema) => import("graphql").GraphQLSchema;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* `@auth` for a service whose operations name their organization: the roles that hold on at
|
|
31
|
+
* least one reachable organization. The operation must still decide on its own organization.
|
|
32
|
+
*/
|
|
33
|
+
export declare const reachableAuthDirective: {
|
|
34
|
+
name: string;
|
|
35
|
+
typeDefs: string;
|
|
36
|
+
transformer: (schema: import("graphql").GraphQLSchema) => import("graphql").GraphQLSchema;
|
|
37
|
+
};
|
|
38
|
+
//# sourceMappingURL=auth-directive.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-directive.d.ts","sourceRoot":"","sources":["../../src/utils/auth-directive.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;+FAmB+F;AA2B/F;;GAEG;AACH,eAAO,MAAM,mBAAmB;;;;CAE/B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,sBAAsB;;;;CAElC,CAAC"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*********************************************************************************************
|
|
3
|
+
* *
|
|
4
|
+
* The `@auth` directives of ERA - the framework directive, fed with the EFFECTIVE roles. *
|
|
5
|
+
* *
|
|
6
|
+
* The framework directive checks `user.hasRole(requires)`, that is `roles[]`: the roles of *
|
|
7
|
+
* the organization the user BELONGS to. On an organization reached through a grant those *
|
|
8
|
+
* are the wrong roles. These directives keep the framework's check - authenticated, active, *
|
|
9
|
+
* one of the required roles - and hand it the roles that actually hold, computed by the *
|
|
10
|
+
* single rule in `scope.ts` (`effectiveRoles`). *
|
|
11
|
+
* *
|
|
12
|
+
* Two of them, because the two kinds of service ask two different questions: *
|
|
13
|
+
* *
|
|
14
|
+
* tenantAuthDirective - a request that works inside ONE organization, the selected one *
|
|
15
|
+
* or the user's own (app-srv): the roles there decide. *
|
|
16
|
+
* reachableAuthDirective - a request whose operations NAME their organization in the *
|
|
17
|
+
* arguments (auth-srv): the directive cannot know it, so it only *
|
|
18
|
+
* asks whether the role holds SOMEWHERE, and the operation *
|
|
19
|
+
* decides on its own organization with `assertOrgRole`. *
|
|
20
|
+
* *
|
|
21
|
+
*********************************************************************************************/
|
|
22
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
23
|
+
exports.reachableAuthDirective = exports.tenantAuthDirective = void 0;
|
|
24
|
+
const nx_frame_be_1 = require("@nextage/nx-frame-be");
|
|
25
|
+
const scope_1 = require("./scope");
|
|
26
|
+
const tenant_1 = require("./tenant");
|
|
27
|
+
/**
|
|
28
|
+
* A stand-in of the request user that answers `hasRole` with the given roles.
|
|
29
|
+
*
|
|
30
|
+
* The directive reads `id`, `active` and `hasRole` and nothing else; the user itself is left
|
|
31
|
+
* untouched, so every later check still sees its memberships, grants and roles.
|
|
32
|
+
*
|
|
33
|
+
* @param user the authenticated user
|
|
34
|
+
* @param roles the roles that hold for this check
|
|
35
|
+
* @returns the user as the directive must see it
|
|
36
|
+
*/
|
|
37
|
+
function withRoles(user, roles) {
|
|
38
|
+
return {
|
|
39
|
+
id: user.id,
|
|
40
|
+
active: user.active,
|
|
41
|
+
roles,
|
|
42
|
+
hasRole: (role) => (Array.isArray(role) ? role : [role]).some(r => roles.includes(r))
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* `@auth` for a service whose requests work inside one organization: the roles that hold there.
|
|
47
|
+
*/
|
|
48
|
+
exports.tenantAuthDirective = (0, nx_frame_be_1.createAuthDirective)('auth', (context) => context.user ? withRoles(context.user, (0, tenant_1.tenantRoles)(context)) : null);
|
|
49
|
+
/**
|
|
50
|
+
* `@auth` for a service whose operations name their organization: the roles that hold on at
|
|
51
|
+
* least one reachable organization. The operation must still decide on its own organization.
|
|
52
|
+
*/
|
|
53
|
+
exports.reachableAuthDirective = (0, nx_frame_be_1.createAuthDirective)('auth', (context) => context.user ? withRoles(context.user, (0, scope_1.reachableRoles)(context.user)) : null);
|
|
54
|
+
//# sourceMappingURL=auth-directive.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-directive.js","sourceRoot":"","sources":["../../src/utils/auth-directive.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;+FAmB+F;;;AAE/F,sDAAgF;AAEhF,mCAAmE;AACnE,qCAAoE;AAEpE;;;;;;;;;GASG;AACH,SAAS,SAAS,CAAC,IAAc,EAAE,KAAe;IAEhD,OAAO;QACL,EAAE,EAAO,IAAI,CAAC,EAAE;QAChB,MAAM,EAAG,IAAI,CAAC,MAAM;QACpB,KAAK;QACL,OAAO,EAAE,CAAC,IAAuB,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;KAC7F,CAAC;AAChB,CAAC;AAED;;GAEG;AACU,QAAA,mBAAmB,GAAG,IAAA,iCAAmB,EAAC,MAAM,EAAE,CAAC,OAAkB,EAAE,EAAE,CACpF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,EAAE,IAAA,oBAAW,EAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CACpE,CAAC;AAEF;;;GAGG;AACU,QAAA,sBAAsB,GAAG,IAAA,iCAAmB,EAAC,MAAM,EAAE,CAAC,OAAkB,EAAE,EAAE,CACvF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,EAAE,IAAA,sBAAc,EAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAC5E,CAAC"}
|
package/build/utils/express.d.ts
CHANGED
|
@@ -49,9 +49,15 @@ export declare function sendErrorResponse(res: Response, err: any): void;
|
|
|
49
49
|
*/
|
|
50
50
|
export declare function allowMethods(methods?: string[], message?: string): Handler;
|
|
51
51
|
/**
|
|
52
|
+
* Authorizes a REST route: an authenticated user and, when `roles` is given, the roles it needs.
|
|
52
53
|
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
54
|
+
* The roles are the ones of the REQUEST (`tenantRoles`): those that hold on the organization the
|
|
55
|
+
* request operates on, as on the GraphQL side - a grant decides on the organization it grants,
|
|
56
|
+
* and the membership role never travels to another one.
|
|
57
|
+
*
|
|
58
|
+
* @param roles the roles the route requires, when any
|
|
59
|
+
* @param condition `'&&'` for all of them, anything else for any of them
|
|
60
|
+
* @returns the Express middleware
|
|
55
61
|
*/
|
|
56
62
|
export declare function authHandler(roles?: string[], condition?: string): (req: Request, res: Response, next: NextFunction) => void;
|
|
57
63
|
//# sourceMappingURL=express.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"express.d.ts","sourceRoot":"","sources":["../../src/utils/express.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAEnE,OAAO,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,EAAE,MAAe,mBAAmB,CAAC;AAC7E,OAAO,EAAE,iBAAiB,EAAE,MAA6B,0CAA0C,CAAC;
|
|
1
|
+
{"version":3,"file":"express.d.ts","sourceRoot":"","sources":["../../src/utils/express.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAEnE,OAAO,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,EAAE,MAAe,mBAAmB,CAAC;AAC7E,OAAO,EAAE,iBAAiB,EAAE,MAA6B,0CAA0C,CAAC;AAKpG;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,CAAC,iBAAiB,CAAC,EAAE,cAAc,IAAI,KAAK,MAAM,CAAC,eAAe,CAAC,EAAE,KAAK,OAAO,4BAAQ,IAE5H,KAAK,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,UAYxD;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,QAAQ,EAAE,MAAM,GAAE,MAAY,EAAE,OAAO,GAAE,MAAW,QAMzF;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,GAAG,GAAG,IAAI,CAoB/D;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,OAAO,GAAE,MAAM,EAAO,EAAE,OAAO,GAAE,MAA6B,GAAG,OAAO,CAcpG;AAoBD;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,EAAE,SAAS,CAAC,EAAE,MAAM,IAEtD,KAAK,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,UAmCxD"}
|
package/build/utils/express.js
CHANGED
|
@@ -12,6 +12,7 @@ const http_errors_1 = __importDefault(require("http-errors"));
|
|
|
12
12
|
const express_validator_1 = require("express-validator");
|
|
13
13
|
const nx_frame_be_1 = require("@nextage/nx-frame-be");
|
|
14
14
|
const constants_1 = require("../constants");
|
|
15
|
+
const tenant_1 = require("./tenant");
|
|
15
16
|
/**
|
|
16
17
|
*
|
|
17
18
|
* @param schema
|
|
@@ -114,13 +115,20 @@ function normalizeAllowedMethods(methods) {
|
|
|
114
115
|
.map(method => method.toUpperCase());
|
|
115
116
|
}
|
|
116
117
|
/**
|
|
118
|
+
* Authorizes a REST route: an authenticated user and, when `roles` is given, the roles it needs.
|
|
117
119
|
*
|
|
118
|
-
*
|
|
119
|
-
*
|
|
120
|
+
* The roles are the ones of the REQUEST (`tenantRoles`): those that hold on the organization the
|
|
121
|
+
* request operates on, as on the GraphQL side - a grant decides on the organization it grants,
|
|
122
|
+
* and the membership role never travels to another one.
|
|
123
|
+
*
|
|
124
|
+
* @param roles the roles the route requires, when any
|
|
125
|
+
* @param condition `'&&'` for all of them, anything else for any of them
|
|
126
|
+
* @returns the Express middleware
|
|
120
127
|
*/
|
|
121
128
|
function authHandler(roles, condition) {
|
|
122
129
|
return (req, res, next) => {
|
|
123
|
-
const
|
|
130
|
+
const context = (0, nx_frame_be_1.getAttr)(req, 'context');
|
|
131
|
+
const user = context?.user;
|
|
124
132
|
// On rejection we terminate the chain by WRITING the response body and returning.
|
|
125
133
|
// We must NOT also `next(err)`/`throw`: the framework error classes carry the
|
|
126
134
|
// code in `extensions.code` (GraphQL), not `.status`, so the REST error handler
|
|
@@ -130,14 +138,15 @@ function authHandler(roles, condition) {
|
|
|
130
138
|
if (!user)
|
|
131
139
|
return sendJSONResponse(res, 401, constants_1.RES_CODE.AUTH_REQUIRED);
|
|
132
140
|
if (roles) {
|
|
141
|
+
const held = (0, tenant_1.tenantRoles)(context);
|
|
133
142
|
let hasRoles = true;
|
|
134
143
|
switch (condition) {
|
|
135
144
|
case '&&':
|
|
136
|
-
hasRoles = roles.every(role =>
|
|
145
|
+
hasRoles = roles.every(role => held.includes(role));
|
|
137
146
|
break;
|
|
138
147
|
case '||':
|
|
139
148
|
default:
|
|
140
|
-
hasRoles = roles.some(role =>
|
|
149
|
+
hasRoles = roles.some(role => held.includes(role));
|
|
141
150
|
break;
|
|
142
151
|
}
|
|
143
152
|
if (!hasRoles)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"express.js","sourceRoot":"","sources":["../../src/utils/express.ts"],"names":[],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"express.js","sourceRoot":"","sources":["../../src/utils/express.ts"],"names":[],"mappings":"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"}
|
package/build/utils/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,qBAAqB,CAAC;AACpC,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC;AAC1B,cAAc,UAAU,CAAC;AACzB,cAAc,OAAO,CAAC;AACtB,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,SAAS,CAAC;AACxB,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,WAAW,CAAC;AAC1B,cAAc,UAAU,CAAC;AACzB,cAAc,qBAAqB,CAAC;AACpC,cAAc,2BAA2B,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,cAAc,UAAU,CAAC;AACzB,cAAc,qBAAqB,CAAC;AACpC,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC;AAC1B,cAAc,UAAU,CAAC;AACzB,cAAc,OAAO,CAAC;AACtB,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,SAAS,CAAC;AACxB,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,WAAW,CAAC;AAC1B,cAAc,UAAU,CAAC;AACzB,cAAc,qBAAqB,CAAC;AACpC,cAAc,2BAA2B,CAAC"}
|
package/build/utils/index.js
CHANGED
|
@@ -14,6 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./auth-directive"), exports);
|
|
17
18
|
__exportStar(require("./claims"), exports);
|
|
18
19
|
__exportStar(require("./claims.interfaces"), exports);
|
|
19
20
|
__exportStar(require("./domain"), exports);
|
package/build/utils/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,2CAAyB;AACzB,sDAAoC;AACpC,2CAAyB;AACzB,4CAA0B;AAC1B,2CAAyB;AACzB,wCAAsB;AACtB,kDAAgC;AAChC,mDAAiC;AACjC,0CAAwB;AACxB,qDAAmC;AACnC,kDAAgC;AAChC,4CAA0B;AAC1B,2CAAyB;AACzB,sDAAoC;AACpC,4DAA0C"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,mDAAiC;AACjC,2CAAyB;AACzB,sDAAoC;AACpC,2CAAyB;AACzB,4CAA0B;AAC1B,2CAAyB;AACzB,wCAAsB;AACtB,kDAAgC;AAChC,mDAAiC;AACjC,0CAAwB;AACxB,qDAAmC;AACnC,kDAAgC;AAChC,4CAA0B;AAC1B,2CAAyB;AACzB,sDAAoC;AACpC,4DAA0C"}
|
package/build/utils/scope.d.ts
CHANGED
|
@@ -50,6 +50,69 @@ export declare function resolveOrgScope(user?: BaseUser, orgId?: string): OrgSco
|
|
|
50
50
|
* @throws `AppError('messages.authorization.missingRole')` when out of scope
|
|
51
51
|
*/
|
|
52
52
|
export declare function assertOrgScope(user?: BaseUser, orgId?: string): OrgScope;
|
|
53
|
+
/**
|
|
54
|
+
* The roles that apply to `user` while operating on the organization `orgId`.
|
|
55
|
+
*
|
|
56
|
+
* THE single definition of the EFFECTIVE ORGANIZATION ROLE. A user holds one organization-tier
|
|
57
|
+
* role in `roles[]`, and that role belongs to the organization they are a MEMBER of; a grant
|
|
58
|
+
* carries its own role, which belongs to the granted organization alone. Reading `roles[]` on a
|
|
59
|
+
* granted organization - what every check did - handed the membership role to an organization
|
|
60
|
+
* that never conferred it: a manager granted read-only access wrote and managed, and a member
|
|
61
|
+
* granted management could not.
|
|
62
|
+
*
|
|
63
|
+
* Built on `resolveOrgScope`, so the answer follows the same tiers:
|
|
64
|
+
*
|
|
65
|
+
* PROVIDER (cross-tenant role) -> the user's roles, unchanged: the level reaches every tenant
|
|
66
|
+
* MEMBER of `orgId` -> the user's roles, unchanged: the membership role is theirs
|
|
67
|
+
* GRANTED on `orgId` -> the roles OUTSIDE the organization tier, plus the grant's role
|
|
68
|
+
* unreachable `orgId` -> the roles outside the organization tier, and no other
|
|
69
|
+
*
|
|
70
|
+
* System and application roles (`ADMIN`, `APP_CONFIG`, ...) are never narrowed: they are not a
|
|
71
|
+
* role on an organization, and they follow the user everywhere.
|
|
72
|
+
*
|
|
73
|
+
* @param user the authenticated user (`NxContext.user`)
|
|
74
|
+
* @param orgId the organization being operated on
|
|
75
|
+
* @returns the roles that hold on that organization
|
|
76
|
+
*/
|
|
77
|
+
export declare function effectiveRoles(user?: BaseUser, orgId?: string): string[];
|
|
78
|
+
/**
|
|
79
|
+
* Whether `user` reaches the organization `orgId` AND holds one of `roles` there.
|
|
80
|
+
*
|
|
81
|
+
* The question every per-organization capability asks - "may this user do THIS on THAT
|
|
82
|
+
* organization?" - answered with the effective role, never with `roles[]`.
|
|
83
|
+
*
|
|
84
|
+
* @param user the authenticated user (`NxContext.user`)
|
|
85
|
+
* @param orgId the organization the operation targets
|
|
86
|
+
* @param roles the roles that grant the capability (any of them is enough)
|
|
87
|
+
* @returns `true` when the organization is reachable and one of the roles holds there
|
|
88
|
+
*/
|
|
89
|
+
export declare function hasOrgRole(user: BaseUser | undefined, orgId: string | undefined, roles: readonly string[]): boolean;
|
|
90
|
+
/**
|
|
91
|
+
* Throwing variant of `hasOrgRole`, for the call sites that must simply deny.
|
|
92
|
+
*
|
|
93
|
+
* The error is the one of `assertOrgScope`, for the same reason: an organization out of reach,
|
|
94
|
+
* one that does not exist and one where the role does not hold are not told apart.
|
|
95
|
+
*
|
|
96
|
+
* @param user the authenticated user (`NxContext.user`)
|
|
97
|
+
* @param orgId the organization the operation targets
|
|
98
|
+
* @param roles the roles that grant the capability
|
|
99
|
+
* @returns the scope through which the user reaches the organization
|
|
100
|
+
* @throws `AppError('messages.authorization.missingRole')` when the capability does not hold
|
|
101
|
+
*/
|
|
102
|
+
export declare function assertOrgRole(user: BaseUser | undefined, orgId: string | undefined, roles: readonly string[]): OrgScope;
|
|
103
|
+
/**
|
|
104
|
+
* Every role `user` holds on AT LEAST ONE organization they reach.
|
|
105
|
+
*
|
|
106
|
+
* For a gate that runs before the organization of the operation is known - the `@auth`
|
|
107
|
+
* directive of a service whose operations name their organization in the arguments. It is the
|
|
108
|
+
* union of the effective roles over the reachable organizations, so it answers "could this user
|
|
109
|
+
* be allowed somewhere?"; the operation itself must then decide on its own organization with
|
|
110
|
+
* `hasOrgRole`/`assertOrgRole`.
|
|
111
|
+
*
|
|
112
|
+
* @param user the authenticated user (`NxContext.user`)
|
|
113
|
+
* @returns the user's roles plus the roles of their grants
|
|
114
|
+
*/
|
|
115
|
+
export declare function reachableRoles(user?: BaseUser): string[];
|
|
53
116
|
/**
|
|
54
117
|
* Every organization the user reaches, for the LIST case.
|
|
55
118
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scope.d.ts","sourceRoot":"","sources":["../../src/utils/scope.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;+FAa+F;AAE/F,OAAO,EAAY,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAM1D,OAAO,EAAE,QAAQ,EAAE,MAAgB,oBAAoB,CAAC;AAExD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,eAAe,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CAqBhF;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,QAAQ,CAQxE;AAcD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,eAAe,CAAC,IAAI,CAAC,EAAE,QAAQ,GAAG,MAAM,EAAE,GAAG,SAAS,CAcrE"}
|
|
1
|
+
{"version":3,"file":"scope.d.ts","sourceRoot":"","sources":["../../src/utils/scope.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;+FAa+F;AAE/F,OAAO,EAAY,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAM1D,OAAO,EAAE,QAAQ,EAAE,MAAgB,oBAAoB,CAAC;AAExD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,eAAe,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CAqBhF;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,QAAQ,CAQxE;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,cAAc,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAWxE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,QAAQ,GAAG,SAAS,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAGnH;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,QAAQ,GAAG,SAAS,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,QAAQ,CAQvH;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAAC,IAAI,CAAC,EAAE,QAAQ,GAAG,MAAM,EAAE,CAOxD;AAcD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,eAAe,CAAC,IAAI,CAAC,EAAE,QAAQ,GAAG,MAAM,EAAE,GAAG,SAAS,CAcrE"}
|
package/build/utils/scope.js
CHANGED
|
@@ -16,6 +16,10 @@
|
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
exports.resolveOrgScope = resolveOrgScope;
|
|
18
18
|
exports.assertOrgScope = assertOrgScope;
|
|
19
|
+
exports.effectiveRoles = effectiveRoles;
|
|
20
|
+
exports.hasOrgRole = hasOrgRole;
|
|
21
|
+
exports.assertOrgRole = assertOrgRole;
|
|
22
|
+
exports.reachableRoles = reachableRoles;
|
|
19
23
|
exports.reachableOrgIds = reachableOrgIds;
|
|
20
24
|
const nx_frame_be_1 = require("@nextage/nx-frame-be");
|
|
21
25
|
const constants_1 = require("../constants");
|
|
@@ -77,6 +81,87 @@ function assertOrgScope(user, orgId) {
|
|
|
77
81
|
throw new nx_frame_be_1.AppError('messages.authorization.missingRole');
|
|
78
82
|
return scope;
|
|
79
83
|
}
|
|
84
|
+
/**
|
|
85
|
+
* The roles that apply to `user` while operating on the organization `orgId`.
|
|
86
|
+
*
|
|
87
|
+
* THE single definition of the EFFECTIVE ORGANIZATION ROLE. A user holds one organization-tier
|
|
88
|
+
* role in `roles[]`, and that role belongs to the organization they are a MEMBER of; a grant
|
|
89
|
+
* carries its own role, which belongs to the granted organization alone. Reading `roles[]` on a
|
|
90
|
+
* granted organization - what every check did - handed the membership role to an organization
|
|
91
|
+
* that never conferred it: a manager granted read-only access wrote and managed, and a member
|
|
92
|
+
* granted management could not.
|
|
93
|
+
*
|
|
94
|
+
* Built on `resolveOrgScope`, so the answer follows the same tiers:
|
|
95
|
+
*
|
|
96
|
+
* PROVIDER (cross-tenant role) -> the user's roles, unchanged: the level reaches every tenant
|
|
97
|
+
* MEMBER of `orgId` -> the user's roles, unchanged: the membership role is theirs
|
|
98
|
+
* GRANTED on `orgId` -> the roles OUTSIDE the organization tier, plus the grant's role
|
|
99
|
+
* unreachable `orgId` -> the roles outside the organization tier, and no other
|
|
100
|
+
*
|
|
101
|
+
* System and application roles (`ADMIN`, `APP_CONFIG`, ...) are never narrowed: they are not a
|
|
102
|
+
* role on an organization, and they follow the user everywhere.
|
|
103
|
+
*
|
|
104
|
+
* @param user the authenticated user (`NxContext.user`)
|
|
105
|
+
* @param orgId the organization being operated on
|
|
106
|
+
* @returns the roles that hold on that organization
|
|
107
|
+
*/
|
|
108
|
+
function effectiveRoles(user, orgId) {
|
|
109
|
+
const roles = user?.roles ?? [];
|
|
110
|
+
const scope = resolveOrgScope(user, orgId);
|
|
111
|
+
if (scope?.tier === enums_1.OrgScopeTier.PROVIDER || scope?.tier === enums_1.OrgScopeTier.MEMBER)
|
|
112
|
+
return [...roles];
|
|
113
|
+
const outsideOrgTier = roles.filter(r => !constants_2.ORG_MEMBER_ROLES.includes(r));
|
|
114
|
+
return scope?.role ? [...outsideOrgTier, scope.role] : outsideOrgTier;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Whether `user` reaches the organization `orgId` AND holds one of `roles` there.
|
|
118
|
+
*
|
|
119
|
+
* The question every per-organization capability asks - "may this user do THIS on THAT
|
|
120
|
+
* organization?" - answered with the effective role, never with `roles[]`.
|
|
121
|
+
*
|
|
122
|
+
* @param user the authenticated user (`NxContext.user`)
|
|
123
|
+
* @param orgId the organization the operation targets
|
|
124
|
+
* @param roles the roles that grant the capability (any of them is enough)
|
|
125
|
+
* @returns `true` when the organization is reachable and one of the roles holds there
|
|
126
|
+
*/
|
|
127
|
+
function hasOrgRole(user, orgId, roles) {
|
|
128
|
+
return !!resolveOrgScope(user, orgId) && effectiveRoles(user, orgId).some(r => roles.includes(r));
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Throwing variant of `hasOrgRole`, for the call sites that must simply deny.
|
|
132
|
+
*
|
|
133
|
+
* The error is the one of `assertOrgScope`, for the same reason: an organization out of reach,
|
|
134
|
+
* one that does not exist and one where the role does not hold are not told apart.
|
|
135
|
+
*
|
|
136
|
+
* @param user the authenticated user (`NxContext.user`)
|
|
137
|
+
* @param orgId the organization the operation targets
|
|
138
|
+
* @param roles the roles that grant the capability
|
|
139
|
+
* @returns the scope through which the user reaches the organization
|
|
140
|
+
* @throws `AppError('messages.authorization.missingRole')` when the capability does not hold
|
|
141
|
+
*/
|
|
142
|
+
function assertOrgRole(user, orgId, roles) {
|
|
143
|
+
const scope = assertOrgScope(user, orgId);
|
|
144
|
+
if (!hasOrgRole(user, orgId, roles))
|
|
145
|
+
throw new nx_frame_be_1.AppError('messages.authorization.missingRole');
|
|
146
|
+
return scope;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Every role `user` holds on AT LEAST ONE organization they reach.
|
|
150
|
+
*
|
|
151
|
+
* For a gate that runs before the organization of the operation is known - the `@auth`
|
|
152
|
+
* directive of a service whose operations name their organization in the arguments. It is the
|
|
153
|
+
* union of the effective roles over the reachable organizations, so it answers "could this user
|
|
154
|
+
* be allowed somewhere?"; the operation itself must then decide on its own organization with
|
|
155
|
+
* `hasOrgRole`/`assertOrgRole`.
|
|
156
|
+
*
|
|
157
|
+
* @param user the authenticated user (`NxContext.user`)
|
|
158
|
+
* @returns the user's roles plus the roles of their grants
|
|
159
|
+
*/
|
|
160
|
+
function reachableRoles(user) {
|
|
161
|
+
const roles = new Set(user?.roles ?? []);
|
|
162
|
+
user?.grants?.forEach(g => g.id && g.role && roles.add(g.role));
|
|
163
|
+
return [...roles];
|
|
164
|
+
}
|
|
80
165
|
/**
|
|
81
166
|
* The highest organization-tier role the user holds, if any.
|
|
82
167
|
*
|
package/build/utils/scope.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scope.js","sourceRoot":"","sources":["../../src/utils/scope.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;+FAa+F;;AAiC/F,0CAqBC;AAaD,wCAQC;AAmCD,0CAcC;
|
|
1
|
+
{"version":3,"file":"scope.js","sourceRoot":"","sources":["../../src/utils/scope.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tenancy.d.ts","sourceRoot":"","sources":["../../src/utils/tenancy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;+FAyB+F;AAI/F,OAAO,EAAe,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAOpE;;;;;;;;;;GAUG;AACH,eAAO,MAAM,gBAAgB,eAAe,CAAC;AAE7C;;;;;;GAMG;AACH,eAAO,MAAM,UAAU,EAAE,
|
|
1
|
+
{"version":3,"file":"tenancy.d.ts","sourceRoot":"","sources":["../../src/utils/tenancy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;+FAyB+F;AAI/F,OAAO,EAAe,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAOpE;;;;;;;;;;GAUG;AACH,eAAO,MAAM,gBAAgB,eAAe,CAAC;AAE7C;;;;;;GAMG;AACH,eAAO,MAAM,UAAU,EAAE,eAiFxB,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,WAAW,IAAI,IAAI,CAGlC"}
|
package/build/utils/tenancy.js
CHANGED
|
@@ -98,8 +98,9 @@ exports.eraTenancy = {
|
|
|
98
98
|
return exports.SHARED_TENANT_ID;
|
|
99
99
|
}
|
|
100
100
|
// Writing a tenant's own addition is CONFIGURING the organization, not entering data
|
|
101
|
-
// into it: `ORG_EDITOR` and `ORG_MEMBER` use the catalogue, they do not shape it.
|
|
102
|
-
|
|
101
|
+
// into it: `ORG_EDITOR` and `ORG_MEMBER` use the catalogue, they do not shape it. The
|
|
102
|
+
// role is the one of the REQUEST's organization, so a grant decides on what it grants.
|
|
103
|
+
if (!(0, tenant_1.hasTenantRole)(context, constants_2.TENANT_CONFIG_WRITE_ROLES))
|
|
103
104
|
throw new nx_frame_be_3.AppError('messages.authorization.accessDenied');
|
|
104
105
|
}
|
|
105
106
|
return (0, tenant_1.resolveTenant)(context.user, context.orgId);
|
|
@@ -113,7 +114,7 @@ exports.eraTenancy = {
|
|
|
113
114
|
canWrite(mode, current, context) {
|
|
114
115
|
if (current === exports.SHARED_TENANT_ID)
|
|
115
116
|
return !!context.user?.hasRole?.(constants_1.SYSTEM_ROLES);
|
|
116
|
-
if (mode === nx_frame_be_2.TenancyMode.shared && !
|
|
117
|
+
if (mode === nx_frame_be_2.TenancyMode.shared && !(0, tenant_1.hasTenantRole)(context, constants_2.TENANT_CONFIG_WRITE_ROLES))
|
|
117
118
|
return false;
|
|
118
119
|
return current === (0, tenant_1.resolveTenant)(context.user, context.orgId);
|
|
119
120
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tenancy.js","sourceRoot":"","sources":["../../src/utils/tenancy.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;+FAyB+F;;;
|
|
1
|
+
{"version":3,"file":"tenancy.js","sourceRoot":"","sources":["../../src/utils/tenancy.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;+FAyB+F;;;AAyH/F,kCAGC;AA1HD,sDAAoE;AAEpE,sDAAoE;AAEpE,sDAAoE;AACpE,4CAA4D;AAC5D,4CAA4D;AAC5D,qCAAwD;AAExD;;;;;;;;;;GAUG;AACU,QAAA,gBAAgB,GAAG,YAAY,CAAC;AAE7C;;;;;;GAMG;AACU,QAAA,UAAU,GAAoB;IAEzC,KAAK,EAAE,UAAU;IAEjB;;;;;OAKG;IACH,IAAI,CAAC,IAAiB,EAAE,OAAkB;QAExC,MAAM,MAAM,GAAG,IAAA,sBAAa,EAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;QAE1D,OAAO,CAAC,IAAI,KAAK,yBAAW,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,MAAM,EAAE,wBAAgB,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;IACtF,CAAC;IAED;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACH,KAAK,CAAC,IAAiB,EAAE,SAAkB,EAAE,OAAkB;QAE7D,IAAI,IAAI,KAAK,yBAAW,CAAC,MAAM,EAAE,CAAC;YAEhC,MAAM,QAAQ,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,EAAE,CAAC,wBAAY,CAAC,CAAC;YAEzD,IAAI,SAAS,KAAK,wBAAgB,IAAI,CAAC,QAAQ,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;gBAEnE,IAAI,CAAC,QAAQ;oBACX,MAAM,IAAI,sBAAQ,CAAC,qCAAqC,CAAC,CAAC;gBAE5D,OAAO,wBAAgB,CAAC;YAC1B,CAAC;YAED,qFAAqF;YACrF,sFAAsF;YACtF,uFAAuF;YACvF,IAAI,CAAC,IAAA,sBAAa,EAAC,OAAO,EAAE,qCAAyB,CAAC;gBACpD,MAAM,IAAI,sBAAQ,CAAC,qCAAqC,CAAC,CAAC;QAC9D,CAAC;QAED,OAAO,IAAA,sBAAa,EAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;IACpD,CAAC;IAED;;;;;OAKG;IACH,QAAQ,CAAC,IAAiB,EAAE,OAAgB,EAAE,OAAkB;QAE9D,IAAI,OAAO,KAAK,wBAAgB;YAC9B,OAAO,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,EAAE,CAAC,wBAAY,CAAC,CAAC;QAEjD,IAAI,IAAI,KAAK,yBAAW,CAAC,MAAM,IAAI,CAAC,IAAA,sBAAa,EAAC,OAAO,EAAE,qCAAyB,CAAC;YACnF,OAAO,KAAK,CAAC;QAEf,OAAO,OAAO,KAAK,IAAA,sBAAa,EAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;IAChE,CAAC;CACF,CAAC;AAEF;;;;;;GAMG;AACH,SAAgB,WAAW;IAEzB,iBAAG,CAAC,OAAO,GAAG,kBAAU,CAAC;AAC3B,CAAC"}
|
package/build/utils/tenant.d.ts
CHANGED
|
@@ -45,6 +45,31 @@ import { ExistenceCheckModel, ScopedReadModel } from './tenant.interfaces';
|
|
|
45
45
|
* @throws `AppError('messages.forbidden')` when the selection is out of reach
|
|
46
46
|
*/
|
|
47
47
|
export declare function resolveTenant(user?: BaseUser, orgId?: string): string;
|
|
48
|
+
/**
|
|
49
|
+
* The roles that apply to a request, on the organization it operates on.
|
|
50
|
+
*
|
|
51
|
+
* A request works inside ONE organization: the one it selected, or the user's own when it
|
|
52
|
+
* selected none - the rule of `resolveTenant`. Its roles are the effective roles there
|
|
53
|
+
* (`effectiveRoles`), so on an organization reached through a grant the grant's role decides,
|
|
54
|
+
* and nowhere does the membership role travel to an organization that did not confer it.
|
|
55
|
+
*
|
|
56
|
+
* It does NOT throw where `resolveTenant` does: an unreachable selection simply holds no
|
|
57
|
+
* organization role here, so a role check fails closed, and the scoping refuses the selection
|
|
58
|
+
* itself the moment a query runs. A user without any organization has nothing to narrow and
|
|
59
|
+
* keeps their roles.
|
|
60
|
+
*
|
|
61
|
+
* @param context the request context (authenticated user + selected organization)
|
|
62
|
+
* @returns the roles that hold on the organization of the request
|
|
63
|
+
*/
|
|
64
|
+
export declare function tenantRoles(context?: NxContext): string[];
|
|
65
|
+
/**
|
|
66
|
+
* Whether one of `roles` holds for the request, on the organization it operates on.
|
|
67
|
+
*
|
|
68
|
+
* @param context the request context
|
|
69
|
+
* @param roles the roles that grant the capability (any of them is enough)
|
|
70
|
+
* @returns `true` when one of them is among the roles of the request
|
|
71
|
+
*/
|
|
72
|
+
export declare function hasTenantRole(context: NxContext, roles: readonly string[]): boolean;
|
|
48
73
|
/**
|
|
49
74
|
* Forces `tenantId` on a payload or on a query filter, from the resolved organization.
|
|
50
75
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tenant.d.ts","sourceRoot":"","sources":["../../src/utils/tenant.ts"],"names":[],"mappings":"AAAA;;;;;;;;;+FAS+F;AAE/F,OAAO,EAAY,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAI/E,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAS,qBAAqB,CAAC;AAE9E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,wBAAgB,aAAa,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAkBrE;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,GAAE,SAAc,GAAG,IAAI,CAGvE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,SAAS,CAAC,IAAI,CAAC,EAAE,QAAQ,GAAG,MAAM,CAMjD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,wBAAsB,iBAAiB,CAAC,KAAK,EAAE,eAAe,EAAE,EAAE,EAAE,MAAM,EAAE,OAAO,GAAE,SAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAMpH;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkDG;AACH,wBAAsB,iBAAiB,CAAC,KAAK,EAAE,mBAAmB,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CASpG;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,uBAAuB,CAAC,KAAK,EAAE,mBAAmB,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAIvG"}
|
|
1
|
+
{"version":3,"file":"tenant.d.ts","sourceRoot":"","sources":["../../src/utils/tenant.ts"],"names":[],"mappings":"AAAA;;;;;;;;;+FAS+F;AAE/F,OAAO,EAAY,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAI/E,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAS,qBAAqB,CAAC;AAE9E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,wBAAgB,aAAa,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAkBrE;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,WAAW,CAAC,OAAO,GAAE,SAAc,GAAG,MAAM,EAAE,CAM7D;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAGnF;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,GAAE,SAAc,GAAG,IAAI,CAGvE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,SAAS,CAAC,IAAI,CAAC,EAAE,QAAQ,GAAG,MAAM,CAMjD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,wBAAsB,iBAAiB,CAAC,KAAK,EAAE,eAAe,EAAE,EAAE,EAAE,MAAM,EAAE,OAAO,GAAE,SAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAMpH;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkDG;AACH,wBAAsB,iBAAiB,CAAC,KAAK,EAAE,mBAAmB,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CASpG;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,uBAAuB,CAAC,KAAK,EAAE,mBAAmB,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAIvG"}
|
package/build/utils/tenant.js
CHANGED
|
@@ -11,6 +11,8 @@
|
|
|
11
11
|
*********************************************************************************************/
|
|
12
12
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
13
|
exports.resolveTenant = resolveTenant;
|
|
14
|
+
exports.tenantRoles = tenantRoles;
|
|
15
|
+
exports.hasTenantRole = hasTenantRole;
|
|
14
16
|
exports.setTenant = setTenant;
|
|
15
17
|
exports.getTenant = getTenant;
|
|
16
18
|
exports.assertTenantScope = assertTenantScope;
|
|
@@ -67,6 +69,37 @@ function resolveTenant(user, orgId) {
|
|
|
67
69
|
throw new nx_frame_be_1.AppError('messages.authorization.accessDenied');
|
|
68
70
|
return orgId;
|
|
69
71
|
}
|
|
72
|
+
/**
|
|
73
|
+
* The roles that apply to a request, on the organization it operates on.
|
|
74
|
+
*
|
|
75
|
+
* A request works inside ONE organization: the one it selected, or the user's own when it
|
|
76
|
+
* selected none - the rule of `resolveTenant`. Its roles are the effective roles there
|
|
77
|
+
* (`effectiveRoles`), so on an organization reached through a grant the grant's role decides,
|
|
78
|
+
* and nowhere does the membership role travel to an organization that did not confer it.
|
|
79
|
+
*
|
|
80
|
+
* It does NOT throw where `resolveTenant` does: an unreachable selection simply holds no
|
|
81
|
+
* organization role here, so a role check fails closed, and the scoping refuses the selection
|
|
82
|
+
* itself the moment a query runs. A user without any organization has nothing to narrow and
|
|
83
|
+
* keeps their roles.
|
|
84
|
+
*
|
|
85
|
+
* @param context the request context (authenticated user + selected organization)
|
|
86
|
+
* @returns the roles that hold on the organization of the request
|
|
87
|
+
*/
|
|
88
|
+
function tenantRoles(context = {}) {
|
|
89
|
+
const user = context.user;
|
|
90
|
+
const orgId = context.orgId || (user?.organizations?.[0]?.id ? String(user.organizations[0].id) : undefined);
|
|
91
|
+
return orgId ? (0, scope_1.effectiveRoles)(user, orgId) : [...(user?.roles ?? [])];
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Whether one of `roles` holds for the request, on the organization it operates on.
|
|
95
|
+
*
|
|
96
|
+
* @param context the request context
|
|
97
|
+
* @param roles the roles that grant the capability (any of them is enough)
|
|
98
|
+
* @returns `true` when one of them is among the roles of the request
|
|
99
|
+
*/
|
|
100
|
+
function hasTenantRole(context, roles) {
|
|
101
|
+
return tenantRoles(context).some(r => roles.includes(r));
|
|
102
|
+
}
|
|
70
103
|
/**
|
|
71
104
|
* Forces `tenantId` on a payload or on a query filter, from the resolved organization.
|
|
72
105
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tenant.js","sourceRoot":"","sources":["../../src/utils/tenant.ts"],"names":[],"mappings":";AAAA;;;;;;;;;+FAS+F;;AA0C/F,sCAkBC;AAqBD,8BAGC;AAaD,8BAMC;AAqCD,8CAMC;AAqDD,8CASC;AAkBD,0DAIC;
|
|
1
|
+
{"version":3,"file":"tenant.js","sourceRoot":"","sources":["../../src/utils/tenant.ts"],"names":[],"mappings":"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"}
|