Files
disknext/models/group.py
于小丘 16cec42181 feat: Implement file download token management and restructure file routes
- Added DownloadTokenManager for creating and verifying JWT download tokens.
- Introduced new download routes for creating download tokens and downloading files using tokens.
- Restructured file upload routes into a dedicated sub-router.
- Updated file upload session management with improved error handling and response structures.
- Created a new MCP (Microservice Communication Protocol) router with basic request and response models.
- Added base models for MCP requests and responses, including method enumeration.
2025-12-23 18:12:11 +08:00

317 lines
8.2 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.
from typing import TYPE_CHECKING
from uuid import UUID
from sqlmodel import Field, Relationship, text
from .base import SQLModelBase
from .mixin import TableBaseMixin, UUIDTableBaseMixin
if TYPE_CHECKING:
from .user import User
from .policy import Policy
# ==================== Base 模型 ====================
class GroupBase(SQLModelBase):
"""用户组基础字段,供数据库模型和 DTO 共享"""
name: str
"""用户组名称"""
class GroupOptionsBase(SQLModelBase):
"""用户组选项基础字段,供数据库模型和 DTO 共享"""
share_download: bool = False
"""是否允许分享下载"""
share_free: bool = False
"""是否免积分获取需要积分的内容"""
relocate: bool = False
"""是否允许文件重定位"""
source_batch: int = 0
"""批量获取源地址数量"""
select_node: bool = False
"""是否允许选择节点"""
advance_delete: bool = False
"""是否允许高级删除"""
# ==================== DTO 模型 ====================
class GroupCreateRequest(SQLModelBase):
"""创建用户组请求 DTO"""
name: str = Field(max_length=255)
"""用户组名称"""
max_storage: int = Field(default=0, ge=0)
"""最大存储空间字节0表示不限制"""
share_enabled: bool = False
"""是否允许创建分享"""
web_dav_enabled: bool = False
"""是否允许使用WebDAV"""
speed_limit: int = Field(default=0, ge=0)
"""速度限制 (KB/s), 0为不限制"""
# 用户组选项
share_download: bool = False
"""是否允许分享下载"""
share_free: bool = False
"""是否免积分获取需要积分的内容"""
relocate: bool = False
"""是否允许文件重定位"""
source_batch: int = Field(default=0, ge=0)
"""批量获取源地址数量"""
select_node: bool = False
"""是否允许选择节点"""
advance_delete: bool = False
"""是否允许高级删除"""
archive_download: bool = False
"""是否允许打包下载"""
archive_task: bool = False
"""是否允许创建打包任务"""
webdav_proxy: bool = False
"""是否允许WebDAV代理"""
aria2: bool = False
"""是否允许使用aria2"""
redirected_source: bool = False
"""是否使用重定向源"""
policy_ids: list[UUID] = []
"""关联的存储策略UUID列表"""
class GroupUpdateRequest(SQLModelBase):
"""更新用户组请求 DTO所有字段可选"""
name: str | None = Field(default=None, max_length=255)
"""用户组名称"""
max_storage: int | None = Field(default=None, ge=0)
"""最大存储空间(字节)"""
share_enabled: bool | None = None
"""是否允许创建分享"""
web_dav_enabled: bool | None = None
"""是否允许使用WebDAV"""
speed_limit: int | None = Field(default=None, ge=0)
"""速度限制 (KB/s)"""
# 用户组选项
share_download: bool | None = None
share_free: bool | None = None
relocate: bool | None = None
source_batch: int | None = None
select_node: bool | None = None
advance_delete: bool | None = None
archive_download: bool | None = None
archive_task: bool | None = None
webdav_proxy: bool | None = None
aria2: bool | None = None
redirected_source: bool | None = None
policy_ids: list[UUID] | None = None
"""关联的存储策略UUID列表"""
class GroupDetailResponse(SQLModelBase):
"""用户组详情响应 DTO"""
id: UUID
"""用户组UUID"""
name: str
"""用户组名称"""
max_storage: int = 0
"""最大存储空间(字节)"""
share_enabled: bool = False
"""是否允许创建分享"""
web_dav_enabled: bool = False
"""是否允许使用WebDAV"""
admin: bool = False
"""是否为管理员组"""
speed_limit: int = 0
"""速度限制 (KB/s)"""
user_count: int = 0
"""用户数量"""
policy_ids: list[UUID] = []
"""关联的存储策略UUID列表"""
# 选项
share_download: bool = False
share_free: bool = False
relocate: bool = False
source_batch: int = 0
select_node: bool = False
advance_delete: bool = False
archive_download: bool = False
archive_task: bool = False
webdav_proxy: bool = False
aria2: bool = False
redirected_source: bool = False
class GroupListResponse(SQLModelBase):
"""用户组列表响应 DTO"""
groups: list["GroupDetailResponse"] = []
"""用户组列表"""
total: int = 0
"""总数"""
class GroupResponse(GroupBase, GroupOptionsBase):
"""用户组响应 DTO"""
id: UUID
"""用户组UUID"""
allow_share: bool = False
"""是否允许分享"""
allow_remote_download: bool = False
"""是否允许离线下载"""
allow_archive_download: bool = False
"""是否允许打包下载"""
compress: bool = False
"""是否允许压缩"""
webdav: bool = False
"""是否允许WebDAV"""
allow_webdav_proxy: bool = False
"""是否允许WebDAV代理"""
# ==================== 数据库模型 ====================
# GroupPolicyLink 定义在 policy.py 中以避免循环导入
from .policy import GroupPolicyLink
class GroupOptions(GroupOptionsBase, TableBaseMixin):
"""用户组选项模型"""
group_id: UUID = Field(
foreign_key="group.id",
unique=True,
ondelete="CASCADE"
)
"""关联的用户组UUID"""
archive_download: bool = False
"""是否允许打包下载"""
archive_task: bool = False
"""是否允许创建打包任务"""
webdav_proxy: bool = False
"""是否允许WebDAV代理"""
aria2: bool = False
"""是否允许使用aria2"""
redirected_source: bool = False
"""是否使用重定向源"""
# 反向关系
group: "Group" = Relationship(back_populates="options")
class Group(GroupBase, UUIDTableBaseMixin):
"""用户组模型"""
name: str = Field(max_length=255, unique=True)
"""用户组名"""
max_storage: int = Field(default=0, sa_column_kwargs={"server_default": "0"})
"""最大存储空间(字节)"""
share_enabled: bool = Field(default=False, sa_column_kwargs={"server_default": text("false")})
"""是否允许创建分享"""
web_dav_enabled: bool = Field(default=False, sa_column_kwargs={"server_default": text("false")})
"""是否允许使用WebDAV"""
admin: bool = False
"""是否为管理员组"""
speed_limit: int = Field(default=0, sa_column_kwargs={"server_default": "0"})
"""速度限制 (KB/s), 0为不限制"""
# 一对一关系:用户组选项
options: GroupOptions | None = Relationship(
back_populates="group",
sa_relationship_kwargs={"uselist": False, "cascade": "all, delete-orphan"}
)
# 多对多关系:用户组可以关联多个存储策略
policies: list["Policy"] = Relationship(
back_populates="groups",
link_model=GroupPolicyLink,
)
# 关系:一个组可以有多个用户
users: list["User"] = Relationship(
back_populates="group",
sa_relationship_kwargs={"foreign_keys": "User.group_id"}
)
"""当前属于该组的用户列表"""
previous_users: list["User"] = Relationship(
back_populates="previous_group",
sa_relationship_kwargs={"foreign_keys": "User.previous_group_id"}
)
"""之前属于该组的用户列表(用于过期后恢复)"""
def to_response(self) -> "GroupResponse":
"""转换为响应 DTO"""
opts = self.options
return GroupResponse(
id=self.id,
name=self.name,
allow_share=self.share_enabled,
webdav=self.web_dav_enabled,
share_download=opts.share_download if opts else False,
share_free=opts.share_free if opts else False,
relocate=opts.relocate if opts else False,
source_batch=opts.source_batch if opts else 0,
select_node=opts.select_node if opts else False,
advance_delete=opts.advance_delete if opts else False,
allow_remote_download=opts.aria2 if opts else False,
allow_archive_download=opts.archive_download if opts else False,
allow_webdav_proxy=opts.webdav_proxy if opts else False,
)