grm-shared-library 1.1.39 → 1.1.41
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/cjs/index.js +1 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/modules/common/index.js +2 -0
- package/dist/cjs/modules/common/index.js.map +1 -1
- package/dist/cjs/modules/common/interfaces/access-validation.interface.js +3 -0
- package/dist/cjs/modules/common/interfaces/access-validation.interface.js.map +1 -0
- package/dist/cjs/modules/common/services/access-validation.service.js +124 -0
- package/dist/cjs/modules/common/services/access-validation.service.js.map +1 -0
- package/dist/cjs/modules/common/services/index.js +19 -0
- package/dist/cjs/modules/common/services/index.js.map +1 -0
- package/dist/cjs/modules/common/services/user-context-header.service.js +74 -0
- package/dist/cjs/modules/common/services/user-context-header.service.js.map +1 -0
- package/dist/cjs/utilities/user-context-header.service.js +0 -72
- package/dist/cjs/utilities/user-context-header.service.js.map +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/modules/common/index.js +2 -0
- package/dist/esm/modules/common/index.js.map +1 -1
- package/dist/esm/modules/common/interfaces/access-validation.interface.js +2 -0
- package/dist/esm/modules/common/interfaces/access-validation.interface.js.map +1 -0
- package/dist/esm/modules/common/services/access-validation.service.js +120 -0
- package/dist/esm/modules/common/services/access-validation.service.js.map +1 -0
- package/dist/esm/modules/common/services/index.js +3 -0
- package/dist/esm/modules/common/services/index.js.map +1 -0
- package/dist/esm/modules/common/services/user-context-header.service.js +70 -0
- package/dist/esm/modules/common/services/user-context-header.service.js.map +1 -0
- package/dist/esm/utilities/user-context-header.service.js +1 -69
- package/dist/esm/utilities/user-context-header.service.js.map +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/modules/common/index.d.ts +2 -0
- package/dist/types/modules/common/interfaces/access-validation.interface.d.ts +21 -0
- package/dist/types/modules/common/services/access-validation.service.d.ts +48 -0
- package/dist/types/modules/common/services/index.d.ts +2 -0
- package/dist/types/modules/common/services/user-context-header.service.d.ts +19 -0
- package/dist/types/utilities/user-context-header.service.d.ts +0 -19
- package/package.json +1 -1
package/dist/cjs/index.js
CHANGED
|
@@ -39,7 +39,7 @@ __exportStar(require("./constants/http-headers"), exports);
|
|
|
39
39
|
__exportStar(require("./kafka/index"), exports);
|
|
40
40
|
// Utilities
|
|
41
41
|
__exportStar(require("./decorators/case-decorators"), exports);
|
|
42
|
-
__exportStar(require("./
|
|
42
|
+
__exportStar(require("./modules/common/services/user-context-header.service"), exports);
|
|
43
43
|
// Exceptions
|
|
44
44
|
__exportStar(require("./exceptions/index"), exports);
|
|
45
45
|
//# sourceMappingURL=index.js.map
|
package/dist/cjs/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,UAAU;AACV,uDAAqC;AACrC,+DAA6C;AAC7C,yDAAuC;AACvC,6DAA2C;AAC3C,uDAAqC;AACrC,uDAAqC;AACrC,iEAA+C;AAC/C,wDAAsC;AACtC,gEAA8C;AAC9C,2DAAyC;AACzC,2DAAyC;AACzC,sDAAoC;AAEpC,aAAa;AACb,8DAA4C;AAC5C,mEAAiD;AACjD,8DAA4C;AAC5C,2DAAyC;AACzC,0DAAwC;AAExC,YAAY;AACZ,2DAAyC;AAEzC,QAAQ;AACR,gDAA8B;AAE9B,YAAY;AACZ,+DAA6C;AAC7C,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,UAAU;AACV,uDAAqC;AACrC,+DAA6C;AAC7C,yDAAuC;AACvC,6DAA2C;AAC3C,uDAAqC;AACrC,uDAAqC;AACrC,iEAA+C;AAC/C,wDAAsC;AACtC,gEAA8C;AAC9C,2DAAyC;AACzC,2DAAyC;AACzC,sDAAoC;AAEpC,aAAa;AACb,8DAA4C;AAC5C,mEAAiD;AACjD,8DAA4C;AAC5C,2DAAyC;AACzC,0DAAwC;AAExC,YAAY;AACZ,2DAAyC;AAEzC,QAAQ;AACR,gDAA8B;AAE9B,YAAY;AACZ,+DAA6C;AAC7C,wFAAsE;AAEtE,aAAa;AACb,qDAAmC"}
|
|
@@ -20,5 +20,7 @@ __exportStar(require("./dtos/contact-person.dto"), exports);
|
|
|
20
20
|
__exportStar(require("./interfaces/map-location"), exports);
|
|
21
21
|
__exportStar(require("./interfaces/map-address"), exports);
|
|
22
22
|
__exportStar(require("./interfaces/contact-person"), exports);
|
|
23
|
+
__exportStar(require("./interfaces/access-validation.interface"), exports);
|
|
23
24
|
__exportStar(require("./constants/service.const"), exports);
|
|
25
|
+
__exportStar(require("./services"), exports);
|
|
24
26
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/modules/common/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,0DAAwC;AACxC,yDAAuC;AACvC,4DAA0C;AAC1C,4DAA0C;AAC1C,2DAAyC;AACzC,8DAA4C;AAC5C,4DAA0C"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/modules/common/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,0DAAwC;AACxC,yDAAuC;AACvC,4DAA0C;AAC1C,4DAA0C;AAC1C,2DAAyC;AACzC,8DAA4C;AAC5C,2EAAyD;AACzD,4DAA0C;AAC1C,6CAA2B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"access-validation.interface.js","sourceRoot":"","sources":["../../../../../src/modules/common/interfaces/access-validation.interface.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AccessValidationService = void 0;
|
|
4
|
+
const common_1 = require("@nestjs/common");
|
|
5
|
+
/**
|
|
6
|
+
* Service for validating access control across microservices
|
|
7
|
+
* Provides centralized validation logic to ensure consistency
|
|
8
|
+
*/
|
|
9
|
+
class AccessValidationService {
|
|
10
|
+
/**
|
|
11
|
+
* Validates if a user has access to perform list operations
|
|
12
|
+
* @param accessScope - The access scope for the user
|
|
13
|
+
* @param pluralEntityName - The name of the entities being accessed (for error messages)
|
|
14
|
+
*/
|
|
15
|
+
validateListAccess(accessScope, pluralEntityName = 'entities') {
|
|
16
|
+
if (accessScope.isSuperAdmin) {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
if (accessScope.organizationFilter || accessScope.controlCentreFilter) {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
throw new common_1.ForbiddenException(`Access denied: Insufficient permissions to access ${pluralEntityName}`);
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Validates if a user has access to a specific entity
|
|
26
|
+
* @param accessScope - The access scope for the user
|
|
27
|
+
* @param entity - The entity to check access for
|
|
28
|
+
* @param entityName - The name of the entity (for error messages)
|
|
29
|
+
*/
|
|
30
|
+
validateEntityAccess(accessScope, entity, entityName = 'Entity') {
|
|
31
|
+
if (accessScope.isSuperAdmin) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
if (accessScope.organizationFilter && entity.organizationId === accessScope.organizationFilter) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
if (accessScope.controlCentreFilter && entity.controlCentreId === accessScope.controlCentreFilter) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
throw new common_1.ForbiddenException(`Access denied: Insufficient permissions to access this ${entityName.toLowerCase()}`);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Validates if a user can create an entity with the specified organization/control centre
|
|
44
|
+
* @param accessScope - The access scope for the user
|
|
45
|
+
* @param createDto - The DTO containing organizationId/controlCentreId
|
|
46
|
+
* @param entityName - The name of the entity (for error messages)
|
|
47
|
+
*/
|
|
48
|
+
validateCreateAccess(accessScope, createDto, entityName = 'entity') {
|
|
49
|
+
if (accessScope.isSuperAdmin) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
// Check organization level access
|
|
53
|
+
if (createDto.organizationId) {
|
|
54
|
+
if (accessScope.organizationFilter && createDto.organizationId !== accessScope.organizationFilter) {
|
|
55
|
+
throw new common_1.ForbiddenException(`Cannot create ${entityName} for this organization`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
// Check control centre level access
|
|
59
|
+
if (createDto.controlCentreId) {
|
|
60
|
+
if (accessScope.controlCentreFilter && createDto.controlCentreId !== accessScope.controlCentreFilter) {
|
|
61
|
+
throw new common_1.ForbiddenException(`Cannot create ${entityName} for this control centre`);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
// Ensure user has at least organization or control centre level access
|
|
65
|
+
if (!accessScope.organizationFilter && !accessScope.controlCentreFilter) {
|
|
66
|
+
throw new common_1.ForbiddenException(`Insufficient permissions to create ${entityName}`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Validates if a user has access to update entities
|
|
71
|
+
* @param accessScope - The access scope for the user
|
|
72
|
+
* @param entityName - The name of the entity (for error messages)
|
|
73
|
+
*/
|
|
74
|
+
validateUpdateAccess(accessScope, entityName = 'entity') {
|
|
75
|
+
if (accessScope.isSuperAdmin) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
// Ensure user has at least organization or control centre level access
|
|
79
|
+
if (!accessScope.organizationFilter && !accessScope.controlCentreFilter) {
|
|
80
|
+
throw new common_1.ForbiddenException(`Insufficient permissions to update ${entityName}`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Validates if a user has access to delete entities
|
|
85
|
+
* @param accessScope - The access scope for the user
|
|
86
|
+
* @param entityName - The name of the entity (for error messages)
|
|
87
|
+
*/
|
|
88
|
+
validateDeleteAccess(accessScope, entityName = 'entity') {
|
|
89
|
+
if (accessScope.isSuperAdmin) {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
// Ensure user has at least organization or control centre level access
|
|
93
|
+
if (!accessScope.organizationFilter && !accessScope.controlCentreFilter) {
|
|
94
|
+
throw new common_1.ForbiddenException(`Insufficient permissions to delete ${entityName}`);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Validates if a user can update an entity with the specified organization/control centre changes
|
|
99
|
+
* @param accessScope - The access scope for the user
|
|
100
|
+
* @param existingEntity - The existing entity
|
|
101
|
+
* @param updateDto - The DTO containing updated organizationId/controlCentreId
|
|
102
|
+
* @param entityName - The name of the entity (for error messages)
|
|
103
|
+
*/
|
|
104
|
+
validateUpdateEntityAccess(accessScope, existingEntity, updateDto, entityName = 'entity') {
|
|
105
|
+
// First validate access to the existing entity
|
|
106
|
+
this.validateEntityAccess(accessScope, existingEntity, entityName);
|
|
107
|
+
// Then validate update permissions
|
|
108
|
+
this.validateUpdateAccess(accessScope, entityName);
|
|
109
|
+
// If organization is being changed, validate access to new organization
|
|
110
|
+
if (updateDto.organizationId && updateDto.organizationId !== existingEntity.organizationId) {
|
|
111
|
+
if (accessScope.organizationFilter && updateDto.organizationId !== accessScope.organizationFilter) {
|
|
112
|
+
throw new common_1.ForbiddenException(`Cannot move ${entityName} to this organization`);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
// If control centre is being changed, validate access to new control centre
|
|
116
|
+
if (updateDto.controlCentreId && updateDto.controlCentreId !== existingEntity.controlCentreId) {
|
|
117
|
+
if (accessScope.controlCentreFilter && updateDto.controlCentreId !== accessScope.controlCentreFilter) {
|
|
118
|
+
throw new common_1.ForbiddenException(`Cannot move ${entityName} to this control centre`);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
exports.AccessValidationService = AccessValidationService;
|
|
124
|
+
//# sourceMappingURL=access-validation.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"access-validation.service.js","sourceRoot":"","sources":["../../../../../src/modules/common/services/access-validation.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./access-validation.service"), exports);
|
|
18
|
+
__exportStar(require("./user-context-header.service"), exports);
|
|
19
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/modules/common/services/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,8DAA4C;AAC5C,gEAA8C"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.UserContextHeaderService = void 0;
|
|
4
|
+
const http_headers_1 = require("../../../constants/http-headers");
|
|
5
|
+
/**
|
|
6
|
+
* Utility service for handling user context via HTTP headers
|
|
7
|
+
* This provides a consistent way to pass user context between API Gateway and microservices
|
|
8
|
+
*/
|
|
9
|
+
class UserContextHeaderService {
|
|
10
|
+
/**
|
|
11
|
+
* Convert UserContext to HTTP headers for microservice communication
|
|
12
|
+
*/
|
|
13
|
+
static buildHeaders(userContext) {
|
|
14
|
+
const headers = {};
|
|
15
|
+
headers[http_headers_1.HTTP_HEADERS.USER_ID] = userContext.userId.toString();
|
|
16
|
+
headers[http_headers_1.HTTP_HEADERS.USER_ROLES] = JSON.stringify(userContext.roles);
|
|
17
|
+
headers[http_headers_1.HTTP_HEADERS.ACCESS_SCOPE] = JSON.stringify(userContext.accessScope);
|
|
18
|
+
if (userContext.organizationId) {
|
|
19
|
+
headers[http_headers_1.HTTP_HEADERS.ORGANIZATION_ID] = userContext.organizationId.toString();
|
|
20
|
+
}
|
|
21
|
+
if (userContext.controlCentreId) {
|
|
22
|
+
headers[http_headers_1.HTTP_HEADERS.CONTROL_CENTRE_ID] = userContext.controlCentreId.toString();
|
|
23
|
+
}
|
|
24
|
+
// Also provide full context as single header for convenience
|
|
25
|
+
headers[http_headers_1.HTTP_HEADERS.USER_CONTEXT] = JSON.stringify(userContext);
|
|
26
|
+
return headers;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Extract UserContext from HTTP headers in microservices
|
|
30
|
+
*/
|
|
31
|
+
static extractFromHeaders(headers) {
|
|
32
|
+
try {
|
|
33
|
+
// First try to get full context from single header
|
|
34
|
+
const fullContextHeader = this.getHeaderValue(headers, http_headers_1.HTTP_HEADERS.USER_CONTEXT);
|
|
35
|
+
if (fullContextHeader) {
|
|
36
|
+
return JSON.parse(fullContextHeader);
|
|
37
|
+
}
|
|
38
|
+
// Fallback: reconstruct from individual headers
|
|
39
|
+
const userIdHeader = this.getHeaderValue(headers, http_headers_1.HTTP_HEADERS.USER_ID);
|
|
40
|
+
const rolesHeader = this.getHeaderValue(headers, http_headers_1.HTTP_HEADERS.USER_ROLES);
|
|
41
|
+
const accessScopeHeader = this.getHeaderValue(headers, http_headers_1.HTTP_HEADERS.ACCESS_SCOPE);
|
|
42
|
+
if (!userIdHeader || !rolesHeader || !accessScopeHeader) {
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
const userId = parseInt(userIdHeader);
|
|
46
|
+
const roles = JSON.parse(rolesHeader);
|
|
47
|
+
const accessScope = JSON.parse(accessScopeHeader);
|
|
48
|
+
const organizationIdHeader = this.getHeaderValue(headers, http_headers_1.HTTP_HEADERS.ORGANIZATION_ID);
|
|
49
|
+
const controlCentreIdHeader = this.getHeaderValue(headers, http_headers_1.HTTP_HEADERS.CONTROL_CENTRE_ID);
|
|
50
|
+
return {
|
|
51
|
+
userId,
|
|
52
|
+
roles,
|
|
53
|
+
accessScope,
|
|
54
|
+
organizationId: organizationIdHeader ? parseInt(organizationIdHeader) : undefined,
|
|
55
|
+
controlCentreId: controlCentreIdHeader ? parseInt(controlCentreIdHeader) : undefined
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
console.error('Error extracting user context from headers:', error);
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Helper to get header value (handles string | string[] types)
|
|
65
|
+
*/
|
|
66
|
+
static getHeaderValue(headers, key) {
|
|
67
|
+
const value = headers[key.toLowerCase()] || headers[key];
|
|
68
|
+
if (!value)
|
|
69
|
+
return null;
|
|
70
|
+
return Array.isArray(value) ? value[0] : value;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
exports.UserContextHeaderService = UserContextHeaderService;
|
|
74
|
+
//# sourceMappingURL=user-context-header.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"user-context-header.service.js","sourceRoot":"","sources":["../../../../../src/modules/common/services/user-context-header.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,74 +1,2 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.UserContextHeaderService = void 0;
|
|
4
|
-
const http_headers_1 = require("../constants/http-headers");
|
|
5
|
-
/**
|
|
6
|
-
* Utility service for handling user context via HTTP headers
|
|
7
|
-
* This provides a consistent way to pass user context between API Gateway and microservices
|
|
8
|
-
*/
|
|
9
|
-
class UserContextHeaderService {
|
|
10
|
-
/**
|
|
11
|
-
* Convert UserContext to HTTP headers for microservice communication
|
|
12
|
-
*/
|
|
13
|
-
static buildHeaders(userContext) {
|
|
14
|
-
const headers = {};
|
|
15
|
-
headers[http_headers_1.HTTP_HEADERS.USER_ID] = userContext.userId.toString();
|
|
16
|
-
headers[http_headers_1.HTTP_HEADERS.USER_ROLES] = JSON.stringify(userContext.roles);
|
|
17
|
-
headers[http_headers_1.HTTP_HEADERS.ACCESS_SCOPE] = JSON.stringify(userContext.accessScope);
|
|
18
|
-
if (userContext.organizationId) {
|
|
19
|
-
headers[http_headers_1.HTTP_HEADERS.ORGANIZATION_ID] = userContext.organizationId.toString();
|
|
20
|
-
}
|
|
21
|
-
if (userContext.controlCentreId) {
|
|
22
|
-
headers[http_headers_1.HTTP_HEADERS.CONTROL_CENTRE_ID] = userContext.controlCentreId.toString();
|
|
23
|
-
}
|
|
24
|
-
// Also provide full context as single header for convenience
|
|
25
|
-
headers[http_headers_1.HTTP_HEADERS.USER_CONTEXT] = JSON.stringify(userContext);
|
|
26
|
-
return headers;
|
|
27
|
-
}
|
|
28
|
-
/**
|
|
29
|
-
* Extract UserContext from HTTP headers in microservices
|
|
30
|
-
*/
|
|
31
|
-
static extractFromHeaders(headers) {
|
|
32
|
-
try {
|
|
33
|
-
// First try to get full context from single header
|
|
34
|
-
const fullContextHeader = this.getHeaderValue(headers, http_headers_1.HTTP_HEADERS.USER_CONTEXT);
|
|
35
|
-
if (fullContextHeader) {
|
|
36
|
-
return JSON.parse(fullContextHeader);
|
|
37
|
-
}
|
|
38
|
-
// Fallback: reconstruct from individual headers
|
|
39
|
-
const userIdHeader = this.getHeaderValue(headers, http_headers_1.HTTP_HEADERS.USER_ID);
|
|
40
|
-
const rolesHeader = this.getHeaderValue(headers, http_headers_1.HTTP_HEADERS.USER_ROLES);
|
|
41
|
-
const accessScopeHeader = this.getHeaderValue(headers, http_headers_1.HTTP_HEADERS.ACCESS_SCOPE);
|
|
42
|
-
if (!userIdHeader || !rolesHeader || !accessScopeHeader) {
|
|
43
|
-
return null;
|
|
44
|
-
}
|
|
45
|
-
const userId = parseInt(userIdHeader);
|
|
46
|
-
const roles = JSON.parse(rolesHeader);
|
|
47
|
-
const accessScope = JSON.parse(accessScopeHeader);
|
|
48
|
-
const organizationIdHeader = this.getHeaderValue(headers, http_headers_1.HTTP_HEADERS.ORGANIZATION_ID);
|
|
49
|
-
const controlCentreIdHeader = this.getHeaderValue(headers, http_headers_1.HTTP_HEADERS.CONTROL_CENTRE_ID);
|
|
50
|
-
return {
|
|
51
|
-
userId,
|
|
52
|
-
roles,
|
|
53
|
-
accessScope,
|
|
54
|
-
organizationId: organizationIdHeader ? parseInt(organizationIdHeader) : undefined,
|
|
55
|
-
controlCentreId: controlCentreIdHeader ? parseInt(controlCentreIdHeader) : undefined
|
|
56
|
-
};
|
|
57
|
-
}
|
|
58
|
-
catch (error) {
|
|
59
|
-
console.error('Error extracting user context from headers:', error);
|
|
60
|
-
return null;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* Helper to get header value (handles string | string[] types)
|
|
65
|
-
*/
|
|
66
|
-
static getHeaderValue(headers, key) {
|
|
67
|
-
const value = headers[key.toLowerCase()] || headers[key];
|
|
68
|
-
if (!value)
|
|
69
|
-
return null;
|
|
70
|
-
return Array.isArray(value) ? value[0] : value;
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
exports.UserContextHeaderService = UserContextHeaderService;
|
|
74
2
|
//# sourceMappingURL=user-context-header.service.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"user-context-header.service.js","sourceRoot":"","sources":["../../../src/utilities/user-context-header.service.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"user-context-header.service.js","sourceRoot":"","sources":["../../../src/utilities/user-context-header.service.ts"],"names":[],"mappings":""}
|
package/dist/esm/index.js
CHANGED
|
@@ -23,7 +23,7 @@ export * from './constants/http-headers';
|
|
|
23
23
|
export * from './kafka/index';
|
|
24
24
|
// Utilities
|
|
25
25
|
export * from './decorators/case-decorators';
|
|
26
|
-
export * from './
|
|
26
|
+
export * from './modules/common/services/user-context-header.service';
|
|
27
27
|
// Exceptions
|
|
28
28
|
export * from './exceptions/index';
|
|
29
29
|
//# sourceMappingURL=index.js.map
|
package/dist/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,UAAU;AACV,cAAc,sBAAsB,CAAC;AACrC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,wBAAwB,CAAC;AACvC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,uBAAuB,CAAC;AACtC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,0BAA0B,CAAC;AACzC,cAAc,0BAA0B,CAAC;AACzC,cAAc,qBAAqB,CAAC;AAEpC,aAAa;AACb,cAAc,6BAA6B,CAAC;AAC5C,cAAc,kCAAkC,CAAC;AACjD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,0BAA0B,CAAC;AACzC,cAAc,yBAAyB,CAAC;AAExC,YAAY;AACZ,cAAc,0BAA0B,CAAC;AAEzC,QAAQ;AACR,cAAc,eAAe,CAAC;AAE9B,YAAY;AACZ,cAAc,8BAA8B,CAAC;AAC7C,cAAc,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,UAAU;AACV,cAAc,sBAAsB,CAAC;AACrC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,wBAAwB,CAAC;AACvC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,uBAAuB,CAAC;AACtC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,0BAA0B,CAAC;AACzC,cAAc,0BAA0B,CAAC;AACzC,cAAc,qBAAqB,CAAC;AAEpC,aAAa;AACb,cAAc,6BAA6B,CAAC;AAC5C,cAAc,kCAAkC,CAAC;AACjD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,0BAA0B,CAAC;AACzC,cAAc,yBAAyB,CAAC;AAExC,YAAY;AACZ,cAAc,0BAA0B,CAAC;AAEzC,QAAQ;AACR,cAAc,eAAe,CAAC;AAE9B,YAAY;AACZ,cAAc,8BAA8B,CAAC;AAC7C,cAAc,uDAAuD,CAAC;AAEtE,aAAa;AACb,cAAc,oBAAoB,CAAC"}
|
|
@@ -4,5 +4,7 @@ export * from './dtos/contact-person.dto';
|
|
|
4
4
|
export * from './interfaces/map-location';
|
|
5
5
|
export * from './interfaces/map-address';
|
|
6
6
|
export * from './interfaces/contact-person';
|
|
7
|
+
export * from './interfaces/access-validation.interface';
|
|
7
8
|
export * from './constants/service.const';
|
|
9
|
+
export * from './services';
|
|
8
10
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/modules/common/index.ts"],"names":[],"mappings":"AAAA,cAAc,yBAAyB,CAAC;AACxC,cAAc,wBAAwB,CAAC;AACvC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,0BAA0B,CAAC;AACzC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,2BAA2B,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/modules/common/index.ts"],"names":[],"mappings":"AAAA,cAAc,yBAAyB,CAAC;AACxC,cAAc,wBAAwB,CAAC;AACvC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,0BAA0B,CAAC;AACzC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,0CAA0C,CAAC;AACzD,cAAc,2BAA2B,CAAC;AAC1C,cAAc,YAAY,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"access-validation.interface.js","sourceRoot":"","sources":["../../../../../src/modules/common/interfaces/access-validation.interface.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { ForbiddenException } from '@nestjs/common';
|
|
2
|
+
/**
|
|
3
|
+
* Service for validating access control across microservices
|
|
4
|
+
* Provides centralized validation logic to ensure consistency
|
|
5
|
+
*/
|
|
6
|
+
export class AccessValidationService {
|
|
7
|
+
/**
|
|
8
|
+
* Validates if a user has access to perform list operations
|
|
9
|
+
* @param accessScope - The access scope for the user
|
|
10
|
+
* @param pluralEntityName - The name of the entities being accessed (for error messages)
|
|
11
|
+
*/
|
|
12
|
+
validateListAccess(accessScope, pluralEntityName = 'entities') {
|
|
13
|
+
if (accessScope.isSuperAdmin) {
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
if (accessScope.organizationFilter || accessScope.controlCentreFilter) {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
throw new ForbiddenException(`Access denied: Insufficient permissions to access ${pluralEntityName}`);
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Validates if a user has access to a specific entity
|
|
23
|
+
* @param accessScope - The access scope for the user
|
|
24
|
+
* @param entity - The entity to check access for
|
|
25
|
+
* @param entityName - The name of the entity (for error messages)
|
|
26
|
+
*/
|
|
27
|
+
validateEntityAccess(accessScope, entity, entityName = 'Entity') {
|
|
28
|
+
if (accessScope.isSuperAdmin) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
if (accessScope.organizationFilter && entity.organizationId === accessScope.organizationFilter) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
if (accessScope.controlCentreFilter && entity.controlCentreId === accessScope.controlCentreFilter) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
throw new ForbiddenException(`Access denied: Insufficient permissions to access this ${entityName.toLowerCase()}`);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Validates if a user can create an entity with the specified organization/control centre
|
|
41
|
+
* @param accessScope - The access scope for the user
|
|
42
|
+
* @param createDto - The DTO containing organizationId/controlCentreId
|
|
43
|
+
* @param entityName - The name of the entity (for error messages)
|
|
44
|
+
*/
|
|
45
|
+
validateCreateAccess(accessScope, createDto, entityName = 'entity') {
|
|
46
|
+
if (accessScope.isSuperAdmin) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
// Check organization level access
|
|
50
|
+
if (createDto.organizationId) {
|
|
51
|
+
if (accessScope.organizationFilter && createDto.organizationId !== accessScope.organizationFilter) {
|
|
52
|
+
throw new ForbiddenException(`Cannot create ${entityName} for this organization`);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
// Check control centre level access
|
|
56
|
+
if (createDto.controlCentreId) {
|
|
57
|
+
if (accessScope.controlCentreFilter && createDto.controlCentreId !== accessScope.controlCentreFilter) {
|
|
58
|
+
throw new ForbiddenException(`Cannot create ${entityName} for this control centre`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
// Ensure user has at least organization or control centre level access
|
|
62
|
+
if (!accessScope.organizationFilter && !accessScope.controlCentreFilter) {
|
|
63
|
+
throw new ForbiddenException(`Insufficient permissions to create ${entityName}`);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Validates if a user has access to update entities
|
|
68
|
+
* @param accessScope - The access scope for the user
|
|
69
|
+
* @param entityName - The name of the entity (for error messages)
|
|
70
|
+
*/
|
|
71
|
+
validateUpdateAccess(accessScope, entityName = 'entity') {
|
|
72
|
+
if (accessScope.isSuperAdmin) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
// Ensure user has at least organization or control centre level access
|
|
76
|
+
if (!accessScope.organizationFilter && !accessScope.controlCentreFilter) {
|
|
77
|
+
throw new ForbiddenException(`Insufficient permissions to update ${entityName}`);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Validates if a user has access to delete entities
|
|
82
|
+
* @param accessScope - The access scope for the user
|
|
83
|
+
* @param entityName - The name of the entity (for error messages)
|
|
84
|
+
*/
|
|
85
|
+
validateDeleteAccess(accessScope, entityName = 'entity') {
|
|
86
|
+
if (accessScope.isSuperAdmin) {
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
// Ensure user has at least organization or control centre level access
|
|
90
|
+
if (!accessScope.organizationFilter && !accessScope.controlCentreFilter) {
|
|
91
|
+
throw new ForbiddenException(`Insufficient permissions to delete ${entityName}`);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Validates if a user can update an entity with the specified organization/control centre changes
|
|
96
|
+
* @param accessScope - The access scope for the user
|
|
97
|
+
* @param existingEntity - The existing entity
|
|
98
|
+
* @param updateDto - The DTO containing updated organizationId/controlCentreId
|
|
99
|
+
* @param entityName - The name of the entity (for error messages)
|
|
100
|
+
*/
|
|
101
|
+
validateUpdateEntityAccess(accessScope, existingEntity, updateDto, entityName = 'entity') {
|
|
102
|
+
// First validate access to the existing entity
|
|
103
|
+
this.validateEntityAccess(accessScope, existingEntity, entityName);
|
|
104
|
+
// Then validate update permissions
|
|
105
|
+
this.validateUpdateAccess(accessScope, entityName);
|
|
106
|
+
// If organization is being changed, validate access to new organization
|
|
107
|
+
if (updateDto.organizationId && updateDto.organizationId !== existingEntity.organizationId) {
|
|
108
|
+
if (accessScope.organizationFilter && updateDto.organizationId !== accessScope.organizationFilter) {
|
|
109
|
+
throw new ForbiddenException(`Cannot move ${entityName} to this organization`);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
// If control centre is being changed, validate access to new control centre
|
|
113
|
+
if (updateDto.controlCentreId && updateDto.controlCentreId !== existingEntity.controlCentreId) {
|
|
114
|
+
if (accessScope.controlCentreFilter && updateDto.controlCentreId !== accessScope.controlCentreFilter) {
|
|
115
|
+
throw new ForbiddenException(`Cannot move ${entityName} to this control centre`);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=access-validation.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"access-validation.service.js","sourceRoot":"","sources":["../../../../../src/modules/common/services/access-validation.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAIpD;;;GAGG;AACH,MAAM,OAAO,uBAAuB;IAEhC;;;;OAIG;IACH,kBAAkB,CAAC,WAAwB,EAAE,mBAA2B,UAAU;QAC9E,IAAI,WAAW,CAAC,YAAY,EAAE,CAAC;YAC3B,OAAO;QACX,CAAC;QAED,IAAI,WAAW,CAAC,kBAAkB,IAAI,WAAW,CAAC,mBAAmB,EAAE,CAAC;YACpE,OAAO;QACX,CAAC;QAED,MAAM,IAAI,kBAAkB,CAAC,qDAAqD,gBAAgB,EAAE,CAAC,CAAC;IAC1G,CAAC;IAED;;;;;OAKG;IACH,oBAAoB,CAChB,WAAwB,EACxB,MAAS,EACT,aAAqB,QAAQ;QAE7B,IAAI,WAAW,CAAC,YAAY,EAAE,CAAC;YAC3B,OAAO;QACX,CAAC;QAED,IAAI,WAAW,CAAC,kBAAkB,IAAI,MAAM,CAAC,cAAc,KAAK,WAAW,CAAC,kBAAkB,EAAE,CAAC;YAC7F,OAAO;QACX,CAAC;QAED,IAAI,WAAW,CAAC,mBAAmB,IAAI,MAAM,CAAC,eAAe,KAAK,WAAW,CAAC,mBAAmB,EAAE,CAAC;YAChG,OAAO;QACX,CAAC;QAED,MAAM,IAAI,kBAAkB,CAAC,0DAA0D,UAAU,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;IACvH,CAAC;IAED;;;;;OAKG;IACH,oBAAoB,CAChB,WAAwB,EACxB,SAAY,EACZ,aAAqB,QAAQ;QAE7B,IAAI,WAAW,CAAC,YAAY,EAAE,CAAC;YAC3B,OAAO;QACX,CAAC;QAED,kCAAkC;QAClC,IAAI,SAAS,CAAC,cAAc,EAAE,CAAC;YAC3B,IAAI,WAAW,CAAC,kBAAkB,IAAI,SAAS,CAAC,cAAc,KAAK,WAAW,CAAC,kBAAkB,EAAE,CAAC;gBAChG,MAAM,IAAI,kBAAkB,CAAC,iBAAiB,UAAU,wBAAwB,CAAC,CAAC;YACtF,CAAC;QACL,CAAC;QAED,oCAAoC;QACpC,IAAI,SAAS,CAAC,eAAe,EAAE,CAAC;YAC5B,IAAI,WAAW,CAAC,mBAAmB,IAAI,SAAS,CAAC,eAAe,KAAK,WAAW,CAAC,mBAAmB,EAAE,CAAC;gBACnG,MAAM,IAAI,kBAAkB,CAAC,iBAAiB,UAAU,0BAA0B,CAAC,CAAC;YACxF,CAAC;QACL,CAAC;QAED,uEAAuE;QACvE,IAAI,CAAC,WAAW,CAAC,kBAAkB,IAAI,CAAC,WAAW,CAAC,mBAAmB,EAAE,CAAC;YACtE,MAAM,IAAI,kBAAkB,CAAC,sCAAsC,UAAU,EAAE,CAAC,CAAC;QACrF,CAAC;IACL,CAAC;IAED;;;;OAIG;IACH,oBAAoB,CAAC,WAAwB,EAAE,aAAqB,QAAQ;QACxE,IAAI,WAAW,CAAC,YAAY,EAAE,CAAC;YAC3B,OAAO;QACX,CAAC;QAED,uEAAuE;QACvE,IAAI,CAAC,WAAW,CAAC,kBAAkB,IAAI,CAAC,WAAW,CAAC,mBAAmB,EAAE,CAAC;YACtE,MAAM,IAAI,kBAAkB,CAAC,sCAAsC,UAAU,EAAE,CAAC,CAAC;QACrF,CAAC;IACL,CAAC;IAED;;;;OAIG;IACH,oBAAoB,CAAC,WAAwB,EAAE,aAAqB,QAAQ;QACxE,IAAI,WAAW,CAAC,YAAY,EAAE,CAAC;YAC3B,OAAO;QACX,CAAC;QAED,uEAAuE;QACvE,IAAI,CAAC,WAAW,CAAC,kBAAkB,IAAI,CAAC,WAAW,CAAC,mBAAmB,EAAE,CAAC;YACtE,MAAM,IAAI,kBAAkB,CAAC,sCAAsC,UAAU,EAAE,CAAC,CAAC;QACrF,CAAC;IACL,CAAC;IAED;;;;;;OAMG;IACH,0BAA0B,CACtB,WAAwB,EACxB,cAAiB,EACjB,SAAY,EACZ,aAAqB,QAAQ;QAE7B,+CAA+C;QAC/C,IAAI,CAAC,oBAAoB,CAAC,WAAW,EAAE,cAAc,EAAE,UAAU,CAAC,CAAC;QAEnE,mCAAmC;QACnC,IAAI,CAAC,oBAAoB,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;QAEnD,wEAAwE;QACxE,IAAI,SAAS,CAAC,cAAc,IAAI,SAAS,CAAC,cAAc,KAAK,cAAc,CAAC,cAAc,EAAE,CAAC;YACzF,IAAI,WAAW,CAAC,kBAAkB,IAAI,SAAS,CAAC,cAAc,KAAK,WAAW,CAAC,kBAAkB,EAAE,CAAC;gBAChG,MAAM,IAAI,kBAAkB,CAAC,eAAe,UAAU,uBAAuB,CAAC,CAAC;YACnF,CAAC;QACL,CAAC;QAED,4EAA4E;QAC5E,IAAI,SAAS,CAAC,eAAe,IAAI,SAAS,CAAC,eAAe,KAAK,cAAc,CAAC,eAAe,EAAE,CAAC;YAC5F,IAAI,WAAW,CAAC,mBAAmB,IAAI,SAAS,CAAC,eAAe,KAAK,WAAW,CAAC,mBAAmB,EAAE,CAAC;gBACnG,MAAM,IAAI,kBAAkB,CAAC,eAAe,UAAU,yBAAyB,CAAC,CAAC;YACrF,CAAC;QACL,CAAC;IACL,CAAC;CACJ"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/modules/common/services/index.ts"],"names":[],"mappings":"AAAA,cAAc,6BAA6B,CAAC;AAC5C,cAAc,+BAA+B,CAAC"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { HTTP_HEADERS } from '../../../constants/http-headers';
|
|
2
|
+
/**
|
|
3
|
+
* Utility service for handling user context via HTTP headers
|
|
4
|
+
* This provides a consistent way to pass user context between API Gateway and microservices
|
|
5
|
+
*/
|
|
6
|
+
export class UserContextHeaderService {
|
|
7
|
+
/**
|
|
8
|
+
* Convert UserContext to HTTP headers for microservice communication
|
|
9
|
+
*/
|
|
10
|
+
static buildHeaders(userContext) {
|
|
11
|
+
const headers = {};
|
|
12
|
+
headers[HTTP_HEADERS.USER_ID] = userContext.userId.toString();
|
|
13
|
+
headers[HTTP_HEADERS.USER_ROLES] = JSON.stringify(userContext.roles);
|
|
14
|
+
headers[HTTP_HEADERS.ACCESS_SCOPE] = JSON.stringify(userContext.accessScope);
|
|
15
|
+
if (userContext.organizationId) {
|
|
16
|
+
headers[HTTP_HEADERS.ORGANIZATION_ID] = userContext.organizationId.toString();
|
|
17
|
+
}
|
|
18
|
+
if (userContext.controlCentreId) {
|
|
19
|
+
headers[HTTP_HEADERS.CONTROL_CENTRE_ID] = userContext.controlCentreId.toString();
|
|
20
|
+
}
|
|
21
|
+
// Also provide full context as single header for convenience
|
|
22
|
+
headers[HTTP_HEADERS.USER_CONTEXT] = JSON.stringify(userContext);
|
|
23
|
+
return headers;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Extract UserContext from HTTP headers in microservices
|
|
27
|
+
*/
|
|
28
|
+
static extractFromHeaders(headers) {
|
|
29
|
+
try {
|
|
30
|
+
// First try to get full context from single header
|
|
31
|
+
const fullContextHeader = this.getHeaderValue(headers, HTTP_HEADERS.USER_CONTEXT);
|
|
32
|
+
if (fullContextHeader) {
|
|
33
|
+
return JSON.parse(fullContextHeader);
|
|
34
|
+
}
|
|
35
|
+
// Fallback: reconstruct from individual headers
|
|
36
|
+
const userIdHeader = this.getHeaderValue(headers, HTTP_HEADERS.USER_ID);
|
|
37
|
+
const rolesHeader = this.getHeaderValue(headers, HTTP_HEADERS.USER_ROLES);
|
|
38
|
+
const accessScopeHeader = this.getHeaderValue(headers, HTTP_HEADERS.ACCESS_SCOPE);
|
|
39
|
+
if (!userIdHeader || !rolesHeader || !accessScopeHeader) {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
const userId = parseInt(userIdHeader);
|
|
43
|
+
const roles = JSON.parse(rolesHeader);
|
|
44
|
+
const accessScope = JSON.parse(accessScopeHeader);
|
|
45
|
+
const organizationIdHeader = this.getHeaderValue(headers, HTTP_HEADERS.ORGANIZATION_ID);
|
|
46
|
+
const controlCentreIdHeader = this.getHeaderValue(headers, HTTP_HEADERS.CONTROL_CENTRE_ID);
|
|
47
|
+
return {
|
|
48
|
+
userId,
|
|
49
|
+
roles,
|
|
50
|
+
accessScope,
|
|
51
|
+
organizationId: organizationIdHeader ? parseInt(organizationIdHeader) : undefined,
|
|
52
|
+
controlCentreId: controlCentreIdHeader ? parseInt(controlCentreIdHeader) : undefined
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
console.error('Error extracting user context from headers:', error);
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Helper to get header value (handles string | string[] types)
|
|
62
|
+
*/
|
|
63
|
+
static getHeaderValue(headers, key) {
|
|
64
|
+
const value = headers[key.toLowerCase()] || headers[key];
|
|
65
|
+
if (!value)
|
|
66
|
+
return null;
|
|
67
|
+
return Array.isArray(value) ? value[0] : value;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=user-context-header.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"user-context-header.service.js","sourceRoot":"","sources":["../../../../../src/modules/common/services/user-context-header.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,70 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
/**
|
|
3
|
-
* Utility service for handling user context via HTTP headers
|
|
4
|
-
* This provides a consistent way to pass user context between API Gateway and microservices
|
|
5
|
-
*/
|
|
6
|
-
export class UserContextHeaderService {
|
|
7
|
-
/**
|
|
8
|
-
* Convert UserContext to HTTP headers for microservice communication
|
|
9
|
-
*/
|
|
10
|
-
static buildHeaders(userContext) {
|
|
11
|
-
const headers = {};
|
|
12
|
-
headers[HTTP_HEADERS.USER_ID] = userContext.userId.toString();
|
|
13
|
-
headers[HTTP_HEADERS.USER_ROLES] = JSON.stringify(userContext.roles);
|
|
14
|
-
headers[HTTP_HEADERS.ACCESS_SCOPE] = JSON.stringify(userContext.accessScope);
|
|
15
|
-
if (userContext.organizationId) {
|
|
16
|
-
headers[HTTP_HEADERS.ORGANIZATION_ID] = userContext.organizationId.toString();
|
|
17
|
-
}
|
|
18
|
-
if (userContext.controlCentreId) {
|
|
19
|
-
headers[HTTP_HEADERS.CONTROL_CENTRE_ID] = userContext.controlCentreId.toString();
|
|
20
|
-
}
|
|
21
|
-
// Also provide full context as single header for convenience
|
|
22
|
-
headers[HTTP_HEADERS.USER_CONTEXT] = JSON.stringify(userContext);
|
|
23
|
-
return headers;
|
|
24
|
-
}
|
|
25
|
-
/**
|
|
26
|
-
* Extract UserContext from HTTP headers in microservices
|
|
27
|
-
*/
|
|
28
|
-
static extractFromHeaders(headers) {
|
|
29
|
-
try {
|
|
30
|
-
// First try to get full context from single header
|
|
31
|
-
const fullContextHeader = this.getHeaderValue(headers, HTTP_HEADERS.USER_CONTEXT);
|
|
32
|
-
if (fullContextHeader) {
|
|
33
|
-
return JSON.parse(fullContextHeader);
|
|
34
|
-
}
|
|
35
|
-
// Fallback: reconstruct from individual headers
|
|
36
|
-
const userIdHeader = this.getHeaderValue(headers, HTTP_HEADERS.USER_ID);
|
|
37
|
-
const rolesHeader = this.getHeaderValue(headers, HTTP_HEADERS.USER_ROLES);
|
|
38
|
-
const accessScopeHeader = this.getHeaderValue(headers, HTTP_HEADERS.ACCESS_SCOPE);
|
|
39
|
-
if (!userIdHeader || !rolesHeader || !accessScopeHeader) {
|
|
40
|
-
return null;
|
|
41
|
-
}
|
|
42
|
-
const userId = parseInt(userIdHeader);
|
|
43
|
-
const roles = JSON.parse(rolesHeader);
|
|
44
|
-
const accessScope = JSON.parse(accessScopeHeader);
|
|
45
|
-
const organizationIdHeader = this.getHeaderValue(headers, HTTP_HEADERS.ORGANIZATION_ID);
|
|
46
|
-
const controlCentreIdHeader = this.getHeaderValue(headers, HTTP_HEADERS.CONTROL_CENTRE_ID);
|
|
47
|
-
return {
|
|
48
|
-
userId,
|
|
49
|
-
roles,
|
|
50
|
-
accessScope,
|
|
51
|
-
organizationId: organizationIdHeader ? parseInt(organizationIdHeader) : undefined,
|
|
52
|
-
controlCentreId: controlCentreIdHeader ? parseInt(controlCentreIdHeader) : undefined
|
|
53
|
-
};
|
|
54
|
-
}
|
|
55
|
-
catch (error) {
|
|
56
|
-
console.error('Error extracting user context from headers:', error);
|
|
57
|
-
return null;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
/**
|
|
61
|
-
* Helper to get header value (handles string | string[] types)
|
|
62
|
-
*/
|
|
63
|
-
static getHeaderValue(headers, key) {
|
|
64
|
-
const value = headers[key.toLowerCase()] || headers[key];
|
|
65
|
-
if (!value)
|
|
66
|
-
return null;
|
|
67
|
-
return Array.isArray(value) ? value[0] : value;
|
|
68
|
-
}
|
|
69
|
-
}
|
|
1
|
+
"use strict";
|
|
70
2
|
//# sourceMappingURL=user-context-header.service.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"user-context-header.service.js","sourceRoot":"","sources":["../../../src/utilities/user-context-header.service.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"user-context-header.service.js","sourceRoot":"","sources":["../../../src/utilities/user-context-header.service.ts"],"names":[],"mappings":""}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -18,5 +18,5 @@ export * from './interfaces/pagination';
|
|
|
18
18
|
export * from './constants/http-headers';
|
|
19
19
|
export * from './kafka/index';
|
|
20
20
|
export * from './decorators/case-decorators';
|
|
21
|
-
export * from './
|
|
21
|
+
export * from './modules/common/services/user-context-header.service';
|
|
22
22
|
export * from './exceptions/index';
|
|
@@ -4,4 +4,6 @@ export * from './dtos/contact-person.dto';
|
|
|
4
4
|
export * from './interfaces/map-location';
|
|
5
5
|
export * from './interfaces/map-address';
|
|
6
6
|
export * from './interfaces/contact-person';
|
|
7
|
+
export * from './interfaces/access-validation.interface';
|
|
7
8
|
export * from './constants/service.const';
|
|
9
|
+
export * from './services';
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Interface for entities that can be checked for access control
|
|
3
|
+
*/
|
|
4
|
+
export interface EntityAccessCheck {
|
|
5
|
+
organizationId?: number;
|
|
6
|
+
controlCentreId?: number;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Interface for create DTOs that need access validation
|
|
10
|
+
*/
|
|
11
|
+
export interface CreateEntityAccessCheck {
|
|
12
|
+
organizationId?: number;
|
|
13
|
+
controlCentreId?: number;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Interface for update DTOs that need access validation
|
|
17
|
+
*/
|
|
18
|
+
export interface UpdateEntityAccessCheck {
|
|
19
|
+
organizationId?: number;
|
|
20
|
+
controlCentreId?: number;
|
|
21
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { AccessScope } from '../../user/interfaces/access-scope';
|
|
2
|
+
import { EntityAccessCheck, CreateEntityAccessCheck, UpdateEntityAccessCheck } from '../interfaces/access-validation.interface';
|
|
3
|
+
/**
|
|
4
|
+
* Service for validating access control across microservices
|
|
5
|
+
* Provides centralized validation logic to ensure consistency
|
|
6
|
+
*/
|
|
7
|
+
export declare class AccessValidationService {
|
|
8
|
+
/**
|
|
9
|
+
* Validates if a user has access to perform list operations
|
|
10
|
+
* @param accessScope - The access scope for the user
|
|
11
|
+
* @param pluralEntityName - The name of the entities being accessed (for error messages)
|
|
12
|
+
*/
|
|
13
|
+
validateListAccess(accessScope: AccessScope, pluralEntityName?: string): void;
|
|
14
|
+
/**
|
|
15
|
+
* Validates if a user has access to a specific entity
|
|
16
|
+
* @param accessScope - The access scope for the user
|
|
17
|
+
* @param entity - The entity to check access for
|
|
18
|
+
* @param entityName - The name of the entity (for error messages)
|
|
19
|
+
*/
|
|
20
|
+
validateEntityAccess<T extends EntityAccessCheck>(accessScope: AccessScope, entity: T, entityName?: string): void;
|
|
21
|
+
/**
|
|
22
|
+
* Validates if a user can create an entity with the specified organization/control centre
|
|
23
|
+
* @param accessScope - The access scope for the user
|
|
24
|
+
* @param createDto - The DTO containing organizationId/controlCentreId
|
|
25
|
+
* @param entityName - The name of the entity (for error messages)
|
|
26
|
+
*/
|
|
27
|
+
validateCreateAccess<T extends CreateEntityAccessCheck>(accessScope: AccessScope, createDto: T, entityName?: string): void;
|
|
28
|
+
/**
|
|
29
|
+
* Validates if a user has access to update entities
|
|
30
|
+
* @param accessScope - The access scope for the user
|
|
31
|
+
* @param entityName - The name of the entity (for error messages)
|
|
32
|
+
*/
|
|
33
|
+
validateUpdateAccess(accessScope: AccessScope, entityName?: string): void;
|
|
34
|
+
/**
|
|
35
|
+
* Validates if a user has access to delete entities
|
|
36
|
+
* @param accessScope - The access scope for the user
|
|
37
|
+
* @param entityName - The name of the entity (for error messages)
|
|
38
|
+
*/
|
|
39
|
+
validateDeleteAccess(accessScope: AccessScope, entityName?: string): void;
|
|
40
|
+
/**
|
|
41
|
+
* Validates if a user can update an entity with the specified organization/control centre changes
|
|
42
|
+
* @param accessScope - The access scope for the user
|
|
43
|
+
* @param existingEntity - The existing entity
|
|
44
|
+
* @param updateDto - The DTO containing updated organizationId/controlCentreId
|
|
45
|
+
* @param entityName - The name of the entity (for error messages)
|
|
46
|
+
*/
|
|
47
|
+
validateUpdateEntityAccess<T extends EntityAccessCheck, U extends UpdateEntityAccessCheck>(accessScope: AccessScope, existingEntity: T, updateDto: U, entityName?: string): void;
|
|
48
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { UserContext } from '../../user/interfaces/user-context';
|
|
2
|
+
/**
|
|
3
|
+
* Utility service for handling user context via HTTP headers
|
|
4
|
+
* This provides a consistent way to pass user context between API Gateway and microservices
|
|
5
|
+
*/
|
|
6
|
+
export declare class UserContextHeaderService {
|
|
7
|
+
/**
|
|
8
|
+
* Convert UserContext to HTTP headers for microservice communication
|
|
9
|
+
*/
|
|
10
|
+
static buildHeaders(userContext: UserContext): Record<string, string>;
|
|
11
|
+
/**
|
|
12
|
+
* Extract UserContext from HTTP headers in microservices
|
|
13
|
+
*/
|
|
14
|
+
static extractFromHeaders(headers: Record<string, string | string[]>): UserContext | null;
|
|
15
|
+
/**
|
|
16
|
+
* Helper to get header value (handles string | string[] types)
|
|
17
|
+
*/
|
|
18
|
+
private static getHeaderValue;
|
|
19
|
+
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { UserContext } from '../modules/user/interfaces/user-context';
|
|
2
|
-
/**
|
|
3
|
-
* Utility service for handling user context via HTTP headers
|
|
4
|
-
* This provides a consistent way to pass user context between API Gateway and microservices
|
|
5
|
-
*/
|
|
6
|
-
export declare class UserContextHeaderService {
|
|
7
|
-
/**
|
|
8
|
-
* Convert UserContext to HTTP headers for microservice communication
|
|
9
|
-
*/
|
|
10
|
-
static buildHeaders(userContext: UserContext): Record<string, string>;
|
|
11
|
-
/**
|
|
12
|
-
* Extract UserContext from HTTP headers in microservices
|
|
13
|
-
*/
|
|
14
|
-
static extractFromHeaders(headers: Record<string, string | string[]>): UserContext | null;
|
|
15
|
-
/**
|
|
16
|
-
* Helper to get header value (handles string | string[] types)
|
|
17
|
-
*/
|
|
18
|
-
private static getHeaderValue;
|
|
19
|
-
}
|