Extend admin for websites/scripts and surface links

This commit is contained in:
Nirodan
2026-01-22 12:26:21 +01:00
parent 0699158486
commit e3b34bfc47
5 changed files with 555 additions and 22 deletions
+248
View File
@@ -18,6 +18,40 @@ def _require_admin():
return user, None
def _ensure_tables(cur):
cur.execute(
"""
CREATE TABLE IF NOT EXISTS users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL UNIQUE,
password VARCHAR(255) NOT NULL,
role VARCHAR(20) NOT NULL
)
"""
)
cur.execute(
"""
CREATE TABLE IF NOT EXISTS websites (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
url VARCHAR(255) NOT NULL,
description VARCHAR(255) DEFAULT ''
)
"""
)
cur.execute(
"""
CREATE TABLE IF NOT EXISTS scripts (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
description VARCHAR(255) DEFAULT '',
content TEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
"""
)
@admin_bp.route("/api/admin/users", methods=["GET"])
def list_users():
_, err = _require_admin()
@@ -27,6 +61,7 @@ def list_users():
cfg = load_config()
conn = connect(**cfg)
cur = conn.cursor(dictionary=True)
_ensure_tables(cur)
cur.execute("SELECT id, username, role FROM users ORDER BY username ASC")
users = cur.fetchall()
cur.close()
@@ -52,6 +87,7 @@ def create_user():
cfg = load_config()
conn = connect(**cfg)
cur = conn.cursor(dictionary=True)
_ensure_tables(cur)
cur.execute("SELECT id FROM users WHERE username=%s", (username,))
if cur.fetchone():
cur.close()
@@ -86,6 +122,7 @@ def update_user(user_id):
cfg = load_config()
conn = connect(**cfg)
cur = conn.cursor()
_ensure_tables(cur)
if role:
cur.execute("UPDATE users SET role=%s WHERE id=%s", (role, user_id))
if password:
@@ -112,6 +149,7 @@ def delete_user(user_id):
cfg = load_config()
conn = connect(**cfg)
cur = conn.cursor()
_ensure_tables(cur)
# Schutz: Admin darf sich nicht selbst löschen
cur.execute("SELECT username FROM users WHERE id=%s", (user_id,))
row = cur.fetchone()
@@ -133,3 +171,213 @@ def delete_user(user_id):
except Exception as e:
logger.error(f"[Admin delete_user] {e}")
return jsonify({"message": "Serverfehler"}), 500
# ---------- Websites (Admin CRUD) ----------
@admin_bp.route("/api/admin/websites", methods=["GET"])
def list_websites_admin():
_, err = _require_admin()
if err:
return err
try:
cfg = load_config()
conn = connect(**cfg)
cur = conn.cursor(dictionary=True)
_ensure_tables(cur)
cur.execute("SELECT id, name, url, description FROM websites ORDER BY name ASC")
rows = cur.fetchall()
cur.close()
conn.close()
return jsonify(rows)
except Exception as e:
logger.error(f"[Admin list_websites] {e}")
return jsonify({"message": "Serverfehler"}), 500
@admin_bp.route("/api/admin/websites", methods=["POST"])
def create_website():
_, err = _require_admin()
if err:
return err
data = request.get_json() or {}
name = data.get("name", "").strip()
url = data.get("url", "").strip()
description = data.get("description", "").strip()
if not name or not url:
return jsonify({"message": "Name und URL erforderlich"}), 400
try:
cfg = load_config()
conn = connect(**cfg)
cur = conn.cursor()
_ensure_tables(cur)
cur.execute(
"INSERT INTO websites (name, url, description) VALUES (%s, %s, %s)",
(name, url, description),
)
conn.commit()
new_id = cur.lastrowid
cur.close()
conn.close()
return jsonify({"id": new_id, "name": name, "url": url, "description": description}), 201
except Exception as e:
logger.error(f"[Admin create_website] {e}")
return jsonify({"message": "Serverfehler"}), 500
@admin_bp.route("/api/admin/websites/<int:item_id>", methods=["PUT"])
def update_website(item_id):
_, err = _require_admin()
if err:
return err
data = request.get_json() or {}
try:
cfg = load_config()
conn = connect(**cfg)
cur = conn.cursor()
_ensure_tables(cur)
cur.execute(
"UPDATE websites SET name=%s, url=%s, description=%s WHERE id=%s",
(data.get("name"), data.get("url"), data.get("description", ""), item_id),
)
conn.commit()
cur.close()
conn.close()
return jsonify({"message": "Aktualisiert"}), 200
except Exception as e:
logger.error(f"[Admin update_website] {e}")
return jsonify({"message": "Serverfehler"}), 500
@admin_bp.route("/api/admin/websites/<int:item_id>", methods=["DELETE"])
def delete_website(item_id):
_, err = _require_admin()
if err:
return err
try:
cfg = load_config()
conn = connect(**cfg)
cur = conn.cursor()
_ensure_tables(cur)
cur.execute("DELETE FROM websites WHERE id=%s", (item_id,))
conn.commit()
cur.close()
conn.close()
return jsonify({"message": "Gelöscht"}), 200
except Exception as e:
logger.error(f"[Admin delete_website] {e}")
return jsonify({"message": "Serverfehler"}), 500
# ---------- Scripts (Admin CRUD) ----------
@admin_bp.route("/api/admin/scripts", methods=["GET"])
def list_scripts_admin():
_, err = _require_admin()
if err:
return err
try:
cfg = load_config()
conn = connect(**cfg)
cur = conn.cursor(dictionary=True)
_ensure_tables(cur)
cur.execute("SELECT id, name, description, created_at FROM scripts ORDER BY created_at DESC")
rows = cur.fetchall()
cur.close()
conn.close()
return jsonify(rows)
except Exception as e:
logger.error(f"[Admin list_scripts] {e}")
return jsonify({"message": "Serverfehler"}), 500
@admin_bp.route("/api/admin/scripts", methods=["POST"])
def create_script():
_, err = _require_admin()
if err:
return err
data = request.get_json() or {}
name = data.get("name", "").strip()
description = data.get("description", "").strip()
content = data.get("content", "")
if not name or not content:
return jsonify({"message": "Name und Inhalt erforderlich"}), 400
try:
cfg = load_config()
conn = connect(**cfg)
cur = conn.cursor()
_ensure_tables(cur)
cur.execute(
"INSERT INTO scripts (name, description, content) VALUES (%s, %s, %s)",
(name, description, content),
)
conn.commit()
new_id = cur.lastrowid
cur.close()
conn.close()
return jsonify({"id": new_id, "name": name, "description": description}), 201
except Exception as e:
logger.error(f"[Admin create_script] {e}")
return jsonify({"message": "Serverfehler"}), 500
@admin_bp.route("/api/admin/scripts/<int:item_id>", methods=["DELETE"])
def delete_script(item_id):
_, err = _require_admin()
if err:
return err
try:
cfg = load_config()
conn = connect(**cfg)
cur = conn.cursor()
_ensure_tables(cur)
cur.execute("DELETE FROM scripts WHERE id=%s", (item_id,))
conn.commit()
cur.close()
conn.close()
return jsonify({"message": "Gelöscht"}), 200
except Exception as e:
logger.error(f"[Admin delete_script] {e}")
return jsonify({"message": "Serverfehler"}), 500
# ---------- Public (logged-in) endpoints ----------
@admin_bp.route("/api/websites", methods=["GET"])
def list_websites_public():
user = verify_token()
if not user:
return jsonify({"message": "Nicht autorisiert"}), 401
try:
cfg = load_config()
conn = connect(**cfg)
cur = conn.cursor(dictionary=True)
_ensure_tables(cur)
cur.execute("SELECT id, name, url, description FROM websites ORDER BY name ASC")
rows = cur.fetchall()
cur.close()
conn.close()
return jsonify(rows)
except Exception as e:
logger.error(f"[Public list_websites] {e}")
return jsonify({"message": "Serverfehler"}), 500
@admin_bp.route("/api/scripts", methods=["GET"])
def list_scripts_public():
user = verify_token()
if not user:
return jsonify({"message": "Nicht autorisiert"}), 401
try:
cfg = load_config()
conn = connect(**cfg)
cur = conn.cursor(dictionary=True)
_ensure_tables(cur)
cur.execute("SELECT id, name, description, created_at FROM scripts ORDER BY created_at DESC")
rows = cur.fetchall()
cur.close()
conn.close()
return jsonify(rows)
except Exception as e:
logger.error(f"[Public list_scripts] {e}")
return jsonify({"message": "Serverfehler"}), 500