feat: 更新用户组和选项模型,优化存储信息获取逻辑

This commit is contained in:
2025-12-18 14:27:41 +08:00
parent 8d2658b166
commit d271c81de7
3 changed files with 117 additions and 46 deletions

View File

@@ -1,44 +1,94 @@
from typing import Optional, List, TYPE_CHECKING from typing import TYPE_CHECKING
from sqlmodel import Field, Relationship, text, Column, JSON from sqlmodel import Field, Relationship, text
from .base import TableBase from .base import TableBase
from sqlmodel import SQLModel
if TYPE_CHECKING: if TYPE_CHECKING:
from .user import User from .user import User
class GroupOptions(SQLModel):
archive_download: bool | None = False class GroupOptions(TableBase, table=True):
archive_task: bool | None = False """用户组选项模型"""
share_download: bool | None = False
share_free: bool | None = False group_id: int = Field(foreign_key="group.id", unique=True)
webdav_proxy: bool | None = False """关联的用户组ID"""
aria2: bool | None = False
relocate: bool | None = False archive_download: bool = False
source_batch: int | None = 10 """是否允许打包下载"""
redirected_source: bool | None = False
available_nodes: List[int] | None = [] archive_task: bool = False
select_node: bool | None = False """是否允许创建打包任务"""
advance_delete: bool | None = False
share_download: bool = False
"""是否允许分享下载"""
share_free: bool = False
"""是否免积分分享"""
webdav_proxy: bool = False
"""是否允许WebDAV代理"""
aria2: bool = False
"""是否允许使用aria2"""
relocate: bool = False
"""是否允许文件重定位"""
source_batch: int = 10
"""批量获取源地址数量"""
redirected_source: bool = False
"""是否使用重定向源"""
available_nodes: str = "[]"
"""可用节点ID列表JSON数组"""
select_node: bool = False
"""是否允许选择节点"""
advance_delete: bool = False
"""是否允许高级删除"""
# 反向关系
group: "Group" = Relationship(back_populates="options")
class Group(TableBase, table=True): class Group(TableBase, table=True):
"""用户组模型""" """用户组模型"""
name: str = Field(max_length=255, unique=True, description="用户组名") name: str = Field(max_length=255, unique=True)
policies: str | None = Field(default=None, max_length=255, description="允许的策略ID列表逗号分隔") """用户组名"""
max_storage: int = Field(default=0, sa_column_kwargs={"server_default": "0"}, description="最大存储空间(字节)")
share_enabled: bool = Field(default=False, sa_column_kwargs={"server_default": text("false")}, description="是否允许创建分享") policies: str | None = Field(default=None, max_length=255)
web_dav_enabled: bool = Field(default=False, sa_column_kwargs={"server_default": text("false")}, description="是否允许使用WebDAV") """允许的策略ID列表逗号分隔"""
admin: bool = Field(default=False, description="是否为管理员组")
speed_limit: int = Field(default=0, sa_column_kwargs={"server_default": "0"}, description="速度限制 (KB/s), 0为不限制") max_storage: int = Field(default=0, sa_column_kwargs={"server_default": "0"})
options: GroupOptions = Field(default=GroupOptions, sa_column=Column(JSON), description="其他选项") """最大存储空间(字节)"""
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}
)
# 关系:一个组可以有多个用户 # 关系:一个组可以有多个用户
user: List["User"] = Relationship( user: list["User"] = Relationship(
back_populates="group", back_populates="group",
sa_relationship_kwargs={"foreign_keys": "User.group_id"} sa_relationship_kwargs={"foreign_keys": "User.group_id"}
) )
previous_user: List["User"] = Relationship( previous_user: list["User"] = Relationship(
back_populates="previous_group", back_populates="previous_group",
sa_relationship_kwargs={"foreign_keys": "User.previous_group_id"} sa_relationship_kwargs={"foreign_keys": "User.previous_group_id"}
) )

View File

@@ -145,38 +145,48 @@ async def init_default_group() -> None:
async for session in get_session(): async for session in get_session():
# 未找到初始管理组时,则创建 # 未找到初始管理组时,则创建
if not await Group.get(session, Group.id == 1): if not await Group.get(session, Group.id == 1):
await Group( admin_group = await Group(
name="管理员", name="管理员",
max_storage=1 * 1024 * 1024 * 1024, # 1GB max_storage=1 * 1024 * 1024 * 1024, # 1GB
share_enabled=True, share_enabled=True,
web_dav_enabled=True, web_dav_enabled=True,
admin=True, admin=True,
options=GroupOptions( ).save(session)
archive_download=True, assert admin_group.id is not None
archive_task=True, await GroupOptions(
share_download=True, group_id=admin_group.id,
aria2=True, archive_download=True,
).model_dump(), archive_task=True,
share_download=True,
aria2=True,
).save(session) ).save(session)
# 未找到初始注册会员时,则创建 # 未找到初始注册会员时,则创建
if not await Group.get(session, Group.id == 2): if not await Group.get(session, Group.id == 2):
await Group( member_group = await Group(
name="注册会员", name="注册会员",
max_storage=1 * 1024 * 1024 * 1024, # 1GB max_storage=1 * 1024 * 1024 * 1024, # 1GB
share_enabled=True, share_enabled=True,
web_dav_enabled=True, web_dav_enabled=True,
options=GroupOptions(share_download=True).model_dump(), ).save(session)
assert member_group.id is not None
await GroupOptions(
group_id=member_group.id,
share_download=True,
).save(session) ).save(session)
# 未找到初始游客组时,则创建 # 未找到初始游客组时,则创建
if not await Group.get(session, Group.id == 3): if not await Group.get(session, Group.id == 3):
await Group( guest_group = await Group(
name="游客", name="游客",
policies="[]", policies="[]",
share_enabled=False, share_enabled=False,
web_dav_enabled=False, web_dav_enabled=False,
options=GroupOptions(share_download=True).model_dump(), ).save(session)
assert guest_group.id is not None
await GroupOptions(
group_id=guest_group.id,
share_download=True,
).save(session) ).save(session)
async def init_default_user() -> None: async def init_default_user() -> None:

View File

@@ -227,20 +227,31 @@ async def router_user_me(
description='Get user storage information.', description='Get user storage information.',
dependencies=[Depends(AuthRequired)], dependencies=[Depends(AuthRequired)],
) )
def router_user_storage( async def router_user_storage(
session: SessionDep,
user: Annotated[models.user.User, Depends(AuthRequired)], user: Annotated[models.user.User, Depends(AuthRequired)],
) -> models.response.ResponseModel: ) -> models.response.ResponseModel:
""" """
Get user storage information. 获取用户存储空间信息。
Returns: 返回值:
dict: A dictionary containing user storage information. - used: 已使用空间(字节)
- free: 剩余空间(字节)
- total: 总容量(字节)= 用户组容量
""" """
# 获取用户组的基础存储容量
group = await models.Group.get(session, models.Group.id == user.group_id)
if not group:
raise HTTPException(status_code=500, detail="用户组不存在")
total: int = group.max_storage
used: int = user.storage
free: int = max(0, total - used)
return models.response.ResponseModel( return models.response.ResponseModel(
data={ data={
"used": 0, "used": used,
"free": 0, "free": free,
"total": 0, "total": total,
} }
) )