import prisma from '../../lib/prisma'; import { UserDTO, UserRole } from '../../types'; import { hashPassword, verifyPassword } from '../../lib/auth'; export const UserService = { /** * Retrieves a user by ID with specific fields selected. */ async getUserById(id: string): Promise { const user = await prisma.user.findUnique({ where: { id }, select: { id: true, username: true, avatarUrl: true, role: true, status: true, createdAt: true, lastLogin: true } }); if (!user) return null; return { ...user, role: user.role as UserRole, // Cast Prisma enum to TS enum createdAt: user.createdAt.toISOString(), lastLogin: user.lastLogin?.toISOString() || new Date().toISOString(), avatarUrl: user.avatarUrl || '' }; }, /** * Get user by username (for login) */ async getUserByUsername(username: string) { return prisma.user.findUnique({ where: { username } }); }, /** * Get user by email */ async getUserByEmail(email: string) { return prisma.user.findUnique({ where: { email } }); }, /** * Create a new user with hashed password */ async createUser(username: string, password: string, email?: string) { const hashedPassword = await hashPassword(password); // Generate a random avatar URL using DiceBear or similar service const avatarUrl = `https://api.dicebear.com/7.x/avataaars/svg?seed=${username}`; return prisma.user.create({ data: { username, password: hashedPassword, email, avatarUrl, role: 'CREATOR', status: 'ACTIVE' } }); }, /** * Authenticate user with username and password * Returns user if credentials are valid, null otherwise */ async authenticateUser(username: string, password: string): Promise { const user = await this.getUserByUsername(username); if (!user || !user.password) { return null; } const isValid = await verifyPassword(password, user.password); if (!isValid) { return null; } // Update last login time await prisma.user.update({ where: { id: user.id }, data: { lastLogin: new Date() } }); // Return user DTO (without password) return { id: user.id, username: user.username, avatarUrl: user.avatarUrl || '', role: user.role as UserRole, status: user.status as any, createdAt: user.createdAt.toISOString(), lastLogin: new Date().toISOString() }; }, /** * Admin: Get all users */ async getAllUsers() { return prisma.user.findMany({ orderBy: { createdAt: 'desc' } }); }, /** * Updates user profile settings */ async updateUser(id: string, data: { username?: string; avatarUrl?: string }) { return prisma.user.update({ where: { id }, data: { username: data.username, avatarUrl: data.avatarUrl } }); }, /** * Admin: Update user role */ async updateUserRole(id: string, role: 'USER' | 'CREATOR' | 'MANAGER' | 'ADMIN') { return prisma.user.update({ where: { id }, data: { role } }); }, /** * Admin: Toggle Ban Status */ async toggleUserStatus(id: string) { const user = await prisma.user.findUnique({ where: { id } }); if (!user) throw new Error('User not found'); const newStatus = user.status === 'ACTIVE' ? 'BANNED' : 'ACTIVE'; return prisma.user.update({ where: { id }, data: { status: newStatus } }); } };