From 9930782819b6ee07c24f96269278608f1b74e642 Mon Sep 17 00:00:00 2001 From: Bkolb Date: Thu, 2 Apr 2026 20:33:00 +0200 Subject: [PATCH] New User Form --- app/flask-postgres/app/app.py | 122 ++++++++++++++ app/flask-postgres/app/templates/profil.html | 9 +- .../app/templates/useradmin_user_new.html | 149 ++++++++++++++++++ app/flask-postgres/styles/site.css | 54 +++++++ 4 files changed, 332 insertions(+), 2 deletions(-) create mode 100644 app/flask-postgres/app/templates/useradmin_user_new.html diff --git a/app/flask-postgres/app/app.py b/app/flask-postgres/app/app.py index b21c96d..2538a28 100644 --- a/app/flask-postgres/app/app.py +++ b/app/flask-postgres/app/app.py @@ -621,4 +621,126 @@ def pwdchange(): error_message=error_message, success_message=success_message, **get_current_user() + ) + +@app.route("/useradmin/mandant/new", methods=["GET", "POST"]) +@user_admin_required +def useradmin_user_new(): + current_mandant_id = session.get("mandant_id") + + conn = get_connection() + cur = conn.cursor() + + cur.execute(""" + SELECT id, group_name + FROM app_group + WHERE mandant_id = %s + ORDER BY group_name + """, (current_mandant_id,)) + gruppen = fetchall_dict(cur) + + form_error = None + form_values = { + "email": "", + "name": "", + "status": "1", + "selected_groups": [] + } + + if request.method == "POST": + email = request.form.get("email", "").strip().lower() + name = request.form.get("name", "").strip() + password = request.form.get("password", "") + password2 = request.form.get("password2", "") + status = request.form.get("status", "1").strip() + selected_groups = request.form.getlist("group_ids") + + form_values = { + "email": email, + "name": name, + "status": status, + "selected_groups": selected_groups + } + + email_pattern = r"^[^@\s]+@[^@\s]+\.[^@\s]+$" + + if not email: + form_error = "E-Mail ist ein Pflichtfeld." + elif not re.match(email_pattern, email): + form_error = "Bitte eine gültige E-Mail-Adresse eingeben." + elif not name: + form_error = "Name ist ein Pflichtfeld." + elif not password: + form_error = "Passwort ist ein Pflichtfeld." + elif not password2: + form_error = "Bitte Passwort bestätigen." + elif password != password2: + form_error = "Die beiden Passwörter stimmen nicht überein." + elif len(password) < 8: + form_error = "Das Passwort muss mindestens 8 Zeichen lang sein." + else: + cur.execute(""" + SELECT id + FROM app_user + WHERE lower(email) = %s + """, (email,)) + existing_user = cur.fetchone() + + if existing_user: + form_error = "Ein Benutzer mit dieser E-Mail existiert bereits." + else: + password_hash = generate_password_hash(password) + + cur.execute(""" + INSERT INTO app_user ( + email, + name, + mandant_id, + password_hash, + status + ) + VALUES (%s, %s, %s, %s, %s) + RETURNING id + """, ( + email, + name, + current_mandant_id, + password_hash, + int(status or 1) + )) + new_user_id = cur.fetchone()[0] + + if selected_groups: + cur.execute(""" + SELECT id + FROM app_group + WHERE mandant_id = %s + AND id = ANY(%s) + """, (current_mandant_id, selected_groups)) + valid_groups = cur.fetchall() + + for row in valid_groups: + group_id = row[0] + cur.execute(""" + INSERT INTO user_group (user_id, group_id, mandant_id) + VALUES (%s, %s, %s) + """, (new_user_id, group_id, current_mandant_id)) + + conn.commit() + cur.close() + conn.close() + + return redirect(url_for("useradmin_mandant")) + + cur.close() + conn.close() + + return render_template( + "useradmin_user_new.html", + page_title="Neuer User", + active_page="useradmin", + gruppen=gruppen, + form_error=form_error, + form_values=form_values, + **get_current_user() ) \ No newline at end of file diff --git a/app/flask-postgres/app/templates/profil.html b/app/flask-postgres/app/templates/profil.html index 3eafcc1..6206898 100644 --- a/app/flask-postgres/app/templates/profil.html +++ b/app/flask-postgres/app/templates/profil.html @@ -12,16 +12,21 @@ Mandant E-Mail{{ profile.mandant_email or '-' }} Mandant Level{{ profile.mandant_level }} - + Gruppen im Mandanten {% if gruppen %} - {{ gruppen | join(', ') }} +
+ {% for gruppe in gruppen %} + {{ gruppe }} + {% endfor %} +
{% else %} - {% endif %} +
diff --git a/app/flask-postgres/app/templates/useradmin_user_new.html b/app/flask-postgres/app/templates/useradmin_user_new.html new file mode 100644 index 0000000..138dce5 --- /dev/null +++ b/app/flask-postgres/app/templates/useradmin_user_new.html @@ -0,0 +1,149 @@ +{% extends "base.html" %} + +{% block content %} + + + +
+
+ + {% if form_error %} +
{{ form_error }}
+ {% endif %} + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ +
+ {% for gruppe in gruppen %} + + {% endfor %} +
+
+ +
+ +
+ + Zurück +
+
+ +
+
+
+ + + +{% endblock %} \ No newline at end of file diff --git a/app/flask-postgres/styles/site.css b/app/flask-postgres/styles/site.css index 6f55eec..cea0111 100644 --- a/app/flask-postgres/styles/site.css +++ b/app/flask-postgres/styles/site.css @@ -375,4 +375,58 @@ button { .top-nav a { min-width: auto; } +} + +.group-badges { + display: flex; + flex-wrap: wrap; + gap: 8px; +} + +.group-badge { + display: inline-flex; + align-items: center; + padding: 6px 12px; + border-radius: 999px; + background: #eef4fb; + color: #0d2f57; + font-weight: 600; + font-size: 14px; + border: 1px solid #dce3ea; +} +/* ========================= + 12. NEW USER +========================= */ +.checkbox-group { + display: flex; + flex-wrap: wrap; + gap: 10px 16px; + padding: 4px 0; +} + +.checkbox-item { + display: inline-flex; + align-items: center; + gap: 8px; + padding: 8px 12px; + background: #eef4fb; + border: 1px solid #dce3ea; + border-radius: 10px; + color: #0d2f57; + font-weight: 600; +} + +.checkbox-item input[type="checkbox"] { + margin: 0; +} + +.admin-grid-form select { + width: 100%; + min-height: 46px; + padding: 10px 12px; + border: 1px solid #cfd8e3; + border-radius: 10px; + font-size: 16px; + box-sizing: border-box; + background: #fff; } \ No newline at end of file