Files
QQuiz/backend/services/auth_service.py
handsomezhuzhu ed87aae014 docs: 完善文档和清理项目,添加 Gemini 配置指南
主要更新:

📚 文档改进
- 新增 AI_CONFIGURATION.md:详细的 AI 提供商配置指南
- 新增 CHINA_MIRROR_GUIDE.md:中国镜像加速指南
- 删除 6 个过时文档(DEPLOYMENT.md, QUICK_START.md 等)
- 更新 README.md:添加 Gemini 功能特性和 AI 提供商对比表

🧹 脚本清理
- 删除 11 个重复/过时脚本(从 25 个减少到 14 个)
- 删除 PostgreSQL 相关脚本(项目使用 MySQL)
- 删除重复的启动脚本(start_windows.bat, start_app.bat 等)

⚙️ 配置文件更新
- 更新 .env.example:添加 Gemini 配置示例和说明
- 默认 AI_PROVIDER 改为 gemini(推荐)
- 添加各提供商的获取 API Key 链接

🎯 核心改进
- 突出 Gemini 原生 PDF 理解优势
- 提供清晰的 AI 提供商选择指南
- 简化项目结构,提高可维护性

清理内容:
- 删除 docs: DEPLOYMENT.md, DOCKER_MIRROR_SETUP.md, GITHUB_PUSH_GUIDE.md,
  QUICK_START.md, README_QUICKSTART.md, START_HERE.txt
- 删除 scripts: auto_setup_and_run.bat, check_postgres.bat, logs_windows.bat,
  push_to_github.bat, quick_config.bat, restart_docker.bat, setup_docker_mirror.bat,
  start_app.bat, start_postgres.bat, start_windows.bat, start_windows_china.bat

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-01 23:21:04 +08:00

85 lines
2.2 KiB
Python

"""
Authentication Service
"""
from fastapi import Depends, HTTPException, status
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select
from typing import Optional
from models import User
from database import get_db
from utils import decode_access_token
security = HTTPBearer()
async def get_current_user(
credentials: HTTPAuthorizationCredentials = Depends(security),
db: AsyncSession = Depends(get_db)
) -> User:
"""
Get current authenticated user from JWT token.
"""
token = credentials.credentials
credentials_exception = HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Could not validate credentials",
headers={"WWW-Authenticate": "Bearer"},
)
# Decode token
payload = decode_access_token(token)
if payload is None:
raise credentials_exception
user_id = payload.get("sub")
if user_id is None:
raise credentials_exception
# Convert user_id to int if it's a string
try:
user_id = int(user_id)
except (ValueError, TypeError):
raise credentials_exception
# Get user from database
result = await db.execute(select(User).where(User.id == user_id))
user = result.scalar_one_or_none()
if user is None:
raise credentials_exception
return user
async def get_current_admin_user(
current_user: User = Depends(get_current_user)
) -> User:
"""
Get current user and verify admin permissions.
"""
if not current_user.is_admin:
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail="Not enough permissions"
)
return current_user
async def get_optional_user(
credentials: Optional[HTTPAuthorizationCredentials] = Depends(security),
db: AsyncSession = Depends(get_db)
) -> Optional[User]:
"""
Get current user if token is provided, otherwise return None.
Useful for endpoints that work for both authenticated and anonymous users.
"""
if credentials is None:
return None
try:
return await get_current_user(credentials, db)
except HTTPException:
return None