- Extend audit.service.js with logging functions for projects, todos, companies, time tracking, and auth - Create audit.controller.js for fetching recent audit logs with user info - Create audit.routes.js with GET /api/audit-logs endpoint - Add audit logging to project, todo, company, time-tracking, and auth controllers - Log create/delete operations for projects, todos, companies - Log timer start/stop for time tracking - Log login/logout events 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
211 lines
4.8 KiB
JavaScript
211 lines
4.8 KiB
JavaScript
import * as todoService from '../services/todo.service.js';
|
|
import { logTodoCreated, logTodoDeleted, logTodoCompleted } from '../services/audit.service.js';
|
|
|
|
/**
|
|
* Get all todos
|
|
* GET /api/todos?search=query&projectId=xxx&companyId=xxx&assignedTo=xxx&status=xxx
|
|
*/
|
|
export const getAllTodos = async (req, res, next) => {
|
|
try {
|
|
const { search, projectId, companyId, assignedTo, status, completed, priority } = req.query;
|
|
|
|
// Handle both 'status' and 'completed' query params
|
|
let statusFilter = status;
|
|
if (completed !== undefined) {
|
|
statusFilter = completed === 'true' ? 'completed' : 'pending';
|
|
}
|
|
|
|
const filters = {
|
|
searchTerm: search,
|
|
projectId,
|
|
companyId,
|
|
assignedTo,
|
|
status: statusFilter,
|
|
priority,
|
|
};
|
|
|
|
const todos = await todoService.getAllTodos(filters);
|
|
|
|
res.status(200).json({
|
|
success: true,
|
|
count: todos.length,
|
|
data: todos,
|
|
});
|
|
} catch (error) {
|
|
return next(error);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Get my todos (assigned to current user)
|
|
* GET /api/todos/my?status=xxx
|
|
*/
|
|
export const getMyTodos = async (req, res, next) => {
|
|
try {
|
|
const userId = req.userId;
|
|
const { status } = req.query;
|
|
|
|
const filters = {
|
|
assignedTo: userId,
|
|
status,
|
|
};
|
|
|
|
const todos = await todoService.getAllTodos(filters);
|
|
|
|
res.status(200).json({
|
|
success: true,
|
|
count: todos.length,
|
|
data: todos,
|
|
});
|
|
} catch (error) {
|
|
return next(error);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Get todo by ID
|
|
* GET /api/todos/:todoId
|
|
*/
|
|
export const getTodoById = async (req, res, next) => {
|
|
try {
|
|
const { todoId } = req.params;
|
|
|
|
const todo = await todoService.getTodoById(todoId);
|
|
|
|
res.status(200).json({
|
|
success: true,
|
|
data: todo,
|
|
});
|
|
} catch (error) {
|
|
return next(error);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Get todo with relations (project, company, assigned user, notes)
|
|
* GET /api/todos/:todoId/details
|
|
*/
|
|
export const getTodoWithRelations = async (req, res, next) => {
|
|
try {
|
|
const { todoId } = req.params;
|
|
|
|
const todo = await todoService.getTodoWithRelations(todoId);
|
|
|
|
res.status(200).json({
|
|
success: true,
|
|
data: todo,
|
|
});
|
|
} catch (error) {
|
|
return next(error);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Create new todo
|
|
* POST /api/todos
|
|
* Body: { title, description, projectId, companyId, assignedUserIds, status, priority, dueDate }
|
|
*/
|
|
export const createTodo = async (req, res, next) => {
|
|
try {
|
|
const userId = req.userId;
|
|
const data = req.body;
|
|
|
|
console.log('Backend received todo data:', data);
|
|
const todo = await todoService.createTodo(userId, data);
|
|
|
|
// Log audit event
|
|
await logTodoCreated(userId, todo.id, todo.title, req.ip, req.headers['user-agent']);
|
|
|
|
res.status(201).json({
|
|
success: true,
|
|
data: todo,
|
|
message: 'Todo bolo vytvorené',
|
|
});
|
|
} catch (error) {
|
|
return next(error);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Update todo
|
|
* PATCH /api/todos/:todoId
|
|
* Body: { title, description, projectId, companyId, assignedUserIds, status, priority, dueDate }
|
|
*/
|
|
export const updateTodo = async (req, res, next) => {
|
|
try {
|
|
const { todoId } = req.params;
|
|
const data = req.body;
|
|
|
|
console.log('Backend received update data:', data);
|
|
const todo = await todoService.updateTodo(todoId, data);
|
|
|
|
res.status(200).json({
|
|
success: true,
|
|
data: todo,
|
|
message: 'Todo bolo aktualizované',
|
|
});
|
|
} catch (error) {
|
|
return next(error);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Delete todo
|
|
* DELETE /api/todos/:todoId
|
|
*/
|
|
export const deleteTodo = async (req, res, next) => {
|
|
try {
|
|
const { todoId } = req.params;
|
|
const userId = req.userId;
|
|
|
|
// Get todo info before deleting
|
|
const todo = await todoService.getTodoById(todoId);
|
|
const todoTitle = todo?.title;
|
|
|
|
const result = await todoService.deleteTodo(todoId);
|
|
|
|
// Log audit event
|
|
await logTodoDeleted(userId, todoId, todoTitle, req.ip, req.headers['user-agent']);
|
|
|
|
res.status(200).json({
|
|
success: true,
|
|
message: result.message,
|
|
});
|
|
} catch (error) {
|
|
return next(error);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Toggle todo completion status
|
|
* PATCH /api/todos/:todoId/toggle
|
|
*/
|
|
export const toggleTodo = async (req, res, next) => {
|
|
try {
|
|
const { todoId } = req.params;
|
|
const userId = req.userId;
|
|
|
|
// Get current todo
|
|
const todo = await todoService.getTodoById(todoId);
|
|
const wasCompleted = todo.status === 'completed';
|
|
|
|
// Toggle completed status
|
|
const updated = await todoService.updateTodo(todoId, {
|
|
status: wasCompleted ? 'pending' : 'completed',
|
|
});
|
|
|
|
// Log audit event if todo was completed
|
|
if (!wasCompleted) {
|
|
await logTodoCompleted(userId, todoId, todo.title, req.ip, req.headers['user-agent']);
|
|
}
|
|
|
|
res.status(200).json({
|
|
success: true,
|
|
data: updated,
|
|
message: 'Todo status aktualizovaný',
|
|
});
|
|
} catch (error) {
|
|
return next(error);
|
|
}
|
|
};
|