From d2ba96c26ae4463fa4c5fddd6314d9e31d6fb2cc Mon Sep 17 00:00:00 2001 From: Davide Scaini Date: Mon, 13 Apr 2026 20:10:15 +0200 Subject: [PATCH] fix admin delete to wipe originals/edits/geojson; rename button to Reset data MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The old DELETE /api/admin/users/{handle}/activities only removed *.json files and _merged/, leaving originals/ (Strava FIT files) and edits/ untouched — causing the 968 MB disk usage after a delete. _wipe_user_activities() now removes activities/, edits/, originals/, _merged/, index.json, athlete.json, and .bincio_cache.json. Admin page button renamed to "Reset data" with updated confirmation text. --- bincio/serve/server.py | 55 +++++++++++++++++++++----------- site/src/pages/admin/index.astro | 8 +++-- 2 files changed, 42 insertions(+), 21 deletions(-) diff --git a/bincio/serve/server.py b/bincio/serve/server.py index 9003d02..2c86469 100644 --- a/bincio/serve/server.py +++ b/bincio/serve/server.py @@ -517,38 +517,57 @@ async def admin_rebuild( return JSONResponse({"ok": True}) +def _wipe_user_activities(user_dir: Path) -> int: + """Delete all extracted activity files and caches for a user. + + Removes activities/ (JSON + GeoJSON + timeseries), edits/, originals/, + _merged/, index.json, athlete.json, and the dedup cache. + Leaves the user directory itself intact (account remains in the DB). + Returns the number of files deleted. + """ + import shutil + deleted = 0 + + for subdir in ("activities", "edits", "originals"): + d = user_dir / subdir + if d.exists(): + for f in d.rglob("*"): + if f.is_file(): + deleted += 1 + shutil.rmtree(d) + + for name in ("_merged", ): + d = user_dir / name + if d.exists(): + shutil.rmtree(d) + + for name in ("index.json", "athlete.json", ".bincio_cache.json"): + f = user_dir / name + if f.exists(): + f.unlink() + deleted += 1 + + return deleted + + @app.delete("/api/admin/users/{handle}/activities") async def admin_delete_activities( handle: str, bincio_session: Optional[str] = Cookie(default=None), ) -> JSONResponse: - """Delete all activity JSON files for a user and wipe the merged cache.""" + """Delete all activity data for a user and wipe the merged cache.""" _require_admin(bincio_session) user_dir = _get_data_dir() / handle if not user_dir.is_dir(): raise HTTPException(404, f"No data directory for user '{handle}'") - deleted = 0 - activities_dir = user_dir / "activities" - if activities_dir.is_dir(): - for f in activities_dir.glob("*.json"): - f.unlink() - deleted += 1 - - # Wipe merged cache, top-level index, and dedup cache so re-uploads aren't blocked - import shutil - merged_dir = user_dir / "_merged" - if merged_dir.exists(): - shutil.rmtree(merged_dir) - for name in ("index.json", ".bincio_cache.json"): - f = user_dir / name - if f.exists(): - f.unlink() - + deleted = _wipe_user_activities(user_dir) _trigger_rebuild(handle) return JSONResponse({"ok": True, "deleted": deleted}) + + # ── Write API (ported from bincio edit, auth-gated) ─────────────────────────── def _user_data_dir(handle: str) -> Path: diff --git a/site/src/pages/admin/index.astro b/site/src/pages/admin/index.astro index c67ac33..1789631 100644 --- a/site/src/pages/admin/index.astro +++ b/site/src/pages/admin/index.astro @@ -33,10 +33,11 @@ import Base from '../../layouts/Base.astro'; -

Delete all activities for ? This cannot be undone.

+

Reset all data for ?

+

Removes all activities, originals, edits, and images. The account is kept. This cannot be undone.

- +
@@ -124,7 +125,8 @@ import Base from '../../layouts/Base.astro'; + title="Wipe all activities, originals, edits and images — account is kept" + >Reset data