@flusys/nestjs-shared 6.0.0 → 6.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.
- package/cjs/constants/index.js +1 -1
- package/cjs/constants/permissions.js +9 -1
- package/cjs/guards/index.js +1 -0
- package/cjs/guards/optional-jwt-auth.guard.js +67 -0
- package/cjs/guards/permission.guard.js +11 -10
- package/cjs/interfaces/ai-assistant-adapter.interface.js +24 -0
- package/cjs/interfaces/index.js +2 -0
- package/cjs/interfaces/permission-sync-adapter.interface.js +11 -0
- package/cjs/utils/index.js +1 -0
- package/cjs/utils/permission-cache-key.util.js +31 -0
- package/constants/index.d.ts +1 -1
- package/constants/permissions.d.ts +6 -0
- package/fesm/constants/index.js +1 -1
- package/fesm/constants/permissions.js +7 -1
- package/fesm/guards/index.js +1 -0
- package/fesm/guards/optional-jwt-auth.guard.js +57 -0
- package/fesm/guards/permission.guard.js +12 -11
- package/fesm/interfaces/ai-assistant-adapter.interface.js +3 -0
- package/fesm/interfaces/index.js +2 -0
- package/fesm/interfaces/permission-sync-adapter.interface.js +1 -0
- package/fesm/utils/index.js +1 -0
- package/fesm/utils/permission-cache-key.util.js +10 -0
- package/guards/index.d.ts +1 -0
- package/guards/optional-jwt-auth.guard.d.ts +10 -0
- package/guards/permission.guard.d.ts +0 -1
- package/interfaces/ai-assistant-adapter.interface.d.ts +43 -0
- package/interfaces/index.d.ts +2 -0
- package/interfaces/permission-sync-adapter.interface.d.ts +7 -0
- package/package.json +2 -2
- package/utils/index.d.ts +1 -0
- package/utils/permission-cache-key.util.d.ts +9 -0
package/cjs/constants/index.js
CHANGED
|
@@ -60,5 +60,5 @@ const PERMISSION_GUARD_CONFIG = 'PERMISSION_GUARD_CONFIG';
|
|
|
60
60
|
const IDEMPOTENCY_KEY_HEADER = 'x-idempotency-key';
|
|
61
61
|
const REQUEST_ID_HEADER = 'x-request-id';
|
|
62
62
|
const CLIENT_TYPE_HEADER = 'x-client-type';
|
|
63
|
-
const PERMISSIONS_CACHE_PREFIX = 'permissions';
|
|
63
|
+
const PERMISSIONS_CACHE_PREFIX = 'my-permissions';
|
|
64
64
|
const IDEMPOTENCY_CACHE_PREFIX = 'idempotency';
|
|
@@ -13,6 +13,9 @@ _export(exports, {
|
|
|
13
13
|
get ACTION_PERMISSIONS () {
|
|
14
14
|
return ACTION_PERMISSIONS;
|
|
15
15
|
},
|
|
16
|
+
get AI_ASSISTANT_PERMISSIONS () {
|
|
17
|
+
return AI_ASSISTANT_PERMISSIONS;
|
|
18
|
+
},
|
|
16
19
|
get BRANCH_PERMISSIONS () {
|
|
17
20
|
return BRANCH_PERMISSIONS;
|
|
18
21
|
},
|
|
@@ -248,6 +251,9 @@ const TASK_COMMENT_PERMISSIONS = {
|
|
|
248
251
|
READ: 'task-comment.read',
|
|
249
252
|
DELETE: 'task-comment.delete'
|
|
250
253
|
};
|
|
254
|
+
const AI_ASSISTANT_PERMISSIONS = {
|
|
255
|
+
VIEW_ALL_HISTORY: 'ai-assistant.view-all-history'
|
|
256
|
+
};
|
|
251
257
|
const PERMISSIONS = {
|
|
252
258
|
// Auth
|
|
253
259
|
USER: USER_PERMISSIONS,
|
|
@@ -283,5 +289,7 @@ const PERMISSIONS = {
|
|
|
283
289
|
TASK_LIST: TASK_LIST_PERMISSIONS,
|
|
284
290
|
TASK: TASK_PERMISSIONS,
|
|
285
291
|
TASK_LABEL: TASK_LABEL_PERMISSIONS,
|
|
286
|
-
TASK_COMMENT: TASK_COMMENT_PERMISSIONS
|
|
292
|
+
TASK_COMMENT: TASK_COMMENT_PERMISSIONS,
|
|
293
|
+
// AI Assistant
|
|
294
|
+
AI_ASSISTANT: AI_ASSISTANT_PERMISSIONS
|
|
287
295
|
};
|
package/cjs/guards/index.js
CHANGED
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
3
3
|
value: true
|
|
4
4
|
});
|
|
5
5
|
_export_star(require("./jwt-auth.guard"), exports);
|
|
6
|
+
_export_star(require("./optional-jwt-auth.guard"), exports);
|
|
6
7
|
_export_star(require("./permission.guard"), exports);
|
|
7
8
|
function _export_star(from, to) {
|
|
8
9
|
Object.keys(from).forEach(function(k) {
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
Object.defineProperty(exports, "OptionalJwtGuard", {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: function() {
|
|
8
|
+
return OptionalJwtGuard;
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
const _common = require("@nestjs/common");
|
|
12
|
+
const _core = require("@nestjs/core");
|
|
13
|
+
const _passport = require("@nestjs/passport");
|
|
14
|
+
const _constants = require("../constants");
|
|
15
|
+
function _define_property(obj, key, value) {
|
|
16
|
+
if (key in obj) {
|
|
17
|
+
Object.defineProperty(obj, key, {
|
|
18
|
+
value: value,
|
|
19
|
+
enumerable: true,
|
|
20
|
+
configurable: true,
|
|
21
|
+
writable: true
|
|
22
|
+
});
|
|
23
|
+
} else {
|
|
24
|
+
obj[key] = value;
|
|
25
|
+
}
|
|
26
|
+
return obj;
|
|
27
|
+
}
|
|
28
|
+
function _ts_decorate(decorators, target, key, desc) {
|
|
29
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
30
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
31
|
+
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;
|
|
32
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
33
|
+
}
|
|
34
|
+
function _ts_metadata(k, v) {
|
|
35
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
36
|
+
}
|
|
37
|
+
function _ts_param(paramIndex, decorator) {
|
|
38
|
+
return function(target, key) {
|
|
39
|
+
decorator(target, key, paramIndex);
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
let OptionalJwtGuard = class OptionalJwtGuard extends (0, _passport.AuthGuard)('jwt') {
|
|
43
|
+
canActivate(context) {
|
|
44
|
+
const isPublic = this.reflector.getAllAndOverride(_constants.IS_PUBLIC_KEY, [
|
|
45
|
+
context.getHandler(),
|
|
46
|
+
context.getClass()
|
|
47
|
+
]);
|
|
48
|
+
if (isPublic) {
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
return super.canActivate(context);
|
|
52
|
+
}
|
|
53
|
+
handleRequest(_err, user) {
|
|
54
|
+
return user || undefined;
|
|
55
|
+
}
|
|
56
|
+
constructor(reflector){
|
|
57
|
+
super(), _define_property(this, "reflector", void 0), this.reflector = reflector;
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
OptionalJwtGuard = _ts_decorate([
|
|
61
|
+
(0, _common.Injectable)(),
|
|
62
|
+
_ts_param(0, (0, _common.Inject)(_core.Reflector)),
|
|
63
|
+
_ts_metadata("design:type", Function),
|
|
64
|
+
_ts_metadata("design:paramtypes", [
|
|
65
|
+
typeof _core.Reflector === "undefined" ? Object : _core.Reflector
|
|
66
|
+
])
|
|
67
|
+
], OptionalJwtGuard);
|
|
@@ -14,6 +14,7 @@ const _hybridcacheclass = require("../classes/hybrid-cache.class");
|
|
|
14
14
|
const _constants = require("../constants");
|
|
15
15
|
const _permissionexception = require("../exceptions/permission.exception");
|
|
16
16
|
const _permissioninterface = require("../interfaces/permission.interface");
|
|
17
|
+
const _permissioncachekeyutil = require("../utils/permission-cache-key.util");
|
|
17
18
|
function _define_property(obj, key, value) {
|
|
18
19
|
if (key in obj) {
|
|
19
20
|
Object.defineProperty(obj, key, {
|
|
@@ -157,14 +158,14 @@ let PermissionGuard = class PermissionGuard {
|
|
|
157
158
|
}
|
|
158
159
|
async getUserPermissions(user) {
|
|
159
160
|
if (!this.cache) throw new _permissionexception.PermissionSystemUnavailableException();
|
|
160
|
-
const cacheKey =
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
return (
|
|
161
|
+
const cacheKey = (0, _permissioncachekeyutil.buildPermissionCacheKey)({
|
|
162
|
+
userId: user.id,
|
|
163
|
+
companyId: user.companyId,
|
|
164
|
+
branchId: user.branchId
|
|
165
|
+
}, this.config);
|
|
166
|
+
const cached = await this.cache.get(cacheKey);
|
|
167
|
+
if (!cached) return [];
|
|
168
|
+
return Array.isArray(cached) ? cached : cached.backendCodes || [];
|
|
168
169
|
}
|
|
169
170
|
hasPermission(userPermissions, requiredPermission) {
|
|
170
171
|
if (userPermissions.includes(requiredPermission)) return true;
|
|
@@ -184,8 +185,8 @@ let PermissionGuard = class PermissionGuard {
|
|
|
184
185
|
this.cache = cache;
|
|
185
186
|
this.config = {
|
|
186
187
|
enableCompanyFeature: false,
|
|
187
|
-
userPermissionKeyFormat:
|
|
188
|
-
companyPermissionKeyFormat:
|
|
188
|
+
userPermissionKeyFormat: _permissioncachekeyutil.DEFAULT_USER_PERMISSION_KEY_FORMAT,
|
|
189
|
+
companyPermissionKeyFormat: _permissioncachekeyutil.DEFAULT_COMPANY_PERMISSION_KEY_FORMAT,
|
|
189
190
|
...config
|
|
190
191
|
};
|
|
191
192
|
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
function _export(target, all) {
|
|
6
|
+
for(var name in all)Object.defineProperty(target, name, {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: Object.getOwnPropertyDescriptor(all, name).get
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
_export(exports, {
|
|
12
|
+
get AI_ASSISTANT_AUTH_PROVIDER () {
|
|
13
|
+
return AI_ASSISTANT_AUTH_PROVIDER;
|
|
14
|
+
},
|
|
15
|
+
get AI_ASSISTANT_TOOL_PROVIDER () {
|
|
16
|
+
return AI_ASSISTANT_TOOL_PROVIDER;
|
|
17
|
+
},
|
|
18
|
+
get AI_ASSISTANT_USER_LOOKUP_PROVIDER () {
|
|
19
|
+
return AI_ASSISTANT_USER_LOOKUP_PROVIDER;
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
const AI_ASSISTANT_AUTH_PROVIDER = 'AI_ASSISTANT_AUTH_PROVIDER';
|
|
23
|
+
const AI_ASSISTANT_TOOL_PROVIDER = 'AI_ASSISTANT_TOOL_PROVIDER';
|
|
24
|
+
const AI_ASSISTANT_USER_LOOKUP_PROVIDER = 'AI_ASSISTANT_USER_LOOKUP_PROVIDER';
|
package/cjs/interfaces/index.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", {
|
|
3
3
|
value: true
|
|
4
4
|
});
|
|
5
|
+
_export_star(require("./ai-assistant-adapter.interface"), exports);
|
|
5
6
|
_export_star(require("./api.interface"), exports);
|
|
6
7
|
_export_star(require("./datasource.interface"), exports);
|
|
7
8
|
_export_star(require("./event-manager-adapter.interface"), exports);
|
|
@@ -10,6 +11,7 @@ _export_star(require("./logged-user-info.interface"), exports);
|
|
|
10
11
|
_export_star(require("./module-config.interface"), exports);
|
|
11
12
|
_export_star(require("./notification-adapter.interface"), exports);
|
|
12
13
|
_export_star(require("./permission.interface"), exports);
|
|
14
|
+
_export_star(require("./permission-sync-adapter.interface"), exports);
|
|
13
15
|
function _export_star(from, to) {
|
|
14
16
|
Object.keys(from).forEach(function(k) {
|
|
15
17
|
if (k !== "default" && !Object.prototype.hasOwnProperty.call(to, k)) {
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
Object.defineProperty(exports, "PERMISSION_SYNC_ADAPTER", {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: function() {
|
|
8
|
+
return PERMISSION_SYNC_ADAPTER;
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
const PERMISSION_SYNC_ADAPTER = 'PERMISSION_SYNC_ADAPTER';
|
package/cjs/utils/index.js
CHANGED
|
@@ -4,6 +4,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
});
|
|
5
5
|
_export_star(require("./date-time.util"), exports);
|
|
6
6
|
_export_star(require("./html-sanitizer.util"), exports);
|
|
7
|
+
_export_star(require("./permission-cache-key.util"), exports);
|
|
7
8
|
_export_star(require("./query-helpers.util"), exports);
|
|
8
9
|
_export_star(require("./request.util"), exports);
|
|
9
10
|
_export_star(require("./string.util"), exports);
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
function _export(target, all) {
|
|
6
|
+
for(var name in all)Object.defineProperty(target, name, {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: Object.getOwnPropertyDescriptor(all, name).get
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
_export(exports, {
|
|
12
|
+
get DEFAULT_COMPANY_PERMISSION_KEY_FORMAT () {
|
|
13
|
+
return DEFAULT_COMPANY_PERMISSION_KEY_FORMAT;
|
|
14
|
+
},
|
|
15
|
+
get DEFAULT_USER_PERMISSION_KEY_FORMAT () {
|
|
16
|
+
return DEFAULT_USER_PERMISSION_KEY_FORMAT;
|
|
17
|
+
},
|
|
18
|
+
get buildPermissionCacheKey () {
|
|
19
|
+
return buildPermissionCacheKey;
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
const _constants = require("../constants");
|
|
23
|
+
const DEFAULT_USER_PERMISSION_KEY_FORMAT = `${_constants.PERMISSIONS_CACHE_PREFIX}:user:{userId}`;
|
|
24
|
+
const DEFAULT_COMPANY_PERMISSION_KEY_FORMAT = `${_constants.PERMISSIONS_CACHE_PREFIX}:company:{companyId}:branch:{branchId}:user:{userId}`;
|
|
25
|
+
function buildPermissionCacheKey(options, config) {
|
|
26
|
+
const isCompanyScope = Boolean(config?.enableCompanyFeature && options.companyId);
|
|
27
|
+
if (isCompanyScope) {
|
|
28
|
+
return (config?.companyPermissionKeyFormat || DEFAULT_COMPANY_PERMISSION_KEY_FORMAT).replace('{userId}', options.userId).replace('{companyId}', options.companyId).replace('{branchId}', options.branchId || 'null');
|
|
29
|
+
}
|
|
30
|
+
return (config?.userPermissionKeyFormat || DEFAULT_USER_PERMISSION_KEY_FORMAT).replace('{userId}', options.userId);
|
|
31
|
+
}
|
package/constants/index.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ export declare const PERMISSION_GUARD_CONFIG = "PERMISSION_GUARD_CONFIG";
|
|
|
5
5
|
export declare const IDEMPOTENCY_KEY_HEADER = "x-idempotency-key";
|
|
6
6
|
export declare const REQUEST_ID_HEADER = "x-request-id";
|
|
7
7
|
export declare const CLIENT_TYPE_HEADER = "x-client-type";
|
|
8
|
-
export declare const PERMISSIONS_CACHE_PREFIX = "permissions";
|
|
8
|
+
export declare const PERMISSIONS_CACHE_PREFIX = "my-permissions";
|
|
9
9
|
export declare const IDEMPOTENCY_CACHE_PREFIX = "idempotency";
|
|
10
10
|
export * from './permissions';
|
|
11
11
|
export * from './message-keys';
|
|
@@ -151,6 +151,9 @@ export declare const TASK_COMMENT_PERMISSIONS: {
|
|
|
151
151
|
readonly READ: "task-comment.read";
|
|
152
152
|
readonly DELETE: "task-comment.delete";
|
|
153
153
|
};
|
|
154
|
+
export declare const AI_ASSISTANT_PERMISSIONS: {
|
|
155
|
+
readonly VIEW_ALL_HISTORY: "ai-assistant.view-all-history";
|
|
156
|
+
};
|
|
154
157
|
export declare const PERMISSIONS: {
|
|
155
158
|
readonly USER: {
|
|
156
159
|
readonly CREATE: "user.create";
|
|
@@ -302,5 +305,8 @@ export declare const PERMISSIONS: {
|
|
|
302
305
|
readonly READ: "task-comment.read";
|
|
303
306
|
readonly DELETE: "task-comment.delete";
|
|
304
307
|
};
|
|
308
|
+
readonly AI_ASSISTANT: {
|
|
309
|
+
readonly VIEW_ALL_HISTORY: "ai-assistant.view-all-history";
|
|
310
|
+
};
|
|
305
311
|
};
|
|
306
312
|
export type PermissionCode = (typeof PERMISSIONS)[keyof typeof PERMISSIONS][keyof (typeof PERMISSIONS)[keyof typeof PERMISSIONS]];
|
package/fesm/constants/index.js
CHANGED
|
@@ -9,7 +9,7 @@ export const IDEMPOTENCY_KEY_HEADER = 'x-idempotency-key';
|
|
|
9
9
|
export const REQUEST_ID_HEADER = 'x-request-id';
|
|
10
10
|
export const CLIENT_TYPE_HEADER = 'x-client-type';
|
|
11
11
|
// Cache key prefixes
|
|
12
|
-
export const PERMISSIONS_CACHE_PREFIX = 'permissions';
|
|
12
|
+
export const PERMISSIONS_CACHE_PREFIX = 'my-permissions';
|
|
13
13
|
export const IDEMPOTENCY_CACHE_PREFIX = 'idempotency';
|
|
14
14
|
// Permission codes
|
|
15
15
|
export * from './permissions';
|
|
@@ -160,6 +160,10 @@ export const TASK_COMMENT_PERMISSIONS = {
|
|
|
160
160
|
READ: 'task-comment.read',
|
|
161
161
|
DELETE: 'task-comment.delete'
|
|
162
162
|
};
|
|
163
|
+
// ==================== AI ASSISTANT MODULE ====================
|
|
164
|
+
export const AI_ASSISTANT_PERMISSIONS = {
|
|
165
|
+
VIEW_ALL_HISTORY: 'ai-assistant.view-all-history'
|
|
166
|
+
};
|
|
163
167
|
// ==================== AGGREGATED EXPORTS ====================
|
|
164
168
|
export const PERMISSIONS = {
|
|
165
169
|
// Auth
|
|
@@ -196,5 +200,7 @@ export const PERMISSIONS = {
|
|
|
196
200
|
TASK_LIST: TASK_LIST_PERMISSIONS,
|
|
197
201
|
TASK: TASK_PERMISSIONS,
|
|
198
202
|
TASK_LABEL: TASK_LABEL_PERMISSIONS,
|
|
199
|
-
TASK_COMMENT: TASK_COMMENT_PERMISSIONS
|
|
203
|
+
TASK_COMMENT: TASK_COMMENT_PERMISSIONS,
|
|
204
|
+
// AI Assistant
|
|
205
|
+
AI_ASSISTANT: AI_ASSISTANT_PERMISSIONS
|
|
200
206
|
};
|
package/fesm/guards/index.js
CHANGED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
function _define_property(obj, key, value) {
|
|
2
|
+
if (key in obj) {
|
|
3
|
+
Object.defineProperty(obj, key, {
|
|
4
|
+
value: value,
|
|
5
|
+
enumerable: true,
|
|
6
|
+
configurable: true,
|
|
7
|
+
writable: true
|
|
8
|
+
});
|
|
9
|
+
} else {
|
|
10
|
+
obj[key] = value;
|
|
11
|
+
}
|
|
12
|
+
return obj;
|
|
13
|
+
}
|
|
14
|
+
function _ts_decorate(decorators, target, key, desc) {
|
|
15
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
16
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
17
|
+
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;
|
|
18
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
19
|
+
}
|
|
20
|
+
function _ts_metadata(k, v) {
|
|
21
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
22
|
+
}
|
|
23
|
+
function _ts_param(paramIndex, decorator) {
|
|
24
|
+
return function(target, key) {
|
|
25
|
+
decorator(target, key, paramIndex);
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
import { Inject, Injectable } from '@nestjs/common';
|
|
29
|
+
import { Reflector } from '@nestjs/core';
|
|
30
|
+
import { AuthGuard } from '@nestjs/passport';
|
|
31
|
+
import { IS_PUBLIC_KEY } from '../constants';
|
|
32
|
+
export class OptionalJwtGuard extends AuthGuard('jwt') {
|
|
33
|
+
canActivate(context) {
|
|
34
|
+
const isPublic = this.reflector.getAllAndOverride(IS_PUBLIC_KEY, [
|
|
35
|
+
context.getHandler(),
|
|
36
|
+
context.getClass()
|
|
37
|
+
]);
|
|
38
|
+
if (isPublic) {
|
|
39
|
+
return true;
|
|
40
|
+
}
|
|
41
|
+
return super.canActivate(context);
|
|
42
|
+
}
|
|
43
|
+
handleRequest(_err, user) {
|
|
44
|
+
return user || undefined;
|
|
45
|
+
}
|
|
46
|
+
constructor(reflector){
|
|
47
|
+
super(), _define_property(this, "reflector", void 0), this.reflector = reflector;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
OptionalJwtGuard = _ts_decorate([
|
|
51
|
+
Injectable(),
|
|
52
|
+
_ts_param(0, Inject(Reflector)),
|
|
53
|
+
_ts_metadata("design:type", Function),
|
|
54
|
+
_ts_metadata("design:paramtypes", [
|
|
55
|
+
typeof Reflector === "undefined" ? Object : Reflector
|
|
56
|
+
])
|
|
57
|
+
], OptionalJwtGuard);
|
|
@@ -28,9 +28,10 @@ function _ts_param(paramIndex, decorator) {
|
|
|
28
28
|
import { Inject, Injectable, Optional, UnauthorizedException } from '@nestjs/common';
|
|
29
29
|
import { Reflector } from '@nestjs/core';
|
|
30
30
|
import { HybridCache } from '../classes/hybrid-cache.class';
|
|
31
|
-
import { AUTH_MESSAGES, CACHE_INSTANCE, IS_PUBLIC_KEY, PERMISSION_GUARD_CONFIG,
|
|
31
|
+
import { AUTH_MESSAGES, CACHE_INSTANCE, IS_PUBLIC_KEY, PERMISSION_GUARD_CONFIG, PERMISSIONS_KEY } from '../constants';
|
|
32
32
|
import { InsufficientPermissionsException, NoPermissionsFoundException, PermissionSystemUnavailableException } from '../exceptions/permission.exception';
|
|
33
33
|
import { PermissionGuardConfig } from '../interfaces/permission.interface';
|
|
34
|
+
import { buildPermissionCacheKey, DEFAULT_COMPANY_PERMISSION_KEY_FORMAT, DEFAULT_USER_PERMISSION_KEY_FORMAT } from '../utils/permission-cache-key.util';
|
|
34
35
|
export class PermissionGuard {
|
|
35
36
|
async canActivate(context) {
|
|
36
37
|
const isPublic = this.reflector.getAllAndOverride(IS_PUBLIC_KEY, [
|
|
@@ -147,14 +148,14 @@ export class PermissionGuard {
|
|
|
147
148
|
}
|
|
148
149
|
async getUserPermissions(user) {
|
|
149
150
|
if (!this.cache) throw new PermissionSystemUnavailableException();
|
|
150
|
-
const cacheKey =
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
return (
|
|
151
|
+
const cacheKey = buildPermissionCacheKey({
|
|
152
|
+
userId: user.id,
|
|
153
|
+
companyId: user.companyId,
|
|
154
|
+
branchId: user.branchId
|
|
155
|
+
}, this.config);
|
|
156
|
+
const cached = await this.cache.get(cacheKey);
|
|
157
|
+
if (!cached) return [];
|
|
158
|
+
return Array.isArray(cached) ? cached : cached.backendCodes || [];
|
|
158
159
|
}
|
|
159
160
|
hasPermission(userPermissions, requiredPermission) {
|
|
160
161
|
if (userPermissions.includes(requiredPermission)) return true;
|
|
@@ -174,8 +175,8 @@ export class PermissionGuard {
|
|
|
174
175
|
this.cache = cache;
|
|
175
176
|
this.config = {
|
|
176
177
|
enableCompanyFeature: false,
|
|
177
|
-
userPermissionKeyFormat:
|
|
178
|
-
companyPermissionKeyFormat:
|
|
178
|
+
userPermissionKeyFormat: DEFAULT_USER_PERMISSION_KEY_FORMAT,
|
|
179
|
+
companyPermissionKeyFormat: DEFAULT_COMPANY_PERMISSION_KEY_FORMAT,
|
|
179
180
|
...config
|
|
180
181
|
};
|
|
181
182
|
}
|
package/fesm/interfaces/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export * from './ai-assistant-adapter.interface';
|
|
1
2
|
export * from './api.interface';
|
|
2
3
|
export * from './datasource.interface';
|
|
3
4
|
export * from './event-manager-adapter.interface';
|
|
@@ -6,3 +7,4 @@ export * from './logged-user-info.interface';
|
|
|
6
7
|
export * from './module-config.interface';
|
|
7
8
|
export * from './notification-adapter.interface';
|
|
8
9
|
export * from './permission.interface';
|
|
10
|
+
export * from './permission-sync-adapter.interface';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const PERMISSION_SYNC_ADAPTER = 'PERMISSION_SYNC_ADAPTER';
|
package/fesm/utils/index.js
CHANGED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { PERMISSIONS_CACHE_PREFIX } from '../constants';
|
|
2
|
+
export const DEFAULT_USER_PERMISSION_KEY_FORMAT = `${PERMISSIONS_CACHE_PREFIX}:user:{userId}`;
|
|
3
|
+
export const DEFAULT_COMPANY_PERMISSION_KEY_FORMAT = `${PERMISSIONS_CACHE_PREFIX}:company:{companyId}:branch:{branchId}:user:{userId}`;
|
|
4
|
+
/** Single source of truth for permission cache keys, shared by the guard (reader) and cache service (writer) so a config override can't desync them; company scope requires enableCompanyFeature, not just a companyId */ export function buildPermissionCacheKey(options, config) {
|
|
5
|
+
const isCompanyScope = Boolean(config?.enableCompanyFeature && options.companyId);
|
|
6
|
+
if (isCompanyScope) {
|
|
7
|
+
return (config?.companyPermissionKeyFormat || DEFAULT_COMPANY_PERMISSION_KEY_FORMAT).replace('{userId}', options.userId).replace('{companyId}', options.companyId).replace('{branchId}', options.branchId || 'null');
|
|
8
|
+
}
|
|
9
|
+
return (config?.userPermissionKeyFormat || DEFAULT_USER_PERMISSION_KEY_FORMAT).replace('{userId}', options.userId);
|
|
10
|
+
}
|
package/guards/index.d.ts
CHANGED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { ExecutionContext } from '@nestjs/common';
|
|
2
|
+
import { Reflector } from '@nestjs/core';
|
|
3
|
+
declare const OptionalJwtGuard_base: import("@nestjs/passport").Type<import("@nestjs/passport").IAuthGuard>;
|
|
4
|
+
export declare class OptionalJwtGuard extends OptionalJwtGuard_base {
|
|
5
|
+
private reflector;
|
|
6
|
+
constructor(reflector: Reflector);
|
|
7
|
+
canActivate(context: ExecutionContext): boolean | Promise<boolean> | import("rxjs").Observable<boolean>;
|
|
8
|
+
handleRequest<TUser = unknown>(_err: unknown, user: unknown): TUser;
|
|
9
|
+
}
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { ILoggedUserInfo } from './logged-user-info.interface';
|
|
2
|
+
export declare const AI_ASSISTANT_AUTH_PROVIDER = "AI_ASSISTANT_AUTH_PROVIDER";
|
|
3
|
+
export declare const AI_ASSISTANT_TOOL_PROVIDER = "AI_ASSISTANT_TOOL_PROVIDER";
|
|
4
|
+
export declare const AI_ASSISTANT_USER_LOOKUP_PROVIDER = "AI_ASSISTANT_USER_LOOKUP_PROVIDER";
|
|
5
|
+
export interface IAiAssistantAuthContext {
|
|
6
|
+
userId: string;
|
|
7
|
+
role: string;
|
|
8
|
+
permissions: string[];
|
|
9
|
+
companyId?: string;
|
|
10
|
+
branchId?: string;
|
|
11
|
+
[key: string]: unknown;
|
|
12
|
+
}
|
|
13
|
+
export interface IAiAssistantIdentity {
|
|
14
|
+
userId: string;
|
|
15
|
+
companyId?: string;
|
|
16
|
+
branchId?: string;
|
|
17
|
+
[key: string]: unknown;
|
|
18
|
+
}
|
|
19
|
+
export interface IAiAssistantAuthProvider {
|
|
20
|
+
resolveAuthContext(identity: IAiAssistantIdentity | null): Promise<IAiAssistantAuthContext>;
|
|
21
|
+
}
|
|
22
|
+
export interface IAiAssistantUserBasicInfo {
|
|
23
|
+
id: string;
|
|
24
|
+
name: string;
|
|
25
|
+
email: string;
|
|
26
|
+
}
|
|
27
|
+
export interface IAiAssistantUserLookupProvider {
|
|
28
|
+
getUsersByIds(ids: string[], user: ILoggedUserInfo): Promise<IAiAssistantUserBasicInfo[]>;
|
|
29
|
+
}
|
|
30
|
+
export interface IAiAssistantJsonSchema {
|
|
31
|
+
type: 'object';
|
|
32
|
+
properties: Record<string, unknown>;
|
|
33
|
+
required?: string[];
|
|
34
|
+
[key: string]: unknown;
|
|
35
|
+
}
|
|
36
|
+
export interface IAiAssistantToolDefinition<TArgs = Record<string, unknown>, TResult = unknown> {
|
|
37
|
+
name: string;
|
|
38
|
+
description: string;
|
|
39
|
+
inputSchema: IAiAssistantJsonSchema;
|
|
40
|
+
renderHint?: 'text' | 'table';
|
|
41
|
+
isVisible(ctx: IAiAssistantAuthContext): boolean;
|
|
42
|
+
handler(args: TArgs, ctx: IAiAssistantAuthContext): Promise<TResult>;
|
|
43
|
+
}
|
package/interfaces/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export * from './ai-assistant-adapter.interface';
|
|
1
2
|
export * from './api.interface';
|
|
2
3
|
export * from './datasource.interface';
|
|
3
4
|
export * from './event-manager-adapter.interface';
|
|
@@ -6,3 +7,4 @@ export * from './logged-user-info.interface';
|
|
|
6
7
|
export * from './module-config.interface';
|
|
7
8
|
export * from './notification-adapter.interface';
|
|
8
9
|
export * from './permission.interface';
|
|
10
|
+
export * from './permission-sync-adapter.interface';
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export interface IPermissionSyncAdapter {
|
|
2
|
+
onCompanyDeleted?(companyId: string): Promise<void>;
|
|
3
|
+
onBranchDeleted?(branchId: string, companyId: string): Promise<void>;
|
|
4
|
+
onUserCompanyAccessRevoked?(userId: string, companyId: string): Promise<void>;
|
|
5
|
+
onUserBranchAccessRevoked?(userId: string, branchId: string, companyId: string): Promise<void>;
|
|
6
|
+
}
|
|
7
|
+
export declare const PERMISSION_SYNC_ADAPTER = "PERMISSION_SYNC_ADAPTER";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flusys/nestjs-shared",
|
|
3
|
-
"version": "6.0.
|
|
3
|
+
"version": "6.0.2",
|
|
4
4
|
"description": "Common shared utilities for Flusys NestJS applications",
|
|
5
5
|
"main": "cjs/index.js",
|
|
6
6
|
"module": "fesm/index.js",
|
|
@@ -112,6 +112,6 @@
|
|
|
112
112
|
"rxjs": "^7.8.0"
|
|
113
113
|
},
|
|
114
114
|
"dependencies": {
|
|
115
|
-
"@flusys/nestjs-core": "6.0.
|
|
115
|
+
"@flusys/nestjs-core": "6.0.2"
|
|
116
116
|
}
|
|
117
117
|
}
|
package/utils/index.d.ts
CHANGED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { PermissionGuardConfig } from '../interfaces/permission.interface';
|
|
2
|
+
export interface PermissionCacheKeyOptions {
|
|
3
|
+
userId: string;
|
|
4
|
+
companyId?: string | null;
|
|
5
|
+
branchId?: string | null;
|
|
6
|
+
}
|
|
7
|
+
export declare const DEFAULT_USER_PERMISSION_KEY_FORMAT = "my-permissions:user:{userId}";
|
|
8
|
+
export declare const DEFAULT_COMPANY_PERMISSION_KEY_FORMAT = "my-permissions:company:{companyId}:branch:{branchId}:user:{userId}";
|
|
9
|
+
export declare function buildPermissionCacheKey(options: PermissionCacheKeyOptions, config?: PermissionGuardConfig): string;
|