230 lines
6.9 KiB
Python
230 lines
6.9 KiB
Python
from typing import Any, List, Optional
|
|
from fastapi import APIRouter, Body, Depends, HTTPException, Query
|
|
from fastapi.encoders import jsonable_encoder
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
from sqlalchemy.future import select
|
|
from sqlalchemy import func, or_
|
|
|
|
from app.api import deps
|
|
from app.core import security
|
|
from app.db.session import get_db
|
|
from app.models.user import User
|
|
from app.schemas.user import User as UserSchema, UserCreate, UserUpdate, UserListResponse
|
|
|
|
router = APIRouter()
|
|
|
|
@router.get("/", response_model=UserListResponse)
|
|
async def read_users(
|
|
db: AsyncSession = Depends(get_db),
|
|
skip: int = Query(0, ge=0),
|
|
limit: int = Query(20, ge=1, le=100),
|
|
search: Optional[str] = Query(None, description="搜索关键词"),
|
|
role: Optional[str] = Query(None, description="角色筛选"),
|
|
is_active: Optional[bool] = Query(None, description="状态筛选"),
|
|
current_user: User = Depends(deps.get_current_user),
|
|
) -> Any:
|
|
"""
|
|
获取用户列表(支持分页、搜索、筛选)
|
|
"""
|
|
query = select(User)
|
|
count_query = select(func.count(User.id))
|
|
|
|
# 搜索条件
|
|
if search:
|
|
search_filter = or_(
|
|
User.email.ilike(f"%{search}%"),
|
|
User.full_name.ilike(f"%{search}%"),
|
|
User.phone.ilike(f"%{search}%")
|
|
)
|
|
query = query.where(search_filter)
|
|
count_query = count_query.where(search_filter)
|
|
|
|
# 角色筛选
|
|
if role:
|
|
query = query.where(User.role == role)
|
|
count_query = count_query.where(User.role == role)
|
|
|
|
# 状态筛选
|
|
if is_active is not None:
|
|
query = query.where(User.is_active == is_active)
|
|
count_query = count_query.where(User.is_active == is_active)
|
|
|
|
# 获取总数
|
|
total_result = await db.execute(count_query)
|
|
total = total_result.scalar()
|
|
|
|
# 分页查询
|
|
query = query.order_by(User.created_at.desc()).offset(skip).limit(limit)
|
|
result = await db.execute(query)
|
|
users = result.scalars().all()
|
|
|
|
return {
|
|
"users": users,
|
|
"total": total,
|
|
"skip": skip,
|
|
"limit": limit
|
|
}
|
|
|
|
@router.post("/", response_model=UserSchema)
|
|
async def create_user(
|
|
*,
|
|
db: AsyncSession = Depends(get_db),
|
|
user_in: UserCreate,
|
|
current_user: User = Depends(deps.get_current_active_superuser),
|
|
) -> Any:
|
|
"""
|
|
创建新用户(仅管理员)
|
|
"""
|
|
result = await db.execute(select(User).where(User.email == user_in.email))
|
|
user = result.scalars().first()
|
|
if user:
|
|
raise HTTPException(
|
|
status_code=400,
|
|
detail="该邮箱已被注册",
|
|
)
|
|
|
|
db_user = User(
|
|
email=user_in.email,
|
|
hashed_password=security.get_password_hash(user_in.password),
|
|
full_name=user_in.full_name,
|
|
phone=user_in.phone,
|
|
role=user_in.role,
|
|
is_active=user_in.is_active if user_in.is_active is not None else True,
|
|
is_superuser=user_in.is_superuser if user_in.is_superuser is not None else False,
|
|
)
|
|
db.add(db_user)
|
|
await db.commit()
|
|
await db.refresh(db_user)
|
|
return db_user
|
|
|
|
@router.get("/me", response_model=UserSchema)
|
|
async def read_user_me(
|
|
current_user: User = Depends(deps.get_current_user),
|
|
) -> Any:
|
|
"""
|
|
获取当前用户信息
|
|
"""
|
|
return current_user
|
|
|
|
@router.put("/me", response_model=UserSchema)
|
|
async def update_user_me(
|
|
*,
|
|
db: AsyncSession = Depends(get_db),
|
|
user_in: UserUpdate,
|
|
current_user: User = Depends(deps.get_current_user),
|
|
) -> Any:
|
|
"""
|
|
更新当前用户信息
|
|
"""
|
|
update_data = user_in.model_dump(exclude_unset=True)
|
|
|
|
# 普通用户不能修改自己的角色和超级管理员状态
|
|
update_data.pop('role', None)
|
|
update_data.pop('is_superuser', None)
|
|
update_data.pop('is_active', None)
|
|
|
|
# 如果更新密码
|
|
if 'password' in update_data and update_data['password']:
|
|
update_data['hashed_password'] = security.get_password_hash(update_data['password'])
|
|
update_data.pop('password', None)
|
|
|
|
for field, value in update_data.items():
|
|
setattr(current_user, field, value)
|
|
|
|
await db.commit()
|
|
await db.refresh(current_user)
|
|
return current_user
|
|
|
|
@router.get("/{user_id}", response_model=UserSchema)
|
|
async def read_user(
|
|
user_id: str,
|
|
db: AsyncSession = Depends(get_db),
|
|
current_user: User = Depends(deps.get_current_user),
|
|
) -> Any:
|
|
"""
|
|
获取指定用户信息
|
|
"""
|
|
result = await db.execute(select(User).where(User.id == user_id))
|
|
user = result.scalars().first()
|
|
if not user:
|
|
raise HTTPException(status_code=404, detail="用户不存在")
|
|
return user
|
|
|
|
@router.put("/{user_id}", response_model=UserSchema)
|
|
async def update_user(
|
|
user_id: str,
|
|
*,
|
|
db: AsyncSession = Depends(get_db),
|
|
user_in: UserUpdate,
|
|
current_user: User = Depends(deps.get_current_active_superuser),
|
|
) -> Any:
|
|
"""
|
|
更新用户信息(仅管理员)
|
|
"""
|
|
result = await db.execute(select(User).where(User.id == user_id))
|
|
user = result.scalars().first()
|
|
if not user:
|
|
raise HTTPException(status_code=404, detail="用户不存在")
|
|
|
|
update_data = user_in.model_dump(exclude_unset=True)
|
|
|
|
# 如果更新密码
|
|
if 'password' in update_data and update_data['password']:
|
|
update_data['hashed_password'] = security.get_password_hash(update_data['password'])
|
|
update_data.pop('password', None)
|
|
|
|
for field, value in update_data.items():
|
|
setattr(user, field, value)
|
|
|
|
await db.commit()
|
|
await db.refresh(user)
|
|
return user
|
|
|
|
@router.delete("/{user_id}")
|
|
async def delete_user(
|
|
user_id: str,
|
|
db: AsyncSession = Depends(get_db),
|
|
current_user: User = Depends(deps.get_current_active_superuser),
|
|
) -> Any:
|
|
"""
|
|
删除用户(仅管理员)
|
|
"""
|
|
if user_id == current_user.id:
|
|
raise HTTPException(status_code=400, detail="不能删除自己的账户")
|
|
|
|
result = await db.execute(select(User).where(User.id == user_id))
|
|
user = result.scalars().first()
|
|
if not user:
|
|
raise HTTPException(status_code=404, detail="用户不存在")
|
|
|
|
await db.delete(user)
|
|
await db.commit()
|
|
return {"message": "用户已删除"}
|
|
|
|
@router.post("/{user_id}/toggle-status", response_model=UserSchema)
|
|
async def toggle_user_status(
|
|
user_id: str,
|
|
db: AsyncSession = Depends(get_db),
|
|
current_user: User = Depends(deps.get_current_active_superuser),
|
|
) -> Any:
|
|
"""
|
|
切换用户状态(启用/禁用)
|
|
"""
|
|
if user_id == current_user.id:
|
|
raise HTTPException(status_code=400, detail="不能禁用自己的账户")
|
|
|
|
result = await db.execute(select(User).where(User.id == user_id))
|
|
user = result.scalars().first()
|
|
if not user:
|
|
raise HTTPException(status_code=404, detail="用户不存在")
|
|
|
|
user.is_active = not user.is_active
|
|
await db.commit()
|
|
await db.refresh(user)
|
|
return user
|
|
|
|
|
|
|
|
|
|
|