feat: enable auth in all api

This commit is contained in:
EstrellaXD
2023-05-20 17:31:42 +08:00
parent 30d49636ae
commit 589df384c9
9 changed files with 130 additions and 62 deletions

View File

@@ -1,45 +1,19 @@
from fastapi import Depends, HTTPException, status
from fastapi.security import OAuth2PasswordRequestForm, OAuth2PasswordBearer
from fastapi.security import OAuth2PasswordRequestForm
from module.database.user import AuthDB
from module.security.jwt import create_access_token, decode_token
from module.security import create_access_token, get_current_user, update_user_info, auth_user
from module.models.user import User
from .program import router
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/api/v1/auth/login")
async def get_current_user(token: str = Depends(oauth2_scheme)):
if not token:
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token")
payload = decode_token(token)
if not payload:
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token")
username = payload.get("sub")
with AuthDB() as user_db:
user = user_db.get_user(username)
if not user:
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid username")
return user
async def get_token_data(token: str = Depends(oauth2_scheme)):
payload = decode_token(token)
if not payload:
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token")
return payload
@router.post("/api/v1/auth/login", response_model=dict, tags=["auth"])
async def login(form_data: OAuth2PasswordRequestForm = Depends()):
username = form_data.username
password = form_data.password
with AuthDB() as db:
if not db.auth_user(username, password):
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid username or password")
token = create_access_token({"sub": username})
return {"access_token": token, "token_type": "bearer", "expire": 86400}
auth_user(username, password)
token = create_access_token({"sub": username})
return {"access_token": token, "token_type": "bearer", "expire": 86400}
@router.get("/api/v1/auth/refresh_token", response_model=dict, tags=["auth"])
@@ -62,12 +36,8 @@ async def logout(
@router.post("/api/v1/auth/update", response_model=dict, tags=["auth"])
async def update_user(data: User, current_user: User = Depends(get_current_user)):
async def update_user(user_data: User, current_user: User = Depends(get_current_user)):
if not current_user:
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token")
try:
with AuthDB() as db:
db.update_user(current_user.username, data)
return {"message": "update success"}
except Exception as e:
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e))
return update_user_info(user_data, current_user)

View File

@@ -1,42 +1,57 @@
from fastapi import Depends, HTTPException, status
from .log import router
from module.models import BangumiData
from module.database import BangumiDatabase
from module.manager import TorrentManager
from module.security import get_current_user
@router.get("/api/v1/bangumi/getAll", tags=["bangumi"], response_model=list[BangumiData])
async def get_all_data():
async def get_all_data(current_user=Depends(get_current_user)):
if not current_user:
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token")
with TorrentManager() as torrent:
return torrent.search_all()
@router.get("/api/v1/bangumi/getData/{bangumi_id}", tags=["bangumi"], response_model=BangumiData)
async def get_data(bangumi_id: str):
async def get_data(bangumi_id: str, current_user=Depends(get_current_user)):
if not current_user:
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token")
with TorrentManager() as torrent:
return torrent.search_data(bangumi_id)
@router.post("/api/v1/bangumi/updateData", tags=["bangumi"])
async def update_data(data: BangumiData):
async def update_data(data: BangumiData, current_user=Depends(get_current_user)):
if not current_user:
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token")
with TorrentManager() as torrent:
return torrent.update_rule(data)
@router.delete("/api/v1/bangumi/deleteData/{bangumi_id}", tags=["bangumi"])
async def delete_data(bangumi_id: str):
async def delete_data(bangumi_id: str, current_user=Depends(get_current_user)):
if not current_user:
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token")
with TorrentManager() as torrent:
return torrent.delete_data(bangumi_id)
@router.delete("/api/v1/bangumi/deleteRule/{bangumi_id}", tags=["bangumi"])
async def delete_rule(bangumi_id: str, file: bool = False):
async def delete_rule(bangumi_id: str, file: bool = False, current_user=Depends(get_current_user)):
if not current_user:
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token")
with TorrentManager() as torrent:
return torrent.delete_rule(bangumi_id, file)
@router.get("/api/v1/bangumi/resetAll", tags=["bangumi"])
async def reset_all():
async def reset_all(current_user=Depends(get_current_user)):
if not current_user:
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token")
with BangumiDatabase() as database:
database.delete_all()
return {"status": "ok"}

View File

@@ -1,20 +1,27 @@
import logging
from fastapi import Depends, HTTPException, status
from .bangumi import router
from module.conf import settings
from module.models import Config
from module.security import get_current_user
logger = logging.getLogger(__name__)
@router.get("/api/v1/getConfig", tags=["config"], response_model=Config)
async def get_config():
async def get_config(current_user=Depends(get_current_user)):
if not current_user:
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token")
return settings
@router.post("/api/v1/updateConfig", tags=["config"])
async def update_config(config: Config):
async def update_config(config: Config, current_user=Depends(get_current_user)):
if not current_user:
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token")
try:
settings.save(config_dict=config.dict())
settings.load()

View File

