finai/backend/app/api/permissions.py

87 lines
3.1 KiB
Python

from collections import OrderedDict
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy import delete, select
from sqlalchemy.orm import Session
from app.db import get_db
from app.deps import require_admin
from app.models import Permission, User
from app.models.user import role_permissions
from app.schemas.role import (
PermissionCreate,
PermissionGroup,
PermissionResponse,
PermissionUpdate,
)
from app.services.audit_service import write_audit
router = APIRouter()
def _serialize(p: Permission) -> PermissionResponse:
return PermissionResponse(id=p.id, code=p.code, name=p.name, module=p.module)
@router.get("", response_model=list[PermissionGroup])
def list_permissions(db: Session = Depends(get_db), _: User = Depends(require_admin)) -> list[PermissionGroup]:
permissions = db.scalars(select(Permission).order_by(Permission.module, Permission.id)).all()
grouped: "OrderedDict[str, list[PermissionResponse]]" = OrderedDict()
for p in permissions:
grouped.setdefault(p.module or "其他", []).append(_serialize(p))
return [PermissionGroup(module=m, items=items) for m, items in grouped.items()]
@router.post("", response_model=PermissionResponse)
def create_permission(
payload: PermissionCreate,
db: Session = Depends(get_db),
admin: User = Depends(require_admin),
) -> PermissionResponse:
if db.scalar(select(Permission).where(Permission.code == payload.code)):
raise HTTPException(status_code=409, detail="权限 code 已存在")
p = Permission(code=payload.code, name=payload.name, module=payload.module)
db.add(p)
db.flush()
write_audit(db, "permission.create", actor_id=admin.id, target_type="permission", target_id=str(p.id))
db.commit()
db.refresh(p)
return _serialize(p)
@router.patch("/{permission_id}", response_model=PermissionResponse)
def update_permission(
permission_id: int,
payload: PermissionUpdate,
db: Session = Depends(get_db),
admin: User = Depends(require_admin),
) -> PermissionResponse:
p = db.get(Permission, permission_id)
if not p:
raise HTTPException(status_code=404, detail="权限不存在")
if payload.name is not None:
p.name = payload.name
if payload.module is not None:
p.module = payload.module
write_audit(db, "permission.update", actor_id=admin.id, target_type="permission", target_id=str(p.id))
db.commit()
db.refresh(p)
return _serialize(p)
@router.delete("/{permission_id}")
def delete_permission(
permission_id: int,
db: Session = Depends(get_db),
admin: User = Depends(require_admin),
) -> dict:
p = db.get(Permission, permission_id)
if not p:
raise HTTPException(status_code=404, detail="权限不存在")
db.execute(delete(role_permissions).where(role_permissions.c.permission_id == permission_id))
write_audit(db, "permission.delete", actor_id=admin.id, target_type="permission", target_id=str(permission_id),
detail={"code": p.code, "name": p.name})
db.delete(p)
db.commit()
return {"deleted": True, "id": permission_id}