@autofleet/shtinker 0.0.1
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/const.d.ts +3 -0
- package/dist/const.js +6 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +63 -0
- package/dist/types.d.ts +24 -0
- package/dist/types.js +2 -0
- package/package.json +34 -0
- package/src/const.ts +3 -0
- package/src/index.ts +61 -0
- package/src/types.ts +27 -0
- package/tsconfig.json +13 -0
package/dist/const.d.ts
ADDED
package/dist/const.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AUDIT_LOG_CONTEXT_KEY = exports.AUDIT_LOG_ROWS_QUEUE = exports.AUDIT_LOG_CONTEXT_QUEUE = void 0;
|
|
4
|
+
exports.AUDIT_LOG_CONTEXT_QUEUE = 'audit-log-context';
|
|
5
|
+
exports.AUDIT_LOG_ROWS_QUEUE = 'audit-log-rows';
|
|
6
|
+
exports.AUDIT_LOG_CONTEXT_KEY = 'auditLogContext';
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { AuditLoggerOptions } from './types';
|
|
2
|
+
declare class AuditLogger {
|
|
3
|
+
private rabbit;
|
|
4
|
+
private sequelize;
|
|
5
|
+
constructor(options: AuditLoggerOptions);
|
|
6
|
+
enableAuditLogging(): void;
|
|
7
|
+
setAuditingContext: (entityType: string, entityId: string, action: string) => (req: any, res: any, next: any) => Promise<void>;
|
|
8
|
+
}
|
|
9
|
+
export default AuditLogger;
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
const zehut_1 = require("@autofleet/zehut");
|
|
13
|
+
const const_1 = require("./const");
|
|
14
|
+
const getAuditingContext = () => {
|
|
15
|
+
var _a;
|
|
16
|
+
const currentTrace = (0, zehut_1.getCurrentPayload)();
|
|
17
|
+
const auditingContext = (_a = currentTrace === null || currentTrace === void 0 ? void 0 : currentTrace.context) === null || _a === void 0 ? void 0 : _a.get(const_1.AUDIT_LOG_CONTEXT_KEY);
|
|
18
|
+
return auditingContext;
|
|
19
|
+
};
|
|
20
|
+
class AuditLogger {
|
|
21
|
+
constructor(options) {
|
|
22
|
+
this.setAuditingContext = (entityType, entityId, action) => (req, res, next) => __awaiter(this, void 0, void 0, function* () {
|
|
23
|
+
const currentTrace = (0, zehut_1.getCurrentPayload)();
|
|
24
|
+
if (currentTrace) {
|
|
25
|
+
const user = currentTrace.context.get('userObject');
|
|
26
|
+
const auditLogContext = {
|
|
27
|
+
entityType,
|
|
28
|
+
entityId,
|
|
29
|
+
action,
|
|
30
|
+
endpoint: req.url,
|
|
31
|
+
method: req.method,
|
|
32
|
+
performedBy: user.id,
|
|
33
|
+
};
|
|
34
|
+
currentTrace.context.set(const_1.AUDIT_LOG_CONTEXT_KEY, auditLogContext);
|
|
35
|
+
yield this.rabbit.sendToQueue(const_1.AUDIT_LOG_CONTEXT_QUEUE, auditLogContext);
|
|
36
|
+
next();
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
this.rabbit = options.rabbit;
|
|
40
|
+
this.sequelize = options.sequelize;
|
|
41
|
+
}
|
|
42
|
+
enableAuditLogging() {
|
|
43
|
+
Object.entries(this.sequelize.models).forEach(([modelName, modelType]) => {
|
|
44
|
+
modelType.addHook('afterSave', (instance) => __awaiter(this, void 0, void 0, function* () {
|
|
45
|
+
const auditingContext = getAuditingContext();
|
|
46
|
+
if (auditingContext) {
|
|
47
|
+
const changedProperties = instance.changed();
|
|
48
|
+
const payload = {
|
|
49
|
+
entityType: modelName,
|
|
50
|
+
entityId: instance.id,
|
|
51
|
+
rows: changedProperties.map((property) => ({
|
|
52
|
+
property,
|
|
53
|
+
previousValue: instance.previousValue(property),
|
|
54
|
+
newValue: instance.get(property),
|
|
55
|
+
})),
|
|
56
|
+
};
|
|
57
|
+
yield this.rabbit.sendToQueue(const_1.AUDIT_LOG_ROWS_QUEUE, payload);
|
|
58
|
+
}
|
|
59
|
+
}));
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
exports.default = AuditLogger;
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Sequelize } from 'sequelize-typescript';
|
|
2
|
+
import RabbitMq from '@autofleet/rabbit';
|
|
3
|
+
export type AuditLoggerOptions = {
|
|
4
|
+
rabbit: RabbitMq;
|
|
5
|
+
sequelize: Sequelize;
|
|
6
|
+
};
|
|
7
|
+
export interface AuditLogContext {
|
|
8
|
+
entityType: string;
|
|
9
|
+
entityId: string;
|
|
10
|
+
action: string;
|
|
11
|
+
performedBy: string;
|
|
12
|
+
endpoint: string;
|
|
13
|
+
method: string;
|
|
14
|
+
}
|
|
15
|
+
export interface AuditLogRow {
|
|
16
|
+
property: string;
|
|
17
|
+
previousValue: any;
|
|
18
|
+
newValue: any;
|
|
19
|
+
}
|
|
20
|
+
export interface AuditLogPayload {
|
|
21
|
+
entityType: string;
|
|
22
|
+
entityId: string;
|
|
23
|
+
rows: AuditLogRow;
|
|
24
|
+
}
|
package/dist/types.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@autofleet/shtinker",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"start": "ts-node src/index.ts",
|
|
8
|
+
"build": "rm -rf dist && tsc",
|
|
9
|
+
"linter": "./node_modules/.bin/eslint .",
|
|
10
|
+
"test": "jest --forceExit",
|
|
11
|
+
"coverage": "jest --coverage --forceExit && rm -rf ./coverage",
|
|
12
|
+
"dev": "nodemon"
|
|
13
|
+
},
|
|
14
|
+
"dependencies": {
|
|
15
|
+
"@autofleet/logger": "^2.0.5",
|
|
16
|
+
"@autofleet/rabbit": "^2.4.1",
|
|
17
|
+
"@autofleet/zehut": "^2.0.4",
|
|
18
|
+
"sequelize-typescript": "^2.1.5"
|
|
19
|
+
},
|
|
20
|
+
"devDependencies": {
|
|
21
|
+
"@types/jest": "^27.0.9",
|
|
22
|
+
"@types/node": "^18.11.19",
|
|
23
|
+
"@typescript-eslint/eslint-plugin": "^4.8.1",
|
|
24
|
+
"eslint": "^7.13.0",
|
|
25
|
+
"eslint-config-airbnb-typescript": "^12.0.0",
|
|
26
|
+
"eslint-plugin-import": "^2.22.1",
|
|
27
|
+
"jest": "^27.0.5",
|
|
28
|
+
"ts-jest": "^27.0.3",
|
|
29
|
+
"ts-node": "^10.9.1",
|
|
30
|
+
"typescript": "^4.9.5"
|
|
31
|
+
},
|
|
32
|
+
"author": "Autofleet",
|
|
33
|
+
"license": "ISC"
|
|
34
|
+
}
|
package/src/const.ts
ADDED
package/src/index.ts
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { getCurrentPayload as getCurrentTrace } from '@autofleet/zehut';
|
|
2
|
+
import { AuditLogPayload, AuditLoggerOptions, AuditLogContext } from './types';
|
|
3
|
+
import { AUDIT_LOG_CONTEXT_QUEUE, AUDIT_LOG_ROWS_QUEUE, AUDIT_LOG_CONTEXT_KEY } from './const';
|
|
4
|
+
|
|
5
|
+
const getAuditingContext = () => {
|
|
6
|
+
const currentTrace = getCurrentTrace();
|
|
7
|
+
const auditingContext = currentTrace?.context?.get(AUDIT_LOG_CONTEXT_KEY);
|
|
8
|
+
return auditingContext;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
class AuditLogger {
|
|
12
|
+
private rabbit;
|
|
13
|
+
|
|
14
|
+
private sequelize;
|
|
15
|
+
|
|
16
|
+
constructor(options: AuditLoggerOptions) {
|
|
17
|
+
this.rabbit = options.rabbit;
|
|
18
|
+
this.sequelize = options.sequelize;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
enableAuditLogging(): void {
|
|
22
|
+
Object.entries(this.sequelize.models).forEach(([modelName, modelType]) => {
|
|
23
|
+
modelType.addHook('afterSave', async (instance: any) => {
|
|
24
|
+
const auditingContext = getAuditingContext();
|
|
25
|
+
if (auditingContext) {
|
|
26
|
+
const changedProperties = instance.changed();
|
|
27
|
+
const payload: AuditLogPayload = {
|
|
28
|
+
entityType: modelName,
|
|
29
|
+
entityId: instance.id,
|
|
30
|
+
rows: changedProperties.map((property: string) => ({
|
|
31
|
+
property,
|
|
32
|
+
previousValue: instance.previousValue(property),
|
|
33
|
+
newValue: instance.get(property),
|
|
34
|
+
})),
|
|
35
|
+
};
|
|
36
|
+
await this.rabbit.sendToQueue(AUDIT_LOG_ROWS_QUEUE, payload);
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
setAuditingContext = (entityType: string, entityId: string, action: string) => async (req: any, res: any, next: any) => {
|
|
43
|
+
const currentTrace = getCurrentTrace();
|
|
44
|
+
if (currentTrace) {
|
|
45
|
+
const user = currentTrace.context.get('userObject');
|
|
46
|
+
const auditLogContext: AuditLogContext = {
|
|
47
|
+
entityType,
|
|
48
|
+
entityId,
|
|
49
|
+
action,
|
|
50
|
+
endpoint: req.url,
|
|
51
|
+
method: req.method,
|
|
52
|
+
performedBy: user.id,
|
|
53
|
+
};
|
|
54
|
+
currentTrace.context.set(AUDIT_LOG_CONTEXT_KEY, auditLogContext);
|
|
55
|
+
await this.rabbit.sendToQueue(AUDIT_LOG_CONTEXT_QUEUE, auditLogContext);
|
|
56
|
+
next();
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export default AuditLogger;
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Sequelize } from 'sequelize-typescript';
|
|
2
|
+
import RabbitMq from '@autofleet/rabbit';
|
|
3
|
+
|
|
4
|
+
export type AuditLoggerOptions = {
|
|
5
|
+
rabbit: RabbitMq;
|
|
6
|
+
sequelize: Sequelize;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export interface AuditLogContext {
|
|
10
|
+
entityType: string;
|
|
11
|
+
entityId: string;
|
|
12
|
+
action: string;
|
|
13
|
+
performedBy: string;
|
|
14
|
+
endpoint: string;
|
|
15
|
+
method: string;
|
|
16
|
+
}
|
|
17
|
+
export interface AuditLogRow {
|
|
18
|
+
property: string;
|
|
19
|
+
previousValue: any;
|
|
20
|
+
newValue: any;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface AuditLogPayload {
|
|
24
|
+
entityType: string;
|
|
25
|
+
entityId: string;
|
|
26
|
+
rows: AuditLogRow;
|
|
27
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "es6",
|
|
4
|
+
"module": "commonjs",
|
|
5
|
+
"declaration": true,
|
|
6
|
+
"outDir": "./dist",
|
|
7
|
+
"strict": true,
|
|
8
|
+
"esModuleInterop": true,
|
|
9
|
+
"experimentalDecorators": true,
|
|
10
|
+
"emitDecoratorMetadata": true
|
|
11
|
+
},
|
|
12
|
+
"exclude": ["node_modules", "**/*.test.ts"]
|
|
13
|
+
}
|