import { prisma } from "./db.server"; import { hashPassword } from "./auth.server"; import type { User } from "@prisma/client"; import type { CreateUserData, UpdateUserData, UserWithoutPassword } from "~/types/database"; import { AUTH_LEVELS, USER_STATUS } from "~/types/auth"; // Get all users with role-based filtering export async function getUsers( currentUserAuthLevel: number, searchQuery?: string, page: number = 1, limit: number = 10 ): Promise<{ users: UserWithoutPassword[]; total: number; totalPages: number; }> { const offset = (page - 1) * limit; // Build where clause based on current user's auth level const whereClause: any = {}; // Admins cannot see superadmin accounts if (currentUserAuthLevel === AUTH_LEVELS.ADMIN) { whereClause.authLevel = { gt: AUTH_LEVELS.SUPERADMIN, }; } // Add search functionality if (searchQuery) { const searchLower = searchQuery.toLowerCase(); whereClause.OR = [ { name: { contains: searchLower } }, { username: { contains: searchLower } }, { email: { contains: searchLower } }, ]; } const [users, total] = await Promise.all([ prisma.user.findMany({ where: whereClause, select: { id: true, name: true, username: true, email: true, status: true, authLevel: true, createdDate: true, editDate: true, }, orderBy: { createdDate: 'desc' }, skip: offset, take: limit, }), prisma.user.count({ where: whereClause }), ]); return { users, total, totalPages: Math.ceil(total / limit), }; } // Get user by ID with role-based access control export async function getUserById( id: number, currentUserAuthLevel: number ): Promise { const user = await prisma.user.findUnique({ where: { id }, select: { id: true, name: true, username: true, email: true, status: true, authLevel: true, createdDate: true, editDate: true, }, }); if (!user) return null; // Admins cannot access superadmin accounts if (currentUserAuthLevel === AUTH_LEVELS.ADMIN && user.authLevel === AUTH_LEVELS.SUPERADMIN) { return null; } return user; } // Create new user export async function createUser( userData: CreateUserData, currentUserAuthLevel: number ): Promise<{ success: boolean; user?: UserWithoutPassword; error?: string }> { try { // Validate that current user can create users with the specified auth level if (currentUserAuthLevel === AUTH_LEVELS.ADMIN && userData.authLevel === AUTH_LEVELS.SUPERADMIN) { return { success: false, error: "لا يمكن للمدير إنشاء حساب مدير عام" }; } // Check if username or email already exists const existingUser = await prisma.user.findFirst({ where: { OR: [ { username: userData.username }, { email: userData.email }, ], }, }); if (existingUser) { if (existingUser.username === userData.username) { return { success: false, error: "اسم المستخدم موجود بالفعل" }; } if (existingUser.email === userData.email) { return { success: false, error: "البريد الإلكتروني موجود بالفعل" }; } } // Hash password const hashedPassword = await hashPassword(userData.password); // Create user const user = await prisma.user.create({ data: { name: userData.name, username: userData.username, email: userData.email, password: hashedPassword, authLevel: userData.authLevel, status: userData.status || USER_STATUS.ACTIVE, }, select: { id: true, name: true, username: true, email: true, status: true, authLevel: true, createdDate: true, editDate: true, }, }); return { success: true, user }; } catch (error) { console.error("Error creating user:", error); return { success: false, error: "حدث خطأ أثناء إنشاء المستخدم" }; } } // Update user export async function updateUser( id: number, userData: UpdateUserData, currentUserAuthLevel: number ): Promise<{ success: boolean; user?: UserWithoutPassword; error?: string }> { try { // Get existing user to check permissions const existingUser = await getUserById(id, currentUserAuthLevel); if (!existingUser) { return { success: false, error: "المستخدم غير موجود أو لا يمكن الوصول إليه" }; } // Validate auth level changes if (userData.authLevel !== undefined) { if (currentUserAuthLevel === AUTH_LEVELS.ADMIN && userData.authLevel === AUTH_LEVELS.SUPERADMIN) { return { success: false, error: "لا يمكن للمدير تعيين مستوى مدير عام" }; } } // Check for username/email conflicts if (userData.username || userData.email) { const conflictUser = await prisma.user.findFirst({ where: { AND: [ { id: { not: id } }, { OR: [ userData.username ? { username: userData.username } : {}, userData.email ? { email: userData.email } : {}, ].filter(condition => Object.keys(condition).length > 0), }, ], }, }); if (conflictUser) { if (conflictUser.username === userData.username) { return { success: false, error: "اسم المستخدم موجود بالفعل" }; } if (conflictUser.email === userData.email) { return { success: false, error: "البريد الإلكتروني موجود بالفعل" }; } } } // Prepare update data const updateData: any = {}; if (userData.name !== undefined) updateData.name = userData.name; if (userData.username !== undefined) updateData.username = userData.username; if (userData.email !== undefined) updateData.email = userData.email; if (userData.authLevel !== undefined) updateData.authLevel = userData.authLevel; if (userData.status !== undefined) updateData.status = userData.status; // Hash new password if provided if (userData.password) { updateData.password = await hashPassword(userData.password); } // Update user const user = await prisma.user.update({ where: { id }, data: updateData, select: { id: true, name: true, username: true, email: true, status: true, authLevel: true, createdDate: true, editDate: true, }, }); return { success: true, user }; } catch (error) { console.error("Error updating user:", error); return { success: false, error: "حدث خطأ أثناء تحديث المستخدم" }; } } // Delete user export async function deleteUser( id: number, currentUserAuthLevel: number ): Promise<{ success: boolean; error?: string }> { try { // Get existing user to check permissions const existingUser = await getUserById(id, currentUserAuthLevel); if (!existingUser) { return { success: false, error: "المستخدم غير موجود أو لا يمكن الوصول إليه" }; } // Prevent deletion of superadmin by admin if (currentUserAuthLevel === AUTH_LEVELS.ADMIN && existingUser.authLevel === AUTH_LEVELS.SUPERADMIN) { return { success: false, error: "لا يمكن للمدير حذف حساب مدير عام" }; } // Check if this is the last superadmin if (existingUser.authLevel === AUTH_LEVELS.SUPERADMIN) { const superadminCount = await prisma.user.count({ where: { authLevel: AUTH_LEVELS.SUPERADMIN }, }); if (superadminCount <= 1) { return { success: false, error: "لا يمكن حذف آخر مدير عام في النظام" }; } } // Delete user await prisma.user.delete({ where: { id }, }); return { success: true }; } catch (error) { console.error("Error deleting user:", error); return { success: false, error: "حدث خطأ أثناء حذف المستخدم" }; } } // Toggle user status (active/inactive) export async function toggleUserStatus( id: number, currentUserAuthLevel: number ): Promise<{ success: boolean; user?: UserWithoutPassword; error?: string }> { try { const existingUser = await getUserById(id, currentUserAuthLevel); if (!existingUser) { return { success: false, error: "المستخدم غير موجود أو لا يمكن الوصول إليه" }; } const newStatus = existingUser.status === USER_STATUS.ACTIVE ? USER_STATUS.INACTIVE : USER_STATUS.ACTIVE; const user = await prisma.user.update({ where: { id }, data: { status: newStatus }, select: { id: true, name: true, username: true, email: true, status: true, authLevel: true, createdDate: true, editDate: true, }, }); return { success: true, user }; } catch (error) { console.error("Error toggling user status:", error); return { success: false, error: "حدث خطأ أثناء تغيير حالة المستخدم" }; } } // Get auth level display name export function getAuthLevelName(authLevel: number): string { switch (authLevel) { case AUTH_LEVELS.SUPERADMIN: return "مدير عام"; case AUTH_LEVELS.ADMIN: return "مدير"; case AUTH_LEVELS.USER: return "مستخدم"; default: return "غير محدد"; } } // Get status display name export function getStatusName(status: string): string { switch (status) { case USER_STATUS.ACTIVE: return "نشط"; case USER_STATUS.INACTIVE: return "غير نشط"; default: return "غير محدد"; } }