diff --git a/app/flask-postgres/app/app.py b/app/flask-postgres/app/app.py index 1a84cca..7daa572 100644 --- a/app/flask-postgres/app/app.py +++ b/app/flask-postgres/app/app.py @@ -1,6 +1,7 @@ import logging import os import re +import shutil from datetime import datetime from logging.handlers import RotatingFileHandler @@ -17,7 +18,7 @@ from flask import ( from werkzeug.security import check_password_hash, generate_password_hash from werkzeug.utils import secure_filename -from config import Config, COUNTRY_VAT_LABELS +from config import Config, COUNTRY_VAT_LABELS, FILES_DIR from db import get_connection, fetchone_dict, fetchall_dict from auth import login_required from permissions import is_video_allowed_for_level, is_course_allowed_for_level, get_allowed_checklist_levels_for_mandant_level @@ -494,6 +495,11 @@ def admin_mandanten(): kontakt_email = request.form.get("kontakt_email", "").strip() level = request.form.get("level", "0").strip() + admin_name = request.form.get("admin_name", "").strip() + admin_email = request.form.get("admin_email", "").strip().lower() + admin_password = request.form.get("admin_password", "") + admin_password2 = request.form.get("admin_password2", "") + email_pattern = r"^[^@\s]+@[^@\s]+\.[^@\s]+$" error_message = None @@ -507,6 +513,21 @@ def admin_mandanten(): elif not re.match(email_pattern, kontakt_email): error_message = "Bitte eine gültige Kontakt-E-Mail eingeben." + elif not admin_name: + error_message = "Admin User Name ist ein Pflichtfeld." + elif not admin_email: + error_message = "Admin User E-Mail ist ein Pflichtfeld." + elif not re.match(email_pattern, admin_email): + error_message = "Bitte eine gültige Admin E-Mail-Adresse eingeben." + elif not admin_password: + error_message = "Admin Passwort ist ein Pflichtfeld." + elif not admin_password2: + error_message = "Bitte Admin Passwort bestätigen." + elif admin_password != admin_password2: + error_message = "Die beiden Admin-Passwörter stimmen nicht überein." + elif len(admin_password) < 8: + error_message = "Das Admin Passwort muss mindestens 8 Zeichen lang sein." + if error_message: cur.execute(""" SELECT id, kuerzel, name, kontakt_email, level @@ -529,21 +550,77 @@ def admin_mandanten(): active_page="admin", mandanten=mandanten, form_error=error_message, - form_values={ + form_values = { "kuerzel": kuerzel, "name": name, "kontakt_email": kontakt_email, "level": level, - }, + "admin_name": admin_name, + "admin_email": admin_email, + } + **get_current_user() ) + cur.execute(""" + SELECT id + FROM app_user + WHERE lower(email) = %s + """, (admin_email,)) + existing_admin_user = cur.fetchone() + + if existing_admin_user: + error_message = "Ein Benutzer mit der Admin E-Mail existiert bereits." + cur.execute(""" INSERT INTO mandant (kuerzel, name, kontakt_email, level) VALUES (%s, %s, %s, %s) + RETURNING id """, (kuerzel, name, kontakt_email, int(level or 0))) + new_mandant_id = cur.fetchone()[0] + + # Standardgruppen für den neuen Mandanten + cur.execute(""" + INSERT INTO app_group (mandant_id, group_name) + VALUES (%s, %s) + RETURNING id + """, (new_mandant_id, "Useradministration")) + useradmin_group_id = cur.fetchone()[0] + + cur.execute(""" + INSERT INTO app_group (mandant_id, group_name) + VALUES (%s, %s) + RETURNING id + """, (new_mandant_id, "Contentmanager")) + contentmanager_group_id = cur.fetchone()[0] + + # erster Admin-User + admin_password_hash = generate_password_hash(admin_password) + + cur.execute(""" + INSERT INTO app_user (email, name, mandant_id, password_hash, status) + VALUES (%s, %s, %s, %s, %s) + RETURNING id + """, (admin_email, admin_name, new_mandant_id, admin_password_hash, 1)) + new_admin_user_id = cur.fetchone()[0] + + # User beiden Gruppen zuordnen + cur.execute(""" + INSERT INTO user_group (user_id, group_id, mandant_id) + VALUES (%s, %s, %s) + """, (new_admin_user_id, useradmin_group_id, new_mandant_id)) + + cur.execute(""" + INSERT INTO user_group (user_id, group_id, mandant_id) + VALUES (%s, %s, %s) + """, (new_admin_user_id, contentmanager_group_id, new_mandant_id)) + conn.commit() + # Verzeichnis anlegen + mandant_dir = os.path.join(Config.FILES_DIR, str(new_mandant_id)) + os.makedirs(mandant_dir, exist_ok=True) + elif action == "update": mandant_id = request.form.get("id") kuerzel = request.form.get("kuerzel", "").strip() @@ -563,9 +640,17 @@ def admin_mandanten(): elif action == "delete": mandant_id = request.form.get("id") - cur.execute("DELETE FROM mandant WHERE id = %s", (int(mandant_id),)) + mandant_id_int = int(mandant_id) + + # Verzeichnis vor/nach dem Delete entfernen + mandant_dir = os.path.join(Config.FILES_DIR, str(mandant_id_int)) + + cur.execute("DELETE FROM mandant WHERE id = %s", (mandant_id_int,)) conn.commit() + if os.path.isdir(mandant_dir): + shutil.rmtree(mandant_dir, ignore_errors=True) + cur.close() conn.close() return redirect(url_for("admin_mandanten")) @@ -1150,7 +1235,7 @@ def dokument_upload(item_id): final_name_part = item["default_filename"] or original_filename stored_filename = f"{item_id}-{secure_filename(final_name_part)}" - mandant_dir = os.path.join("/files", str(mandant_id)) + mandant_dir = os.path.join("/app/files", str(mandant_id)) os.makedirs(mandant_dir, exist_ok=True) full_path = os.path.join(mandant_dir, stored_filename) @@ -1205,7 +1290,7 @@ def dokument_upload(item_id): @contentmanager_required def dokument_delete(item_id): mandant_id = session.get("mandant_id") - mandant_dir = os.path.join("/files", str(mandant_id)) + mandant_dir = os.path.join("/app/files", str(mandant_id)) conn = get_connection() cur = conn.cursor() @@ -1260,7 +1345,7 @@ def dokument_file(item_id): abort(404) stored_filename = row[0] - mandant_dir = os.path.join("/files", str(mandant_id)) + mandant_dir = os.path.join("/app/files", str(mandant_id)) return send_from_directory(mandant_dir, stored_filename) @app.template_filter("datetime")