회사 관리자 메뉴 권한 필터링 적용
This commit is contained in:
parent
c4e81dd740
commit
f6e0e02ddf
|
|
@ -19,15 +19,21 @@ export class AdminService {
|
||||||
|
|
||||||
// menuType에 따른 WHERE 조건 생성
|
// menuType에 따른 WHERE 조건 생성
|
||||||
const menuTypeCondition =
|
const menuTypeCondition =
|
||||||
menuType !== undefined ? `MENU.MENU_TYPE = ${parseInt(menuType)}` : "1 = 1";
|
menuType !== undefined
|
||||||
|
? `MENU.MENU_TYPE = ${parseInt(menuType)}`
|
||||||
|
: "1 = 1";
|
||||||
|
|
||||||
// 메뉴 관리 화면인지 좌측 사이드바인지 구분
|
// 메뉴 관리 화면인지 좌측 사이드바인지 구분
|
||||||
// includeInactive가 true거나 menuType이 undefined면 메뉴 관리 화면
|
// includeInactive가 true거나 menuType이 undefined면 메뉴 관리 화면
|
||||||
const includeInactive = paramMap.includeInactive === true;
|
const includeInactive = paramMap.includeInactive === true;
|
||||||
const isManagementScreen = includeInactive || menuType === undefined;
|
const isManagementScreen = includeInactive || menuType === undefined;
|
||||||
// 메뉴 관리 화면: 모든 상태의 메뉴 표시, 좌측 사이드바: active만 표시
|
// 메뉴 관리 화면: 모든 상태의 메뉴 표시, 좌측 사이드바: active만 표시
|
||||||
const statusCondition = isManagementScreen ? "1 = 1" : "MENU.STATUS = 'active'";
|
const statusCondition = isManagementScreen
|
||||||
const subStatusCondition = isManagementScreen ? "1 = 1" : "MENU_SUB.STATUS = 'active'";
|
? "1 = 1"
|
||||||
|
: "MENU.STATUS = 'active'";
|
||||||
|
const subStatusCondition = isManagementScreen
|
||||||
|
? "1 = 1"
|
||||||
|
: "MENU_SUB.STATUS = 'active'";
|
||||||
|
|
||||||
// 1. 권한 그룹 기반 필터링 (좌측 사이드바인 경우만)
|
// 1. 권한 그룹 기반 필터링 (좌측 사이드바인 경우만)
|
||||||
let authFilter = "";
|
let authFilter = "";
|
||||||
|
|
@ -35,7 +41,11 @@ export class AdminService {
|
||||||
let queryParams: any[] = [userLang];
|
let queryParams: any[] = [userLang];
|
||||||
let paramIndex = 2;
|
let paramIndex = 2;
|
||||||
|
|
||||||
if (menuType !== undefined && userType !== "SUPER_ADMIN" && !isManagementScreen) {
|
if (
|
||||||
|
menuType !== undefined &&
|
||||||
|
userType !== "SUPER_ADMIN" &&
|
||||||
|
!isManagementScreen
|
||||||
|
) {
|
||||||
// 좌측 사이드바 + SUPER_ADMIN이 아닌 경우만 권한 체크
|
// 좌측 사이드바 + SUPER_ADMIN이 아닌 경우만 권한 체크
|
||||||
const userRoleGroups = await query<any>(
|
const userRoleGroups = await query<any>(
|
||||||
`
|
`
|
||||||
|
|
@ -56,45 +66,45 @@ export class AdminService {
|
||||||
);
|
);
|
||||||
|
|
||||||
if (userType === "COMPANY_ADMIN") {
|
if (userType === "COMPANY_ADMIN") {
|
||||||
// 회사 관리자: 자기 회사 메뉴는 모두, 공통 메뉴는 권한 있는 것만
|
// 회사 관리자: 권한 그룹 기반 필터링 적용
|
||||||
if (userRoleGroups.length > 0) {
|
if (userRoleGroups.length > 0) {
|
||||||
const roleObjids = userRoleGroups.map((rg: any) => rg.role_objid);
|
const roleObjids = userRoleGroups.map((rg: any) => rg.role_objid);
|
||||||
// 루트 메뉴: 회사 코드만 체크 (권한 체크 X)
|
// 회사 관리자도 권한 그룹 설정에 따라 메뉴 필터링
|
||||||
authFilter = `AND MENU.COMPANY_CODE IN ($${paramIndex}, '*')`;
|
authFilter = `
|
||||||
|
AND MENU.COMPANY_CODE IN ($${paramIndex}, '*')
|
||||||
|
AND EXISTS (
|
||||||
|
SELECT 1
|
||||||
|
FROM rel_menu_auth rma
|
||||||
|
WHERE rma.menu_objid = MENU.OBJID
|
||||||
|
AND rma.auth_objid = ANY($${paramIndex + 1})
|
||||||
|
AND rma.read_yn = 'Y'
|
||||||
|
)
|
||||||
|
`;
|
||||||
queryParams.push(userCompanyCode);
|
queryParams.push(userCompanyCode);
|
||||||
const companyParamIndex = paramIndex;
|
|
||||||
paramIndex++;
|
paramIndex++;
|
||||||
|
|
||||||
// 하위 메뉴: 회사 메뉴는 모두, 공통 메뉴는 권한 체크
|
// 하위 메뉴도 권한 체크
|
||||||
unionFilter = `
|
unionFilter = `
|
||||||
AND (
|
AND MENU_SUB.COMPANY_CODE IN ($${paramIndex - 1}, '*')
|
||||||
MENU_SUB.COMPANY_CODE = $${companyParamIndex}
|
AND EXISTS (
|
||||||
OR (
|
SELECT 1
|
||||||
MENU_SUB.COMPANY_CODE = '*'
|
FROM rel_menu_auth rma
|
||||||
AND EXISTS (
|
WHERE rma.menu_objid = MENU_SUB.OBJID
|
||||||
SELECT 1
|
AND rma.auth_objid = ANY($${paramIndex})
|
||||||
FROM rel_menu_auth rma
|
AND rma.read_yn = 'Y'
|
||||||
WHERE rma.menu_objid = MENU_SUB.OBJID
|
|
||||||
AND rma.auth_objid = ANY($${paramIndex})
|
|
||||||
AND rma.read_yn = 'Y'
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
`;
|
`;
|
||||||
queryParams.push(roleObjids);
|
queryParams.push(roleObjids);
|
||||||
paramIndex++;
|
paramIndex++;
|
||||||
logger.info(
|
logger.info(
|
||||||
`✅ 회사 관리자: 회사 ${userCompanyCode} 메뉴 전체 + 권한 있는 공통 메뉴`
|
`✅ 회사 관리자: 권한 있는 메뉴만 (${roleObjids.length}개 그룹)`
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
// 권한 그룹이 없는 회사 관리자: 자기 회사 메뉴만
|
// 권한 그룹이 없는 회사 관리자: 메뉴 없음
|
||||||
authFilter = `AND MENU.COMPANY_CODE = $${paramIndex}`;
|
logger.warn(
|
||||||
unionFilter = `AND MENU_SUB.COMPANY_CODE = $${paramIndex}`;
|
`⚠️ 회사 관리자 ${userId}는 권한 그룹이 없어 메뉴가 표시되지 않습니다.`
|
||||||
queryParams.push(userCompanyCode);
|
|
||||||
paramIndex++;
|
|
||||||
logger.info(
|
|
||||||
`✅ 회사 관리자 (권한 그룹 없음): 회사 ${userCompanyCode} 메뉴만`
|
|
||||||
);
|
);
|
||||||
|
return [];
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// 일반 사용자: 권한 그룹 필수
|
// 일반 사용자: 권한 그룹 필수
|
||||||
|
|
@ -131,7 +141,11 @@ export class AdminService {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (menuType !== undefined && userType === "SUPER_ADMIN" && !isManagementScreen) {
|
} else if (
|
||||||
|
menuType !== undefined &&
|
||||||
|
userType === "SUPER_ADMIN" &&
|
||||||
|
!isManagementScreen
|
||||||
|
) {
|
||||||
// 좌측 사이드바 + SUPER_ADMIN: 권한 그룹 체크 없이 모든 공통 메뉴 표시
|
// 좌측 사이드바 + SUPER_ADMIN: 권한 그룹 체크 없이 모든 공통 메뉴 표시
|
||||||
logger.info(`✅ 최고 관리자는 권한 그룹 체크 없이 모든 공통 메뉴 표시`);
|
logger.info(`✅ 최고 관리자는 권한 그룹 체크 없이 모든 공통 메뉴 표시`);
|
||||||
// unionFilter는 비워둠 (하위 메뉴도 공통 메뉴만)
|
// unionFilter는 비워둠 (하위 메뉴도 공통 메뉴만)
|
||||||
|
|
@ -167,7 +181,7 @@ export class AdminService {
|
||||||
companyFilter = `AND MENU.COMPANY_CODE = $${paramIndex}`;
|
companyFilter = `AND MENU.COMPANY_CODE = $${paramIndex}`;
|
||||||
queryParams.push(userCompanyCode);
|
queryParams.push(userCompanyCode);
|
||||||
paramIndex++;
|
paramIndex++;
|
||||||
|
|
||||||
// 하위 메뉴에도 회사 필터링 적용 (공통 메뉴 제외)
|
// 하위 메뉴에도 회사 필터링 적용 (공통 메뉴 제외)
|
||||||
if (unionFilter === "") {
|
if (unionFilter === "") {
|
||||||
unionFilter = `AND MENU_SUB.COMPANY_CODE = $${paramIndex - 1}`;
|
unionFilter = `AND MENU_SUB.COMPANY_CODE = $${paramIndex - 1}`;
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ import { useRouter } from "next/navigation";
|
||||||
import { AlertCircle } from "lucide-react";
|
import { AlertCircle } from "lucide-react";
|
||||||
import { DualListBox } from "@/components/common/DualListBox";
|
import { DualListBox } from "@/components/common/DualListBox";
|
||||||
import { MenuPermissionsTable } from "./MenuPermissionsTable";
|
import { MenuPermissionsTable } from "./MenuPermissionsTable";
|
||||||
|
import { useMenu } from "@/contexts/MenuContext";
|
||||||
|
|
||||||
interface RoleDetailManagementProps {
|
interface RoleDetailManagementProps {
|
||||||
roleId: string;
|
roleId: string;
|
||||||
|
|
@ -25,6 +26,7 @@ interface RoleDetailManagementProps {
|
||||||
export function RoleDetailManagement({ roleId }: RoleDetailManagementProps) {
|
export function RoleDetailManagement({ roleId }: RoleDetailManagementProps) {
|
||||||
const { user: currentUser } = useAuth();
|
const { user: currentUser } = useAuth();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
const { refreshMenus } = useMenu();
|
||||||
|
|
||||||
const isSuperAdmin = currentUser?.companyCode === "*" && currentUser?.userType === "SUPER_ADMIN";
|
const isSuperAdmin = currentUser?.companyCode === "*" && currentUser?.userType === "SUPER_ADMIN";
|
||||||
|
|
||||||
|
|
@ -178,6 +180,9 @@ export function RoleDetailManagement({ roleId }: RoleDetailManagementProps) {
|
||||||
if (response.success) {
|
if (response.success) {
|
||||||
alert("멤버가 성공적으로 저장되었습니다.");
|
alert("멤버가 성공적으로 저장되었습니다.");
|
||||||
loadMembers(); // 새로고침
|
loadMembers(); // 새로고침
|
||||||
|
|
||||||
|
// 사이드바 메뉴 새로고침 (현재 사용자가 영향받을 수 있음)
|
||||||
|
await refreshMenus();
|
||||||
} else {
|
} else {
|
||||||
alert(response.message || "멤버 저장에 실패했습니다.");
|
alert(response.message || "멤버 저장에 실패했습니다.");
|
||||||
}
|
}
|
||||||
|
|
@ -187,7 +192,7 @@ export function RoleDetailManagement({ roleId }: RoleDetailManagementProps) {
|
||||||
} finally {
|
} finally {
|
||||||
setIsSavingMembers(false);
|
setIsSavingMembers(false);
|
||||||
}
|
}
|
||||||
}, [roleGroup, selectedUsers, loadMembers]);
|
}, [roleGroup, selectedUsers, loadMembers, refreshMenus]);
|
||||||
|
|
||||||
// 메뉴 권한 저장 핸들러
|
// 메뉴 권한 저장 핸들러
|
||||||
const handleSavePermissions = useCallback(async () => {
|
const handleSavePermissions = useCallback(async () => {
|
||||||
|
|
@ -200,6 +205,9 @@ export function RoleDetailManagement({ roleId }: RoleDetailManagementProps) {
|
||||||
if (response.success) {
|
if (response.success) {
|
||||||
alert("메뉴 권한이 성공적으로 저장되었습니다.");
|
alert("메뉴 권한이 성공적으로 저장되었습니다.");
|
||||||
loadMenuPermissions(); // 새로고침
|
loadMenuPermissions(); // 새로고침
|
||||||
|
|
||||||
|
// 사이드바 메뉴 새로고침 (권한 변경 즉시 반영)
|
||||||
|
await refreshMenus();
|
||||||
} else {
|
} else {
|
||||||
alert(response.message || "메뉴 권한 저장에 실패했습니다.");
|
alert(response.message || "메뉴 권한 저장에 실패했습니다.");
|
||||||
}
|
}
|
||||||
|
|
@ -209,7 +217,7 @@ export function RoleDetailManagement({ roleId }: RoleDetailManagementProps) {
|
||||||
} finally {
|
} finally {
|
||||||
setIsSavingPermissions(false);
|
setIsSavingPermissions(false);
|
||||||
}
|
}
|
||||||
}, [roleGroup, menuPermissions, loadMenuPermissions]);
|
}, [roleGroup, menuPermissions, loadMenuPermissions, refreshMenus]);
|
||||||
|
|
||||||
if (isLoading) {
|
if (isLoading) {
|
||||||
return (
|
return (
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue