add garbageCollector

This commit is contained in:
hendrik 2026-01-08 20:35:13 +01:00
parent 5ed71bdcdd
commit ee414d4b57
2 changed files with 120 additions and 0 deletions

View File

@ -0,0 +1,113 @@
from flask import Flask, render_template_string, request, redirect, url_for, abort
import os
import shutil
from pathlib import Path
from config import BASE_DIRS, DEFAULT_BASE
app = Flask(__name__)
def get_base(name):
if name not in BASE_DIRS:
abort(400)
return BASE_DIRS[name]
def safe_path(base: Path, rel: str) -> Path:
"""Resolve rel under base and prevent path traversal."""
target = (base / rel).resolve()
if not str(target).startswith(str(base)):
abort(403)
return target
@app.route("/")
def index():
base_name = request.args.get("base", DEFAULT_BASE)
base = get_base(base_name)
rel = request.args.get("path", "")
current = safe_path(base, rel)
if not current.exists() or not current.is_dir():
abort(404)
items = []
for p in sorted(current.iterdir(), key=lambda x: (x.is_file(), x.name.lower())):
items.append({
"name": p.name,
"is_dir": p.is_dir(),
"rel": str(p.relative_to(base)),
})
return render_template_string(TEMPLATE, items=items, base_name=base_name, rel=rel, bases=BASE_DIRS.keys())
@app.post("/delete")
def delete():
base_name = request.form.get("base", DEFAULT_BASE)
base = get_base(base_name)
rel = request.form.get("path")
target = safe_path(base, rel)
if not target.exists():
abort(404)
if target.is_dir():
shutil.rmtree(target)
else:
target.unlink()
parent = os.path.dirname(rel)
return redirect(url_for("index", base=base_name, path=parent))
# ---- UI ----
TEMPLATE = """
<!doctype html>
<title>Minimal File Browser</title>
<style>
body { font-family: sans-serif; margin: 2rem; }
.row { display: flex; gap: 1rem; align-items: center; }
.file { margin-left: 1.5rem; }
button { color: red; }
</style>
<form method="get">
Base folder:
<select name="base" onchange="this.form.submit()">
{% for b in bases %}
<option value="{{b}}" {% if b==base_name %}selected{% endif %}>{{b}}</option>
{% endfor %}
</select>
</form>
<h3>Path: /{{ rel }}</h3>
<ul>
{% if rel and '/' in rel %}
<li><a href="/?base={{base_name}}&path={{ rel.rsplit('/',1)[0] }}">..</a></li>
{% elif rel %}
<li><a href="/?base={{base_name}}">..</a></li>
{% endif %}
{% for i in items %}
<li class="row">
{% if i.is_dir %}
<a href="/?base={{base_name}}&path={{ i.rel }}">📁 {{ i.name }}</a>
{% else %}
<span class="file">📄 {{ i.name }}</span>
{% endif %}
<form method="post" action="/delete" onsubmit="return confirm('Delete {{i.name}}?')">
<input type="hidden" name="base" value="{{base_name}}">
<input type="hidden" name="path" value="{{ i.rel }}">
<button type="submit">Delete</button>
</form>
</li>
{% endfor %}
</ul>
"""
if __name__ == "__main__":
app.run(host="192.168.101.13", port=8000)

View File

@ -0,0 +1,7 @@
from pathlib import Path
BASE_DIRS = {
"data": Path("/root/garbageCollector").resolve(),
"uploads": Path("/srv/uploads").resolve(),
}
DEFAULT_BASE = "data"