111
This commit is contained in:
parent
379e7fb6c2
commit
cc61bca776
@ -5,6 +5,7 @@ const authService = require("../../../services/auth.service");
|
||||
const { body } = require("express-validator");
|
||||
const validate = require("../../../middleware/validator.middleware");
|
||||
const authMiddleware = require("../../../middleware/auth.middleware");
|
||||
const logger = require("../../../config/logger");
|
||||
|
||||
router.post(
|
||||
"/login",
|
||||
@ -60,4 +61,65 @@ router.post(
|
||||
}
|
||||
);
|
||||
|
||||
// 토큰 검증 엔드포인트
|
||||
router.post("/validate", async (req, res, next) => {
|
||||
try {
|
||||
const token = req.headers.authorization?.replace("Bearer ", "");
|
||||
if (!token) {
|
||||
return res.status(401).json({
|
||||
valid: false,
|
||||
message: "Token is required",
|
||||
});
|
||||
}
|
||||
|
||||
const result = await authService.validateToken(token);
|
||||
res.json(result);
|
||||
} catch (error) {
|
||||
logger.error("Validate endpoint error:", {
|
||||
error: error.message,
|
||||
stack: error.stack,
|
||||
});
|
||||
|
||||
if (
|
||||
error.name === "JsonWebTokenError" ||
|
||||
error.name === "TokenExpiredError"
|
||||
) {
|
||||
return res.status(401).json({
|
||||
valid: false,
|
||||
message: error.message,
|
||||
});
|
||||
}
|
||||
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
|
||||
// 토큰 갱신 엔드포인트
|
||||
router.post("/refresh", async (req, res, next) => {
|
||||
try {
|
||||
const token = req.headers.authorization?.replace("Bearer ", "");
|
||||
if (!token) {
|
||||
return res.status(401).json({
|
||||
message: "Token is required",
|
||||
});
|
||||
}
|
||||
|
||||
const result = await authService.refreshToken(token);
|
||||
res.json(result);
|
||||
} catch (error) {
|
||||
logger.error("Refresh token endpoint error:", {
|
||||
error: error.message,
|
||||
stack: error.stack,
|
||||
});
|
||||
|
||||
if (error.name === "JsonWebTokenError") {
|
||||
return res.status(401).json({
|
||||
message: "Invalid token",
|
||||
});
|
||||
}
|
||||
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = router;
|
||||
|
@ -68,20 +68,11 @@ class AuthService {
|
||||
const companyData = userData.Company || {};
|
||||
delete userData.Roles;
|
||||
|
||||
// const userInfo = {
|
||||
// ...userData,
|
||||
// companyName: companyData.name,
|
||||
// businessNumber: companyData.businessNumber,
|
||||
// contractEndDate: companyData.contractEndDate,
|
||||
// permissions,
|
||||
// };
|
||||
const userInfo = {
|
||||
...userData,
|
||||
companyId: companyData.id,
|
||||
companyName: companyData.name,
|
||||
businessNumber: companyData.businessNumber,
|
||||
contractEndDate: companyData.contractEndDate,
|
||||
branchId: userData.Branch?.id,
|
||||
branchName: userData.Branch?.name,
|
||||
permissions,
|
||||
};
|
||||
@ -205,12 +196,38 @@ class AuthService {
|
||||
const userInfo = {
|
||||
...userData,
|
||||
companyName: companyData.name,
|
||||
branchName: userData.Branch?.name,
|
||||
businessNumber: companyData.businessNumber,
|
||||
contractEndDate: companyData.contractEndDate,
|
||||
permissions,
|
||||
isEdgeLogin: true, // Edge 로그인 여부 표시
|
||||
};
|
||||
|
||||
// const userInfo = {
|
||||
// // 기본 사용자 정보
|
||||
// id: userData.id,
|
||||
// username: userData.username,
|
||||
// name: userData.name,
|
||||
// email: userData.email,
|
||||
// phone: userData.phone,
|
||||
// role: userData.role,
|
||||
// isActive: userData.isActive,
|
||||
|
||||
// // 회사 정보
|
||||
// companyId: companyData.id,
|
||||
// companyName: companyData.name,
|
||||
// businessNumber: companyData.businessNumber,
|
||||
// contractEndDate: companyData.contractEndDate,
|
||||
|
||||
// // 지점 정보
|
||||
// branchId: userData.Branch?.id,
|
||||
// branchName: userData.Branch?.name,
|
||||
|
||||
// // 권한 및 기타 정보
|
||||
// permissions,
|
||||
// isEdgeLogin: true,
|
||||
// };
|
||||
|
||||
const token = this._generateToken(userInfo);
|
||||
|
||||
return {
|
||||
@ -333,6 +350,133 @@ class AuthService {
|
||||
expiresIn: config.jwt.expiresIn,
|
||||
});
|
||||
}
|
||||
|
||||
async validateToken(token) {
|
||||
try {
|
||||
const decoded = jwt.verify(token, config.jwt.secret);
|
||||
|
||||
const user = await User.findOne({
|
||||
where: { id: decoded.id },
|
||||
include: [
|
||||
{
|
||||
model: Company,
|
||||
attributes: ["id", "name", "businessNumber", "contractEndDate"],
|
||||
where: { isActive: true },
|
||||
},
|
||||
{
|
||||
model: Branch,
|
||||
attributes: ["id", "name"],
|
||||
},
|
||||
{
|
||||
model: Role,
|
||||
through: { attributes: [] },
|
||||
attributes: ["id", "name", "permissions"],
|
||||
required: false,
|
||||
},
|
||||
],
|
||||
attributes: {
|
||||
exclude: ["password"],
|
||||
},
|
||||
});
|
||||
|
||||
if (!user || !user.isActive) {
|
||||
throw new Error("User not found or inactive");
|
||||
}
|
||||
|
||||
// 권한 정보 가공
|
||||
const permissions = this._processPermissions(user.Roles || []);
|
||||
|
||||
// 사용자 정보 구성
|
||||
const userData = user.toJSON();
|
||||
const companyData = userData.Company || {};
|
||||
delete userData.Roles;
|
||||
|
||||
const userInfo = {
|
||||
...userData,
|
||||
companyId: companyData.id,
|
||||
companyName: companyData.name,
|
||||
businessNumber: companyData.businessNumber,
|
||||
contractEndDate: companyData.contractEndDate,
|
||||
branchId: userData.Branch?.id,
|
||||
branchName: userData.Branch?.name,
|
||||
permissions,
|
||||
};
|
||||
|
||||
return {
|
||||
valid: true,
|
||||
user: userInfo,
|
||||
};
|
||||
} catch (error) {
|
||||
logger.error("Token validation error:", error.message);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async refreshToken(token) {
|
||||
try {
|
||||
const decoded = jwt.verify(token, config.jwt.secret, {
|
||||
ignoreExpiration: true,
|
||||
});
|
||||
|
||||
const user = await User.findOne({
|
||||
where: { id: decoded.id },
|
||||
include: this._getUserIncludes(),
|
||||
});
|
||||
|
||||
if (!user || !user.isActive) {
|
||||
throw new Error("User not found or inactive");
|
||||
}
|
||||
|
||||
const userInfo = this._formatUserInfo(user);
|
||||
const newToken = this._generateToken(userInfo);
|
||||
|
||||
return {
|
||||
token: newToken,
|
||||
user: userInfo,
|
||||
};
|
||||
} catch (error) {
|
||||
logger.error("Token refresh error:", error.message);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
_getUserIncludes() {
|
||||
return [
|
||||
{
|
||||
model: Company,
|
||||
attributes: ["id", "name", "businessNumber", "contractEndDate"],
|
||||
where: { isActive: true },
|
||||
},
|
||||
{
|
||||
model: Branch,
|
||||
attributes: ["id", "name"],
|
||||
},
|
||||
{
|
||||
model: Role,
|
||||
through: { attributes: [] },
|
||||
attributes: ["id", "name", "permissions"],
|
||||
required: false,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
_formatUserInfo(user) {
|
||||
const userData = user.toJSON();
|
||||
const companyData = userData.Company || {};
|
||||
const permissions = this._processPermissions(userData.Roles || []);
|
||||
delete userData.Roles;
|
||||
|
||||
return {
|
||||
...userData,
|
||||
companyId: companyData.id,
|
||||
companyName: companyData.name,
|
||||
businessNumber: companyData.businessNumber,
|
||||
contractEndDate: companyData.contractEndDate,
|
||||
branchId: userData.Branch?.id,
|
||||
branchName: userData.Branch?.name,
|
||||
permissions,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = new AuthService();
|
||||
|
@ -333,7 +333,7 @@ export function SideNav() {
|
||||
<Building2 className="h-5 w-5 text-gray-500 mt-0.5" />
|
||||
<div className="flex-1">
|
||||
<h3 className="text-sm font-medium text-gray-900">
|
||||
{user?.companyName}
|
||||
{user?.companyName} - {user?.branchName}
|
||||
</h3>
|
||||
<p className="text-xs text-gray-500">
|
||||
사업자번호: {formatBusinessNumber(user?.businessNumber || "")}
|
||||
|
@ -20,6 +20,7 @@ export interface User {
|
||||
businessNumber: string;
|
||||
contractEndDate: string;
|
||||
branchId?: string;
|
||||
branchName: string;
|
||||
permissions: Permissions; // 권한 정보 추가
|
||||
}
|
||||
|
||||
|
@ -13,6 +13,7 @@ export interface User {
|
||||
businessNumber: string;
|
||||
contractEndDate: string;
|
||||
branchId?: string;
|
||||
branchName: string;
|
||||
departmentId?: string;
|
||||
roleId?: string;
|
||||
Company?: {
|
||||
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user