""" 路由公共依赖。 提供“可选登录”依赖与权限判断工具: - 文章可见性控制需要区分“游客”和“登录用户” - 携带有效令牌时返回用户,未携带令牌时返回 None """ from typing import Optional from fastapi import Depends, HTTPException, status from fastapi.security import HTTPAuthorizationCredentials from sqlalchemy.orm import Session from ..auth import bearer_scheme, decode_token from ..database import get_db from ..models import ROLE_BLOGGER, ROLE_FRIEND, User def get_optional_user( credentials: HTTPAuthorizationCredentials = Depends(bearer_scheme), db: Session = Depends(get_db), ) -> Optional[User]: """可选登录依赖:未携带令牌返回 None;令牌无效返回 401;否则返回当前用户。""" if credentials is None: return None payload = decode_token(credentials.credentials) try: user_id = int(payload.get("sub")) except (TypeError, ValueError): raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="令牌无效") user = db.query(User).filter(User.id == user_id).first() # 令牌版本校验:与 get_current_user 保持一致,密码重置后旧令牌失效 if user is not None and (payload.get("ver") or 0) != (user.token_version or 0): raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="登录状态已失效,请重新登录") return user def can_read_friend_article(user: Optional[User]) -> bool: """判断用户是否具备查看好友文章的权限(friend / blogger)。""" return user is not None and user.role in (ROLE_FRIEND, ROLE_BLOGGER)