feat: Implement API routers for user, tag, vas, webdav, and slave functionalities
- Added user authentication and registration endpoints with JWT support. - Created tag management routes for creating and deleting tags. - Implemented value-added service (VAS) endpoints for managing storage packs and orders. - Developed WebDAV account management routes for creating, updating, and deleting accounts. - Introduced slave router for handling file uploads, downloads, and aria2 task management. - Enhanced JWT utility functions for token creation and secret key management. - Established lifespan management for FastAPI application startup and shutdown processes. - Integrated password handling utilities with Argon2 hashing and two-factor authentication support.
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
from sqlmodel import SQLModel
|
||||
from sqlalchemy.ext.asyncio import AsyncEngine, create_async_engine
|
||||
from sqlmodel.ext.asyncio.session import AsyncSession
|
||||
from pkg.conf import appmeta
|
||||
from utils.conf import appmeta
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
from typing import AsyncGenerator
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ from .base import TableBase, SQLModelBase, UUIDTableBase
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .user import User
|
||||
from .policy import Policy
|
||||
|
||||
|
||||
# ==================== Base 模型 ====================
|
||||
@@ -70,6 +71,10 @@ class GroupResponse(GroupBase, GroupOptionsBase):
|
||||
|
||||
# ==================== 数据库模型 ====================
|
||||
|
||||
# GroupPolicyLink 定义在 policy.py 中以避免循环导入
|
||||
from .policy import GroupPolicyLink
|
||||
|
||||
|
||||
class GroupOptions(GroupOptionsBase, TableBase, table=True):
|
||||
"""用户组选项模型"""
|
||||
|
||||
@@ -104,9 +109,6 @@ class Group(GroupBase, UUIDTableBase, table=True):
|
||||
name: str = Field(max_length=255, unique=True)
|
||||
"""用户组名"""
|
||||
|
||||
policies: str | None = Field(default=None, max_length=255)
|
||||
"""允许的策略ID列表,逗号分隔"""
|
||||
|
||||
max_storage: int = Field(default=0, sa_column_kwargs={"server_default": "0"})
|
||||
"""最大存储空间(字节)"""
|
||||
|
||||
@@ -128,6 +130,12 @@ class Group(GroupBase, UUIDTableBase, table=True):
|
||||
sa_relationship_kwargs={"uselist": False}
|
||||
)
|
||||
|
||||
# 多对多关系:用户组可以关联多个存储策略
|
||||
policies: list["Policy"] = Relationship(
|
||||
back_populates="groups",
|
||||
link_model=GroupPolicyLink,
|
||||
)
|
||||
|
||||
# 关系:一个组可以有多个用户
|
||||
user: list["User"] = Relationship(
|
||||
back_populates="group",
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
|
||||
from .setting import Setting, SettingsType
|
||||
from .color import ThemeResponse
|
||||
from pkg.conf.appmeta import BackendVersion
|
||||
from pkg.password.pwd import Password
|
||||
from utils.conf.appmeta import BackendVersion
|
||||
from utils.password.pwd import Password
|
||||
from loguru import logger as log
|
||||
|
||||
async def migration() -> None:
|
||||
@@ -138,12 +138,17 @@ async def init_default_settings() -> None:
|
||||
|
||||
async def init_default_group() -> None:
|
||||
from .group import Group, GroupOptions
|
||||
from .policy import Policy, GroupPolicyLink
|
||||
from .setting import Setting
|
||||
from .database import get_session
|
||||
|
||||
log.info('初始化用户组...')
|
||||
|
||||
async for session in get_session():
|
||||
# 获取默认存储策略
|
||||
default_policy = await Policy.get(session, Policy.name == "本地存储")
|
||||
default_policy_id = default_policy.id if default_policy else None
|
||||
|
||||
# 未找到初始管理组时,则创建
|
||||
if not await Group.get(session, Group.name == "管理员"):
|
||||
admin_group = Group(
|
||||
@@ -167,6 +172,14 @@ async def init_default_group() -> None:
|
||||
advance_delete=True,
|
||||
).save(session)
|
||||
|
||||
# 关联默认存储策略
|
||||
if default_policy_id:
|
||||
session.add(GroupPolicyLink(
|
||||
group_id=admin_group_id,
|
||||
policy_id=default_policy_id,
|
||||
))
|
||||
await session.commit()
|
||||
|
||||
# 未找到初始注册会员时,则创建
|
||||
if not await Group.get(session, Group.name == "注册会员"):
|
||||
member_group = Group(
|
||||
@@ -183,6 +196,14 @@ async def init_default_group() -> None:
|
||||
share_download=True,
|
||||
).save(session)
|
||||
|
||||
# 关联默认存储策略
|
||||
if default_policy_id:
|
||||
session.add(GroupPolicyLink(
|
||||
group_id=member_group_id,
|
||||
policy_id=default_policy_id,
|
||||
))
|
||||
await session.commit()
|
||||
|
||||
# 更新 default_group 设置为注册会员组的 UUID
|
||||
default_group_setting = await Setting.get(session, Setting.name == "default_group")
|
||||
if default_group_setting:
|
||||
@@ -204,6 +225,8 @@ async def init_default_group() -> None:
|
||||
share_download=True,
|
||||
).save(session)
|
||||
|
||||
# 游客组不关联存储策略(无法上传)
|
||||
|
||||
async def init_default_user() -> None:
|
||||
from .user import User
|
||||
from .group import Group
|
||||
|
||||
@@ -1,12 +1,24 @@
|
||||
from typing import TYPE_CHECKING
|
||||
from uuid import UUID
|
||||
|
||||
from enum import StrEnum
|
||||
from sqlmodel import Field, Relationship, text
|
||||
|
||||
from .base import UUIDTableBase
|
||||
from .base import SQLModelBase, UUIDTableBase
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .object import Object
|
||||
from .group import Group
|
||||
|
||||
|
||||
class GroupPolicyLink(SQLModelBase, table=True):
|
||||
"""用户组与存储策略的多对多关联表"""
|
||||
|
||||
group_id: UUID = Field(foreign_key="group.id", primary_key=True)
|
||||
"""用户组UUID"""
|
||||
|
||||
policy_id: UUID = Field(foreign_key="policy.id", primary_key=True)
|
||||
"""存储策略UUID"""
|
||||
|
||||
class PolicyType(StrEnum):
|
||||
LOCAL = "local"
|
||||
@@ -60,6 +72,12 @@ class Policy(UUIDTableBase, table=True):
|
||||
# 关系
|
||||
objects: list["Object"] = Relationship(back_populates="policy")
|
||||
"""策略下的所有对象"""
|
||||
|
||||
# 多对多关系:策略可以被多个用户组使用
|
||||
groups: list["Group"] = Relationship(
|
||||
back_populates="policies",
|
||||
link_model=GroupPolicyLink,
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
async def create(
|
||||
|
||||
@@ -10,17 +10,8 @@ from sqlmodel import Field
|
||||
from .base import SQLModelBase
|
||||
|
||||
# [TODO] 未来把这拆了,直接按需返回状态码
|
||||
class ResponseModel(SQLModelBase):
|
||||
class ResponseBase(SQLModelBase):
|
||||
"""通用响应模型"""
|
||||
|
||||
code: int = Field(default=0, ge=0, lt=60000)
|
||||
"""系统内部状态码,0表示成功,其他表示失败"""
|
||||
|
||||
data: Any = None
|
||||
"""响应数据"""
|
||||
|
||||
msg: str | None = None
|
||||
"""响应消息,可以是错误消息或信息提示"""
|
||||
|
||||
instance_id: uuid.UUID = Field(default_factory=uuid.uuid4)
|
||||
"""实例ID,用于标识请求的唯一性"""
|
||||
|
||||
Reference in New Issue
Block a user