feat: add models for physical files, policies, and user management

- Implement PhysicalFile model to manage physical file references and reference counting.
- Create Policy model with associated options and group links for storage policies.
- Introduce Redeem and Report models for handling redeem codes and reports.
- Add Settings model for site configuration and user settings management.
- Develop Share model for sharing objects with unique codes and associated metadata.
- Implement SourceLink model for managing download links associated with objects.
- Create StoragePack model for managing user storage packages.
- Add Tag model for user-defined tags with manual and automatic types.
- Implement Task model for managing background tasks with status tracking.
- Develop User model with comprehensive user management features including authentication.
- Introduce UserAuthn model for managing WebAuthn credentials.
- Create WebDAV model for managing WebDAV accounts associated with users.
This commit is contained in:
2026-02-10 16:25:49 +08:00
parent 62c671e07b
commit 209cb24ab4
92 changed files with 3640 additions and 1444 deletions

198
sqlmodels/download.py Normal file
View File

@@ -0,0 +1,198 @@
from enum import StrEnum
from typing import TYPE_CHECKING, Annotated
from uuid import UUID
from sqlmodel import Field, Relationship, UniqueConstraint, Index
from .base import SQLModelBase
from .mixin import UUIDTableBaseMixin, TableBaseMixin
if TYPE_CHECKING:
from .user import User
from .task import Task
from .node import Node
class DownloadStatus(StrEnum):
"""下载状态枚举"""
PREPARING = "preparing"
"""准备中"""
RUNNING = "running"
"""进行中"""
COMPLETED = "completed"
"""已完成"""
ERROR = "error"
"""错误"""
class DownloadType(StrEnum):
"""下载类型枚举"""
# [TODO] 补充具体下载类型
pass
# ==================== Aria2 信息模型 ====================
class DownloadAria2InfoBase(SQLModelBase):
"""Aria2下载信息基础模型"""
info_hash: Annotated[str | None, Field(max_length=40)] = None
"""InfoHashBT种子"""
piece_length: int = 0
"""分片大小"""
num_pieces: int = 0
"""分片数量"""
num_seeders: int = 0
"""做种人数"""
connections: int = 0
"""连接数"""
upload_speed: int = 0
"""上传速度bytes/s"""
upload_length: int = 0
"""已上传大小(字节)"""
error_code: str | None = None
"""错误代码"""
error_message: str | None = None
"""错误信息"""
class DownloadAria2Info(DownloadAria2InfoBase, SQLModelBase, table=True):
"""Aria2下载信息模型与Download一对一关联"""
download_id: UUID = Field(
foreign_key="download.id",
primary_key=True,
ondelete="CASCADE"
)
"""关联的下载任务UUID"""
# 反向关系
download: "Download" = Relationship(back_populates="aria2_info")
"""关联的下载任务"""
class DownloadAria2File(SQLModelBase, TableBaseMixin):
"""Aria2下载文件列表与Download一对多关联"""
download_id: UUID = Field(
foreign_key="download.id",
index=True,
ondelete="CASCADE"
)
"""关联的下载任务UUID"""
file_index: int = Field(ge=1)
"""文件索引从1开始"""
path: str
"""文件路径"""
length: int = 0
"""文件大小(字节)"""
completed_length: int = 0
"""已完成大小(字节)"""
is_selected: bool = True
"""是否选中下载"""
# 反向关系
download: "Download" = Relationship(back_populates="aria2_files")
"""关联的下载任务"""
# ==================== 主模型 ====================
class DownloadBase(SQLModelBase):
pass
class Download(DownloadBase, UUIDTableBaseMixin):
"""离线下载任务模型"""
__table_args__ = (
UniqueConstraint("node_id", "g_id", name="uq_download_node_gid"),
Index("ix_download_user_status", "user_id", "status"),
)
status: DownloadStatus = Field(default=DownloadStatus.PREPARING, index=True)
"""下载状态"""
type: int = Field(default=0)
"""任务类型 [TODO] 待定义枚举"""
source: str
"""来源URL或标识"""
total_size: int = Field(default=0)
"""总大小(字节)"""
downloaded_size: int = Field(default=0)
"""已下载大小(字节)"""
g_id: str | None = Field(default=None, index=True)
"""Aria2 GID"""
speed: int = Field(default=0)
"""下载速度bytes/s"""
parent: str | None = Field(default=None, max_length=255)
"""父任务标识"""
error: str | None = Field(default=None)
"""错误信息"""
dst: str
"""目标存储路径"""
# 外键
user_id: UUID = Field(
foreign_key="user.id",
index=True,
ondelete="CASCADE"
)
"""所属用户UUID"""
task_id: int | None = Field(
default=None,
foreign_key="task.id",
index=True,
ondelete="SET NULL"
)
"""关联的任务ID"""
node_id: int = Field(
foreign_key="node.id",
index=True,
ondelete="RESTRICT"
)
"""执行下载的节点ID"""
# 关系
aria2_info: DownloadAria2Info | None = Relationship(
back_populates="download",
sa_relationship_kwargs={"uselist": False, "cascade": "all, delete-orphan"},
)
"""Aria2下载信息"""
aria2_files: list[DownloadAria2File] = Relationship(
back_populates="download",
sa_relationship_kwargs={"cascade": "all, delete-orphan"}
)
"""Aria2文件列表"""
user: "User" = Relationship(back_populates="downloads")
"""所属用户"""
task: "Task" = Relationship(back_populates="downloads")
"""关联的任务"""
node: "Node" = Relationship(back_populates="downloads")
"""执行下载的节点"""