@@ -1,9 +1,12 @@
from fastapi import Depends, HTTPException, status
from .config import router
from module.models.api import *
from module.models import BangumiData
from module.manager import SeasonCollector
from module.rss import analyser
from module.security import get_current_user
def link_process(link):
@@ -11,7 +14,9 @@ def link_process(link):
@router.post("/api/v1/download/analysis", tags=["download"])
async def analysis(link: RssLink):
async def analysis(link: RssLink, current_user=Depends(get_current_user)):
if not current_user:
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token")
data = link_process(link.rss_link)
if data:
return data[0]
@@ -20,7 +25,9 @@ async def analysis(link: RssLink):
@router.post("/api/v1/download/collection", tags=["download"])
async def download_collection(data: BangumiData):
async def download_collection(data: BangumiData, current_user=Depends(get_current_user)):
if not current_user:
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token")
if data:
with SeasonCollector() as collector:
collector.collect_season(data, data.rss_link[0])
@@ -30,7 +37,9 @@ async def download_collection(data: BangumiData):
@router.post("/api/v1/download/subscribe", tags=["download"])
async def subscribe(data: BangumiData):
async def subscribe(data: BangumiData, current_user=Depends(get_current_user)):
if not current_user:
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token")
if data:
with SeasonCollector() as collector:
collector.subscribe_season(data)

View File

@@ -1,13 +1,16 @@
import os
from fastapi import Response
from fastapi import Response, HTTPException, Depends, status
from .auth import router
from module.conf import LOG_PATH
from module.security import get_current_user
@router.get("/api/v1/log", tags=["log"])
async def get_log():
async def get_log(current_user=Depends(get_current_user)):
if not current_user:
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token")
if os.path.isfile(LOG_PATH):
with open(LOG_PATH, "r") as f:
return Response(f.read(), media_type="text/plain")
@@ -16,7 +19,9 @@ async def get_log():
@router.get("/api/v1/log/clear", tags=["log"])
async def clear_log():
async def clear_log(current_user=Depends(get_current_user)):
if not current_user:
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token")
if os.path.isfile(LOG_PATH):
with open(LOG_PATH, "w") as f:
f.write("")

View File

@@ -2,12 +2,11 @@ import signal
import logging
import os
from fastapi.exceptions import HTTPException
from fastapi import HTTPException, status, Depends
from fastapi import FastAPI
from module.core import Program
from module.security import get_current_user
logger = logging.getLogger(__name__)
program = Program()
@@ -25,7 +24,9 @@ async def shutdown():
@router.get("/api/v1/restart", tags=["program"])
async def restart():
async def restart(current_user=Depends(get_current_user)):
if not current_user:
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token")
try:
program.restart()
return {"status": "ok"}
@@ -36,7 +37,9 @@ async def restart():
@router.get("/api/v1/start", tags=["program"])
async def start():
async def start(current_user=Depends(get_current_user)):
if not current_user:
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token")
try:
program.start()
return {"status": "ok"}
@@ -47,13 +50,17 @@ async def start():
@router.get("/api/v1/stop", tags=["program"])
async def stop():
async def stop(current_user=Depends(get_current_user)):
if not current_user:
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token")
program.stop()
return {"status": "ok"}
@router.get("/api/v1/status", tags=["program"])
async def status():
async def status(current_user=Depends(get_current_user)):
if not current_user:
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token")
if not program.is_running:
return {"status": "stop"}
else:
@@ -61,7 +68,9 @@ async def status():
@router.get("/api/v1/shutdown", tags=["program"])
async def shutdown_program():
async def shutdown_program(current_user=Depends(get_current_user)):
if not current_user:
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token")
program.stop()
logger.info("Shutting down program...")
os.kill(os.getpid(), signal.SIGINT)
@@ -70,10 +79,14 @@ async def shutdown_program():
# Check status
@router.get("/api/v1/check/downloader", tags=["check"])
async def check_downloader_status():
async def check_downloader_status(current_user=Depends(get_current_user)):
if not current_user:
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token")
return program.check_downloader()
@router.get("/api/v1/check/rss", tags=["check"])
async def check_rss_status():
async def check_rss_status(current_user=Depends(get_current_user)):
if not current_user:
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token")
return program.check_analyser()

View File

@@ -1 +1,2 @@
from .bangumi import BangumiDatabase
from .user import AuthDB

View File

@@ -0,0 +1,2 @@
from .jwt import create_access_token
from .api import get_current_user, get_token_data, auth_user, update_user_info

View File

@@ -0,0 +1,46 @@
from fastapi import Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer
from .jwt import decode_token
from module.database import AuthDB
from module.models.user import User
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/api/v1/auth/login")
async def get_current_user(token: str = Depends(oauth2_scheme)):
if not token:
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token")
payload = decode_token(token)
if not payload:
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token")
username = payload.get("sub")
with AuthDB() as user_db:
user = user_db.get_user(username)
if not user:
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid username")
return user
async def get_token_data(token: str = Depends(oauth2_scheme)):
payload = decode_token(token)
if not payload:
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token")
return payload
def update_user_info(user_data: User, current_user):
try:
with AuthDB() as db:
db.update_user(current_user.username, user_data)
return {"message": "update success"}
except Exception as e:
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e))
def auth_user(username, password):
with AuthDB() as db:
if not db.auth_user(username, password):
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid username or password")