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 { body } = require("express-validator");
|
||||||
const validate = require("../../../middleware/validator.middleware");
|
const validate = require("../../../middleware/validator.middleware");
|
||||||
const authMiddleware = require("../../../middleware/auth.middleware");
|
const authMiddleware = require("../../../middleware/auth.middleware");
|
||||||
|
const logger = require("../../../config/logger");
|
||||||
|
|
||||||
router.post(
|
router.post(
|
||||||
"/login",
|
"/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;
|
module.exports = router;
|
||||||
|
@ -68,20 +68,11 @@ class AuthService {
|
|||||||
const companyData = userData.Company || {};
|
const companyData = userData.Company || {};
|
||||||
delete userData.Roles;
|
delete userData.Roles;
|
||||||
|
|
||||||
// const userInfo = {
|
|
||||||
// ...userData,
|
|
||||||
// companyName: companyData.name,
|
|
||||||
// businessNumber: companyData.businessNumber,
|
|
||||||
// contractEndDate: companyData.contractEndDate,
|
|
||||||
// permissions,
|
|
||||||
// };
|
|
||||||
const userInfo = {
|
const userInfo = {
|
||||||
...userData,
|
...userData,
|
||||||
companyId: companyData.id,
|
|
||||||
companyName: companyData.name,
|
companyName: companyData.name,
|
||||||
businessNumber: companyData.businessNumber,
|
businessNumber: companyData.businessNumber,
|
||||||
contractEndDate: companyData.contractEndDate,
|
contractEndDate: companyData.contractEndDate,
|
||||||
branchId: userData.Branch?.id,
|
|
||||||
branchName: userData.Branch?.name,
|
branchName: userData.Branch?.name,
|
||||||
permissions,
|
permissions,
|
||||||
};
|
};
|
||||||
@ -205,12 +196,38 @@ class AuthService {
|
|||||||
const userInfo = {
|
const userInfo = {
|
||||||
...userData,
|
...userData,
|
||||||
companyName: companyData.name,
|
companyName: companyData.name,
|
||||||
|
branchName: userData.Branch?.name,
|
||||||
businessNumber: companyData.businessNumber,
|
businessNumber: companyData.businessNumber,
|
||||||
contractEndDate: companyData.contractEndDate,
|
contractEndDate: companyData.contractEndDate,
|
||||||
permissions,
|
permissions,
|
||||||
isEdgeLogin: true, // Edge 로그인 여부 표시
|
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);
|
const token = this._generateToken(userInfo);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -333,6 +350,133 @@ class AuthService {
|
|||||||
expiresIn: config.jwt.expiresIn,
|
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();
|
module.exports = new AuthService();
|
||||||
|
@ -333,7 +333,7 @@ export function SideNav() {
|
|||||||
<Building2 className="h-5 w-5 text-gray-500 mt-0.5" />
|
<Building2 className="h-5 w-5 text-gray-500 mt-0.5" />
|
||||||
<div className="flex-1">
|
<div className="flex-1">
|
||||||
<h3 className="text-sm font-medium text-gray-900">
|
<h3 className="text-sm font-medium text-gray-900">
|
||||||
{user?.companyName}
|
{user?.companyName} - {user?.branchName}
|
||||||
</h3>
|
</h3>
|
||||||
<p className="text-xs text-gray-500">
|
<p className="text-xs text-gray-500">
|
||||||
사업자번호: {formatBusinessNumber(user?.businessNumber || "")}
|
사업자번호: {formatBusinessNumber(user?.businessNumber || "")}
|
||||||
|
@ -20,6 +20,7 @@ export interface User {
|
|||||||
businessNumber: string;
|
businessNumber: string;
|
||||||
contractEndDate: string;
|
contractEndDate: string;
|
||||||
branchId?: string;
|
branchId?: string;
|
||||||
|
branchName: string;
|
||||||
permissions: Permissions; // 권한 정보 추가
|
permissions: Permissions; // 권한 정보 추가
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@ export interface User {
|
|||||||
businessNumber: string;
|
businessNumber: string;
|
||||||
contractEndDate: string;
|
contractEndDate: string;
|
||||||
branchId?: string;
|
branchId?: string;
|
||||||
|
branchName: string;
|
||||||
departmentId?: string;
|
departmentId?: string;
|
||||||
roleId?: string;
|
roleId?: string;
|
||||||
Company?: {
|
Company?: {
|
||||||
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user