Files
MoviePilot/app/api/dependencies/auth.py
DDSRem 2de976f6b3 Merge pull request #7050 from DDSRem-Dev/codex-comment-migration
docs: 统一全项目中文注释和结构化契约说明
2026-10-17 19:26:29 +08:00

189 lines
5.5 KiB
Python

"""
用户身份、授权与认证服务依赖。
"""
from typing import Any, cast
from fastapi import Depends, HTTPException
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.orm import Session
from app.adapters.web.security.access import verify_token
from app.api.context import get_async_session, get_host_runtime, get_sync_session
from app.application.security.auth import (
AuthConfigRepository,
AuthPasskeyRepository,
AuthService,
AuthUserRepository,
)
from app.application.security.passkey import PasskeyRepository, PasskeyService
from app.application.security.user import (
UserRepository,
UserService,
)
from app.application.security.userconfig import get_configured_user_configuration
from app.schemas.token import TokenPayload as _SchemaTokenPayload
from app.startup.composition.context import HostRuntime
def get_user_service(
db: AsyncSession = Depends(get_async_session),
runtime: HostRuntime = Depends(get_host_runtime),
) -> UserService:
"""
组装用户管理应用服务。
"""
return UserService(
repository=cast(
UserRepository, runtime.authentication.user_repository(db)
),
unit_of_work=runtime.persistence.async_transaction(db),
configuration=get_configured_user_configuration(),
)
def get_auth_service(
runtime: HostRuntime = Depends(get_host_runtime),
) -> AuthService:
"""
组装同步认证应用服务。
"""
return AuthService(
users=cast(AuthUserRepository, runtime.authentication.standalone_user()),
config=cast(AuthConfigRepository, runtime.authentication.system_config()),
passkeys=cast(AuthPasskeyRepository, runtime.authentication.passkey()),
)
def get_passkey_service(
runtime: HostRuntime = Depends(get_host_runtime),
) -> PasskeyService:
"""
组装 PassKey 应用服务。
"""
return PasskeyService(repository=cast(
PasskeyRepository, runtime.authentication.passkey()
))
def get_current_user(
db: Session = Depends(get_sync_session),
token_data: _SchemaTokenPayload = Depends(verify_token),
runtime: HostRuntime = Depends(get_host_runtime),
) -> Any:
"""
读取令牌对应用户;主体 ID 缺失或账号不存在时按认证失败处理。
"""
user_repository = cast(
AuthUserRepository, runtime.authentication.user_repository(db)
)
user = user_repository.get_by_id(token_data.sub) if token_data.sub is not None else None
if not user:
raise HTTPException(
status_code=401,
detail="用户不存在",
headers={"WWW-Authenticate": "Bearer"},
)
return user
async def get_current_user_async(
db: AsyncSession = Depends(get_async_session),
token_data: _SchemaTokenPayload = Depends(verify_token),
runtime: HostRuntime = Depends(get_host_runtime),
) -> Any:
"""
异步读取令牌对应用户;主体 ID 缺失或账号不存在时按认证失败处理。
"""
user_repository = cast(
UserRepository, runtime.authentication.user_repository(db)
)
user = await user_repository.async_get_by_id(token_data.sub) if token_data.sub is not None else None
if not user:
raise HTTPException(
status_code=401,
detail="用户不存在",
headers={"WWW-Authenticate": "Bearer"},
)
return user
def get_current_active_user(
current_user: Any = Depends(get_current_user),
) -> Any:
"""
校验并返回当前激活用户。
"""
if not current_user.is_active:
raise HTTPException(
status_code=401,
detail="用户未激活",
headers={"WWW-Authenticate": "Bearer"},
)
return current_user
async def get_current_active_user_async(
current_user: Any = Depends(get_current_user_async),
) -> Any:
"""
异步校验并返回当前激活用户。
"""
if not current_user.is_active:
raise HTTPException(
status_code=401,
detail="用户未激活",
headers={"WWW-Authenticate": "Bearer"},
)
return current_user
def _ensure_manage_user(current_user: Any) -> Any:
"""
校验用户具备全局管理权限。
"""
permissions = current_user.permissions or {}
if not current_user.is_superuser and not bool(permissions.get("manage")):
raise HTTPException(status_code=403, detail="用户权限不足")
return current_user
def get_current_active_manage_user(
current_user: Any = Depends(get_current_active_user),
) -> Any:
"""
返回当前拥有管理权限的激活用户。
"""
return _ensure_manage_user(current_user)
async def get_current_active_manage_user_async(
current_user: Any = Depends(get_current_active_user_async),
) -> Any:
"""
异步返回当前拥有管理权限的激活用户。
"""
return _ensure_manage_user(current_user)
def get_current_active_superuser(
current_user: Any = Depends(get_current_active_user),
) -> Any:
"""
校验并返回当前激活超级管理员。
"""
if not current_user.is_superuser:
raise HTTPException(status_code=403, detail="用户权限不足")
return current_user
async def get_current_active_superuser_async(
current_user: Any = Depends(get_current_active_user_async),
) -> Any:
"""
异步校验并返回当前激活超级管理员。
"""
if not current_user.is_superuser:
raise HTTPException(status_code=403, detail="用户权限不足")
return current_user