@devstroupe/devkit-nest 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/audit/audit.context.d.ts +9 -0
- package/dist/audit/audit.context.js +5 -0
- package/dist/audit/audit.interceptor.d.ts +5 -0
- package/dist/audit/audit.interceptor.js +81 -0
- package/dist/audit/audit.module.d.ts +2 -0
- package/dist/audit/audit.module.js +29 -0
- package/dist/audit/audit.subscriber.d.ts +14 -0
- package/dist/audit/audit.subscriber.js +129 -0
- package/dist/audit/index.d.ts +4 -0
- package/dist/audit/index.js +20 -0
- package/dist/auth/index.d.ts +2 -0
- package/dist/auth/index.js +18 -0
- package/dist/auth/permissions.decorator.d.ts +2 -0
- package/dist/auth/permissions.decorator.js +7 -0
- package/dist/auth/permissions.guard.d.ts +7 -0
- package/dist/auth/permissions.guard.js +46 -0
- package/dist/auth/permissions.guard.test.d.ts +1 -0
- package/dist/auth/permissions.guard.test.js +100 -0
- package/dist/http/base-crud.controller.d.ts +2 -0
- package/dist/http/base-crud.controller.js +24 -3
- package/dist/index.d.ts +4 -0
- package/dist/index.js +4 -0
- package/dist/realtime/index.d.ts +3 -0
- package/dist/realtime/index.js +19 -0
- package/dist/realtime/realtime.gateway.d.ts +14 -0
- package/dist/realtime/realtime.gateway.js +134 -0
- package/dist/realtime/realtime.module.d.ts +2 -0
- package/dist/realtime/realtime.module.js +22 -0
- package/dist/realtime/realtime.service.d.ts +10 -0
- package/dist/realtime/realtime.service.js +32 -0
- package/dist/storage/drivers/local.storage.d.ts +11 -0
- package/dist/storage/drivers/local.storage.js +114 -0
- package/dist/storage/drivers/local.storage.test.d.ts +1 -0
- package/dist/storage/drivers/local.storage.test.js +106 -0
- package/dist/storage/drivers/s3.storage.d.ts +12 -0
- package/dist/storage/drivers/s3.storage.js +138 -0
- package/dist/storage/index.d.ts +5 -0
- package/dist/storage/index.js +21 -0
- package/dist/storage/storage.module.d.ts +11 -0
- package/dist/storage/storage.module.js +81 -0
- package/dist/storage/storage.module.test.d.ts +1 -0
- package/dist/storage/storage.module.test.js +113 -0
- package/dist/storage/storage.service.d.ts +7 -0
- package/dist/storage/storage.service.js +6 -0
- package/dist/storage/storage.types.d.ts +42 -0
- package/dist/storage/storage.types.js +2 -0
- package/package.json +12 -2
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { AsyncLocalStorage } from 'async_hooks';
|
|
2
|
+
export interface AuditRequestContext {
|
|
3
|
+
userId?: string | number;
|
|
4
|
+
ip?: string;
|
|
5
|
+
userAgent?: string;
|
|
6
|
+
correlationId?: string;
|
|
7
|
+
timestamp: Date;
|
|
8
|
+
}
|
|
9
|
+
export declare const auditLocalStorage: AsyncLocalStorage<AuditRequestContext>;
|
|
@@ -0,0 +1,81 @@
|
|
|
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 __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
19
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
20
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
21
|
+
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;
|
|
22
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
23
|
+
};
|
|
24
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
25
|
+
var ownKeys = function(o) {
|
|
26
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
27
|
+
var ar = [];
|
|
28
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
29
|
+
return ar;
|
|
30
|
+
};
|
|
31
|
+
return ownKeys(o);
|
|
32
|
+
};
|
|
33
|
+
return function (mod) {
|
|
34
|
+
if (mod && mod.__esModule) return mod;
|
|
35
|
+
var result = {};
|
|
36
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
37
|
+
__setModuleDefault(result, mod);
|
|
38
|
+
return result;
|
|
39
|
+
};
|
|
40
|
+
})();
|
|
41
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
+
exports.AuditInterceptor = void 0;
|
|
43
|
+
const common_1 = require("@nestjs/common");
|
|
44
|
+
const rxjs_1 = require("rxjs");
|
|
45
|
+
const audit_context_1 = require("./audit.context");
|
|
46
|
+
const crypto = __importStar(require("crypto"));
|
|
47
|
+
let AuditInterceptor = class AuditInterceptor {
|
|
48
|
+
intercept(context, next) {
|
|
49
|
+
const http = context.switchToHttp();
|
|
50
|
+
const req = http.getRequest();
|
|
51
|
+
if (!req) {
|
|
52
|
+
return next.handle();
|
|
53
|
+
}
|
|
54
|
+
const correlationId = req.headers['x-correlation-id'] || crypto.randomUUID();
|
|
55
|
+
const ip = req.ip || req.headers['x-forwarded-for'] || req.socket.remoteAddress;
|
|
56
|
+
const userAgent = req.headers['user-agent'];
|
|
57
|
+
// O usuário é extraído do JWT que o AuthGuard decodificou e salvou no request.user
|
|
58
|
+
const userId = req.user?.sub || req.user?.id || undefined;
|
|
59
|
+
const auditContext = {
|
|
60
|
+
userId,
|
|
61
|
+
ip,
|
|
62
|
+
userAgent,
|
|
63
|
+
correlationId,
|
|
64
|
+
timestamp: new Date(),
|
|
65
|
+
};
|
|
66
|
+
// Executa a requisição dentro do escopo do AsyncLocalStorage
|
|
67
|
+
return new rxjs_1.Observable((subscriber) => {
|
|
68
|
+
audit_context_1.auditLocalStorage.run(auditContext, () => {
|
|
69
|
+
next.handle().subscribe({
|
|
70
|
+
next: (val) => subscriber.next(val),
|
|
71
|
+
error: (err) => subscriber.error(err),
|
|
72
|
+
complete: () => subscriber.complete(),
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
exports.AuditInterceptor = AuditInterceptor;
|
|
79
|
+
exports.AuditInterceptor = AuditInterceptor = __decorate([
|
|
80
|
+
(0, common_1.Injectable)()
|
|
81
|
+
], AuditInterceptor);
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
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
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.AuditModule = void 0;
|
|
10
|
+
const common_1 = require("@nestjs/common");
|
|
11
|
+
const core_1 = require("@nestjs/core");
|
|
12
|
+
const audit_interceptor_1 = require("./audit.interceptor");
|
|
13
|
+
const audit_subscriber_1 = require("./audit.subscriber");
|
|
14
|
+
let AuditModule = class AuditModule {
|
|
15
|
+
};
|
|
16
|
+
exports.AuditModule = AuditModule;
|
|
17
|
+
exports.AuditModule = AuditModule = __decorate([
|
|
18
|
+
(0, common_1.Global)(),
|
|
19
|
+
(0, common_1.Module)({
|
|
20
|
+
providers: [
|
|
21
|
+
audit_subscriber_1.AuditSubscriber,
|
|
22
|
+
{
|
|
23
|
+
provide: core_1.APP_INTERCEPTOR,
|
|
24
|
+
useClass: audit_interceptor_1.AuditInterceptor,
|
|
25
|
+
},
|
|
26
|
+
],
|
|
27
|
+
exports: [],
|
|
28
|
+
})
|
|
29
|
+
], AuditModule);
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { EntitySubscriberInterface, InsertEvent, UpdateEvent, RemoveEvent, DataSource } from 'typeorm';
|
|
2
|
+
export declare class AuditSubscriber implements EntitySubscriberInterface {
|
|
3
|
+
private readonly logger;
|
|
4
|
+
constructor(dataSource: DataSource);
|
|
5
|
+
private redact;
|
|
6
|
+
private getDiff;
|
|
7
|
+
private getEntityId;
|
|
8
|
+
beforeInsert(event: InsertEvent<any>): void;
|
|
9
|
+
beforeUpdate(event: UpdateEvent<any>): void;
|
|
10
|
+
afterInsert(event: InsertEvent<any>): void;
|
|
11
|
+
afterUpdate(event: UpdateEvent<any>): void;
|
|
12
|
+
afterRemove(event: RemoveEvent<any>): void;
|
|
13
|
+
private processEvent;
|
|
14
|
+
}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
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
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
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
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.AuditSubscriber = void 0;
|
|
13
|
+
const typeorm_1 = require("typeorm");
|
|
14
|
+
const audit_context_1 = require("./audit.context");
|
|
15
|
+
const common_1 = require("@nestjs/common");
|
|
16
|
+
const DEFAULT_REDACT_FIELDS = [
|
|
17
|
+
'password',
|
|
18
|
+
'token',
|
|
19
|
+
'secret',
|
|
20
|
+
'secretaccesskey',
|
|
21
|
+
'accesskey',
|
|
22
|
+
'passwordhash',
|
|
23
|
+
'current_refresh_token',
|
|
24
|
+
'currentrefreshtoken',
|
|
25
|
+
'creditcard',
|
|
26
|
+
'cvv',
|
|
27
|
+
];
|
|
28
|
+
let AuditSubscriber = class AuditSubscriber {
|
|
29
|
+
logger = new common_1.Logger('AuditSystem');
|
|
30
|
+
constructor(dataSource) {
|
|
31
|
+
dataSource.subscribers.push(this);
|
|
32
|
+
}
|
|
33
|
+
redact(data) {
|
|
34
|
+
if (!data || typeof data !== 'object')
|
|
35
|
+
return data;
|
|
36
|
+
const copy = Array.isArray(data) ? [...data] : { ...data };
|
|
37
|
+
for (const key of Object.keys(copy)) {
|
|
38
|
+
const lowerKey = key.toLowerCase();
|
|
39
|
+
if (DEFAULT_REDACT_FIELDS.includes(lowerKey)) {
|
|
40
|
+
copy[key] = '******';
|
|
41
|
+
}
|
|
42
|
+
else if (typeof copy[key] === 'object' && copy[key] !== null) {
|
|
43
|
+
copy[key] = this.redact(copy[key]);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return copy;
|
|
47
|
+
}
|
|
48
|
+
getDiff(before, after) {
|
|
49
|
+
const oldValues = {};
|
|
50
|
+
const newValues = {};
|
|
51
|
+
if (!before || !after) {
|
|
52
|
+
return { oldValues: before, newValues: after };
|
|
53
|
+
}
|
|
54
|
+
for (const key of Object.keys(after)) {
|
|
55
|
+
if (key === 'updatedAt' || key === 'createdAt')
|
|
56
|
+
continue;
|
|
57
|
+
const valBefore = before[key];
|
|
58
|
+
const valAfter = after[key];
|
|
59
|
+
// Comparação simples para detectar mudanças
|
|
60
|
+
if (JSON.stringify(valBefore) !== JSON.stringify(valAfter)) {
|
|
61
|
+
oldValues[key] = valBefore;
|
|
62
|
+
newValues[key] = valAfter;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return { oldValues, newValues };
|
|
66
|
+
}
|
|
67
|
+
getEntityId(event) {
|
|
68
|
+
return event.entityId || event.entity?.id || event.databaseEntity?.id;
|
|
69
|
+
}
|
|
70
|
+
beforeInsert(event) {
|
|
71
|
+
const store = audit_context_1.auditLocalStorage.getStore();
|
|
72
|
+
if (store && store.userId && event.entity) {
|
|
73
|
+
if ('createdByUserId' in event.entity) {
|
|
74
|
+
event.entity.createdByUserId = store.userId;
|
|
75
|
+
}
|
|
76
|
+
if ('updatedByUserId' in event.entity) {
|
|
77
|
+
event.entity.updatedByUserId = store.userId;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
beforeUpdate(event) {
|
|
82
|
+
const store = audit_context_1.auditLocalStorage.getStore();
|
|
83
|
+
if (store && store.userId && event.entity) {
|
|
84
|
+
if ('updatedByUserId' in event.entity) {
|
|
85
|
+
event.entity.updatedByUserId = store.userId;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
afterInsert(event) {
|
|
90
|
+
this.processEvent('CREATE', event.metadata.tableName, this.getEntityId(event), null, event.entity);
|
|
91
|
+
}
|
|
92
|
+
afterUpdate(event) {
|
|
93
|
+
if (!event.databaseEntity || !event.entity)
|
|
94
|
+
return;
|
|
95
|
+
const { oldValues, newValues } = this.getDiff(event.databaseEntity, event.entity);
|
|
96
|
+
// Só registra se de fato mudou algo além de updatedAt/createdAt
|
|
97
|
+
if (Object.keys(newValues).length > 0) {
|
|
98
|
+
this.processEvent('UPDATE', event.metadata.tableName, this.getEntityId(event), oldValues, newValues);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
afterRemove(event) {
|
|
102
|
+
this.processEvent('DELETE', event.metadata.tableName, this.getEntityId(event), event.databaseEntity, null);
|
|
103
|
+
}
|
|
104
|
+
processEvent(action, entity, id, before, after) {
|
|
105
|
+
const store = audit_context_1.auditLocalStorage.getStore();
|
|
106
|
+
if (!store)
|
|
107
|
+
return; // Se a alteração ocorreu fora de uma requisição HTTP (ex: seeds, scripts), não auditamos por este canal
|
|
108
|
+
const logPayload = {
|
|
109
|
+
action,
|
|
110
|
+
entity,
|
|
111
|
+
entityId: id,
|
|
112
|
+
before: this.redact(before),
|
|
113
|
+
after: this.redact(after),
|
|
114
|
+
userId: store.userId,
|
|
115
|
+
ip: store.ip,
|
|
116
|
+
userAgent: store.userAgent,
|
|
117
|
+
correlationId: store.correlationId,
|
|
118
|
+
timestamp: store.timestamp,
|
|
119
|
+
};
|
|
120
|
+
// Imprimir o log de auditoria no formato JSON estruturado no console
|
|
121
|
+
this.logger.log(`[AUDIT] ${JSON.stringify(logPayload)}`);
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
exports.AuditSubscriber = AuditSubscriber;
|
|
125
|
+
exports.AuditSubscriber = AuditSubscriber = __decorate([
|
|
126
|
+
(0, typeorm_1.EventSubscriber)(),
|
|
127
|
+
(0, common_1.Injectable)(),
|
|
128
|
+
__metadata("design:paramtypes", [typeorm_1.DataSource])
|
|
129
|
+
], AuditSubscriber);
|
|
@@ -0,0 +1,20 @@
|
|
|
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("./audit.module"), exports);
|
|
18
|
+
__exportStar(require("./audit.interceptor"), exports);
|
|
19
|
+
__exportStar(require("./audit.subscriber"), exports);
|
|
20
|
+
__exportStar(require("./audit.context"), exports);
|
|
@@ -0,0 +1,18 @@
|
|
|
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("./permissions.decorator"), exports);
|
|
18
|
+
__exportStar(require("./permissions.guard"), exports);
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Permissions = exports.PERMISSIONS_KEY = void 0;
|
|
4
|
+
const common_1 = require("@nestjs/common");
|
|
5
|
+
exports.PERMISSIONS_KEY = 'devkit-permissions';
|
|
6
|
+
const Permissions = (...permissions) => (0, common_1.SetMetadata)(exports.PERMISSIONS_KEY, permissions);
|
|
7
|
+
exports.Permissions = Permissions;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { CanActivate, ExecutionContext } from '@nestjs/common';
|
|
2
|
+
import { Reflector } from '@nestjs/core';
|
|
3
|
+
export declare class PermissionsGuard implements CanActivate {
|
|
4
|
+
private reflector;
|
|
5
|
+
constructor(reflector: Reflector);
|
|
6
|
+
canActivate(context: ExecutionContext): boolean;
|
|
7
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
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
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
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
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.PermissionsGuard = void 0;
|
|
13
|
+
const common_1 = require("@nestjs/common");
|
|
14
|
+
const core_1 = require("@nestjs/core");
|
|
15
|
+
const permissions_decorator_1 = require("./permissions.decorator");
|
|
16
|
+
let PermissionsGuard = class PermissionsGuard {
|
|
17
|
+
reflector;
|
|
18
|
+
constructor(reflector) {
|
|
19
|
+
this.reflector = reflector;
|
|
20
|
+
}
|
|
21
|
+
canActivate(context) {
|
|
22
|
+
const requiredPermissions = this.reflector.getAllAndOverride(permissions_decorator_1.PERMISSIONS_KEY, [
|
|
23
|
+
context.getHandler(),
|
|
24
|
+
context.getClass(),
|
|
25
|
+
]);
|
|
26
|
+
if (!requiredPermissions || requiredPermissions.length === 0) {
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
const request = context.switchToHttp().getRequest();
|
|
30
|
+
const user = request.user;
|
|
31
|
+
if (!user) {
|
|
32
|
+
return false; // Bloqueia acesso caso não esteja autenticado
|
|
33
|
+
}
|
|
34
|
+
// Atalho para super admin
|
|
35
|
+
if (user.role === 'ADMIN') {
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
const userPermissions = user.permissions || [];
|
|
39
|
+
return requiredPermissions.every((permission) => userPermissions.includes(permission));
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
exports.PermissionsGuard = PermissionsGuard;
|
|
43
|
+
exports.PermissionsGuard = PermissionsGuard = __decorate([
|
|
44
|
+
(0, common_1.Injectable)(),
|
|
45
|
+
__metadata("design:paramtypes", [core_1.Reflector])
|
|
46
|
+
], PermissionsGuard);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,100 @@
|
|
|
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 __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
const node_test_1 = require("node:test");
|
|
37
|
+
const assert = __importStar(require("node:assert"));
|
|
38
|
+
const permissions_guard_1 = require("./permissions.guard");
|
|
39
|
+
(0, node_test_1.describe)('PermissionsGuard', () => {
|
|
40
|
+
const createMockContext = (user) => {
|
|
41
|
+
return {
|
|
42
|
+
switchToHttp: () => ({
|
|
43
|
+
getRequest: () => ({ user }),
|
|
44
|
+
}),
|
|
45
|
+
getHandler: () => ({}),
|
|
46
|
+
getClass: () => ({}),
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
(0, node_test_1.test)('deve permitir acesso se não houver permissões exigidas', () => {
|
|
50
|
+
const mockReflector = {
|
|
51
|
+
getAllAndOverride: () => undefined,
|
|
52
|
+
};
|
|
53
|
+
const guard = new permissions_guard_1.PermissionsGuard(mockReflector);
|
|
54
|
+
const context = createMockContext({ role: 'USER', permissions: [] });
|
|
55
|
+
const result = guard.canActivate(context);
|
|
56
|
+
assert.strictEqual(result, true);
|
|
57
|
+
});
|
|
58
|
+
(0, node_test_1.test)('deve permitir acesso se o usuário for ADMIN (super admin)', () => {
|
|
59
|
+
const mockReflector = {
|
|
60
|
+
getAllAndOverride: () => ['create:cabin'],
|
|
61
|
+
};
|
|
62
|
+
const guard = new permissions_guard_1.PermissionsGuard(mockReflector);
|
|
63
|
+
const context = createMockContext({ role: 'ADMIN', permissions: [] });
|
|
64
|
+
const result = guard.canActivate(context);
|
|
65
|
+
assert.strictEqual(result, true);
|
|
66
|
+
});
|
|
67
|
+
(0, node_test_1.test)('deve permitir acesso se o usuário tiver todas as permissões exigidas', () => {
|
|
68
|
+
const mockReflector = {
|
|
69
|
+
getAllAndOverride: () => ['read:cabin', 'update:cabin'],
|
|
70
|
+
};
|
|
71
|
+
const guard = new permissions_guard_1.PermissionsGuard(mockReflector);
|
|
72
|
+
const context = createMockContext({
|
|
73
|
+
role: 'USER',
|
|
74
|
+
permissions: ['read:cabin', 'update:cabin', 'delete:cabin'],
|
|
75
|
+
});
|
|
76
|
+
const result = guard.canActivate(context);
|
|
77
|
+
assert.strictEqual(result, true);
|
|
78
|
+
});
|
|
79
|
+
(0, node_test_1.test)('deve negar acesso se o usuário não tiver todas as permissões exigidas', () => {
|
|
80
|
+
const mockReflector = {
|
|
81
|
+
getAllAndOverride: () => ['read:cabin', 'update:cabin'],
|
|
82
|
+
};
|
|
83
|
+
const guard = new permissions_guard_1.PermissionsGuard(mockReflector);
|
|
84
|
+
const context = createMockContext({
|
|
85
|
+
role: 'USER',
|
|
86
|
+
permissions: ['read:cabin'], // Falta 'update:cabin'
|
|
87
|
+
});
|
|
88
|
+
const result = guard.canActivate(context);
|
|
89
|
+
assert.strictEqual(result, false);
|
|
90
|
+
});
|
|
91
|
+
(0, node_test_1.test)('deve negar acesso se não houver usuário autenticado na request', () => {
|
|
92
|
+
const mockReflector = {
|
|
93
|
+
getAllAndOverride: () => ['read:cabin'],
|
|
94
|
+
};
|
|
95
|
+
const guard = new permissions_guard_1.PermissionsGuard(mockReflector);
|
|
96
|
+
const context = createMockContext(undefined);
|
|
97
|
+
const result = guard.canActivate(context);
|
|
98
|
+
assert.strictEqual(result, false);
|
|
99
|
+
});
|
|
100
|
+
});
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import { RealtimeService } from '../realtime/realtime.service';
|
|
1
2
|
export declare abstract class BaseCrudController<Entity, FilterDto = any> {
|
|
2
3
|
protected readonly service: any;
|
|
3
4
|
constructor(service: any);
|
|
5
|
+
protected readonly realtimeService?: RealtimeService;
|
|
4
6
|
create(body: any): Promise<Entity>;
|
|
5
7
|
update(id: string, body: any): Promise<Entity>;
|
|
6
8
|
findMany(filter: FilterDto): Promise<any>;
|
|
@@ -15,16 +15,28 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
15
15
|
exports.BaseCrudController = void 0;
|
|
16
16
|
const common_1 = require("@nestjs/common");
|
|
17
17
|
const swagger_1 = require("@nestjs/swagger");
|
|
18
|
+
const realtime_service_1 = require("../realtime/realtime.service");
|
|
18
19
|
class BaseCrudController {
|
|
19
20
|
service;
|
|
20
21
|
constructor(service) {
|
|
21
22
|
this.service = service;
|
|
22
23
|
}
|
|
24
|
+
realtimeService;
|
|
23
25
|
async create(body) {
|
|
24
|
-
|
|
26
|
+
const result = await this.service.create(body);
|
|
27
|
+
if (this.realtimeService) {
|
|
28
|
+
const entityName = this.constructor.name.replace('Controller', '').replace('MsController', '').toLowerCase();
|
|
29
|
+
this.realtimeService.publishEntityChange(entityName, 'create', result, result.tenantId);
|
|
30
|
+
}
|
|
31
|
+
return result;
|
|
25
32
|
}
|
|
26
33
|
async update(id, body) {
|
|
27
|
-
|
|
34
|
+
const result = await this.service.update(+id, body);
|
|
35
|
+
if (this.realtimeService) {
|
|
36
|
+
const entityName = this.constructor.name.replace('Controller', '').replace('MsController', '').toLowerCase();
|
|
37
|
+
this.realtimeService.publishEntityChange(entityName, 'update', result, result.tenantId);
|
|
38
|
+
}
|
|
39
|
+
return result;
|
|
28
40
|
}
|
|
29
41
|
async findMany(filter) {
|
|
30
42
|
return await this.service.findMany(filter);
|
|
@@ -33,10 +45,19 @@ class BaseCrudController {
|
|
|
33
45
|
return await this.service.findOne(+id);
|
|
34
46
|
}
|
|
35
47
|
async delete(id) {
|
|
36
|
-
|
|
48
|
+
await this.service.delete(+id);
|
|
49
|
+
if (this.realtimeService) {
|
|
50
|
+
const entityName = this.constructor.name.replace('Controller', '').replace('MsController', '').toLowerCase();
|
|
51
|
+
this.realtimeService.publishEntityChange(entityName, 'delete', { id: +id });
|
|
52
|
+
}
|
|
37
53
|
}
|
|
38
54
|
}
|
|
39
55
|
exports.BaseCrudController = BaseCrudController;
|
|
56
|
+
__decorate([
|
|
57
|
+
(0, common_1.Inject)(realtime_service_1.RealtimeService),
|
|
58
|
+
(0, common_1.Optional)(),
|
|
59
|
+
__metadata("design:type", realtime_service_1.RealtimeService)
|
|
60
|
+
], BaseCrudController.prototype, "realtimeService", void 0);
|
|
40
61
|
__decorate([
|
|
41
62
|
(0, common_1.Post)(),
|
|
42
63
|
(0, swagger_1.ApiOperation)({ summary: 'Create entity' }),
|
package/dist/index.d.ts
CHANGED
|
@@ -2,3 +2,7 @@ export * from './database/factory-where';
|
|
|
2
2
|
export * from './database/base.repository';
|
|
3
3
|
export * from './database/typeorm-query.builder';
|
|
4
4
|
export * from './http/base-crud.controller';
|
|
5
|
+
export * from './storage';
|
|
6
|
+
export * from './auth';
|
|
7
|
+
export * from './realtime';
|
|
8
|
+
export * from './audit';
|
package/dist/index.js
CHANGED
|
@@ -18,3 +18,7 @@ __exportStar(require("./database/factory-where"), exports);
|
|
|
18
18
|
__exportStar(require("./database/base.repository"), exports);
|
|
19
19
|
__exportStar(require("./database/typeorm-query.builder"), exports);
|
|
20
20
|
__exportStar(require("./http/base-crud.controller"), exports);
|
|
21
|
+
__exportStar(require("./storage"), exports);
|
|
22
|
+
__exportStar(require("./auth"), exports);
|
|
23
|
+
__exportStar(require("./realtime"), exports);
|
|
24
|
+
__exportStar(require("./audit"), exports);
|
|
@@ -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("./realtime.module"), exports);
|
|
18
|
+
__exportStar(require("./realtime.service"), exports);
|
|
19
|
+
__exportStar(require("./realtime.gateway"), exports);
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { OnGatewayConnection, OnGatewayDisconnect } from '@nestjs/websockets';
|
|
2
|
+
import { Server, Socket } from 'socket.io';
|
|
3
|
+
export declare class RealtimeGateway implements OnGatewayConnection, OnGatewayDisconnect {
|
|
4
|
+
server: Server;
|
|
5
|
+
private readonly logger;
|
|
6
|
+
private connectedUsers;
|
|
7
|
+
handleConnection(client: Socket): void;
|
|
8
|
+
handleDisconnect(client: Socket): void;
|
|
9
|
+
emitEntityChange(entityName: string, action: string, data: any, tenantId?: string): void;
|
|
10
|
+
handleSubscribeEntity(entity: string, client: Socket): {
|
|
11
|
+
event: string;
|
|
12
|
+
data: string;
|
|
13
|
+
};
|
|
14
|
+
}
|