🔧 Menu Integration: - 공통 헤더의 목록관리 서브메뉴에 현황판 추가 - 아이콘: fas fa-chart-line (보라색) - URL: /issues-dashboard.html 🔓 Permission Update: - 현황판 기본 접근 권한을 True로 변경 - 모든 사용자가 기본적으로 현황판 접근 가능 - 사용자 관리에서 권한 설정 가능 📍 Navigation Path: 목록관리 → 현황판 (4번째 서브메뉴) - 수신함 - 관리함 - 폐기함 - 현황판 ← NEW Expected Result: ✅ 헤더 메뉴에서 현황판 접근 가능 ✅ 모든 사용자 기본 접근 권한 보유 ✅ 사용자 관리에서 권한 설정 표시
330 lines
11 KiB
Python
330 lines
11 KiB
Python
"""
|
|
페이지 권한 관리 API 라우터
|
|
사용자별 페이지 접근 권한을 관리하는 엔드포인트들
|
|
"""
|
|
|
|
from fastapi import APIRouter, Depends, HTTPException, status
|
|
from sqlalchemy.orm import Session
|
|
from typing import List, Optional
|
|
from pydantic import BaseModel
|
|
|
|
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: str
|
|
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)
|
|
}
|