import { prisma } from '../config/database'; import { Prisma } from '@prisma/client'; import { config } from '../config'; import { logger } from '../config/logger'; import jwt from 'jsonwebtoken'; import { ListUsersResponse, GetUserResponse, ActivateAccount, UpdateUser, UpdateRoleResponse, DeactivateAccountResponse, ActivateAccountResponse, } from '../types/usersmanagement.types'; import { UserResponse } from '../types/user.types'; import { UnauthorizedError, ValidationError, ForbiddenError } from '../middleware/errorHandler'; export class UserManagementService { async listUsers(): Promise { try { const users = await prisma.user.findMany({ include: { profile: true, role: true } }); return { code: 200, message: 'Users fetched successfully', data: users.map(user => this.formatUserResponse(user)) }; } catch (error) { logger.error('Failed to fetch users', { error }); throw error; } } async getUserById(id: number): Promise { try { const user = await prisma.user.findUnique({ where: { id }, include: { role: true, profile: true } }); if (!user) throw new UnauthorizedError('User not found'); return { code: 200, message: 'User fetched successfully', data: this.formatUserResponse(user) }; } catch (error) { logger.error('Failed to fetch user by ID', { error }); throw error; } } async deactivateAccount(token: string): Promise { try { // Decode JWT token to get user ID const decoded = jwt.verify(token, config.jwt.secret) as { id: number; username: string; email: string; roleCode: string }; const user = await prisma.user.findUnique({ where: { id: decoded.id } }); if (!user) throw new UnauthorizedError('User not found'); // Check if account is already deactivated if (user.is_deactivated) { logger.warn('Deactivate attempt with deactivated account', { userId: user.id }); throw new ForbiddenError('This account has already been deactivated'); } // Deactivate account await prisma.user.update({ where: { id: user.id }, data: { is_deactivated: true } }); logger.info('Account deactivated successfully', { userId: user.id }); return { code: 200, message: 'Account deactivated successfully' }; } catch (error) { if (error instanceof jwt.JsonWebTokenError) { logger.error('Invalid JWT token:', error); throw new UnauthorizedError('Invalid token'); } if (error instanceof jwt.TokenExpiredError) { logger.error('JWT token expired:', error); throw new UnauthorizedError('Token expired'); } logger.error('Failed to deactivate account', { error }); throw error; } } async activateAccount(token: string): Promise { try { // Decode JWT token to get user ID const decoded = jwt.verify(token, config.jwt.secret) as { id: number; username: string; email: string; roleCode: string }; const user = await prisma.user.findUnique({ where: { id: decoded.id } }); if (!user) throw new UnauthorizedError('User not found'); // Check if account is already activated if (!user.is_deactivated) { logger.warn('Activate attempt with activated account', { userId: user.id }); throw new ForbiddenError('This account has already been activated'); } // Activate account await prisma.user.update({ where: { id: user.id }, data: { is_deactivated: false } }); logger.info('Account activated successfully', { userId: user.id }); return { code: 200, message: 'Account activated successfully' }; } catch (error) { if (error instanceof jwt.JsonWebTokenError) { logger.error('Invalid JWT token:', error); throw new UnauthorizedError('Invalid token'); } if (error instanceof jwt.TokenExpiredError) { logger.error('JWT token expired:', error); throw new UnauthorizedError('Token expired'); } logger.error('Failed to activate account', { error }); throw error; } } /** * Format user response */ private formatUserResponse(user: any): UserResponse { return { id: user.id, username: user.username, email: user.email, created_at: user.created_at, updated_at: user.updated_at, role: { code: user.role.code, name: user.role.name as { th: string; en: string } }, profile: user.profile ? { prefix: user.profile.prefix as { th?: string; en?: string } | undefined, first_name: user.profile.first_name, last_name: user.profile.last_name, avatar_url: user.profile.avatar_url, birth_date: user.profile.birth_date, phone: user.profile.phone } : undefined }; } }