This commit is contained in:
2025-10-05 11:57:43 +07:00
parent 754e494e7f
commit 670228b76e
52 changed files with 39264 additions and 331 deletions

205
backend/src/routes/users.js Normal file → Executable file
View File

@@ -1,136 +1,99 @@
// File: backend/src/routes/users.js
import { Router } from "express";
import { User, Role } from "../db/sequelize.js";
import { authJwt, permGuard } from "../middleware/index.js";
import { hashPassword } from "../utils/passwords.js";
import { Router } from 'express';
import { User, Role } from '../db/sequelize.js';
import { authJwt } from "../middleware/authJwt.js";
import { loadPrincipalMw } from "../middleware/loadPrincipal.js"; // แก้ไข: import ให้ถูกต้อง
import { requirePerm } from '../middleware/requirePerm.js';
import { hashPassword } from '../utils/passwords.js';
const router = Router();
// Middleware สำหรับทุก route ในไฟล์นี้
router.use(authJwt.verifyToken);
// Middleware Chain ที่ถูกต้อง 100%
router.use(authJwt(), loadPrincipalMw());
// GET /api/users - ดึงรายชื่อผู้ใช้ทั้งหมด
router.get(
"/",
permGuard("manage_users"), // ตรวจสอบสิทธิ์
async (req, res, next) => {
// GET /api/users
router.get('/', requirePerm('users.view'), async (req, res, next) => {
try {
const users = await User.findAll({
attributes: { exclude: ["password_hash"] }, // **สำคัญมาก: ห้ามส่ง password hash ออกไป**
include: [
{
model: Role,
attributes: ["id", "name"],
through: { attributes: [] }, // ไม่ต้องเอาข้อมูลจากตาราง join (UserRoles) มา
},
],
order: [["username", "ASC"]],
});
res.json(users);
const users = await User.findAll({
attributes: { exclude: ['password_hash'] },
include: [{ model: Role, attributes: ['id', 'name'], through: { attributes: [] } }],
order: [['username', 'ASC']]
});
res.json(users);
} catch (error) { next(error); }
});
// POST /api/users
router.post('/', requirePerm('users.manage'), async (req, res, next) => {
const { username, email, password, first_name, last_name, is_active, roles } = req.body;
if (!username || !email || !password) {
return res.status(400).json({ message: 'Username, email, and password are required' });
}
try {
const password_hash = await hashPassword(password);
const newUser = await User.create({
username, email, password_hash, first_name, last_name, is_active: is_active !== false,
created_by: req.principal.user_id,
updated_by: req.principal.user_id,
org_id: req.principal.org_ids[0] || null,
});
if (roles && roles.length > 0) {
await newUser.setRoles(roles);
}
const userWithRoles = await User.findByPk(newUser.id, {
attributes: { exclude: ['password_hash'] },
include: [{ model: Role, attributes: ['id', 'name'], through: { attributes: [] } }]
});
res.status(201).json(userWithRoles);
} catch (error) {
next(error);
if (error.name === 'SequelizeUniqueConstraintError') {
return res.status(409).json({ message: 'Username or email already exists.' });
}
next(error);
}
}
);
// POST /api/users - สร้างผู้ใช้ใหม่
router.post("/", permGuard("manage_users"), async (req, res, next) => {
const { username, email, password, first_name, last_name, is_active, roles } =
req.body;
if (!username || !email || !password) {
return res
.status(400)
.json({ message: "Username, email, and password are required" });
}
try {
const password_hash = await hashPassword(password);
const newUser = await User.create({
username,
email,
password_hash,
first_name,
last_name,
is_active: is_active !== false,
});
if (roles && roles.length > 0) {
await newUser.setRoles(roles);
}
const userWithRoles = await User.findByPk(newUser.id, {
attributes: { exclude: ["password_hash"] },
include: [
{
model: Role,
attributes: ["id", "name"],
through: { attributes: [] },
},
],
});
res.status(201).json(userWithRoles);
} catch (error) {
if (error.name === "SequelizeUniqueConstraintError") {
return res
.status(409)
.json({ message: "Username or email already exists." });
}
next(error);
}
});
// PUT /api/users/:id - อัปเดตข้อมูลผู้ใช้
router.put("/:id", permGuard("manage_users"), async (req, res, next) => {
const { id } = req.params;
const { email, first_name, last_name, is_active, roles } = req.body;
// PUT /api/users/:id
router.put('/:id', requirePerm('users.manage'), async (req, res, next) => {
const { id } = req.params;
const { email, first_name, last_name, is_active, roles } = req.body;
try {
const user = await User.findByPk(id);
if (!user) {
return res.status(404).json({ message: 'User not found' });
}
user.email = email ?? user.email;
user.first_name = first_name ?? user.first_name;
user.last_name = last_name ?? user.last_name;
user.is_active = is_active ?? user.is_active;
user.updated_by = req.principal.user_id;
await user.save();
try {
const user = await User.findByPk(id);
if (!user) {
return res.status(404).json({ message: "User not found" });
}
user.email = email ?? user.email;
user.first_name = first_name ?? user.first_name;
user.last_name = last_name ?? user.last_name;
user.is_active = is_active ?? user.is_active;
await user.save();
if (roles) {
await user.setRoles(roles);
}
const updatedUser = await User.findByPk(id, {
attributes: { exclude: ["password_hash"] },
include: [
{
model: Role,
attributes: ["id", "name"],
through: { attributes: [] },
},
],
});
res.json(updatedUser);
} catch (error) {
next(error);
}
if (roles) {
await user.setRoles(roles);
}
const updatedUser = await User.findByPk(id, {
attributes: { exclude: ['password_hash'] },
include: [{ model: Role, attributes: ['id', 'name'], through: { attributes: [] } }]
});
res.json(updatedUser);
} catch (error) { next(error); }
});
// DELETE /api/users/:id - ลบผู้ใช้ (Soft Delete)
router.delete("/:id", permGuard("manage_users"), async (req, res, next) => {
try {
const user = await User.findByPk(req.params.id);
if (!user) {
return res.status(404).json({ message: "User not found" });
}
user.is_active = false; // Soft Delete
await user.save();
res.status(204).send();
} catch (error) {
next(error);
}
// DELETE /api/users/:id
router.delete('/:id', requirePerm('users.manage'), async (req, res, next) => {
try {
const user = await User.findByPk(req.params.id);
if (!user) {
return res.status(404).json({ message: 'User not found' });
}
user.is_active = false;
user.updated_by = req.principal.user_id;
await user.save();
res.status(204).send();
} catch (error) { next(error); }
});
export default router;
export default router;