♻️ refactor api code

This commit is contained in:
felinae98 2022-12-23 21:47:28 +08:00
parent 410cac1af3
commit 0ebbdd2c0d
5 changed files with 189 additions and 193 deletions

View File

@ -30,15 +30,15 @@ export const login = createAsyncThunk(
);
const setLoginReducer: CaseReducer<AuthStatus, PayloadAction<TokenResp>> = (state, action) => {
if (action.payload.status === 200) {
state.login = true;
state.id = action.payload.id;
state.userType = action.payload.type;
state.token = action.payload.token;
} else {
state.login = false;
state.failed = true;
}
state.login = true;
state.id = action.payload.id;
state.userType = action.payload.type;
state.token = action.payload.token;
};
export const setLoginFailedReducer: CaseReducer<AuthStatus> = (state) => {
state.login = false;
state.failed = true;
};
export const setLogoutReducer: CaseReducer<AuthStatus> = (state) => {

View File

@ -1,5 +1,4 @@
export interface TokenResp {
status: number;
token: string;
type: string;
id: number;
@ -44,7 +43,7 @@ export interface SubscribeResp {
}
export interface StatusResp {
status: number;
ok: boolean;
msg: string;
}

View File

@ -1,9 +1,9 @@
import os
from dataclasses import dataclass
from pathlib import Path
from typing import Union
import socketio
from fastapi.applications import FastAPI
from fastapi.staticfiles import StaticFiles
from nonebot import get_driver, on_command
from nonebot.adapters.onebot.v11 import Bot
@ -14,30 +14,9 @@ from nonebot.rule import to_me
from nonebot.typing import T_State
from ..plugin_config import plugin_config
from ..types import WeightConfig
from .api import (
add_group_sub,
auth,
del_group_sub,
get_global_conf,
get_subs_info,
get_target_name,
get_weight_config,
test,
update_group_sub,
update_weigth_config,
)
from .jwt import load_jwt
from .api import router as api_router
from .token_manager import token_manager as tm
URL_BASE = "/bison/"
GLOBAL_CONF_URL = f"{URL_BASE}api/global_conf"
AUTH_URL = f"{URL_BASE}api/auth"
SUBSCRIBE_URL = f"{URL_BASE}api/subs"
GET_TARGET_NAME_URL = f"{URL_BASE}api/target_name"
WEIGHT_URL = f"{URL_BASE}api/weight"
TEST_URL = f"{URL_BASE}test"
STATIC_PATH = (Path(__file__).parent / "dist").resolve()
sio = socketio.AsyncServer(async_mode="asgi", cors_allowed_origins="*")
@ -57,90 +36,18 @@ class SinglePageApplication(StaticFiles):
def register_router_fastapi(driver: Driver, socketio):
from fastapi import HTTPException, status
from fastapi.param_functions import Depends
from fastapi.security import OAuth2PasswordBearer
oath_scheme = OAuth2PasswordBearer(tokenUrl="token")
async def get_jwt_obj(token: str = Depends(oath_scheme)):
obj = load_jwt(token)
if not obj:
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED)
return obj
async def check_group_permission(
groupNumber: int, token_obj: dict = Depends(get_jwt_obj)
):
groups = token_obj["groups"]
for group in groups:
if int(groupNumber) == group["id"]:
return
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN)
async def check_is_superuser(token_obj: dict = Depends(get_jwt_obj)):
if token_obj.get("type") != "admin":
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN)
@dataclass
class AddSubscribeReq:
platformName: str
target: str
targetName: str
cats: list[int]
tags: list[str]
static_path = STATIC_PATH
nonebot_app = FastAPI(
title="nonebot-bison",
description="nonebot-bison webui and api",
)
nonebot_app.include_router(api_router)
nonebot_app.mount(
"/", SinglePageApplication(directory=static_path), name="bison-frontend"
)
app = driver.server_app
static_path = STATIC_PATH
app.get(TEST_URL)(test)
app.get(GLOBAL_CONF_URL)(get_global_conf)
app.get(AUTH_URL)(auth)
@app.get(SUBSCRIBE_URL)
async def subs(jwt_obj: dict = Depends(get_jwt_obj)):
return await get_subs_info(jwt_obj)
@app.get(GET_TARGET_NAME_URL)
async def _get_target_name(
platformName: str, target: str, jwt_obj: dict = Depends(get_jwt_obj)
):
return await get_target_name(platformName, target, jwt_obj)
@app.post(SUBSCRIBE_URL, dependencies=[Depends(check_group_permission)])
async def _add_group_subs(groupNumber: int, req: AddSubscribeReq):
return await add_group_sub(
group_number=groupNumber,
platform_name=req.platformName,
target=req.target,
target_name=req.targetName,
cats=req.cats,
tags=req.tags,
)
@app.patch(SUBSCRIBE_URL, dependencies=[Depends(check_group_permission)])
async def _update_group_subs(groupNumber: int, req: AddSubscribeReq):
return await update_group_sub(
group_number=groupNumber,
platform_name=req.platformName,
target=req.target,
target_name=req.targetName,
cats=req.cats,
tags=req.tags,
)
@app.delete(SUBSCRIBE_URL, dependencies=[Depends(check_group_permission)])
async def _del_group_subs(groupNumber: int, target: str, platformName: str):
return await del_group_sub(groupNumber, platformName, target)
@app.get(WEIGHT_URL, dependencies=[Depends(check_is_superuser)])
async def _get_weight_config():
return await get_weight_config()
@app.put(WEIGHT_URL, dependencies=[Depends(check_is_superuser)])
async def _update_weight_config(platform_name: str, target: str, req: WeightConfig):
return await update_weigth_config(platform_name, target, req)
app.mount(URL_BASE, SinglePageApplication(directory=static_path), name="bison")
app.mount("/bison", nonebot_app, "nonebot-bison")
def init():
@ -156,7 +63,7 @@ def init():
host = "localhost"
logger.opt(colors=True).info(
f"Nonebot test frontend will be running at: "
f"<b><u>http://{host}:{port}{URL_BASE}</u></b>"
f"<b><u>http://{host}:{port}/bison</u></b>"
)

