From bda9bb3d6140042914a2f6d59c20b8cc387be4b7 Mon Sep 17 00:00:00 2001 From: Daniel Hougaard Date: Sun, 8 Sep 2024 19:21:17 +0400 Subject: [PATCH] fix: rename list audit logs and include project --- backend/src/ee/routes/v1/project-router.ts | 6 ++- .../ee/services/audit-log/audit-log-dal.ts | 37 +++++++++++++++---- .../services/audit-log/audit-log-service.ts | 28 ++++++++------ .../ee/services/audit-log/audit-log-types.ts | 4 +- 4 files changed, 53 insertions(+), 22 deletions(-) diff --git a/backend/src/ee/routes/v1/project-router.ts b/backend/src/ee/routes/v1/project-router.ts index aa32fcb5f..b3cff0322 100644 --- a/backend/src/ee/routes/v1/project-router.ts +++ b/backend/src/ee/routes/v1/project-router.ts @@ -122,6 +122,10 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => { }) .merge( z.object({ + project: z.object({ + name: z.string(), + slug: z.string() + }), event: z.object({ type: z.string(), metadata: z.any() @@ -138,7 +142,7 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => { }, onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY, AuthMode.IDENTITY_ACCESS_TOKEN]), handler: async (req) => { - const auditLogs = await server.services.auditLog.listProjectAuditLogs({ + const auditLogs = await server.services.auditLog.listAuditLogs({ actorId: req.permission.id, actorOrgId: req.permission.orgId, actorAuthMethod: req.permission.authMethod, diff --git a/backend/src/ee/services/audit-log/audit-log-dal.ts b/backend/src/ee/services/audit-log/audit-log-dal.ts index bcb76e6a5..3021beb0d 100644 --- a/backend/src/ee/services/audit-log/audit-log-dal.ts +++ b/backend/src/ee/services/audit-log/audit-log-dal.ts @@ -1,9 +1,9 @@ import { Knex } from "knex"; import { TDbClient } from "@app/db"; -import { TableName } from "@app/db/schemas"; +import { AuditLogsSchema, TableName } from "@app/db/schemas"; import { DatabaseError } from "@app/lib/errors"; -import { ormify, stripUndefinedInWhere } from "@app/lib/knex"; +import { ormify, selectAllTableCols, stripUndefinedInWhere } from "@app/lib/knex"; import { logger } from "@app/lib/logger"; import { QueueName } from "@app/queue"; @@ -33,23 +33,44 @@ export const auditLogDALFactory = (db: TDbClient) => { .where( stripUndefinedInWhere({ projectId, - orgId, + [`${TableName.AuditLog}.orgId`]: orgId, eventType, - actor, userAgentType }) ) + + .leftJoin(TableName.Project, `${TableName.AuditLog}.projectId`, `${TableName.Project}.id`) + + .select(selectAllTableCols(TableName.AuditLog)) + + .select( + db.ref("name").withSchema(TableName.Project).as("projectName"), + db.ref("slug").withSchema(TableName.Project).as("projectSlug") + ) + .limit(limit) .offset(offset) - .orderBy("createdAt", "desc"); + .orderBy(`${TableName.AuditLog}.createdAt`, "desc"); + + if (actor) { + void sqlQuery.whereRaw(`"actorMetadata"->>'userId' = ?`, [actor]); + } + if (startDate) { - void sqlQuery.where("createdAt", ">=", startDate); + void sqlQuery.where(`${TableName.AuditLog}.createdAt`, ">=", startDate); } if (endDate) { - void sqlQuery.where("createdAt", "<=", endDate); + void sqlQuery.where(`${TableName.AuditLog}.createdAt`, "<=", endDate); } const docs = await sqlQuery; - return docs; + + return docs.map((doc) => ({ + ...AuditLogsSchema.parse(doc), + project: { + name: doc.projectName, + slug: doc.projectSlug + } + })); } catch (error) { throw new DatabaseError({ error }); } diff --git a/backend/src/ee/services/audit-log/audit-log-service.ts b/backend/src/ee/services/audit-log/audit-log-service.ts index 2916eb412..2fc7e0de3 100644 --- a/backend/src/ee/services/audit-log/audit-log-service.ts +++ b/backend/src/ee/services/audit-log/audit-log-service.ts @@ -22,7 +22,7 @@ export const auditLogServiceFactory = ({ auditLogQueue, permissionService }: TAuditLogServiceFactoryDep) => { - const listProjectAuditLogs = async ({ + const listAuditLogs = async ({ userAgentType, eventType, offset, @@ -36,14 +36,19 @@ export const auditLogServiceFactory = ({ projectId, auditLogActor }: TListProjectAuditLogDTO) => { - const { permission } = await permissionService.getProjectPermission( - actor, - actorId, - projectId, - actorAuthMethod, - actorOrgId - ); - ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.AuditLogs); + if (projectId) { + const { permission } = await permissionService.getProjectPermission( + actor, + actorId, + projectId, + actorAuthMethod, + actorOrgId + ); + ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.AuditLogs); + } + + // If project ID is not provided, then we need to return all the audit logs for the organization itself. + const auditLogs = await auditLogDAL.find({ startDate, endDate, @@ -52,8 +57,9 @@ export const auditLogServiceFactory = ({ eventType, userAgentType, actor: auditLogActor, - projectId + ...(projectId ? { projectId } : { orgId: actorOrgId }) }); + return auditLogs.map(({ eventType: logEventType, actor: eActor, actorMetadata, eventMetadata, ...el }) => ({ ...el, event: { type: logEventType, metadata: eventMetadata }, @@ -76,6 +82,6 @@ export const auditLogServiceFactory = ({ return { createAuditLog, - listProjectAuditLogs + listAuditLogs }; }; diff --git a/backend/src/ee/services/audit-log/audit-log-types.ts b/backend/src/ee/services/audit-log/audit-log-types.ts index 981b3777e..6202d30f2 100644 --- a/backend/src/ee/services/audit-log/audit-log-types.ts +++ b/backend/src/ee/services/audit-log/audit-log-types.ts @@ -6,14 +6,14 @@ import { PkiItemType } from "@app/services/pki-collection/pki-collection-types"; export type TListProjectAuditLogDTO = { auditLogActor?: string; - projectId: string; + projectId: string | null; eventType?: string; startDate?: string; endDate?: string; userAgentType?: string; limit?: number; offset?: number; -} & TProjectPermission; +} & Omit; export type TCreateAuditLogDTO = { event: Event;