Merge remote-tracking branch 'upstream/main'
All checks were successful
Build and Push Images / build-and-push (push) Successful in 8m28s

This commit is contained in:
kjs
2025-12-30 15:37:37 +09:00
33 changed files with 4326 additions and 4055 deletions

View File

@@ -141,6 +141,110 @@ export class AuthController {
}
}
/**
* POST /api/auth/switch-company
* WACE 관리자 전용: 다른 회사로 전환
*/
static async switchCompany(req: Request, res: Response): Promise<void> {
try {
const { companyCode } = req.body;
const authHeader = req.get("Authorization");
const token = authHeader && authHeader.split(" ")[1];
if (!token) {
res.status(401).json({
success: false,
message: "인증 토큰이 필요합니다.",
error: { code: "TOKEN_MISSING" },
});
return;
}
// 현재 사용자 정보 확인
const currentUser = JwtUtils.verifyToken(token);
// WACE 관리자 권한 체크 (userType = "SUPER_ADMIN"만 확인)
// 이미 다른 회사로 전환한 상태(companyCode != "*")에서도 다시 전환 가능해야 함
if (currentUser.userType !== "SUPER_ADMIN") {
logger.warn(`회사 전환 권한 없음: userId=${currentUser.userId}, userType=${currentUser.userType}, companyCode=${currentUser.companyCode}`);
res.status(403).json({
success: false,
message: "회사 전환은 최고 관리자(SUPER_ADMIN)만 가능합니다.",
error: { code: "FORBIDDEN" },
});
return;
}
// 전환할 회사 코드 검증
if (!companyCode || companyCode.trim() === "") {
res.status(400).json({
success: false,
message: "전환할 회사 코드가 필요합니다.",
error: { code: "INVALID_INPUT" },
});
return;
}
logger.info(`=== WACE 관리자 회사 전환 ===`, {
userId: currentUser.userId,
originalCompanyCode: currentUser.companyCode,
targetCompanyCode: companyCode,
});
// 회사 코드 존재 여부 확인 (company_code가 "*"가 아닌 경우만)
if (companyCode !== "*") {
const { query } = await import("../database/db");
const companies = await query<any>(
"SELECT company_code, company_name FROM company_mng WHERE company_code = $1",
[companyCode]
);
if (companies.length === 0) {
res.status(404).json({
success: false,
message: "존재하지 않는 회사 코드입니다.",
error: { code: "COMPANY_NOT_FOUND" },
});
return;
}
}
// 새로운 JWT 토큰 발급 (company_code만 변경)
const newPersonBean: PersonBean = {
...currentUser,
companyCode: companyCode.trim(), // 전환할 회사 코드로 변경
};
const newToken = JwtUtils.generateToken(newPersonBean);
logger.info(`✅ 회사 전환 성공: ${currentUser.userId}${companyCode}`);
res.status(200).json({
success: true,
message: "회사 전환 완료",
data: {
token: newToken,
companyCode: companyCode.trim(),
},
});
} catch (error) {
logger.error(
`회사 전환 API 오류: ${error instanceof Error ? error.message : error}`
);
res.status(500).json({
success: false,
message: "회사 전환 중 오류가 발생했습니다.",
error: {
code: "SERVER_ERROR",
details:
error instanceof Error
? error.message
: "알 수 없는 오류가 발생했습니다.",
},
});
}
}
/**
* POST /api/auth/logout
* 기존 Java ApiLoginController.logout() 메서드 포팅
@@ -226,13 +330,14 @@ export class AuthController {
}
// 프론트엔드 호환성을 위해 더 많은 사용자 정보 반환
// ⚠️ JWT 토큰의 companyCode를 우선 사용 (회사 전환 기능 지원)
const userInfoResponse: any = {
userId: dbUserInfo.userId,
userName: dbUserInfo.userName || "",
deptName: dbUserInfo.deptName || "",
companyCode: dbUserInfo.companyCode || "ILSHIN",
company_code: dbUserInfo.companyCode || "ILSHIN", // 프론트엔드 호환성
userType: dbUserInfo.userType || "USER",
companyCode: userInfo.companyCode || dbUserInfo.companyCode || "ILSHIN", // JWT 토큰 우선
company_code: userInfo.companyCode || dbUserInfo.companyCode || "ILSHIN", // JWT 토큰 우선
userType: userInfo.userType || dbUserInfo.userType || "USER", // JWT 토큰 우선
userTypeName: dbUserInfo.userTypeName || "일반사용자",
email: dbUserInfo.email || "",
photo: dbUserInfo.photo,

View File

@@ -47,4 +47,10 @@ router.post("/refresh", AuthController.refreshToken);
*/
router.post("/signup", AuthController.signup);
/**
* POST /api/auth/switch-company
* WACE 관리자 전용: 다른 회사로 전환
*/
router.post("/switch-company", AuthController.switchCompany);
export default router;

View File

@@ -412,9 +412,9 @@ export class AdminService {
let queryParams: any[] = [userLang];
let paramIndex = 2;
if (userType === "SUPER_ADMIN" && userCompanyCode === "*") {
// SUPER_ADMIN: 권한 그룹 체크 없이 공통 메뉴 표시
logger.info("✅ 좌측 사이드바 (SUPER_ADMIN): 공통 메뉴 표시");
if (userType === "SUPER_ADMIN") {
// SUPER_ADMIN: 권한 그룹 체크 없이 해당 회사의 모든 메뉴 표시
logger.info(`✅ 좌측 사이드바 (SUPER_ADMIN): 회사 ${userCompanyCode}의 모든 메뉴 표시`);
authFilter = "";
unionFilter = "";
} else {