| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106 |
- import os
- import shutil
- import logging
- import tempfile
- from fastapi import FastAPI, Request, File, UploadFile, Form
- from fastapi.responses import HTMLResponse, RedirectResponse, FileResponse
- from fastapi.templating import Jinja2Templates
- from fastapi.staticfiles import StaticFiles
- # Setup logging
- logging.basicConfig(level=logging.INFO)
- logger = logging.getLogger("overlay-manager")
- # root_path ensures FastAPI knows it lives at /patch-manager/
- app = FastAPI(root_path="/patch-manager")
- os.makedirs("static", exist_ok=True)
- app.mount("/static", StaticFiles(directory="static"), name="static")
- templates = Jinja2Templates(directory="templates")
- OVERLAY_DIR = "/srv"
- @app.get("/", response_class=HTMLResponse)
- async def index(request: Request):
- files = []
- dirs = set([""])
- if os.path.exists(OVERLAY_DIR):
- for root, dirnames, filenames in os.walk(OVERLAY_DIR):
- rel_root = os.path.relpath(root, OVERLAY_DIR)
- if rel_root != ".":
- dirs.add(rel_root)
- for filename in filenames:
- rel_path = os.path.relpath(os.path.join(root, filename), OVERLAY_DIR)
- files.append(rel_path)
-
- return templates.TemplateResponse("index.html", {
- "request": request,
- "files": sorted(files),
- "dirs": sorted(list(dirs))
- })
- @app.get("/download-all")
- async def download_all():
- """Zips the entire /srv directory and serves it as a backup."""
- with tempfile.TemporaryDirectory() as tmpdir:
- zip_base = os.path.join(tmpdir, "backup")
- shutil.make_archive(zip_base, 'zip', OVERLAY_DIR)
- return FileResponse(
- path=f"{zip_base}.zip",
- filename="ardupilot_overlays_backup.zip",
- media_type='application/zip'
- )
- @app.post("/upload")
- async def upload_file(file: UploadFile = File(...), target_path: str = Form("")):
- save_dir = os.path.join(OVERLAY_DIR, target_path.strip("/"))
- os.makedirs(save_dir, exist_ok=True)
- file_location = os.path.join(save_dir, file.filename)
- with open(file_location, "wb+") as file_object:
- shutil.copyfileobj(file.file, file_object)
- return RedirectResponse(url="./", status_code=303)
- @app.post("/create_folder")
- async def create_folder(folder_path: str = Form(...)):
- save_dir = os.path.join(OVERLAY_DIR, folder_path.strip("/"))
- os.makedirs(save_dir, exist_ok=True)
- return RedirectResponse(url="./", status_code=303)
- @app.post("/delete")
- async def delete_file(filepath: str = Form(...)):
- target = os.path.join(OVERLAY_DIR, filepath.lstrip("/"))
- if os.path.exists(target):
- if os.path.isdir(target):
- shutil.rmtree(target)
- else:
- os.remove(target)
- return RedirectResponse(url="./", status_code=303)
- @app.get("/edit", response_class=HTMLResponse)
- async def edit_file(request: Request, filepath: str):
- clean_path = filepath.lstrip("/")
- target = os.path.join(OVERLAY_DIR, clean_path)
- logger.info(f"Attempting to edit: {target}")
- if not os.path.exists(target):
- return HTMLResponse(content=f"<h1>404 Not Found</h1><p>File {target} missing.</p><a href='./'>Back</a>", status_code=404)
- try:
- with open(target, "r", encoding="utf-8", errors="ignore") as f:
- content = f.read()
- except Exception as e:
- return HTMLResponse(content=f"<h1>Error</h1><p>{str(e)}</p>", status_code=500)
- return templates.TemplateResponse("edit.html", {
- "request": request,
- "filepath": filepath,
- "content": content
- })
- @app.post("/edit")
- async def save_file(filepath: str = Form(...), content: str = Form(...)):
- target = os.path.join(OVERLAY_DIR, filepath.lstrip("/"))
- if os.path.exists(target):
- with open(target, "w", encoding="utf-8") as f:
- f.write(content)
- return RedirectResponse(url="./", status_code=303)
|