Files
NateMan/nateman/commands.py
T
2021-08-10 17:53:30 +02:00

217 lines
6.2 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# NateMan Nachschreibtermin-Manager
# commands.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 <https://www.gnu.org/licenses/>.
"""
Enthält Befehle zur Verwendung im Terminal (Command Line Interface).
"""
import click
from flask.cli import with_appcontext
from . import emails, util
from .config_manager import config
from .models import Lehrer, Stufe, db, Session
@click.group()
def cli():
"""Enthält Befehle zur Steuerung der NateMan-Webanwendung."""
pass
@click.command("add-lehrer")
@click.argument("kuerzel", type=click.STRING)
@click.option("--password", type=click.STRING, default=None)
@click.option("--admin", is_flag=True)
@with_appcontext
def add_lehrer_command(kuerzel, password, admin):
"""Erstellt einen Lehreraccount."""
lehrer = Lehrer.query.filter_by(kuerzel=kuerzel).first()
if lehrer is not None:
click.echo("Fehler: Ein Lehrerkonto mit diesem Kürzel ist bereits registriert.", err=True)
return 1
if not password:
password = click.prompt("Neues Passwort eingeben (unsichtbar)", hide_input=True)
if not util.validate_bcrypt_password(password):
click.echo("Fehler: Das Passwort darf höchstens 72 Bytes groß sein.", err=True)
return 1
new_lehrer = Lehrer(kuerzel=kuerzel, is_admin=admin)
new_lehrer.set_password(password)
db.session.add(new_lehrer)
db.session.commit()
click.echo("Lehrerkonto wurde erfolgreich angelegt.")
return 0
@click.command("add-stufe")
@click.argument("names", type=click.STRING, nargs=-1)
@with_appcontext
def add_stufe_command(names):
"""Fügt eine neue Stufe zur Datenbank hinzu."""
if len(names) == 0:
click.echo("Fehler: Bitte geben Sie mindestens eine Stufe an.", err=True)
return 1
for name in names:
if util.is_integer_string(name):
click.echo(f"Fehler: Stufenname darf keine Ganzzahl sein.", err=True)
return 1
stufe = Stufe.query.filter_by(name=name).first()
if stufe is not None:
click.echo(f"Fehler: Die Stufe {name} existiert bereits.", err=True)
return 1
new_stufe = Stufe(name=name)
db.session.add(new_stufe)
db.session.commit()
click.echo("Die Stufe(n) wurde(n) erfolgreich hinzugefügt.")
return 0
@click.command("remove-stufe")
@click.argument("name", type=click.STRING)
@click.option("--yes", is_flag=True)
@with_appcontext
def remove_stufe_command(name, yes):
"""Entfernt eine Stufe und alle mit ihr verknüpften Daten von der Datenbank."""
stufe = Stufe.query.filter_by(name=name).first()
if stufe is None:
click.echo("Fehler: Diese Stufe existiert nicht.", err=True)
return 1
if not yes:
if not click.confirm(f"Durch diesen Vorgang werden alle mit der Stufe {stufe.name} verknüpften Daten gelöscht. "
f"Fortfahren?"):
click.echo("Vorgang abgebrochen.")
return 0
db.session.delete(stufe)
db.session.commit()
click.echo("Die Stufe wurde erfolgreich entfernt.")
return 0
@click.command("make-admin")
@click.argument("kuerzel")
@with_appcontext
def make_admin_command(kuerzel):
"""Gibt einem Lehrerkonto Administratorrechte."""
lehrer = Lehrer.query.filter_by(kuerzel=kuerzel).first()
if lehrer is None:
click.echo("Fehler: Das angegebene Kürzel ist nicht registriert.", err=True)
return 1
if lehrer.is_admin:
click.echo(kuerzel + " ist bereits Administrator.")
return 0
lehrer.is_admin = True
db.session.commit()
click.echo(kuerzel + " ist jetzt Administrator.")
return 0
@click.command("take-admin")
@click.argument("kuerzel")
@with_appcontext
def take_admin_command(kuerzel):
"""Nimmt einem Lehrerkonto seine Administratorrechte."""
lehrer = Lehrer.query.filter_by(kuerzel=kuerzel).first()
if lehrer is None:
click.echo("Fehler: Das angegebene Kürzel ist nicht registriert.", err=True)
return 1
if not lehrer.is_admin:
click.echo(kuerzel + " ist bereits kein Administrator.")
return 0
lehrer.is_admin = False
db.session.commit()
click.echo(kuerzel + " ist jetzt kein Administrator mehr.")
return 0
@click.command("cleanup")
@with_appcontext
def cleanup_command():
"""Entfernt abgelaufene Daten aus der NateMan-Datenbank."""
Session.cleanup()
Lehrer.password_reset_cleanup()
db.session.commit()
return 0
@click.command("send-reminder-mails")
@with_appcontext
def send_reminder_mails_command():
"""Sendet Erinnerungsemails an alle Lehrkräfte, die unbearbeitete vergangene Klausuren haben."""
emails.send_reminder_mails()
return 0
@click.command("apply-email-format")
@click.option("-f", "--format", "fmt", type=click.STRING, default=None)
@click.option("-o", "--override", is_flag=True)
@with_appcontext
def apply_email_format_command(fmt, override):
"""Wendet das E-Mail-Adressen-Format auf Lehrer an."""
fmt = fmt or config.get("email-address-format", None)
if fmt is None:
click.echo("Fehler: Ein Format ist weder konfiguriert, noch wurde eines angegeben.", err=True)
return 1
query = Lehrer.query if override else Lehrer.query.filter_by(email=None)
lehrer = query.all()
for l in lehrer:
l.set_default_email_address(fmt)
db.session.commit()
return 0
def init_commands():
cli.add_command(add_lehrer_command)
cli.add_command(make_admin_command)
cli.add_command(take_admin_command)
cli.add_command(add_stufe_command)
cli.add_command(remove_stufe_command)
cli.add_command(send_reminder_mails_command)
cli.add_command(apply_email_format_command)
cli.add_command(cleanup_command)
init_commands()