permissions-contractx 1.0.1 → 1.0.2
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.
|
@@ -3,13 +3,24 @@ import { JwtPayload } from '../interfaces';
|
|
|
3
3
|
* Request-scoped service to manage current user context
|
|
4
4
|
* Provides convenient methods to access user information and check permissions
|
|
5
5
|
*/
|
|
6
|
+
interface RequestWithUser {
|
|
7
|
+
user?: any;
|
|
8
|
+
tenant?: any;
|
|
9
|
+
}
|
|
6
10
|
export declare class UserContextService {
|
|
11
|
+
private readonly request;
|
|
7
12
|
private user;
|
|
13
|
+
private autoInitialized;
|
|
14
|
+
constructor(request: RequestWithUser);
|
|
8
15
|
/**
|
|
9
16
|
* Set the current user context
|
|
10
17
|
* This is typically called by the authentication guard
|
|
11
18
|
*/
|
|
12
19
|
setUser(user: JwtPayload): void;
|
|
20
|
+
/**
|
|
21
|
+
* Auto-initialize user from request if not manually set
|
|
22
|
+
*/
|
|
23
|
+
private tryAutoInitialize;
|
|
13
24
|
/**
|
|
14
25
|
* Get the current authenticated user
|
|
15
26
|
*/
|
|
@@ -30,6 +41,11 @@ export declare class UserContextService {
|
|
|
30
41
|
* Get the current user's client ID
|
|
31
42
|
*/
|
|
32
43
|
getClientId(): string | null;
|
|
44
|
+
/**
|
|
45
|
+
* Get the tenant key (key_client) for multi-tenant operations
|
|
46
|
+
* Tries multiple sources: user.key_client, user.clientId, tenant.key_client
|
|
47
|
+
*/
|
|
48
|
+
getTenantKey(): string | null;
|
|
33
49
|
/**
|
|
34
50
|
* Get the current user's session ID
|
|
35
51
|
*/
|
|
@@ -111,4 +127,5 @@ export declare class UserContextService {
|
|
|
111
127
|
clientId: string | null;
|
|
112
128
|
};
|
|
113
129
|
}
|
|
130
|
+
export {};
|
|
114
131
|
//# sourceMappingURL=user-context.service.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"user-context.service.d.ts","sourceRoot":"","sources":["../../src/services/user-context.service.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"user-context.service.d.ts","sourceRoot":"","sources":["../../src/services/user-context.service.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAG3C;;;GAGG;AACH,UAAU,eAAe;IACvB,IAAI,CAAC,EAAE,GAAG,CAAC;IACX,MAAM,CAAC,EAAE,GAAG,CAAC;CACd;AAED,qBACa,kBAAkB;IAKV,OAAO,CAAC,QAAQ,CAAC,OAAO;IAJ3C,OAAO,CAAC,IAAI,CAA2B;IACvC,OAAO,CAAC,eAAe,CAAS;gBAGI,OAAO,EAAE,eAAe;IAG5D;;;OAGG;IACH,OAAO,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI;IAI/B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IA4EzB;;OAEG;IACH,OAAO,IAAI,UAAU,GAAG,IAAI;IAK5B;;OAEG;IACH,SAAS,IAAI,MAAM,GAAG,IAAI;IAM1B;;OAEG;IACH,eAAe,IAAI,MAAM,GAAG,IAAI;IAMhC;;OAEG;IACH,YAAY,IAAI,MAAM,GAAG,IAAI;IAM7B;;OAEG;IACH,WAAW,IAAI,MAAM,GAAG,IAAI;IAM5B;;;OAGG;IACH,YAAY,IAAI,MAAM,GAAG,IAAI;IAsC7B;;OAEG;IACH,YAAY,IAAI,MAAM,GAAG,IAAI;IAM7B;;OAEG;IACH,YAAY,IAAI,MAAM,EAAE;IAKxB;;OAEG;IACH,kBAAkB,IAAI,MAAM,EAAE;IAK9B;;OAEG;IACH,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAI9B;;OAEG;IACH,UAAU,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,EAAE,GAAG,OAAO;IAKxD;;OAEG;IACH,WAAW,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,EAAE,GAAG,OAAO;IAKzD;;OAEG;IACH,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO;IAI1C;;OAEG;IACH,gBAAgB,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,OAAO;IAKhD;;OAEG;IACH,iBAAiB,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,OAAO;IAKjD;;OAEG;IACH,eAAe,IAAI,OAAO;IAK1B;;OAEG;IACH,YAAY,IAAI,OAAO;IAIvB;;OAEG;IACH,OAAO,IAAI,OAAO;IAIlB;;OAEG;IACH,YAAY,IAAI,OAAO;IAIvB;;OAEG;IACH,cAAc,IAAI,OAAO;IAIzB;;OAEG;IACH,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO;IAOxC;;OAEG;IACH,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE;IAM9C;;OAEG;IACH,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO;IAIzD;;OAEG;IACH,cAAc,IAAI;QAChB,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;QAClB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;QACpB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;QACrB,KAAK,EAAE,MAAM,EAAE,CAAC;QAChB,eAAe,EAAE,MAAM,CAAC;QACxB,OAAO,EAAE,OAAO,CAAC;QACjB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;KACzB;CAWF"}
|
|
@@ -5,17 +5,22 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
5
5
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
6
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
7
|
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
+
};
|
|
8
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
15
|
exports.UserContextService = void 0;
|
|
10
16
|
const common_1 = require("@nestjs/common");
|
|
17
|
+
const core_1 = require("@nestjs/core");
|
|
11
18
|
const contractx_roles_constants_1 = require("../constants/contractx-roles.constants");
|
|
12
|
-
/**
|
|
13
|
-
* Request-scoped service to manage current user context
|
|
14
|
-
* Provides convenient methods to access user information and check permissions
|
|
15
|
-
*/
|
|
16
19
|
let UserContextService = class UserContextService {
|
|
17
|
-
constructor() {
|
|
20
|
+
constructor(request) {
|
|
21
|
+
this.request = request;
|
|
18
22
|
this.user = null;
|
|
23
|
+
this.autoInitialized = false;
|
|
19
24
|
}
|
|
20
25
|
/**
|
|
21
26
|
* Set the current user context
|
|
@@ -24,16 +29,89 @@ let UserContextService = class UserContextService {
|
|
|
24
29
|
setUser(user) {
|
|
25
30
|
this.user = user;
|
|
26
31
|
}
|
|
32
|
+
/**
|
|
33
|
+
* Auto-initialize user from request if not manually set
|
|
34
|
+
*/
|
|
35
|
+
tryAutoInitialize() {
|
|
36
|
+
if (this.autoInitialized || this.user !== null) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
this.autoInitialized = true;
|
|
40
|
+
// Try to get user from request.user (populated by JWT middleware)
|
|
41
|
+
if (this.request?.user) {
|
|
42
|
+
try {
|
|
43
|
+
// Handle different user object formats
|
|
44
|
+
const requestUser = this.request.user;
|
|
45
|
+
// Convert to JwtPayload format
|
|
46
|
+
const payload = {
|
|
47
|
+
sub: requestUser.sub || requestUser.id || requestUser.user_id,
|
|
48
|
+
role: requestUser.role || requestUser.roles || [],
|
|
49
|
+
permissions: requestUser.permissions || [],
|
|
50
|
+
fullName: requestUser.fullName || requestUser.full_name || requestUser.username || '',
|
|
51
|
+
email: requestUser.email,
|
|
52
|
+
clientId: Array.isArray(requestUser.clientId)
|
|
53
|
+
? requestUser.clientId[0]
|
|
54
|
+
: (requestUser.clientId || requestUser.client_id),
|
|
55
|
+
sessionId: requestUser.sessionId || requestUser.session_id,
|
|
56
|
+
iat: requestUser.iat,
|
|
57
|
+
exp: requestUser.exp,
|
|
58
|
+
iss: requestUser.iss,
|
|
59
|
+
aud: requestUser.aud,
|
|
60
|
+
};
|
|
61
|
+
// Copy any additional properties
|
|
62
|
+
Object.keys(requestUser).forEach(key => {
|
|
63
|
+
if (!(key in payload)) {
|
|
64
|
+
payload[key] = requestUser[key];
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
this.user = payload;
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
// If parsing fails, continue to try request.tenant
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
// Fallback: try to get user from request.tenant (if populated by custom middleware)
|
|
75
|
+
if (this.request?.tenant) {
|
|
76
|
+
try {
|
|
77
|
+
const tenant = this.request.tenant;
|
|
78
|
+
const payload = {
|
|
79
|
+
sub: tenant.user_id || tenant.sub || tenant.id,
|
|
80
|
+
role: tenant.roles || [tenant.role].filter(Boolean),
|
|
81
|
+
permissions: tenant.permissions || [],
|
|
82
|
+
fullName: tenant.fullName || tenant.full_name || tenant.username || '',
|
|
83
|
+
email: tenant.email,
|
|
84
|
+
clientId: Array.isArray(tenant.clientId)
|
|
85
|
+
? tenant.clientId[0]
|
|
86
|
+
: (tenant.clientId || tenant.client_id),
|
|
87
|
+
sessionId: tenant.sessionId || tenant.session_id,
|
|
88
|
+
};
|
|
89
|
+
// Copy additional properties
|
|
90
|
+
Object.keys(tenant).forEach(key => {
|
|
91
|
+
if (!(key in payload)) {
|
|
92
|
+
payload[key] = tenant[key];
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
this.user = payload;
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
catch (error) {
|
|
99
|
+
// If parsing fails, user remains null
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
27
103
|
/**
|
|
28
104
|
* Get the current authenticated user
|
|
29
105
|
*/
|
|
30
106
|
getUser() {
|
|
107
|
+
this.tryAutoInitialize();
|
|
31
108
|
return this.user;
|
|
32
109
|
}
|
|
33
110
|
/**
|
|
34
111
|
* Get the current user's ID
|
|
35
112
|
*/
|
|
36
113
|
getUserId() {
|
|
114
|
+
this.tryAutoInitialize();
|
|
37
115
|
if (this.user?.sub === undefined || this.user?.sub === null)
|
|
38
116
|
return null;
|
|
39
117
|
return String(this.user.sub);
|
|
@@ -42,6 +120,7 @@ let UserContextService = class UserContextService {
|
|
|
42
120
|
* Get the current user's full name
|
|
43
121
|
*/
|
|
44
122
|
getUserFullName() {
|
|
123
|
+
this.tryAutoInitialize();
|
|
45
124
|
if (this.user?.fullName === undefined || this.user?.fullName === null)
|
|
46
125
|
return null;
|
|
47
126
|
return this.user.fullName;
|
|
@@ -50,6 +129,7 @@ let UserContextService = class UserContextService {
|
|
|
50
129
|
* Get the current user's email
|
|
51
130
|
*/
|
|
52
131
|
getUserEmail() {
|
|
132
|
+
this.tryAutoInitialize();
|
|
53
133
|
if (this.user?.email === undefined || this.user?.email === null)
|
|
54
134
|
return null;
|
|
55
135
|
return this.user.email;
|
|
@@ -58,14 +138,51 @@ let UserContextService = class UserContextService {
|
|
|
58
138
|
* Get the current user's client ID
|
|
59
139
|
*/
|
|
60
140
|
getClientId() {
|
|
141
|
+
this.tryAutoInitialize();
|
|
61
142
|
if (this.user?.clientId === undefined || this.user?.clientId === null)
|
|
62
143
|
return null;
|
|
63
|
-
return this.user.clientId;
|
|
144
|
+
return Array.isArray(this.user.clientId) ? this.user.clientId[0] : this.user.clientId;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Get the tenant key (key_client) for multi-tenant operations
|
|
148
|
+
* Tries multiple sources: user.key_client, user.clientId, tenant.key_client
|
|
149
|
+
*/
|
|
150
|
+
getTenantKey() {
|
|
151
|
+
this.tryAutoInitialize();
|
|
152
|
+
// Try to get from user object first
|
|
153
|
+
if (this.user) {
|
|
154
|
+
// Check for key_client property
|
|
155
|
+
const keyClient = this.user.key_client;
|
|
156
|
+
if (keyClient) {
|
|
157
|
+
return Array.isArray(keyClient) ? keyClient[0] : keyClient;
|
|
158
|
+
}
|
|
159
|
+
// Fallback to clientId
|
|
160
|
+
if (this.user.clientId) {
|
|
161
|
+
return Array.isArray(this.user.clientId) ? this.user.clientId[0] : this.user.clientId;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
// Try to get from request.tenant directly
|
|
165
|
+
if (this.request?.tenant?.key_client) {
|
|
166
|
+
const tenantKeyClient = this.request.tenant.key_client;
|
|
167
|
+
return Array.isArray(tenantKeyClient) ? tenantKeyClient[0] : tenantKeyClient;
|
|
168
|
+
}
|
|
169
|
+
// Try to get from request.user directly (in case of format differences)
|
|
170
|
+
if (this.request?.user?.key_client) {
|
|
171
|
+
const userKeyClient = this.request.user.key_client;
|
|
172
|
+
return Array.isArray(userKeyClient) ? userKeyClient[0] : userKeyClient;
|
|
173
|
+
}
|
|
174
|
+
// Try to get clientId from request.user directly
|
|
175
|
+
if (this.request?.user?.clientId) {
|
|
176
|
+
const userClientId = this.request.user.clientId;
|
|
177
|
+
return Array.isArray(userClientId) ? userClientId[0] : userClientId;
|
|
178
|
+
}
|
|
179
|
+
return null;
|
|
64
180
|
}
|
|
65
181
|
/**
|
|
66
182
|
* Get the current user's session ID
|
|
67
183
|
*/
|
|
68
184
|
getSessionId() {
|
|
185
|
+
this.tryAutoInitialize();
|
|
69
186
|
if (this.user?.sessionId === undefined || this.user?.sessionId === null)
|
|
70
187
|
return null;
|
|
71
188
|
return this.user.sessionId;
|
|
@@ -74,12 +191,14 @@ let UserContextService = class UserContextService {
|
|
|
74
191
|
* Get all user roles
|
|
75
192
|
*/
|
|
76
193
|
getUserRoles() {
|
|
194
|
+
this.tryAutoInitialize();
|
|
77
195
|
return this.user?.role || [];
|
|
78
196
|
}
|
|
79
197
|
/**
|
|
80
198
|
* Get all user permissions
|
|
81
199
|
*/
|
|
82
200
|
getUserPermissions() {
|
|
201
|
+
this.tryAutoInitialize();
|
|
83
202
|
return this.user?.permissions || [];
|
|
84
203
|
}
|
|
85
204
|
/**
|
|
@@ -126,6 +245,7 @@ let UserContextService = class UserContextService {
|
|
|
126
245
|
* Check if user is authenticated
|
|
127
246
|
*/
|
|
128
247
|
isAuthenticated() {
|
|
248
|
+
this.tryAutoInitialize();
|
|
129
249
|
return this.user !== null;
|
|
130
250
|
}
|
|
131
251
|
/**
|
|
@@ -188,5 +308,7 @@ let UserContextService = class UserContextService {
|
|
|
188
308
|
};
|
|
189
309
|
exports.UserContextService = UserContextService;
|
|
190
310
|
exports.UserContextService = UserContextService = __decorate([
|
|
191
|
-
(0, common_1.Injectable)({ scope: common_1.Scope.REQUEST })
|
|
311
|
+
(0, common_1.Injectable)({ scope: common_1.Scope.REQUEST }),
|
|
312
|
+
__param(0, (0, common_1.Inject)(core_1.REQUEST)),
|
|
313
|
+
__metadata("design:paramtypes", [Object])
|
|
192
314
|
], UserContextService);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "permissions-contractx",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "Enterprise-grade authentication and authorization package for NestJS microservices with role-based and permission-based access control",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|