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:
2025-12-19 18:04:34 +08:00
parent 11b67bde6d
commit 51b6de921b
30 changed files with 223 additions and 534 deletions

View File

@@ -1,10 +1,10 @@
from fastapi import FastAPI
from pkg.conf import appmeta
from pkg.lifespan import lifespan
from utils.conf import appmeta
from utils.lifespan import lifespan
from models.database import init_db
from models.migration import migration
from pkg.JWT import JWT
from utils.JWT import JWT
from routers import routers
# 添加初始化数据库启动项

View File

@@ -5,7 +5,7 @@ from jwt import InvalidTokenError
import jwt
from models.user import User
from pkg.JWT import JWT
from utils.JWT import JWT
from .dependencies import SessionDep
credentials_exception = HTTPException(

View File

@@ -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

View File

@@ -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",

View File

@@ -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

View File

@@ -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(

View File

@@ -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用于标识请求的唯一性"""

View File

@@ -5,7 +5,7 @@ from middleware.auth import AdminRequired
from middleware.dependencies import SessionDep
from models import User
from models.user import UserPublic
from models.response import ResponseModel
from models.response import ResponseBase
# 管理员根目录 /api/admin
admin_router = APIRouter(
@@ -68,7 +68,7 @@ admin_vas_router = APIRouter(
description='Get site summary information',
dependencies=[Depends(AdminRequired)],
)
def router_admin_get_summary() -> ResponseModel:
def router_admin_get_summary() -> ResponseBase:
"""
获取站点概况信息包括用户数分享数文件数等
@@ -83,7 +83,7 @@ def router_admin_get_summary() -> ResponseModel:
description='Get community news',
dependencies=[Depends(AdminRequired)],
)
def router_admin_get_news() -> ResponseModel:
def router_admin_get_news() -> ResponseBase:
"""
获取社区新闻信息包括最新的动态和公告
@@ -98,7 +98,7 @@ def router_admin_get_news() -> ResponseModel:
description='Update settings',
dependencies=[Depends(AdminRequired)],
)
def router_admin_update_settings() -> ResponseModel:
def router_admin_update_settings() -> ResponseBase:
"""
更新站点设置包括站点名称描述等
@@ -113,7 +113,7 @@ def router_admin_update_settings() -> ResponseModel:
description='Get settings',
dependencies=[Depends(AdminRequired)],
)
def router_admin_get_settings() -> ResponseModel:
def router_admin_get_settings() -> ResponseBase:
"""
获取站点设置包括站点名称描述等
@@ -128,7 +128,7 @@ def router_admin_get_settings() -> ResponseModel:
description='Get user group list',
dependencies=[Depends(AdminRequired)],
)
def router_admin_get_groups() -> ResponseModel:
def router_admin_get_groups() -> ResponseBase:
"""
获取用户组列表包括每个用户组的名称和权限信息
@@ -143,7 +143,7 @@ def router_admin_get_groups() -> ResponseModel:
description='Get user group information by ID',
dependencies=[Depends(AdminRequired)],
)
def router_admin_get_group(group_id: int) -> ResponseModel:
def router_admin_get_group(group_id: int) -> ResponseBase:
"""
根据用户组ID获取用户组信息包括名称权限等
@@ -165,7 +165,7 @@ def router_admin_get_group_members(
group_id: int,
page: int = 1,
page_size: int = 20
) -> ResponseModel:
) -> ResponseBase:
"""
根据用户组ID获取用户组成员列表
@@ -185,7 +185,7 @@ def router_admin_get_group_members(
description='Create a new user group',
dependencies=[Depends(AdminRequired)],
)
def router_admin_create_group() -> ResponseModel:
def router_admin_create_group() -> ResponseBase:
"""
创建一个新的用户组设置名称和权限等信息
@@ -200,7 +200,7 @@ def router_admin_create_group() -> ResponseModel:
description='Update user group information by ID',
dependencies=[Depends(AdminRequired)],
)
def router_admin_update_group(group_id: int) -> ResponseModel:
def router_admin_update_group(group_id: int) -> ResponseBase:
"""
根据用户组ID更新用户组信息包括名称权限等
@@ -218,7 +218,7 @@ def router_admin_update_group(group_id: int) -> ResponseModel:
description='Delete user group by ID',
dependencies=[Depends(AdminRequired)],
)
def router_admin_delete_group(group_id: int) -> ResponseModel:
def router_admin_delete_group(group_id: int) -> ResponseBase:
"""
根据用户组ID删除用户组
@@ -236,7 +236,7 @@ def router_admin_delete_group(group_id: int) -> ResponseModel:
description='Get user information by ID',
dependencies=[Depends(AdminRequired)],
)
async def router_admin_get_user(session: SessionDep, user_id: int) -> ResponseModel:
async def router_admin_get_user(session: SessionDep, user_id: int) -> ResponseBase:
"""
根据用户ID获取用户信息包括用户名邮箱注册时间等
@@ -248,7 +248,7 @@ async def router_admin_get_user(session: SessionDep, user_id: int) -> ResponseMo
ResponseModel: 包含用户信息的响应模型
"""
user = await User.get_exist_one(session, user_id)
return ResponseModel(data=user.to_public().model_dump())
return ResponseBase(data=user.to_public().model_dump())
@admin_user_router.get(
path='/list',
@@ -260,7 +260,7 @@ async def router_admin_get_users(
session: SessionDep,
page: int = 1,
page_size: int = 20
) -> ResponseModel:
) -> ResponseBase:
"""
获取用户列表支持分页
@@ -280,7 +280,7 @@ async def router_admin_get_users(
offset=offset,
limit=page_size
)
return ResponseModel(
return ResponseBase(
data=[user.to_public().model_dump() for user in users]
)
@@ -293,7 +293,7 @@ async def router_admin_get_users(
async def router_admin_create_user(
session: SessionDep,
user: User,
) -> ResponseModel:
) -> ResponseBase:
"""
创建一个新的用户设置用户名密码等信息
@@ -302,12 +302,12 @@ async def router_admin_create_user(
"""
existing_user = await User.get(session, User.username == user.username)
if existing_user:
return ResponseModel(
return ResponseBase(
code=400,
msg="User with this username already exists."
)
user = await user.save(session)
return ResponseModel(data=user.to_public().model_dump())
return ResponseBase(data=user.to_public().model_dump())
@admin_user_router.patch(
path='/{user_id}',
@@ -315,7 +315,7 @@ async def router_admin_create_user(
description='Update user information by ID',
dependencies=[Depends(AdminRequired)],
)
def router_admin_update_user(user_id: int) -> ResponseModel:
def router_admin_update_user(user_id: int) -> ResponseBase:
"""
根据用户ID更新用户信息包括用户名邮箱等
@@ -333,7 +333,7 @@ def router_admin_update_user(user_id: int) -> ResponseModel:
description='Delete user by ID',
dependencies=[Depends(AdminRequired)],
)
def router_admin_delete_user(user_id: int) -> ResponseModel:
def router_admin_delete_user(user_id: int) -> ResponseBase:
"""
根据用户ID删除用户
@@ -360,7 +360,7 @@ def router_admin_calibrate_storage():
description='Get file list',
dependencies=[Depends(AdminRequired)],
)
def router_admin_get_file_list() -> ResponseModel:
def router_admin_get_file_list() -> ResponseBase:
"""
获取文件列表包括文件名称大小上传时间等
@@ -375,7 +375,7 @@ def router_admin_get_file_list() -> ResponseModel:
description='Preview file by ID',
dependencies=[Depends(AdminRequired)],
)
def router_admin_preview_file(file_id: int) -> ResponseModel:
def router_admin_preview_file(file_id: int) -> ResponseBase:
"""
根据文件ID预览文件内容
@@ -393,7 +393,7 @@ def router_admin_preview_file(file_id: int) -> ResponseModel:
description='Ban the file, user can\'t open, copy, move, download or share this file if administrator ban.',
dependencies=[Depends(AdminRequired)],
)
def router_admin_ban_file(file_id: int) -> ResponseModel:
def router_admin_ban_file(file_id: int) -> ResponseBase:
"""
根据文件ID封禁文件
@@ -413,7 +413,7 @@ def router_admin_ban_file(file_id: int) -> ResponseModel:
description='Delete file by ID',
dependencies=[Depends(AdminRequired)],
)
def router_admin_delete_file(file_id: int) -> ResponseModel:
def router_admin_delete_file(file_id: int) -> ResponseBase:
"""
根据文件ID删除文件
@@ -431,7 +431,7 @@ def router_admin_delete_file(file_id: int) -> ResponseModel:
description='',
dependencies=[Depends(AdminRequired)]
)
def router_admin_aira2_test() -> ResponseModel:
def router_admin_aira2_test() -> ResponseBase:
pass
@admin_policy_router.get(
@@ -440,7 +440,7 @@ def router_admin_aira2_test() -> ResponseModel:
description='',
dependencies=[Depends(AdminRequired)]
)
def router_policy_list() -> ResponseModel:
def router_policy_list() -> ResponseBase:
pass
@admin_policy_router.post(
@@ -449,7 +449,7 @@ def router_policy_list() -> ResponseModel:
description='',
dependencies=[Depends(AdminRequired)]
)
def router_policy_test_path() -> ResponseModel:
def router_policy_test_path() -> ResponseBase:
pass
@admin_policy_router.post(
@@ -458,7 +458,7 @@ def router_policy_test_path() -> ResponseModel:
description='',
dependencies=[Depends(AdminRequired)]
)
def router_policy_test_slave() -> ResponseModel:
def router_policy_test_slave() -> ResponseBase:
pass
@admin_policy_router.post(
@@ -467,7 +467,7 @@ def router_policy_test_slave() -> ResponseModel:
description='',
dependencies=[Depends(AdminRequired)]
)
def router_policy_add_policy() -> ResponseModel:
def router_policy_add_policy() -> ResponseBase:
pass
@admin_policy_router.post(
@@ -476,7 +476,7 @@ def router_policy_add_policy() -> ResponseModel:
description='',
dependencies=[Depends(AdminRequired)]
)
def router_policy_add_cors() -> ResponseModel:
def router_policy_add_cors() -> ResponseBase:
pass
@admin_policy_router.post(
@@ -485,7 +485,7 @@ def router_policy_add_cors() -> ResponseModel:
description='',
dependencies=[Depends(AdminRequired)]
)
def router_policy_add_scf() -> ResponseModel:
def router_policy_add_scf() -> ResponseBase:
pass
@admin_policy_router.get(
@@ -494,7 +494,7 @@ def router_policy_add_scf() -> ResponseModel:
description='',
dependencies=[Depends(AdminRequired)]
)
def router_policy_onddrive_oauth() -> ResponseModel:
def router_policy_onddrive_oauth() -> ResponseBase:
pass
@admin_policy_router.get(
@@ -503,7 +503,7 @@ def router_policy_onddrive_oauth() -> ResponseModel:
description='',
dependencies=[Depends(AdminRequired)]
)
def router_policy_get_policy() -> ResponseModel:
def router_policy_get_policy() -> ResponseBase:
pass
@admin_policy_router.delete(
@@ -512,5 +512,5 @@ def router_policy_get_policy() -> ResponseModel:
description='',
dependencies=[Depends(AdminRequired)]
)
def router_policy_delete_policy() -> ResponseModel:
def router_policy_delete_policy() -> ResponseBase:
pass

