added modules & forms jobcaegory-jobrequest-referral-relation etc
This commit is contained in:
93
src/modules/user/controller/user.controller.ts
Normal file
93
src/modules/user/controller/user.controller.ts
Normal file
@@ -0,0 +1,93 @@
|
||||
// src/modules/user/controller/user.controller.ts
|
||||
import { NextFunction } from "express";
|
||||
import { Controller } from "../../../core/controller/main.controller";
|
||||
import { ServerResponse } from "../../../core/types";
|
||||
import UserService from "../service/user.service";
|
||||
|
||||
class UserControllerClass extends Controller {
|
||||
#service;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.#service = UserService;
|
||||
}
|
||||
|
||||
async create(req: any, res: ServerResponse, next: NextFunction) {
|
||||
try {
|
||||
const data = await this.#service.create(req.body);
|
||||
return res.status(201).json({ status: 201, data, message: "کاربر ساخته شد" });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
async getAll(req: any, res: ServerResponse, next: NextFunction) {
|
||||
try {
|
||||
const data = await this.#service.getAll({
|
||||
search: req.query.search as string | undefined,
|
||||
isActive: req.query.isActive !== undefined ? req.query.isActive === "true" : undefined,
|
||||
});
|
||||
|
||||
return res.status(200).json({ status: 200, data, message: "Ok" });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
async getOne(req: any, res: ServerResponse, next: NextFunction) {
|
||||
try {
|
||||
const data = await this.#service.getById(req.params.id);
|
||||
return res.status(200).json({ status: 200, data, message: "Ok" });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
async update(req: any, res: ServerResponse, next: NextFunction) {
|
||||
try {
|
||||
const data = await this.#service.update(req.params.id, req.body);
|
||||
return res.status(200).json({ status: 200, data, message: "آپدیت شد" });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
async toggleActive(req: any, res: ServerResponse, next: NextFunction) {
|
||||
try {
|
||||
const { isActive } = req.body as { isActive: boolean };
|
||||
const data = await this.#service.toggleActive(req.params.id, isActive);
|
||||
return res.status(200).json({ status: 200, data, message: "وضعیت بروزرسانی شد" });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
async remove(req: any, res: ServerResponse, next: NextFunction) {
|
||||
try {
|
||||
await this.#service.remove(req.params.id);
|
||||
return res.status(200).json({ status: 200, data: {}, message: "حذف شد" });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
// Auth: لاگین
|
||||
async login(req: any, res: ServerResponse, next: NextFunction) {
|
||||
try {
|
||||
const { email, password } = req.body;
|
||||
const user = await this.#service.login(email, password);
|
||||
|
||||
// اینجا JWT بسازید و برگردانید (اگر دارید)
|
||||
return res.status(200).json({
|
||||
status: 200,
|
||||
data: { user },
|
||||
message: "ورود موفق",
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const UserController = new UserControllerClass();
|
||||
export default UserController;
|
||||
18
src/modules/user/routes/user.routes.ts
Normal file
18
src/modules/user/routes/user.routes.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
// src/modules/user/routes/user.routes.ts
|
||||
import { Router } from "express";
|
||||
import UserController from "../controller/user.controller";
|
||||
|
||||
const userRouter = Router();
|
||||
|
||||
// Auth
|
||||
userRouter.post("/login", UserController.login.bind(UserController));
|
||||
|
||||
// CRUD (معمولاً باید پشت adminMiddleware باشد)
|
||||
userRouter.post("/", UserController.create.bind(UserController));
|
||||
userRouter.get("/", UserController.getAll.bind(UserController));
|
||||
userRouter.get("/:id", UserController.getOne.bind(UserController));
|
||||
userRouter.put("/:id", UserController.update.bind(UserController));
|
||||
userRouter.patch("/:id/active", UserController.toggleActive.bind(UserController));
|
||||
userRouter.delete("/:id", UserController.remove.bind(UserController));
|
||||
|
||||
export default userRouter;
|
||||
132
src/modules/user/service/user.service.ts
Normal file
132
src/modules/user/service/user.service.ts
Normal file
@@ -0,0 +1,132 @@
|
||||
// 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;
|
||||
Reference in New Issue
Block a user