# -*- coding: utf-8 -*- import re from flask import url_for from flask_wtf import FlaskForm as Form from flask_login import current_user from wtforms import ( StringField, PasswordField, ValidationError, BooleanField, validators, ) from wtforms.form import FormMeta from markupsafe import Markup from .utils import NotRegexp from accounts.app import accounts_app USERNAME_RE = re.compile(r"^[a-zA-Z][a-zA-Z0-9-]{1,15}$") USERNAME_EXCLUDE_RE = re.compile(r"^(admin|root)") class RegisterForm(Form): username = StringField( "Benutzername", [ validators.Regexp( USERNAME_RE, message="Benutzername darf nur aus a-z, " "Zahlen und - bestehen (2-16 Zeichen, am Anfang nur a-z).", ), NotRegexp( USERNAME_EXCLUDE_RE, message="Dieser Benutzername ist nicht erlaubt.", ), ], ) mail = StringField( "E-Mail-Adresse", [validators.Email(), validators.Length(min=6, max=50)], ) question = StringField( "Hauptstadt von Deutschland?", [ validators.AnyOf( ("Berlin", "berlin"), message="Bitte beantworte die Frage." ) ], ) def validate_username(self, field): try: accounts_app.user_backend.get_by_uid(field.data) except accounts_app.user_backend.NoSuchUserError: if accounts_app.username_blacklist: if field.data.lower() in accounts_app.username_blacklist: raise ValidationError( Markup( "Dieser Benutzername ist momentan nicht erlaubt. " 'Weitere Informationen' % url_for("default.about") ) ) else: raise ValidationError("Dieser Benutzername ist schon vergeben.") def validate_mail(self, field): try: accounts_app.user_backend.get_by_mail(field.data) except accounts_app.user_backend.NoSuchUserError: pass else: raise ValidationError( Markup( "Ein Benutzername mit dieser Adresse existiert bereits. " "Falls du deinen Benutzernamen vergessen hast, kannst du " 'die Passwort-vergessen-Funktion benutzen.' % url_for("default.lost_password") ) ) class AdminCreateAccountForm(RegisterForm): def validate_username(self, field): try: accounts_app.user_backend.get_by_uid(field.data) except accounts_app.user_backend.NoSuchUserError: return else: raise ValidationError("Dieser Benutzername ist schon vergeben") question = None class RegisterCompleteForm(Form): password = PasswordField( "Passwort", [ validators.DataRequired(), validators.EqualTo( "password_confirm", message="Passwörter stimmen nicht überein" ), ], ) password_confirm = PasswordField("Passwort bestätigen") # n.b. this form is also used in lost_password_complete class LostPasswordForm(Form): username_or_mail = StringField("Benutzername oder E-Mail") user = None def validate_username_or_mail(self, field): if "@" not in field.data: try: self.user = accounts_app.user_backend.get_by_uid(field.data) except accounts_app.user_backend.NoSuchUserError: raise ValidationError( "Es gibt keinen Benutzer mit diesem Namen." ) else: try: self.user = accounts_app.user_backend.get_by_mail(field.data) except accounts_app.user_backend.NoSuchUserError: raise ValidationError( "Es gibt keinen Benutzer mit dieser Adresse." ) class SettingsMeta(FormMeta): def __call__(cls, *args, **kwargs): for service in accounts_app.all_services: setattr( cls, "password_%s" % service.id, PasswordField( "Passwort für %s" % service.name, [ validators.Optional(), validators.EqualTo( "password_confirm_%s" % service.id, message="Passwörter stimmen nicht überein", ), ], ), ) setattr( cls, "password_confirm_%s" % service.id, PasswordField("Passwort für %s (Bestätigung)" % service.name), ) setattr( cls, "delete_%s" % service.id, BooleanField("Passwort für %s löschen" % service.name), ) return super(SettingsMeta, cls).__call__(*args, **kwargs) class SettingsForm(Form, metaclass=SettingsMeta): old_password = PasswordField("Altes Passwort") password = PasswordField( "Neues Passwort", [ validators.Optional(), validators.EqualTo( "password_confirm", message="Passwörter stimmen nicht überein" ), ], ) password_confirm = PasswordField("Passwort bestätigen") mail = StringField( "E-Mail-Adresse", [ validators.Optional(), validators.Email(), validators.Length(min=6, max=50), ], ) def validate_old_password(self, field): if self.password.data: if not field.data: raise ValidationError( "Gib bitte dein altes Passwort ein, um ein neues zu setzen." ) if field.data != current_user.password: raise ValidationError("Altes Passwort ist falsch.") def validate_mail(self, field): results = accounts_app.user_backend.find_by_mail(field.data) for user in results: if user.uid != current_user.uid: raise ValidationError( "Diese E-Mail-Adresse wird schon von einem anderen Account benutzt!" ) def get_servicepassword(self, service_id: str): return getattr(self, "password_%s" % service_id) def get_servicepasswordconfirm(self, service_id: str): return getattr(self, "password_confirm_%s" % service_id) def get_servicedelete(self, service_id: str): return getattr(self, "delete_%s" % service_id) class AdminDisableAccountForm(Form): username = StringField("Benutzername") user = None def validate_username(self, field): try: self.user = accounts_app.user_backend.get_by_uid(field.data) except accounts_app.user_backend.NoSuchUserError: raise ValidationError("Dieser Benutzername existiert nicht")