View File

@@ -1,7 +1,7 @@
from fastapi import APIRouter, Depends, Query
from fastapi.responses import PlainTextResponse, RedirectResponse
from middleware.auth import SignRequired
from models.response import ResponseModel
from models.response import ResponseBase
import service.oauth
callback_router = APIRouter(
@@ -33,7 +33,7 @@ callback_router.include_router(upload_router)
summary='QQ互联回调',
description='Handle QQ OAuth callback and return user information.',
)
def router_callback_qq() -> ResponseModel:
def router_callback_qq() -> ResponseBase:
"""
Handle QQ OAuth callback and return user information.
@@ -79,7 +79,7 @@ async def router_callback_github(
summary='支付宝支付回调',
description='Handle Alipay payment callback and return payment status.',
)
def router_callback_alipay() -> ResponseModel:
def router_callback_alipay() -> ResponseBase:
"""
Handle Alipay payment callback and return payment status.
@@ -93,7 +93,7 @@ def router_callback_alipay() -> ResponseModel:
summary='微信支付回调',
description='Handle WeChat Pay payment callback and return payment status.',
)
def router_callback_wechat() -> ResponseModel:
def router_callback_wechat() -> ResponseBase:
"""
Handle WeChat Pay payment callback and return payment status.
@@ -107,7 +107,7 @@ def router_callback_wechat() -> ResponseModel:
summary='Stripe支付回调',
description='Handle Stripe payment callback and return payment status.',
)
def router_callback_stripe() -> ResponseModel:
def router_callback_stripe() -> ResponseBase:
"""
Handle Stripe payment callback and return payment status.
@@ -136,7 +136,7 @@ def router_callback_easypay() -> PlainTextResponse:
summary='自定义支付回调',
description='Handle custom payment callback and return payment status.',
)
def router_callback_custom(order_no: str, id: str) -> ResponseModel:
def router_callback_custom(order_no: str, id: str) -> ResponseBase:
"""
Handle custom payment callback and return payment status.
@@ -154,7 +154,7 @@ def router_callback_custom(order_no: str, id: str) -> ResponseModel:
summary='远程上传回调',
description='Handle remote upload callback and return upload status.',
)
def router_callback_remote(session_id: str, key: str) -> ResponseModel:
def router_callback_remote(session_id: str, key: str) -> ResponseBase:
"""
Handle remote upload callback and return upload status.
@@ -172,7 +172,7 @@ def router_callback_remote(session_id: str, key: str) -> ResponseModel:
summary='七牛云上传回调',
description='Handle Qiniu Cloud upload callback and return upload status.',
)
def router_callback_qiniu(session_id: str) -> ResponseModel:
def router_callback_qiniu(session_id: str) -> ResponseBase:
"""
Handle Qiniu Cloud upload callback and return upload status.
@@ -189,7 +189,7 @@ def router_callback_qiniu(session_id: str) -> ResponseModel:
summary='腾讯云上传回调',
description='Handle Tencent Cloud upload callback and return upload status.',
)
def router_callback_tencent(session_id: str) -> ResponseModel:
def router_callback_tencent(session_id: str) -> ResponseBase:
"""
Handle Tencent Cloud upload callback and return upload status.
@@ -206,7 +206,7 @@ def router_callback_tencent(session_id: str) -> ResponseModel:
summary='阿里云上传回调',
description='Handle Aliyun upload callback and return upload status.',
)
def router_callback_aliyun(session_id: str) -> ResponseModel:
def router_callback_aliyun(session_id: str) -> ResponseBase:
"""
Handle Aliyun upload callback and return upload status.
@@ -223,7 +223,7 @@ def router_callback_aliyun(session_id: str) -> ResponseModel:
summary='又拍云上传回调',
description='Handle Upyun upload callback and return upload status.',
)
def router_callback_upyun(session_id: str) -> ResponseModel:
def router_callback_upyun(session_id: str) -> ResponseBase:
"""
Handle Upyun upload callback and return upload status.
@@ -240,7 +240,7 @@ def router_callback_upyun(session_id: str) -> ResponseModel:
summary='AWS S3上传回调',
description='Handle AWS S3 upload callback and return upload status.',
)
def router_callback_aws(session_id: str) -> ResponseModel:
def router_callback_aws(session_id: str) -> ResponseBase:
"""
Handle AWS S3 upload callback and return upload status.
@@ -257,7 +257,7 @@ def router_callback_aws(session_id: str) -> ResponseModel:
summary='OneDrive上传完成回调',
description='Handle OneDrive upload completion callback and return upload status.',
)
def router_callback_onedrive_finish(session_id: str) -> ResponseModel:
def router_callback_onedrive_finish(session_id: str) -> ResponseBase:
"""
Handle OneDrive upload completion callback and return upload status.
@@ -274,7 +274,7 @@ def router_callback_onedrive_finish(session_id: str) -> ResponseModel:
summary='OneDrive授权回调',
description='Handle OneDrive authorization callback and return authorization status.',
)
def router_callback_onedrive_auth() -> ResponseModel:
def router_callback_onedrive_auth() -> ResponseBase:
"""
Handle OneDrive authorization callback and return authorization status.
@@ -288,7 +288,7 @@ def router_callback_onedrive_auth() -> ResponseModel:
summary='Google OAuth 完成',
description='Handle Google OAuth completion callback and return authorization status.',
)
def router_callback_google_auth() -> ResponseModel:
def router_callback_google_auth() -> ResponseBase:
"""
Handle Google OAuth completion callback and return authorization status.

