Files
M-Project/backend/routers/projects.py
hyungi 41b557a709 Fix: 페이지 간 이동 시 로그아웃 문제 해결 및 기능 개선
- 토큰 저장 키 통일 (access_token으로 일관성 확보)
- 일일공수 페이지 API 스크립트 로딩 순서 수정
- 프로젝트 관리 페이지 비활성 프로젝트 표시 문제 해결
- 업로드 카테고리에 '기타' 항목 추가 (백엔드 schemas.py 포함)
- 비밀번호 변경 기능 API 연동으로 수정
- 프로젝트 드롭다운 z-index 문제 해결
- CORS 설정 및 Nginx 구성 개선
- 비밀번호 해싱 방식 pbkdf2_sha256으로 변경 (bcrypt 72바이트 제한 해결)
2025-10-25 07:22:20 +09:00

130 lines
3.9 KiB
Python

from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.orm import Session
from typing import List
from database.database import get_db
from database.models import Project, User, UserRole
from database.schemas import ProjectCreate, ProjectUpdate, Project as ProjectSchema
from routers.auth import get_current_user
router = APIRouter(
prefix="/api/projects",
tags=["projects"]
)
def check_admin_permission(current_user: User = Depends(get_current_user)):
"""관리자 권한 확인"""
if current_user.role != UserRole.admin:
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail="관리자 권한이 필요합니다."
)
return current_user
@router.options("/")
async def projects_options():
"""OPTIONS preflight 요청 처리"""
return {"message": "OK"}
@router.post("/", response_model=ProjectSchema)
async def create_project(
project: ProjectCreate,
db: Session = Depends(get_db),
current_user: User = Depends(check_admin_permission)
):
"""프로젝트 생성 (관리자만)"""
# Job No. 중복 확인
existing_project = db.query(Project).filter(Project.job_no == project.job_no).first()
if existing_project:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="이미 존재하는 Job No.입니다."
)
# 프로젝트 생성
db_project = Project(
job_no=project.job_no,
project_name=project.project_name,
created_by_id=current_user.id
)
db.add(db_project)
db.commit()
db.refresh(db_project)
return db_project
@router.get("/", response_model=List[ProjectSchema])
async def get_projects(
skip: int = 0,
limit: int = 100,
active_only: bool = True,
db: Session = Depends(get_db)
):
"""프로젝트 목록 조회"""
query = db.query(Project)
if active_only:
query = query.filter(Project.is_active == True)
projects = query.offset(skip).limit(limit).all()
return projects
@router.get("/{project_id}", response_model=ProjectSchema)
async def get_project(
project_id: int,
db: Session = Depends(get_db)
):
"""특정 프로젝트 조회"""
project = db.query(Project).filter(Project.id == project_id).first()
if not project:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="프로젝트를 찾을 수 없습니다."
)
return project
@router.put("/{project_id}", response_model=ProjectSchema)
async def update_project(
project_id: int,
project_update: ProjectUpdate,
db: Session = Depends(get_db),
current_user: User = Depends(check_admin_permission)
):
"""프로젝트 수정 (관리자만)"""
project = db.query(Project).filter(Project.id == project_id).first()
if not project:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="프로젝트를 찾을 수 없습니다."
)
# 업데이트할 필드만 수정
update_data = project_update.dict(exclude_unset=True)
for field, value in update_data.items():
setattr(project, field, value)
db.commit()
db.refresh(project)
return project
@router.delete("/{project_id}")
async def delete_project(
project_id: int,
db: Session = Depends(get_db),
current_user: User = Depends(check_admin_permission)
):
"""프로젝트 삭제 (비활성화) (관리자만)"""
project = db.query(Project).filter(Project.id == project_id).first()
if not project:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="프로젝트를 찾을 수 없습니다."
)
# 실제 삭제 대신 비활성화
project.is_active = False
db.commit()
return {"message": "프로젝트가 삭제되었습니다."}