@globaltracking/auth-middleware 2.0.0 → 2.1.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/dist/config.d.ts.map +1 -1
- package/dist/config.js +7 -1
- package/dist/config.js.map +1 -1
- package/dist/extract-user.d.ts +6 -1
- package/dist/extract-user.d.ts.map +1 -1
- package/dist/extract-user.js +39 -2
- package/dist/extract-user.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/middlewares/require-permission.d.ts +2 -2
- package/dist/middlewares/require-permission.d.ts.map +1 -1
- package/dist/middlewares/require-permission.js +23 -8
- package/dist/middlewares/require-permission.js.map +1 -1
- package/dist/middlewares/require-role.d.ts +4 -2
- package/dist/middlewares/require-role.d.ts.map +1 -1
- package/dist/middlewares/require-role.js +12 -4
- package/dist/middlewares/require-role.js.map +1 -1
- package/dist/middlewares/require-self.d.ts +1 -1
- package/dist/middlewares/require-self.d.ts.map +1 -1
- package/dist/middlewares/require-self.js +4 -3
- package/dist/middlewares/require-self.js.map +1 -1
- package/dist/nestjs/guards/permissions.guard.d.ts +5 -1
- package/dist/nestjs/guards/permissions.guard.d.ts.map +1 -1
- package/dist/nestjs/guards/permissions.guard.js +12 -3
- package/dist/nestjs/guards/permissions.guard.js.map +1 -1
- package/dist/strategies/gateway-header.strategy.d.ts.map +1 -1
- package/dist/strategies/gateway-header.strategy.js +8 -1
- package/dist/strategies/gateway-header.strategy.js.map +1 -1
- package/dist/strategies/jwt.strategy.d.ts.map +1 -1
- package/dist/strategies/jwt.strategy.js +8 -1
- package/dist/strategies/jwt.strategy.js.map +1 -1
- package/dist/strategies/trusted-headers.strategy.d.ts.map +1 -1
- package/dist/strategies/trusted-headers.strategy.js +16 -1
- package/dist/strategies/trusted-headers.strategy.js.map +1 -1
- package/dist/types.d.ts +45 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/helpers.d.ts +14 -1
- package/dist/utils/helpers.d.ts.map +1 -1
- package/dist/utils/helpers.js +22 -2
- package/dist/utils/helpers.js.map +1 -1
- package/dist/utils/jwt.js +8 -1
- package/dist/utils/jwt.js.map +1 -1
- package/package.json +2 -2
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AA+BzD;;GAEG;AACH,wBAAgB,QAAQ,CAAC,MAAM,GAAE,UAAe,GAAG,IAAI,CAqCtD;AAED,wBAAgB,SAAS,IAAI,kBAAkB,CAE9C;AAED,+CAA+C;AAC/C,wBAAgB,WAAW,IAAI,IAAI,CAElC"}
|
package/dist/config.js
CHANGED
|
@@ -41,6 +41,9 @@ const DEFAULT_TRUSTED_HEADERS = {
|
|
|
41
41
|
userId: 'x-user-id',
|
|
42
42
|
orgId: 'x-org-id',
|
|
43
43
|
userRole: 'x-user-role',
|
|
44
|
+
roles: 'x-user-roles',
|
|
45
|
+
isSystemAdmin: 'x-is-system-admin',
|
|
46
|
+
actingOnOrg: 'x-acting-on-org',
|
|
44
47
|
requestId: 'x-request-id',
|
|
45
48
|
gatewayToken: 'x-gateway-token',
|
|
46
49
|
};
|
|
@@ -50,7 +53,10 @@ const DEFAULT_CONFIG = {
|
|
|
50
53
|
publicKey: '',
|
|
51
54
|
publicKeyPath: '',
|
|
52
55
|
strategies: ['gateway-header', 'jwt'],
|
|
53
|
-
|
|
56
|
+
// `system_admin` is NOT here — system-admin bypass comes from the
|
|
57
|
+
// `is_system_admin` claim (see types.ts). `org_admin` is the only
|
|
58
|
+
// bypass role, and its bypass is implicitly within-tenant.
|
|
59
|
+
adminRoles: ['org_admin'],
|
|
54
60
|
internalGatewayToken: '',
|
|
55
61
|
trustedHeaderNames: { ...DEFAULT_TRUSTED_HEADERS },
|
|
56
62
|
rbacServiceUrl: '',
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
package/dist/extract-user.d.ts
CHANGED
|
@@ -4,7 +4,12 @@ import { AuthUser } from './types';
|
|
|
4
4
|
* Extract AuthUser from a request using the configured strategy chain.
|
|
5
5
|
* Iterates through `config.strategies` in order, trying each until one succeeds.
|
|
6
6
|
*
|
|
7
|
-
*
|
|
7
|
+
* After extraction, if the caller is a system admin and the request carries
|
|
8
|
+
* `X-Acting-On-Org`, the user's effective org is overridden to the target
|
|
9
|
+
* tenant (and the home org is recorded under `user.actingOnOrg`).
|
|
10
|
+
*
|
|
11
|
+
* Throws UnauthorizedError if no strategy can handle the request; throws
|
|
12
|
+
* ForbiddenError if a non-system-admin tries to use `X-Acting-On-Org`.
|
|
8
13
|
*/
|
|
9
14
|
export declare function extractUser(req: Request): AuthUser;
|
|
10
15
|
//# sourceMappingURL=extract-user.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extract-user.d.ts","sourceRoot":"","sources":["../src/extract-user.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAGlC,OAAO,EAAE,QAAQ,EAAgB,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"extract-user.d.ts","sourceRoot":"","sources":["../src/extract-user.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAGlC,OAAO,EAAE,QAAQ,EAAgB,MAAM,SAAS,CAAC;AAuDjD;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,OAAO,GAAG,QAAQ,CAYlD"}
|
package/dist/extract-user.js
CHANGED
|
@@ -11,18 +11,55 @@ const strategyMap = {
|
|
|
11
11
|
'trusted-headers': new trusted_headers_strategy_1.TrustedHeadersStrategy(),
|
|
12
12
|
'jwt': new jwt_strategy_1.JwtStrategy(),
|
|
13
13
|
};
|
|
14
|
+
const UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
15
|
+
/**
|
|
16
|
+
* Apply the `X-Acting-On-Org` override, if any. Only system admins may use
|
|
17
|
+
* it. For anyone else, a non-empty header is rejected loudly so a misissued
|
|
18
|
+
* request fails fast rather than silently ignoring the header.
|
|
19
|
+
*/
|
|
20
|
+
function applyActingOnOrg(req, user) {
|
|
21
|
+
const config = (0, config_1.getConfig)();
|
|
22
|
+
const headerName = config.trustedHeaderNames.actingOnOrg;
|
|
23
|
+
const raw = req.headers[headerName];
|
|
24
|
+
const actingOnOrgId = typeof raw === 'string' ? raw.trim() : '';
|
|
25
|
+
if (!actingOnOrgId) {
|
|
26
|
+
return user;
|
|
27
|
+
}
|
|
28
|
+
if (!user.isSystemAdmin) {
|
|
29
|
+
throw new errors_1.ForbiddenError(`${headerName} header is only valid for system admins`, { actingOnOrgId, userId: user.userId });
|
|
30
|
+
}
|
|
31
|
+
if (!UUID_REGEX.test(actingOnOrgId)) {
|
|
32
|
+
throw new errors_1.ForbiddenError(`${headerName} must be a UUID`, { actingOnOrgId });
|
|
33
|
+
}
|
|
34
|
+
const homeOrgId = user.orgId;
|
|
35
|
+
return {
|
|
36
|
+
...user,
|
|
37
|
+
orgId: actingOnOrgId,
|
|
38
|
+
tenantId: actingOnOrgId,
|
|
39
|
+
actingOnOrg: {
|
|
40
|
+
homeOrgId,
|
|
41
|
+
targetOrgId: actingOnOrgId,
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
}
|
|
14
45
|
/**
|
|
15
46
|
* Extract AuthUser from a request using the configured strategy chain.
|
|
16
47
|
* Iterates through `config.strategies` in order, trying each until one succeeds.
|
|
17
48
|
*
|
|
18
|
-
*
|
|
49
|
+
* After extraction, if the caller is a system admin and the request carries
|
|
50
|
+
* `X-Acting-On-Org`, the user's effective org is overridden to the target
|
|
51
|
+
* tenant (and the home org is recorded under `user.actingOnOrg`).
|
|
52
|
+
*
|
|
53
|
+
* Throws UnauthorizedError if no strategy can handle the request; throws
|
|
54
|
+
* ForbiddenError if a non-system-admin tries to use `X-Acting-On-Org`.
|
|
19
55
|
*/
|
|
20
56
|
function extractUser(req) {
|
|
21
57
|
const config = (0, config_1.getConfig)();
|
|
22
58
|
for (const strategyName of config.strategies) {
|
|
23
59
|
const strategy = strategyMap[strategyName];
|
|
24
60
|
if (strategy && strategy.canHandle(req)) {
|
|
25
|
-
|
|
61
|
+
const user = strategy.extract(req);
|
|
62
|
+
return applyActingOnOrg(req, user);
|
|
26
63
|
}
|
|
27
64
|
}
|
|
28
65
|
throw new errors_1.UnauthorizedError('No authentication credentials provided');
|
package/dist/extract-user.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extract-user.js","sourceRoot":"","sources":["../src/extract-user.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"extract-user.js","sourceRoot":"","sources":["../src/extract-user.ts"],"names":[],"mappings":";;AAqEA,kCAYC;AAhFD,qCAAqC;AACrC,qCAA6D;AAG7D,kFAA6E;AAC7E,oFAA+E;AAC/E,4DAAwD;AAExD,MAAM,WAAW,GAAiD;IAChE,gBAAgB,EAAE,IAAI,+CAAqB,EAAE;IAC7C,iBAAiB,EAAE,IAAI,iDAAsB,EAAE;IAC/C,KAAK,EAAE,IAAI,0BAAW,EAAE;CACzB,CAAC;AAEF,MAAM,UAAU,GACd,iEAAiE,CAAC;AAEpE;;;;GAIG;AACH,SAAS,gBAAgB,CAAC,GAAY,EAAE,IAAc;IACpD,MAAM,MAAM,GAAG,IAAA,kBAAS,GAAE,CAAC;IAC3B,MAAM,UAAU,GAAG,MAAM,CAAC,kBAAkB,CAAC,WAAW,CAAC;IACzD,MAAM,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IACpC,MAAM,aAAa,GAAG,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAChE,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC;QACxB,MAAM,IAAI,uBAAc,CACtB,GAAG,UAAU,yCAAyC,EACtD,EAAE,aAAa,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CACvC,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,aAAa,CAAC,EAAE,CAAC;QACpC,MAAM,IAAI,uBAAc,CACtB,GAAG,UAAU,iBAAiB,EAC9B,EAAE,aAAa,EAAE,CAClB,CAAC;IACJ,CAAC;IAED,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC;IAC7B,OAAO;QACL,GAAG,IAAI;QACP,KAAK,EAAE,aAAa;QACpB,QAAQ,EAAE,aAAa;QACvB,WAAW,EAAE;YACX,SAAS;YACT,WAAW,EAAE,aAAa;SAC3B;KACF,CAAC;AACJ,CAAC;AAED;;;;;;;;;;GAUG;AACH,SAAgB,WAAW,CAAC,GAAY;IACtC,MAAM,MAAM,GAAG,IAAA,kBAAS,GAAE,CAAC;IAE3B,KAAK,MAAM,YAAY,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;QAC7C,MAAM,QAAQ,GAAG,WAAW,CAAC,YAAY,CAAC,CAAC;QAC3C,IAAI,QAAQ,IAAI,QAAQ,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC;YACxC,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YACnC,OAAO,gBAAgB,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QACrC,CAAC;IACH,CAAC;IAED,MAAM,IAAI,0BAAiB,CAAC,wCAAwC,CAAC,CAAC;AACxE,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -12,5 +12,5 @@ export { requirePermission, requireAnyPermission } from './middlewares/require-p
|
|
|
12
12
|
export { requireTenant } from './middlewares/require-tenant';
|
|
13
13
|
export { requireSelf } from './middlewares/require-self';
|
|
14
14
|
export { authErrorHandler } from './middlewares/error-handler';
|
|
15
|
-
export { hasRole, hasPermission, hasAnyPermission } from './utils/helpers';
|
|
15
|
+
export { hasRole, hasPermission, hasAnyPermission, isSystemAdmin, isOrgAdmin } from './utils/helpers';
|
|
16
16
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAG5D,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,UAAU,EAAE,YAAY,EAAE,UAAU,EAAE,QAAQ,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAGxI,OAAO,EAAE,SAAS,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAGxE,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAG7C,OAAO,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AACzE,OAAO,EAAE,qBAAqB,EAAE,MAAM,sCAAsC,CAAC;AAC7E,OAAO,EAAE,sBAAsB,EAAE,MAAM,uCAAuC,CAAC;AAC/E,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAGxD,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,kCAAkC,CAAC;AAC3F,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAG/D,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAG5D,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,UAAU,EAAE,YAAY,EAAE,UAAU,EAAE,QAAQ,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAGxI,OAAO,EAAE,SAAS,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAGxE,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAG7C,OAAO,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AACzE,OAAO,EAAE,qBAAqB,EAAE,MAAM,sCAAsC,CAAC;AAC7E,OAAO,EAAE,sBAAsB,EAAE,MAAM,uCAAuC,CAAC;AAC/E,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAGxD,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,kCAAkC,CAAC;AAC3F,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAG/D,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.hasAnyPermission = exports.hasPermission = exports.hasRole = exports.authErrorHandler = exports.requireSelf = exports.requireTenant = exports.requireAnyPermission = exports.requirePermission = exports.requireRole = exports.authenticate = exports.JwtStrategy = exports.TrustedHeadersStrategy = exports.GatewayHeaderStrategy = exports.extractUser = exports.ForbiddenError = exports.UnauthorizedError = exports.AuthError = exports.resetConfig = exports.getConfig = exports.initAuth = void 0;
|
|
3
|
+
exports.isOrgAdmin = exports.isSystemAdmin = exports.hasAnyPermission = exports.hasPermission = exports.hasRole = exports.authErrorHandler = exports.requireSelf = exports.requireTenant = exports.requireAnyPermission = exports.requirePermission = exports.requireRole = exports.authenticate = exports.JwtStrategy = exports.TrustedHeadersStrategy = exports.GatewayHeaderStrategy = exports.extractUser = exports.ForbiddenError = exports.UnauthorizedError = exports.AuthError = exports.resetConfig = exports.getConfig = exports.initAuth = void 0;
|
|
4
4
|
// Configuration
|
|
5
5
|
var config_1 = require("./config");
|
|
6
6
|
Object.defineProperty(exports, "initAuth", { enumerable: true, get: function () { return config_1.initAuth; } });
|
|
@@ -39,4 +39,6 @@ var helpers_1 = require("./utils/helpers");
|
|
|
39
39
|
Object.defineProperty(exports, "hasRole", { enumerable: true, get: function () { return helpers_1.hasRole; } });
|
|
40
40
|
Object.defineProperty(exports, "hasPermission", { enumerable: true, get: function () { return helpers_1.hasPermission; } });
|
|
41
41
|
Object.defineProperty(exports, "hasAnyPermission", { enumerable: true, get: function () { return helpers_1.hasAnyPermission; } });
|
|
42
|
+
Object.defineProperty(exports, "isSystemAdmin", { enumerable: true, get: function () { return helpers_1.isSystemAdmin; } });
|
|
43
|
+
Object.defineProperty(exports, "isOrgAdmin", { enumerable: true, get: function () { return helpers_1.isOrgAdmin; } });
|
|
42
44
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,gBAAgB;AAChB,mCAA4D;AAAnD,kGAAA,QAAQ,OAAA;AAAE,mGAAA,SAAS,OAAA;AAAE,qGAAA,WAAW,OAAA;AAKzC,SAAS;AACT,mCAAwE;AAA/D,mGAAA,SAAS,OAAA;AAAE,2GAAA,iBAAiB,OAAA;AAAE,wGAAA,cAAc,OAAA;AAErD,kBAAkB;AAClB,+CAA6C;AAApC,2GAAA,WAAW,OAAA;AAIpB,gFAA6E;AAApE,gIAAA,qBAAqB,OAAA;AAC9B,kFAA+E;AAAtE,kIAAA,sBAAsB,OAAA;AAC/B,0DAAwD;AAA/C,2GAAA,WAAW,OAAA;AAEpB,cAAc;AACd,2DAA0D;AAAjD,4GAAA,YAAY,OAAA;AACrB,2DAAyD;AAAhD,2GAAA,WAAW,OAAA;AACpB,uEAA2F;AAAlF,uHAAA,iBAAiB,OAAA;AAAE,0HAAA,oBAAoB,OAAA;AAChD,+DAA6D;AAApD,+GAAA,aAAa,OAAA;AACtB,2DAAyD;AAAhD,2GAAA,WAAW,OAAA;AACpB,6DAA+D;AAAtD,iHAAA,gBAAgB,OAAA;AAEzB,oBAAoB;AACpB,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,gBAAgB;AAChB,mCAA4D;AAAnD,kGAAA,QAAQ,OAAA;AAAE,mGAAA,SAAS,OAAA;AAAE,qGAAA,WAAW,OAAA;AAKzC,SAAS;AACT,mCAAwE;AAA/D,mGAAA,SAAS,OAAA;AAAE,2GAAA,iBAAiB,OAAA;AAAE,wGAAA,cAAc,OAAA;AAErD,kBAAkB;AAClB,+CAA6C;AAApC,2GAAA,WAAW,OAAA;AAIpB,gFAA6E;AAApE,gIAAA,qBAAqB,OAAA;AAC9B,kFAA+E;AAAtE,kIAAA,sBAAsB,OAAA;AAC/B,0DAAwD;AAA/C,2GAAA,WAAW,OAAA;AAEpB,cAAc;AACd,2DAA0D;AAAjD,4GAAA,YAAY,OAAA;AACrB,2DAAyD;AAAhD,2GAAA,WAAW,OAAA;AACpB,uEAA2F;AAAlF,uHAAA,iBAAiB,OAAA;AAAE,0HAAA,oBAAoB,OAAA;AAChD,+DAA6D;AAApD,+GAAA,aAAa,OAAA;AACtB,2DAAyD;AAAhD,2GAAA,WAAW,OAAA;AACpB,6DAA+D;AAAtD,iHAAA,gBAAgB,OAAA;AAEzB,oBAAoB;AACpB,2CAAsG;AAA7F,kGAAA,OAAO,OAAA;AAAE,wGAAA,aAAa,OAAA;AAAE,2GAAA,gBAAgB,OAAA;AAAE,wGAAA,aAAa,OAAA;AAAE,qGAAA,UAAU,OAAA"}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { Request, Response, NextFunction } from 'express';
|
|
2
2
|
/**
|
|
3
3
|
* Returns middleware that checks if the user has ALL of the required permissions.
|
|
4
|
-
*
|
|
4
|
+
* System admins bypass unconditionally; RBAC admin roles bypass within-tenant.
|
|
5
5
|
*/
|
|
6
6
|
export declare function requirePermission(...permissions: string[]): (req: Request, _res: Response, next: NextFunction) => void;
|
|
7
7
|
/**
|
|
8
8
|
* Returns middleware that checks if the user has AT LEAST ONE of the listed permissions.
|
|
9
|
-
*
|
|
9
|
+
* System admins bypass unconditionally; RBAC admin roles bypass within-tenant.
|
|
10
10
|
*/
|
|
11
11
|
export declare function requireAnyPermission(...permissions: string[]): (req: Request, _res: Response, next: NextFunction) => void;
|
|
12
12
|
//# sourceMappingURL=require-permission.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"require-permission.d.ts","sourceRoot":"","sources":["../../src/middlewares/require-permission.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"require-permission.d.ts","sourceRoot":"","sources":["../../src/middlewares/require-permission.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAwB1D;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,WAAW,EAAE,MAAM,EAAE,IAChD,KAAK,OAAO,EAAE,MAAM,QAAQ,EAAE,MAAM,YAAY,KAAG,IAAI,CA0BhE;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,WAAW,EAAE,MAAM,EAAE,IACnD,KAAK,OAAO,EAAE,MAAM,QAAQ,EAAE,MAAM,YAAY,KAAG,IAAI,CA0BhE"}
|
|
@@ -4,9 +4,28 @@ exports.requirePermission = requirePermission;
|
|
|
4
4
|
exports.requireAnyPermission = requireAnyPermission;
|
|
5
5
|
const config_1 = require("../config");
|
|
6
6
|
const errors_1 = require("../errors");
|
|
7
|
+
/**
|
|
8
|
+
* Centralized bypass check.
|
|
9
|
+
*
|
|
10
|
+
* `is_system_admin` gets an unconditional bypass — the claim is sourced from
|
|
11
|
+
* `users.is_system_admin`, which the HTTP API cannot set. Cross-tenant scope
|
|
12
|
+
* is controlled separately via the `X-Acting-On-Org` header (handled in
|
|
13
|
+
* extract-user.ts).
|
|
14
|
+
*
|
|
15
|
+
* `config.adminRoles` (default `['org_admin']`) gets a bypass within the
|
|
16
|
+
* user's own tenant. The user's `orgId` comes from their verified JWT /
|
|
17
|
+
* gateway-verified header, so there's no way for them to target another
|
|
18
|
+
* tenant — the bypass is implicitly in-tenant only.
|
|
19
|
+
*/
|
|
20
|
+
function canBypass(user) {
|
|
21
|
+
if (user.isSystemAdmin)
|
|
22
|
+
return true;
|
|
23
|
+
const adminRoles = (0, config_1.getConfig)().adminRoles;
|
|
24
|
+
return user.roles.some((r) => adminRoles.includes(r));
|
|
25
|
+
}
|
|
7
26
|
/**
|
|
8
27
|
* Returns middleware that checks if the user has ALL of the required permissions.
|
|
9
|
-
*
|
|
28
|
+
* System admins bypass unconditionally; RBAC admin roles bypass within-tenant.
|
|
10
29
|
*/
|
|
11
30
|
function requirePermission(...permissions) {
|
|
12
31
|
return (req, _res, next) => {
|
|
@@ -14,9 +33,7 @@ function requirePermission(...permissions) {
|
|
|
14
33
|
next(new errors_1.UnauthorizedError('Authentication required'));
|
|
15
34
|
return;
|
|
16
35
|
}
|
|
17
|
-
|
|
18
|
-
// Admin roles bypass all permission checks
|
|
19
|
-
if (config.adminRoles.includes(req.user.role)) {
|
|
36
|
+
if (canBypass(req.user)) {
|
|
20
37
|
next();
|
|
21
38
|
return;
|
|
22
39
|
}
|
|
@@ -34,7 +51,7 @@ function requirePermission(...permissions) {
|
|
|
34
51
|
}
|
|
35
52
|
/**
|
|
36
53
|
* Returns middleware that checks if the user has AT LEAST ONE of the listed permissions.
|
|
37
|
-
*
|
|
54
|
+
* System admins bypass unconditionally; RBAC admin roles bypass within-tenant.
|
|
38
55
|
*/
|
|
39
56
|
function requireAnyPermission(...permissions) {
|
|
40
57
|
return (req, _res, next) => {
|
|
@@ -42,9 +59,7 @@ function requireAnyPermission(...permissions) {
|
|
|
42
59
|
next(new errors_1.UnauthorizedError('Authentication required'));
|
|
43
60
|
return;
|
|
44
61
|
}
|
|
45
|
-
|
|
46
|
-
// Admin roles bypass all permission checks
|
|
47
|
-
if (config.adminRoles.includes(req.user.role)) {
|
|
62
|
+
if (canBypass(req.user)) {
|
|
48
63
|
next();
|
|
49
64
|
return;
|
|
50
65
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"require-permission.js","sourceRoot":"","sources":["../../src/middlewares/require-permission.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"require-permission.js","sourceRoot":"","sources":["../../src/middlewares/require-permission.ts"],"names":[],"mappings":";;AA4BA,8CA2BC;AAMD,oDA2BC;AAvFD,sCAAsC;AACtC,sCAA8D;AAG9D;;;;;;;;;;;;GAYG;AACH,SAAS,SAAS,CAAC,IAAc;IAC/B,IAAI,IAAI,CAAC,aAAa;QAAE,OAAO,IAAI,CAAC;IACpC,MAAM,UAAU,GAAG,IAAA,kBAAS,GAAE,CAAC,UAAU,CAAC;IAC1C,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;AACxD,CAAC;AAED;;;GAGG;AACH,SAAgB,iBAAiB,CAAC,GAAG,WAAqB;IACxD,OAAO,CAAC,GAAY,EAAE,IAAc,EAAE,IAAkB,EAAQ,EAAE;QAChE,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;YACd,IAAI,CAAC,IAAI,0BAAiB,CAAC,yBAAyB,CAAC,CAAC,CAAC;YACvD,OAAO;QACT,CAAC;QAED,IAAI,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YACxB,IAAI,EAAE,CAAC;YACP,OAAO;QACT,CAAC;QAED,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAChD,MAAM,OAAO,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QAE7D,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvB,IAAI,CACF,IAAI,uBAAc,CAAC,0BAA0B,EAAE;gBAC7C,QAAQ,EAAE,WAAW;gBACrB,mBAAmB,EAAE,OAAO;aAC7B,CAAC,CACH,CAAC;YACF,OAAO;QACT,CAAC;QAED,IAAI,EAAE,CAAC;IACT,CAAC,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,SAAgB,oBAAoB,CAAC,GAAG,WAAqB;IAC3D,OAAO,CAAC,GAAY,EAAE,IAAc,EAAE,IAAkB,EAAQ,EAAE;QAChE,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;YACd,IAAI,CAAC,IAAI,0BAAiB,CAAC,yBAAyB,CAAC,CAAC,CAAC;YACvD,OAAO;QACT,CAAC;QAED,IAAI,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YACxB,IAAI,EAAE,CAAC;YACP,OAAO;QACT,CAAC;QAED,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAChD,MAAM,MAAM,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QAEzD,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,IAAI,CACF,IAAI,uBAAc,CAAC,8CAA8C,EAAE;gBACjE,YAAY,EAAE,WAAW;gBACzB,MAAM,EAAE,GAAG,CAAC,IAAI,CAAC,WAAW;aAC7B,CAAC,CACH,CAAC;YACF,OAAO;QACT,CAAC;QAED,IAAI,EAAE,CAAC;IACT,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import { Request, Response, NextFunction } from 'express';
|
|
2
2
|
/**
|
|
3
|
-
* Returns middleware that checks if the authenticated user has
|
|
3
|
+
* Returns middleware that checks if the authenticated user has ANY of the
|
|
4
|
+
* allowed roles. System admins always pass (they implicitly hold every role
|
|
5
|
+
* for cross-tenant operations).
|
|
4
6
|
*
|
|
5
7
|
* @param roles - One or more allowed role strings
|
|
6
8
|
* @returns Express middleware
|
|
7
9
|
*
|
|
8
10
|
* @example
|
|
9
|
-
* app.delete('/v1/vehicles/:id', authenticate, requireRole('
|
|
11
|
+
* app.delete('/v1/vehicles/:id', authenticate, requireRole('fleet_manager'), handler);
|
|
10
12
|
*/
|
|
11
13
|
export declare function requireRole(...roles: string[]): (req: Request, _res: Response, next: NextFunction) => void;
|
|
12
14
|
//# sourceMappingURL=require-role.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"require-role.d.ts","sourceRoot":"","sources":["../../src/middlewares/require-role.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAG1D
|
|
1
|
+
{"version":3,"file":"require-role.d.ts","sourceRoot":"","sources":["../../src/middlewares/require-role.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAG1D;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CAAC,GAAG,KAAK,EAAE,MAAM,EAAE,IACpC,KAAK,OAAO,EAAE,MAAM,QAAQ,EAAE,MAAM,YAAY,KAAG,IAAI,CAyBhE"}
|
|
@@ -3,13 +3,15 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.requireRole = requireRole;
|
|
4
4
|
const errors_1 = require("../errors");
|
|
5
5
|
/**
|
|
6
|
-
* Returns middleware that checks if the authenticated user has
|
|
6
|
+
* Returns middleware that checks if the authenticated user has ANY of the
|
|
7
|
+
* allowed roles. System admins always pass (they implicitly hold every role
|
|
8
|
+
* for cross-tenant operations).
|
|
7
9
|
*
|
|
8
10
|
* @param roles - One or more allowed role strings
|
|
9
11
|
* @returns Express middleware
|
|
10
12
|
*
|
|
11
13
|
* @example
|
|
12
|
-
* app.delete('/v1/vehicles/:id', authenticate, requireRole('
|
|
14
|
+
* app.delete('/v1/vehicles/:id', authenticate, requireRole('fleet_manager'), handler);
|
|
13
15
|
*/
|
|
14
16
|
function requireRole(...roles) {
|
|
15
17
|
return (req, _res, next) => {
|
|
@@ -17,10 +19,16 @@ function requireRole(...roles) {
|
|
|
17
19
|
next(new errors_1.UnauthorizedError('Authentication required'));
|
|
18
20
|
return;
|
|
19
21
|
}
|
|
20
|
-
if (
|
|
22
|
+
if (req.user.isSystemAdmin) {
|
|
23
|
+
next();
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
const userRoles = new Set(req.user.roles);
|
|
27
|
+
const hasAny = roles.some((r) => userRoles.has(r));
|
|
28
|
+
if (!hasAny) {
|
|
21
29
|
next(new errors_1.ForbiddenError('Insufficient role', {
|
|
22
30
|
required: roles,
|
|
23
|
-
actual: req.user.
|
|
31
|
+
actual: req.user.roles,
|
|
24
32
|
}));
|
|
25
33
|
return;
|
|
26
34
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"require-role.js","sourceRoot":"","sources":["../../src/middlewares/require-role.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"require-role.js","sourceRoot":"","sources":["../../src/middlewares/require-role.ts"],"names":[],"mappings":";;AAcA,kCA0BC;AAvCD,sCAA8D;AAE9D;;;;;;;;;;GAUG;AACH,SAAgB,WAAW,CAAC,GAAG,KAAe;IAC5C,OAAO,CAAC,GAAY,EAAE,IAAc,EAAE,IAAkB,EAAQ,EAAE;QAChE,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;YACd,IAAI,CAAC,IAAI,0BAAiB,CAAC,yBAAyB,CAAC,CAAC,CAAC;YACvD,OAAO;QACT,CAAC;QAED,IAAI,GAAG,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC;YAC3B,IAAI,EAAE,CAAC;YACP,OAAO;QACT,CAAC;QAED,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC1C,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QACnD,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,IAAI,CACF,IAAI,uBAAc,CAAC,mBAAmB,EAAE;gBACtC,QAAQ,EAAE,KAAK;gBACf,MAAM,EAAE,GAAG,CAAC,IAAI,CAAC,KAAK;aACvB,CAAC,CACH,CAAC;YACF,OAAO;QACT,CAAC;QAED,IAAI,EAAE,CAAC;IACT,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -2,7 +2,7 @@ import { Request, Response, NextFunction } from 'express';
|
|
|
2
2
|
/**
|
|
3
3
|
* Returns middleware that ensures the authenticated user can only access their own resources.
|
|
4
4
|
* Compares `req.user.userId` with `req.params[paramName]`.
|
|
5
|
-
*
|
|
5
|
+
* System admins bypass unconditionally; RBAC admin roles bypass within-tenant.
|
|
6
6
|
*
|
|
7
7
|
* @param paramName - Route parameter name to compare against. Default: 'userId'
|
|
8
8
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"require-self.d.ts","sourceRoot":"","sources":["../../src/middlewares/require-self.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAI1D;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,SAAS,SAAW,IACtC,KAAK,OAAO,EAAE,MAAM,QAAQ,EAAE,MAAM,YAAY,KAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"require-self.d.ts","sourceRoot":"","sources":["../../src/middlewares/require-self.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAI1D;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,SAAS,SAAW,IACtC,KAAK,OAAO,EAAE,MAAM,QAAQ,EAAE,MAAM,YAAY,KAAG,IAAI,CAoChE"}
|
|
@@ -6,7 +6,7 @@ const errors_1 = require("../errors");
|
|
|
6
6
|
/**
|
|
7
7
|
* Returns middleware that ensures the authenticated user can only access their own resources.
|
|
8
8
|
* Compares `req.user.userId` with `req.params[paramName]`.
|
|
9
|
-
*
|
|
9
|
+
* System admins bypass unconditionally; RBAC admin roles bypass within-tenant.
|
|
10
10
|
*
|
|
11
11
|
* @param paramName - Route parameter name to compare against. Default: 'userId'
|
|
12
12
|
*/
|
|
@@ -17,8 +17,9 @@ function requireSelf(paramName = 'userId') {
|
|
|
17
17
|
return;
|
|
18
18
|
}
|
|
19
19
|
const config = (0, config_1.getConfig)();
|
|
20
|
-
//
|
|
21
|
-
if (
|
|
20
|
+
// System admins and configured admin roles bypass the self check.
|
|
21
|
+
if (req.user.isSystemAdmin ||
|
|
22
|
+
req.user.roles.some((r) => config.adminRoles.includes(r))) {
|
|
22
23
|
next();
|
|
23
24
|
return;
|
|
24
25
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"require-self.js","sourceRoot":"","sources":["../../src/middlewares/require-self.ts"],"names":[],"mappings":";;AAWA,
|
|
1
|
+
{"version":3,"file":"require-self.js","sourceRoot":"","sources":["../../src/middlewares/require-self.ts"],"names":[],"mappings":";;AAWA,kCAqCC;AA/CD,sCAAsC;AACtC,sCAA8D;AAE9D;;;;;;GAMG;AACH,SAAgB,WAAW,CAAC,SAAS,GAAG,QAAQ;IAC9C,OAAO,CAAC,GAAY,EAAE,IAAc,EAAE,IAAkB,EAAQ,EAAE;QAChE,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;YACd,IAAI,CAAC,IAAI,0BAAiB,CAAC,yBAAyB,CAAC,CAAC,CAAC;YACvD,OAAO;QACT,CAAC;QAED,MAAM,MAAM,GAAG,IAAA,kBAAS,GAAE,CAAC;QAE3B,kEAAkE;QAClE,IACE,GAAG,CAAC,IAAI,CAAC,aAAa;YACtB,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EACzD,CAAC;YACD,IAAI,EAAE,CAAC;YACP,OAAO;QACT,CAAC;QAED,MAAM,YAAY,GAAG,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAE3C,IAAI,CAAC,YAAY,EAAE,CAAC;YAClB,IAAI,CAAC,IAAI,uBAAc,CAAC,oBAAoB,SAAS,cAAc,CAAC,CAAC,CAAC;YACtE,OAAO;QACT,CAAC;QAED,IAAI,GAAG,CAAC,IAAI,CAAC,MAAM,KAAK,YAAY,EAAE,CAAC;YACrC,IAAI,CACF,IAAI,uBAAc,CAAC,wCAAwC,EAAE;gBAC3D,MAAM,EAAE,YAAY;gBACpB,MAAM,EAAE,GAAG,CAAC,IAAI,CAAC,MAAM;aACxB,CAAC,CACH,CAAC;YACF,OAAO;QACT,CAAC;QAED,IAAI,EAAE,CAAC;IACT,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -9,7 +9,11 @@ import { ResolvedAuthConfig } from '../../types';
|
|
|
9
9
|
* 3. If rbacServiceUrl is configured → HTTP call to RBAC service
|
|
10
10
|
* 4. Else → deny (fail-closed)
|
|
11
11
|
*
|
|
12
|
-
*
|
|
12
|
+
* Bypass rules:
|
|
13
|
+
* - `user.isSystemAdmin === true` → unconditional bypass (cross-tenant).
|
|
14
|
+
* - Any role in `config.adminRoles` (default `['org_admin']`) → bypass
|
|
15
|
+
* within the user's own tenant (their orgId is JWT-bound, so they
|
|
16
|
+
* can't target another tenant; bypass is implicitly in-tenant only).
|
|
13
17
|
*/
|
|
14
18
|
export declare class GtPermissionsGuard implements CanActivate {
|
|
15
19
|
private readonly config;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"permissions.guard.d.ts","sourceRoot":"","sources":["../../../src/nestjs/guards/permissions.guard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAkD,MAAM,gBAAgB,CAAC;AAC/G,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,OAAO,EAAY,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAE3D
|
|
1
|
+
{"version":3,"file":"permissions.guard.d.ts","sourceRoot":"","sources":["../../../src/nestjs/guards/permissions.guard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAkD,MAAM,gBAAgB,CAAC;AAC/G,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,OAAO,EAAY,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAE3D;;;;;;;;;;;;;GAaG;AACH,qBACa,kBAAmB,YAAW,WAAW;IAI1B,OAAO,CAAC,QAAQ,CAAC,MAAM;IAC/C,OAAO,CAAC,QAAQ,CAAC,SAAS;IAJ5B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAuC;gBAGnB,MAAM,EAAE,kBAAkB,EAClD,SAAS,EAAE,SAAS;IAGjC,WAAW,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAC;YAmEhD,kBAAkB;YAwBlB,cAAc;CA+C7B"}
|
|
@@ -25,7 +25,11 @@ const constants_1 = require("../constants");
|
|
|
25
25
|
* 3. If rbacServiceUrl is configured → HTTP call to RBAC service
|
|
26
26
|
* 4. Else → deny (fail-closed)
|
|
27
27
|
*
|
|
28
|
-
*
|
|
28
|
+
* Bypass rules:
|
|
29
|
+
* - `user.isSystemAdmin === true` → unconditional bypass (cross-tenant).
|
|
30
|
+
* - Any role in `config.adminRoles` (default `['org_admin']`) → bypass
|
|
31
|
+
* within the user's own tenant (their orgId is JWT-bound, so they
|
|
32
|
+
* can't target another tenant; bypass is implicitly in-tenant only).
|
|
29
33
|
*/
|
|
30
34
|
let GtPermissionsGuard = GtPermissionsGuard_1 = class GtPermissionsGuard {
|
|
31
35
|
constructor(config, reflector) {
|
|
@@ -50,8 +54,12 @@ let GtPermissionsGuard = GtPermissionsGuard_1 = class GtPermissionsGuard {
|
|
|
50
54
|
if (!user) {
|
|
51
55
|
throw new common_1.ForbiddenException('No user context found');
|
|
52
56
|
}
|
|
53
|
-
//
|
|
54
|
-
if (
|
|
57
|
+
// System admin: unconditional bypass (cross-tenant authority).
|
|
58
|
+
if (user.isSystemAdmin) {
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
// RBAC admin roles: in-tenant bypass.
|
|
62
|
+
if (user.roles.some((r) => this.config.adminRoles.includes(r))) {
|
|
55
63
|
return true;
|
|
56
64
|
}
|
|
57
65
|
// Tier 1: In-memory check from JWT claims
|
|
@@ -101,6 +109,7 @@ let GtPermissionsGuard = GtPermissionsGuard_1 = class GtPermissionsGuard {
|
|
|
101
109
|
'x-user-id': user.userId,
|
|
102
110
|
'x-org-id': user.orgId,
|
|
103
111
|
'x-user-role': user.role,
|
|
112
|
+
'x-user-roles': user.roles.join(','),
|
|
104
113
|
...(this.config.internalGatewayToken
|
|
105
114
|
? { 'x-gateway-token': this.config.internalGatewayToken }
|
|
106
115
|
: {}),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"permissions.guard.js","sourceRoot":"","sources":["../../../src/nestjs/guards/permissions.guard.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,2CAA+G;AAC/G,uCAAyC;AACzC,4CAA8E;AAG9E
|
|
1
|
+
{"version":3,"file":"permissions.guard.js","sourceRoot":"","sources":["../../../src/nestjs/guards/permissions.guard.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gateway-header.strategy.d.ts","sourceRoot":"","sources":["../../src/strategies/gateway-header.strategy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAElC,OAAO,EAAE,QAAQ,EAAc,MAAM,UAAU,CAAC;AAEhD,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAE9D;;;GAGG;AACH,qBAAa,qBAAsB,YAAW,sBAAsB;IAClE,QAAQ,CAAC,IAAI,oBAAoB;IAEjC,SAAS,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO;IAKhC,OAAO,CAAC,GAAG,EAAE,OAAO,GAAG,QAAQ;
|
|
1
|
+
{"version":3,"file":"gateway-header.strategy.d.ts","sourceRoot":"","sources":["../../src/strategies/gateway-header.strategy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAElC,OAAO,EAAE,QAAQ,EAAc,MAAM,UAAU,CAAC;AAEhD,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAE9D;;;GAGG;AACH,qBAAa,qBAAsB,YAAW,sBAAsB;IAClE,QAAQ,CAAC,IAAI,oBAAoB;IAEjC,SAAS,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO;IAKhC,OAAO,CAAC,GAAG,EAAE,OAAO,GAAG,QAAQ;CAyChC"}
|
|
@@ -35,10 +35,17 @@ class GatewayHeaderStrategy {
|
|
|
35
35
|
if (!payload.sub) {
|
|
36
36
|
throw new errors_1.UnauthorizedError('Token missing required claim: sub');
|
|
37
37
|
}
|
|
38
|
+
const roles = Array.isArray(payload.roles)
|
|
39
|
+
? payload.roles.filter((r) => typeof r === 'string')
|
|
40
|
+
: payload.role
|
|
41
|
+
? [payload.role]
|
|
42
|
+
: [];
|
|
38
43
|
return {
|
|
39
44
|
userId: payload.sub,
|
|
40
45
|
email: payload.email || '',
|
|
41
|
-
role: payload.role
|
|
46
|
+
role: roles[0] ?? payload.role ?? '',
|
|
47
|
+
roles,
|
|
48
|
+
isSystemAdmin: payload.is_system_admin === true,
|
|
42
49
|
orgId: payload.org_id || '',
|
|
43
50
|
tenantId: payload.tenant_id || payload.org_id || '',
|
|
44
51
|
permissions: Array.isArray(payload.permissions) ? payload.permissions : [],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gateway-header.strategy.js","sourceRoot":"","sources":["../../src/strategies/gateway-header.strategy.ts"],"names":[],"mappings":";;;AACA,sCAAsC;AAEtC,sCAA8C;AAG9C;;;GAGG;AACH,MAAa,qBAAqB;IAAlC;QACW,SAAI,GAAG,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"gateway-header.strategy.js","sourceRoot":"","sources":["../../src/strategies/gateway-header.strategy.ts"],"names":[],"mappings":";;;AACA,sCAAsC;AAEtC,sCAA8C;AAG9C;;;GAGG;AACH,MAAa,qBAAqB;IAAlC;QACW,SAAI,GAAG,gBAAgB,CAAC;IAgDnC,CAAC;IA9CC,SAAS,CAAC,GAAY;QACpB,MAAM,MAAM,GAAG,IAAA,kBAAS,GAAE,CAAC;QAC3B,OAAO,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC;IACjD,CAAC;IAED,OAAO,CAAC,GAAY;QAClB,MAAM,MAAM,GAAG,IAAA,kBAAS,GAAE,CAAC;QAC3B,MAAM,WAAW,GAAG,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,iBAAiB,CAAW,CAAC;QAEpE,IAAI,OAAe,CAAC;QACpB,IAAI,CAAC;YACH,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QACjE,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,IAAI,0BAAiB,CAAC,iCAAiC,CAAC,CAAC;QACjE,CAAC;QAED,IAAI,OAAmB,CAAC;QACxB,IAAI,CAAC;YACH,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAChC,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,IAAI,0BAAiB,CAAC,6BAA6B,CAAC,CAAC;QAC7D,CAAC;QAED,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;YACjB,MAAM,IAAI,0BAAiB,CAAC,mCAAmC,CAAC,CAAC;QACnE,CAAC;QAED,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC;YACxC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC;YACjE,CAAC,CAAC,OAAO,CAAC,IAAI;gBACZ,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC;gBAChB,CAAC,CAAC,EAAE,CAAC;QAET,OAAO;YACL,MAAM,EAAE,OAAO,CAAC,GAAG;YACnB,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,EAAE;YAC1B,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,IAAI,IAAI,EAAE;YACpC,KAAK;YACL,aAAa,EAAE,OAAO,CAAC,eAAe,KAAK,IAAI;YAC/C,KAAK,EAAE,OAAO,CAAC,MAAM,IAAI,EAAE;YAC3B,QAAQ,EAAE,OAAO,CAAC,SAAS,IAAI,OAAO,CAAC,MAAM,IAAI,EAAE;YACnD,WAAW,EAAE,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE;YAC1E,SAAS,EAAG,GAAG,CAAC,OAAO,CAAC,cAAc,CAAY,IAAI,EAAE;YACxD,UAAU,EAAE,gBAAgB;SAC7B,CAAC;IACJ,CAAC;CACF;AAjDD,sDAiDC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jwt.strategy.d.ts","sourceRoot":"","sources":["../../src/strategies/jwt.strategy.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAElC,OAAO,EAAE,QAAQ,EAAc,MAAM,UAAU,CAAC;AAEhD,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAE9D;;;GAGG;AACH,qBAAa,WAAY,YAAW,sBAAsB;IACxD,QAAQ,CAAC,IAAI,SAAS;IAEtB,SAAS,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO;IAIhC,OAAO,CAAC,GAAG,EAAE,OAAO,GAAG,QAAQ;
|
|
1
|
+
{"version":3,"file":"jwt.strategy.d.ts","sourceRoot":"","sources":["../../src/strategies/jwt.strategy.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAElC,OAAO,EAAE,QAAQ,EAAc,MAAM,UAAU,CAAC;AAEhD,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAE9D;;;GAGG;AACH,qBAAa,WAAY,YAAW,sBAAsB;IACxD,QAAQ,CAAC,IAAI,SAAS;IAEtB,SAAS,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO;IAIhC,OAAO,CAAC,GAAG,EAAE,OAAO,GAAG,QAAQ;CAsDhC"}
|
|
@@ -78,10 +78,17 @@ class JwtStrategy {
|
|
|
78
78
|
if (!decoded.sub) {
|
|
79
79
|
throw new errors_1.UnauthorizedError('Token missing required claim: sub');
|
|
80
80
|
}
|
|
81
|
+
const roles = Array.isArray(decoded.roles)
|
|
82
|
+
? decoded.roles.filter((r) => typeof r === 'string')
|
|
83
|
+
: decoded.role
|
|
84
|
+
? [decoded.role]
|
|
85
|
+
: [];
|
|
81
86
|
return {
|
|
82
87
|
userId: decoded.sub,
|
|
83
88
|
email: decoded.email || '',
|
|
84
|
-
role: decoded.role
|
|
89
|
+
role: roles[0] ?? decoded.role ?? '',
|
|
90
|
+
roles,
|
|
91
|
+
isSystemAdmin: decoded.is_system_admin === true,
|
|
85
92
|
orgId: decoded.org_id || '',
|
|
86
93
|
tenantId: decoded.tenant_id || decoded.org_id || '',
|
|
87
94
|
permissions: Array.isArray(decoded.permissions) ? decoded.permissions : [],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jwt.strategy.js","sourceRoot":"","sources":["../../src/strategies/jwt.strategy.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,kDAAoC;AAEpC,sCAAsC;AAEtC,sCAA8C;AAG9C;;;GAGG;AACH,MAAa,WAAW;IAAxB;QACW,SAAI,GAAG,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"jwt.strategy.js","sourceRoot":"","sources":["../../src/strategies/jwt.strategy.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"trusted-headers.strategy.d.ts","sourceRoot":"","sources":["../../src/strategies/trusted-headers.strategy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAElC,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEpC,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAE9D;;;;;;GAMG;AACH,qBAAa,sBAAuB,YAAW,sBAAsB;IACnE,QAAQ,CAAC,IAAI,qBAAqB;IAElC,SAAS,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO;IAMhC,OAAO,CAAC,GAAG,EAAE,OAAO,GAAG,QAAQ;
|
|
1
|
+
{"version":3,"file":"trusted-headers.strategy.d.ts","sourceRoot":"","sources":["../../src/strategies/trusted-headers.strategy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAElC,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEpC,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAE9D;;;;;;GAMG;AACH,qBAAa,sBAAuB,YAAW,sBAAsB;IACnE,QAAQ,CAAC,IAAI,qBAAqB;IAElC,SAAS,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO;IAMhC,OAAO,CAAC,GAAG,EAAE,OAAO,GAAG,QAAQ;CA+ChC"}
|
|
@@ -34,10 +34,25 @@ class TrustedHeadersStrategy {
|
|
|
34
34
|
}
|
|
35
35
|
}
|
|
36
36
|
const orgId = req.headers[headerNames.orgId] || '';
|
|
37
|
+
// Prefer `x-user-roles` (comma-separated) over the legacy single-role header.
|
|
38
|
+
const rawRolesHeader = req.headers[headerNames.roles];
|
|
39
|
+
const legacyRole = req.headers[headerNames.userRole] || '';
|
|
40
|
+
const roles = rawRolesHeader
|
|
41
|
+
? rawRolesHeader
|
|
42
|
+
.split(',')
|
|
43
|
+
.map((r) => r.trim())
|
|
44
|
+
.filter((r) => r.length > 0)
|
|
45
|
+
: legacyRole
|
|
46
|
+
? [legacyRole]
|
|
47
|
+
: [];
|
|
48
|
+
const isAdminHeader = req.headers[headerNames.isSystemAdmin] ?? '';
|
|
49
|
+
const isSystemAdmin = ['true', '1', 'yes'].includes(isAdminHeader.trim().toLowerCase());
|
|
37
50
|
return {
|
|
38
51
|
userId,
|
|
39
52
|
email: '',
|
|
40
|
-
role:
|
|
53
|
+
role: roles[0] ?? legacyRole,
|
|
54
|
+
roles,
|
|
55
|
+
isSystemAdmin,
|
|
41
56
|
orgId,
|
|
42
57
|
tenantId: orgId,
|
|
43
58
|
permissions: [],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"trusted-headers.strategy.js","sourceRoot":"","sources":["../../src/strategies/trusted-headers.strategy.ts"],"names":[],"mappings":";;;AACA,sCAAsC;AAEtC,sCAA8C;AAG9C;;;;;;GAMG;AACH,MAAa,sBAAsB;IAAnC;QACW,SAAI,GAAG,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"trusted-headers.strategy.js","sourceRoot":"","sources":["../../src/strategies/trusted-headers.strategy.ts"],"names":[],"mappings":";;;AACA,sCAAsC;AAEtC,sCAA8C;AAG9C;;;;;;GAMG;AACH,MAAa,sBAAsB;IAAnC;QACW,SAAI,GAAG,iBAAiB,CAAC;IAuDpC,CAAC;IArDC,SAAS,CAAC,GAAY;QACpB,MAAM,MAAM,GAAG,IAAA,kBAAS,GAAE,CAAC;QAC3B,MAAM,WAAW,GAAG,MAAM,CAAC,kBAAkB,CAAC;QAC9C,OAAO,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;IAC3C,CAAC;IAED,OAAO,CAAC,GAAY;QAClB,MAAM,MAAM,GAAG,IAAA,kBAAS,GAAE,CAAC;QAC3B,MAAM,WAAW,GAAG,MAAM,CAAC,kBAAkB,CAAC;QAE9C,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC,MAAM,CAAuB,CAAC;QACrE,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,0BAAiB,CAAC,0CAA0C,CAAC,CAAC;QAC1E,CAAC;QAED,uCAAuC;QACvC,IAAI,MAAM,CAAC,oBAAoB,EAAE,CAAC;YAChC,MAAM,YAAY,GAAG,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC,YAAY,CAAuB,CAAC;YACjF,IAAI,YAAY,KAAK,MAAM,CAAC,oBAAoB,EAAE,CAAC;gBACjD,MAAM,IAAI,0BAAiB,CAAC,kCAAkC,CAAC,CAAC;YAClE,CAAC;QACH,CAAC;QAED,MAAM,KAAK,GAAI,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC,KAAK,CAAY,IAAI,EAAE,CAAC;QAE/D,8EAA8E;QAC9E,MAAM,cAAc,GAAG,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC,KAAK,CAAuB,CAAC;QAC5E,MAAM,UAAU,GAAI,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC,QAAQ,CAAY,IAAI,EAAE,CAAC;QACvE,MAAM,KAAK,GAAa,cAAc;YACpC,CAAC,CAAC,cAAc;iBACX,KAAK,CAAC,GAAG,CAAC;iBACV,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;iBACpB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;YAChC,CAAC,CAAC,UAAU;gBACV,CAAC,CAAC,CAAC,UAAU,CAAC;gBACd,CAAC,CAAC,EAAE,CAAC;QAET,MAAM,aAAa,GAAI,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC,aAAa,CAAwB,IAAI,EAAE,CAAC;QAC3F,MAAM,aAAa,GAAG,CAAC,MAAM,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC;QAExF,OAAO;YACL,MAAM;YACN,KAAK,EAAE,EAAE;YACT,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,UAAU;YAC5B,KAAK;YACL,aAAa;YACb,KAAK;YACL,QAAQ,EAAE,KAAK;YACf,WAAW,EAAE,EAAE;YACf,SAAS,EAAG,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC,SAAS,CAAY,IAAI,EAAE;YAC/D,UAAU,EAAE,iBAAiB;SAC9B,CAAC;IACJ,CAAC;CACF;AAxDD,wDAwDC"}
|
package/dist/types.d.ts
CHANGED
|
@@ -3,9 +3,34 @@ export type UserRole = 'system_admin' | 'org_admin' | 'user' | (string & {});
|
|
|
3
3
|
export interface AuthUser {
|
|
4
4
|
userId: string;
|
|
5
5
|
email: string;
|
|
6
|
+
/**
|
|
7
|
+
* @deprecated Use `roles` (array) instead. This is `roles[0] ?? ''` for
|
|
8
|
+
* backwards compatibility with callers that haven't migrated yet.
|
|
9
|
+
*/
|
|
6
10
|
role: UserRole;
|
|
11
|
+
/** All roles assigned to this user in their current org. */
|
|
12
|
+
roles: string[];
|
|
13
|
+
/**
|
|
14
|
+
* True when this user is a cross-tenant Global Tracking platform staff
|
|
15
|
+
* member. Sourced from `users.is_system_admin` via the JWT. Grants a
|
|
16
|
+
* middleware-level bypass on permission checks AND allows cross-tenant
|
|
17
|
+
* action via `X-Acting-On-Org`.
|
|
18
|
+
*/
|
|
19
|
+
isSystemAdmin: boolean;
|
|
7
20
|
orgId: string;
|
|
8
21
|
tenantId: string;
|
|
22
|
+
/**
|
|
23
|
+
* When a system admin used `X-Acting-On-Org` to target a different tenant,
|
|
24
|
+
* this records their HOME org (the org they logged in as). Downstream
|
|
25
|
+
* audit logging should include this so staff actions on customer tenants
|
|
26
|
+
* are traceable.
|
|
27
|
+
*/
|
|
28
|
+
actingOnOrg?: {
|
|
29
|
+
/** The system admin's original home org (from their JWT). */
|
|
30
|
+
homeOrgId: string;
|
|
31
|
+
/** The org they are currently acting on (= `orgId`). */
|
|
32
|
+
targetOrgId: string;
|
|
33
|
+
};
|
|
9
34
|
permissions: string[];
|
|
10
35
|
requestId: string;
|
|
11
36
|
authSource: AuthStrategy;
|
|
@@ -16,6 +41,9 @@ export interface TrustedHeaderNames {
|
|
|
16
41
|
userId?: string;
|
|
17
42
|
orgId?: string;
|
|
18
43
|
userRole?: string;
|
|
44
|
+
roles?: string;
|
|
45
|
+
isSystemAdmin?: string;
|
|
46
|
+
actingOnOrg?: string;
|
|
19
47
|
requestId?: string;
|
|
20
48
|
gatewayToken?: string;
|
|
21
49
|
}
|
|
@@ -32,7 +60,14 @@ export interface AuthConfig {
|
|
|
32
60
|
superAdminRole?: string;
|
|
33
61
|
/** Ordered list of strategies to try. Default: ['gateway-header', 'jwt'] */
|
|
34
62
|
strategies?: AuthStrategy[];
|
|
35
|
-
/**
|
|
63
|
+
/**
|
|
64
|
+
* RBAC role names that receive a permission-check bypass within their own
|
|
65
|
+
* tenant. Default: ['org_admin'].
|
|
66
|
+
*
|
|
67
|
+
* Note: `system_admin` is NOT on this list — system-admin bypass is
|
|
68
|
+
* sourced from the `is_system_admin` claim, and (unlike org_admin) comes
|
|
69
|
+
* with cross-tenant authority via `X-Acting-On-Org`.
|
|
70
|
+
*/
|
|
36
71
|
adminRoles?: string[];
|
|
37
72
|
/** Shared secret for InternalOnlyGuard. Also reads from env INTERNAL_GATEWAY_TOKEN */
|
|
38
73
|
internalGatewayToken?: string;
|
|
@@ -46,7 +81,15 @@ export interface AuthConfig {
|
|
|
46
81
|
export interface JwtPayload {
|
|
47
82
|
sub: string;
|
|
48
83
|
email: string;
|
|
49
|
-
|
|
84
|
+
/** @deprecated Prefer `roles` (array). Kept as `roles[0]` for older consumers. */
|
|
85
|
+
role?: string;
|
|
86
|
+
/** All RBAC role names assigned to this user in their current org. */
|
|
87
|
+
roles?: string[];
|
|
88
|
+
/**
|
|
89
|
+
* Whether this user is a Global Tracking platform-staff member
|
|
90
|
+
* (`users.is_system_admin = TRUE`). Grants cross-tenant privilege.
|
|
91
|
+
*/
|
|
92
|
+
is_system_admin?: boolean;
|
|
50
93
|
tenant_id: string;
|
|
51
94
|
org_id: string;
|
|
52
95
|
permissions: string[];
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GAAG,gBAAgB,GAAG,iBAAiB,GAAG,KAAK,CAAC;AAExE,MAAM,MAAM,QAAQ,GAAG,cAAc,GAAG,WAAW,GAAG,MAAM,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;AAE7E,MAAM,WAAW,QAAQ;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,YAAY,CAAC;CAC1B;AAED,wEAAwE;AACxE,MAAM,MAAM,WAAW,GAAG,QAAQ,CAAC;AAEnC,MAAM,WAAW,kBAAkB;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,UAAU;IACzB,sFAAsF;IACtF,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,oFAAoF;IACpF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gEAAgE;IAChE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,+DAA+D;IAC/D,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB,oEAAoE;IACpE,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB,4EAA4E;IAC5E,UAAU,CAAC,EAAE,YAAY,EAAE,CAAC;IAC5B
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/utils/helpers.d.ts
CHANGED
|
@@ -1,8 +1,21 @@
|
|
|
1
1
|
import { AuthUser } from '../types';
|
|
2
2
|
/**
|
|
3
|
-
* Check if a user has
|
|
3
|
+
* Check if a user has ANY of the specified roles. Checks the full `roles`
|
|
4
|
+
* array, not just the legacy `role` single-value field.
|
|
4
5
|
*/
|
|
5
6
|
export declare function hasRole(user: AuthUser, ...roles: string[]): boolean;
|
|
7
|
+
/**
|
|
8
|
+
* True when this user is a Global Tracking platform-staff member (from
|
|
9
|
+
* the `is_system_admin` JWT claim). System admins get cross-tenant scope
|
|
10
|
+
* via the `X-Acting-On-Org` header and bypass permission checks
|
|
11
|
+
* unconditionally.
|
|
12
|
+
*/
|
|
13
|
+
export declare function isSystemAdmin(user: AuthUser): boolean;
|
|
14
|
+
/**
|
|
15
|
+
* True when this user has the `org_admin` RBAC role in their tenant.
|
|
16
|
+
* org_admin does NOT cross tenants; their bypass is scoped to `user.orgId`.
|
|
17
|
+
*/
|
|
18
|
+
export declare function isOrgAdmin(user: AuthUser): boolean;
|
|
6
19
|
/**
|
|
7
20
|
* Check if a user has ALL of the specified permissions.
|
|
8
21
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/utils/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEpC
|
|
1
|
+
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/utils/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEpC;;;GAGG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAGnE;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAErD;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAElD;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,QAAQ,EAAE,GAAG,WAAW,EAAE,MAAM,EAAE,GAAG,OAAO,CAG/E;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,QAAQ,EAAE,GAAG,WAAW,EAAE,MAAM,EAAE,GAAG,OAAO,CAGlF"}
|
package/dist/utils/helpers.js
CHANGED
|
@@ -1,13 +1,33 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.hasRole = hasRole;
|
|
4
|
+
exports.isSystemAdmin = isSystemAdmin;
|
|
5
|
+
exports.isOrgAdmin = isOrgAdmin;
|
|
4
6
|
exports.hasPermission = hasPermission;
|
|
5
7
|
exports.hasAnyPermission = hasAnyPermission;
|
|
6
8
|
/**
|
|
7
|
-
* Check if a user has
|
|
9
|
+
* Check if a user has ANY of the specified roles. Checks the full `roles`
|
|
10
|
+
* array, not just the legacy `role` single-value field.
|
|
8
11
|
*/
|
|
9
12
|
function hasRole(user, ...roles) {
|
|
10
|
-
|
|
13
|
+
const userRoles = new Set(user.roles);
|
|
14
|
+
return roles.some((r) => userRoles.has(r));
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* True when this user is a Global Tracking platform-staff member (from
|
|
18
|
+
* the `is_system_admin` JWT claim). System admins get cross-tenant scope
|
|
19
|
+
* via the `X-Acting-On-Org` header and bypass permission checks
|
|
20
|
+
* unconditionally.
|
|
21
|
+
*/
|
|
22
|
+
function isSystemAdmin(user) {
|
|
23
|
+
return user.isSystemAdmin === true;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* True when this user has the `org_admin` RBAC role in their tenant.
|
|
27
|
+
* org_admin does NOT cross tenants; their bypass is scoped to `user.orgId`.
|
|
28
|
+
*/
|
|
29
|
+
function isOrgAdmin(user) {
|
|
30
|
+
return user.roles.includes('org_admin');
|
|
11
31
|
}
|
|
12
32
|
/**
|
|
13
33
|
* Check if a user has ALL of the specified permissions.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../src/utils/helpers.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../src/utils/helpers.ts"],"names":[],"mappings":";;AAMA,0BAGC;AAQD,sCAEC;AAMD,gCAEC;AAKD,sCAGC;AAKD,4CAGC;AAzCD;;;GAGG;AACH,SAAgB,OAAO,CAAC,IAAc,EAAE,GAAG,KAAe;IACxD,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACtC,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;AAC7C,CAAC;AAED;;;;;GAKG;AACH,SAAgB,aAAa,CAAC,IAAc;IAC1C,OAAO,IAAI,CAAC,aAAa,KAAK,IAAI,CAAC;AACrC,CAAC;AAED;;;GAGG;AACH,SAAgB,UAAU,CAAC,IAAc;IACvC,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;AAC1C,CAAC;AAED;;GAEG;AACH,SAAgB,aAAa,CAAC,IAAc,EAAE,GAAG,WAAqB;IACpE,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC5C,OAAO,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;AACpD,CAAC;AAED;;GAEG;AACH,SAAgB,gBAAgB,CAAC,IAAc,EAAE,GAAG,WAAqB;IACvE,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC5C,OAAO,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;AACnD,CAAC"}
|
package/dist/utils/jwt.js
CHANGED
|
@@ -90,10 +90,17 @@ function mapPayloadToUser(payload, authSource) {
|
|
|
90
90
|
if (!payload.sub) {
|
|
91
91
|
throw new errors_1.UnauthorizedError('Token missing required claim: sub');
|
|
92
92
|
}
|
|
93
|
+
const roles = Array.isArray(payload.roles)
|
|
94
|
+
? payload.roles.filter((r) => typeof r === 'string')
|
|
95
|
+
: payload.role
|
|
96
|
+
? [payload.role]
|
|
97
|
+
: [];
|
|
93
98
|
return {
|
|
94
99
|
userId: payload.sub,
|
|
95
100
|
email: payload.email || '',
|
|
96
|
-
role: payload.role
|
|
101
|
+
role: roles[0] ?? payload.role ?? '',
|
|
102
|
+
roles,
|
|
103
|
+
isSystemAdmin: payload.is_system_admin === true,
|
|
97
104
|
tenantId: payload.tenant_id || payload.org_id || '',
|
|
98
105
|
orgId: payload.org_id || '',
|
|
99
106
|
permissions: Array.isArray(payload.permissions) ? payload.permissions : [],
|
package/dist/utils/jwt.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jwt.js","sourceRoot":"","sources":["../../src/utils/jwt.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AASA,kCA2BC;AAMD,kDAkBC;AA5DD,kDAAoC;AACpC,sCAAsC;AAEtC,sCAA8C;AAE9C;;;GAGG;AACH,SAAgB,WAAW,CAAC,KAAa;IACvC,MAAM,MAAM,GAAG,IAAA,kBAAS,GAAE,CAAC;IAE3B,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;QACtB,MAAM,IAAI,0BAAiB,CACzB,2DAA2D,CAC5D,CAAC;IACJ,CAAC;IAED,IAAI,OAAmB,CAAC;IAExB,IAAI,CAAC;QACH,OAAO,GAAG,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,SAAS,EAAE;YAC5C,UAAU,EAAE,CAAC,OAAO,CAAC;YACrB,MAAM,EAAE,MAAM,CAAC,SAAS,IAAI,SAAS;SACtC,CAAe,CAAC;IACnB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,YAAY,GAAG,CAAC,iBAAiB,EAAE,CAAC;YACzC,MAAM,IAAI,0BAAiB,CAAC,mBAAmB,CAAC,CAAC;QACnD,CAAC;QACD,IAAI,GAAG,YAAY,GAAG,CAAC,iBAAiB,EAAE,CAAC;YACzC,MAAM,IAAI,0BAAiB,CAAC,kBAAkB,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;QAC/D,CAAC;QACD,MAAM,IAAI,0BAAiB,CAAC,2BAA2B,CAAC,CAAC;IAC3D,CAAC;IAED,OAAO,gBAAgB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;AAC1C,CAAC;AAED;;;GAGG;AACH,SAAgB,mBAAmB,CAAC,WAAmB;IACrD,IAAI,OAAe,CAAC;IAEpB,IAAI,CAAC;QACH,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IACjE,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,0BAAiB,CAAC,iCAAiC,CAAC,CAAC;IACjE,CAAC;IAED,IAAI,OAAmB,CAAC;IAExB,IAAI,CAAC;QACH,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAChC,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,0BAAiB,CAAC,6BAA6B,CAAC,CAAC;IAC7D,CAAC;IAED,OAAO,gBAAgB,CAAC,OAAO,EAAE,gBAAgB,CAAC,CAAC;AACrD,CAAC;AAED,SAAS,gBAAgB,CAAC,OAAmB,EAAE,UAAoC;IACjF,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;QACjB,MAAM,IAAI,0BAAiB,CAAC,mCAAmC,CAAC,CAAC;IACnE,CAAC;IAED,OAAO;QACL,MAAM,EAAE,OAAO,CAAC,GAAG;QACnB,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,EAAE;QAC1B,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,EAAE;
|
|
1
|
+
{"version":3,"file":"jwt.js","sourceRoot":"","sources":["../../src/utils/jwt.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@globaltracking/auth-middleware",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "Unified authentication and authorization middleware for the Global Tracking platform (Express + NestJS)",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
],
|
|
20
20
|
"scripts": {
|
|
21
21
|
"build": "tsc -p tsconfig.build.json",
|
|
22
|
-
"clean": "
|
|
22
|
+
"clean": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\"",
|
|
23
23
|
"prebuild": "npm run clean",
|
|
24
24
|
"test": "jest --coverage",
|
|
25
25
|
"test:watch": "jest --watch",
|