# 권한 그룹 시스템 설계 (RBAC) ## 개요 회사 내에서 **역할 기반 접근 제어(RBAC - Role-Based Access Control)**를 통해 세밀한 권한 관리를 제공합니다. ## 기존 시스템 분석 ### 현재 테이블 구조 #### 1. `authority_master` - 권한 그룹 마스터 ```sql CREATE TABLE authority_master ( objid NUMERIC PRIMARY KEY, auth_name VARCHAR, -- 권한 그룹 이름 (예: "영업팀 권한", "개발팀 권한") auth_code VARCHAR, -- 권한 코드 (예: "SALES_TEAM", "DEV_TEAM") writer VARCHAR, regdate TIMESTAMP, status VARCHAR ); ``` #### 2. `authority_sub_user` - 권한 그룹 멤버 ```sql CREATE TABLE authority_sub_user ( objid NUMERIC PRIMARY KEY, master_objid NUMERIC, -- authority_master.objid 참조 user_id VARCHAR, -- user_info.user_id 참조 writer VARCHAR, regdate TIMESTAMP ); ``` #### 3. `rel_menu_auth` - 메뉴 권한 매핑 ```sql CREATE TABLE rel_menu_auth ( objid NUMERIC, menu_objid NUMERIC, -- menu_info.objid 참조 auth_objid NUMERIC, -- authority_master.objid 참조 writer VARCHAR, regdate TIMESTAMP, create_yn VARCHAR, -- 생성 권한 (Y/N) read_yn VARCHAR, -- 조회 권한 (Y/N) update_yn VARCHAR, -- 수정 권한 (Y/N) delete_yn VARCHAR -- 삭제 권한 (Y/N) ); ``` ## 개선 사항 ### 1. 회사별 권한 그룹 지원 **현재 문제점:** - `authority_master` 테이블에 `company_code` 컬럼이 없음 - 모든 회사가 권한 그룹을 공유하게 됨 **해결 방안:** ```sql -- 마이그레이션 028 ALTER TABLE authority_master ADD COLUMN company_code VARCHAR(20); CREATE INDEX idx_authority_master_company ON authority_master(company_code); -- 기존 데이터 마이그레이션 (기본값 설정) UPDATE authority_master SET company_code = 'ILSHIN' WHERE company_code IS NULL; ``` ### 2. 권한 레벨과 권한 그룹의 차이 | 구분 | 권한 레벨 (userType) | 권한 그룹 (authority_master) | | ---------- | -------------------------------- | ------------------------------ | | **목적** | 시스템 레벨 권한 | 메뉴별 세부 권한 | | **범위** | 전역 (시스템 전체) | 회사별 (회사 내부) | | **관리자** | 최고 관리자 (SUPER_ADMIN) | 회사 관리자 (COMPANY_ADMIN) | | **예시** | SUPER_ADMIN, COMPANY_ADMIN, USER | "영업팀", "개발팀", "관리자팀" | ### 3. 2단계 권한 체계 ``` ┌─────────────────────────────────────────────────────────────┐ │ 1단계: 권한 레벨 (userType) │ │ - SUPER_ADMIN: 모든 회사 관리, DDL 실행 │ │ - COMPANY_ADMIN: 자기 회사 관리, 권한 그룹 생성 │ │ - USER: 자기 회사 데이터 조회/수정 │ └─────────────────────────────────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────────────┐ │ 2단계: 권한 그룹 (authority_master) │ │ - 회사 내부에서 메뉴별 세부 권한 설정 │ │ - 생성(C), 조회(R), 수정(U), 삭제(D) 권한 제어 │ └─────────────────────────────────────────────────────────────┘ ``` ## 사용 시나리오 ### 시나리오 1: 영업팀 권한 그룹 **요구사항:** - 영업팀은 고객 관리, 계약 관리 메뉴만 접근 가능 - 고객 정보는 조회/수정 가능하지만 삭제 불가 - 계약은 생성/조회/수정 가능 **구현:** ```sql -- 1. 권한 그룹 생성 INSERT INTO authority_master (objid, auth_name, auth_code, company_code, status) VALUES (nextval('seq_authority'), '영업팀 권한', 'SALES_TEAM', 'COMPANY_1', 'active'); -- 2. 사용자 추가 INSERT INTO authority_sub_user (objid, master_objid, user_id) VALUES (nextval('seq_auth_sub'), 1, 'user1'), (nextval('seq_auth_sub'), 1, 'user2'); -- 3. 메뉴 권한 설정 -- 고객 관리 메뉴 INSERT INTO rel_menu_auth (menu_objid, auth_objid, create_yn, read_yn, update_yn, delete_yn) VALUES (100, 1, 'N', 'Y', 'Y', 'N'); -- 계약 관리 메뉴 INSERT INTO rel_menu_auth (menu_objid, auth_objid, create_yn, read_yn, update_yn, delete_yn) VALUES (101, 1, 'Y', 'Y', 'Y', 'N'); ``` ### 시나리오 2: 개발팀 권한 그룹 **요구사항:** - 개발팀은 모든 기술 메뉴 접근 가능 - 프로젝트, 코드 관리 메뉴는 모든 권한 보유 - 시스템 설정은 조회만 가능 **구현:** ```sql -- 1. 권한 그룹 생성 INSERT INTO authority_master (objid, auth_name, auth_code, company_code, status) VALUES (nextval('seq_authority'), '개발팀 권한', 'DEV_TEAM', 'COMPANY_1', 'active'); -- 2. 메뉴 권한 설정 INSERT INTO rel_menu_auth (menu_objid, auth_objid, create_yn, read_yn, update_yn, delete_yn) VALUES (200, 2, 'Y', 'Y', 'Y', 'Y'), -- 프로젝트 관리 (모든 권한) (201, 2, 'Y', 'Y', 'Y', 'Y'), -- 코드 관리 (모든 권한) (202, 2, 'N', 'Y', 'N', 'N'); -- 시스템 설정 (조회만) ``` ## 구현 단계 ### Phase 1: 데이터베이스 마이그레이션 - [ ] `authority_master`에 `company_code` 추가 - [ ] 기존 데이터 마이그레이션 - [ ] 인덱스 생성 ### Phase 2: 백엔드 API - [ ] 권한 그룹 CRUD API - `GET /api/admin/roles` - 회사별 권한 그룹 목록 - `POST /api/admin/roles` - 권한 그룹 생성 - `PUT /api/admin/roles/:id` - 권한 그룹 수정 - `DELETE /api/admin/roles/:id` - 권한 그룹 삭제 - [ ] 권한 그룹 멤버 관리 API - `GET /api/admin/roles/:id/members` - 멤버 목록 - `POST /api/admin/roles/:id/members` - 멤버 추가 - `DELETE /api/admin/roles/:id/members/:userId` - 멤버 제거 - [ ] 메뉴 권한 매핑 API - `GET /api/admin/roles/:id/menu-permissions` - 메뉴 권한 목록 - `PUT /api/admin/roles/:id/menu-permissions` - 메뉴 권한 설정 ### Phase 3: 프론트엔드 UI - [ ] 권한 그룹 관리 페이지 (`/admin/roles`) - 권한 그룹 목록 (회사별 필터링) - 권한 그룹 생성/수정/삭제 - [ ] 권한 그룹 상세 페이지 (`/admin/roles/:id`) - 멤버 관리 (사용자 추가/제거) - 메뉴 권한 설정 (CRUD 권한 토글) - [ ] 사용자 관리 페이지 연동 - 사용자별 권한 그룹 할당 ### Phase 4: 권한 체크 로직 - [ ] 미들웨어 개선 - 권한 레벨 체크 (기존) - 권한 그룹 체크 (신규) - 메뉴별 CRUD 권한 체크 (신규) - [ ] 프론트엔드 가드 - 메뉴 표시/숨김 - 버튼 활성화/비활성화 ## 권한 체크 플로우 ``` 사용자 요청 ↓ 1. 인증 체크 (로그인 여부) ↓ 2. 권한 레벨 체크 (userType) - SUPER_ADMIN: 모든 접근 허용 - COMPANY_ADMIN: 자기 회사만 - USER: 권한 그룹 체크로 이동 ↓ 3. 권한 그룹 체크 (authority_sub_user) - 사용자가 속한 권한 그룹 조회 ↓ 4. 메뉴 권한 체크 (rel_menu_auth) - 요청한 메뉴에 대한 권한 확인 - CRUD 권한 체크 ↓ 5. 접근 허용/거부 ``` ## 예상 UI 구조 ### 권한 그룹 관리 페이지 ``` ┌─────────────────────────────────────────────────────────┐ │ 권한 그룹 관리 │ ├─────────────────────────────────────────────────────────┤ │ [회사 선택: COMPANY_1 ▼] [검색: ____] [+ 그룹 생성] │ ├─────────────────────────────────────────────────────────┤ │ ┌───────────────┬──────────┬──────────┬────────┐ │ │ │ 권한 그룹명 │ 코드 │ 멤버 수 │ 액션 │ │ │ ├───────────────┼──────────┼──────────┼────────┤ │ │ │ 영업팀 권한 │ SALES │ 5명 │ [수정] │ │ │ │ 개발팀 권한 │ DEV │ 8명 │ [수정] │ │ │ │ 관리자팀 │ ADMIN │ 2명 │ [수정] │ │ │ └───────────────┴──────────┴──────────┴────────┘ │ └─────────────────────────────────────────────────────────┘ ``` ### 권한 그룹 상세 페이지 ``` ┌─────────────────────────────────────────────────────────┐ │ 영업팀 권한 (SALES_TEAM) │ ├─────────────────────────────────────────────────────────┤ │ 【 멤버 관리 】 │ │ [+ 멤버 추가] │ │ ┌──────────┬──────────┬────────┐ │ │ │ 사용자 ID │ 이름 │ 액션 │ │ │ ├──────────┼──────────┼────────┤ │ │ │ user1 │ 김철수 │ [제거] │ │ │ │ user2 │ 이영희 │ [제거] │ │ │ └──────────┴──────────┴────────┘ │ ├─────────────────────────────────────────────────────────┤ │ 【 메뉴 권한 설정 】 │ │ ┌─────────────┬────┬────┬────┬────┐ │ │ │ 메뉴 │ 생성│ 조회│ 수정│ 삭제│ │ │ ├─────────────┼────┼────┼────┼────┤ │ │ │ 고객 관리 │ □ │ ☑ │ ☑ │ □ │ │ │ │ 계약 관리 │ ☑ │ ☑ │ ☑ │ □ │ │ │ │ 매출 분석 │ □ │ ☑ │ □ │ □ │ │ │ └─────────────┴────┴────┴────┴────┘ │ │ [저장] [취소] │ └─────────────────────────────────────────────────────────┘ ``` ## 마이그레이션 계획 ### 028_add_company_code_to_authority_master.sql ```sql -- 권한 그룹 테이블에 회사 코드 추가 ALTER TABLE authority_master ADD COLUMN IF NOT EXISTS company_code VARCHAR(20); -- 인덱스 생성 CREATE INDEX IF NOT EXISTS idx_authority_master_company ON authority_master(company_code); -- 기존 데이터 마이그레이션 UPDATE authority_master SET company_code = 'ILSHIN' WHERE company_code IS NULL; -- NOT NULL 제약 조건 추가 ALTER TABLE authority_master ALTER COLUMN company_code SET NOT NULL; ALTER TABLE authority_master ALTER COLUMN company_code SET DEFAULT 'ILSHIN'; -- 주석 추가 COMMENT ON COLUMN authority_master.company_code IS '회사 코드 (회사별 권한 그룹 격리)'; ``` ## 참고 사항 ### 권한 우선순위 1. **SUPER_ADMIN**: 모든 권한 (권한 그룹 체크 생략) 2. **COMPANY_ADMIN**: 회사 내 모든 권한 (권한 그룹 체크 생략) 3. **USER**: 권한 그룹에 따른 메뉴별 권한 ### 권한 그룹 vs 권한 레벨 - **권한 레벨**: 사용자 등록 시 최초 1회 설정 (최고 관리자가 변경) - **권한 그룹**: 회사 관리자가 자유롭게 생성/관리, 사용자는 여러 그룹에 속할 수 있음 ### 보안 고려사항 - 회사 관리자는 자기 회사의 권한 그룹만 관리 가능 - 최고 관리자는 모든 회사의 권한 그룹 관리 가능 - 권한 그룹 삭제 시 연결된 사용자/메뉴 권한도 함께 삭제 (CASCADE) ## 다음 단계 1. **마이그레이션 028 실행** → `company_code` 추가 2. **백엔드 API 개발** → 권한 그룹 CRUD 3. **프론트엔드 UI 개발** → 권한 그룹 관리 페이지 4. **권한 체크 로직 통합** → 미들웨어 개선 이 설계를 구현하시겠습니까?