최고관리자가 부여한 권한에 따라 메뉴 보여주기
This commit is contained in:
@@ -227,6 +227,15 @@ export const getUserList = async (req: AuthenticatedRequest, res: Response) => {
|
||||
logger.info("회사 코드 필터 적용", { companyCode });
|
||||
}
|
||||
|
||||
// 최고 관리자 필터링 (회사 관리자와 일반 사용자는 최고 관리자를 볼 수 없음)
|
||||
if (req.user && req.user.companyCode !== "*") {
|
||||
// 최고 관리자가 아닌 경우, company_code가 "*"인 사용자는 제외
|
||||
whereConditions.push(`company_code != '*'`);
|
||||
logger.info("최고 관리자 필터링 적용", {
|
||||
userCompanyCode: req.user.companyCode,
|
||||
});
|
||||
}
|
||||
|
||||
// 검색 조건 처리
|
||||
if (search && typeof search === "string" && search.trim()) {
|
||||
// 통합 검색
|
||||
|
||||
@@ -21,11 +21,87 @@ export class AdminService {
|
||||
const menuTypeCondition =
|
||||
menuType !== undefined ? `MENU_TYPE = ${parseInt(menuType)}` : "1 = 1";
|
||||
|
||||
// 회사별 필터링 조건 생성
|
||||
let companyFilter = "";
|
||||
// 1. 권한 그룹 기반 필터링 (좌측 사이드바인 경우만)
|
||||
let authFilter = "";
|
||||
let queryParams: any[] = [userLang];
|
||||
let paramIndex = 2;
|
||||
|
||||
if (menuType !== undefined && userType !== "SUPER_ADMIN") {
|
||||
// 좌측 사이드바 + SUPER_ADMIN이 아닌 경우
|
||||
const userRoleGroups = await query<any>(
|
||||
`
|
||||
SELECT DISTINCT am.objid AS role_objid, am.auth_name
|
||||
FROM authority_master am
|
||||
JOIN authority_sub_user asu ON am.objid = asu.master_objid
|
||||
WHERE asu.user_id = $1
|
||||
AND am.status = 'active'
|
||||
`,
|
||||
[userId]
|
||||
);
|
||||
|
||||
logger.info(
|
||||
`✅ 사용자 ${userId}가 속한 권한 그룹: ${userRoleGroups.length}개`,
|
||||
{
|
||||
roleGroups: userRoleGroups.map((rg: any) => rg.auth_name),
|
||||
}
|
||||
);
|
||||
|
||||
if (userType === "COMPANY_ADMIN") {
|
||||
// 회사 관리자: 자기 회사 메뉴는 모두, 공통 메뉴는 권한 있는 것만
|
||||
if (userRoleGroups.length > 0) {
|
||||
const roleObjids = userRoleGroups.map((rg: any) => rg.role_objid);
|
||||
// 루트 메뉴: 회사 코드만 체크 (권한 체크 X)
|
||||
// 하위 메뉴: 회사 메뉴는 모두, 공통 메뉴는 권한 체크
|
||||
authFilter = `AND MENU.COMPANY_CODE IN ($${paramIndex}, '*')`;
|
||||
queryParams.push(userCompanyCode);
|
||||
queryParams.push(roleObjids);
|
||||
paramIndex += 2;
|
||||
logger.info(
|
||||
`✅ 회사 관리자: 회사 ${userCompanyCode} 메뉴 전체 + 권한 있는 공통 메뉴`
|
||||
);
|
||||
} else {
|
||||
// 권한 그룹이 없는 회사 관리자: 자기 회사 메뉴만
|
||||
authFilter = `AND MENU.COMPANY_CODE = $${paramIndex}`;
|
||||
queryParams.push(userCompanyCode);
|
||||
paramIndex++;
|
||||
logger.info(
|
||||
`✅ 회사 관리자 (권한 그룹 없음): 회사 ${userCompanyCode} 메뉴만`
|
||||
);
|
||||
}
|
||||
} else {
|
||||
// 일반 사용자: 권한 그룹 필수
|
||||
if (userRoleGroups.length > 0) {
|
||||
const roleObjids = userRoleGroups.map((rg: any) => rg.role_objid);
|
||||
authFilter = `
|
||||
AND EXISTS (
|
||||
SELECT 1
|
||||
FROM rel_menu_auth rma
|
||||
WHERE rma.menu_objid = MENU.OBJID
|
||||
AND rma.auth_objid = ANY($${paramIndex})
|
||||
AND rma.read_yn = 'Y'
|
||||
)
|
||||
`;
|
||||
queryParams.push(roleObjids);
|
||||
paramIndex++;
|
||||
logger.info(
|
||||
`✅ 일반 사용자: 권한 있는 메뉴만 (${roleObjids.length}개 그룹)`
|
||||
);
|
||||
} else {
|
||||
// 권한 그룹이 없는 일반 사용자: 메뉴 없음
|
||||
logger.warn(
|
||||
`⚠️ 사용자 ${userId}는 권한 그룹이 없어 메뉴가 표시되지 않습니다.`
|
||||
);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
} else if (menuType !== undefined && userType === "SUPER_ADMIN") {
|
||||
// 좌측 사이드바 + SUPER_ADMIN: 권한 그룹 체크 없이 모든 공통 메뉴 표시
|
||||
logger.info(`✅ 최고 관리자는 권한 그룹 체크 없이 모든 공통 메뉴 표시`);
|
||||
}
|
||||
|
||||
// 2. 회사별 필터링 조건 생성
|
||||
let companyFilter = "";
|
||||
|
||||
// SUPER_ADMIN과 COMPANY_ADMIN 구분
|
||||
if (userType === "SUPER_ADMIN" && userCompanyCode === "*") {
|
||||
// SUPER_ADMIN
|
||||
@@ -38,15 +114,16 @@ export class AdminService {
|
||||
logger.info("✅ 좌측 사이드바 (SUPER_ADMIN): 공통 메뉴만 표시");
|
||||
companyFilter = `AND MENU.COMPANY_CODE = '*'`;
|
||||
}
|
||||
} else {
|
||||
// COMPANY_ADMIN: 좌측 사이드바, 메뉴 관리 화면 모두 자기 회사만
|
||||
} else if (menuType === undefined) {
|
||||
// 메뉴 관리 화면: 자기 회사 + 공통 메뉴
|
||||
logger.info(
|
||||
`✅ ${menuType === undefined ? "메뉴 관리 화면" : "좌측 사이드바"} (COMPANY_ADMIN): 회사 ${userCompanyCode} 메뉴만 표시`
|
||||
`✅ 메뉴 관리 화면: 회사 ${userCompanyCode} + 공통 메뉴 표시`
|
||||
);
|
||||
companyFilter = `AND MENU.COMPANY_CODE = $${paramIndex}`;
|
||||
companyFilter = `AND (MENU.COMPANY_CODE = $${paramIndex} OR MENU.COMPANY_CODE = '*')`;
|
||||
queryParams.push(userCompanyCode);
|
||||
paramIndex++;
|
||||
}
|
||||
// menuType이 정의된 경우 (좌측 사이드바)는 authFilter에서 이미 회사 필터링 포함
|
||||
|
||||
// 기존 Java의 selectAdminMenuList 쿼리를 Raw Query로 포팅
|
||||
// WITH RECURSIVE 쿼리 구현
|
||||
@@ -131,6 +208,7 @@ export class AdminService {
|
||||
WHERE ${menuTypeCondition}
|
||||
AND STATUS = 'active'
|
||||
${companyFilter}
|
||||
${authFilter}
|
||||
AND NOT EXISTS (
|
||||
SELECT 1 FROM MENU_INFO parent_menu
|
||||
WHERE parent_menu.OBJID = MENU.PARENT_OBJ_ID
|
||||
@@ -196,6 +274,19 @@ export class AdminService {
|
||||
JOIN V_MENU ON MENU_SUB.PARENT_OBJ_ID = V_MENU.OBJID
|
||||
WHERE MENU_SUB.OBJID != ANY(V_MENU.PATH)
|
||||
AND MENU_SUB.STATUS = 'active'
|
||||
AND (
|
||||
MENU_SUB.COMPANY_CODE = $2
|
||||
OR (
|
||||
MENU_SUB.COMPANY_CODE = '*'
|
||||
AND EXISTS (
|
||||
SELECT 1
|
||||
FROM rel_menu_auth rma
|
||||
WHERE rma.menu_objid = MENU_SUB.OBJID
|
||||
AND rma.auth_objid = ANY($3)
|
||||
AND rma.read_yn = 'Y'
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
SELECT
|
||||
LEVEL AS LEV,
|
||||
@@ -248,7 +339,7 @@ export class AdminService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 사용자 메뉴 목록 조회 (회사별 필터링 적용)
|
||||
* 사용자 메뉴 목록 조회 (권한 그룹 기반 필터링)
|
||||
*/
|
||||
static async getUserMenuList(paramMap: any): Promise<any[]> {
|
||||
try {
|
||||
@@ -256,17 +347,64 @@ export class AdminService {
|
||||
|
||||
const { userId, userCompanyCode, userType, userLang = "ko" } = paramMap;
|
||||
|
||||
// 좌측 사이드바: SUPER_ADMIN은 공통 메뉴, COMPANY_ADMIN은 자기 회사 메뉴
|
||||
let companyFilter = "";
|
||||
// 1. 사용자가 속한 권한 그룹 조회
|
||||
const userRoleGroups = await query<any>(
|
||||
`
|
||||
SELECT DISTINCT am.objid AS role_objid, am.auth_name
|
||||
FROM authority_master am
|
||||
JOIN authority_sub_user asu ON am.objid = asu.master_objid
|
||||
WHERE asu.user_id = $1
|
||||
AND am.status = 'active'
|
||||
`,
|
||||
[userId]
|
||||
);
|
||||
|
||||
logger.info(
|
||||
`✅ 사용자 ${userId}가 속한 권한 그룹: ${userRoleGroups.length}개`,
|
||||
{
|
||||
roleGroups: userRoleGroups.map((rg: any) => rg.auth_name),
|
||||
}
|
||||
);
|
||||
|
||||
// 2. 권한 그룹 기반 메뉴 필터 조건 생성
|
||||
let authFilter = "";
|
||||
let queryParams: any[] = [userLang];
|
||||
let paramIndex = 2;
|
||||
|
||||
if (userRoleGroups.length > 0) {
|
||||
// 권한 그룹이 있는 경우: read_yn = 'Y'인 메뉴만 필터링
|
||||
const roleObjids = userRoleGroups.map((rg: any) => rg.role_objid);
|
||||
authFilter = `
|
||||
AND EXISTS (
|
||||
SELECT 1
|
||||
FROM rel_menu_auth rma
|
||||
WHERE rma.menu_objid = MENU.OBJID
|
||||
AND rma.auth_objid = ANY($${paramIndex})
|
||||
AND rma.read_yn = 'Y'
|
||||
)
|
||||
`;
|
||||
queryParams.push(roleObjids);
|
||||
paramIndex++;
|
||||
logger.info(
|
||||
`✅ 권한 그룹 기반 메뉴 필터링 적용: ${roleObjids.length}개 그룹`
|
||||
);
|
||||
} else {
|
||||
// 권한 그룹이 없는 경우: 메뉴 없음
|
||||
logger.warn(
|
||||
`⚠️ 사용자 ${userId}는 권한 그룹이 없어 메뉴가 표시되지 않습니다.`
|
||||
);
|
||||
return [];
|
||||
}
|
||||
|
||||
// 3. 회사별 필터링 조건 생성
|
||||
let companyFilter = "";
|
||||
|
||||
if (userType === "SUPER_ADMIN" && userCompanyCode === "*") {
|
||||
// SUPER_ADMIN: 공통 메뉴만 (company_code = '*')
|
||||
logger.info("✅ 좌측 사이드바 (SUPER_ADMIN): 공통 메뉴만 표시");
|
||||
companyFilter = `AND MENU.COMPANY_CODE = '*'`;
|
||||
} else {
|
||||
// COMPANY_ADMIN: 자기 회사 메뉴만
|
||||
// COMPANY_ADMIN/USER: 자기 회사 메뉴만
|
||||
logger.info(
|
||||
`✅ 좌측 사이드바 (COMPANY_ADMIN): 회사 ${userCompanyCode} 메뉴만 표시`
|
||||
);
|
||||
@@ -318,6 +456,7 @@ export class AdminService {
|
||||
AND MENU_TYPE = 1
|
||||
AND STATUS = 'active'
|
||||
${companyFilter}
|
||||
${authFilter}
|
||||
|
||||
UNION ALL
|
||||
|
||||
@@ -341,6 +480,7 @@ export class AdminService {
|
||||
FROM MENU_INFO MENU_SUB
|
||||
JOIN V_MENU ON MENU_SUB.PARENT_OBJ_ID = V_MENU.OBJID
|
||||
WHERE MENU_SUB.STATUS = 'active'
|
||||
${authFilter.replace(/MENU\.OBJID/g, "MENU_SUB.OBJID")}
|
||||
)
|
||||
SELECT
|
||||
LEVEL AS LEV,
|
||||
|
||||
Reference in New Issue
Block a user