from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy.ext.asyncio import AsyncSession from fastcrud import FastCRUD from datetime import timedelta import redis.asyncio as redis from database import get_db from models import User from schemas import UserCreate, UserResponse, UserLogin, Token from utils.password import verify_password, get_password_hash from utils.jwt import create_access_token from config import app_settings from utils.redis_client import get_redis, set_token_in_redis from middleware import get_current_user router = APIRouter(prefix="/users", tags=["users"]) # 创建FastCRUD实例 user_crud = FastCRUD(User, UserResponse) @router.post("/login", response_model=Token) async def login(user_data: UserLogin, db: AsyncSession = Depends(get_db), redis_conn: redis.Redis = Depends(get_redis)): """用户登录""" # 查找用户 user = await db.query(User).filter(User.username == user_data.username).first() # 验证用户是否存在且密码正确 if not user or not verify_password(user_data.password, user.password_hash): raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="用户名或密码错误", headers={"WWW-Authenticate": "Bearer"}, ) # 创建访问令牌 access_token_expires = timedelta(minutes=app_settings.access_token_expire_minutes) access_token = create_access_token( data={"sub": str(user.id), "username": user.username}, expires_delta=access_token_expires ) # 将令牌存储到Redis expire_seconds = int(access_token_expires.total_seconds()) await set_token_in_redis(redis_conn, user.id, access_token, expire_seconds) return {"access_token": access_token, "token_type": "bearer"} @router.post("/", response_model=UserResponse) async def create_user(user_data: UserCreate, db: AsyncSession = Depends(get_db)): """创建用户""" # 生成密码哈希值 hashed_password = get_password_hash(user_data.password) # 创建用户实例,使用密码哈希值 db_user = User( username=user_data.username, nickname=user_data.nickname, email=user_data.email, phone=user_data.phone, wx_openid=user_data.wx_openid, avatar=user_data.avatar, password_hash=hashed_password, role_id=user_data.role_id ) # 使用FastCRUD创建用户 created_user = await user_crud.create(db, db_user) return created_user @router.get("/", response_model=list[UserResponse]) async def get_users(db: AsyncSession = Depends(get_db), current_user: User = Depends(get_current_user)): """获取所有用户""" users = await user_crud.get_multi(db) return users @router.get("/{user_id}", response_model=UserResponse) async def get_user(user_id: int, db: AsyncSession = Depends(get_db), current_user: User = Depends(get_current_user)): """获取单个用户""" user = await user_crud.get(db, user_id) if not user: raise HTTPException(status_code=404, detail="用户不存在") return user @router.put("/{user_id}", response_model=UserResponse) async def update_user(user_id: int, user_data: UserCreate, db: AsyncSession = Depends(get_db), current_user: User = Depends(get_current_user)): """更新用户""" # 生成密码哈希值 hashed_password = get_password_hash(user_data.password) # 准备更新数据 update_data = user_data.dict() update_data["password_hash"] = hashed_password del update_data["password"] # 删除明文密码 # 使用FastCRUD更新用户 updated_user = await user_crud.update(db, user_id, update_data) if not updated_user: raise HTTPException(status_code=404, detail="用户不存在") return updated_user @router.delete("/{user_id}") async def delete_user(user_id: int, db: AsyncSession = Depends(get_db), current_user: User = Depends(get_current_user)): """删除用户""" deleted = await user_crud.delete(db, user_id) if not deleted: raise HTTPException(status_code=404, detail="用户不存在") return {"message": "用户删除成功"} @router.post("/logout") async def logout(current_user: User = Depends(get_current_user), redis_conn: redis.Redis = Depends(get_redis)): """用户登出""" from utils.redis_client import delete_token_from_redis await delete_token_from_redis(redis_conn, current_user.id) return {"message": "登出成功"} @router.get("/me", response_model=UserResponse) async def get_current_user_info(current_user: User = Depends(get_current_user)): """获取当前用户信息""" return current_user