Files
lcbp3.np-dms.work/backend/src/middleware/auth.js
2025-10-04 23:55:15 +07:00

62 lines
2.0 KiB
JavaScript
Executable File

// FILE: backend/src/middleware/auth.js
import jwt from "jsonwebtoken";
import { config } from "../config.js";
import { User, Role, UserRole } from "../db/sequelize.js";
export function signAccessToken(payload) {
return jwt.sign(payload, config.JWT.SECRET, {
expiresIn: config.JWT.EXPIRES_IN,
});
}
export function signRefreshToken(payload) {
return jwt.sign(payload, config.JWT.REFRESH_SECRET, {
expiresIn: config.JWT.REFRESH_EXPIRES_IN,
});
}
export function extractToken(req) {
// ให้คุกกี้มาก่อน แล้วค่อย Bearer (รองรับทั้งสองทาง)
const cookieTok = req.cookies?.access_token || null;
if (cookieTok) return cookieTok;
const hdr = req.headers.authorization || "";
return hdr.startsWith("Bearer ") ? hdr.slice(7) : null;
}
export function requireAuth(req, res, next) {
if (req.path === "/health") return next(); // อนุญาต health เสมอ
const token = extractToken(req);
if (!token) return res.status(401).json({ error: "Missing token" });
try {
req.user = jwt.verify(token, config.JWT.SECRET);
next();
} catch {
return res.status(401).json({ error: "Invalid/Expired token" });
}
}
// ใช้กับเส้นทางที่ login แล้วจะ enrich ต่อได้ แต่ไม่บังคับ
export function optionalAuth(req, _res, next) {
const token = extractToken(req);
if (!token) return next();
try {
req.user = jwt.verify(token, config.JWT.SECRET);
} catch {}
next();
}
export async function enrichRoles(req, _res, next) {
if (!req.user?.user_id) return next();
const rows = await UserRole.findAll({
where: { user_id: req.user.user_id },
include: [{ model: Role }],
}).catch(() => []);
req.user.roles = rows.map((r) => r.role?.role_name).filter(Boolean);
next();
}
export function hasPerm(req, perm) {
const set = new Set(req?.user?.permissions || []);
return set.has(perm);
}