Files
MoviePilot/app/db/oper/user.py
2026-08-23 23:33:07 +08:00

168 lines
5.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
用户数据访问。
认证依赖(get_current_user 等八个)已迁至 app/api/deps.py——那是 HTTP 层的关注点,
产出 403/400 而非数据。本模块只保留 UserOper。
这里不为那八个名字留惰性转发,否则会把
app.db.oper.user -> app.api.deps -> app.application.security 这条边永久焊进依赖图,
让数据访问模块在静态分析里牵着整个鉴权栈。仓外插件的旧 ``app.db.user_oper`` 路径由
runtime 兼容映射指向 SDK 薄门面;canonical 数据访问模块仍只依赖模型,不承担兼容职责。
"""
from typing import List, Optional
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select
from app.db.base import DbOper
from app.db.models.user import User
class UserOper(DbOper):
"""
用户管理
"""
def list(self) -> List[User]:
"""
获取用户列表
"""
return self._execute_sync_query(User.list)
def add(self, **kwargs):
"""
新增用户
"""
user = User(**kwargs)
self._stage_create(user)
def get_by_name(self, name: str) -> Optional[User]:
"""
根据用户名获取用户
"""
return self._execute_sync_query(
lambda session: User.get_by_name(session, name)
)
def get_by_id(self, user_id: int) -> Optional[User]:
"""按 ID 获取用户。"""
return self._execute_sync_query(
lambda session: User.get_by_id(session, user_id)
)
async def async_list(self) -> List[User]:
"""异步获取用户列表。"""
return await self._execute_async_query(User.async_list)
async def async_create(self, payload: dict) -> Optional[User]:
"""异步创建用户。"""
user = User(**payload)
async def stage(session: AsyncSession) -> User:
"""在当前异步事务中暂存用户并分配主键。"""
session.add(user)
await session.flush()
return user
return await self._execute_async_write(stage)
async def async_update(self, user_id: int, payload: dict) -> Optional[User]:
"""异步更新用户。"""
user = await self.async_get_by_id(user_id)
if user:
async def stage(session: AsyncSession) -> User:
"""在当前事务中更新用户字段,必要时重新附加游离对象。"""
for key, value in payload.items():
setattr(user, key, value)
return await session.merge(user)
await self._execute_async_write(stage)
return user
async def async_delete(self, user_id: int) -> bool:
"""异步删除用户。"""
return bool(await self._execute_async_write(
lambda session: User.async_delete_by_id(session, user_id)
))
async def async_delete_by_name(self, name: str) -> bool:
"""在独立异步事务中按用户名删除用户。"""
return bool(await self._execute_async_write(
lambda session: User().async_delete_by_name(session, name)
))
async def async_update_otp_by_name(
self,
name: str,
otp: bool,
secret: str,
) -> bool:
"""异步更新用户 OTP 状态。"""
return bool(await self._execute_async_write(
lambda session: User.async_update_otp_by_name(
session, name, otp, secret
)
))
async def async_get_by_name(self, name: str) -> Optional[User]:
"""
异步根据用户名获取用户。
"""
async def query(session: AsyncSession) -> Optional[User]:
"""在调用方异步会话中执行用户名查询。"""
result = await session.execute(select(User).where(User.name == name))
return result.scalars().first()
return await self._execute_async_query(query)
async def async_get_by_id(self, user_id: int) -> Optional[User]:
"""
异步根据用户 ID 获取用户。
"""
async def query(session: AsyncSession) -> Optional[User]:
"""在调用方异步会话中执行用户 ID 查询。"""
result = await session.execute(select(User).where(User.id == user_id))
return result.scalars().first()
return await self._execute_async_query(query)
def get_permissions(self, name: str) -> dict:
"""
获取用户权限
"""
user = self.get_by_name(name)
if user:
return user.permissions or {}
return {}
def get_settings(self, name: str) -> Optional[dict]:
"""
获取用户个性化设置,返回None表示用户不存在
"""
user = self.get_by_name(name)
if user:
return user.settings or {}
return None
def get_setting(self, name: str, key: str) -> Optional[str]:
"""
获取用户个性化设置
"""
settings = self.get_settings(name)
if settings:
return settings.get(key)
return None
def get_name(self, **kwargs) -> Optional[str]:
"""
根据绑定账号获取用户名称
"""
users = self.list()
for user in users:
user_setting = user.settings
if user_setting:
for k, v in kwargs.items():
if user_setting.get(k) == str(v):
return user.name
return None