""" 페이지 권한 관리 API 라우터 사용자별 페이지 접근 권한을 관리하는 엔드포인트들 """ from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy.orm import Session from typing import List, Optional from pydantic import BaseModel, Field from datetime import datetime from database.database import get_db from database.models import User, UserPagePermission, UserRole from routers.auth import get_current_user router = APIRouter(prefix="/api", tags=["page-permissions"]) # Pydantic 모델들 class PagePermissionRequest(BaseModel): user_id: int page_name: str can_access: bool notes: Optional[str] = None class PagePermissionResponse(BaseModel): id: int user_id: int page_name: str can_access: bool granted_by_id: Optional[int] granted_at: Optional[datetime] notes: Optional[str] class Config: from_attributes = True class UserPagePermissionSummary(BaseModel): user_id: int username: str full_name: Optional[str] role: str permissions: List[PagePermissionResponse] # 기본 페이지 목록 DEFAULT_PAGES = { 'issues_create': {'title': '부적합 등록', 'default_access': True}, 'issues_view': {'title': '부적합 조회', 'default_access': True}, 'issues_manage': {'title': '부적합 관리', 'default_access': True}, 'issues_inbox': {'title': '수신함', 'default_access': True}, 'issues_management': {'title': '관리함', 'default_access': False}, 'issues_archive': {'title': '폐기함', 'default_access': False}, 'issues_dashboard': {'title': '현황판', 'default_access': True}, 'projects_manage': {'title': '프로젝트 관리', 'default_access': False}, 'daily_work': {'title': '일일 공수', 'default_access': False}, 'reports': {'title': '보고서', 'default_access': False}, 'users_manage': {'title': '사용자 관리', 'default_access': False} } @router.post("/page-permissions/grant") async def grant_page_permission( request: PagePermissionRequest, db: Session = Depends(get_db), current_user: User = Depends(get_current_user) ): """페이지 권한 부여/취소""" # 관리자만 권한 설정 가능 if current_user.role != UserRole.admin: raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail="관리자만 권한을 설정할 수 있습니다." ) # 대상 사용자 확인 target_user = db.query(User).filter(User.id == request.user_id).first() if not target_user: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="사용자를 찾을 수 없습니다." ) # 유효한 페이지명 확인 if request.page_name not in DEFAULT_PAGES: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail="유효하지 않은 페이지명입니다." ) # 기존 권한 확인 existing_permission = db.query(UserPagePermission).filter( UserPagePermission.user_id == request.user_id, UserPagePermission.page_name == request.page_name ).first() if existing_permission: # 기존 권한 업데이트 existing_permission.can_access = request.can_access existing_permission.granted_by_id = current_user.id existing_permission.notes = request.notes db.commit() db.refresh(existing_permission) return {"message": "권한이 업데이트되었습니다.", "permission_id": existing_permission.id} else: # 새 권한 생성 new_permission = UserPagePermission( user_id=request.user_id, page_name=request.page_name, can_access=request.can_access, granted_by_id=current_user.id, notes=request.notes ) db.add(new_permission) db.commit() db.refresh(new_permission) return {"message": "권한이 설정되었습니다.", "permission_id": new_permission.id} @router.get("/users/{user_id}/page-permissions", response_model=List[PagePermissionResponse]) async def get_user_page_permissions( user_id: int, db: Session = Depends(get_db), current_user: User = Depends(get_current_user) ): """특정 사용자의 페이지 권한 목록 조회""" # 관리자이거나 본인의 권한만 조회 가능 if current_user.role != UserRole.admin and current_user.id != user_id: raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail="권한이 없습니다." ) # 사용자 존재 확인 user = db.query(User).filter(User.id == user_id).first() if not user: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="사용자를 찾을 수 없습니다." ) # 사용자의 페이지 권한 조회 permissions = db.query(UserPagePermission).filter( UserPagePermission.user_id == user_id ).all() return permissions @router.get("/page-permissions/check/{user_id}/{page_name}") async def check_page_access( user_id: int, page_name: str, db: Session = Depends(get_db), current_user: User = Depends(get_current_user) ): """특정 사용자의 특정 페이지 접근 권한 확인""" # 사용자 존재 확인 user = db.query(User).filter(User.id == user_id).first() if not user: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="사용자를 찾을 수 없습니다." ) # admin은 모든 페이지 접근 가능 if user.role == UserRole.admin: return {"can_access": True, "reason": "admin_role"} # 유효한 페이지명 확인 if page_name not in DEFAULT_PAGES: return {"can_access": False, "reason": "invalid_page"} # 개별 권한 확인 permission = db.query(UserPagePermission).filter( UserPagePermission.user_id == user_id, UserPagePermission.page_name == page_name ).first() if permission: return { "can_access": permission.can_access, "reason": "explicit_permission", "granted_at": permission.granted_at.isoformat() if permission.granted_at else None } # 기본 권한 확인 default_access = DEFAULT_PAGES[page_name]['default_access'] return { "can_access": default_access, "reason": "default_permission" } @router.get("/page-permissions/all-users", response_model=List[UserPagePermissionSummary]) async def get_all_users_permissions( db: Session = Depends(get_db), current_user: User = Depends(get_current_user) ): """모든 사용자의 페이지 권한 요약 조회 (관리자용)""" if current_user.role != UserRole.admin: raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail="관리자만 접근할 수 있습니다." ) # 모든 사용자 조회 users = db.query(User).filter(User.is_active == True).all() result = [] for user in users: # 각 사용자의 권한 조회 permissions = db.query(UserPagePermission).filter( UserPagePermission.user_id == user.id ).all() result.append(UserPagePermissionSummary( user_id=user.id, username=user.username, full_name=user.full_name, role=user.role.value, permissions=permissions )) return result @router.get("/page-permissions/available-pages") async def get_available_pages( current_user: User = Depends(get_current_user) ): """사용 가능한 페이지 목록 조회""" return { "pages": DEFAULT_PAGES, "total_count": len(DEFAULT_PAGES) } @router.delete("/page-permissions/{permission_id}") async def delete_page_permission( permission_id: int, db: Session = Depends(get_db), current_user: User = Depends(get_current_user) ): """페이지 권한 삭제 (기본값으로 되돌림)""" if current_user.role != UserRole.admin: raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail="관리자만 권한을 삭제할 수 있습니다." ) # 권한 조회 permission = db.query(UserPagePermission).filter( UserPagePermission.id == permission_id ).first() if not permission: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="권한을 찾을 수 없습니다." ) # 권한 삭제 db.delete(permission) db.commit() return {"message": "권한이 삭제되었습니다. 기본값이 적용됩니다."} class BulkPermissionRequest(BaseModel): user_id: int permissions: List[dict] # [{"page_name": "issues_manage", "can_access": true}, ...] @router.post("/page-permissions/bulk-grant") async def bulk_grant_permissions( request: BulkPermissionRequest, db: Session = Depends(get_db), current_user: User = Depends(get_current_user) ): """사용자의 여러 페이지 권한을 일괄 설정""" if current_user.role != UserRole.admin: raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail="관리자만 권한을 설정할 수 있습니다." ) # 대상 사용자 확인 target_user = db.query(User).filter(User.id == request.user_id).first() if not target_user: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="사용자를 찾을 수 없습니다." ) updated_permissions = [] for perm_data in request.permissions: page_name = perm_data.get('page_name') can_access = perm_data.get('can_access', False) # 유효한 페이지명 확인 if page_name not in DEFAULT_PAGES: continue # 기존 권한 확인 existing_permission = db.query(UserPagePermission).filter( UserPagePermission.user_id == request.user_id, UserPagePermission.page_name == page_name ).first() if existing_permission: # 기존 권한 업데이트 existing_permission.can_access = can_access existing_permission.granted_by_id = current_user.id updated_permissions.append(existing_permission) else: # 새 권한 생성 new_permission = UserPagePermission( user_id=request.user_id, page_name=page_name, can_access=can_access, granted_by_id=current_user.id ) db.add(new_permission) updated_permissions.append(new_permission) db.commit() return { "message": f"{len(updated_permissions)}개의 권한이 설정되었습니다.", "updated_count": len(updated_permissions) }