@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.
@@ -0,0 +1,3 @@
1
+ export declare const AUDIT_LOG_CONTEXT_QUEUE = "audit-log-context";
2
+ export declare const AUDIT_LOG_ROWS_QUEUE = "audit-log-rows";
3
+ export declare const AUDIT_LOG_CONTEXT_KEY = "auditLogContext";
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';
@@ -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;
@@ -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
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
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
@@ -0,0 +1,3 @@
1
+ export const AUDIT_LOG_CONTEXT_QUEUE = 'audit-log-context';
2
+ export const AUDIT_LOG_ROWS_QUEUE = 'audit-log-rows';
3
+ export const AUDIT_LOG_CONTEXT_KEY = 'auditLogContext';
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
+ }