View File

@ -1,4 +1,9 @@
import nonebot
from fastapi import status
from fastapi.exceptions import HTTPException
from fastapi.param_functions import Depends
from fastapi.routing import APIRouter
from fastapi.security.oauth2 import OAuth2PasswordBearer
from nonebot.adapters.onebot.v11.bot import Bot
from ..apis import check_sub_target
@ -12,25 +17,58 @@ from ..config.db_config import SubscribeDupException
from ..platform import platform_manager
from ..types import Target as T_Target
from ..types import WeightConfig
from .jwt import pack_jwt
from .jwt import load_jwt, pack_jwt
from .token_manager import token_manager
from .types import (
AddSubscribeReq,
GlobalConf,
PlatformConfig,
StatusResp,
SubscribeConfig,
SubscribeGroupDetail,
SubscribeResp,
TokenResp,
)
router = APIRouter(prefix="/api", tags=["api"])
oath_scheme = OAuth2PasswordBearer(tokenUrl="token")
async def test():
return {"status": 200, "text": "test"}
async def get_jwt_obj(token: str = Depends(oath_scheme)):
obj = load_jwt(token)
if not obj:
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED)
return obj
async def get_global_conf():
async def check_group_permission(
groupNumber: int, token_obj: dict = Depends(get_jwt_obj)
):
groups = token_obj["groups"]
for group in groups:
if int(groupNumber) == group["id"]:
return
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN)
async def check_is_superuser(token_obj: dict = Depends(get_jwt_obj)):
if token_obj.get("type") != "admin":
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN)
@router.get("/global_conf")
async def get_global_conf() -> GlobalConf:
res = {}
for platform_name, platform in platform_manager.items():
res[platform_name] = {
"platformName": platform_name,
"categories": platform.categories,
"enabledTag": platform.enable_tag,
"name": platform.name,
"hasTarget": getattr(platform, "has_target"),
}
return {"platformConf": res}
res[platform_name] = PlatformConfig(
platformName=platform_name,
categories=platform.categories,
enabledTag=platform.enable_tag,
name=platform.name,
hasTarget=getattr(platform, "has_target"),
)
return GlobalConf(platformConf=res)
async def get_admin_groups(qq: int):
@ -46,7 +84,8 @@ async def get_admin_groups(qq: int):
return res
async def auth(token: str):
@router.get("/auth")
async def auth(token: str) -> TokenResp:
if qq_tuple := token_manager.get_user(token):
qq, nickname = qq_tuple
bot = nonebot.get_bot()
@ -66,113 +105,112 @@ async def auth(token: str):
)
),
}
ret_obj = {
"type": "admin",
"name": nickname,
"id": qq,
"token": pack_jwt(jwt_obj),
}
return {"status": 200, **ret_obj}
ret_obj = TokenResp(
type="admin",
name=nickname,
id=qq,
token=pack_jwt(jwt_obj),
)
return ret_obj
if admin_groups := await get_admin_groups(int(qq)):
jwt_obj = {"id": str(qq), "type": "user", "groups": admin_groups}
ret_obj = {
"type": "user",
"name": nickname,
"id": qq,
"token": pack_jwt(jwt_obj),
}
return {"status": 200, **ret_obj}
ret_obj = TokenResp(
type="user",
name=nickname,
id=qq,
token=pack_jwt(jwt_obj),
)
return ret_obj
else:
return {"status": 400, "type": "", "name": "", "id": 0, "token": ""}
raise HTTPException(400, "permission denied")
else:
return {"status": 400, "type": "", "name": "", "id": 0, "token": ""}
raise HTTPException(400, "code error")
async def get_subs_info(jwt_obj: dict):
@router.get("/subs")
async def get_subs_info(jwt_obj: dict = Depends(get_jwt_obj)) -> SubscribeResp:
groups = jwt_obj["groups"]
res = {}
res: SubscribeResp = {}
for group in groups:
group_id = group["id"]
raw_subs = await config.list_subscribe(group_id, "group")
subs = list(
map(
lambda sub: {
"platformName": sub.target.platform_name,
"targetName": sub.target.target_name,
"cats": sub.categories,
"tags": sub.tags,
"target": sub.target.target,
},
lambda sub: SubscribeConfig(
platformName=sub.target.platform_name,
targetName=sub.target.target_name,
cats=sub.categories, # type: ignore
tags=sub.tags, # type: ignore
target=sub.target.target,
),
raw_subs,
)
)
res[group_id] = {"name": group["name"], "subscribes": subs}
res[group_id] = SubscribeGroupDetail(name=group["name"], subscribes=subs)
return res
async def get_target_name(platform_name: str, target: str, jwt_obj: dict):
return {"targetName": await check_sub_target(platform_name, target)}
@router.get("/target_name", dependencies=[Depends(get_jwt_obj)])
async def get_target_name(platformName: str, target: str):
return {"targetName": await check_sub_target(platformName, T_Target(target))}
async def add_group_sub(
group_number: int,
platform_name: str,
target: str,
target_name: str,
cats: list[int],
tags: list[str],
):
@router.post("/subs", dependencies=[Depends(check_group_permission)])
async def add_group_sub(groupNumber: int, req: AddSubscribeReq) -> StatusResp:
try:
await config.add_subscribe(
int(group_number),
int(groupNumber),
"group",
T_Target(target),
target_name,
platform_name,
cats,
tags,
T_Target(req.target),
req.targetName,
req.platformName,
req.cats,
req.tags,
)
return {"status": 200, "msg": ""}
return StatusResp(ok=True, msg="")
except SubscribeDupException:
return {"status": 403, "msg": ""}
raise HTTPException(status.HTTP_400_BAD_REQUEST, "subscribe duplicated")
async def del_group_sub(group_number: int, platform_name: str, target: str):
@router.delete("/subs", dependencies=[Depends(check_group_permission)])
async def del_group_sub(groupNumber: int, platformName: str, target: str):
try:
await config.del_subscribe(int(group_number), "group", target, platform_name)
await config.del_subscribe(int(groupNumber), "group", target, platformName)
except (NoSuchUserException, NoSuchSubscribeException):
return {"status": 400, "msg": "删除错误"}
return {"status": 200, "msg": ""}
raise HTTPException(status.HTTP_400_BAD_REQUEST, "no such user or subscribe")
return StatusResp(ok=True, msg="")
async def update_group_sub(
group_number: int,
platform_name: str,
target: str,
target_name: str,
cats: list[int],
tags: list[str],
):
@router.patch("/subs", dependencies=[Depends(check_group_permission)])
async def update_group_sub(groupNumber: int, req: AddSubscribeReq):
try:
await config.update_subscribe(
int(group_number), "group", target, target_name, platform_name, cats, tags
int(groupNumber),
"group",
req.target,
req.targetName,
req.platformName,
req.cats,
req.tags,
)
except (NoSuchUserException, NoSuchSubscribeException):
return {"status": 400, "msg": "更新错误"}
return {"status": 200, "msg": ""}
raise HTTPException(status.HTTP_400_BAD_REQUEST, "no such user or subscribe")
return StatusResp(ok=True, msg="")
@router.get("/weight", dependencies=[Depends(check_is_superuser)])
async def get_weight_config():
return await config.get_all_weight_config()
@router.put("/weight", dependencies=[Depends(check_is_superuser)])
async def update_weigth_config(
platform_name: str, target: str, weight_config: WeightConfig
platformName: str, target: str, weight_config: WeightConfig
):
try:
await config.update_time_weight_config(
T_Target(target), platform_name, weight_config
T_Target(target), platformName, weight_config
)
except NoSuchTargetException:
return {"status": 400, "msg": "该订阅不存在"}
return {"status": 200, "msg": ""}
raise HTTPException(status.HTTP_400_BAD_REQUEST, "no such subscribe")
return StatusResp(ok=True, msg="")

View File

@ -0,0 +1,52 @@
from pydantic import BaseModel
class PlatformConfig(BaseModel):
name: str
categories: dict[int, str]
enabledTag: bool
platformName: str
hasTarget: bool
AllPlatformConf = dict[str, PlatformConfig]
class GlobalConf(BaseModel):
platformConf: AllPlatformConf
class TokenResp(BaseModel):
token: str
type: str
id: int
name: str
class SubscribeConfig(BaseModel):
platformName: str
target: str
targetName: str
cats: list[int]
tags: list[str]
class SubscribeGroupDetail(BaseModel):
name: str
subscribes: list[SubscribeConfig]
SubscribeResp = dict[str, SubscribeGroupDetail]
class AddSubscribeReq(BaseModel):
platformName: str
target: str
targetName: str
cats: list[int]
tags: list[str]
class StatusResp(BaseModel):
ok: bool
msg: str