summaryrefslogtreecommitdiffstats
path: root/accounts/forms.py
blob: b59ab6409886c13a4749738485e1c5c91baec22c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# -*- 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. '
                        '<a href="%s">Weitere Informationen</a>'
                        % 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 <a href="%s">Passwort-vergessen-Funktion</a> 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')