View File

@@ -97,7 +97,7 @@ async def router_directory_create(
session: SessionDep,
user: Annotated[User, Depends(AuthRequired)],
request: DirectoryCreateRequest
) -> response.ResponseModel:
) -> response.ResponseBase:
"""
创建目录
@@ -146,7 +146,7 @@ async def router_directory_create(
new_folder_name = new_folder.name
await new_folder.save(session)
return response.ResponseModel(
return response.ResponseBase(
data={
"id": new_folder_id,
"name": new_folder_name,

View File

@@ -1,6 +1,6 @@
from fastapi import APIRouter, Depends
from middleware.auth import SignRequired
from models.response import ResponseModel
from models.response import ResponseBase
aria2_router = APIRouter(
prefix="/aria2",
@@ -13,7 +13,7 @@ aria2_router = APIRouter(
description='Create a URL download task endpoint.',
dependencies=[Depends(SignRequired)]
)
def router_aria2_url() -> ResponseModel:
def router_aria2_url() -> ResponseBase:
"""
Create a URL download task endpoint.
@@ -28,7 +28,7 @@ def router_aria2_url() -> ResponseModel:
description='Create a torrent download task endpoint.',
dependencies=[Depends(SignRequired)]
)
def router_aria2_torrent(id: str) -> ResponseModel:
def router_aria2_torrent(id: str) -> ResponseBase:
"""
Create a torrent download task endpoint.
@@ -46,7 +46,7 @@ def router_aria2_torrent(id: str) -> ResponseModel:
description='Re-select files to download endpoint.',
dependencies=[Depends(SignRequired)]
)
def router_aria2_select(gid: str) -> ResponseModel:
def router_aria2_select(gid: str) -> ResponseBase:
"""
Re-select files to download endpoint.
@@ -64,7 +64,7 @@ def router_aria2_select(gid: str) -> ResponseModel:
description='Delete a download task endpoint.',
dependencies=[Depends(SignRequired)]
)
def router_aria2_delete(gid: str) -> ResponseModel:
def router_aria2_delete(gid: str) -> ResponseBase:
"""
Delete a download task endpoint.
@@ -82,7 +82,7 @@ def router_aria2_delete(gid: str) -> ResponseModel:
description='Get currently downloading tasks endpoint.',
dependencies=[Depends(SignRequired)]
)
def router_aria2_downloading() -> ResponseModel:
def router_aria2_downloading() -> ResponseBase:
"""
Get currently downloading tasks endpoint.
@@ -97,7 +97,7 @@ def router_aria2_downloading() -> ResponseModel:
description='Get finished tasks endpoint.',
dependencies=[Depends(SignRequired)]
)
def router_aria2_finished() -> ResponseModel:
def router_aria2_finished() -> ResponseBase:
"""
Get finished tasks endpoint.

View File

@@ -1,7 +1,7 @@
from fastapi import APIRouter, Depends, UploadFile
from fastapi.responses import FileResponse
from middleware.auth import SignRequired
from models.response import ResponseModel
from models.response import ResponseBase
file_router = APIRouter(
prefix="/file",
@@ -36,7 +36,7 @@ def router_file_get(id: str, name: str) -> FileResponse:
summary='文件外链(301跳转)',
description='Get file external link with 301 redirect endpoint.',
)
def router_file_source(id: str, name: str) -> ResponseModel:
def router_file_source(id: str, name: str) -> ResponseBase:
"""
Get file external link with 301 redirect endpoint.
@@ -54,7 +54,7 @@ def router_file_source(id: str, name: str) -> ResponseModel:
summary='下载文件',
description='Download file endpoint.',
)
def router_file_download(id: str) -> ResponseModel:
def router_file_download(id: str) -> ResponseBase:
"""
Download file endpoint.
@@ -71,7 +71,7 @@ def router_file_download(id: str) -> ResponseModel:
summary='打包并下载文件',
description='Archive and download files endpoint.',
)
def router_file_archive_download(sessionID: str) -> ResponseModel:
def router_file_archive_download(sessionID: str) -> ResponseBase:
"""
Archive and download files endpoint.
@@ -88,7 +88,7 @@ def router_file_archive_download(sessionID: str) -> ResponseModel:
summary='文件上传',
description='File upload endpoint.',
)
def router_file_upload(sessionID: str, index: int, file: UploadFile) -> ResponseModel:
def router_file_upload(sessionID: str, index: int, file: UploadFile) -> ResponseBase:
"""
File upload endpoint.
@@ -107,7 +107,7 @@ def router_file_upload(sessionID: str, index: int, file: UploadFile) -> Response
description='Create an upload session endpoint.',
dependencies=[Depends(SignRequired)],
)
def router_file_upload_session() -> ResponseModel:
def router_file_upload_session() -> ResponseBase:
"""
Create an upload session endpoint.
@@ -122,7 +122,7 @@ def router_file_upload_session() -> ResponseModel:
description='Delete an upload session endpoint.',
dependencies=[Depends(SignRequired)]
)
def router_file_upload_session_delete(sessionID: str) -> ResponseModel:
def router_file_upload_session_delete(sessionID: str) -> ResponseBase:
"""
Delete an upload session endpoint.
@@ -140,7 +140,7 @@ def router_file_upload_session_delete(sessionID: str) -> ResponseModel:
description='Clear all upload sessions endpoint.',
dependencies=[Depends(SignRequired)]
)
def router_file_upload_session_clear() -> ResponseModel:
def router_file_upload_session_clear() -> ResponseBase:
"""
Clear all upload sessions endpoint.
@@ -155,7 +155,7 @@ def router_file_upload_session_clear() -> ResponseModel:
description='Update file information endpoint.',
dependencies=[Depends(SignRequired)]
)
def router_file_update(id: str) -> ResponseModel:
def router_file_update(id: str) -> ResponseBase:
"""
Update file information endpoint.
@@ -173,7 +173,7 @@ def router_file_update(id: str) -> ResponseModel:
description='Create a blank file endpoint.',
dependencies=[Depends(SignRequired)]
)
def router_file_create() -> ResponseModel:
def router_file_create() -> ResponseBase:
"""
Create a blank file endpoint.
@@ -188,7 +188,7 @@ def router_file_create() -> ResponseModel:
description='Create a file download session endpoint.',
dependencies=[Depends(SignRequired)]
)
def router_file_download(id: str) -> ResponseModel:
def router_file_download(id: str) -> ResponseBase:
"""
Create a file download session endpoint.
@@ -206,7 +206,7 @@ def router_file_download(id: str) -> ResponseModel:
description='Preview file endpoint.',
dependencies=[Depends(SignRequired)]
)
def router_file_preview(id: str) -> ResponseModel:
def router_file_preview(id: str) -> ResponseBase:
"""
Preview file endpoint.
@@ -224,7 +224,7 @@ def router_file_preview(id: str) -> ResponseModel:
description='Get text file content endpoint.',
dependencies=[Depends(SignRequired)]
)
def router_file_content(id: str) -> ResponseModel:
def router_file_content(id: str) -> ResponseBase:
"""
Get text file content endpoint.
@@ -242,7 +242,7 @@ def router_file_content(id: str) -> ResponseModel:
description='Get Office document preview URL endpoint.',
dependencies=[Depends(SignRequired)]
)
def router_file_doc(id: str) -> ResponseModel:
def router_file_doc(id: str) -> ResponseBase:
"""
Get Office document preview URL endpoint.
@@ -260,7 +260,7 @@ def router_file_doc(id: str) -> ResponseModel:
description='Get file thumbnail endpoint.',
dependencies=[Depends(SignRequired)]
)
def router_file_thumb(id: str) -> ResponseModel:
def router_file_thumb(id: str) -> ResponseBase:
"""
Get file thumbnail endpoint.
@@ -278,7 +278,7 @@ def router_file_thumb(id: str) -> ResponseModel:
description='Get file external link endpoint.',
dependencies=[Depends(SignRequired)]
)
def router_file_source(id: str) -> ResponseModel:
def router_file_source(id: str) -> ResponseBase:
"""
Get file external link endpoint.
@@ -296,7 +296,7 @@ def router_file_source(id: str) -> ResponseModel:
description='Archive files for download endpoint.',
dependencies=[Depends(SignRequired)]
)
def router_file_archive(id: str) -> ResponseModel:
def router_file_archive(id: str) -> ResponseBase:
"""
Archive files for download endpoint.
@@ -314,7 +314,7 @@ def router_file_archive(id: str) -> ResponseModel:
description='Create file compression task endpoint.',
dependencies=[Depends(SignRequired)]
)
def router_file_compress(id: str) -> ResponseModel:
def router_file_compress(id: str) -> ResponseBase:
"""
Create file compression task endpoint.
@@ -332,7 +332,7 @@ def router_file_compress(id: str) -> ResponseModel:
description='Create file extraction task endpoint.',
dependencies=[Depends(SignRequired)]
)
def router_file_decompress(id: str) -> ResponseModel:
def router_file_decompress(id: str) -> ResponseBase:
"""
Create file extraction task endpoint.
@@ -350,7 +350,7 @@ def router_file_decompress(id: str) -> ResponseModel:
description='Create file relocation task endpoint.',
dependencies=[Depends(SignRequired)]
)
def router_file_relocate(id: str) -> ResponseModel:
def router_file_relocate(id: str) -> ResponseBase:
"""
Create file relocation task endpoint.
@@ -368,7 +368,7 @@ def router_file_relocate(id: str) -> ResponseModel:
description='Search files by keyword endpoint.',
dependencies=[Depends(SignRequired)]
)
def router_file_search(type: str, keyword: str) -> ResponseModel:
def router_file_search(type: str, keyword: str) -> ResponseBase:
"""
Search files by keyword endpoint.

View File

@@ -5,7 +5,7 @@ from fastapi import APIRouter, Depends, HTTPException
from middleware.auth import AuthRequired
from middleware.dependencies import SessionDep
from models import Object, ObjectDeleteRequest, ObjectMoveRequest, User
from models.response import ResponseModel
from models.response import ResponseBase
object_router = APIRouter(
prefix="/object",
@@ -22,7 +22,7 @@ async def router_object_delete(
session: SessionDep,
user: Annotated[User, Depends(AuthRequired)],
request: ObjectDeleteRequest,
) -> ResponseModel:
) -> ResponseBase:
"""
删除对象端点
@@ -41,7 +41,7 @@ async def router_object_delete(
await obj.delete(session)
deleted_count += 1
return ResponseModel(
return ResponseBase(
data={
"deleted": deleted_count,
"total": len(request.ids),
@@ -58,7 +58,7 @@ async def router_object_move(
session: SessionDep,
user: Annotated[User, Depends(AuthRequired)],
request: ObjectMoveRequest,
) -> ResponseModel:
) -> ResponseBase:
"""
移动对象端点
@@ -100,7 +100,7 @@ async def router_object_move(
await src.save(session)
moved_count += 1
return ResponseModel(
return ResponseBase(
data={
"moved": moved_count,
"total": len(request.src_ids),
@@ -113,7 +113,7 @@ async def router_object_move(
description='Copy an object endpoint.',
dependencies=[Depends(AuthRequired)]
)
def router_object_copy() -> ResponseModel:
def router_object_copy() -> ResponseBase:
"""
Copy an object endpoint.
@@ -128,7 +128,7 @@ def router_object_copy() -> ResponseModel:
description='Rename an object endpoint.',
dependencies=[Depends(AuthRequired)]
)
def router_object_rename() -> ResponseModel:
def router_object_rename() -> ResponseBase:
"""
Rename an object endpoint.
@@ -143,7 +143,7 @@ def router_object_rename() -> ResponseModel:
description='Get object properties endpoint.',
dependencies=[Depends(AuthRequired)]
)
def router_object_property(id: str) -> ResponseModel:
def router_object_property(id: str) -> ResponseBase:
"""
Get object properties endpoint.

View File

@@ -3,7 +3,7 @@ from sqlalchemy import and_
import json
from middleware.dependencies import SessionDep
from models.response import ResponseModel
from models.response import ResponseBase
from models.setting import Setting
site_router = APIRouter(
@@ -33,7 +33,7 @@ async def _get_setting_json(session: SessionDep, type_: str, name: str) -> dict
path="/ping",
summary="测试用路由",
description="A simple endpoint to check if the site is up and running.",
response_model=ResponseModel,
response_model=ResponseBase,
)
def router_site_ping():
"""
@@ -42,15 +42,15 @@ def router_site_ping():
Returns:
str: A message indicating the site is running.
"""
from pkg.conf.appmeta import BackendVersion
return ResponseModel(data=BackendVersion)
from utils.conf.appmeta import BackendVersion
return ResponseBase(data=BackendVersion)
@site_router.get(
path='/captcha',
summary='验证码',
description='Get a Base64 captcha image.',
response_model=ResponseModel,
response_model=ResponseBase,
)
def router_site_captcha():
"""
@@ -66,7 +66,7 @@ def router_site_captcha():
path='/config',
summary='站点全局配置',
description='Get the configuration file.',
response_model=ResponseModel,
response_model=ResponseBase,
)
async def router_site_config(session: SessionDep):
"""
@@ -75,7 +75,7 @@ async def router_site_config(session: SessionDep):
Returns:
dict: The site configuration.
"""
return ResponseModel(
return ResponseBase(
data={
"title": await _get_setting(session, "basic", "siteName"),
"loginCaptcha": await _get_setting_bool(session, "login", "login_captcha"),

View File

@@ -1,7 +1,7 @@
from fastapi import APIRouter, Depends
from fastapi.responses import FileResponse
from middleware.auth import SignRequired
from models.response import ResponseModel
from models.response import ResponseBase
slave_router = APIRouter(
prefix="/slave",
@@ -18,15 +18,15 @@ slave_aria2_router = APIRouter(
summary='测试用路由',
description='Test route for checking connectivity.',
)
def router_slave_ping() -> ResponseModel:
def router_slave_ping() -> ResponseBase:
"""
Test route for checking connectivity.
Returns:
ResponseModel: A response model indicating success.
"""
from pkg.conf.appmeta import BackendVersion
return ResponseModel(data=BackendVersion)
from utils.conf.appmeta import BackendVersion
return ResponseBase(data=BackendVersion)
@slave_router.post(
path='/post',
@@ -34,7 +34,7 @@ def router_slave_ping() -> ResponseModel:
description='Upload data to the server.',
dependencies=[Depends(SignRequired)],
)
def router_slave_post(data: str) -> ResponseModel:
def router_slave_post(data: str) -> ResponseBase:
"""
Upload data to the server.
@@ -50,7 +50,7 @@ def router_slave_post(data: str) -> ResponseModel:
path='/get/{speed}/{path}/{name}',
summary='获取下载',
)
def router_slave_download(speed: int, path: str, name: str) -> ResponseModel:
def router_slave_download(speed: int, path: str, name: str) -> ResponseBase:
"""
Get download information.
@@ -88,7 +88,7 @@ def router_slave_download_by_sign(sign: str) -> FileResponse:
description='Get the external link for a file based on its signature.',
dependencies=[Depends(SignRequired)],
)
def router_slave_source(speed: int, path: str, name: str) -> ResponseModel:
def router_slave_source(speed: int, path: str, name: str) -> ResponseBase:
"""
Get the external link for a file based on its signature.
@@ -126,7 +126,7 @@ def router_slave_source_by_sign(sign: str) -> FileResponse:
description='Get a thumbnail image based on its ID.',
dependencies=[Depends(SignRequired)],
)
def router_slave_thumb(id: str) -> ResponseModel:
def router_slave_thumb(id: str) -> ResponseBase:
"""
Get a thumbnail image based on its ID.
@@ -144,7 +144,7 @@ def router_slave_thumb(id: str) -> ResponseModel:
description='Delete a file from the server.',
dependencies=[Depends(SignRequired)],
)
def router_slave_delete(path: str) -> ResponseModel:
def router_slave_delete(path: str) -> ResponseBase:
"""
Delete a file from the server.
@@ -162,7 +162,7 @@ def router_slave_delete(path: str) -> ResponseModel:
description='Test the connection to the Aria2 service from the slave.',
dependencies=[Depends(SignRequired)],
)
def router_slave_aria2_test() -> ResponseModel:
def router_slave_aria2_test() -> ResponseBase:
"""
Test the connection to the Aria2 service from the slave.
"""
@@ -174,7 +174,7 @@ def router_slave_aria2_test() -> ResponseModel:
description='Get information about an Aria2 task by its GID.',
dependencies=[Depends(SignRequired)],
)
def router_slave_aria2_get(gid: str = None) -> ResponseModel:
def router_slave_aria2_get(gid: str = None) -> ResponseBase:
"""
Get information about an Aria2 task by its GID.
@@ -192,7 +192,7 @@ def router_slave_aria2_get(gid: str = None) -> ResponseModel:
description='Add a new Aria2 task.',
dependencies=[Depends(SignRequired)],
)
def router_slave_aria2_add(gid: str, url: str, options: dict = None) -> ResponseModel:
def router_slave_aria2_add(gid: str, url: str, options: dict = None) -> ResponseBase:
"""
Add a new Aria2 task.
@@ -212,7 +212,7 @@ def router_slave_aria2_add(gid: str, url: str, options: dict = None) -> Response
description='Remove an Aria2 task by its GID.',
dependencies=[Depends(SignRequired)],
)
def router_slave_aria2_remove(gid: str) -> ResponseModel:
def router_slave_aria2_remove(gid: str) -> ResponseBase:
"""
Remove an Aria2 task by its GID.

View File

@@ -1,6 +1,6 @@
from fastapi import APIRouter, Depends
from middleware.auth import SignRequired
from models.response import ResponseModel
from models.response import ResponseBase
tag_router = APIRouter(
prefix='/tag',
@@ -13,7 +13,7 @@ tag_router = APIRouter(
description='Create a file classification tag.',
dependencies=[Depends(SignRequired)],
)
def router_tag_create_filter() -> ResponseModel:
def router_tag_create_filter() -> ResponseBase:
"""
Create a file classification tag.
@@ -28,7 +28,7 @@ def router_tag_create_filter() -> ResponseModel:
description='Create a directory shortcut tag.',
dependencies=[Depends(SignRequired)],
)
def router_tag_create_link() -> ResponseModel:
def router_tag_create_link() -> ResponseBase:
"""
Create a directory shortcut tag.
@@ -43,7 +43,7 @@ def router_tag_create_link() -> ResponseModel:
description='Delete a tag by its ID.',
dependencies=[Depends(SignRequired)],
)
def router_tag_delete(id: str) -> ResponseModel:
def router_tag_delete(id: str) -> ResponseBase:
"""
Delete a tag by its ID.

