From fa7090a88b33b1c10f7c69ea1a18614529f0f9bf Mon Sep 17 00:00:00 2001 From: Whispering Wind <151555003+ReturnFI@users.noreply.github.com> Date: Fri, 25 Apr 2025 21:58:04 +0330 Subject: [PATCH] feat(api): Add endpoints for webpanel decoy management using background tasks - Add POST `/api/v1/config/hysteria/webpanel/decoy/setup` endpoint to configure the decoy site. - Add POST `/api/v1/config/hysteria/webpanel/decoy/stop` endpoint to remove the decoy site configuration. - Implement `BackgroundTasks` for both endpoints to prevent Caddy service restarts from interrupting the API response. - Add `SetupDecoyRequest` Pydantic schema for the setup endpoint payload. --- core/scripts/webpanel/config/config.py | 1 + .../routers/api/v1/config/hysteria.py | 46 +++++++++++++++++-- .../routers/api/v1/schema/response.py | 8 +++- 3 files changed, 50 insertions(+), 5 deletions(-) diff --git a/core/scripts/webpanel/config/config.py b/core/scripts/webpanel/config/config.py index 3960896..2b48d56 100644 --- a/core/scripts/webpanel/config/config.py +++ b/core/scripts/webpanel/config/config.py @@ -10,6 +10,7 @@ class Configs(BaseSettings): API_TOKEN: str EXPIRATION_MINUTES: int ROOT_PATH: str + DECOY_PATH: str | None = None class Config: env_file = '.env' diff --git a/core/scripts/webpanel/routers/api/v1/config/hysteria.py b/core/scripts/webpanel/routers/api/v1/config/hysteria.py index 7837892..08f06cd 100644 --- a/core/scripts/webpanel/routers/api/v1/config/hysteria.py +++ b/core/scripts/webpanel/routers/api/v1/config/hysteria.py @@ -1,6 +1,6 @@ -from fastapi import APIRouter, HTTPException, UploadFile, File +from fastapi import APIRouter, BackgroundTasks, HTTPException, UploadFile, File from ..schema.config.hysteria import ConfigFile, GetPortResponse, GetSniResponse -from ..schema.response import DetailResponse, IPLimitConfig +from ..schema.response import DetailResponse, IPLimitConfig, SetupDecoyRequest from fastapi.responses import FileResponse import shutil import zipfile @@ -333,4 +333,44 @@ async def config_ip_limit_api(config: IPLimitConfig): details += f' Max IPs per user: {config.max_ips}.' return DetailResponse(detail=details) except Exception as e: - raise HTTPException(status_code=400, detail=f'Error configuring IP Limiter: {str(e)}') \ No newline at end of file + raise HTTPException(status_code=400, detail=f'Error configuring IP Limiter: {str(e)}') + + +def run_setup_decoy_background(domain: str, decoy_path: str): + """Function to run decoy setup in the background.""" + try: + cli_api.setup_webpanel_decoy(domain, decoy_path) + except Exception: + pass + +def run_stop_decoy_background(): + """Function to run decoy stop in the background.""" + try: + cli_api.stop_webpanel_decoy() + except Exception: + pass + +@router.post('/webpanel/decoy/setup', response_model=DetailResponse, summary='Setup/Update WebPanel Decoy Site (Background Task)') +async def setup_decoy_api(request_body: SetupDecoyRequest, background_tasks: BackgroundTasks): + """ + Initiates the setup or update of the decoy site configuration for the web panel. + Requires the web panel service to be running. + The actual operation (including Caddy restart) runs in the background. + """ + if not os.path.isdir(request_body.decoy_path): + raise HTTPException(status_code=400, detail=f"Decoy path does not exist or is not a directory: {request_body.decoy_path}") + + background_tasks.add_task(run_setup_decoy_background, request_body.domain, request_body.decoy_path) + + return DetailResponse(detail=f'Web Panel decoy site setup initiated for domain {request_body.domain}. Caddy will restart in the background.') + + +@router.post('/webpanel/decoy/stop', response_model=DetailResponse, summary='Stop WebPanel Decoy Site (Background Task)') +async def stop_decoy_api(background_tasks: BackgroundTasks): + """ + Initiates the removal of the decoy site configuration for the web panel. + The actual operation (including Caddy restart) runs in the background. + """ + background_tasks.add_task(run_stop_decoy_background) + + return DetailResponse(detail='Web Panel decoy site stop initiated. Caddy will restart in the background.') \ No newline at end of file diff --git a/core/scripts/webpanel/routers/api/v1/schema/response.py b/core/scripts/webpanel/routers/api/v1/schema/response.py index 9a80bf6..670ad29 100644 --- a/core/scripts/webpanel/routers/api/v1/schema/response.py +++ b/core/scripts/webpanel/routers/api/v1/schema/response.py @@ -1,5 +1,5 @@ from typing import Optional -from pydantic import BaseModel +from pydantic import BaseModel, Field class DetailResponse(BaseModel): @@ -7,4 +7,8 @@ class DetailResponse(BaseModel): class IPLimitConfig(BaseModel): block_duration: Optional[int] = None - max_ips: Optional[int] = None \ No newline at end of file + max_ips: Optional[int] = None + +class SetupDecoyRequest(BaseModel): + domain: str = Field(..., description="Domain name associated with the web panel") + decoy_path: str = Field(..., description="Absolute path to the directory containing the decoy website files") \ No newline at end of file