@flusys/nestjs-shared 1.1.0-beta → 2.0.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/README.md +501 -720
- package/cjs/classes/api-controller.class.js +9 -24
- package/cjs/classes/api-service.class.js +59 -92
- package/cjs/classes/index.js +1 -0
- package/cjs/classes/winston-logger-adapter.class.js +23 -40
- package/cjs/constants/index.js +14 -0
- package/cjs/constants/permissions.js +184 -0
- package/cjs/decorators/api-response.decorator.js +1 -1
- package/cjs/decorators/index.js +1 -0
- package/cjs/decorators/sanitize-html.decorator.js +36 -0
- package/cjs/dtos/delete.dto.js +10 -0
- package/cjs/dtos/filter-and-pagination.dto.js +24 -34
- package/cjs/dtos/pagination.dto.js +4 -8
- package/cjs/dtos/response-payload.dto.js +0 -116
- package/cjs/entities/identity.js +4 -4
- package/cjs/entities/user-root.js +13 -14
- package/cjs/guards/permission.guard.js +51 -105
- package/cjs/interceptors/index.js +1 -3
- package/cjs/interceptors/set-user-field-on-body.interceptor.js +60 -0
- package/cjs/interceptors/slug.interceptor.js +30 -9
- package/cjs/interfaces/datasource.interface.js +4 -0
- package/cjs/interfaces/index.js +2 -1
- package/cjs/interfaces/module-config.interface.js +4 -0
- package/cjs/middlewares/logger.middleware.js +50 -89
- package/cjs/modules/cache/cache.module.js +3 -3
- package/cjs/modules/datasource/datasource.module.js +11 -14
- package/cjs/modules/datasource/multi-tenant-datasource.service.js +29 -113
- package/cjs/modules/utils/utils.service.js +40 -203
- package/cjs/utils/error-handler.util.js +35 -12
- package/cjs/utils/html-sanitizer.util.js +64 -0
- package/cjs/utils/index.js +4 -0
- package/cjs/utils/query-helpers.util.js +53 -0
- package/cjs/utils/request.util.js +70 -0
- package/cjs/utils/string.util.js +63 -0
- package/classes/api-controller.class.d.ts +5 -5
- package/classes/api-service.class.d.ts +7 -5
- package/classes/index.d.ts +1 -0
- package/classes/request-scoped-api.service.d.ts +3 -2
- package/classes/winston-logger-adapter.class.d.ts +2 -0
- package/constants/index.d.ts +1 -0
- package/constants/permissions.d.ts +179 -0
- package/decorators/index.d.ts +1 -0
- package/decorators/sanitize-html.decorator.d.ts +2 -0
- package/dtos/delete.dto.d.ts +1 -0
- package/dtos/filter-and-pagination.dto.d.ts +0 -2
- package/dtos/response-payload.dto.d.ts +0 -20
- package/fesm/classes/api-controller.class.js +9 -24
- package/fesm/classes/api-service.class.js +59 -92
- package/fesm/classes/index.js +2 -0
- package/fesm/classes/winston-logger-adapter.class.js +23 -40
- package/fesm/constants/index.js +2 -0
- package/fesm/constants/permissions.js +128 -0
- package/fesm/decorators/api-response.decorator.js +1 -1
- package/fesm/decorators/index.js +1 -0
- package/fesm/decorators/sanitize-html.decorator.js +45 -0
- package/fesm/dtos/delete.dto.js +12 -2
- package/fesm/dtos/filter-and-pagination.dto.js +26 -47
- package/fesm/dtos/pagination.dto.js +4 -8
- package/fesm/dtos/response-payload.dto.js +0 -107
- package/fesm/entities/identity.js +4 -4
- package/fesm/entities/user-root.js +13 -14
- package/fesm/guards/permission.guard.js +51 -105
- package/fesm/interceptors/index.js +1 -3
- package/fesm/interceptors/set-user-field-on-body.interceptor.js +39 -0
- package/fesm/interceptors/slug.interceptor.js +31 -10
- package/fesm/interfaces/datasource.interface.js +20 -0
- package/fesm/interfaces/index.js +2 -1
- package/fesm/interfaces/module-config.interface.js +5 -0
- package/fesm/middlewares/logger.middleware.js +50 -83
- package/fesm/modules/cache/cache.module.js +2 -2
- package/fesm/modules/datasource/datasource.module.js +11 -14
- package/fesm/modules/datasource/multi-tenant-datasource.service.js +29 -113
- package/fesm/modules/utils/utils.service.js +41 -204
- package/fesm/utils/error-handler.util.js +36 -13
- package/fesm/utils/html-sanitizer.util.js +69 -0
- package/fesm/utils/index.js +4 -0
- package/fesm/utils/query-helpers.util.js +78 -0
- package/fesm/utils/request.util.js +58 -0
- package/fesm/utils/string.util.js +71 -0
- package/guards/permission.guard.d.ts +2 -0
- package/interceptors/index.d.ts +1 -3
- package/interceptors/set-user-field-on-body.interceptor.d.ts +5 -0
- package/interceptors/slug.interceptor.d.ts +2 -1
- package/interfaces/api.interface.d.ts +2 -2
- package/interfaces/datasource.interface.d.ts +5 -0
- package/interfaces/identity.interface.d.ts +4 -4
- package/interfaces/index.d.ts +2 -1
- package/interfaces/logged-user-info.interface.d.ts +0 -2
- package/interfaces/module-config.interface.d.ts +6 -0
- package/interfaces/permission.interface.d.ts +0 -1
- package/middlewares/logger.middleware.d.ts +2 -2
- package/modules/datasource/datasource.module.d.ts +1 -0
- package/modules/datasource/multi-tenant-datasource.service.d.ts +0 -1
- package/modules/utils/utils.service.d.ts +4 -14
- package/package.json +4 -4
- package/utils/error-handler.util.d.ts +14 -19
- package/utils/html-sanitizer.util.d.ts +2 -0
- package/utils/index.d.ts +4 -0
- package/utils/query-helpers.util.d.ts +16 -0
- package/utils/request.util.d.ts +4 -0
- package/utils/string.util.d.ts +2 -0
- package/cjs/interceptors/set-create-by-on-body.interceptor.js +0 -40
- package/cjs/interceptors/set-delete-by-on-body.interceptor.js +0 -40
- package/cjs/interceptors/set-update-by-on-body.interceptor.js +0 -40
- package/cjs/interfaces/base-query.interface.js +0 -6
- package/fesm/interceptors/set-create-by-on-body.interceptor.js +0 -30
- package/fesm/interceptors/set-delete-by-on-body.interceptor.js +0 -30
- package/fesm/interceptors/set-update-by-on-body.interceptor.js +0 -30
- package/fesm/interfaces/base-query.interface.js +0 -3
- package/interceptors/set-create-by-on-body.interceptor.d.ts +0 -5
- package/interceptors/set-delete-by-on-body.interceptor.d.ts +0 -5
- package/interceptors/set-update-by-on-body.interceptor.d.ts +0 -5
- package/interfaces/base-query.interface.d.ts +0 -7
|
@@ -8,10 +8,10 @@ Object.defineProperty(exports, "createApiController", {
|
|
|
8
8
|
return createApiController;
|
|
9
9
|
}
|
|
10
10
|
});
|
|
11
|
-
const _decorators = require("
|
|
12
|
-
const _dtos = require("
|
|
13
|
-
const _guards = require("
|
|
14
|
-
const _interceptors = require("
|
|
11
|
+
const _decorators = require("../decorators");
|
|
12
|
+
const _dtos = require("../dtos");
|
|
13
|
+
const _guards = require("../guards");
|
|
14
|
+
const _interceptors = require("../interceptors");
|
|
15
15
|
const _common = require("@nestjs/common");
|
|
16
16
|
const _swagger = require("@nestjs/swagger");
|
|
17
17
|
const _classtransformer = require("class-transformer");
|
|
@@ -104,8 +104,10 @@ function createApiController(createDtoClass, updateDtoClass, responseDtoClass, o
|
|
|
104
104
|
// 2. It's an object with 'level' property but no endpoint keys
|
|
105
105
|
const isGlobalSecurity = typeof securityConfig === 'string' || securityConfig && typeof securityConfig === 'object' && 'level' in securityConfig && !endpointKeys.some((key)=>key in securityConfig);
|
|
106
106
|
// Normalize security config for each endpoint
|
|
107
|
+
// IMPORTANT: When per-endpoint security is specified, default to 'jwt' for unconfigured endpoints
|
|
108
|
+
// to prevent accidentally exposing endpoints without authentication
|
|
107
109
|
const defaultSecurity = isGlobalSecurity ? normalizeSecurity(securityConfig) : {
|
|
108
|
-
level: '
|
|
110
|
+
level: 'jwt'
|
|
109
111
|
};
|
|
110
112
|
const security = {
|
|
111
113
|
insert: isGlobalSecurity ? defaultSecurity : normalizeSecurity(securityConfig?.insert),
|
|
@@ -347,16 +349,7 @@ function createApiController(createDtoClass, updateDtoClass, responseDtoClass, o
|
|
|
347
349
|
(0, _common.HttpCode)(_common.HttpStatus.OK),
|
|
348
350
|
(0, _swagger.ApiOperation)({
|
|
349
351
|
summary: 'Get all items with filters and pagination',
|
|
350
|
-
description:
|
|
351
|
-
Retrieves items with support for:
|
|
352
|
-
- **filter**: Apply field-based filters (e.g., \`{ "isActive": true }\`)
|
|
353
|
-
- **pagination**: Control page and page size
|
|
354
|
-
- **sort**: Order by any field (e.g., \`{ "createdAt": "DESC" }\`)
|
|
355
|
-
- **select**: Choose specific fields to return
|
|
356
|
-
- **withDeleted**: Include soft-deleted items
|
|
357
|
-
- **extraKey**: Include additional relations
|
|
358
|
-
- **q** (query param): Global text search
|
|
359
|
-
`
|
|
352
|
+
description: 'Supports filter, pagination, sort, select, withDeleted, and q (search) params'
|
|
360
353
|
}),
|
|
361
354
|
(0, _swagger.ApiQuery)({
|
|
362
355
|
name: 'q',
|
|
@@ -385,15 +378,7 @@ Retrieves items with support for:
|
|
|
385
378
|
(0, _common.HttpCode)(_common.HttpStatus.OK),
|
|
386
379
|
(0, _swagger.ApiOperation)({
|
|
387
380
|
summary: 'Delete, restore, or permanently remove items',
|
|
388
|
-
description:
|
|
389
|
-
Performs one of three actions:
|
|
390
|
-
|
|
391
|
-
- **"delete"** (soft delete): Marks items as deleted but keeps in database
|
|
392
|
-
- **"restore"**: Reverts soft-deleted items to active
|
|
393
|
-
- **"permanent"**: Completely removes items from database
|
|
394
|
-
|
|
395
|
-
Supports single ID or array of IDs for batch operations.
|
|
396
|
-
`
|
|
381
|
+
description: 'Types: delete (soft), restore, permanent. Supports batch IDs.'
|
|
397
382
|
}),
|
|
398
383
|
(0, _swagger.ApiResponse)({
|
|
399
384
|
status: 200,
|
|
@@ -26,116 +26,52 @@ function _define_property(obj, key, value) {
|
|
|
26
26
|
}
|
|
27
27
|
let ApiService = class ApiService {
|
|
28
28
|
async insert(dto, user) {
|
|
29
|
-
|
|
30
|
-
const qr = this.repository.manager.connection.createQueryRunner();
|
|
31
|
-
await qr.connect();
|
|
32
|
-
await qr.startTransaction();
|
|
33
|
-
try {
|
|
29
|
+
return this.executeInTransaction('insert', async (qr)=>{
|
|
34
30
|
await this.beforeInsertOperation(dto, user, qr);
|
|
35
31
|
const entities = await this.convertRequestDtoToEntity(dto, user);
|
|
36
32
|
const saved = await qr.manager.save(this.repository.target, entities);
|
|
37
|
-
await this.afterInsertOperation(saved, user, qr);
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
])
|
|
44
|
-
]);
|
|
45
|
-
const first = Array.isArray(saved) ? saved[0] : saved;
|
|
46
|
-
return this.convertEntityToResponseDto(first, false);
|
|
47
|
-
} catch (error) {
|
|
48
|
-
await qr.rollbackTransaction();
|
|
49
|
-
this.handleError(error, 'insert');
|
|
50
|
-
} finally{
|
|
51
|
-
await qr.release();
|
|
52
|
-
}
|
|
33
|
+
await this.afterInsertOperation(this.ensureArray(saved), user, qr);
|
|
34
|
+
return {
|
|
35
|
+
saved,
|
|
36
|
+
returnFirst: true
|
|
37
|
+
};
|
|
38
|
+
});
|
|
53
39
|
}
|
|
54
40
|
async insertMany(dtos, user) {
|
|
55
|
-
|
|
56
|
-
const qr = this.repository.manager.connection.createQueryRunner();
|
|
57
|
-
await qr.connect();
|
|
58
|
-
await qr.startTransaction();
|
|
59
|
-
try {
|
|
41
|
+
return this.executeInTransaction('insertMany', async (qr)=>{
|
|
60
42
|
await this.beforeInsertOperation(dtos, user, qr);
|
|
61
43
|
const entities = await this.convertRequestDtoToEntity(dtos, user);
|
|
62
44
|
const saved = await qr.manager.save(this.repository.target, entities);
|
|
63
|
-
await this.afterInsertOperation(
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
this.clearCacheForId(Array.isArray(saved) ? saved : [
|
|
70
|
-
saved
|
|
71
|
-
])
|
|
72
|
-
]);
|
|
73
|
-
const list = (Array.isArray(saved) ? saved : [
|
|
74
|
-
saved
|
|
75
|
-
]).map((e)=>this.convertEntityToResponseDto(e, false));
|
|
76
|
-
return list;
|
|
77
|
-
} catch (error) {
|
|
78
|
-
await qr.rollbackTransaction();
|
|
79
|
-
this.handleError(error, 'insertMany');
|
|
80
|
-
} finally{
|
|
81
|
-
await qr.release();
|
|
82
|
-
}
|
|
45
|
+
await this.afterInsertOperation(this.ensureArray(saved), user, qr);
|
|
46
|
+
return {
|
|
47
|
+
saved,
|
|
48
|
+
returnFirst: false
|
|
49
|
+
};
|
|
50
|
+
});
|
|
83
51
|
}
|
|
84
52
|
async update(dto, user) {
|
|
85
|
-
|
|
86
|
-
const qr = this.repository.manager.connection.createQueryRunner();
|
|
87
|
-
await qr.connect();
|
|
88
|
-
await qr.startTransaction();
|
|
89
|
-
try {
|
|
53
|
+
return this.executeInTransaction('update', async (qr)=>{
|
|
90
54
|
await this.beforeUpdateOperation(dto, user, qr);
|
|
91
55
|
const entities = await this.convertRequestDtoToEntity(dto, user);
|
|
92
56
|
const saved = await qr.manager.save(this.repository.target, entities);
|
|
93
|
-
await this.afterUpdateOperation(saved, user, qr);
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
])
|
|
100
|
-
]);
|
|
101
|
-
const first = Array.isArray(saved) ? saved[0] : saved;
|
|
102
|
-
return this.convertEntityToResponseDto(first, false);
|
|
103
|
-
} catch (error) {
|
|
104
|
-
await qr.rollbackTransaction();
|
|
105
|
-
this.handleError(error, 'update');
|
|
106
|
-
} finally{
|
|
107
|
-
await qr.release();
|
|
108
|
-
}
|
|
57
|
+
await this.afterUpdateOperation(this.ensureArray(saved), user, qr);
|
|
58
|
+
return {
|
|
59
|
+
saved,
|
|
60
|
+
returnFirst: true
|
|
61
|
+
};
|
|
62
|
+
});
|
|
109
63
|
}
|
|
110
64
|
async updateMany(dtos, user) {
|
|
111
|
-
|
|
112
|
-
const qr = this.repository.manager.connection.createQueryRunner();
|
|
113
|
-
await qr.connect();
|
|
114
|
-
await qr.startTransaction();
|
|
115
|
-
try {
|
|
65
|
+
return this.executeInTransaction('updateMany', async (qr)=>{
|
|
116
66
|
await this.beforeUpdateOperation(dtos, user, qr);
|
|
117
67
|
const entities = await this.convertRequestDtoToEntity(dtos, user);
|
|
118
68
|
const saved = await qr.manager.save(this.repository.target, entities);
|
|
119
|
-
await this.afterUpdateOperation(
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
this.clearCacheForId(Array.isArray(saved) ? saved : [
|
|
126
|
-
saved
|
|
127
|
-
])
|
|
128
|
-
]);
|
|
129
|
-
const list = (Array.isArray(saved) ? saved : [
|
|
130
|
-
saved
|
|
131
|
-
]).map((e)=>this.convertEntityToResponseDto(e, false));
|
|
132
|
-
return list;
|
|
133
|
-
} catch (error) {
|
|
134
|
-
await qr.rollbackTransaction();
|
|
135
|
-
this.handleError(error, 'updateMany');
|
|
136
|
-
} finally{
|
|
137
|
-
await qr.release();
|
|
138
|
-
}
|
|
69
|
+
await this.afterUpdateOperation(this.ensureArray(saved), user, qr);
|
|
70
|
+
return {
|
|
71
|
+
saved,
|
|
72
|
+
returnFirst: false
|
|
73
|
+
};
|
|
74
|
+
});
|
|
139
75
|
}
|
|
140
76
|
async findByIds(ids, user) {
|
|
141
77
|
await this.ensureRepositoryInitialized();
|
|
@@ -354,6 +290,37 @@ let ApiService = class ApiService {
|
|
|
354
290
|
});
|
|
355
291
|
_errorhandlerutil.ErrorHandler.rethrowError(error);
|
|
356
292
|
}
|
|
293
|
+
/** Ensures value is always an array */ ensureArray(value) {
|
|
294
|
+
return Array.isArray(value) ? value : [
|
|
295
|
+
value
|
|
296
|
+
];
|
|
297
|
+
}
|
|
298
|
+
/** Executes operation in transaction with automatic cache clearing */ async executeInTransaction(operation, fn) {
|
|
299
|
+
await this.ensureRepositoryInitialized();
|
|
300
|
+
const qr = this.repository.manager.connection.createQueryRunner();
|
|
301
|
+
await qr.connect();
|
|
302
|
+
await qr.startTransaction();
|
|
303
|
+
try {
|
|
304
|
+
const { saved, returnFirst } = await fn(qr);
|
|
305
|
+
await qr.commitTransaction();
|
|
306
|
+
const savedArray = this.ensureArray(saved);
|
|
307
|
+
if (this.isCacheable) {
|
|
308
|
+
await Promise.all([
|
|
309
|
+
this.clearCacheForAll(),
|
|
310
|
+
this.clearCacheForId(savedArray)
|
|
311
|
+
]);
|
|
312
|
+
}
|
|
313
|
+
if (returnFirst) {
|
|
314
|
+
return this.convertEntityToResponseDto(savedArray[0], false);
|
|
315
|
+
}
|
|
316
|
+
return savedArray.map((e)=>this.convertEntityToResponseDto(e, false));
|
|
317
|
+
} catch (error) {
|
|
318
|
+
await qr.rollbackTransaction();
|
|
319
|
+
this.handleError(error, operation);
|
|
320
|
+
} finally{
|
|
321
|
+
await qr.release();
|
|
322
|
+
}
|
|
323
|
+
}
|
|
357
324
|
// Hooks (override in child classes)
|
|
358
325
|
async ensureRepositoryInitialized() {}
|
|
359
326
|
async beforeInsertOperation(_dto, _user, _queryRunner) {}
|
package/cjs/classes/index.js
CHANGED
|
@@ -8,6 +8,7 @@ _export_star(require("./request-scoped-api.service"), exports);
|
|
|
8
8
|
_export_star(require("./hybrid-cache.class"), exports);
|
|
9
9
|
_export_star(require("./winston-logger-adapter.class"), exports);
|
|
10
10
|
_export_star(require("./winston.logger.class"), exports);
|
|
11
|
+
_export_star(require("../constants/permissions"), exports);
|
|
11
12
|
function _export_star(from, to) {
|
|
12
13
|
Object.keys(from).forEach(function(k) {
|
|
13
14
|
if (k !== "default" && !Object.prototype.hasOwnProperty.call(to, k)) {
|
|
@@ -47,46 +47,31 @@ function _define_property(obj, key, value) {
|
|
|
47
47
|
return meta;
|
|
48
48
|
}
|
|
49
49
|
let WinstonLoggerAdapter = class WinstonLoggerAdapter {
|
|
50
|
-
|
|
51
|
-
const meta = args
|
|
52
|
-
|
|
50
|
+
buildLogMeta(context, args, extra) {
|
|
51
|
+
const meta = args?.length && typeof args[0] === 'object' ? args[0] : {};
|
|
52
|
+
return {
|
|
53
53
|
context: context || this.context,
|
|
54
54
|
...getCorrelationMeta(),
|
|
55
|
-
...meta
|
|
56
|
-
|
|
55
|
+
...meta,
|
|
56
|
+
...extra
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
log(message, context, ...args) {
|
|
60
|
+
_winstonloggerclass.instance.info(message, this.buildLogMeta(context, args));
|
|
57
61
|
}
|
|
58
62
|
error(message, trace, context, ...args) {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
stack: trace,
|
|
63
|
-
...getCorrelationMeta(),
|
|
64
|
-
...meta
|
|
65
|
-
});
|
|
63
|
+
_winstonloggerclass.instance.error(message, this.buildLogMeta(context, args, {
|
|
64
|
+
stack: trace
|
|
65
|
+
}));
|
|
66
66
|
}
|
|
67
67
|
warn(message, context, ...args) {
|
|
68
|
-
|
|
69
|
-
_winstonloggerclass.instance.warn(message, {
|
|
70
|
-
context: context || this.context,
|
|
71
|
-
...getCorrelationMeta(),
|
|
72
|
-
...meta
|
|
73
|
-
});
|
|
68
|
+
_winstonloggerclass.instance.warn(message, this.buildLogMeta(context, args));
|
|
74
69
|
}
|
|
75
70
|
debug(message, context, ...args) {
|
|
76
|
-
|
|
77
|
-
_winstonloggerclass.instance.debug(message, {
|
|
78
|
-
context: context || this.context,
|
|
79
|
-
...getCorrelationMeta(),
|
|
80
|
-
...meta
|
|
81
|
-
});
|
|
71
|
+
_winstonloggerclass.instance.debug(message, this.buildLogMeta(context, args));
|
|
82
72
|
}
|
|
83
73
|
verbose(message, context, ...args) {
|
|
84
|
-
|
|
85
|
-
_winstonloggerclass.instance.verbose(message, {
|
|
86
|
-
context: context || this.context,
|
|
87
|
-
...getCorrelationMeta(),
|
|
88
|
-
...meta
|
|
89
|
-
});
|
|
74
|
+
_winstonloggerclass.instance.verbose(message, this.buildLogMeta(context, args));
|
|
90
75
|
}
|
|
91
76
|
constructor(context){
|
|
92
77
|
_define_property(this, "context", void 0);
|
|
@@ -94,25 +79,23 @@ let WinstonLoggerAdapter = class WinstonLoggerAdapter {
|
|
|
94
79
|
}
|
|
95
80
|
};
|
|
96
81
|
let NestLoggerAdapter = class NestLoggerAdapter {
|
|
82
|
+
formatMessage(message, args) {
|
|
83
|
+
return args?.length ? `${message} ${JSON.stringify(args)}` : message;
|
|
84
|
+
}
|
|
97
85
|
log(message, context, ...args) {
|
|
98
|
-
|
|
99
|
-
this.logger.log(logMessage, context);
|
|
86
|
+
this.logger.log(this.formatMessage(message, args), context);
|
|
100
87
|
}
|
|
101
88
|
error(message, trace, context, ...args) {
|
|
102
|
-
|
|
103
|
-
this.logger.error(logMessage, trace, context);
|
|
89
|
+
this.logger.error(this.formatMessage(message, args), trace, context);
|
|
104
90
|
}
|
|
105
91
|
warn(message, context, ...args) {
|
|
106
|
-
|
|
107
|
-
this.logger.warn(logMessage, context);
|
|
92
|
+
this.logger.warn(this.formatMessage(message, args), context);
|
|
108
93
|
}
|
|
109
94
|
debug(message, context, ...args) {
|
|
110
|
-
|
|
111
|
-
this.logger.debug(logMessage, context);
|
|
95
|
+
this.logger.debug(this.formatMessage(message, args), context);
|
|
112
96
|
}
|
|
113
97
|
verbose(message, context, ...args) {
|
|
114
|
-
|
|
115
|
-
this.logger.verbose(logMessage, context);
|
|
98
|
+
this.logger.verbose(this.formatMessage(message, args), context);
|
|
116
99
|
}
|
|
117
100
|
constructor(logger){
|
|
118
101
|
_define_property(this, "logger", void 0);
|
package/cjs/constants/index.js
CHANGED
|
@@ -41,6 +41,20 @@ _export(exports, {
|
|
|
41
41
|
return REQUEST_ID_HEADER;
|
|
42
42
|
}
|
|
43
43
|
});
|
|
44
|
+
_export_star(require("./permissions"), exports);
|
|
45
|
+
function _export_star(from, to) {
|
|
46
|
+
Object.keys(from).forEach(function(k) {
|
|
47
|
+
if (k !== "default" && !Object.prototype.hasOwnProperty.call(to, k)) {
|
|
48
|
+
Object.defineProperty(to, k, {
|
|
49
|
+
enumerable: true,
|
|
50
|
+
get: function() {
|
|
51
|
+
return from[k];
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
return from;
|
|
57
|
+
}
|
|
44
58
|
const IS_PUBLIC_KEY = 'isPublic';
|
|
45
59
|
const PERMISSIONS_KEY = 'permissions';
|
|
46
60
|
const CACHE_INSTANCE = 'CACHE_INSTANCE';
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Centralized Permission Codes
|
|
3
|
+
*
|
|
4
|
+
* Single source of truth for all permission codes used across the application.
|
|
5
|
+
* Use these constants instead of hardcoded strings to prevent typos and enable easy refactoring.
|
|
6
|
+
*
|
|
7
|
+
* Naming Convention: <entity>.<action>
|
|
8
|
+
* - entity: The resource being accessed (e.g., user, role, company)
|
|
9
|
+
* - action: The operation being performed (create, read, update, delete, assign)
|
|
10
|
+
*/ // ==================== AUTH MODULE ====================
|
|
11
|
+
"use strict";
|
|
12
|
+
Object.defineProperty(exports, "__esModule", {
|
|
13
|
+
value: true
|
|
14
|
+
});
|
|
15
|
+
function _export(target, all) {
|
|
16
|
+
for(var name in all)Object.defineProperty(target, name, {
|
|
17
|
+
enumerable: true,
|
|
18
|
+
get: Object.getOwnPropertyDescriptor(all, name).get
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
_export(exports, {
|
|
22
|
+
get ACTION_PERMISSIONS () {
|
|
23
|
+
return ACTION_PERMISSIONS;
|
|
24
|
+
},
|
|
25
|
+
get BRANCH_PERMISSIONS () {
|
|
26
|
+
return BRANCH_PERMISSIONS;
|
|
27
|
+
},
|
|
28
|
+
get COMPANY_ACTION_PERMISSIONS () {
|
|
29
|
+
return COMPANY_ACTION_PERMISSIONS;
|
|
30
|
+
},
|
|
31
|
+
get COMPANY_PERMISSIONS () {
|
|
32
|
+
return COMPANY_PERMISSIONS;
|
|
33
|
+
},
|
|
34
|
+
get EMAIL_CONFIG_PERMISSIONS () {
|
|
35
|
+
return EMAIL_CONFIG_PERMISSIONS;
|
|
36
|
+
},
|
|
37
|
+
get EMAIL_TEMPLATE_PERMISSIONS () {
|
|
38
|
+
return EMAIL_TEMPLATE_PERMISSIONS;
|
|
39
|
+
},
|
|
40
|
+
get FILE_PERMISSIONS () {
|
|
41
|
+
return FILE_PERMISSIONS;
|
|
42
|
+
},
|
|
43
|
+
get FOLDER_PERMISSIONS () {
|
|
44
|
+
return FOLDER_PERMISSIONS;
|
|
45
|
+
},
|
|
46
|
+
get FORM_PERMISSIONS () {
|
|
47
|
+
return FORM_PERMISSIONS;
|
|
48
|
+
},
|
|
49
|
+
get FORM_RESULT_PERMISSIONS () {
|
|
50
|
+
return FORM_RESULT_PERMISSIONS;
|
|
51
|
+
},
|
|
52
|
+
get PERMISSIONS () {
|
|
53
|
+
return PERMISSIONS;
|
|
54
|
+
},
|
|
55
|
+
get ROLE_ACTION_PERMISSIONS () {
|
|
56
|
+
return ROLE_ACTION_PERMISSIONS;
|
|
57
|
+
},
|
|
58
|
+
get ROLE_PERMISSIONS () {
|
|
59
|
+
return ROLE_PERMISSIONS;
|
|
60
|
+
},
|
|
61
|
+
get STORAGE_CONFIG_PERMISSIONS () {
|
|
62
|
+
return STORAGE_CONFIG_PERMISSIONS;
|
|
63
|
+
},
|
|
64
|
+
get USER_ACTION_PERMISSIONS () {
|
|
65
|
+
return USER_ACTION_PERMISSIONS;
|
|
66
|
+
},
|
|
67
|
+
get USER_PERMISSIONS () {
|
|
68
|
+
return USER_PERMISSIONS;
|
|
69
|
+
},
|
|
70
|
+
get USER_ROLE_PERMISSIONS () {
|
|
71
|
+
return USER_ROLE_PERMISSIONS;
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
const USER_PERMISSIONS = {
|
|
75
|
+
CREATE: 'user.create',
|
|
76
|
+
READ: 'user.read',
|
|
77
|
+
UPDATE: 'user.update',
|
|
78
|
+
DELETE: 'user.delete'
|
|
79
|
+
};
|
|
80
|
+
const COMPANY_PERMISSIONS = {
|
|
81
|
+
CREATE: 'company.create',
|
|
82
|
+
READ: 'company.read',
|
|
83
|
+
UPDATE: 'company.update',
|
|
84
|
+
DELETE: 'company.delete'
|
|
85
|
+
};
|
|
86
|
+
const BRANCH_PERMISSIONS = {
|
|
87
|
+
CREATE: 'branch.create',
|
|
88
|
+
READ: 'branch.read',
|
|
89
|
+
UPDATE: 'branch.update',
|
|
90
|
+
DELETE: 'branch.delete'
|
|
91
|
+
};
|
|
92
|
+
const ACTION_PERMISSIONS = {
|
|
93
|
+
CREATE: 'action.create',
|
|
94
|
+
READ: 'action.read',
|
|
95
|
+
UPDATE: 'action.update',
|
|
96
|
+
DELETE: 'action.delete'
|
|
97
|
+
};
|
|
98
|
+
const ROLE_PERMISSIONS = {
|
|
99
|
+
CREATE: 'role.create',
|
|
100
|
+
READ: 'role.read',
|
|
101
|
+
UPDATE: 'role.update',
|
|
102
|
+
DELETE: 'role.delete'
|
|
103
|
+
};
|
|
104
|
+
const ROLE_ACTION_PERMISSIONS = {
|
|
105
|
+
READ: 'role-action.read',
|
|
106
|
+
ASSIGN: 'role-action.assign'
|
|
107
|
+
};
|
|
108
|
+
const USER_ROLE_PERMISSIONS = {
|
|
109
|
+
READ: 'user-role.read',
|
|
110
|
+
ASSIGN: 'user-role.assign'
|
|
111
|
+
};
|
|
112
|
+
const USER_ACTION_PERMISSIONS = {
|
|
113
|
+
READ: 'user-action.read',
|
|
114
|
+
ASSIGN: 'user-action.assign'
|
|
115
|
+
};
|
|
116
|
+
const COMPANY_ACTION_PERMISSIONS = {
|
|
117
|
+
READ: 'company-action.read',
|
|
118
|
+
ASSIGN: 'company-action.assign'
|
|
119
|
+
};
|
|
120
|
+
const FILE_PERMISSIONS = {
|
|
121
|
+
CREATE: 'file.create',
|
|
122
|
+
READ: 'file.read',
|
|
123
|
+
UPDATE: 'file.update',
|
|
124
|
+
DELETE: 'file.delete'
|
|
125
|
+
};
|
|
126
|
+
const FOLDER_PERMISSIONS = {
|
|
127
|
+
CREATE: 'folder.create',
|
|
128
|
+
READ: 'folder.read',
|
|
129
|
+
UPDATE: 'folder.update',
|
|
130
|
+
DELETE: 'folder.delete'
|
|
131
|
+
};
|
|
132
|
+
const STORAGE_CONFIG_PERMISSIONS = {
|
|
133
|
+
CREATE: 'storage-config.create',
|
|
134
|
+
READ: 'storage-config.read',
|
|
135
|
+
UPDATE: 'storage-config.update',
|
|
136
|
+
DELETE: 'storage-config.delete'
|
|
137
|
+
};
|
|
138
|
+
const EMAIL_CONFIG_PERMISSIONS = {
|
|
139
|
+
CREATE: 'email-config.create',
|
|
140
|
+
READ: 'email-config.read',
|
|
141
|
+
UPDATE: 'email-config.update',
|
|
142
|
+
DELETE: 'email-config.delete'
|
|
143
|
+
};
|
|
144
|
+
const EMAIL_TEMPLATE_PERMISSIONS = {
|
|
145
|
+
CREATE: 'email-template.create',
|
|
146
|
+
READ: 'email-template.read',
|
|
147
|
+
UPDATE: 'email-template.update',
|
|
148
|
+
DELETE: 'email-template.delete'
|
|
149
|
+
};
|
|
150
|
+
const FORM_PERMISSIONS = {
|
|
151
|
+
CREATE: 'form.create',
|
|
152
|
+
READ: 'form.read',
|
|
153
|
+
UPDATE: 'form.update',
|
|
154
|
+
DELETE: 'form.delete'
|
|
155
|
+
};
|
|
156
|
+
const FORM_RESULT_PERMISSIONS = {
|
|
157
|
+
CREATE: 'form-result.create',
|
|
158
|
+
READ: 'form-result.read',
|
|
159
|
+
UPDATE: 'form-result.update',
|
|
160
|
+
DELETE: 'form-result.delete'
|
|
161
|
+
};
|
|
162
|
+
const PERMISSIONS = {
|
|
163
|
+
// Auth
|
|
164
|
+
USER: USER_PERMISSIONS,
|
|
165
|
+
COMPANY: COMPANY_PERMISSIONS,
|
|
166
|
+
BRANCH: BRANCH_PERMISSIONS,
|
|
167
|
+
// IAM
|
|
168
|
+
ACTION: ACTION_PERMISSIONS,
|
|
169
|
+
ROLE: ROLE_PERMISSIONS,
|
|
170
|
+
ROLE_ACTION: ROLE_ACTION_PERMISSIONS,
|
|
171
|
+
USER_ROLE: USER_ROLE_PERMISSIONS,
|
|
172
|
+
USER_ACTION: USER_ACTION_PERMISSIONS,
|
|
173
|
+
COMPANY_ACTION: COMPANY_ACTION_PERMISSIONS,
|
|
174
|
+
// Storage
|
|
175
|
+
FILE: FILE_PERMISSIONS,
|
|
176
|
+
FOLDER: FOLDER_PERMISSIONS,
|
|
177
|
+
STORAGE_CONFIG: STORAGE_CONFIG_PERMISSIONS,
|
|
178
|
+
// Email
|
|
179
|
+
EMAIL_CONFIG: EMAIL_CONFIG_PERMISSIONS,
|
|
180
|
+
EMAIL_TEMPLATE: EMAIL_TEMPLATE_PERMISSIONS,
|
|
181
|
+
// Form Builder
|
|
182
|
+
FORM: FORM_PERMISSIONS,
|
|
183
|
+
FORM_RESULT: FORM_RESULT_PERMISSIONS
|
|
184
|
+
};
|
|
@@ -8,7 +8,7 @@ Object.defineProperty(exports, "ApiResponseDto", {
|
|
|
8
8
|
return ApiResponseDto;
|
|
9
9
|
}
|
|
10
10
|
});
|
|
11
|
-
const _dtos = require("
|
|
11
|
+
const _dtos = require("../dtos");
|
|
12
12
|
const _common = require("@nestjs/common");
|
|
13
13
|
const _swagger = require("@nestjs/swagger");
|
|
14
14
|
const ApiResponseDto = (dto, isArray = false, arrayType = 'list')=>{
|
package/cjs/decorators/index.js
CHANGED
|
@@ -6,6 +6,7 @@ _export_star(require("./api-response.decorator"), exports);
|
|
|
6
6
|
_export_star(require("./current-user.decorator"), exports);
|
|
7
7
|
_export_star(require("./public.decorator"), exports);
|
|
8
8
|
_export_star(require("./require-permission.decorator"), exports);
|
|
9
|
+
_export_star(require("./sanitize-html.decorator"), exports);
|
|
9
10
|
function _export_star(from, to) {
|
|
10
11
|
Object.keys(from).forEach(function(k) {
|
|
11
12
|
if (k !== "default" && !Object.prototype.hasOwnProperty.call(to, k)) {
|
|
@@ -0,0 +1,36 @@
|
|
|
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 SanitizeAndTrim () {
|
|
13
|
+
return SanitizeAndTrim;
|
|
14
|
+
},
|
|
15
|
+
get SanitizeHtml () {
|
|
16
|
+
return SanitizeHtml;
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
const _classtransformer = require("class-transformer");
|
|
20
|
+
const _htmlsanitizerutil = require("../utils/html-sanitizer.util");
|
|
21
|
+
function SanitizeHtml() {
|
|
22
|
+
return (0, _classtransformer.Transform)(({ value })=>{
|
|
23
|
+
if (typeof value === 'string') {
|
|
24
|
+
return (0, _htmlsanitizerutil.escapeHtml)(value);
|
|
25
|
+
}
|
|
26
|
+
return value;
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
function SanitizeAndTrim() {
|
|
30
|
+
return (0, _classtransformer.Transform)(({ value })=>{
|
|
31
|
+
if (typeof value === 'string') {
|
|
32
|
+
return (0, _htmlsanitizerutil.escapeHtml)(value.trim());
|
|
33
|
+
}
|
|
34
|
+
return value;
|
|
35
|
+
});
|
|
36
|
+
}
|
package/cjs/dtos/delete.dto.js
CHANGED
|
@@ -36,6 +36,7 @@ let DeleteDto = class DeleteDto {
|
|
|
36
36
|
constructor(){
|
|
37
37
|
_define_property(this, "id", void 0);
|
|
38
38
|
_define_property(this, "type", void 0);
|
|
39
|
+
_define_property(this, "deletedById", void 0);
|
|
39
40
|
}
|
|
40
41
|
};
|
|
41
42
|
_ts_decorate([
|
|
@@ -80,3 +81,12 @@ _ts_decorate([
|
|
|
80
81
|
]),
|
|
81
82
|
_ts_metadata("design:type", String)
|
|
82
83
|
], DeleteDto.prototype, "type", void 0);
|
|
84
|
+
_ts_decorate([
|
|
85
|
+
(0, _swagger.ApiPropertyOptional)({
|
|
86
|
+
description: 'User ID who initiated the deletion (auto-set by interceptor)',
|
|
87
|
+
example: 'f2e9c8d0-7a2a-11eb-9439-0242ac130002'
|
|
88
|
+
}),
|
|
89
|
+
(0, _classvalidator.IsOptional)(),
|
|
90
|
+
(0, _classvalidator.IsUUID)(),
|
|
91
|
+
_ts_metadata("design:type", String)
|
|
92
|
+
], DeleteDto.prototype, "deletedById", void 0);
|