# 宇之然内容创作平台 - 认证API from datetime import timedelta from fastapi import APIRouter, Depends, HTTPException, status, Request from sqlalchemy.orm import Session from typing import Optional import secrets from ..core.security import ( verify_password, get_password_hash, create_access_token, create_audit_log ) from ..database import get_db from ..models import User from pydantic import BaseModel router = APIRouter() class LoginRequest(BaseModel): username: str password: str class LoginResponse(BaseModel): token: str role: str user: dict class RegisterRequest(BaseModel): username: str password: str role: str = "user" @router.post("/login", response_model=LoginResponse) async def login( login_data: LoginRequest, request: Request, db: Session = Depends(get_db) ): """用户登录""" user = db.query(User).filter(User.username == login_data.username).first() # 检查用户是否存在和密码是否正确 if not user or not verify_password(login_data.password, user.password_hash): # 记录失败的登录尝试 create_audit_log( db=db, user_id=0, # 未知用户 action="login_failed", resource_type="user", resource_id=None, details=f"用户名: {login_data.username}", ip_address=request.client.host, user_agent=request.headers.get("User-Agent", "") ) raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="用户名或密码错误" ) # 更新最后登录时间 user.last_login = __import__('datetime').datetime.utcnow() db.commit() # 创建访问令牌 access_token_expires = timedelta(minutes=10080) # 7天 access_token = create_access_token( data={"sub": user.username}, expires_delta=access_token_expires ) # 记录成功的登录 create_audit_log( db=db, user_id=user.id, action="login", resource_type="user", resource_id=user.id, details=f"登录成功", ip_address=request.client.host, user_agent=request.headers.get("User-Agent", "") ) return { "token": access_token, "role": user.role, "user": { "id": user.id, "username": user.username, "role": user.role, "created_at": user.created_at.isoformat() if user.created_at else None, "last_login": user.last_login.isoformat() if user.last_login else None } } @router.get("/me") async def read_users_me( current_user=Depends(lambda: None), # 占位符,实际由依赖注入 db: Session = Depends(get_db) ): """获取当前用户信息""" # 这里应该使用JWT验证中间件获取current_user # 简化实现... raise HTTPException(status_code=501, detail="功能待实现") @router.post("/register") async def register( user_data: RegisterRequest, db: Session = Depends(get_db) ): """用户注册(管理员功能)""" # 检查用户名是否已存在 existing_user = db.query(User).filter(User.username == user_data.username).first() if existing_user: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail="用户名已存在" ) # 创建新用户 hashed_password = get_password_hash(user_data.password) new_user = User( username=user_data.username, password_hash=hashed_password, role=user_data.role ) db.add(new_user) db.commit() db.refresh(new_user) # 记录审计日志 from .auth import create_audit_log create_audit_log( db=db, user_id=new_user.id, action="create_user", resource_type="user", resource_id=new_user.id, details=f"角色: {user_data.role}" ) return { "id": new_user.id, "username": new_user.username, "role": new_user.role, "created_at": new_user.created_at.isoformat() if new_user.created_at else None }