using Microsoft.AspNetCore.Authorization; using System.Security.Claims; namespace SharedKernel.Constants { public class Menu { public int Id { get; set; } public required string Name { get; set; } public string? Path { get; set; } public string? Icon { get; set; } public List? Children { get; set; } = []; public bool HasChildren => Children != null && Children.Count > 0; // 이 메뉴를 볼 수 있는 역할 목록 (없으면 모두 허용) public List? Roles { get; set; } // 정책 이름으로도 제한 가능하게 public List? Policies { get; set; } } public static class Menus { public static List GetMenus() { return new List { new Menu { Id = 100, Name = "상황판", Path = "/", Icon = "", Children = null, Roles = [ "Admin", "상황판" ], Policies = null }, new Menu { Id = 200, Name = "환경", Path = null, Icon = "", Roles = [ "Admin", "환경" ], Children = new List { new Menu { Id = 201, Name = "서버 정보", Path = "/Server/Info", Roles = [ "Admin", "환경 - 서버 정보" ], Policies = null }, new Menu { Id = 202, Name = "환경변수", Path = "/Server/Env", Roles = [ "Admin", "환경 - 환경변수" ] }, new Menu { Id = 203, Name = "기본 설정", Path = "/Config/Basic", Roles = [ "Admin", "환경 - 기본 설정" ] }, new Menu { Id = 204, Name = "메타 태그", Path = "/Config/Meta", Roles = [ "Admin", "환경 - 메타 태그" ] }, new Menu { Id = 205, Name = "회사 정보", Path = "/Config/Company", Roles = [ "Admin", "환경 - 회사 정보" ] }, new Menu { Id = 206, Name = "회원 설정", Path = "/Config/Register", Roles = [ "Admin", "환경 - 회원 설정" ] }, new Menu { Id = 207, Name = "알림 발송 확인", Path = "/Config/Test/Email", Roles = [ "Admin", "환경 - 알림 발송 확인" ] }, new Menu { Id = 208, Name = "알림 발송 양식", Path = "/Config/Template/Email", Roles = [ "Admin", "환경 - 알림 발송 양식" ] }, new Menu { Id = 209, Name = "API 설정", Path = "/Config/External", Roles = [ "Admin", "환경 - API 설정" ] }, new Menu { Id = 210, Name = "Cache 관리", Path = "/Server/Cache", Roles = [ "Admin", "환경 - Cache 관리" ] } } }, new Menu { Id = 250, Name = "관리자", Path = null, Icon = "", Roles = [ "Admin", "관리자" ], Children = new List { new Menu { Id = 251, Name = "회원 관리", Path = "/Director/User", Roles = [ "Admin", "관리자 회원" ] }, new Menu { Id = 252, Name = "로그인 내역", Path = "/Director/LoginLog", Roles = [ "Admin", "관리자 - 로그인 내역" ] }, new Menu { Id = 253, Name = "접근 기록", Path = "/Director/AccessLog", Roles = [ "Admin", "관리자 - 처리 기록" ] } } }, new Menu { Id = 300, Name = "일반", Path = null, Icon = "", Roles = [ "Admin", "일반" ], Children = new List { new Menu { Id = 301, Name = "문서 관리", Path = "/Document", Roles = [ "Admin", "일반 - 문서 관리" ] }, new Menu { Id = 302, Name = "팝업 관리", Path = "/Popup", Roles = [ "Admin", "일반 - 팝업 관리" ] }, new Menu { Id = 303, Name = "FAQ 관리", Path = "/Faq/List", Roles = [ "Admin", "일반 - FAQ 관리" ] }, new Menu { Id = 304, Name = "배너 관리", Path = "/Banner/List", Roles = [ "Admin", "일반 - 배너 관리" ] } } }, new Menu { Id = 400, Name = "회원", Path = null, Icon = "", Roles = [ "Admin", "회원" ], Children = new List { new Menu { Id = 401, Name = "회원 목록", Path = "/Member/List", Roles = [ "Admin", "회원 - 회원 목록" ] }, new Menu { Id = 402, Name = "회원 등급", Path = "/Member/Grade", Roles = [ "Admin", "회원 - 회원 등급" ] }, new Menu { Id = 403, Name = "현재 접속자", Path = "/Member/Visitor", Roles = [ "Admin", "회원 - 현재 접속자" ] }, new Menu { Id = 404, Name = "로그인 내역", Path = "/Member/Log/Login", Roles = [ "Admin", "회원 - 로그인 내역" ] }, new Menu { Id = 405, Name = "이메일 변경 내역", Path = "/Member/Log/Email", Roles = [ "Admin", "회원 - 이메일 변경 내역" ] }, new Menu { Id = 406, Name = "별명 변경 내역", Path = "/Member/Log/Name", Roles = [ "Admin", "회원 - 별명 변경 내역" ] }, new Menu { Id = 407, Name = "한마디 변경 내역", Path = "/Member/Log/Summary", Roles = [ "Admin", "회원 - 한마디 변경 내역" ] }, new Menu { Id = 408, Name = "자기소개 변경 내역", Path = "/Member/Log/Intro", Roles = [ "Admin", "회원 - 자기소개 변경 내역" ] }, new Menu { Id = 409, Name = "지갑 관리", Path = "/Member/Wallet/List", Roles = [ "Admin", "회원 - 지갑 관리", "Joblepay" ] }, new Menu { Id = 410, Name = "거래 장부", Path = "/Member/Wallet/Transactions", Roles = [ "Admin", "회원 - 거래 장부" ] } } }, new Menu { Id = 500, Name = "게시판", Path = null, Icon = "", Roles = [ "Admin", "게시판" ], Children = new List { new Menu { Id = 501, Name = "분류 관리", Path = "/Forum/Board/Group", Roles = [ "Admin", "게시판 - 분류 관리" ] }, new Menu { Id = 502, Name = "게시판 관리", Path = "/Forum/Board/List", Roles = [ "Admin", "게시판 - 게시판 관리" ] }, new Menu { Id = 503, Name = "게시물 관리", Path = "/Forum/Posts/List", Roles = [ "Admin", "게시판 - 게시물 관리" ] }, new Menu { Id = 504, Name = "휴지통", Path = "/Forum/Trash/Post", Roles = [ "Admin", "게시판 - 휴지통" ] }, new Menu { Id = 505, Name = "첨부파일", Path = "/Forum/Attachments/PostFile", Roles = [ "Admin", "게시판 - 첨부파일" ] }, new Menu { Id = 506, Name = "이미지", Path = "/Forum/Attachments/PostImage", Roles = [ "Admin", "게시판 - 이미지" ] }, new Menu { Id = 507, Name = "반응 관리", Path = "/Forum/Reactions/Post", Roles = [ "Admin", "게시판 - 반응 관리" ] }, new Menu { Id = 508, Name = "신고 관리", Path = "/Forum/Reports/Post", Roles = [ "Admin", "게시판 - 신고 관리" ] } } }, new Menu { Id = 600, Name = "댓글", Path = null, Icon = "", Roles = [ "Admin", "댓글" ], Children = new List { new Menu { Id = 601, Name = "댓글 관리", Path = "/Forum/Comments/List", Roles = [ "Admin", "댓글 - 댓글 관리" ] }, new Menu { Id = 602, Name = "휴지통", Path = "/Forum/Trash/Comment", Roles = [ "Admin", "댓글 - 휴지통" ] }, new Menu { Id = 603, Name = "첨부파일", Path = "/Forum/Attachments/CommentFile", Roles = [ "Admin", "댓글 - 첨부파일" ] }, new Menu { Id = 604, Name = "이미지", Path = "/Forum/Attachments/CommentImage", Roles = [ "Admin", "댓글 - 이미지" ] }, new Menu { Id = 605, Name = "반응 관리", Path = "/Forum/Reactions/Comment", Roles = [ "Admin", "댓글 - 반응 관리" ] }, new Menu { Id = 606, Name = "신고 관리", Path = "/Forum/Reports/Comment", Roles = [ "Admin", "댓글 - 신고 관리" ] } } }, new Menu { Id = 700, Name = "채널", Path = "/Channel/List", Icon = "", Children = null, Roles = [ "Admin", "채널", "채널 - 채널 목록" ] }, new Menu { Id = 800, Name = "결제", Path = null, Icon = "", Roles = [ "Admin", "결제" ], Children = new List { new Menu { Id = 801, Name = "다날 결제 내역", Path = "/Payments/Danal/Confirm", Roles = [ "Admin", "결제 - 다날 결제 내역" ] }, new Menu { Id = 802, Name = "다날 취소 내역", Path = "/Payments/Danal/Cancel", Roles = [ "Admin", "결제 - 다날 취소 내역" ] }, new Menu { Id = 803, Name = "다날 오류 내역", Path = "/Payments/Danal/Error", Roles = [ "Admin", "결제 - 다날 오류 내역" ] } } }, /*new Menu { Id = 900, Name = "후원", Path = null, Icon = "", Roles = [ "Admin", "후원" ], Children = new List { new Menu { Id = 901, Name = "후원 내역", Path = "/Donation/List", Roles = [ "Admin", "후원 - 후원 내역" ] }, new Menu { Id = 902, Name = "후원 알림", Path = "/Donation/Alert", Roles = [ "Admin", "후원 - 후원 알림" ] } } },*/ /*new Menu { Id = 1000, Name = "정산", Path = null, Icon = "", Roles = [ "Admin", "정산" ], Children = new List { new Menu { Id = 1001, Name = "매출 관리", Path = "/Payout/Sales", Roles = [ "Admin", "정산 - 매출 관리" ] }, new Menu { Id = 1002, Name = "통계", Path = "/Payout/Statistics", Roles = [ "Admin", "정산 - 통계" ] }, new Menu { Id = 1003, Name = "회원 정산 내역", Path = "/Payout/Settlement/List", Roles = [ "Admin", "정산 - 회원 정산 내역" ] } } }*/ }; } public static async Task> FilterForUserAsync(ClaimsPrincipal user, IAuthorizationService authorizationService) { var menus = GetMenus(); var result = new List(); foreach (var menu in menus) { var filtered = await FilterMenuRecursiveAsync(menu, user, authorizationService); if (filtered != null) { result.Add(filtered); } } return result; } private static async Task FilterMenuRecursiveAsync(Menu menu, ClaimsPrincipal user, IAuthorizationService authorizationService) { // 현재 메뉴에 대한 접근 권한 체크 if (!await IsMenuAllowedAsync(menu, user, authorizationService)) { // 자식이 있으면, 자식은 볼 수 있지만 부모는 숨기고 싶을 수도 있음 if (menu.Children is { Count: > 0 }) { var allowedChildren = new List(); foreach (var child in menu.Children) { var filteredChild = await FilterMenuRecursiveAsync(child, user, authorizationService); if (filteredChild != null) { allowedChildren.Add(filteredChild); } } if (allowedChildren.Count == 0) { return null; } return new Menu { Id = menu.Id, Name = menu.Name, Path = menu.Path, Icon = menu.Icon, Roles = menu.Roles, Policies = menu.Policies, Children = allowedChildren }; } return null; } // 부모는 허용되지만, 자식 중 제한이 있을 수도 있으니 List? filteredChildren = null; if (menu.Children is { Count: > 0 }) { filteredChildren = new List(); foreach (var child in menu.Children) { var filteredChild = await FilterMenuRecursiveAsync(child, user, authorizationService); if (filteredChild != null) { filteredChildren.Add(filteredChild); } } if (filteredChildren.Count == 0) { filteredChildren = null; } } return new Menu { Id = menu.Id, Name = menu.Name, Path = menu.Path, Icon = menu.Icon, Roles = menu.Roles, Policies = menu.Policies, Children = filteredChildren }; } private static async Task IsMenuAllowedAsync(Menu menu, ClaimsPrincipal user, IAuthorizationService authorizationService) { // 로그인 안 한 경우: 익명에게도 보여줄 메뉴만 허용하고 싶으면 분기 추가 if (!user.Identity?.IsAuthenticated ?? true) { // 예: 익명은 아무 메뉴도 못 본다고 가정 return false; } // Roles 지정되어 있으면 Role 기반 체크 if (menu.Roles is { Count: > 0 }) { // 하나라도 만족하면 허용 foreach (var role in menu.Roles) { if (user.IsInRole(role)) { return true; } } return false; } // Policies 지정되어 있으면 Policy 기반 체크 if (menu.Policies is { Count: > 0 }) { foreach (var policy in menu.Policies) { var authResult = await authorizationService.AuthorizeAsync(user, policy); if (authResult.Succeeded) { return true; } } return false; } // 역할/정책 제한이 없으면 모두 허용 return true; } } }