From 6639006d655ed413f5258a834567dac90ebad15a Mon Sep 17 00:00:00 2001 From: olaf Date: Sun, 29 Jun 2025 06:58:23 +0000 Subject: [PATCH] Refactoring of routes group functionalities working --- dashboard/package.json | 2 +- dashboard/src/apiGroups.ts | 4 +- dashboard/src/dashboard.tsx | 2 +- server/database.py | 13 +++ server/routes/clients.py | 44 +++++++++ server/routes/events.py | 33 +++++++ server/routes/groups.py | 128 +++++++++++++++++++++++++ server/wsgi.py | 186 +++--------------------------------- 8 files changed, 234 insertions(+), 178 deletions(-) create mode 100644 server/database.py create mode 100644 server/routes/clients.py create mode 100644 server/routes/events.py create mode 100644 server/routes/groups.py diff --git a/dashboard/package.json b/dashboard/package.json index 4165b89..590e0c7 100644 --- a/dashboard/package.json +++ b/dashboard/package.json @@ -4,7 +4,7 @@ "version": "0.0.0", "type": "module", "scripts": { - "dev": "vite", + "dev": "vite --host 0.0.0.0 --port 3000", "build": "tsc -b && vite build", "lint": "eslint .", "preview": "vite preview" diff --git a/dashboard/src/apiGroups.ts b/dashboard/src/apiGroups.ts index e7c6ce2..3408a6c 100644 --- a/dashboard/src/apiGroups.ts +++ b/dashboard/src/apiGroups.ts @@ -16,12 +16,12 @@ export async function fetchGroups() { export async function deleteGroup(groupName: string) { // Passe ggf. an deine API an - return fetch(`/api/groups/${encodeURIComponent(groupName)}`, { method: 'DELETE' }); + return fetch(`/api/groups/byname/${encodeURIComponent(groupName)}`, { method: 'DELETE' }); } export async function renameGroup(oldName: string, newName: string) { // Passe ggf. an deine API an - return fetch(`/api/groups/${encodeURIComponent(oldName)}`, { + return fetch(`/api/groups/byname/${encodeURIComponent(oldName)}`, { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ newName }), diff --git a/dashboard/src/dashboard.tsx b/dashboard/src/dashboard.tsx index e665f9e..2fde2d0 100644 --- a/dashboard/src/dashboard.tsx +++ b/dashboard/src/dashboard.tsx @@ -8,7 +8,7 @@ const Dashboard: React.FC = () => { useEffect(() => { fetchClients().then(setClients).catch(console.error); }, []); - + return (
diff --git a/server/database.py b/server/database.py new file mode 100644 index 0000000..3b4718a --- /dev/null +++ b/server/database.py @@ -0,0 +1,13 @@ +import os +from sqlalchemy import create_engine +from sqlalchemy.orm import sessionmaker + +# Umgebungsvariablen +DB_USER = os.getenv("DB_USER", "infoscreen_admin") +DB_PASSWORD = os.getenv("DB_PASSWORD", "KqtpM7wmNd&mFKs") +DB_HOST = os.getenv("DB_HOST", "db") +DB_NAME = os.getenv("DB_NAME", "infoscreen_by_taa") + +DB_URL = f"mysql+pymysql://{DB_USER}:{DB_PASSWORD}@{DB_HOST}/{DB_NAME}" +engine = create_engine(DB_URL, echo=False) +Session = sessionmaker(bind=engine) \ No newline at end of file diff --git a/server/routes/clients.py b/server/routes/clients.py new file mode 100644 index 0000000..4d3bffc --- /dev/null +++ b/server/routes/clients.py @@ -0,0 +1,44 @@ +import sys +sys.path.append('/workspace') +from flask import Blueprint, request, jsonify +from models import Client, ClientGroup +from database import Session + +clients_bp = Blueprint("clients", __name__, url_prefix="/api/clients") + + +@clients_bp.route("", methods=["GET"]) +def get_clients(): + session = Session() + clients = session.query(Client).all() + result = [ + { + "uuid": c.uuid, + "location": c.location, + "hardware_hash": c.hardware_hash, + "ip_address": c.ip_address, + "last_alive": c.last_alive.isoformat() if c.last_alive else None, + "group_id": c.group_id, + } + for c in clients + ] + session.close() + return jsonify(result) + + +@clients_bp.route("/group", methods=["PUT"]) +def update_clients_group(): + data = request.get_json() + client_ids = data.get("client_ids", []) + group_name = data.get("group_name") + session = Session() + group = session.query(ClientGroup).filter_by(name=group_name).first() + if not group: + session.close() + return jsonify({"error": "Gruppe nicht gefunden"}), 404 + session.query(Client).filter(Client.uuid.in_(client_ids)).update( + {Client.group_id: group.id}, synchronize_session=False + ) + session.commit() + session.close() + return jsonify({"success": True}) diff --git a/server/routes/events.py b/server/routes/events.py new file mode 100644 index 0000000..393d750 --- /dev/null +++ b/server/routes/events.py @@ -0,0 +1,33 @@ +import sys +sys.path.append('/workspace') +from flask import Blueprint, request, jsonify +from models import Event +from sqlalchemy import and_ +from database import Session + +events_bp = Blueprint("events", __name__, url_prefix="/api/events") + + +@events_bp.route("", methods=["GET"]) +def get_events(): + session = Session() + start = request.args.get("start") + end = request.args.get("end") + client_uuid = request.args.get("client_uuid") + query = session.query(Event).filter(Event.is_active == True) + if start and end: + query = query.filter(and_(Event.start < end, Event.end > start)) + if client_uuid: + query = query.filter(Event.client_uuid == client_uuid) + events = query.all() + result = [] + for e in events: + result.append({ + "Id": str(e.id), + "Subject": e.title, + "StartTime": e.start.isoformat() if e.start else None, + "EndTime": e.end.isoformat() if e.end else None, + "IsAllDay": False, + }) + session.close() + return jsonify(result) diff --git a/server/routes/groups.py b/server/routes/groups.py new file mode 100644 index 0000000..f4f8009 --- /dev/null +++ b/server/routes/groups.py @@ -0,0 +1,128 @@ +from database import Session +from models import ClientGroup +from flask import Blueprint, request, jsonify +import sys +sys.path.append('/workspace') + +groups_bp = Blueprint("groups", __name__, url_prefix="/api/groups") + + +@groups_bp.route("", methods=["POST"]) +def create_group(): + data = request.get_json() + name = data.get("name") + if not name or not name.strip(): + return jsonify({"error": "Gruppenname erforderlich"}), 400 + + session = Session() + if session.query(ClientGroup).filter_by(name=name).first(): + session.close() + return jsonify({"error": "Gruppe existiert bereits"}), 409 + + group = ClientGroup(name=name, is_active=True) + session.add(group) + session.commit() + result = { + "id": group.id, + "name": group.name, + "created_at": group.created_at.isoformat() if group.created_at else None, + "is_active": group.is_active, + } + session.close() + return jsonify(result), 201 + + +@groups_bp.route("", methods=["GET"]) +def get_groups(): + session = Session() + groups = session.query(ClientGroup).all() + result = [ + { + "id": g.id, + "name": g.name, + "created_at": g.created_at.isoformat() if g.created_at else None, + "is_active": g.is_active, + } + for g in groups + ] + session.close() + return jsonify(result) + + +@groups_bp.route("/", methods=["PUT"]) +def update_group(group_id): + data = request.get_json() + session = Session() + group = session.query(ClientGroup).filter_by(id=group_id).first() + if not group: + session.close() + return jsonify({"error": "Gruppe nicht gefunden"}), 404 + if "name" in data: + group.name = data["name"] + if "is_active" in data: + group.is_active = bool(data["is_active"]) + session.commit() + result = { + "id": group.id, + "name": group.name, + "created_at": group.created_at.isoformat() if group.created_at else None, + "is_active": group.is_active, + } + session.close() + return jsonify(result) + + +@groups_bp.route("/", methods=["DELETE"]) +def delete_group(group_id): + session = Session() + group = session.query(ClientGroup).filter_by(id=group_id).first() + if not group: + session.close() + return jsonify({"error": "Gruppe nicht gefunden"}), 404 + session.delete(group) + session.commit() + session.close() + return jsonify({"success": True}) + + +@groups_bp.route("/byname/", methods=["DELETE"]) +def delete_group_by_name(group_name): + session = Session() + group = session.query(ClientGroup).filter_by(name=group_name).first() + if not group: + session.close() + return jsonify({"error": "Gruppe nicht gefunden"}), 404 + session.delete(group) + session.commit() + session.close() + return jsonify({"success": True}) + + +@groups_bp.route("/byname/", methods=["PUT"]) +def rename_group_by_name(old_name): + data = request.get_json() + new_name = data.get("newName") + if not new_name or not new_name.strip(): + return jsonify({"error": "Neuer Name erforderlich"}), 400 + + session = Session() + group = session.query(ClientGroup).filter_by(name=old_name).first() + if not group: + session.close() + return jsonify({"error": "Gruppe nicht gefunden"}), 404 + + # Prüfe, ob der neue Name schon existiert + if session.query(ClientGroup).filter_by(name=new_name).first(): + session.close() + return jsonify({"error": "Gruppe mit diesem Namen existiert bereits"}), 409 + + group.name = new_name + session.commit() + result = { + "id": group.id, + "name": group.name, + "created_at": group.created_at.isoformat() if group.created_at else None, + "is_active": group.is_active, + } + session.close() + return jsonify(result) diff --git a/server/wsgi.py b/server/wsgi.py index ca68f81..77e96cc 100644 --- a/server/wsgi.py +++ b/server/wsgi.py @@ -1,204 +1,42 @@ # server/wsgi.py -from models import Client, ClientGroup -from flask import request, jsonify import glob import os +import sys +sys.path.append('/workspace') from flask import Flask, jsonify, send_from_directory, request -from sqlalchemy.orm import sessionmaker -from sqlalchemy import create_engine, and_ -from models import Client, Base, Event, ClientGroup - -DB_USER = os.getenv("DB_USER") -DB_PASSWORD = os.getenv("DB_PASSWORD") -DB_HOST = os.getenv("DB_HOST") -DB_NAME = os.getenv("DB_NAME") - -# Datenbank-Engine und Session anlegen (passe ggf. die DB-URL an) -DB_URL = f"mysql+pymysql://{DB_USER}:{DB_PASSWORD}@{DB_HOST}/{DB_NAME}" -engine = create_engine(DB_URL, echo=False) -Session = sessionmaker(bind=engine) +from database import Session, engine app = Flask(__name__) +# Blueprints importieren und registrieren +from routes.clients import clients_bp +from routes.groups import groups_bp +from routes.events import events_bp + +app.register_blueprint(clients_bp) +app.register_blueprint(groups_bp) +app.register_blueprint(events_bp) + @app.route("/health") def health(): return jsonify(status="ok") -# Optional: Test-Route - @app.route("/") def index(): return "Hello from Infoscreen‐API!" -# (Weitere Endpunkte, Blueprints, Datenbank-Initialisierung usw. kommen hierher) - @app.route("/screenshots/") def get_screenshot(uuid): - """Liefert den aktuellen Screenshot für die angegebene UUID zurück.""" - print(f"Anfrage für Screenshot mit UUID: {uuid}") pattern = os.path.join("screenshots", f"{uuid}*.jpg") files = glob.glob(pattern) if not files: return jsonify({"error": "Screenshot not found"}), 404 - # Es gibt nur eine Datei pro UUID filename = os.path.basename(files[0]) - print(filename) - print("Arbeitsverzeichnis:", os.getcwd()) - print("Suchmuster:", pattern) - print("Gefundene Dateien:", files) return send_from_directory("screenshots", filename) -@app.route("/api/clients") -def get_clients(): - # from models import Client # Import lokal, da im selben Container - print("Abrufen der Clients aus der Datenbank...") - session = Session() - clients = session.query(Client).all() - result = [ - { - "uuid": c.uuid, - "location": c.location, - "hardware_hash": c.hardware_hash, - "ip_address": c.ip_address, - "last_alive": c.last_alive.isoformat() if c.last_alive else None, - "group_id": c.group_id, - } - for c in clients - ] - session.close() - return jsonify(result) - - -@app.route("/api/events") -def get_events(): - session = Session() - start = request.args.get("start") - end = request.args.get("end") - client_uuid = request.args.get("client_uuid") - query = session.query(Event).filter(Event.is_active == True) - if start and end: - query = query.filter(and_(Event.start < end, Event.end > start)) - if client_uuid: - query = query.filter(Event.client_uuid == client_uuid) - events = query.all() - result = [] - for e in events: - result.append({ - "Id": str(e.id), - "Subject": e.title, - "StartTime": e.start.isoformat() if e.start else None, - "EndTime": e.end.isoformat() if e.end else None, - "IsAllDay": False, - # Optional: weitere Felder wie "Description", "Location", etc. - }) - session.close() - return jsonify(result) - - -@app.route("/api/groups", methods=["POST"]) -def create_group(): - data = request.get_json() - name = data.get("name") - if not name or not name.strip(): - return jsonify({"error": "Gruppenname erforderlich"}), 400 - - session = Session() - # Prüfen, ob der Name schon existiert - if session.query(ClientGroup).filter_by(name=name).first(): - session.close() - return jsonify({"error": "Gruppe existiert bereits"}), 409 - - group = ClientGroup(name=name, is_active=True) - session.add(group) - session.commit() - result = { - "id": group.id, - "name": group.name, - "created_at": group.created_at.isoformat() if group.created_at else None, - "is_active": group.is_active, - } - session.close() - return jsonify(result), 201 - - -@app.route("/api/groups", methods=["GET"]) -def get_groups(): - """Liefert alle Raumgruppen als Liste zurück.""" - session = Session() - groups = session.query(ClientGroup).all() - result = [ - { - "id": g.id, - "name": g.name, - "created_at": g.created_at.isoformat() if g.created_at else None, - "is_active": g.is_active, - } - for g in groups - ] - session.close() - return jsonify(result) - - -@app.route("/api/groups/", methods=["PUT"]) -def update_group(group_id): - """Ändert den Namen oder Status einer Raumgruppe.""" - data = request.get_json() - session = Session() - group = session.query(ClientGroup).filter_by(id=group_id).first() - if not group: - session.close() - return jsonify({"error": "Gruppe nicht gefunden"}), 404 - if "name" in data: - group.name = data["name"] - if "is_active" in data: - group.is_active = bool(data["is_active"]) - session.commit() - result = { - "id": group.id, - "name": group.name, - "created_at": group.created_at.isoformat() if group.created_at else None, - "is_active": group.is_active, - } - session.close() - return jsonify(result) - - -@app.route("/api/groups/", methods=["DELETE"]) -def delete_group(group_id): - """Löscht eine Raumgruppe.""" - session = Session() - group = session.query(ClientGroup).filter_by(id=group_id).first() - if not group: - session.close() - return jsonify({"error": "Gruppe nicht gefunden"}), 404 - session.delete(group) - session.commit() - session.close() - return jsonify({"success": True}) - - -@app.route("/api/clients/group", methods=["PUT"]) -def update_clients_group(): - data = request.get_json() - client_ids = data.get("client_ids", []) - group_name = data.get("group_name") - print(f"Update Clients Group: {group_name}, IDs: {client_ids}") - session = Session() - group = session.query(ClientGroup).filter_by(name=group_name).first() - if not group: - session.close() - return jsonify({"error": "Gruppe nicht gefunden"}), 404 - session.query(Client).filter(Client.uuid.in_(client_ids)).update( - {Client.group_id: group.id}, synchronize_session=False - ) - session.commit() - session.close() - return jsonify({"success": True}) - - if __name__ == "__main__": app.run(host="0.0.0.0", port=8000, debug=True)