/
tsps
/
core
Обзор
Документация
Войти
/
tsps
/
core
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
master
app/api/admin/courts.py
122 строки
4 KB
Василий Петров
Разделение ролей - защита delete
24 мар 2026, 17:43
24 мар 2026, 17:43
8523537
Код
Авторство
О чём код?
from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy.exc import IntegrityError from sqlalchemy.orm import Session from typing import Optional from app.database import get_db from app.models.court import Court from app.schemas.court import CourtCreate, CourtRead, CourtUpdate from app.schemas.common import PaginationOut from app.core.security import get_current_admin_id, require_superadmin import logging logger = logging.getLogger(__name__) router = APIRouter( prefix="/courts", tags=["admin", "courts"], dependencies=[Depends(get_current_admin_id)] # защищаем все методы роутера ) @router.post("", response_model=CourtRead, status_code=status.HTTP_201_CREATED) def create_court( court_in: CourtCreate, admin_id: int = Depends(get_current_admin_id), db: Session = Depends(get_db) ): court = Court(name=court_in.name) db.add(court) try: db.commit() db.refresh(court) logger.info(f"Админ {admin_id} создал суд: {court.name} (ID={court.id})") except IntegrityError: db.rollback() raise HTTPException( status_code=status.HTTP_409_CONFLICT, detail="Суд с таким названием уже существует" ) return court @router.get("", response_model=PaginationOut[CourtRead]) def read_courts( skip: int = 0, limit: int = 100, name: Optional[str] = None, db: Session = Depends(get_db) ): query = db.query(Court) if name: query = query.filter(Court.name.ilike(f"%{name}%")) total = query.count() courts = query.order_by(Court.id).offset(skip).limit(limit).all() return { "items": courts, "total": total, "skip": skip, "limit": limit } @router.get("/{court_id}", response_model=CourtRead) def read_court(court_id: int, db: Session = Depends(get_db)): court = db.get(Court, court_id) if not court: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Суд не найден" ) return court @router.patch("/{court_id}", response_model=CourtRead) def update_court( court_id: int, court_update: CourtUpdate, admin_id: int = Depends(get_current_admin_id), db: Session = Depends(get_db) ): court = db.get(Court, court_id) if not court: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Суд не найден" ) update_data = court_update.model_dump(exclude_unset=True) # обновляем только переданные поля if not update_data: return court try: for field, value in update_data.items(): setattr(court, field, value) db.commit() db.refresh(court) logger.info(f"Админ {admin_id} обновил суд: {court.name} (ID={court.id})") except IntegrityError: db.rollback() raise HTTPException( status_code=status.HTTP_409_CONFLICT, detail="Суд с таким названием уже существует" ) return court @router.delete("/{court_id}", status_code=status.HTTP_204_NO_CONTENT) def delete_court( court_id: int, admin_id: int = Depends(require_superadmin), db: Session = Depends(get_db) ): court = db.get(Court, court_id) if not court: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Суд не найден" ) try: db.delete(court) db.commit() logger.info(f"Админ {admin_id} удалил суд: {court.name} (ID={court.id})") except IntegrityError: db.rollback() raise HTTPException( status_code=status.HTTP_409_CONFLICT, detail="Невозможно удалить суд: существуют связанные записи" ) return