summaryrefslogtreecommitdiffstats
path: root/accounts/views/default/__init__.py
blob: 1854c460c1ed7a664df574856d8376ca3ee94bdb (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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
# -*- coding: utf-8 -*-


from copy import deepcopy
from flask import Blueprint
from flask import current_app, redirect, render_template, request, g, \
     flash, url_for
from flask_login import login_required, login_user, logout_user, current_user
from werkzeug.exceptions import Forbidden

from accounts.forms import RegisterForm, RegisterCompleteForm, \
    LostPasswordForm, SettingsForm
from accounts.utils import templated
from accounts.utils.confirmation import Confirmation
from accounts.utils.login import logout_required
from accounts.models import Account


bp = Blueprint('default', __name__)


@bp.route('/register', methods=['GET', 'POST'])
@templated('register.html')
@logout_required
def register():
    form = RegisterForm()
    if form.validate_on_submit():
        current_app.mail_backend.send(form.mail.data, 'mail/register.txt',
                                      username=form.username.data)

        flash('Es wurde eine E-Mail an die angegebene Adresse geschickt, '
              'um diese zu überprüfen. Bitte folge den Anweisungen in der '
              'E-Mail.', 'success')

        return redirect(url_for('.index'))

    return {'form': form}


@bp.route('/register/<token>', methods=['GET', 'POST'])
@templated('register_complete.html')
@logout_required
def register_complete(token):
    #TODO: check for double uids and mail
    username, mail = Confirmation('register').loads_http(token, max_age=3*24*60*60)

    try:
        current_app.user_backend.get_by_uid(username)
        current_app.user_backend.get_by_mail(mail)
    except current_app.user_backend.NoSuchUserError:
        pass
    else:
        flash('Du hast den Benutzer bereits angelegt! Du kannst dich jetzt einfach einloggen:')
        return redirect(url_for('.index'))

    form = RegisterCompleteForm()
    if form.validate_on_submit():
        user = Account(username, mail, password=form.password.data)
        current_app.user_backend.register(user)
        login_user(user)

        current_app.mail_backend.send(
            current_app.config['MAIL_REGISTER_NOTIFY'],
            'mail/register_notify.txt',
            username=username, mail=mail)

        flash('Benutzer erfolgreich angelegt.', 'success')
        return redirect(url_for('.index'))

    return {
        'form': form,
        'token': token,
        'username': username,
        'mail': mail,
    }


@bp.route('/lost_password', methods=['GET', 'POST'])
@templated('lost_password.html')
@logout_required
def lost_password():
    form = LostPasswordForm()
    if form.validate_on_submit():
        #TODO: make the link only usable once (e.g include a hash of the old pw)
        # atm the only thing we do is make the link valid for only little time
        current_app.mail_backend.send(
            form.user.mail, 'mail/lost_password.txt', username=form.user.uid)

        flash('Wir haben dir eine E-Mail mit einem Link zum Passwort ändern '
              'geschickt. Bitte folge den Anweisungen in der E-Mail.', 'success')

        return redirect(url_for('.index'))

    return {'form': form}


@bp.route('/lost_password/<token>', methods=['GET', 'POST'])
@templated('lost_password_complete.html')
@logout_required
def lost_password_complete(token):
    (username,) = Confirmation('lost_password').loads_http(token, max_age=4*60*60)

    form = RegisterCompleteForm()
    if form.validate_on_submit():
        user = current_app.user_backend.get_by_uid(username)
        user.change_password(form.password.data)
        current_app.user_backend.update(user, as_admin=True)
        login_user(user)

        flash('Passwort geändert.', 'success')
        return redirect(url_for('.index'))

    return {
        'form': form,
        'token': token,
        'username': username,
    }


@bp.route('/', methods=['GET', 'POST'])
@templated('index.html')
@login_required
def index():
    form = SettingsForm(mail=current_user.mail)
    if form.validate_on_submit():
        changed = False

        if request.form.get('submit_services'):
            for service in current_app.all_services:
                field = form.get_servicedelete(service.id)
                if field.data:
                    current_user.reset_password(service.id)
                    changed = True

        elif request.form.get('submit_main'):
            if form.mail.data and form.mail.data != current_user.mail:
                current_app.mail_backend.send(
                    form.mail.data, 'mail/change_mail.txt',
                    username=current_user.uid)

                flash('Es wurde eine E-Mail an die angegebene Adresse geschickt, '
                      'um diese zu überprüfen. Bitte folge den Anweisungen in der '
                      'E-Mail.', 'success')
                changed = True

            if form.password.data:
                current_user.change_password(form.password.data, form.old_password.data)
                flash('Passwort geändert', 'success')
                changed = True

            for service in current_app.all_services:
                field = form.get_servicepassword(service.id)
                if field.data:
                    changed = True
                    current_user.change_password(field.data, None, service.id)

        if changed:
            current_app.user_backend.update(current_user)
            login_user(current_user)
            return redirect(url_for('.index'))
        else:
            flash('Nichts geändert.')


    services = deepcopy(current_app.all_services)
    for s in services:
        s.changed = s.id in current_user.services

    return {
        'form': form,
        'services': services,
    }


@bp.route('/change_mail/<token>')
@login_required
def change_mail(token):
    username, mail = Confirmation('change_mail').loads_http(token, max_age=3*24*60*60)

    if current_user.uid != username:
        raise Forbidden('Bitte logge dich als der Benutzer ein, dessen E-Mail-Adresse du ändern willst.')

    results = current_app.user_backend.find_by_mail(mail)
    for user in results:
        if user.uid != current_user.uid:
            raise Forbidden('Diese E-Mail-Adresse wird schon von einem anderen account benutzt!')

    current_user.change_email(mail)
    current_app.user_backend.update(current_user)

    flash('E-Mail-Adresse geändert.', 'success')
    return redirect(url_for('.index'))


@bp.route('/about')
@templated('about.html')
def about():
    return {
        'app': current_app,
    }


@bp.app_errorhandler(403)
@bp.app_errorhandler(404)
@bp.app_errorhandler(Exception)
def errorhandler(e):
    try:
        code = e.code
    except AttributeError:
        code = 500

    return render_template('error.html', error=e), code