单元测试:新建用户与用户组

This commit is contained in:
2025-07-14 15:13:05 +08:00
parent e011a1ea0e
commit 557a50f539
26 changed files with 396 additions and 242 deletions

View File

@@ -69,7 +69,7 @@ def get_excluded_dirs(exclude_arg: str) -> Set[str]:
def clean_pycache(root_dir: str, exclude_dirs: Set[str], dry_run: bool = False) -> List[str]: def clean_pycache(root_dir: str, exclude_dirs: Set[str], dry_run: bool = False) -> List[str]:
"""清理 __pycache__ 目录""" """清理 __pycache__ 目录"""
log.info("开始清理 __pycache__ 目录...") log.info("开始清理 __pycache__ 目录pass")
cleaned_paths = [] cleaned_paths = []
for dirpath, dirnames, _ in os.walk(root_dir): for dirpath, dirnames, _ in os.walk(root_dir):
@@ -90,7 +90,7 @@ def clean_pycache(root_dir: str, exclude_dirs: Set[str], dry_run: bool = False)
def clean_pyc_files(root_dir: str, exclude_dirs: Set[str], dry_run: bool = False) -> List[str]: def clean_pyc_files(root_dir: str, exclude_dirs: Set[str], dry_run: bool = False) -> List[str]:
"""清理 .pyc 文件""" """清理 .pyc 文件"""
log.info("开始清理 .pyc 文件...") log.info("开始清理 .pyc 文件pass")
cleaned_files = [] cleaned_files = []
for dirpath, dirnames, filenames in os.walk(root_dir): for dirpath, dirnames, filenames in os.walk(root_dir):
@@ -112,7 +112,7 @@ def clean_pyc_files(root_dir: str, exclude_dirs: Set[str], dry_run: bool = False
def clean_pytest_cache(root_dir: str, exclude_dirs: Set[str], dry_run: bool = False) -> List[str]: def clean_pytest_cache(root_dir: str, exclude_dirs: Set[str], dry_run: bool = False) -> List[str]:
"""清理 .pytest_cache 目录""" """清理 .pytest_cache 目录"""
log.info("开始清理 .pytest_cache 目录...") log.info("开始清理 .pytest_cache 目录pass")
cleaned_paths = [] cleaned_paths = []
for dirpath, dirnames, _ in os.walk(root_dir): for dirpath, dirnames, _ in os.walk(root_dir):
@@ -133,7 +133,7 @@ def clean_pytest_cache(root_dir: str, exclude_dirs: Set[str], dry_run: bool = Fa
def clean_nicegui(root_dir: str, dry_run: bool = False) -> Tuple[bool, str]: def clean_nicegui(root_dir: str, dry_run: bool = False) -> Tuple[bool, str]:
"""清理 .nicegui 目录""" """清理 .nicegui 目录"""
log.info("开始清理 .nicegui 目录...") log.info("开始清理 .nicegui 目录pass")
nicegui_dir = os.path.join(root_dir, ".nicegui") nicegui_dir = os.path.join(root_dir, ".nicegui")
if os.path.exists(nicegui_dir) and os.path.isdir(nicegui_dir): if os.path.exists(nicegui_dir) and os.path.isdir(nicegui_dir):
success, error = safe_remove(nicegui_dir, dry_run) success, error = safe_remove(nicegui_dir, dry_run)
@@ -146,7 +146,7 @@ def clean_nicegui(root_dir: str, dry_run: bool = False) -> Tuple[bool, str]:
def clean_testdb(root_dir: str, dry_run: bool = False) -> Tuple[bool, str, str]: def clean_testdb(root_dir: str, dry_run: bool = False) -> Tuple[bool, str, str]:
"""清理测试数据库文件""" """清理测试数据库文件"""
log.info("开始清理 test.db 文件...") log.info("开始清理 test.db 文件pass")
test_db = os.path.join(root_dir, "test.db") test_db = os.path.join(root_dir, "test.db")
if os.path.exists(test_db) and os.path.isfile(test_db): if os.path.exists(test_db) and os.path.isfile(test_db):
success, error = safe_remove(test_db, dry_run) success, error = safe_remove(test_db, dry_run)

10
main.py
View File

@@ -4,10 +4,14 @@ from pkg.conf import appmeta
from models.database import init_db from models.database import init_db
from models.migration import init_default_settings from models.migration import init_default_settings
from pkg.lifespan import lifespan from pkg.lifespan import lifespan
from pkg.JWT import jwt
# 添加初始化数据库启动项
lifespan.add_startup(init_db) lifespan.add_startup(init_db)
lifespan.add_startup(init_default_settings) lifespan.add_startup(init_default_settings)
lifespan.add_startup(jwt.load_secret_key)
# 创建应用实例并设置元数据
app = FastAPI( app = FastAPI(
title=appmeta.APP_NAME, title=appmeta.APP_NAME,
summary=appmeta.summary, summary=appmeta.summary,
@@ -18,6 +22,7 @@ app = FastAPI(
lifespan=lifespan.lifespan, lifespan=lifespan.lifespan,
) )
# 挂载路由
for router in routers.Router: for router in routers.Router:
app.include_router( app.include_router(
router, router,
@@ -30,7 +35,8 @@ for router in routers.Router:
500: {"description": "内部服务器错误 Internal server error"} 500: {"description": "内部服务器错误 Internal server error"}
},) },)
# 启动时打印欢迎信息
if __name__ == "__main__": if __name__ == "__main__":
import uvicorn import uvicorn
uvicorn.run(app=app, host="0.0.0.0", port=5213) # uvicorn.run(app=app, host="0.0.0.0", port=5213) # 生产环境
# uvicorn.run(app='main:app', host="0.0.0.0", port=5213, reload=True) uvicorn.run(app='main:app', host="0.0.0.0", port=5213, reload=True) # 开发环境

View File

@@ -8,7 +8,7 @@ async def AuthRequired(
''' '''
AuthRequired 需要登录 AuthRequired 需要登录
''' '''
return True from models.user import User
async def SignRequired( async def SignRequired(
token: Annotated[str, Depends(jwt.oauth2_scheme)] token: Annotated[str, Depends(jwt.oauth2_scheme)]
@@ -27,4 +27,4 @@ async def AdminRequired(
使用方法: 使用方法:
>>> APIRouter(dependencies=[Depends(is_admin)]) >>> APIRouter(dependencies=[Depends(is_admin)])
''' '''
... pass

View File

@@ -6,7 +6,7 @@ from sqlmodel.ext.asyncio.session import AsyncSession
from sqlalchemy.orm import sessionmaker from sqlalchemy.orm import sessionmaker
from typing import AsyncGenerator from typing import AsyncGenerator
ASYNC_DATABASE_URL = "sqlite+aiosqlite:///database.db" ASYNC_DATABASE_URL = "sqlite+aiosqlite:///:memory:"
engine = create_async_engine( engine = create_async_engine(
ASYNC_DATABASE_URL, ASYNC_DATABASE_URL,

View File

@@ -49,43 +49,58 @@ class Group(BaseModel, table=True):
sa_relationship_kwargs={"foreign_keys": "User.previous_group_id"} sa_relationship_kwargs={"foreign_keys": "User.previous_group_id"}
) )
async def add_group(self, name: str, policies: Optional[str] = None, max_storage: int = 0, @staticmethod
share_enabled: bool = False, web_dav_enabled: bool = False, async def create(
speed_limit: int = 0, options: Optional[str] = None) -> "Group": group: "Group"
) -> "Group":
""" """
向数据库内添加用户组。 向数据库内添加用户组。
:param name: 用户组 :param group: 用户组对象
:type name: str :type group: Group
:param policies: 允许的策略ID列表逗号分隔默认为 None
:type policies: Optional[str]
:param max_storage: 最大存储空间(字节),默认为 0
:type max_storage: int
:param share_enabled: 是否允许创建分享,默认为 False
:type share_enabled: bool
:param web_dav_enabled: 是否允许使用WebDAV默认为 False
:type web_dav_enabled: bool
:param speed_limit: 速度限制 (KB/s), 0为不限制默认为 0
:type speed_limit: int
:param options: 其他选项 (JSON格式),默认为 None
:type options: Optional[str]
:return: 新创建的用户组对象 :return: 新创建的用户组对象
:rtype: Group :rtype: Group
""" """
from .database import get_session from .database import get_session
async for session in get_session():
try:
session.add(group)
await session.commit()
await session.refresh(group)
except Exception as e:
await session.rollback()
raise e
return group
@staticmethod
async def get(
id: int = None
) -> Optional["Group"]:
"""
获取用户组信息。
:param id: 用户组ID默认为 None
:type id: int
:return: 用户组对象或 None
:rtype: Optional[Group]
"""
from .database import get_session
from sqlmodel import select
session = get_session() session = get_session()
new_group = Group( if id is None:
name=name, return None
policies=policies,
max_storage=max_storage,
share_enabled=share_enabled,
web_dav_enabled=web_dav_enabled,
speed_limit=speed_limit,
options=options
)
session.add(new_group)
session.commit() async for session in get_session():
session.refresh(new_group) statement = select(Group).where(Group.id == id)
result = await session.exec(statement)
group = result.one_or_none()
if group:
return group
else:
return None

View File

@@ -114,3 +114,54 @@ async def init_default_settings() -> None:
name=setting.name, name=setting.name,
value=setting.value value=setting.value
) )
async def init_default_group() -> None:
from .group import Group
try:
# 未找到初始管理组时,则创建
if not Group.get(id=1):
Group.add(
name="管理员",
max_storage=1 * 1024 * 1024 * 1024, # 1GB
share_enabled=True,
web_dav_enabled=True,
options={
"ArchiveDownload": True,
"ArchiveTask": True,
"ShareDownload": True,
"Aria2": True,
}
)
except Exception as e:
raise RuntimeError(f"无法创建管理员用户组: {e}") from e
try:
# 未找到初始注册会员时,则创建
if not Group.get(id=2):
Group.add(
name="注册会员",
max_storage=1 * 1024 * 1024 * 1024, # 1GB
share_enabled=True,
web_dav_enabled=True,
options={
"ShareDownload": True,
}
)
except Exception as e:
raise RuntimeError(f"无法创建初始注册会员用户组: {e}") from e
try:
# 未找到初始游客组时,则创建
if not Group.get(id=3):
Group.add(
name="游客",
policies="[]",
share_enabled=False,
web_dav_enabled=False,
options={
"ShareDownload": True,
}
)
except Exception as e:
raise RuntimeError(f"无法创建初始游客用户组: {e}") from e

View File

@@ -71,6 +71,7 @@ class Setting(BaseModel, table=True):
), ),
) )
@staticmethod
async def add( async def add(
type: SETTINGS_TYPE = None, type: SETTINGS_TYPE = None,
name: str = None, name: str = None,
@@ -97,6 +98,7 @@ class Setting(BaseModel, table=True):
await session.commit() await session.commit()
@staticmethod
async def get( async def get(
type: SETTINGS_TYPE, type: SETTINGS_TYPE,
name: str, name: str,
@@ -138,6 +140,7 @@ class Setting(BaseModel, table=True):
else: else:
raise ValueError(f"Unsupported format: {format}") raise ValueError(f"Unsupported format: {format}")
@staticmethod
async def set( async def set(
type: SETTINGS_TYPE, type: SETTINGS_TYPE,
name: str, name: str,
@@ -177,6 +180,7 @@ class Setting(BaseModel, table=True):
setting.value = value setting.value = value
await session.commit() await session.commit()
@staticmethod
async def delete( async def delete(
type: SETTINGS_TYPE, type: SETTINGS_TYPE,
name: str name: str

View File

@@ -87,3 +87,24 @@ class User(BaseModel, table=True):
tags: list["Tag"] = Relationship(back_populates="user") tags: list["Tag"] = Relationship(back_populates="user")
tasks: list["Task"] = Relationship(back_populates="user") tasks: list["Task"] = Relationship(back_populates="user")
webdavs: list["WebDAV"] = Relationship(back_populates="user") webdavs: list["WebDAV"] = Relationship(back_populates="user")
async def create(
user: "User"
):
"""
向数据库内添加用户。
:param user: User 实例
:type user: User
"""
from .database import get_session
async for session in get_session():
try:
session.add(user)
await session.commit()
await session.refresh(user)
except Exception as e:
await session.rollback()
raise e
return user

View File

@@ -1,4 +1,5 @@
from fastapi.security import OAuth2PasswordBearer from fastapi.security import OAuth2PasswordBearer
from models.setting import Setting
oauth2_scheme = OAuth2PasswordBearer( oauth2_scheme = OAuth2PasswordBearer(
scheme_name='获取 JWT Bearer 令牌', scheme_name='获取 JWT Bearer 令牌',
@@ -7,3 +8,13 @@ oauth2_scheme = OAuth2PasswordBearer(
) )
SECRET_KEY = '' SECRET_KEY = ''
async def load_secret_key() -> None:
"""
从数据库读取 JWT 的密钥。
:param key: 用于加密和解密 JWT 的密钥
:type key: str
"""
global SECRET_KEY
SECRET_KEY = await Setting.get(type='auth', name='secret_key')

View File

@@ -70,7 +70,7 @@ def router_admin_get_summary() -> ResponseModel:
Returns: Returns:
ResponseModel: 包含站点概况信息的响应模型。 ResponseModel: 包含站点概况信息的响应模型。
""" """
... pass
@admin_router.get( @admin_router.get(
path='/news', path='/news',
@@ -85,7 +85,7 @@ def router_admin_get_news() -> ResponseModel:
Returns: Returns:
ResponseModel: 包含社区新闻信息的响应模型。 ResponseModel: 包含社区新闻信息的响应模型。
""" """
... pass
@admin_router.patch( @admin_router.patch(
path='/settings', path='/settings',
@@ -100,7 +100,7 @@ def router_admin_update_settings() -> ResponseModel:
Returns: Returns:
ResponseModel: 包含更新结果的响应模型。 ResponseModel: 包含更新结果的响应模型。
""" """
... pass
@admin_router.get( @admin_router.get(
path='/settings', path='/settings',
@@ -115,7 +115,7 @@ def router_admin_get_settings() -> ResponseModel:
Returns: Returns:
ResponseModel: 包含站点设置的响应模型。 ResponseModel: 包含站点设置的响应模型。
""" """
... pass
@admin_group_router.get( @admin_group_router.get(
path='/', path='/',
@@ -130,7 +130,7 @@ def router_admin_get_groups() -> ResponseModel:
Returns: Returns:
ResponseModel: 包含用户组列表的响应模型。 ResponseModel: 包含用户组列表的响应模型。
""" """
... pass
@admin_group_router.get( @admin_group_router.get(
path='/{group_id}', path='/{group_id}',
@@ -148,7 +148,7 @@ def router_admin_get_group(group_id: int) -> ResponseModel:
Returns: Returns:
ResponseModel: 包含用户组信息的响应模型。 ResponseModel: 包含用户组信息的响应模型。
""" """
... pass
@admin_group_router.get( @admin_group_router.get(
path='/list/{group_id}', path='/list/{group_id}',
@@ -172,7 +172,7 @@ def router_admin_get_group_members(
Returns: Returns:
ResponseModel: 包含用户组成员列表的响应模型。 ResponseModel: 包含用户组成员列表的响应模型。
""" """
... pass
@admin_group_router.post( @admin_group_router.post(
path='/', path='/',
@@ -187,7 +187,7 @@ def router_admin_create_group() -> ResponseModel:
Returns: Returns:
ResponseModel: 包含创建结果的响应模型。 ResponseModel: 包含创建结果的响应模型。
""" """
... pass
@admin_group_router.patch( @admin_group_router.patch(
path='/{group_id}', path='/{group_id}',
@@ -205,7 +205,7 @@ def router_admin_update_group(group_id: int) -> ResponseModel:
Returns: Returns:
ResponseModel: 包含更新结果的响应模型。 ResponseModel: 包含更新结果的响应模型。
""" """
... pass
@admin_group_router.delete( @admin_group_router.delete(
path='/{group_id}', path='/{group_id}',
@@ -223,7 +223,7 @@ def router_admin_delete_group(group_id: int) -> ResponseModel:
Returns: Returns:
ResponseModel: 包含删除结果的响应模型。 ResponseModel: 包含删除结果的响应模型。
""" """
... pass
@admin_user_router.get( @admin_user_router.get(
path='/info/{user_id}', path='/info/{user_id}',
@@ -241,7 +241,7 @@ def router_admin_get_user(user_id: int) -> ResponseModel:
Returns: Returns:
ResponseModel: 包含用户信息的响应模型。 ResponseModel: 包含用户信息的响应模型。
""" """
... pass
@admin_user_router.get( @admin_user_router.get(
path='/list', path='/list',
@@ -263,7 +263,7 @@ def router_admin_get_users(
Returns: Returns:
ResponseModel: 包含用户列表的响应模型。 ResponseModel: 包含用户列表的响应模型。
""" """
... pass
@admin_user_router.post( @admin_user_router.post(
path='/create', path='/create',
@@ -278,7 +278,7 @@ def router_admin_create_user() -> ResponseModel:
Returns: Returns:
ResponseModel: 包含创建结果的响应模型。 ResponseModel: 包含创建结果的响应模型。
""" """
... pass
@admin_user_router.patch( @admin_user_router.patch(
path='/{user_id}', path='/{user_id}',
@@ -296,7 +296,7 @@ def router_admin_update_user(user_id: int) -> ResponseModel:
Returns: Returns:
ResponseModel: 包含更新结果的响应模型。 ResponseModel: 包含更新结果的响应模型。
""" """
... pass
@admin_user_router.delete( @admin_user_router.delete(
path='/{user_id}', path='/{user_id}',
@@ -314,7 +314,7 @@ def router_admin_delete_user(user_id: int) -> ResponseModel:
Returns: Returns:
ResponseModel: 包含删除结果的响应模型。 ResponseModel: 包含删除结果的响应模型。
""" """
... pass
@admin_user_router.post( @admin_user_router.post(
path='/calibrate/{user_id}', path='/calibrate/{user_id}',
@@ -323,7 +323,7 @@ def router_admin_delete_user(user_id: int) -> ResponseModel:
dependencies=[Depends(AdminRequired)] dependencies=[Depends(AdminRequired)]
) )
def router_admin_calibrate_storage(): def router_admin_calibrate_storage():
... pass
@admin_file_router.get( @admin_file_router.get(
path='/list', path='/list',
@@ -338,7 +338,7 @@ def router_admin_get_file_list() -> ResponseModel:
Returns: Returns:
ResponseModel: 包含文件列表的响应模型。 ResponseModel: 包含文件列表的响应模型。
""" """
... pass
@admin_file_router.get( @admin_file_router.get(
path='/preview/{file_id}', path='/preview/{file_id}',
@@ -356,7 +356,7 @@ def router_admin_preview_file(file_id: int) -> ResponseModel:
Returns: Returns:
ResponseModel: 包含文件预览内容的响应模型。 ResponseModel: 包含文件预览内容的响应模型。
""" """
... pass
@admin_file_router.patch( @admin_file_router.patch(
path='/ban/{file_id}', path='/ban/{file_id}',
@@ -376,7 +376,7 @@ def router_admin_ban_file(file_id: int) -> ResponseModel:
Returns: Returns:
ResponseModel: 包含删除结果的响应模型。 ResponseModel: 包含删除结果的响应模型。
""" """
... pass
@admin_file_router.delete( @admin_file_router.delete(
path='/{file_id}', path='/{file_id}',
@@ -394,7 +394,7 @@ def router_admin_delete_file(file_id: int) -> ResponseModel:
Returns: Returns:
ResponseModel: 包含删除结果的响应模型。 ResponseModel: 包含删除结果的响应模型。
""" """
... pass
@admin_aria2_router.post( @admin_aria2_router.post(
path='/test', path='/test',
@@ -403,7 +403,7 @@ def router_admin_delete_file(file_id: int) -> ResponseModel:
dependencies=[Depends(AdminRequired)] dependencies=[Depends(AdminRequired)]
) )
def router_admin_aira2_test() -> ResponseModel: def router_admin_aira2_test() -> ResponseModel:
... pass
@admin_policy_router.get( @admin_policy_router.get(
path='/list', path='/list',
@@ -412,7 +412,7 @@ def router_admin_aira2_test() -> ResponseModel:
dependencies=[Depends(AdminRequired)] dependencies=[Depends(AdminRequired)]
) )
def router_policy_list() -> ResponseModel: def router_policy_list() -> ResponseModel:
... pass
@admin_policy_router.post( @admin_policy_router.post(
path='/test/path', path='/test/path',
@@ -421,7 +421,7 @@ def router_policy_list() -> ResponseModel:
dependencies=[Depends(AdminRequired)] dependencies=[Depends(AdminRequired)]
) )
def router_policy_test_path() -> ResponseModel: def router_policy_test_path() -> ResponseModel:
... pass
@admin_policy_router.post( @admin_policy_router.post(
path='/test/slave', path='/test/slave',
@@ -430,7 +430,7 @@ def router_policy_test_path() -> ResponseModel:
dependencies=[Depends(AdminRequired)] dependencies=[Depends(AdminRequired)]
) )
def router_policy_test_slave() -> ResponseModel: def router_policy_test_slave() -> ResponseModel:
... pass
@admin_policy_router.post( @admin_policy_router.post(
path='/', path='/',
@@ -439,7 +439,7 @@ def router_policy_test_slave() -> ResponseModel:
dependencies=[Depends(AdminRequired)] dependencies=[Depends(AdminRequired)]
) )
def router_policy_add_policy() -> ResponseModel: def router_policy_add_policy() -> ResponseModel:
... pass
@admin_policy_router.post( @admin_policy_router.post(
path='/cors', path='/cors',
@@ -448,7 +448,7 @@ def router_policy_add_policy() -> ResponseModel:
dependencies=[Depends(AdminRequired)] dependencies=[Depends(AdminRequired)]
) )
def router_policy_add_cors() -> ResponseModel: def router_policy_add_cors() -> ResponseModel:
... pass
@admin_policy_router.post( @admin_policy_router.post(
path='/scf', path='/scf',
@@ -457,7 +457,7 @@ def router_policy_add_cors() -> ResponseModel:
dependencies=[Depends(AdminRequired)] dependencies=[Depends(AdminRequired)]
) )
def router_policy_add_scf() -> ResponseModel: def router_policy_add_scf() -> ResponseModel:
... pass
@admin_policy_router.get( @admin_policy_router.get(
path='/{id}/oauth', path='/{id}/oauth',
@@ -466,7 +466,7 @@ def router_policy_add_scf() -> ResponseModel:
dependencies=[Depends(AdminRequired)] dependencies=[Depends(AdminRequired)]
) )
def router_policy_onddrive_oauth() -> ResponseModel: def router_policy_onddrive_oauth() -> ResponseModel:
... pass
@admin_policy_router.get( @admin_policy_router.get(
path='/{id}', path='/{id}',
@@ -475,7 +475,7 @@ def router_policy_onddrive_oauth() -> ResponseModel:
dependencies=[Depends(AdminRequired)] dependencies=[Depends(AdminRequired)]
) )
def router_policy_get_policy() -> ResponseModel: def router_policy_get_policy() -> ResponseModel:
... pass
@admin_policy_router.delete( @admin_policy_router.delete(
path='/{id}', path='/{id}',
@@ -484,4 +484,4 @@ def router_policy_get_policy() -> ResponseModel:
dependencies=[Depends(AdminRequired)] dependencies=[Depends(AdminRequired)]
) )
def router_policy_delete_policy() -> ResponseModel: def router_policy_delete_policy() -> ResponseModel:
... pass

View File

@@ -20,7 +20,7 @@ def router_aria2_url() -> ResponseModel:
Returns: Returns:
ResponseModel: A model containing the response data for the URL download task. ResponseModel: A model containing the response data for the URL download task.
""" """
... pass
@aria2_router.post( @aria2_router.post(
path='/torrent/{id}', path='/torrent/{id}',
@@ -38,7 +38,7 @@ def router_aria2_torrent(id: str) -> ResponseModel:
Returns: Returns:
ResponseModel: A model containing the response data for the torrent download task. ResponseModel: A model containing the response data for the torrent download task.
""" """
... pass
@aria2_router.put( @aria2_router.put(
path='/select/{gid}', path='/select/{gid}',
@@ -56,7 +56,7 @@ def router_aria2_select(gid: str) -> ResponseModel:
Returns: Returns:
ResponseModel: A model containing the response data for the re-selection of files. ResponseModel: A model containing the response data for the re-selection of files.
""" """
... pass
@aria2_router.delete( @aria2_router.delete(
path='/task/{gid}', path='/task/{gid}',
@@ -74,7 +74,7 @@ def router_aria2_delete(gid: str) -> ResponseModel:
Returns: Returns:
ResponseModel: A model containing the response data for the deletion of the download task. ResponseModel: A model containing the response data for the deletion of the download task.
""" """
... pass
@aria2_router.get( @aria2_router.get(
'/downloading', '/downloading',
@@ -89,7 +89,7 @@ def router_aria2_downloading() -> ResponseModel:
Returns: Returns:
ResponseModel: A model containing the response data for currently downloading tasks. ResponseModel: A model containing the response data for currently downloading tasks.
""" """
... pass
@aria2_router.get( @aria2_router.get(
path='/finished', path='/finished',
@@ -104,4 +104,4 @@ def router_aria2_finished() -> ResponseModel:
Returns: Returns:
ResponseModel: A model containing the response data for finished tasks. ResponseModel: A model containing the response data for finished tasks.
""" """
... pass

View File

@@ -39,7 +39,7 @@ def router_callback_qq() -> ResponseModel:
Returns: Returns:
ResponseModel: A model containing the response data for the QQ OAuth callback. ResponseModel: A model containing the response data for the QQ OAuth callback.
""" """
... pass
@oauth_router.post( @oauth_router.post(
path='/github', path='/github',
@@ -53,7 +53,7 @@ def router_callback_github() -> ResponseModel:
Returns: Returns:
ResponseModel: A model containing the response data for the GitHub OAuth callback. ResponseModel: A model containing the response data for the GitHub OAuth callback.
""" """
... pass
@pay_router.post( @pay_router.post(
path='/alipay', path='/alipay',
@@ -67,7 +67,7 @@ def router_callback_alipay() -> ResponseModel:
Returns: Returns:
ResponseModel: A model containing the response data for the Alipay payment callback. ResponseModel: A model containing the response data for the Alipay payment callback.
""" """
... pass
@pay_router.post( @pay_router.post(
path='/wechat', path='/wechat',
@@ -81,7 +81,7 @@ def router_callback_wechat() -> ResponseModel:
Returns: Returns:
ResponseModel: A model containing the response data for the WeChat Pay payment callback. ResponseModel: A model containing the response data for the WeChat Pay payment callback.
""" """
... pass
@pay_router.post( @pay_router.post(
path='/stripe', path='/stripe',
@@ -95,7 +95,7 @@ def router_callback_stripe() -> ResponseModel:
Returns: Returns:
ResponseModel: A model containing the response data for the Stripe payment callback. ResponseModel: A model containing the response data for the Stripe payment callback.
""" """
... pass
@pay_router.get( @pay_router.get(
path='/easypay', path='/easypay',
@@ -109,7 +109,7 @@ def router_callback_easypay() -> PlainTextResponse:
Returns: Returns:
PlainTextResponse: A response containing the payment status for the EasyPay payment callback. PlainTextResponse: A response containing the payment status for the EasyPay payment callback.
""" """
... pass
# return PlainTextResponse("success", status_code=200) # return PlainTextResponse("success", status_code=200)
@pay_router.get( @pay_router.get(
@@ -128,7 +128,7 @@ def router_callback_custom(order_no: str, id: str) -> ResponseModel:
Returns: Returns:
ResponseModel: A model containing the response data for the custom payment callback. ResponseModel: A model containing the response data for the custom payment callback.
""" """
... pass
@upload_router.post( @upload_router.post(
path='/remote/{session_id}/{key}', path='/remote/{session_id}/{key}',
@@ -146,7 +146,7 @@ def router_callback_remote(session_id: str, key: str) -> ResponseModel:
Returns: Returns:
ResponseModel: A model containing the response data for the remote upload callback. ResponseModel: A model containing the response data for the remote upload callback.
""" """
... pass
@upload_router.post( @upload_router.post(
path='/qiniu/{session_id}', path='/qiniu/{session_id}',
@@ -163,7 +163,7 @@ def router_callback_qiniu(session_id: str) -> ResponseModel:
Returns: Returns:
ResponseModel: A model containing the response data for the Qiniu Cloud upload callback. ResponseModel: A model containing the response data for the Qiniu Cloud upload callback.
""" """
... pass
@upload_router.post( @upload_router.post(
path='/tencent/{session_id}', path='/tencent/{session_id}',
@@ -180,7 +180,7 @@ def router_callback_tencent(session_id: str) -> ResponseModel:
Returns: Returns:
ResponseModel: A model containing the response data for the Tencent Cloud upload callback. ResponseModel: A model containing the response data for the Tencent Cloud upload callback.
""" """
... pass
@upload_router.post( @upload_router.post(
path='/aliyun/{session_id}', path='/aliyun/{session_id}',
@@ -197,7 +197,7 @@ def router_callback_aliyun(session_id: str) -> ResponseModel:
Returns: Returns:
ResponseModel: A model containing the response data for the Aliyun upload callback. ResponseModel: A model containing the response data for the Aliyun upload callback.
""" """
... pass
@upload_router.post( @upload_router.post(
path='/upyun/{session_id}', path='/upyun/{session_id}',
@@ -214,7 +214,7 @@ def router_callback_upyun(session_id: str) -> ResponseModel:
Returns: Returns:
ResponseModel: A model containing the response data for the Upyun upload callback. ResponseModel: A model containing the response data for the Upyun upload callback.
""" """
... pass
@upload_router.post( @upload_router.post(
path='/aws/{session_id}', path='/aws/{session_id}',
@@ -231,7 +231,7 @@ def router_callback_aws(session_id: str) -> ResponseModel:
Returns: Returns:
ResponseModel: A model containing the response data for the AWS S3 upload callback. ResponseModel: A model containing the response data for the AWS S3 upload callback.
""" """
... pass
@upload_router.post( @upload_router.post(
path='/onedrive/finish/{session_id}', path='/onedrive/finish/{session_id}',
@@ -248,7 +248,7 @@ def router_callback_onedrive_finish(session_id: str) -> ResponseModel:
Returns: Returns:
ResponseModel: A model containing the response data for the OneDrive upload completion callback. ResponseModel: A model containing the response data for the OneDrive upload completion callback.
""" """
... pass
@upload_router.get( @upload_router.get(
path='/ondrive/auth', path='/ondrive/auth',
@@ -262,7 +262,7 @@ def router_callback_onedrive_auth() -> ResponseModel:
Returns: Returns:
ResponseModel: A model containing the response data for the OneDrive authorization callback. ResponseModel: A model containing the response data for the OneDrive authorization callback.
""" """
... pass
@upload_router.get( @upload_router.get(
path='/google/auth', path='/google/auth',
@@ -276,4 +276,4 @@ def router_callback_google_auth() -> ResponseModel:
Returns: Returns:
ResponseModel: A model containing the response data for the Google OAuth completion callback. ResponseModel: A model containing the response data for the Google OAuth completion callback.
""" """
... pass

View File

@@ -20,7 +20,7 @@ def router_directory_create() -> ResponseModel:
Returns: Returns:
ResponseModel: A model containing the response data for the directory creation. ResponseModel: A model containing the response data for the directory creation.
""" """
... pass
@directory_router.get( @directory_router.get(
path='/{path:path}', path='/{path:path}',
@@ -38,4 +38,4 @@ def router_directory_get(path: str) -> ResponseModel:
Returns: Returns:
ResponseModel: A model containing the response data for the directory contents. ResponseModel: A model containing the response data for the directory contents.
""" """
... pass

View File

@@ -1,4 +1,5 @@
from fastapi import APIRouter, Depends from fastapi import APIRouter, Depends, UploadFile
from fastapi.responses import FileResponse
from middleware.auth import SignRequired from middleware.auth import SignRequired
from models.response import ResponseModel from models.response import ResponseModel
@@ -17,7 +18,7 @@ file_upload_router = APIRouter(
summary='文件外链(直接输出文件数据)', summary='文件外链(直接输出文件数据)',
description='Get file external link endpoint.', description='Get file external link endpoint.',
) )
def router_file_get(id: str, name: str) -> ResponseModel: def router_file_get(id: str, name: str) -> FileResponse:
""" """
Get file external link endpoint. Get file external link endpoint.
@@ -26,9 +27,9 @@ def router_file_get(id: str, name: str) -> ResponseModel:
name (str): The name of the file. name (str): The name of the file.
Returns: Returns:
ResponseModel: A model containing the response data for the file. FileResponse: A response containing the file data.
""" """
... pass
@file_router.get( @file_router.get(
path='/source/{id}/{name}', path='/source/{id}/{name}',
@@ -46,7 +47,7 @@ def router_file_source(id: str, name: str) -> ResponseModel:
Returns: Returns:
ResponseModel: A model containing the response data for the file with a redirect. ResponseModel: A model containing the response data for the file with a redirect.
""" """
... pass
@file_upload_router.get( @file_upload_router.get(
path='/download/{id}', path='/download/{id}',
@@ -63,7 +64,7 @@ def router_file_download(id: str) -> ResponseModel:
Returns: Returns:
ResponseModel: A model containing the response data for the file download. ResponseModel: A model containing the response data for the file download.
""" """
... pass
@file_upload_router.get( @file_upload_router.get(
path='/archive/{sessionID}/archive.zip', path='/archive/{sessionID}/archive.zip',
@@ -80,14 +81,14 @@ def router_file_archive_download(sessionID: str) -> ResponseModel:
Returns: Returns:
ResponseModel: A model containing the response data for the archived files download. ResponseModel: A model containing the response data for the archived files download.
""" """
... pass
@file_upload_router.post( @file_upload_router.post(
path='/{sessionID}/{index}', path='/{sessionID}/{index}',
summary='文件上传', summary='文件上传',
description='File upload endpoint.', description='File upload endpoint.',
) )
def router_file_upload(sessionID: str, index: int) -> ResponseModel: def router_file_upload(sessionID: str, index: int, file: UploadFile) -> ResponseModel:
""" """
File upload endpoint. File upload endpoint.
@@ -98,7 +99,7 @@ def router_file_upload(sessionID: str, index: int) -> ResponseModel:
Returns: Returns:
ResponseModel: A model containing the response data. ResponseModel: A model containing the response data.
""" """
... pass
@file_upload_router.put( @file_upload_router.put(
path='/', path='/',
@@ -113,7 +114,7 @@ def router_file_upload_session() -> ResponseModel:
Returns: Returns:
ResponseModel: A model containing the response data for the upload session. ResponseModel: A model containing the response data for the upload session.
""" """
... pass
@file_upload_router.delete( @file_upload_router.delete(
path='/{sessionID}', path='/{sessionID}',
@@ -131,7 +132,7 @@ def router_file_upload_session_delete(sessionID: str) -> ResponseModel:
Returns: Returns:
ResponseModel: A model containing the response data for the deletion. ResponseModel: A model containing the response data for the deletion.
""" """
... pass
@file_upload_router.delete( @file_upload_router.delete(
path='/', path='/',
@@ -146,7 +147,7 @@ def router_file_upload_session_clear() -> ResponseModel:
Returns: Returns:
ResponseModel: A model containing the response data for clearing all sessions. ResponseModel: A model containing the response data for clearing all sessions.
""" """
... pass
@file_router.put( @file_router.put(
path='/update/{id}', path='/update/{id}',
@@ -164,7 +165,7 @@ def router_file_update(id: str) -> ResponseModel:
Returns: Returns:
ResponseModel: A model containing the response data for the file update. ResponseModel: A model containing the response data for the file update.
""" """
... pass
@file_router.post( @file_router.post(
path='/create', path='/create',
@@ -179,7 +180,7 @@ def router_file_create() -> ResponseModel:
Returns: Returns:
ResponseModel: A model containing the response data for the file creation. ResponseModel: A model containing the response data for the file creation.
""" """
... pass
@file_router.put( @file_router.put(
path='/download/{id}', path='/download/{id}',
@@ -197,7 +198,7 @@ def router_file_download(id: str) -> ResponseModel:
Returns: Returns:
ResponseModel: A model containing the response data for the file download session. ResponseModel: A model containing the response data for the file download session.
""" """
... pass
@file_router.get( @file_router.get(
path='/preview/{id}', path='/preview/{id}',
@@ -215,7 +216,7 @@ def router_file_preview(id: str) -> ResponseModel:
Returns: Returns:
ResponseModel: A model containing the response data for the file preview. ResponseModel: A model containing the response data for the file preview.
""" """
... pass
@file_router.get( @file_router.get(
path='/content/{id}', path='/content/{id}',
@@ -233,7 +234,7 @@ def router_file_content(id: str) -> ResponseModel:
Returns: Returns:
ResponseModel: A model containing the response data for the text file content. ResponseModel: A model containing the response data for the text file content.
""" """
... pass
@file_router.get( @file_router.get(
path='/doc/{id}', path='/doc/{id}',
@@ -251,7 +252,7 @@ def router_file_doc(id: str) -> ResponseModel:
Returns: Returns:
ResponseModel: A model containing the response data for the Office document preview URL. ResponseModel: A model containing the response data for the Office document preview URL.
""" """
... pass
@file_router.get( @file_router.get(
path='/thumb/{id}', path='/thumb/{id}',
@@ -269,7 +270,7 @@ def router_file_thumb(id: str) -> ResponseModel:
Returns: Returns:
ResponseModel: A model containing the response data for the file thumbnail. ResponseModel: A model containing the response data for the file thumbnail.
""" """
... pass
@file_router.post( @file_router.post(
path='/source/{id}', path='/source/{id}',
@@ -287,7 +288,7 @@ def router_file_source(id: str) -> ResponseModel:
Returns: Returns:
ResponseModel: A model containing the response data for the file external link. ResponseModel: A model containing the response data for the file external link.
""" """
... pass
@file_router.post( @file_router.post(
path='/archive', path='/archive',
@@ -305,7 +306,7 @@ def router_file_archive(id: str) -> ResponseModel:
Returns: Returns:
ResponseModel: A model containing the response data for the archived files. ResponseModel: A model containing the response data for the archived files.
""" """
... pass
@file_router.post( @file_router.post(
path='/compress', path='/compress',
@@ -323,7 +324,7 @@ def router_file_compress(id: str) -> ResponseModel:
Returns: Returns:
ResponseModel: A model containing the response data for the file compression task. ResponseModel: A model containing the response data for the file compression task.
""" """
... pass
@file_router.post( @file_router.post(
path='/decompress', path='/decompress',
@@ -341,7 +342,7 @@ def router_file_decompress(id: str) -> ResponseModel:
Returns: Returns:
ResponseModel: A model containing the response data for the file extraction task. ResponseModel: A model containing the response data for the file extraction task.
""" """
... pass
@file_router.post( @file_router.post(
path='/relocate', path='/relocate',
@@ -359,7 +360,7 @@ def router_file_relocate(id: str) -> ResponseModel:
Returns: Returns:
ResponseModel: A model containing the response data for the file relocation task. ResponseModel: A model containing the response data for the file relocation task.
""" """
... pass
@file_router.get( @file_router.get(
path='/search/{type}/{keyword}', path='/search/{type}/{keyword}',
@@ -378,4 +379,4 @@ def router_file_search(type: str, keyword: str) -> ResponseModel:
Returns: Returns:
ResponseModel: A model containing the response data for the file search. ResponseModel: A model containing the response data for the file search.
""" """
... pass

View File

@@ -20,7 +20,7 @@ def router_object_delete() -> ResponseModel:
Returns: Returns:
ResponseModel: A model containing the response data for the object deletion. ResponseModel: A model containing the response data for the object deletion.
""" """
... pass
@object_router.patch( @object_router.patch(
path='/', path='/',
@@ -35,7 +35,7 @@ def router_object_move() -> ResponseModel:
Returns: Returns:
ResponseModel: A model containing the response data for the object move. ResponseModel: A model containing the response data for the object move.
""" """
... pass
@object_router.post( @object_router.post(
path='/copy', path='/copy',
@@ -50,7 +50,7 @@ def router_object_copy() -> ResponseModel:
Returns: Returns:
ResponseModel: A model containing the response data for the object copy. ResponseModel: A model containing the response data for the object copy.
""" """
... pass
@object_router.post( @object_router.post(
path='/rename', path='/rename',
@@ -65,7 +65,7 @@ def router_object_rename() -> ResponseModel:
Returns: Returns:
ResponseModel: A model containing the response data for the object rename. ResponseModel: A model containing the response data for the object rename.
""" """
... pass
@object_router.get( @object_router.get(
path='/property/{id}', path='/property/{id}',
@@ -83,4 +83,4 @@ def router_object_property(id: str) -> ResponseModel:
Returns: Returns:
ResponseModel: A model containing the response data for the object properties. ResponseModel: A model containing the response data for the object properties.
""" """
... pass

View File

@@ -23,7 +23,7 @@ def router_share_get(info: str, id: str) -> ResponseModel:
Returns: Returns:
dict: A dictionary containing shared content information. dict: A dictionary containing shared content information.
""" """
... pass
@share_router.put( @share_router.put(
path='/download/{id}', path='/download/{id}',
@@ -40,7 +40,7 @@ def router_share_download(id: str) -> ResponseModel:
Returns: Returns:
dict: A dictionary containing download session information. dict: A dictionary containing download session information.
""" """
... pass
@share_router.get( @share_router.get(
path='preview/{id}', path='preview/{id}',
@@ -57,7 +57,7 @@ def router_share_preview(id: str) -> ResponseModel:
Returns: Returns:
dict: A dictionary containing preview information. dict: A dictionary containing preview information.
""" """
... pass
@share_router.get( @share_router.get(
path='/doc/{id}', path='/doc/{id}',
@@ -74,7 +74,7 @@ def router_share_doc(id: str) -> ResponseModel:
Returns: Returns:
dict: A dictionary containing the document preview URL. dict: A dictionary containing the document preview URL.
""" """
... pass
@share_router.get( @share_router.get(
path='/content/{id}', path='/content/{id}',
@@ -91,7 +91,7 @@ def router_share_content(id: str) -> ResponseModel:
Returns: Returns:
str: The content of the text file. str: The content of the text file.
""" """
... pass
@share_router.get( @share_router.get(
path='/list/{id}/{path:path}', path='/list/{id}/{path:path}',
@@ -109,7 +109,7 @@ def router_share_list(id: str, path: str = '') -> ResponseModel:
Returns: Returns:
dict: A dictionary containing directory listing information. dict: A dictionary containing directory listing information.
""" """
... pass
@share_router.get( @share_router.get(
path='/search/{id}/{type}/{keywords}', path='/search/{id}/{type}/{keywords}',
@@ -128,7 +128,7 @@ def router_share_search(id: str, type: str, keywords: str) -> ResponseModel:
Returns: Returns:
dict: A dictionary containing search results. dict: A dictionary containing search results.
""" """
... pass
@share_router.post( @share_router.post(
path='/archive/{id}', path='/archive/{id}',
@@ -145,7 +145,7 @@ def router_share_archive(id: str) -> ResponseModel:
Returns: Returns:
dict: A dictionary containing archive download information. dict: A dictionary containing archive download information.
""" """
... pass
@share_router.get( @share_router.get(
path='/readme/{id}', path='/readme/{id}',
@@ -162,7 +162,7 @@ def router_share_readme(id: str) -> ResponseModel:
Returns: Returns:
str: The content of the README file. str: The content of the README file.
""" """
... pass
@share_router.get( @share_router.get(
path='/thumb/{id}/{file}', path='/thumb/{id}/{file}',
@@ -180,7 +180,7 @@ def router_share_thumb(id: str, file: str) -> ResponseModel:
Returns: Returns:
str: A Base64 encoded string of the thumbnail image. str: A Base64 encoded string of the thumbnail image.
""" """
... pass
@share_router.post( @share_router.post(
path='/report/{id}', path='/report/{id}',
@@ -197,7 +197,7 @@ def router_share_report(id: str) -> ResponseModel:
Returns: Returns:
dict: A dictionary containing report submission information. dict: A dictionary containing report submission information.
""" """
... pass
@share_router.get( @share_router.get(
path='/search', path='/search',
@@ -215,7 +215,7 @@ def router_share_search_public(keywords: str, type: str = 'all') -> ResponseMode
Returns: Returns:
dict: A dictionary containing search results for public shares. dict: A dictionary containing search results for public shares.
""" """
... pass
##################### #####################
# 需要登录的接口 # 需要登录的接口
@@ -234,7 +234,7 @@ def router_share_create() -> ResponseModel:
Returns: Returns:
ResponseModel: A model containing the response data for the new share creation. ResponseModel: A model containing the response data for the new share creation.
""" """
... pass
@share_router.get( @share_router.get(
path='/', path='/',
@@ -249,7 +249,7 @@ def router_share_list() -> ResponseModel:
Returns: Returns:
ResponseModel: A model containing the response data for the list of shares. ResponseModel: A model containing the response data for the list of shares.
""" """
... pass
@share_router.post( @share_router.post(
path='/save/{id}', path='/save/{id}',
@@ -267,7 +267,7 @@ def router_share_save(id: str) -> ResponseModel:
Returns: Returns:
ResponseModel: A model containing the response data for the saved share. ResponseModel: A model containing the response data for the saved share.
""" """
... pass
@share_router.patch( @share_router.patch(
path='/{id}', path='/{id}',
@@ -285,7 +285,7 @@ def router_share_update(id: str) -> ResponseModel:
Returns: Returns:
ResponseModel: A model containing the response data for the updated share. ResponseModel: A model containing the response data for the updated share.
""" """
... pass
@share_router.delete( @share_router.delete(
path='/{id}', path='/{id}',
@@ -303,4 +303,4 @@ def router_share_delete(id: str) -> ResponseModel:
Returns: Returns:
ResponseModel: A model containing the response data for the deleted share. ResponseModel: A model containing the response data for the deleted share.
""" """
... pass

View File

@@ -34,7 +34,7 @@ def router_site_captcha():
Returns: Returns:
str: A Base64 encoded string of the captcha image. str: A Base64 encoded string of the captcha image.
""" """
... pass
@site_router.get( @site_router.get(
path='/config', path='/config',

View File

@@ -44,7 +44,7 @@ def router_slave_post(data: str) -> ResponseModel:
Returns: Returns:
ResponseModel: A response model indicating success. ResponseModel: A response model indicating success.
""" """
... pass
@slave_router.get( @slave_router.get(
path='/get/{speed}/{path}/{name}', path='/get/{speed}/{path}/{name}',
@@ -62,7 +62,7 @@ def router_slave_download(speed: int, path: str, name: str) -> ResponseModel:
Returns: Returns:
ResponseModel: A response model containing download information. ResponseModel: A response model containing download information.
""" """
... pass
@slave_router.get( @slave_router.get(
path='/download/{sign}', path='/download/{sign}',
@@ -80,7 +80,7 @@ def router_slave_download_by_sign(sign: str) -> FileResponse:
Returns: Returns:
FileResponse: A response containing the file to be downloaded. FileResponse: A response containing the file to be downloaded.
""" """
... pass
@slave_router.get( @slave_router.get(
path='/source/{speed}/{path}/{name}', path='/source/{speed}/{path}/{name}',
@@ -100,7 +100,7 @@ def router_slave_source(speed: int, path: str, name: str) -> ResponseModel:
Returns: Returns:
ResponseModel: A response model containing the external link for the file. ResponseModel: A response model containing the external link for the file.
""" """
... pass
@slave_router.get( @slave_router.get(
path='/source/{sign}', path='/source/{sign}',
@@ -118,7 +118,7 @@ def router_slave_source_by_sign(sign: str) -> FileResponse:
Returns: Returns:
FileResponse: A response containing the file to be retrieved. FileResponse: A response containing the file to be retrieved.
""" """
... pass
@slave_router.get( @slave_router.get(
path='/thumb/{id}', path='/thumb/{id}',
@@ -136,7 +136,7 @@ def router_slave_thumb(id: str) -> ResponseModel:
Returns: Returns:
ResponseModel: A response model containing the Base64 encoded thumbnail image. ResponseModel: A response model containing the Base64 encoded thumbnail image.
""" """
... pass
@slave_router.delete( @slave_router.delete(
path='/delete', path='/delete',
@@ -154,7 +154,7 @@ def router_slave_delete(path: str) -> ResponseModel:
Returns: Returns:
ResponseModel: A response model indicating success or failure of the deletion. ResponseModel: A response model indicating success or failure of the deletion.
""" """
... pass
@slave_aria2_router.post( @slave_aria2_router.post(
path='/test', path='/test',
@@ -166,7 +166,7 @@ def router_slave_aria2_test() -> ResponseModel:
""" """
Test the connection to the Aria2 service from the slave. Test the connection to the Aria2 service from the slave.
""" """
... pass
@slave_aria2_router.get( @slave_aria2_router.get(
path='/get/{gid}', path='/get/{gid}',
@@ -184,7 +184,7 @@ def router_slave_aria2_get(gid: str = None) -> ResponseModel:
Returns: Returns:
ResponseModel: A response model containing the task information. ResponseModel: A response model containing the task information.
""" """
... pass
@slave_aria2_router.post( @slave_aria2_router.post(
path='/add', path='/add',
@@ -204,7 +204,7 @@ def router_slave_aria2_add(gid: str, url: str, options: dict = None) -> Response
Returns: Returns:
ResponseModel: A response model indicating success or failure of the task addition. ResponseModel: A response model indicating success or failure of the task addition.
""" """
... pass
@slave_aria2_router.delete( @slave_aria2_router.delete(
path='/remove/{gid}', path='/remove/{gid}',
@@ -222,4 +222,4 @@ def router_slave_aria2_remove(gid: str) -> ResponseModel:
Returns: Returns:
ResponseModel: A response model indicating success or failure of the task removal. ResponseModel: A response model indicating success or failure of the task removal.
""" """
... pass

View File

@@ -20,7 +20,7 @@ def router_tag_create_filter() -> ResponseModel:
Returns: Returns:
ResponseModel: A model containing the response data for the created tag. ResponseModel: A model containing the response data for the created tag.
""" """
... pass
@tag_router.post( @tag_router.post(
path='/link', path='/link',
@@ -35,7 +35,7 @@ def router_tag_create_link() -> ResponseModel:
Returns: Returns:
ResponseModel: A model containing the response data for the created tag. ResponseModel: A model containing the response data for the created tag.
""" """
... pass
@tag_router.delete( @tag_router.delete(
path='/{id}', path='/{id}',
@@ -53,4 +53,4 @@ def router_tag_delete(id: str) -> ResponseModel:
Returns: Returns:
ResponseModel: A model containing the response data for the deletion operation. ResponseModel: A model containing the response data for the deletion operation.
""" """
... pass

View File

@@ -25,7 +25,7 @@ def router_user_session() -> ResponseModel:
Returns: Returns:
dict: A dictionary containing user session information. dict: A dictionary containing user session information.
""" """
... pass
@user_router.post( @user_router.post(
path='/', path='/',
@@ -39,7 +39,7 @@ def router_user_register() -> ResponseModel:
Returns: Returns:
dict: A dictionary containing user registration information. dict: A dictionary containing user registration information.
""" """
... pass
@user_router.post( @user_router.post(
path='/2fa', path='/2fa',
@@ -53,7 +53,7 @@ def router_user_2fa() -> ResponseModel:
Returns: Returns:
dict: A dictionary containing two-factor authentication information. dict: A dictionary containing two-factor authentication information.
""" """
... pass
@user_router.post( @user_router.post(
path='/reset', path='/reset',
@@ -67,7 +67,7 @@ def router_user_reset() -> ResponseModel:
Returns: Returns:
dict: A dictionary containing information about the password reset email. dict: A dictionary containing information about the password reset email.
""" """
... pass
@user_router.patch( @user_router.patch(
path='/reset', path='/reset',
@@ -81,7 +81,7 @@ def router_user_reset_patch() -> ResponseModel:
Returns: Returns:
dict: A dictionary containing information about the password reset. dict: A dictionary containing information about the password reset.
""" """
... pass
@user_router.get( @user_router.get(
path='/qq', path='/qq',
@@ -95,7 +95,7 @@ def router_user_qq() -> ResponseModel:
Returns: Returns:
dict: A dictionary containing QQ login initialization information. dict: A dictionary containing QQ login initialization information.
""" """
... pass
@user_router.get( @user_router.get(
path='/activate/{id}', path='/activate/{id}',
@@ -112,7 +112,7 @@ def router_user_activate(id: str) -> ResponseModel:
Returns: Returns:
dict: A dictionary containing activation information. dict: A dictionary containing activation information.
""" """
... pass
@user_router.get( @user_router.get(
path='authn/{username}', path='authn/{username}',
@@ -129,7 +129,7 @@ def router_user_authn(username: str) -> ResponseModel:
Returns: Returns:
dict: A dictionary containing WebAuthn initialization information. dict: A dictionary containing WebAuthn initialization information.
""" """
... pass
@user_router.post( @user_router.post(
path='authn/finish/{username}', path='authn/finish/{username}',
@@ -146,7 +146,7 @@ def router_user_authn_finish(username: str) -> ResponseModel:
Returns: Returns:
dict: A dictionary containing WebAuthn login information. dict: A dictionary containing WebAuthn login information.
""" """
... pass
@user_router.get( @user_router.get(
path='/profile/{id}', path='/profile/{id}',
@@ -163,7 +163,7 @@ def router_user_profile(id: str) -> ResponseModel:
Returns: Returns:
dict: A dictionary containing user profile information. dict: A dictionary containing user profile information.
""" """
... pass
@user_router.get( @user_router.get(
path='/avatar/{id}/{size}', path='/avatar/{id}/{size}',
@@ -181,7 +181,7 @@ def router_user_avatar(id: str, size: int = 128) -> ResponseModel:
Returns: Returns:
str: A Base64 encoded string of the user avatar image. str: A Base64 encoded string of the user avatar image.
""" """
... pass
##################### #####################
# 需要登录的接口 # 需要登录的接口
@@ -200,7 +200,7 @@ def router_user_me() -> ResponseModel:
Returns: Returns:
dict: A dictionary containing user information. dict: A dictionary containing user information.
""" """
... pass
@user_router.get( @user_router.get(
path='/storage', path='/storage',
@@ -215,7 +215,7 @@ def router_user_storage() -> ResponseModel:
Returns: Returns:
dict: A dictionary containing user storage information. dict: A dictionary containing user storage information.
""" """
... pass
@user_router.put( @user_router.put(
path='/authn/start', path='/authn/start',
@@ -230,7 +230,7 @@ def router_user_authn_start() -> ResponseModel:
Returns: Returns:
dict: A dictionary containing WebAuthn initialization information. dict: A dictionary containing WebAuthn initialization information.
""" """
... pass
@user_router.put( @user_router.put(
path='/authn/finish', path='/authn/finish',
@@ -245,7 +245,7 @@ def router_user_authn_finish() -> ResponseModel:
Returns: Returns:
dict: A dictionary containing WebAuthn login information. dict: A dictionary containing WebAuthn login information.
""" """
... pass
@user_settings_router.get( @user_settings_router.get(
path='/policies', path='/policies',
@@ -259,7 +259,7 @@ def router_user_settings_policies() -> ResponseModel:
Returns: Returns:
dict: A dictionary containing available storage policies for the user. dict: A dictionary containing available storage policies for the user.
""" """
... pass
@user_settings_router.get( @user_settings_router.get(
path='/nodes', path='/nodes',
@@ -274,7 +274,7 @@ def router_user_settings_nodes() -> ResponseModel:
Returns: Returns:
dict: A dictionary containing available nodes for the user. dict: A dictionary containing available nodes for the user.
""" """
... pass
@user_settings_router.get( @user_settings_router.get(
path='/tasks', path='/tasks',
@@ -289,7 +289,7 @@ def router_user_settings_tasks() -> ResponseModel:
Returns: Returns:
dict: A dictionary containing the user's task queue information. dict: A dictionary containing the user's task queue information.
""" """
... pass
@user_settings_router.get( @user_settings_router.get(
path='/', path='/',
@@ -304,7 +304,7 @@ def router_user_settings() -> ResponseModel:
Returns: Returns:
dict: A dictionary containing the user's current settings. dict: A dictionary containing the user's current settings.
""" """
... pass
@user_settings_router.post( @user_settings_router.post(
path='/avatar', path='/avatar',
@@ -319,7 +319,7 @@ def router_user_settings_avatar() -> ResponseModel:
Returns: Returns:
dict: A dictionary containing the result of the avatar upload. dict: A dictionary containing the result of the avatar upload.
""" """
... pass
@user_settings_router.put( @user_settings_router.put(
path='/avatar', path='/avatar',
@@ -334,7 +334,7 @@ def router_user_settings_avatar_gravatar() -> ResponseModel:
Returns: Returns:
dict: A dictionary containing the result of setting the Gravatar avatar. dict: A dictionary containing the result of setting the Gravatar avatar.
""" """
... pass
@user_settings_router.patch( @user_settings_router.patch(
path='/{option}', path='/{option}',
@@ -352,7 +352,7 @@ def router_user_settings_patch(option: str) -> ResponseModel:
Returns: Returns:
dict: A dictionary containing the result of the settings update. dict: A dictionary containing the result of the settings update.
""" """
... pass
@user_settings_router.get( @user_settings_router.get(
path='/2fa', path='/2fa',
@@ -367,4 +367,4 @@ def router_user_settings_2fa() -> ResponseModel:
Returns: Returns:
dict: A dictionary containing two-factor authentication setup information. dict: A dictionary containing two-factor authentication setup information.
""" """
... pass

View File

@@ -20,7 +20,7 @@ def router_vas_pack() -> ResponseModel:
Returns: Returns:
ResponseModel: A model containing the response data for storage packs and quotas. ResponseModel: A model containing the response data for storage packs and quotas.
""" """
... pass
@vas_router.get( @vas_router.get(
path='/product', path='/product',
@@ -35,7 +35,7 @@ def router_vas_product() -> ResponseModel:
Returns: Returns:
ResponseModel: A model containing the response data for products and payment information. ResponseModel: A model containing the response data for products and payment information.
""" """
... pass
@vas_router.post( @vas_router.post(
path='/order', path='/order',
@@ -50,7 +50,7 @@ def router_vas_order() -> ResponseModel:
Returns: Returns:
ResponseModel: A model containing the response data for the created order. ResponseModel: A model containing the response data for the created order.
""" """
... pass
@vas_router.get( @vas_router.get(
path='/order/{id}', path='/order/{id}',
@@ -68,7 +68,7 @@ def router_vas_order_get(id: str) -> ResponseModel:
Returns: Returns:
ResponseModel: A model containing the response data for the specified order. ResponseModel: A model containing the response data for the specified order.
""" """
... pass
@vas_router.get( @vas_router.get(
path='/redeem', path='/redeem',
@@ -86,7 +86,7 @@ def router_vas_redeem(code: str) -> ResponseModel:
Returns: Returns:
ResponseModel: A model containing the response data for the specified redemption code. ResponseModel: A model containing the response data for the specified redemption code.
""" """
... pass
@vas_router.post( @vas_router.post(
path='/redeem', path='/redeem',
@@ -101,4 +101,4 @@ def router_vas_redeem_post() -> ResponseModel:
Returns: Returns:
ResponseModel: A model containing the response data for the redeemed code. ResponseModel: A model containing the response data for the redeemed code.
""" """
... pass

View File

@@ -21,7 +21,7 @@ def router_webdav_accounts() -> ResponseModel:
Returns: Returns:
ResponseModel: A model containing the response data for the account information. ResponseModel: A model containing the response data for the account information.
""" """
... pass
@webdav_router.post( @webdav_router.post(
path='/accounts', path='/accounts',
@@ -36,7 +36,7 @@ def router_webdav_create_account() -> ResponseModel:
Returns: Returns:
ResponseModel: A model containing the response data for the created account. ResponseModel: A model containing the response data for the created account.
""" """
... pass
@webdav_router.delete( @webdav_router.delete(
path='/accounts/{id}', path='/accounts/{id}',
@@ -54,7 +54,7 @@ def router_webdav_delete_account(id: str) -> ResponseModel:
Returns: Returns:
ResponseModel: A model containing the response data for the deletion operation. ResponseModel: A model containing the response data for the deletion operation.
""" """
... pass
@webdav_router.post( @webdav_router.post(
path='/mount', path='/mount',
@@ -69,7 +69,7 @@ def router_webdav_create_mount() -> ResponseModel:
Returns: Returns:
ResponseModel: A model containing the response data for the created mount point. ResponseModel: A model containing the response data for the created mount point.
""" """
... pass
@webdav_router.delete( @webdav_router.delete(
path='/mount/{id}', path='/mount/{id}',
@@ -87,7 +87,7 @@ def router_webdav_delete_mount(id: str) -> ResponseModel:
Returns: Returns:
ResponseModel: A model containing the response data for the deletion operation. ResponseModel: A model containing the response data for the deletion operation.
""" """
... pass
@webdav_router.patch( @webdav_router.patch(
path='accounts/{id}', path='accounts/{id}',
@@ -105,4 +105,4 @@ def router_webdav_update_account(id: str) -> ResponseModel:
Returns: Returns:
ResponseModel: A model containing the response data for the updated account. ResponseModel: A model containing the response data for the updated account.
""" """
... pass

15
service/user/login.py Normal file
View File

@@ -0,0 +1,15 @@
from models.setting import Setting
async def login(
username: str,
password: str
):
"""
"""
isCaptchaRequired = await Setting.get(type='auth', name='login_captcha', type=bool)
captchaType = await Setting.get(type='auth', name='captcha_type', type=str)
# [TODO] 验证码校验

View File

@@ -26,51 +26,3 @@ async def test_initialize_db():
await database.init_db(url='sqlite:///:memory:') await database.init_db(url='sqlite:///:memory:')
await migration.init_default_settings() await migration.init_default_settings()
@pytest.mark.asyncio
async def test_add_settings():
"""测试数据库的增删改查"""
from models import database
from models.setting import Setting
await database.init_db(url='sqlite:///:memory:')
# 测试增 Create
await Setting.add(
type='example_type',
name='example_name',
value='example_value')
# 测试查 Read
setting = await Setting.get(
type='example_type',
name='example_name')
assert setting is not None, "设置项应该存在"
assert setting.value == 'example_value', "设置值不匹配"
# 测试改 Update
await Setting.set(
type='example_type',
name='example_name',
value='updated_value')
after_update_setting = await Setting.get(
type='example_type',
name='example_name'
)
assert after_update_setting is not None, "设置项应该存在"
assert after_update_setting.value == 'updated_value', "更新后的设置值不匹配"
# 测试删 Delete
await Setting.delete(
type='example_type',
name='example_name')
after_delete_setting = await Setting.get(
type='example_type',
name='example_name'
)
assert after_delete_setting is None, "设置项应该被删除"

49
tests/test_db_settings.py Normal file
View File

@@ -0,0 +1,49 @@
import pytest
@pytest.mark.asyncio
async def test_settings_curd():
"""测试数据库的增删改查"""
from models import database
from models.setting import Setting
await database.init_db(url='sqlite:///:memory:')
# 测试增 Create
await Setting.add(
type='example_type',
name='example_name',
value='example_value')
# 测试查 Read
setting = await Setting.get(
type='example_type',
name='example_name')
assert setting is not None, "设置项应该存在"
assert setting == 'example_value', "设置值不匹配"
# 测试改 Update
await Setting.set(
type='example_type',
name='example_name',
value='updated_value')
after_update_setting = await Setting.get(
type='example_type',
name='example_name'
)
assert after_update_setting is not None, "设置项应该存在"
assert after_update_setting == 'updated_value', "更新后的设置值不匹配"
# 测试删 Delete
await Setting.delete(
type='example_type',
name='example_name')
after_delete_setting = await Setting.get(
type='example_type',
name='example_name'
)
assert after_delete_setting is None, "设置项应该被删除"

29
tests/test_db_user.py Normal file
View File

@@ -0,0 +1,29 @@
import pytest
@pytest.mark.asyncio
async def test_user_curd():
"""测试数据库的增删改查"""
from models import database
from models.group import Group
from models.user import User
await database.init_db(url='sqlite:///:memory:')
# 新建一个测试用户组
test_group = Group(name='test_group')
created_group = await Group.create(test_group)
test_user = User(
email='test_user',
password='test_password',
group_id=created_group.id
)
# 测试增 Create
created_user = await User.create(test_user)
# 验证用户是否存在
assert created_user.id is not None
assert created_user.email == 'test_user'
assert created_user.password == 'test_password'
assert created_user.group_id == created_group.id