from datetime import timedelta from typing import Any from fastapi import APIRouter, Depends, HTTPException, status from fastapi.security import OAuth2PasswordRequestForm from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.future import select from pydantic import BaseModel, EmailStr from app.api import deps from app.core import security from app.core.config import settings from app.db.session import get_db from app.models.user import User from app.schemas.token import Token from app.schemas.user import User as UserSchema, UserCreate router = APIRouter() class RegisterRequest(BaseModel): email: EmailStr password: str full_name: str @router.post("/login", response_model=Token) async def login( db: AsyncSession = Depends(get_db), form_data: OAuth2PasswordRequestForm = Depends() ) -> Any: """ OAuth2 compatible token login, get an access token for future requests. Username field should contain the email address. """ result = await db.execute(select(User).where(User.email == form_data.username)) user = result.scalars().first() if not user or not security.verify_password(form_data.password, user.hashed_password): raise HTTPException(status_code=400, detail="邮箱或密码错误") elif not user.is_active: raise HTTPException(status_code=400, detail="用户已被禁用") access_token_expires = timedelta(minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES) return { "access_token": security.create_access_token( user.id, expires_delta=access_token_expires ), "token_type": "bearer", } @router.post("/register", response_model=UserSchema) async def register( *, db: AsyncSession = Depends(get_db), user_in: RegisterRequest, ) -> Any: """ Register a new user. """ # Check if user already exists result = await db.execute(select(User).where(User.email == user_in.email)) existing_user = result.scalars().first() if existing_user: raise HTTPException( status_code=400, detail="该邮箱已被注册", ) # Check if this is the first user (make them admin) count_result = await db.execute(select(User)) all_users = count_result.scalars().all() is_first_user = len(all_users) == 0 # Create new user db_user = User( email=user_in.email, hashed_password=security.get_password_hash(user_in.password), full_name=user_in.full_name, is_active=True, is_superuser=is_first_user, role="admin" if is_first_user else "member", ) db.add(db_user) await db.commit() await db.refresh(db_user) return db_user