docs(private-api): add docs for private-api
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from . import avatar # noqa: F401
|
from . import avatar, oauth, username # noqa: F401
|
||||||
from .router import router as private_router
|
from .router import router as private_router
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
|
|||||||
@@ -16,13 +16,28 @@ from PIL import Image
|
|||||||
from sqlmodel.ext.asyncio.session import AsyncSession
|
from sqlmodel.ext.asyncio.session import AsyncSession
|
||||||
|
|
||||||
|
|
||||||
@router.post("/avatar/upload", tags=["avatar"])
|
@router.post(
|
||||||
|
"/avatar/upload",
|
||||||
|
name="上传头像",
|
||||||
|
)
|
||||||
async def upload_avatar(
|
async def upload_avatar(
|
||||||
file: str = Body(...),
|
file: str = Body(..., description="Base64 编码的图片数据"),
|
||||||
user_id: int = Body(...),
|
user_id: int = Body(..., description="用户 ID"),
|
||||||
storage: StorageService = Depends(get_storage_service),
|
storage: StorageService = Depends(get_storage_service),
|
||||||
session: AsyncSession = Depends(get_db),
|
session: AsyncSession = Depends(get_db),
|
||||||
):
|
):
|
||||||
|
"""上传用户头像
|
||||||
|
|
||||||
|
接收 Base64 编码的图片数据,验证图片格式和大小后存储到头像目录,并更新用户的头像 URL
|
||||||
|
|
||||||
|
限制条件:
|
||||||
|
- 支持的图片格式: PNG、JPEG、GIF
|
||||||
|
- 最大文件大小: 5MB
|
||||||
|
- 最大图片尺寸: 256x256 像素
|
||||||
|
|
||||||
|
返回:
|
||||||
|
- 头像 URL 和文件哈希值
|
||||||
|
"""
|
||||||
content = base64.b64decode(file)
|
content = base64.b64decode(file)
|
||||||
|
|
||||||
user = await session.get(User, user_id)
|
user = await session.get(User, user_id)
|
||||||
|
|||||||
@@ -13,12 +13,16 @@ from sqlmodel import select, text
|
|||||||
from sqlmodel.ext.asyncio.session import AsyncSession
|
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(
|
async def create_oauth_app(
|
||||||
name: str = Body(..., max_length=100),
|
name: str = Body(..., max_length=100, description="应用程序名称"),
|
||||||
description: str = Body(""),
|
description: str = Body("", description="应用程序描述"),
|
||||||
redirect_uris: list[str] = Body(...),
|
redirect_uris: list[str] = Body(..., description="允许的重定向 URI 列表"),
|
||||||
owner_id: int = Body(...),
|
owner_id: int = Body(..., description="应用程序所有者的用户 ID"),
|
||||||
session: AsyncSession = Depends(get_db),
|
session: AsyncSession = Depends(get_db),
|
||||||
):
|
):
|
||||||
result = await session.execute( # pyright: ignore[reportDeprecated]
|
result = await session.execute( # pyright: ignore[reportDeprecated]
|
||||||
@@ -48,8 +52,15 @@ async def create_oauth_app(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@router.get("/oauth-apps/{client_id}", tags=["OAuth"])
|
@router.get(
|
||||||
async def get_oauth_app(client_id: int, session: AsyncSession = Depends(get_db)):
|
"/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)
|
oauth_app = await session.get(OAuthClient, client_id)
|
||||||
if not oauth_app:
|
if not oauth_app:
|
||||||
raise HTTPException(status_code=404, detail="OAuth app not found")
|
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"])
|
@router.get(
|
||||||
async def get_user_oauth_apps(owner_id: int, session: AsyncSession = Depends(get_db)):
|
"/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(
|
oauth_apps = await session.exec(
|
||||||
select(OAuthClient).where(OAuthClient.owner_id == owner_id)
|
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(
|
async def delete_oauth_app(
|
||||||
client_id: int,
|
client_id: int,
|
||||||
session: AsyncSession = Depends(get_db),
|
session: AsyncSession = Depends(get_db),
|
||||||
@@ -96,12 +119,16 @@ async def delete_oauth_app(
|
|||||||
await session.commit()
|
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(
|
async def update_oauth_app(
|
||||||
client_id: int,
|
client_id: int,
|
||||||
name: str = Body(..., max_length=100),
|
name: str = Body(..., max_length=100, description="应用程序新名称"),
|
||||||
description: str = Body(""),
|
description: str = Body("", description="应用程序新描述"),
|
||||||
redirect_uris: list[str] = Body(...),
|
redirect_uris: list[str] = Body(..., description="新的重定向 URI 列表"),
|
||||||
session: AsyncSession = Depends(get_db),
|
session: AsyncSession = Depends(get_db),
|
||||||
):
|
):
|
||||||
oauth_client = await session.get(OAuthClient, client_id)
|
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(
|
async def refresh_secret(
|
||||||
client_id: int,
|
client_id: int,
|
||||||
session: AsyncSession = Depends(get_db),
|
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(
|
async def generate_oauth_code(
|
||||||
client_id: int,
|
client_id: int,
|
||||||
user_id: int = Body(...),
|
user_id: int = Body(..., description="授权用户的 ID"),
|
||||||
redirect_uri: str = Body(...),
|
redirect_uri: str = Body(..., description="授权后重定向的 URI"),
|
||||||
scopes: list[str] = Body(...),
|
scopes: list[str] = Body(..., description="请求的权限范围列表"),
|
||||||
session: AsyncSession = Depends(get_db),
|
session: AsyncSession = Depends(get_db),
|
||||||
redis: Redis = Depends(get_redis),
|
redis: Redis = Depends(get_redis),
|
||||||
):
|
):
|
||||||
@@ -172,3 +207,9 @@ async def generate_oauth_code(
|
|||||||
mapping={"user_id": user_id, "scopes": ",".join(scopes)},
|
mapping={"user_id": user_id, "scopes": ",".join(scopes)},
|
||||||
)
|
)
|
||||||
await redis.expire(f"oauth:code:{client_id}:{code}", 300)
|
await redis.expire(f"oauth:code:{client_id}:{code}", 300)
|
||||||
|
|
||||||
|
return {
|
||||||
|
"code": code,
|
||||||
|
"redirect_uri": redirect_uri,
|
||||||
|
"expires_in": 300,
|
||||||
|
}
|
||||||
|
|||||||
@@ -35,5 +35,6 @@ async def verify_signature(
|
|||||||
router = APIRouter(
|
router = APIRouter(
|
||||||
prefix="/api/private",
|
prefix="/api/private",
|
||||||
dependencies=[Depends(verify_signature)],
|
dependencies=[Depends(verify_signature)],
|
||||||
include_in_schema=False,
|
include_in_schema=settings.debug,
|
||||||
|
tags=["私有 API"],
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -10,13 +10,27 @@ from sqlmodel import select
|
|||||||
from sqlmodel.ext.asyncio.session import AsyncSession
|
from sqlmodel.ext.asyncio.session import AsyncSession
|
||||||
|
|
||||||
|
|
||||||
@router.post("/rename", tags=["rename"])
|
@router.post(
|
||||||
|
"/rename",
|
||||||
|
name="修改用户名",
|
||||||
|
)
|
||||||
async def user_rename(
|
async def user_rename(
|
||||||
user_id: int = Body(...),
|
user_id: int = Body(..., description="要修改名称的用户 ID"),
|
||||||
new_name: str = Body(...),
|
new_name: str = Body(..., description="新的用户名"),
|
||||||
session: AsyncSession = Depends(get_db),
|
session: AsyncSession = Depends(get_db),
|
||||||
# currentUser: User = Depends(get_current_user)
|
# currentUser: User = Depends(get_current_user)
|
||||||
):
|
):
|
||||||
|
"""修改用户名
|
||||||
|
|
||||||
|
为指定用户修改用户名,并将原用户名添加到历史用户名列表中
|
||||||
|
|
||||||
|
错误情况:
|
||||||
|
- 404: 找不到指定用户
|
||||||
|
- 409: 新用户名已被占用
|
||||||
|
|
||||||
|
返回:
|
||||||
|
- 成功: None
|
||||||
|
"""
|
||||||
current_user = (await session.exec(select(User).where(User.id == user_id))).first()
|
current_user = (await session.exec(select(User).where(User.id == user_id))).first()
|
||||||
if current_user is None:
|
if current_user is None:
|
||||||
raise HTTPException(404, "User not found")
|
raise HTTPException(404, "User not found")
|
||||||
|
|||||||
9
main.py
9
main.py
@@ -39,11 +39,18 @@ async def lifespan(app: FastAPI):
|
|||||||
await redis_client.aclose()
|
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(
|
app = FastAPI(
|
||||||
title="osu! API 模拟服务器",
|
title="osu! API 模拟服务器",
|
||||||
version="1.0.0",
|
version="1.0.0",
|
||||||
lifespan=lifespan,
|
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)
|
app.include_router(api_v2_router)
|
||||||
|
|||||||
Reference in New Issue
Block a user