diff --git a/src/routes/admin/questions.ts b/src/routes/admin/questions.ts index 8c0f042..0306f8c 100644 --- a/src/routes/admin/questions.ts +++ b/src/routes/admin/questions.ts @@ -91,8 +91,9 @@ export async function adminQuestionsRoutes(app: FastifyInstance) { preHandler: [app.authenticate, app.authenticateAdmin], }, async (req, reply) => { + const adminId = req.user!.id; const { questionId } = req.params as { questionId: string }; - await adminQuestionService.approve(questionId); + await adminQuestionService.approve(questionId, adminId); return reply.status(204).send(); }, ); @@ -105,8 +106,9 @@ export async function adminQuestionsRoutes(app: FastifyInstance) { preHandler: [app.authenticate, app.authenticateAdmin], }, async (req, reply) => { + const adminId = req.user!.id; const { questionId } = req.params as { questionId: string }; - await adminQuestionService.reject(questionId); + await adminQuestionService.reject(questionId, adminId); return reply.status(204).send(); }, ); @@ -119,9 +121,10 @@ export async function adminQuestionsRoutes(app: FastifyInstance) { preHandler: [app.authenticate, app.authenticateAdmin], }, async (req, reply) => { + const adminId = req.user!.id; const { questionId } = req.params as { questionId: string }; const body = req.body as EditQuestionInput; - const question = await adminQuestionService.edit(questionId, body); + const question = await adminQuestionService.edit(questionId, body, adminId); return reply.send(question); }, ); diff --git a/src/services/admin/admin-question.service.ts b/src/services/admin/admin-question.service.ts index 70c4080..882cd97 100644 --- a/src/services/admin/admin-question.service.ts +++ b/src/services/admin/admin-question.service.ts @@ -1,7 +1,7 @@ import { eq, asc, count } from 'drizzle-orm'; import type { NodePgDatabase } from 'drizzle-orm/node-postgres'; import type * as schema from '../../db/schema/index.js'; -import { questionBank } from '../../db/schema/index.js'; +import { questionBank, auditLogs } from '../../db/schema/index.js'; import { notFound } from '../../utils/errors.js'; import type { Stack, Level, QuestionType } from '../../db/schema/enums.js'; @@ -80,7 +80,7 @@ export class AdminQuestionService { }; } - async approve(questionId: string): Promise { + async approve(questionId: string, adminId: string): Promise { const [updated] = await this.db .update(questionBank) .set({ @@ -93,9 +93,16 @@ export class AdminQuestionService { if (!updated) { throw notFound('Question not found'); } + + await this.db.insert(auditLogs).values({ + adminId, + action: 'question_approved', + targetType: 'question', + targetId: questionId, + }); } - async reject(questionId: string): Promise { + async reject(questionId: string, adminId: string): Promise { const [updated] = await this.db .update(questionBank) .set({ status: 'rejected' }) @@ -105,9 +112,16 @@ export class AdminQuestionService { if (!updated) { throw notFound('Question not found'); } + + await this.db.insert(auditLogs).values({ + adminId, + action: 'question_rejected', + targetType: 'question', + targetId: questionId, + }); } - async edit(questionId: string, input: EditQuestionInput): Promise { + async edit(questionId: string, input: EditQuestionInput, adminId: string): Promise { const updates: Partial<{ stack: Stack; level: Level; @@ -156,6 +170,14 @@ export class AdminQuestionService { throw notFound('Question not found'); } + await this.db.insert(auditLogs).values({ + adminId, + action: 'question_edited', + targetType: 'question', + targetId: questionId, + details: updates as Record, + }); + return { id: updated.id, stack: updated.stack,