# -*- 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.ext.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/', 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/', 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/') @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