| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126 |
- from __future__ import annotations
- from fastapi import APIRouter, Depends, HTTPException, status
- from sqlalchemy import func
- from sqlmodel import select
- from sqlmodel.ext.asyncio.session import AsyncSession
- from app.db.session import get_async_session
- from app.models.users import User
- from app.schemas.users import UserCreate, UserRead, UserUpdate
- router = APIRouter(prefix="/users", tags=["users"])
- def _base_query():
- return select(User).where(User.is_active.is_(True))
- @router.get("/", response_model=list[UserRead])
- async def list_users(
- session: AsyncSession = Depends(get_async_session),
- ) -> list[User]:
- query = _base_query().order_by(User.created_at.desc())
- result = await session.exec(query)
- return result.all()
- @router.post("/", response_model=UserRead, status_code=status.HTTP_201_CREATED)
- async def create_user(
- payload: UserCreate,
- session: AsyncSession = Depends(get_async_session),
- ) -> User:
- # Check if username already exists
- existing = await session.exec(
- _base_query().where(func.lower(User.username) == payload.username.lower())
- )
- if existing.first():
- raise HTTPException(
- status_code=status.HTTP_409_CONFLICT,
- detail="Username already exists",
- )
- # Store password as plain text
- user = User(
- username=payload.username.strip(),
- password=payload.password,
- role=payload.role,
- )
- session.add(user)
- await session.commit()
- await session.refresh(user)
- return user
- async def _update_user_logic(
- id: int,
- payload: UserUpdate,
- session: AsyncSession,
- ) -> User:
- """更新用户的通用逻辑"""
- user = await _get_user(id, session)
- payload_dict = payload.model_dump(exclude_unset=True)
- if "username" in payload_dict:
- # Check if new username conflicts with existing user
- existing = await session.exec(
- _base_query()
- .where(func.lower(User.username) == payload.username.lower())
- .where(User.id != id)
- )
- if existing.first():
- raise HTTPException(
- status_code=status.HTTP_409_CONFLICT,
- detail="Username already exists",
- )
- user.username = payload.username.strip()
- if "password" in payload_dict:
- user.password = payload.password
- if "role" in payload_dict:
- user.role = payload.role
- await session.commit()
- await session.refresh(user)
- return user
- @router.put("/{id}", response_model=UserRead)
- async def update_user(
- id: int,
- payload: UserUpdate,
- session: AsyncSession = Depends(get_async_session),
- ) -> User:
- return await _update_user_logic(id, payload, session)
- @router.patch("/{id}", response_model=UserRead)
- async def patch_user(
- id: int,
- payload: UserUpdate,
- session: AsyncSession = Depends(get_async_session),
- ) -> User:
- return await _update_user_logic(id, payload, session)
- @router.delete("/{id}", status_code=status.HTTP_204_NO_CONTENT)
- async def delete_user(
- id: int,
- session: AsyncSession = Depends(get_async_session),
- ) -> None:
- user = await _get_user(id, session)
- user.is_active = False
- await session.commit()
- async def _get_user(id: int, session: AsyncSession) -> User:
- result = await session.exec(_base_query().where(User.id == id))
- user = result.one_or_none()
- if user is None:
- raise HTTPException(
- status_code=status.HTTP_404_NOT_FOUND,
- detail=f"User {id} not found",
- )
- return user
|