ERP-node/backend-node/src/middleware/permissionMiddleware.ts

431 lines
10 KiB
TypeScript

/**
* 권한 체크 미들웨어
* 3단계 권한 체계 적용: SUPER_ADMIN / COMPANY_ADMIN / USER
*/
import { Request, Response, NextFunction } from "express";
import { PersonBean } from "../types/auth";
import {
isSuperAdmin,
isCompanyAdmin,
isAdmin,
canExecuteDDL,
canManageUsers,
canManageCompanySettings,
canManageCompanies,
canAccessCompanyData,
PermissionLevel,
createPermissionError,
} from "../utils/permissionUtils";
import { logger } from "../utils/logger";
/**
* 인증된 요청 타입
*/
export interface AuthenticatedRequest extends Request {
user?: PersonBean;
}
/**
* 슈퍼관리자 권한 필수 미들웨어
*/
export const requireSuperAdmin = (
req: AuthenticatedRequest,
res: Response,
next: NextFunction
): void => {
try {
if (!req.user) {
logger.warn("슈퍼관리자 권한 필요 - 인증되지 않은 사용자", {
ip: req.ip,
url: req.originalUrl,
});
res.status(401).json({
success: false,
error: {
code: "AUTHENTICATION_REQUIRED",
details: "인증이 필요합니다.",
},
});
return;
}
if (!isSuperAdmin(req.user)) {
logger.warn("슈퍼관리자 권한 부족", {
userId: req.user.userId,
companyCode: req.user.companyCode,
userType: req.user.userType,
ip: req.ip,
url: req.originalUrl,
});
res.status(403).json(createPermissionError(PermissionLevel.SUPER_ADMIN));
return;
}
logger.info("슈퍼관리자 권한 확인 완료", {
userId: req.user.userId,
url: req.originalUrl,
});
next();
} catch (error) {
logger.error("슈퍼관리자 권한 확인 중 오류:", error);
res.status(500).json({
success: false,
error: {
code: "AUTHORIZATION_ERROR",
details: "권한 확인 중 오류가 발생했습니다.",
},
});
}
};
/**
* 관리자 권한 필수 미들웨어 (슈퍼관리자 + 회사관리자)
*/
export const requireAdmin = (
req: AuthenticatedRequest,
res: Response,
next: NextFunction
): void => {
try {
if (!req.user) {
res.status(401).json({
success: false,
error: {
code: "AUTHENTICATION_REQUIRED",
details: "인증이 필요합니다.",
},
});
return;
}
if (!isAdmin(req.user)) {
logger.warn("관리자 권한 부족", {
userId: req.user.userId,
userType: req.user.userType,
companyCode: req.user.companyCode,
ip: req.ip,
url: req.originalUrl,
});
res
.status(403)
.json(createPermissionError(PermissionLevel.COMPANY_ADMIN));
return;
}
logger.info("관리자 권한 확인 완료", {
userId: req.user.userId,
userType: req.user.userType,
url: req.originalUrl,
});
next();
} catch (error) {
logger.error("관리자 권한 확인 중 오류:", error);
res.status(500).json({
success: false,
error: {
code: "AUTHORIZATION_ERROR",
details: "권한 확인 중 오류가 발생했습니다.",
},
});
}
};
/**
* 회사 데이터 접근 권한 체크 미들웨어
* req.params.companyCode 또는 req.query.companyCode 확인
*/
export const requireCompanyAccess = (
req: AuthenticatedRequest,
res: Response,
next: NextFunction
): void => {
try {
if (!req.user) {
res.status(401).json({
success: false,
error: {
code: "AUTHENTICATION_REQUIRED",
details: "인증이 필요합니다.",
},
});
return;
}
const targetCompanyCode =
(req.params.companyCode as string) ||
(req.query.companyCode as string) ||
(req.body.companyCode as string);
if (!targetCompanyCode) {
res.status(400).json({
success: false,
error: {
code: "COMPANY_CODE_REQUIRED",
details: "회사 코드가 필요합니다.",
},
});
return;
}
if (!canAccessCompanyData(req.user, targetCompanyCode)) {
logger.warn("회사 데이터 접근 권한 없음", {
userId: req.user.userId,
userCompanyCode: req.user.companyCode,
targetCompanyCode,
ip: req.ip,
url: req.originalUrl,
});
res.status(403).json({
success: false,
error: {
code: "COMPANY_ACCESS_DENIED",
details: "해당 회사의 데이터에 접근할 권한이 없습니다.",
},
});
return;
}
next();
} catch (error) {
logger.error("회사 데이터 접근 권한 확인 중 오류:", error);
res.status(500).json({
success: false,
error: {
code: "AUTHORIZATION_ERROR",
details: "권한 확인 중 오류가 발생했습니다.",
},
});
}
};
/**
* 사용자 관리 권한 체크 미들웨어
*/
export const requireUserManagement = (
req: AuthenticatedRequest,
res: Response,
next: NextFunction
): void => {
try {
if (!req.user) {
res.status(401).json({
success: false,
error: {
code: "AUTHENTICATION_REQUIRED",
details: "인증이 필요합니다.",
},
});
return;
}
const targetCompanyCode =
(req.params.companyCode as string) ||
(req.query.companyCode as string) ||
(req.body.companyCode as string);
if (!canManageUsers(req.user, targetCompanyCode)) {
logger.warn("사용자 관리 권한 없음", {
userId: req.user.userId,
userCompanyCode: req.user.companyCode,
targetCompanyCode,
ip: req.ip,
url: req.originalUrl,
});
res.status(403).json({
success: false,
error: {
code: "USER_MANAGEMENT_DENIED",
details: "사용자 관리 권한이 없습니다.",
},
});
return;
}
next();
} catch (error) {
logger.error("사용자 관리 권한 확인 중 오류:", error);
res.status(500).json({
success: false,
error: {
code: "AUTHORIZATION_ERROR",
details: "권한 확인 중 오류가 발생했습니다.",
},
});
}
};
/**
* 회사 설정 변경 권한 체크 미들웨어
*/
export const requireCompanySettingsManagement = (
req: AuthenticatedRequest,
res: Response,
next: NextFunction
): void => {
try {
if (!req.user) {
res.status(401).json({
success: false,
error: {
code: "AUTHENTICATION_REQUIRED",
details: "인증이 필요합니다.",
},
});
return;
}
const targetCompanyCode =
(req.params.companyCode as string) ||
(req.query.companyCode as string) ||
(req.body.companyCode as string);
if (!canManageCompanySettings(req.user, targetCompanyCode)) {
logger.warn("회사 설정 변경 권한 없음", {
userId: req.user.userId,
userCompanyCode: req.user.companyCode,
targetCompanyCode,
ip: req.ip,
url: req.originalUrl,
});
res.status(403).json({
success: false,
error: {
code: "COMPANY_SETTINGS_DENIED",
details: "회사 설정 변경 권한이 없습니다.",
},
});
return;
}
next();
} catch (error) {
logger.error("회사 설정 변경 권한 확인 중 오류:", error);
res.status(500).json({
success: false,
error: {
code: "AUTHORIZATION_ERROR",
details: "권한 확인 중 오류가 발생했습니다.",
},
});
}
};
/**
* 회사 생성/삭제 권한 체크 미들웨어 (슈퍼관리자 전용)
*/
export const requireCompanyManagement = (
req: AuthenticatedRequest,
res: Response,
next: NextFunction
): void => {
try {
if (!req.user) {
res.status(401).json({
success: false,
error: {
code: "AUTHENTICATION_REQUIRED",
details: "인증이 필요합니다.",
},
});
return;
}
if (!canManageCompanies(req.user)) {
logger.warn("회사 관리 권한 없음", {
userId: req.user.userId,
userType: req.user.userType,
companyCode: req.user.companyCode,
ip: req.ip,
url: req.originalUrl,
});
res.status(403).json({
success: false,
error: {
code: "COMPANY_MANAGEMENT_DENIED",
details: "회사 생성/삭제는 최고 관리자만 가능합니다.",
},
});
return;
}
next();
} catch (error) {
logger.error("회사 관리 권한 확인 중 오류:", error);
res.status(500).json({
success: false,
error: {
code: "AUTHORIZATION_ERROR",
details: "권한 확인 중 오류가 발생했습니다.",
},
});
}
};
/**
* DDL 실행 권한 체크 미들웨어 (슈퍼관리자 전용)
*/
export const requireDDLPermission = (
req: AuthenticatedRequest,
res: Response,
next: NextFunction
): void => {
try {
if (!req.user) {
res.status(401).json({
success: false,
error: {
code: "AUTHENTICATION_REQUIRED",
details: "인증이 필요합니다.",
},
});
return;
}
if (!canExecuteDDL(req.user)) {
logger.warn("DDL 실행 권한 없음", {
userId: req.user.userId,
userType: req.user.userType,
companyCode: req.user.companyCode,
ip: req.ip,
url: req.originalUrl,
});
res.status(403).json({
success: false,
error: {
code: "DDL_EXECUTION_DENIED",
details:
"DDL 실행은 최고 관리자만 가능합니다. 데이터베이스 스키마 변경은 company_code가 '*'이고 user_type이 'SUPER_ADMIN'인 사용자만 수행할 수 있습니다.",
},
});
return;
}
logger.info("DDL 실행 권한 확인 완료", {
userId: req.user.userId,
url: req.originalUrl,
});
next();
} catch (error) {
logger.error("DDL 실행 권한 확인 중 오류:", error);
res.status(500).json({
success: false,
error: {
code: "AUTHORIZATION_ERROR",
details: "권한 확인 중 오류가 발생했습니다.",
},
});
}
};