# NateMan – Nachschreibtermin-Manager
# blueprints/admin/lehrer.py
# Copyright © 2020 Niklas Elsbrock
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
"""
Lehrerkonten-Administrations-Blueprint
"""
from flask import Blueprint, abort, current_app, flash, g, redirect, render_template, request, url_for
from ..auth import admin_required
from ... import util
from ...models import Lehrer, Stufe, db
bp = Blueprint("lehrer", __name__, url_prefix="/admin/lehrer")
@bp.route("/")
@admin_required
def index():
""" Lehrerliste """
return render_template("admin/lehrer/index.html.j2")
@bp.route("/", methods=("GET", "POST"))
@admin_required
def edit(lehrer_id):
""" Lehrerbearbeitung """
lehrer: Lehrer = Lehrer.query.filter_by(id=lehrer_id).first()
# HTTP 404 Fehler erzeugen, wenn kein Lehrer unter der ID gefunden wurde
if not lehrer:
abort(404)
return
if request.method != "POST":
return render_template("admin/lehrer/edit.html.j2", lehrer=lehrer)
# ELSE
action = request.form["action"]
# Benutzerdaten ändern
if action == "change-credentials":
new_kuerzel = request.form["new-kuerzel"].strip()
new_email = request.form["new-email"].strip() or None
new_password = request.form["new-password"]
new_beraet_name = request.form["new-beraet"]
new_is_admin = ("new-admin" in request.form)
error_msg = None
change_kuerzel = False
change_email = False
change_password = False
change_beraet = False
change_is_admin = False
# Neues Kürzel, falls angegeben und nicht das aktuelle Kürzel
if new_kuerzel and new_kuerzel != lehrer.kuerzel:
change_kuerzel = True
# existiert das Kürzel bereits?
if Lehrer.query.filter_by(kuerzel=new_kuerzel).count() != 0:
error_msg = "Das angegebene Kürzel ist bereits registriert."
# Neue E-Mail-Adresse, falls angegeben und nicht die aktuelle Adresse
if new_email != lehrer.email:
change_email = True
# ist die neue E-Mail-Adresse syntaktisch ungültig?
if new_email is not None and not util.EMAIL_ADDRESS_REGEX.match(new_email):
error_msg = "Bitte geben Sie eine gültige E-Mail-Adresse ein."
# Neues Passwort, falls angegeben
if new_password:
change_password = True
# ist das neue Passwort zu groß?
if not util.validate_bcrypt_password(new_password):
error_msg = "Das neue Passwort darf höchstens 72 Zeichen lang sein."
if new_beraet_name == "":
new_beraet = None
else:
new_beraet = Stufe.query.filter_by(name=new_beraet_name).first()
if new_beraet is None:
abort(400)
return
if new_beraet != lehrer.beraet:
change_beraet = True
# Administratorstatus ändern
if new_is_admin != lehrer.is_admin:
change_is_admin = True
# Änderungen vornehmen, falls kein Fehler aufgetreten ist
if error_msg is not None:
# Es ist ein Fehler aufgetreten
flash(error_msg, "error")
return redirect(url_for(".edit", lehrer_id=lehrer_id), code=303)
if not (change_kuerzel or change_email or change_password or change_beraet or change_is_admin):
flash("Es wurde nichts geändert.", "error")
return redirect(url_for(".edit", lehrer_id=lehrer_id), code=303)
if change_kuerzel:
old_kuerzel = lehrer.kuerzel
lehrer.kuerzel = new_kuerzel
current_app.logger.info(f"{g.lehrer} hat das Lehrerkürzel des Kontos mit der ID {lehrer.id}"
f" von {old_kuerzel} auf {new_kuerzel} geändert.")
if change_email:
# E-Mail-Adresse wird als confirmed markiert, wenn ein Admin sie ändert
lehrer.email = new_email
lehrer.confirmation_token = None
lehrer.is_confirmed = True
current_app.logger.info(f"{g.lehrer} hat die E-Mail-Adresse von {lehrer} auf {new_email} gesetzt.")
if change_password:
lehrer.set_password(new_password)
current_app.logger.info(f"{g.lehrer} hat das Passwort von {lehrer} geändert.")
if change_beraet:
lehrer.beraet = new_beraet
if new_beraet:
current_app.logger.info(f"{g.lehrer} hat {lehrer} als Beratungslehrkraft für die {new_beraet.name} "
f"festgelegt.")
else:
current_app.logger.info(f"{g.lehrer} hat den Beratungslehrerstatus von {lehrer} entfernt.")
if change_is_admin:
lehrer.is_admin = new_is_admin
if new_is_admin:
current_app.logger.info(f"{g.lehrer} hat {lehrer} den Administratorstatus vergeben.")
else:
current_app.logger.info(f"{g.lehrer} hat {lehrer} den Administratorstatus entfernt.")
db.session.commit()
flash("Benutzerdaten erfolgreich geändert.", "success")
return redirect(url_for(".edit", lehrer_id=lehrer_id), code=303)
# Account löschen
elif action == "delete-account":
current_app.logger.info(f"{g.lehrer} hat das Konto {lehrer} gelöscht.")
db.session.delete(lehrer)
db.session.commit()
flash("Benutzerkonto erfolgreich gelöscht.", "success")
return redirect(url_for(".index"), code=303)
abort(400) # Bad Request, wenn ungültige action
@bp.route("/add", methods=("GET", "POST"))
@admin_required
def add():
""" Lehrerhinzufügung """
if request.method != "POST":
return render_template("admin/lehrer/add.html.j2")
# ELSE
kuerzel = request.form["kuerzel"]
password = request.form["password"]
force_pwd_change = ("force-password-change" in request.form)
error_msg = None
# existiert das Kürzel bereits?
if Lehrer.query.filter_by(kuerzel=kuerzel).count() != 0:
error_msg = "Ein Lehrerkonto mit diesem Kürzel existiert bereits."
# ist das neue Passwort zu groß?
elif not util.validate_bcrypt_password(password):
error_msg = "Das neue Passwort darf höchstens 72 Zeichen lang sein."
if error_msg:
flash(error_msg, "error")
return redirect(url_for(".add"), code=303)
new_lehrer = Lehrer(kuerzel=kuerzel)
new_lehrer.set_password(password, set_pwd_changed=not force_pwd_change)
db.session.add(new_lehrer)
db.session.commit()
flash("Lehrerkonto erfolgreich hinzugefügt.", "success")
current_app.logger.info(f"{g.lehrer} hat das Lehrerkonto {new_lehrer} hinzugefügt")
return redirect(url_for(".edit", lehrer_id=new_lehrer.id), code=303)