// src/modules/user/service/user.service.ts import bcrypt from "bcryptjs"; import { Op } from "sequelize"; import { User } from "../../../models/User"; type CreateUserDTO = { fullname: string; email: string; password: string; roleId: string; isActive?: boolean; }; type UpdateUserDTO = Partial<{ fullname: string; email: string; password: string; roleId: string; isActive: boolean; }>; class UserServiceClass { private async hashPassword(password: string) { const saltRounds = 10; return await bcrypt.hash(password, saltRounds); } private sanitize(user: User) { const json = user.toJSON() as any; delete json.password; return json; } async create(data: CreateUserDTO) { const exists = await User.findOne({ where: { email: data.email } }); if (exists) throw new Error("ایمیل تکراری است"); const hashed = await this.hashPassword(data.password); const user = await User.create({ fullname: data.fullname, email: data.email, password: hashed, roleId: data.roleId, isActive: data.isActive ?? true, }); return this.sanitize(user); } async getAll(query?: { search?: string; isActive?: boolean }) { const where: any = {}; if (typeof query?.isActive === "boolean") where.isActive = query.isActive; if (query?.search) { where[Op.or] = [ { fullname: { [Op.iLike]: `%${query.search}%` } }, { email: { [Op.iLike]: `%${query.search}%` } }, ]; } const users = await User.findAll({ where, order: [["createdAt", "DESC"]], // اگر relation Role را attach کرده‌اید: // include: [{ association: "role" }], }); return users.map((u:any) => this.sanitize(u)); } async getById(id: string) { const user = await User.findByPk(id); if (!user) throw new Error("کاربر یافت نشد"); return this.sanitize(user); } async update(id: string, data: UpdateUserDTO) { const user = await User.findByPk(id); if (!user) throw new Error("کاربر یافت نشد"); // اگر ایمیل تغییر می‌کند، تکراری نبودن را چک کن if (data.email && data.email !== user.email) { const exists = await User.findOne({ where: { email: data.email } }); if (exists) throw new Error("ایمیل تکراری است"); } const updatePayload: any = { ...data }; if (typeof data.password === "string" && data.password.trim().length > 0) { updatePayload.password = await this.hashPassword(data.password); } else { delete updatePayload.password; } await user.update(updatePayload); return this.sanitize(user); } async toggleActive(id: string, isActive: boolean) { const user = await User.findByPk(id); if (!user) throw new Error("کاربر یافت نشد"); await user.update({ isActive }); return this.sanitize(user); } async remove(id: string) { const user = await User.findByPk(id); if (!user) throw new Error("کاربر یافت نشد"); await user.destroy(); return true; } // Auth: لاگین با ایمیل و پسورد async login(email: string, password: string) { const user = await User.findOne({ where: { email } }); if (!user) throw new Error("ایمیل یا رمز عبور اشتباه است"); if (!user.isActive) throw new Error("حساب کاربری غیرفعال است"); const ok = await bcrypt.compare(password, user.password); if (!ok) throw new Error("ایمیل یا رمز عبور اشتباه است"); // اینجا معمولاً JWT صادر می‌کنید؛ من فقط user sanitize برمی‌گردونم return this.sanitize(user); } } const UserService = new UserServiceClass() export default UserService;