Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions apps/server-nestjs/src/main.module.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,33 @@
import { Module } from '@nestjs/common'
import { EventEmitterModule } from '@nestjs/event-emitter'
import { ScheduleModule } from '@nestjs/schedule'
import { DeploymentModule } from './modules/deployment/deployment.module'
import { HealthzModule } from './modules/healthz/healthz.module'
import { KeycloakModule } from './modules/keycloak/keycloak.module'
import { LogModule } from './modules/log/log.module'
import { ProjectHooksModule } from './modules/project-hooks/project-hooks.module'
import { ProjectMembersModule } from './modules/project-members/project-members.module'
import { ProjectRolesModule } from './modules/project-roles/project-roles.module'
import { ProjectSecretsModule } from './modules/project-secrets/project-secrets.module'
import { ProjectServicesModule } from './modules/project-services/project-services.module'
import { ProjectModule } from './modules/project/project.module'
import { ServiceChainModule } from './modules/service-chain/service-chain.module'
import { SystemSettingsModule } from './modules/system-settings/system-settings.module'
import { VersionModule } from './modules/version/version.module'

@Module({
imports: [
EventEmitterModule.forRoot(),
HealthzModule,
KeycloakModule,
ScheduleModule.forRoot(),
SystemSettingsModule,
ServiceChainModule,
ProjectModule,
ProjectHooksModule,
ProjectSecretsModule,
ProjectServicesModule,
ProjectMembersModule,
ProjectRolesModule,
LogModule,
DeploymentModule,
VersionModule,
],
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { Module } from '@nestjs/common'
import { EventEmitterModule } from '@nestjs/event-emitter'

@Module({
imports: [EventEmitterModule.forRoot()],
exports: [EventEmitterModule],
})
export class EventsModule {}
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@ import { Module } from '@nestjs/common'
import { AuthModule } from './auth/auth.module'
import { ConfigurationModule } from './configuration/configuration.module'
import { DatabaseModule } from './database/database.module'
import { EventsModule } from './events/events.module'
import { LoggerModule } from './logger/logger.module'
import { PermissionModule } from './permission/permission.module'

@Module({
providers: [],
imports: [AuthModule, PermissionModule, DatabaseModule, LoggerModule, ConfigurationModule],
exports: [AuthModule, DatabaseModule, PermissionModule, ConfigurationModule],
imports: [AuthModule, PermissionModule, DatabaseModule, LoggerModule, ConfigurationModule, EventsModule],
exports: [AuthModule, DatabaseModule, PermissionModule, ConfigurationModule, EventsModule],
})
export class InfrastructureModule {}
30 changes: 30 additions & 0 deletions apps/server-nestjs/src/modules/log/log-queries.utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import type { Prisma } from '@prisma/client'

const logSelect = {
id: true,
createdAt: true,
updatedAt: true,
action: true,
userId: true,
requestId: true,
projectId: true,
data: true,
} satisfies Prisma.LogSelect

export type LogSelect = Prisma.LogGetPayload<{
select: typeof logSelect
}>

export function countLogs(tx: Prisma.TransactionClient, projectId: string | null | undefined) {
return tx.log.count({ where: { projectId } })
}

export function listLogs(tx: Prisma.TransactionClient, projectId: string | null | undefined, offset: number, limit: number) {
return tx.log.findMany({
orderBy: { createdAt: 'desc' },
skip: offset,
take: limit,
where: { projectId },
select: logSelect,
})
}
2 changes: 1 addition & 1 deletion apps/server-nestjs/src/modules/log/log.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import { Test } from '@nestjs/testing'
import { beforeEach, describe, expect, it } from 'vitest'
import { mockDeep } from 'vitest-mock-extended'
import { PrismaService } from '../infrastructure/database/prisma.service'
import { makeLog } from './log-testing.utils'
import { LogService } from './log.service'
import { makeLog } from './log.testing.utils'

describe('logService', () => {
let module: TestingModule
Expand Down
20 changes: 10 additions & 10 deletions apps/server-nestjs/src/modules/log/log.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import type { Prisma } from '@prisma/client'
import { CleanLogSchema, exclude } from '@cpn-console/shared'
import { Inject, Injectable } from '@nestjs/common'
import { PrismaService } from '../infrastructure/database/prisma.service'
import { countLogs, listLogs } from './log-queries.utils'

interface AddLogArgs {
action: string
Expand All @@ -19,15 +20,7 @@ export class LogService {
) {}

async getLogs(params: AdminLogsQuery) {
const [total, logs] = await this.prisma.$transaction([
this.prisma.log.count({ where: { projectId: params.projectId } }),
this.prisma.log.findMany({
orderBy: { createdAt: 'desc' },
skip: params.offset,
take: params.limit,
where: { projectId: params.projectId },
}),
])
const [total, logs] = await this.getLogsWithCount(params.projectId, params.offset, params.limit)

return {
total,
Expand All @@ -37,6 +30,13 @@ export class LogService {
}
}

async getLogsWithCount(projectId: string | null | undefined, offset: number, limit: number) {
return this.prisma.$transaction([
countLogs(this.prisma, projectId),
listLogs(this.prisma, projectId, offset, limit),
])
}

async addLog({
action,
data,
Expand All @@ -50,7 +50,7 @@ export class LogService {
userId,
requestId,
projectId,
data: exclude<Prisma.InputJsonValue>(data, ['cluster', 'user', 'newCreds', 'apis']),
data: exclude<Prisma.InputJsonValue>(data, ['cluster', 'user', 'newCreds', 'apis', 'config']),
},
})
}
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@ export class ProjectHooksController {
@RequireProjectStatus('initializing', 'created', 'failed', 'warning')
@RequireProjectLocked(false)
@RequireProjectPermission('ReplayHooks')
async replayHooks(
async replay(
@Project() project: ProjectContext,
@AuthUser() user: UserContext,
@Req() request: FastifyRequest,
): Promise<void> {
await this.projectHooks.replayHooks(project.id, user.userId, request.id)
await this.projectHooks.replay(project.id, user.userId, request.id)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ describe('projectHooksService', () => {
const requestId = 'request-id'
const userId = 'user-id'

await service.replayHooks('project-id', userId, requestId)
await service.replay('project-id', userId, requestId)

expect(prisma.project.findFirst).toHaveBeenCalledWith({
where: { id: 'project-id', status: { not: 'archived' } },
Expand All @@ -80,7 +80,7 @@ describe('projectHooksService', () => {
const project = makeProject({ locked: true })
prisma.project.findFirst.mockResolvedValue(project)

await expect(service.replayHooks('project-id', 'user-id', 'request-id')).rejects.toThrow(ForbiddenException)
await expect(service.replay('project-id', 'user-id', 'request-id')).rejects.toThrow(ForbiddenException)

expect(eventEmitter.emitAsync).not.toHaveBeenCalled()
expect(logs.addLog).not.toHaveBeenCalled()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { ProjectWithDetails } from '../project/project-queries.utils'
import { ForbiddenException, Inject, Injectable, Logger } from '@nestjs/common'
import { EventEmitter2 } from '@nestjs/event-emitter'
import { trace } from '@opentelemetry/api'
Expand All @@ -15,6 +16,26 @@ export class ProjectHooksService {
@Inject(LogService) private readonly logs: LogService,
) {}

private async logProjectAction(
action: string,
project: ProjectWithDetails,
messageResume: string,
userId: string | undefined,
requestId: string | undefined,
): Promise<void> {
await this.logs.addLog({
action,
data: {
args: { projectId: project.id },
messageResume,
results: { projectId: project.id, slug: project.slug },
},
userId,
requestId,
projectId: project.id,
})
}

async updateProjectLocked(projectId: string, locked: boolean): Promise<void> {
const project = await this.prisma.project.update({
where: { id: projectId },
Expand All @@ -24,7 +45,7 @@ export class ProjectHooksService {
await this.eventEmitter.emitAsync('project.upsert', project)
}

async replayHooks(projectId: string, requestorUserId?: string, requestId?: string): Promise<void> {
async replay(projectId: string, requestorUserId?: string, requestId?: string): Promise<void> {
const span = trace.getActiveSpan()
span?.setAttribute('project.id', projectId)
this.logger.log(`project.replayHooks started (projectId=${projectId})`)
Expand All @@ -39,22 +60,13 @@ export class ProjectHooksService {
}
span?.setAttribute('project.slug', project.slug)
await this.eventEmitter.emitAsync('project.upsert', project)
await this.logs.addLog({
action: 'Replay hooks for Project',
data: {
args: {
projectId,
},
messageResume: `Hooks du projet rejoués: ${project.slug}`,
results: {
projectId: project.id,
slug: project.slug,
},
},
userId: requestorUserId,
await this.logProjectAction(
'Replay hooks for Project',
project,
`Hooks du projet rejoués: ${project.slug}`,
requestorUserId,
requestId,
projectId: project.id,
})
)
this.logger.log(`project.replayHooks completed (projectId=${projectId})`)
}
}
Loading