mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-08-30 04:27:40 +08:00
148 lines
4.8 KiB
Python
148 lines
4.8 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.passkeys import PasskeyRepository, PasskeyService
|
|
from app.application.security.user import (
|
|
AsyncUnitOfWork,
|
|
UserRepository,
|
|
UserService,
|
|
)
|
|
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=cast(
|
|
AsyncUnitOfWork, runtime.persistence.async_transaction(db)
|
|
),
|
|
)
|
|
|
|
|
|
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:
|
|
"""读取令牌对应用户,不存在时返回 403。"""
|
|
user_repository = cast(
|
|
AuthUserRepository, runtime.authentication.user_repository(db)
|
|
)
|
|
user = user_repository.get_by_id(token_data.sub)
|
|
if not user:
|
|
raise HTTPException(status_code=403, detail="用户不存在")
|
|
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:
|
|
"""异步读取令牌对应用户,不存在时返回 403。"""
|
|
user_repository = cast(
|
|
UserRepository, runtime.authentication.user_repository(db)
|
|
)
|
|
user = await user_repository.async_get_by_id(token_data.sub)
|
|
if not user:
|
|
raise HTTPException(status_code=403, detail="用户不存在")
|
|
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=403, detail="用户未激活")
|
|
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=403, detail="用户未激活")
|
|
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=400, 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_user),
|
|
) -> Any:
|
|
"""校验并返回当前激活超级管理员。"""
|
|
if not current_user.is_superuser:
|
|
raise HTTPException(status_code=400, detail="用户权限不足")
|
|
return current_user
|
|
|
|
|
|
async def get_current_active_superuser_async(
|
|
current_user: Any = Depends(get_current_user_async),
|
|
) -> Any:
|
|
"""异步校验并返回当前激活超级管理员。"""
|
|
if not current_user.is_superuser:
|
|
raise HTTPException(status_code=400, detail="用户权限不足")
|
|
return current_user
|