import { Response } from 'express'; import bcrypt from 'bcryptjs'; import prisma from '../config/database'; import { successResponse, errorResponse, paginatedResponse, parseQueryInt, getParam, getQueryString } from '../utils/helpers'; import { AuthRequest } from '../middleware/auth.middleware'; // Jednoduchý zoznam aktívnych používateľov (pre select/dropdown) // Podporuje server-side vyhľadávanie pre lepší výkon pri veľkom počte používateľov export const getUsersSimple = async (req: AuthRequest, res: Response): Promise => { try { const search = getQueryString(req, 'search'); const limit = parseQueryInt(req.query.limit, 50); // Default 50, max 100 const actualLimit = Math.min(limit, 100); const where = { active: true, ...(search && { OR: [ { name: { contains: search, mode: 'insensitive' as const } }, { email: { contains: search, mode: 'insensitive' as const } }, ], }), }; const users = await prisma.user.findMany({ where, take: actualLimit, orderBy: { name: 'asc' }, select: { id: true, name: true, email: true, }, }); successResponse(res, users); } catch (error) { console.error('Error fetching users simple:', error); errorResponse(res, 'Chyba pri načítaní používateľov.', 500); } }; export const getUsers = async (req: AuthRequest, res: Response): Promise => { try { const page = parseQueryInt(req.query.page, 1); const limit = parseQueryInt(req.query.limit, 20); const skip = (page - 1) * limit; const search = getQueryString(req, 'search'); const active = getQueryString(req, 'active'); const roleId = getQueryString(req, 'roleId'); const where = { ...(active !== undefined && { active: active === 'true' }), ...(roleId && { roleId }), ...(search && { OR: [ { name: { contains: search, mode: 'insensitive' as const } }, { email: { contains: search, mode: 'insensitive' as const } }, ], }), }; const [users, total] = await Promise.all([ prisma.user.findMany({ where, skip, take: limit, orderBy: { createdAt: 'desc' }, select: { id: true, email: true, name: true, active: true, createdAt: true, updatedAt: true, role: { select: { id: true, code: true, name: true, }, }, }, }), prisma.user.count({ where }), ]); paginatedResponse(res, users, total, page, limit); } catch (error) { console.error('Error fetching users:', error); errorResponse(res, 'Chyba pri načítaní používateľov.', 500); } }; export const getUser = async (req: AuthRequest, res: Response): Promise => { try { const id = getParam(req, 'id'); const user = await prisma.user.findUnique({ where: { id }, select: { id: true, email: true, name: true, active: true, createdAt: true, updatedAt: true, role: { select: { id: true, code: true, name: true, permissions: true, }, }, }, }); if (!user) { errorResponse(res, 'Používateľ nebol nájdený.', 404); return; } successResponse(res, user); } catch (error) { console.error('Error fetching user:', error); errorResponse(res, 'Chyba pri načítaní používateľa.', 500); } }; export const updateUser = async (req: AuthRequest, res: Response): Promise => { try { const id = getParam(req, 'id'); const { email, name, active, password } = req.body; const existingUser = await prisma.user.findUnique({ where: { id } }); if (!existingUser) { errorResponse(res, 'Používateľ nebol nájdený.', 404); return; } // Check email uniqueness if changing if (email && email !== existingUser.email) { const emailExists = await prisma.user.findUnique({ where: { email } }); if (emailExists) { errorResponse(res, 'Email je už používaný.', 409); return; } } const updateData: Record = {}; if (email) updateData.email = email; if (name) updateData.name = name; if (active !== undefined) updateData.active = active; if (password) updateData.password = await bcrypt.hash(password, 10); const user = await prisma.user.update({ where: { id }, data: updateData, select: { id: true, email: true, name: true, active: true, role: { select: { id: true, code: true, name: true, }, }, }, }); if (req.logActivity) { await req.logActivity('UPDATE', 'User', id, updateData); } successResponse(res, user, 'Používateľ bol aktualizovaný.'); } catch (error) { console.error('Error updating user:', error); errorResponse(res, 'Chyba pri aktualizácii používateľa.', 500); } }; export const deleteUser = async (req: AuthRequest, res: Response): Promise => { try { const id = getParam(req, 'id'); // Prevent self-deletion if (req.user?.userId === id) { errorResponse(res, 'Nemôžete vymazať vlastný účet.', 400); return; } const user = await prisma.user.findUnique({ where: { id } }); if (!user) { errorResponse(res, 'Používateľ nebol nájdený.', 404); return; } // Soft delete - just deactivate await prisma.user.update({ where: { id }, data: { active: false }, }); if (req.logActivity) { await req.logActivity('DELETE', 'User', id); } successResponse(res, null, 'Používateľ bol deaktivovaný.'); } catch (error) { console.error('Error deleting user:', error); errorResponse(res, 'Chyba pri mazaní používateľa.', 500); } }; export const updateUserRole = async (req: AuthRequest, res: Response): Promise => { try { const id = getParam(req, 'id'); const { roleId } = req.body; // Prevent changing own role if (req.user?.userId === id) { errorResponse(res, 'Nemôžete zmeniť vlastnú rolu.', 400); return; } const user = await prisma.user.findUnique({ where: { id } }); if (!user) { errorResponse(res, 'Používateľ nebol nájdený.', 404); return; } const role = await prisma.userRole.findUnique({ where: { id: roleId } }); if (!role) { errorResponse(res, 'Rola neexistuje.', 404); return; } const updatedUser = await prisma.user.update({ where: { id }, data: { roleId }, select: { id: true, email: true, name: true, role: { select: { id: true, code: true, name: true, }, }, }, }); if (req.logActivity) { await req.logActivity('UPDATE', 'User', id, { roleId, roleName: role.name }); } successResponse(res, updatedUser, 'Rola používateľa bola zmenená.'); } catch (error) { console.error('Error updating user role:', error); errorResponse(res, 'Chyba pri zmene roly.', 500); } };