-
Notifications
You must be signed in to change notification settings - Fork 37
Feat/audit log #76
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Feat/audit log #76
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -4,6 +4,7 @@ import express, { | |||||||||||||||||||
| Response, | ||||||||||||||||||||
| RequestHandler, | ||||||||||||||||||||
| ErrorRequestHandler, | ||||||||||||||||||||
| NextFunction, | ||||||||||||||||||||
| } from "express"; | ||||||||||||||||||||
| import morgan from "morgan"; | ||||||||||||||||||||
| import cors from "cors"; | ||||||||||||||||||||
|
|
@@ -13,6 +14,7 @@ import sessionRouter from "./routes/session.routes"; | |||||||||||||||||||
| import emailVerification from "./routes/emailVerification.routes"; | ||||||||||||||||||||
| import PaymentRoute from "./routes/PaymentLink.routes"; | ||||||||||||||||||||
| import authRoutes from "./routes/authRoutes"; | ||||||||||||||||||||
| import auditLogRoute from "./routes/auditLogRoutes"; | ||||||||||||||||||||
| import userRoutes from "./routes/userRoutes"; | ||||||||||||||||||||
| import healthRouter from "./routes/health.routes"; | ||||||||||||||||||||
| import walletVerificationRoutes from "./routes/wallet-verification.routes"; | ||||||||||||||||||||
|
|
@@ -30,6 +32,8 @@ import { requestLogger } from "./middlewares/requestLogger.middleware"; | |||||||||||||||||||
| import RateLimitMonitoringService from "./services/rateLimitMonitoring.service"; | ||||||||||||||||||||
| import { startExpiredSessionCleanupCronJobs } from "./utils/schedular"; | ||||||||||||||||||||
| import logger from "./utils/logger"; | ||||||||||||||||||||
| import { auth } from "express-openid-connect"; | ||||||||||||||||||||
| import { auditMiddleware } from "./middlewares/audit.middleware"; | ||||||||||||||||||||
|
|
||||||||||||||||||||
| // Initialize express app | ||||||||||||||||||||
| const app = express(); | ||||||||||||||||||||
|
|
@@ -77,6 +81,21 @@ app.use((req, res, next) => { | |||||||||||||||||||
| // Start scheduled jobs | ||||||||||||||||||||
| startExpiredSessionCleanupCronJobs(); | ||||||||||||||||||||
|
|
||||||||||||||||||||
| // Initialize the database connection | ||||||||||||||||||||
| // AppDataSource.initialize() | ||||||||||||||||||||
| // .then(() => { | ||||||||||||||||||||
| // logger.info("Data Source has been initialized!"); | ||||||||||||||||||||
| // }) | ||||||||||||||||||||
| // .catch((err) => { | ||||||||||||||||||||
| // logger.error("Error during Data Source initialization:", err); | ||||||||||||||||||||
| // process.exit(1); // Exit if we can't connect to the database | ||||||||||||||||||||
| // }); | ||||||||||||||||||||
|
Comment on lines
+84
to
+92
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. π‘ Verification agent π§© Analysis chainUncomment or remove database initialization code. The database initialization code is commented out, which suggests it's handled elsewhere. If that's the case, remove this code entirely. If not, uncomment it to ensure the database is properly initialized before handling requests. Leaving commented code in production creates confusion about what's actually running. π Script executed: #!/bin/bash
# Check where database initialization happens in the codebase
rg -A 5 "AppDataSource.initialize" --type=tsLength of output: 2450 Remove redundant commented-out database initialization in src/app.ts The database is already initialized in src/index.ts (and in health routes), so the commented-out block in src/app.ts can be deleted to avoid confusion. β’ File: src/app.ts - // Initialize the database connection
- // AppDataSource.initialize()
- // .then(() => {
- // logger.info("Data Source has been initialized!");
- // })
- // .catch((err) => {
- // logger.error("Error during Data Source initialization:", err);
- // process.exit(1); // Exit if we can't connect to the database
- // });π Committable suggestion
Suggested change
|
||||||||||||||||||||
|
|
||||||||||||||||||||
| app.use(((req: Request, res: Response, next: NextFunction) => { | ||||||||||||||||||||
| req.dataSource = AppDataSource; | ||||||||||||||||||||
| next(); | ||||||||||||||||||||
| }) as RequestHandler); | ||||||||||||||||||||
|
Comment on lines
+94
to
+97
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Missing import for AppDataSource The middleware attaches Add the import at the top of the file: import logger from "./utils/logger";
import { auth } from "express-openid-connect";
import { auditMiddleware } from "./middlewares/audit.middleware";
+import { AppDataSource } from "./config/db";π Committable suggestion
Suggested change
π§° Toolsπͺ ESLint[error] 95-95: 'AppDataSource' is not defined. (no-undef) |
||||||||||||||||||||
|
|
||||||||||||||||||||
| // Log application startup | ||||||||||||||||||||
| logger.info("Application started successfully"); | ||||||||||||||||||||
|
|
||||||||||||||||||||
|
|
@@ -91,7 +110,10 @@ app.use("/users", userRoutes); | |||||||||||||||||||
| app.use("/merchants", merchantRoutes); | ||||||||||||||||||||
| app.use("/webhook-queue/merchant", merchantWebhookQueueRoutes); | ||||||||||||||||||||
| app.use("/reports/transactions", transactionReportsRoutes); | ||||||||||||||||||||
| //app.use("/api/v1/stellar", stellarContractRoutes); | ||||||||||||||||||||
| //app.use("/audit-log", auditLogRoute); | ||||||||||||||||||||
| app.use("/api/v1/stellar", stellarContractRoutes); | ||||||||||||||||||||
|
Comment on lines
+113
to
+114
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Inconsistent route configuration There are two issues here:
Fix these issues with the following changes: -//app.use("/audit-log", auditLogRoute);
-app.use("/api/v1/stellar", stellarContractRoutes);
+app.use("/audit-log", auditLogRoute);
+//app.use("/api/v1/stellar", stellarContractRoutes);Or uncomment the import on line 24: -//import stellarContractRoutes from "./routes/stellar-contract.routes";
+import stellarContractRoutes from "./routes/stellar-contract.routes";π Committable suggestion
Suggested change
π§° Toolsπͺ ESLint[error] 114-114: 'stellarContractRoutes' is not defined. (no-undef) |
||||||||||||||||||||
|
|
||||||||||||||||||||
|
|
||||||||||||||||||||
|
|
||||||||||||||||||||
| // Error handling middleware | ||||||||||||||||||||
| const customErrorHandler: ErrorRequestHandler = (err, req, res, _next) => { | ||||||||||||||||||||
|
|
@@ -117,4 +139,4 @@ app.use(((req: Request, res: Response) => { | |||||||||||||||||||
| }) as RequestHandler); | ||||||||||||||||||||
|
|
||||||||||||||||||||
| // Export app | ||||||||||||||||||||
| export default app; | ||||||||||||||||||||
| export { app }; | ||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. π‘ Verification agent π§© Analysis chainVerify that import changes are applied throughout the codebase. Changing from default export to named export will require updates to all import statements that reference this module. Ensure all imports have been updated to use the new named export format. π Script executed: #!/bin/bash
# Check for imports of app to ensure they're using named imports
rg "import .* from ['\"].*app['\"]" --type=tsLength of output: 330 Update Tests are still using the default import ( β’ src/tests/health.test.ts Example change: -import app from "../app";
+import { app } from "../app";
|
||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,11 +9,13 @@ import { WalletVerification } from "../entities/WalletVerification"; | |
| import { MerchantEntity } from "../entities/Merchant.entity"; | ||
| import { MerchantWebhookEntity } from "../entities/MerchantWebhook.entity"; | ||
| import { MerchantWebhookEventEntity } from "../entities/MerchantWebhookEvent.entity"; | ||
| import { AuditLog } from "../entities/AuditLog.entity"; | ||
| import { PaymentLink } from "../entities/PaymentLink"; | ||
|
|
||
|
|
||
| dotenv.config(); | ||
|
|
||
| const AppDataSource = new DataSource({ | ||
| export const AppDataSource = new DataSource({ | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. π‘ Verification agent π§© Analysis chainExport style change from default to named export. The switch from a default export to a named export improves code consistency and makes imports more explicit throughout the codebase. π Script executed: #!/bin/bash
# Check if all imports of AppDataSource have been updated to use named imports
grep -r "import AppDataSource from" --include="*.ts" .Length of output: 601 Update test imports to use named export Files to update:
Example change: - import AppDataSource from "../config/db";
+ import { AppDataSource } from "../config/db";Ensure all occurrences are corrected so tests import with braces. |
||
| type: "postgres", | ||
| host: process.env.POSTGRES_HOST, | ||
| port: Number(process.env.POSTGRES_PORT), | ||
|
|
@@ -32,10 +34,9 @@ const AppDataSource = new DataSource({ | |
| MerchantEntity, | ||
| MerchantWebhookEntity, | ||
| MerchantWebhookEventEntity, | ||
| AuditLog, | ||
| PaymentLink, | ||
| ], | ||
| migrations: ["src/migrations/*.ts"], | ||
| migrationsTableName: "migrations", | ||
| }); | ||
|
|
||
| export default AppDataSource; | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,36 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { Request, Response } from "express"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { AuditLogActionsEnum } from "../enums/AuditLogAction"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { AuditService } from "../services/Audit.service"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export class AuditLogController { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fetchAllAuditLogs = async (req: Request, res: Response) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const auditService = new AuditService(req.dataSource); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const filters = { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| entityType: req.query.entityType as string, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| entityId: req.query.entityId as string, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| userId: req.query.userId as string, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| action: req.query.action as AuditLogActionsEnum, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| startDate: req.query.startDate | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ? new Date(req.query.startDate as string) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| : undefined, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| endDate: req.query.endDate | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ? new Date(req.query.endDate as string) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| : undefined, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| page: req.query.page ? parseInt(req.query.page as string, 10) : 1, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| limit: req.query.limit ? parseInt(req.query.limit as string, 10) : 10, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+10
to
+23
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. π οΈ Refactor suggestion Validate query params before passing them to the service -const filters = {
- entityType: req.query.entityType as string,
- entityId: req.query.entityId as string,
- userId: req.query.userId as string,
- action: req.query.action as AuditLogActionsEnum,
- startDate: req.query.startDate ? new Date(req.query.startDate as string) : undefined,
- endDate: req.query.endDate ? new Date(req.query.endDate as string) : undefined,
- page: req.query.page ? parseInt(req.query.page as string, 10) : 1,
- limit: req.query.limit ? parseInt(req.query.limit as string, 10) : 10,
-};
+const parseDate = (d?: string) => {
+ const dt = d ? new Date(d) : undefined;
+ if (dt && isNaN(dt.getTime())) throw new Error(`Invalid date: ${d}`);
+ return dt;
+};
+
+const toPositiveInt = (v: unknown, fallback: number) => {
+ const n = Number(v);
+ return Number.isInteger(n) && n > 0 ? n : fallback;
+};
+
+const filters = {
+ entityType: req.query.entityType as string | undefined,
+ entityId: req.query.entityId as string | undefined,
+ userId: req.query.userId as string | undefined,
+ action: req.query.action as AuditLogActionsEnum | undefined,
+ startDate: parseDate(req.query.startDate as string | undefined),
+ endDate: parseDate(req.query.endDate as string | undefined),
+ page: toPositiveInt(req.query.page, 1),
+ limit: toPositiveInt(req.query.limit, 10),
+};This keeps invalid input from propagating to the DB layer and returns a clear π Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const result = await auditService.findAuditLogs(filters); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| res.status(200).json(result); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } catch (error) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (error instanceof Error) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| res.status(400).json({ message: error.message }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| res.status(500).json({ message: "Internal server error" }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -2,11 +2,14 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { Request, Response } from "express"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { AuthService } from "../services/AuthService"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { validateTwoFactorAuthentication } from "./validateTwoFactorAuthentication"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import AppDataSource from "../config/db"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { User } from "../entities/User"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { compare } from "bcryptjs"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { Auth0Profile } from "src/interfaces/auth.interfaces"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { AuditLogActionsEnum } from "../enums/AuditLogAction"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { AuditService } from "../services/Audit.service"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { AppDataSource } from "../config/db"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export class AuthController { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public authService: AuthService; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -17,6 +20,18 @@ export class AuthController { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| register = async (req: Request, res: Response): Promise<void> => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const user = await this.authService.register(req.body); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.log("Done with registration", { user }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const auditService = new AuditService(req.dataSource); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| await auditService.createAuditLogs({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| entityType: "User", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| entityId: String(user.id), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| action: AuditLogActionsEnum.CREATE, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| newValues: req.body, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| userId: String(user.id), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| userEmail: user.email, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ipAddress: req.auditContext?.ipAddress || "0.0.0.0", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| userAgent: req.auditContext?.userAgent || "Unknown", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+23
to
+34
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. π οΈ Refactor suggestion Audit logging implementation for user registration. The audit logging implementation captures comprehensive information about the registration event, including entity details, user information, and request metadata with appropriate fallbacks. Consider wrapping the audit logging in a try-catch block to prevent audit logging failures from affecting the user experience: console.log("Done with registration", { user });
- const auditService = new AuditService(req.dataSource);
- await auditService.createAuditLogs({
- entityType: "User",
- entityId: String(user.id),
- action: AuditLogActionsEnum.CREATE,
- newValues: req.body,
- userId: String(user.id),
- userEmail: user.email,
- ipAddress: req.auditContext?.ipAddress || "0.0.0.0",
- userAgent: req.auditContext?.userAgent || "Unknown",
- });
+ try {
+ const auditService = new AuditService(req.dataSource);
+ await auditService.createAuditLogs({
+ entityType: "User",
+ entityId: String(user.id),
+ action: AuditLogActionsEnum.CREATE,
+ newValues: req.body,
+ userId: String(user.id),
+ userEmail: user.email,
+ ipAddress: req.auditContext?.ipAddress || "0.0.0.0",
+ userAgent: req.auditContext?.userAgent || "Unknown",
+ });
+ } catch (auditError) {
+ console.error("Failed to create audit log for user registration:", auditError);
+ // Continue with the response, don't fail the registration if audit logging fails
+ }π Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| res.status(201).json(user); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } catch (error) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (error instanceof Error) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| import { | ||
| Column, | ||
| CreateDateColumn, | ||
| Entity, | ||
| PrimaryGeneratedColumn, | ||
| } from "typeorm"; | ||
| import { AuditLogActionsEnum } from "../enums/AuditLogAction"; | ||
|
|
||
| @Entity("audit_logs") | ||
| export class AuditLog { | ||
| @PrimaryGeneratedColumn("uuid") | ||
| id: string; | ||
|
|
||
| @Column() | ||
| entityType: string; // 'User', 'PaymentLink', 'BusinessProfile', etc. | ||
|
|
||
| @Column() | ||
| entityId: string; | ||
|
|
||
| @Column({ | ||
| type: "enum", | ||
| enum: AuditLogActionsEnum, | ||
| default: AuditLogActionsEnum.CREATE, | ||
| }) | ||
| action: AuditLogActionsEnum; | ||
|
|
||
| @Column("json", { nullable: true }) | ||
| oldValues?: Record<string, any>; // used when there is an update, so we can see | ||
| // what value was there previously | ||
|
|
||
| @Column("json", { nullable: true }) | ||
| newValues?: Record<string, any>; | ||
|
|
||
| @Column() | ||
| userId: string; | ||
|
|
||
| @Column() | ||
| userEmail: string; | ||
|
|
||
| @Column() | ||
| ipAddress: string; | ||
|
|
||
| @Column() | ||
| userAgent: string; | ||
|
|
||
| @CreateDateColumn() | ||
| createdAt: Date; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Import added but route is commented out
You've imported
auditLogRoutebut the route registration on line 113 is commented out. Either uncomment the route registration or remove this import if it's not being used yet.