refactor: Move audit logging from controllers into services

Add auditContext parameter to service mutating functions. Services now
call audit log functions internally when auditContext is provided.
Controllers pass { userId, ipAddress, userAgent } and no longer import
audit service or fetch extra data for audit purposes.

Files modified:
- 10 service files: added audit imports and auditContext parameter
- 9 controller files: removed audit imports and calls

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
richardtekula
2026-01-28 07:39:41 +01:00
parent caab86079e
commit 3aba6c2955
19 changed files with 315 additions and 430 deletions

View File

@@ -5,6 +5,9 @@ import { NotFoundError } from '../utils/errors.js';
import { getAccessibleResourceIds } from '../middlewares/auth/resourceAccessMiddleware.js';
import { sendPushNotificationToUsers } from './push.service.js';
import { logger } from '../utils/logger.js';
import {
logTodoCreated, logTodoDeleted, logTodoCompleted, logTodoUpdated, logTodoUncompleted,
} from './audit.service.js';
/**
* Get all todos
@@ -142,7 +145,7 @@ export const getTodoById = async (todoId) => {
* @param {string} userId - ID of user creating the todo
* @param {object} data - Todo data including assignedUserIds array
*/
export const createTodo = async (userId, data) => {
export const createTodo = async (userId, data, auditContext = null) => {
const { title, description, projectId, companyId, assignedUserIds, status, priority, dueDate } = data;
// Verify project exists if provided
@@ -228,6 +231,10 @@ export const createTodo = async (userId, data) => {
}
}
if (auditContext) {
await logTodoCreated(auditContext.userId, newTodo.id, newTodo.title, auditContext.ipAddress, auditContext.userAgent);
}
return newTodo;
};
@@ -237,7 +244,7 @@ export const createTodo = async (userId, data) => {
* @param {object} data - Updated data including assignedUserIds array
* @param {string} updatedByUserId - ID of user making the update (for notifications)
*/
export const updateTodo = async (todoId, data, updatedByUserId = null) => {
export const updateTodo = async (todoId, data, updatedByUserId = null, auditContext = null) => {
const todo = await getTodoById(todoId);
const { title, description, projectId, companyId, assignedUserIds, status, priority, dueDate } = data;
@@ -352,17 +359,32 @@ export const updateTodo = async (todoId, data, updatedByUserId = null) => {
}
}
if (auditContext) {
// Detect status changes for specific audit events
if (status === 'completed' && todo.status !== 'completed') {
await logTodoCompleted(auditContext.userId, todoId, todo.title, auditContext.ipAddress, auditContext.userAgent);
} else if (status && status !== 'completed' && todo.status === 'completed') {
await logTodoUncompleted(auditContext.userId, todoId, todo.title, auditContext.ipAddress, auditContext.userAgent);
} else {
await logTodoUpdated(auditContext.userId, todoId, { title: todo.title }, { title: updated.title }, auditContext.ipAddress, auditContext.userAgent);
}
}
return updated;
};
/**
* Delete todo
*/
export const deleteTodo = async (todoId) => {
await getTodoById(todoId); // Check if exists
export const deleteTodo = async (todoId, auditContext = null) => {
const todo = await getTodoById(todoId); // Check if exists
await db.delete(todos).where(eq(todos.id, todoId));
if (auditContext) {
await logTodoDeleted(auditContext.userId, todoId, todo.title, auditContext.ipAddress, auditContext.userAgent);
}
return { success: true, message: 'Todo bolo odstránené' };
};