From c399551a5087307500577cefd88eb33545a4e81a Mon Sep 17 00:00:00 2001 From: Iam54r1n4 Date: Sat, 22 Feb 2025 10:01:16 +0330 Subject: [PATCH] Implement /restore API --- core/cli_api.py | 3 +- .../routers/api/v1/config/hysteria.py | 27 +++- core/scripts/webpanel/templates/settings.html | 137 +++++++++++------- 3 files changed, 110 insertions(+), 57 deletions(-) diff --git a/core/cli_api.py b/core/cli_api.py index cd7d28e..d602d17 100644 --- a/core/cli_api.py +++ b/core/cli_api.py @@ -180,7 +180,8 @@ def backup_hysteria2(): except Exception as ex: raise -def restore_hysteria2(backup_file_path): + +def restore_hysteria2(backup_file_path: str): '''Restores Hysteria configuration from the given backup file.''' try: run_cmd(['bash', Command.RESTORE_HYSTERIA2.value, backup_file_path]) diff --git a/core/scripts/webpanel/routers/api/v1/config/hysteria.py b/core/scripts/webpanel/routers/api/v1/config/hysteria.py index 2474419..58d5c25 100644 --- a/core/scripts/webpanel/routers/api/v1/config/hysteria.py +++ b/core/scripts/webpanel/routers/api/v1/config/hysteria.py @@ -1,7 +1,8 @@ -from fastapi import APIRouter, HTTPException +from fastapi import APIRouter, HTTPException, UploadFile, File from ..schema.config.hysteria import ConfigFile, GetPortResponse, GetSniResponse from ..schema.response import DetailResponse from fastapi.responses import FileResponse +import shutil # from ..schema.config.hysteria import InstallInputBody import os import cli_api @@ -150,20 +151,20 @@ async def set_sni_api(sni: str): @router.get('/backup', response_class=FileResponse, summary='Backup Hysteria2 configuration') -async def backup(): +async def backup_api(): """ Backups the Hysteria2 configuration and sends the backup ZIP file. """ try: cli_api.backup_hysteria2() - backup_dir = "/opt/hysbackup/" + backup_dir = "/opt/hysbackup/" # TODO: get this path from .env if not os.path.isdir(backup_dir): raise HTTPException(status_code=500, detail="Backup directory does not exist.") files = [f for f in os.listdir(backup_dir) if f.endswith('.zip')] files.sort(key=lambda x: os.path.getctime(os.path.join(backup_dir, x)), reverse=True) - latest_backup_file = files[0] if files else None + latest_backup_file = files[0] if files else None if latest_backup_file: backup_file_path = os.path.join(backup_dir, latest_backup_file) @@ -182,6 +183,24 @@ async def backup(): raise HTTPException(status_code=500, detail=f'Error: {str(e)}') +@router.get('/restore', response_model=DetailResponse, summary='Restore Hysteria2 Configuration') +async def restore_api(f: UploadFile = File(...)): + try: + dst_dir_path = '/opt/hysbackup/' # TODO: get this path from .env + if not os.path.isdir(dst_dir_path): # TODO: the dir path should be exist, so no need to check + os.makedirs(dst_dir_path) + + dst_path = os.path.join(dst_dir_path, f.filename) # type: ignore + + with open(dst_path, 'wb') as buffer: + shutil.copyfileobj(f.file, buffer) + + cli_api.restore_hysteria2(dst_path) + return DetailResponse(detail='Hysteria2 restored successfully.') + except Exception as e: + raise HTTPException(status_code=400, detail=f'Error: {str(e)}') + + @router.get('/enable-obfs', response_model=DetailResponse, summary='Enable Hysteria2 obfs') async def enable_obfs(): """ diff --git a/core/scripts/webpanel/templates/settings.html b/core/scripts/webpanel/templates/settings.html index 06045ec..0423dc9 100644 --- a/core/scripts/webpanel/templates/settings.html +++ b/core/scripts/webpanel/templates/settings.html @@ -19,65 +19,84 @@
-
+

-
+
- +
Please enter a valid domain (without http:// or https://).
- +
Please enter a valid port number.
- - + +
@@ -87,20 +106,24 @@
- +
Please enter a valid domain (without http:// or https://).
- +
Please enter a valid port number.
- - + +
@@ -113,20 +136,23 @@
- -
- Please enter a valid API Token. -
+ +
+ Please enter a valid API Token. +
- +
- Please enter a valid Admin ID. + Please enter a valid Admin ID.
- +
@@ -137,7 +163,8 @@
- +
Please enter a valid port number.
@@ -152,7 +179,8 @@
- +
Please enter a valid domain (without http:// or https://).
@@ -166,14 +194,16 @@
- -
+ +
Please enter a valid IPv4 address.
- +
Please enter a valid IPv6 address.
@@ -183,7 +213,8 @@
- +
@@ -200,7 +231,9 @@ - + -{% endblock %} +{% endblock %} \ No newline at end of file