docs(private-api): add docs for private-api

This commit is contained in:
MingxuanGame
2025-08-12 10:21:26 +00:00
parent b09960af4c
commit 147509a93c
6 changed files with 106 additions and 28 deletions

View File

@@ -1,6 +1,6 @@
from __future__ import annotations
from . import avatar # noqa: F401
from . import avatar, oauth, username # noqa: F401
from .router import router as private_router
__all__ = [

View File

@@ -16,13 +16,28 @@ from PIL import Image
from sqlmodel.ext.asyncio.session import AsyncSession
@router.post("/avatar/upload", tags=["avatar"])
@router.post(
"/avatar/upload",
name="上传头像",
)
async def upload_avatar(
file: str = Body(...),
user_id: int = Body(...),
file: str = Body(..., description="Base64 编码的图片数据"),
user_id: int = Body(..., description="用户 ID"),
storage: StorageService = Depends(get_storage_service),
session: AsyncSession = Depends(get_db),
):
"""上传用户头像
接收 Base64 编码的图片数据,验证图片格式和大小后存储到头像目录,并更新用户的头像 URL
限制条件:
- 支持的图片格式: PNG、JPEG、GIF
- 最大文件大小: 5MB
- 最大图片尺寸: 256x256 像素
返回:
- 头像 URL 和文件哈希值
"""
content = base64.b64decode(file)
user = await session.get(User, user_id)

View File

@@ -13,12 +13,16 @@ from sqlmodel import select, text
from sqlmodel.ext.asyncio.session import AsyncSession
@router.post("/oauth-app/create", tags=["OAuth"])
@router.post(
"/oauth-app/create",
name="创建 OAuth 应用",
description="创建一个新的 OAuth 应用程序,并生成客户端 ID 和密钥",
)
async def create_oauth_app(
name: str = Body(..., max_length=100),
description: str = Body(""),
redirect_uris: list[str] = Body(...),
owner_id: int = Body(...),
name: str = Body(..., max_length=100, description="应用程序名称"),
description: str = Body("", description="应用程序描述"),
redirect_uris: list[str] = Body(..., description="允许的重定向 URI 列表"),
owner_id: int = Body(..., description="应用程序所有者的用户 ID"),
session: AsyncSession = Depends(get_db),
):
result = await session.execute( # pyright: ignore[reportDeprecated]
@@ -48,8 +52,15 @@ async def create_oauth_app(
}
@router.get("/oauth-apps/{client_id}", tags=["OAuth"])
async def get_oauth_app(client_id: int, session: AsyncSession = Depends(get_db)):
@router.get(
"/oauth-apps/{client_id}",
name="获取 OAuth 应用信息",
description="通过客户端 ID 获取 OAuth 应用的详细信息",
)
async def get_oauth_app(
client_id: int,
session: AsyncSession = Depends(get_db),
):
oauth_app = await session.get(OAuthClient, client_id)
if not oauth_app:
raise HTTPException(status_code=404, detail="OAuth app not found")
@@ -61,8 +72,15 @@ async def get_oauth_app(client_id: int, session: AsyncSession = Depends(get_db))
}
@router.get("/oauth-apps/user/{owner_id}", tags=["OAuth"])
async def get_user_oauth_apps(owner_id: int, session: AsyncSession = Depends(get_db)):
@router.get(
"/oauth-apps/user/{owner_id}",
name="获取用户的 OAuth 应用列表",
description="获取指定用户创建的所有 OAuth 应用程序",
)
async def get_user_oauth_apps(
owner_id: int,
session: AsyncSession = Depends(get_db),
):
oauth_apps = await session.exec(
select(OAuthClient).where(OAuthClient.owner_id == owner_id)
)
@@ -77,7 +95,12 @@ async def get_user_oauth_apps(owner_id: int, session: AsyncSession = Depends(get
]
@router.delete("/oauth-app/{client_id}", tags=["OAuth"], status_code=204)
@router.delete(
"/oauth-app/{client_id}",
status_code=204,
name="删除 OAuth 应用",
description="删除指定的 OAuth 应用程序及其关联的所有令牌",
)
async def delete_oauth_app(
client_id: int,
session: AsyncSession = Depends(get_db),
@@ -96,12 +119,16 @@ async def delete_oauth_app(
await session.commit()
@router.patch("/oauth-app/{client_id}", tags=["OAuth"])
@router.patch(
"/oauth-app/{client_id}",
name="更新 OAuth 应用",
description="更新指定 OAuth 应用的名称、描述和重定向 URI",
)
async def update_oauth_app(
client_id: int,
name: str = Body(..., max_length=100),
description: str = Body(""),
redirect_uris: list[str] = Body(...),
name: str = Body(..., max_length=100, description="应用程序新名称"),
description: str = Body("", description="应用程序新描述"),
redirect_uris: list[str] = Body(..., description="新的重定向 URI 列表"),
session: AsyncSession = Depends(get_db),
):
oauth_client = await session.get(OAuthClient, client_id)
@@ -122,7 +149,11 @@ async def update_oauth_app(
}
@router.post("/oauth-app/{client_id}/refresh", tags=["OAuth"])
@router.post(
"/oauth-app/{client_id}/refresh",
name="刷新 OAuth 密钥",
description="为指定的 OAuth 应用生成新的客户端密钥,并使所有现有的令牌失效",
)
async def refresh_secret(
client_id: int,
session: AsyncSession = Depends(get_db),
@@ -148,12 +179,16 @@ async def refresh_secret(
}
@router.post("/oauth-app/{client_id}/code")
@router.post(
"/oauth-app/{client_id}/code",
name="生成 OAuth 授权码",
description="为特定用户和 OAuth 应用生成授权码,用于授权码授权流程",
)
async def generate_oauth_code(
client_id: int,
user_id: int = Body(...),
redirect_uri: str = Body(...),
scopes: list[str] = Body(...),
user_id: int = Body(..., description="授权用户的 ID"),
redirect_uri: str = Body(..., description="授权后重定向的 URI"),
scopes: list[str] = Body(..., description="请求的权限范围列表"),
session: AsyncSession = Depends(get_db),
redis: Redis = Depends(get_redis),
):
@@ -172,3 +207,9 @@ async def generate_oauth_code(
mapping={"user_id": user_id, "scopes": ",".join(scopes)},
)
await redis.expire(f"oauth:code:{client_id}:{code}", 300)
return {
"code": code,
"redirect_uri": redirect_uri,
"expires_in": 300,
}

View File

@@ -35,5 +35,6 @@ async def verify_signature(
router = APIRouter(
prefix="/api/private",
dependencies=[Depends(verify_signature)],
include_in_schema=False,
include_in_schema=settings.debug,
tags=["私有 API"],
)

View File

@@ -10,13 +10,27 @@ from sqlmodel import select
from sqlmodel.ext.asyncio.session import AsyncSession
@router.post("/rename", tags=["rename"])
@router.post(
"/rename",
name="修改用户名",
)
async def user_rename(
user_id: int = Body(...),
new_name: str = Body(...),
user_id: int = Body(..., description="要修改名称的用户 ID"),
new_name: str = Body(..., description="新的用户名"),
session: AsyncSession = Depends(get_db),
# currentUser: User = Depends(get_current_user)
):
"""修改用户名
为指定用户修改用户名,并将原用户名添加到历史用户名列表中
错误情况:
- 404: 找不到指定用户
- 409: 新用户名已被占用
返回:
- 成功: None
"""
current_user = (await session.exec(select(User).where(User.id == user_id))).first()
if current_user is None:
raise HTTPException(404, "User not found")

View File

@@ -39,11 +39,18 @@ async def lifespan(app: FastAPI):
await redis_client.aclose()
desc = (
"osu! API 模拟服务器,支持 osu! API v2 和 osu!lazer 的绝大部分功能。\n\n"
"官方文档:[osu!web 文档](https://osu.ppy.sh/docs/index.html)"
)
if settings.debug:
desc += "\n\n私有 API 签名机制:[GitHub](https://github.com/GooGuTeam/osu_lazer_api/wiki/%E7%A7%81%E6%9C%89-API-%E7%AD%BE%E5%90%8D%E9%AA%8C%E8%AF%81%E6%9C%BA%E5%88%B6)"
app = FastAPI(
title="osu! API 模拟服务器",
version="1.0.0",
lifespan=lifespan,
summary="osu! API 模拟服务器,支持 osu! API v2 和 osu!lazer 的绝大部分功能。官方文档https://osu.ppy.sh/docs/index.html",
description=desc,
)
app.include_router(api_v2_router)