View File

@@ -12,8 +12,8 @@ import models
import service
from middleware.auth import AuthRequired
from middleware.dependencies import SessionDep
from pkg.JWT.JWT import SECRET_KEY
from pkg import Password
from utils.JWT.JWT import SECRET_KEY
from utils import Password
user_router = APIRouter(
prefix="/user",
@@ -96,7 +96,7 @@ async def router_user_session(
async def router_user_register(
session: SessionDep,
request: models.RegisterRequest,
) -> models.response.ResponseModel:
) -> models.response.ResponseBase:
"""
用户注册端点
@@ -157,7 +157,7 @@ async def router_user_register(
policy_id=default_policy.id,
).save(session)
return models.response.ResponseModel(
return models.response.ResponseBase(
data={
"user_id": new_user_id,
"username": new_user_username,
@@ -172,7 +172,7 @@ async def router_user_register(
)
def router_user_email_code(
reason: Literal['register', 'reset'] = 'register',
) -> models.response.ResponseModel:
) -> models.response.ResponseBase:
"""
Send a verification code email.
@@ -186,7 +186,7 @@ def router_user_email_code(
summary='初始化QQ登录',
description='Initialize QQ login for a user.',
)
def router_user_qq() -> models.response.ResponseModel:
def router_user_qq() -> models.response.ResponseBase:
"""
Initialize QQ login for a user.
@@ -200,7 +200,7 @@ def router_user_qq() -> models.response.ResponseModel:
summary='WebAuthn登录初始化',
description='Initialize WebAuthn login for a user.',
)
async def router_user_authn(username: str) -> models.response.ResponseModel:
async def router_user_authn(username: str) -> models.response.ResponseBase:
pass
@@ -209,7 +209,7 @@ async def router_user_authn(username: str) -> models.response.ResponseModel:
summary='WebAuthn登录',
description='Finish WebAuthn login for a user.',
)
def router_user_authn_finish(username: str) -> models.response.ResponseModel:
def router_user_authn_finish(username: str) -> models.response.ResponseBase:
"""
Finish WebAuthn login for a user.
@@ -226,7 +226,7 @@ def router_user_authn_finish(username: str) -> models.response.ResponseModel:
summary='获取用户主页展示用分享',
description='Get user profile for display.',
)
def router_user_profile(id: str) -> models.response.ResponseModel:
def router_user_profile(id: str) -> models.response.ResponseBase:
"""
Get user profile for display.
@@ -243,7 +243,7 @@ def router_user_profile(id: str) -> models.response.ResponseModel:
summary='获取用户头像',
description='Get user avatar by ID and size.',
)
def router_user_avatar(id: str, size: int = 128) -> models.response.ResponseModel:
def router_user_avatar(id: str, size: int = 128) -> models.response.ResponseBase:
"""
Get user avatar by ID and size.
@@ -265,12 +265,12 @@ def router_user_avatar(id: str, size: int = 128) -> models.response.ResponseMode
summary='获取用户信息',
description='Get user information.',
dependencies=[Depends(dependency=AuthRequired)],
response_model=models.response.ResponseModel,
response_model=models.response.ResponseBase,
)
async def router_user_me(
session: SessionDep,
user: Annotated[models.User, Depends(AuthRequired)],
) -> models.response.ResponseModel:
) -> models.response.ResponseBase:
"""
获取用户信息.
@@ -302,7 +302,7 @@ async def router_user_me(
tags=[tag.name for tag in user_tags] if user_tags else [],
)
return models.response.ResponseModel(data=user_response.model_dump())
return models.response.ResponseBase(data=user_response.model_dump())
@user_router.get(
path='/storage',
@@ -313,7 +313,7 @@ async def router_user_me(
async def router_user_storage(
session: SessionDep,
user: Annotated[models.user.User, Depends(AuthRequired)],
) -> models.response.ResponseModel:
) -> models.response.ResponseBase:
"""
获取用户存储空间信息
@@ -330,7 +330,7 @@ async def router_user_storage(
used: int = user.storage
free: int = max(0, total - used)
return models.response.ResponseModel(
return models.response.ResponseBase(
data={
"used": used,
"free": free,
@@ -347,7 +347,7 @@ async def router_user_storage(
async def router_user_authn_start(
session: SessionDep,
user: Annotated[models.user.User, Depends(AuthRequired)],
) -> models.response.ResponseModel:
) -> models.response.ResponseBase:
"""
Initialize WebAuthn login for a user.
@@ -378,7 +378,7 @@ async def router_user_authn_start(
user_display_name=user.nick or user.username,
)
return models.response.ResponseModel(data=options_to_json_dict(options))
return models.response.ResponseBase(data=options_to_json_dict(options))
@user_router.put(
path='/authn/finish',
@@ -386,7 +386,7 @@ async def router_user_authn_start(
description='Finish WebAuthn login for a user.',
dependencies=[Depends(AuthRequired)],
)
def router_user_authn_finish() -> models.response.ResponseModel:
def router_user_authn_finish() -> models.response.ResponseBase:
"""
Finish WebAuthn login for a user.
@@ -400,7 +400,7 @@ def router_user_authn_finish() -> models.response.ResponseModel:
summary='获取用户可选存储策略',
description='Get user selectable storage policies.',
)
def router_user_settings_policies() -> models.response.ResponseModel:
def router_user_settings_policies() -> models.response.ResponseBase:
"""
Get user selectable storage policies.
@@ -415,7 +415,7 @@ def router_user_settings_policies() -> models.response.ResponseModel:
description='Get user selectable nodes.',
dependencies=[Depends(AuthRequired)],
)
def router_user_settings_nodes() -> models.response.ResponseModel:
def router_user_settings_nodes() -> models.response.ResponseBase:
"""
Get user selectable nodes.
@@ -430,7 +430,7 @@ def router_user_settings_nodes() -> models.response.ResponseModel:
description='Get user task queue.',
dependencies=[Depends(AuthRequired)],
)
def router_user_settings_tasks() -> models.response.ResponseModel:
def router_user_settings_tasks() -> models.response.ResponseBase:
"""
Get user task queue.
@@ -445,14 +445,14 @@ def router_user_settings_tasks() -> models.response.ResponseModel:
description='Get current user settings.',
dependencies=[Depends(AuthRequired)],
)
def router_user_settings() -> models.response.ResponseModel:
def router_user_settings() -> models.response.ResponseBase:
"""
Get current user settings.
Returns:
dict: A dictionary containing the current user settings.
"""
return models.response.ResponseModel(data=models.UserSettingResponse().model_dump())
return models.response.ResponseBase(data=models.UserSettingResponse().model_dump())
@user_settings_router.post(
path='/avatar',
@@ -460,7 +460,7 @@ def router_user_settings() -> models.response.ResponseModel:
description='Upload user avatar from file.',
dependencies=[Depends(AuthRequired)],
)
def router_user_settings_avatar() -> models.response.ResponseModel:
def router_user_settings_avatar() -> models.response.ResponseBase:
"""
Upload user avatar from file.
@@ -475,7 +475,7 @@ def router_user_settings_avatar() -> models.response.ResponseModel:
description='Set user avatar to Gravatar.',
dependencies=[Depends(AuthRequired)],
)
def router_user_settings_avatar_gravatar() -> models.response.ResponseModel:
def router_user_settings_avatar_gravatar() -> models.response.ResponseBase:
"""
Set user avatar to Gravatar.
@@ -490,7 +490,7 @@ def router_user_settings_avatar_gravatar() -> models.response.ResponseModel:
description='Update user settings.',
dependencies=[Depends(AuthRequired)],
)
def router_user_settings_patch(option: str) -> models.response.ResponseModel:
def router_user_settings_patch(option: str) -> models.response.ResponseBase:
"""
Update user settings.
@@ -510,7 +510,7 @@ def router_user_settings_patch(option: str) -> models.response.ResponseModel:
)
async def router_user_settings_2fa(
user: Annotated[models.user.User, Depends(AuthRequired)],
) -> models.response.ResponseModel:
) -> models.response.ResponseBase:
"""
Get two-factor authentication initialization information.
@@ -518,7 +518,7 @@ async def router_user_settings_2fa(
dict: A dictionary containing two-factor authentication setup information.
"""
return models.response.ResponseModel(
return models.response.ResponseBase(
data=await Password.generate_totp(user.username)
)
@@ -533,7 +533,7 @@ async def router_user_settings_2fa_enable(
user: Annotated[models.user.User, Depends(AuthRequired)],
setup_token: str,
code: str,
) -> models.response.ResponseModel:
) -> models.response.ResponseBase:
"""
Enable two-factor authentication for the user.
@@ -559,6 +559,6 @@ async def router_user_settings_2fa_enable(
user.two_factor = secret
user = await user.save(session)
return models.response.ResponseModel(
return models.response.ResponseBase(
data={"message": "Two-factor authentication enabled successfully"}
)

View File

@@ -1,6 +1,6 @@
from fastapi import APIRouter, Depends
from middleware.auth import SignRequired
from models.response import ResponseModel
from models.response import ResponseBase
vas_router = APIRouter(
prefix="/vas",
@@ -13,7 +13,7 @@ vas_router = APIRouter(
description='Get information about storage packs and quotas.',
dependencies=[Depends(SignRequired)]
)
def router_vas_pack() -> ResponseModel:
def router_vas_pack() -> ResponseBase:
"""
Get information about storage packs and quotas.
@@ -28,7 +28,7 @@ def router_vas_pack() -> ResponseModel:
description='Get product information along with payment details.',
dependencies=[Depends(SignRequired)]
)
def router_vas_product() -> ResponseModel:
def router_vas_product() -> ResponseBase:
"""
Get product information along with payment details.
@@ -43,7 +43,7 @@ def router_vas_product() -> ResponseModel:
description='Create an order for a product.',
dependencies=[Depends(SignRequired)]
)
def router_vas_order() -> ResponseModel:
def router_vas_order() -> ResponseBase:
"""
Create an order for a product.
@@ -58,7 +58,7 @@ def router_vas_order() -> ResponseModel:
description='Get information about a specific payment order by ID.',
dependencies=[Depends(SignRequired)]
)
def router_vas_order_get(id: str) -> ResponseModel:
def router_vas_order_get(id: str) -> ResponseBase:
"""
Get information about a specific payment order by ID.
@@ -76,7 +76,7 @@ def router_vas_order_get(id: str) -> ResponseModel:
description='Get information about a specific redemption code.',
dependencies=[Depends(SignRequired)]
)
def router_vas_redeem(code: str) -> ResponseModel:
def router_vas_redeem(code: str) -> ResponseBase:
"""
Get information about a specific redemption code.
@@ -94,7 +94,7 @@ def router_vas_redeem(code: str) -> ResponseModel:
description='Redeem a redemption code for a product or service.',
dependencies=[Depends(SignRequired)]
)
def router_vas_redeem_post() -> ResponseModel:
def router_vas_redeem_post() -> ResponseBase:
"""
Redeem a redemption code for a product or service.

View File

@@ -1,6 +1,6 @@
from fastapi import APIRouter, Depends, Request
from middleware.auth import SignRequired
from models.response import ResponseModel
from models.response import ResponseBase
# WebDAV 管理路由
webdav_router = APIRouter(
@@ -14,7 +14,7 @@ webdav_router = APIRouter(
description='Get account information for WebDAV.',
dependencies=[Depends(SignRequired)],
)
def router_webdav_accounts() -> ResponseModel:
def router_webdav_accounts() -> ResponseBase:
"""
Get account information for WebDAV.
@@ -29,7 +29,7 @@ def router_webdav_accounts() -> ResponseModel:
description='Create a new WebDAV account.',
dependencies=[Depends(SignRequired)],
)
def router_webdav_create_account() -> ResponseModel:
def router_webdav_create_account() -> ResponseBase:
"""
Create a new WebDAV account.
@@ -44,7 +44,7 @@ def router_webdav_create_account() -> ResponseModel:
description='Delete a WebDAV account by its ID.',
dependencies=[Depends(SignRequired)],
)
def router_webdav_delete_account(id: str) -> ResponseModel:
def router_webdav_delete_account(id: str) -> ResponseBase:
"""
Delete a WebDAV account by its ID.
@@ -62,7 +62,7 @@ def router_webdav_delete_account(id: str) -> ResponseModel:
description='Create a new WebDAV mount point.',
dependencies=[Depends(SignRequired)],
)
def router_webdav_create_mount() -> ResponseModel:
def router_webdav_create_mount() -> ResponseBase:
"""
Create a new WebDAV mount point.
@@ -77,7 +77,7 @@ def router_webdav_create_mount() -> ResponseModel:
description='Delete a WebDAV mount point by its ID.',
dependencies=[Depends(SignRequired)],
)
def router_webdav_delete_mount(id: str) -> ResponseModel:
def router_webdav_delete_mount(id: str) -> ResponseBase:
"""
Delete a WebDAV mount point by its ID.
@@ -95,7 +95,7 @@ def router_webdav_delete_mount(id: str) -> ResponseModel:
description='Update WebDAV account information by ID.',
dependencies=[Depends(SignRequired)],
)
def router_webdav_update_account(id: str) -> ResponseModel:
def router_webdav_update_account(id: str) -> ResponseBase:
"""
Update WebDAV account information by ID.

View File

@@ -1,306 +0,0 @@
from fastapi import APIRouter, Depends
from middleware.auth import SignRequired
from models.response import ResponseModel
share_router = APIRouter(
prefix='/share',
tags=["share"],
)
@share_router.get(
path='/{info}/{id}',
summary='获取分享',
description='Get shared content by info type and ID.',
)
def router_share_get(info: str, id: str) -> ResponseModel:
"""
Get shared content by info type and ID.
Args:
info (str): The type of information being shared.
id (str): The ID of the shared content.
Returns:
dict: A dictionary containing shared content information.
"""
pass
@share_router.put(
path='/download/{id}',
summary='创建文件下载会话',
description='Create a file download session by ID.',
)
def router_share_download(id: str) -> ResponseModel:
"""
Create a file download session by ID.
Args:
id (str): The ID of the file to be downloaded.
Returns:
dict: A dictionary containing download session information.
"""
pass
@share_router.get(
path='preview/{id}',
summary='预览分享文件',
description='Preview shared file by ID.',
)
def router_share_preview(id: str) -> ResponseModel:
"""
Preview shared file by ID.
Args:
id (str): The ID of the file to be previewed.
Returns:
dict: A dictionary containing preview information.
"""
pass
@share_router.get(
path='/doc/{id}',
summary='取得Office文档预览地址',
description='Get Office document preview URL by ID.',
)
def router_share_doc(id: str) -> ResponseModel:
"""
Get Office document preview URL by ID.
Args:
id (str): The ID of the Office document.
Returns:
dict: A dictionary containing the document preview URL.
"""
pass
@share_router.get(
path='/content/{id}',
summary='获取文本文件内容',
description='Get text file content by ID.',
)
def router_share_content(id: str) -> ResponseModel:
"""
Get text file content by ID.
Args:
id (str): The ID of the text file.
Returns:
str: The content of the text file.
"""
pass
@share_router.get(
path='/list/{id}/{path:path}',
summary='获取目录列文件',
description='Get directory listing by ID and path.',
)
def router_share_list(id: str, path: str = '') -> ResponseModel:
"""
Get directory listing by ID and path.
Args:
id (str): The ID of the directory.
path (str): The path within the directory.
Returns:
dict: A dictionary containing directory listing information.
"""
pass
@share_router.get(
path='/search/{id}/{type}/{keywords}',
summary='分享目录搜索',
description='Search within a shared directory by ID, type, and keywords.',
)
def router_share_search(id: str, type: str, keywords: str) -> ResponseModel:
"""
Search within a shared directory by ID, type, and keywords.
Args:
id (str): The ID of the shared directory.
type (str): The type of search (e.g., file, folder).
keywords (str): The keywords to search for.
Returns:
dict: A dictionary containing search results.
"""
pass
@share_router.post(
path='/archive/{id}',
summary='归档打包下载',
description='Archive and download shared content by ID.',
)
def router_share_archive(id: str) -> ResponseModel:
"""
Archive and download shared content by ID.
Args:
id (str): The ID of the content to be archived.
Returns:
dict: A dictionary containing archive download information.
"""
pass
@share_router.get(
path='/readme/{id}',
summary='获取README文本文件内容',
description='Get README text file content by ID.',
)
def router_share_readme(id: str) -> ResponseModel:
"""
Get README text file content by ID.
Args:
id (str): The ID of the README file.
Returns:
str: The content of the README file.
"""
pass
@share_router.get(
path='/thumb/{id}/{file}',
summary='获取缩略图',
description='Get thumbnail image by ID and file name.',
)
def router_share_thumb(id: str, file: str) -> ResponseModel:
"""
Get thumbnail image by ID and file name.
Args:
id (str): The ID of the shared content.
file (str): The name of the file for which to get the thumbnail.
Returns:
str: A Base64 encoded string of the thumbnail image.
"""
pass
@share_router.post(
path='/report/{id}',
summary='举报分享',
description='Report shared content by ID.',
)
def router_share_report(id: str) -> ResponseModel:
"""
Report shared content by ID.
Args:
id (str): The ID of the shared content to report.
Returns:
dict: A dictionary containing report submission information.
"""
pass
@share_router.get(
path='/search',
summary='搜索公共分享',
description='Search public shares by keywords and type.',
)
def router_share_search_public(keywords: str, type: str = 'all') -> ResponseModel:
"""
Search public shares by keywords and type.
Args:
keywords (str): The keywords to search for.
type (str): The type of search (e.g., all, file, folder).
Returns:
dict: A dictionary containing search results for public shares.
"""
pass
#####################
# 需要登录的接口
#####################
@share_router.post(
path='/',
summary='创建新分享',
description='Create a new share endpoint.',
dependencies=[Depends(SignRequired)]
)
def router_share_create() -> ResponseModel:
"""
Create a new share endpoint.
Returns:
ResponseModel: A model containing the response data for the new share creation.
"""
pass
@share_router.get(
path='/',
summary='列出我的分享',
description='Get a list of shares.',
dependencies=[Depends(SignRequired)]
)
def router_share_list() -> ResponseModel:
"""
Get a list of shares.
Returns:
ResponseModel: A model containing the response data for the list of shares.
"""
pass
@share_router.post(
path='/save/{id}',
summary='转存他人分享',
description='Save another user\'s share by ID.',
dependencies=[Depends(SignRequired)]
)
def router_share_save(id: str) -> ResponseModel:
"""
Save another user's share by ID.
Args:
id (str): The ID of the share to be saved.
Returns:
ResponseModel: A model containing the response data for the saved share.
"""
pass
@share_router.patch(
path='/{id}',
summary='更新分享信息',
description='Update share information by ID.',
dependencies=[Depends(SignRequired)]
)
def router_share_update(id: str) -> ResponseModel:
"""
Update share information by ID.
Args:
id (str): The ID of the share to be updated.
Returns:
ResponseModel: A model containing the response data for the updated share.
"""
pass
@share_router.delete(
path='/{id}',
summary='删除分享',
description='Delete a share by ID.',
dependencies=[Depends(SignRequired)]
)
def router_share_delete(id: str) -> ResponseModel:
"""
Delete a share by ID.
Args:
id (str): The ID of the share to be deleted.
Returns:
ResponseModel: A model containing the response data for the deleted share.
"""
pass

1
routers/dav/README.md Normal file
View File

@@ -0,0 +1 @@
# WebDAV 操作路由

View File

@@ -1,46 +0,0 @@
from fastapi import APIRouter
from .controllers import (
share,
site,
user,
file,
aria2,
directory,
object,
callback,
vas,
tag,
webdav,
admin,
slave
)
Router: list[APIRouter] = [
share.share_router,
site.site_router,
user.user_router,
user.user_settings_router,
file.file_router,
file.file_upload_router,
aria2.aria2_router,
directory.directory_router,
object.object_router,
callback.callback_router,
callback.oauth_router,
callback.pay_router,
callback.upload_router,
vas.vas_router,
tag.tag_router,
webdav.webdav_router,
admin.admin_router,
admin.admin_group_router,
admin.admin_user_router,
admin.admin_file_router,
admin.admin_aria2_router,
admin.admin_policy_router,
admin.admin_task_router,
admin.admin_vas_router,
slave.slave_router,
slave.slave_aria2_router
]

View File

@@ -4,7 +4,7 @@ from loguru import logger as log
from sqlmodel.ext.asyncio.session import AsyncSession
from models import LoginRequest, TokenResponse, User
from pkg.JWT.JWT import create_access_token, create_refresh_token
from utils.JWT.JWT import create_access_token, create_refresh_token
async def Login(
@@ -25,7 +25,7 @@ async def Login(
:return: TokenResponse 对象或状态码或 None
"""
from pkg.password.pwd import Password
from utils.password.pwd import Password
# TODO: 验证码校验
# captcha_setting = await Setting.get(

View File

@@ -15,7 +15,7 @@ def is_valid_instance_id(instance_id):
assert False, f"instance_id is not a valid UUID4: {instance_id}"
def test_read_main():
from pkg.conf.appmeta import BackendVersion
from utils.conf.appmeta import BackendVersion
response = client.get("/api/site/ping")
json_response = response.json()

View File

@@ -1,5 +1,5 @@
import pytest
from pkg.password.pwd import Password
from utils.password.pwd import Password
def test_password():
for i in range(10):

View File

@@ -7,8 +7,8 @@ import pyotp
from itsdangerous import URLSafeTimedSerializer, BadSignature, SignatureExpired
from pydantic import BaseModel, Field
from pkg.JWT.JWT import SECRET_KEY
from pkg.conf import appmeta
from utils.JWT.JWT import SECRET_KEY
from utils.conf import appmeta
_ph = PasswordHasher()