diff options
author | Alexander Sulfrian <alexander@sulfrian.net> | 2016-01-23 13:04:35 +0100 |
---|---|---|
committer | Alexander Sulfrian <alexander@sulfrian.net> | 2016-01-25 01:56:13 +0100 |
commit | 899947bd00df10cca15aca1b3c14125b38b35ecf (patch) | |
tree | cbe0cd8023efa657b478476a70f83d2f5cb5509b /accounts/__init__.py | |
parent | bd20d0ff1c7a582f3c53d30bfc387139c419ef35 (diff) | |
download | web-899947bd00df10cca15aca1b3c14125b38b35ecf.tar.gz web-899947bd00df10cca15aca1b3c14125b38b35ecf.tar.bz2 web-899947bd00df10cca15aca1b3c14125b38b35ecf.zip |
Moved everything into a package
Diffstat (limited to 'accounts/__init__.py')
-rw-r--r-- | accounts/__init__.py | 301 |
1 files changed, 301 insertions, 0 deletions
diff --git a/accounts/__init__.py b/accounts/__init__.py new file mode 100644 index 0000000..8fbcdd0 --- /dev/null +++ b/accounts/__init__.py @@ -0,0 +1,301 @@ +# -*- coding: utf-8 -*- + +import account +import ldap +import os +from copy import deepcopy +from flask import flash, Flask, g, redirect, request, session +from utils import * +from uuid import uuid4 + +from views import admin + +app = Flask(__name__) +app.register_blueprint(admin.bp, url_prefix='/admin') +app.config.from_object('accounts.default_settings') +if 'SPLINE_ACCOUNT_WEB_SETTINGS' in os.environ: + app.config.from_envvar('SPLINE_ACCOUNT_WEB_SETTINGS') + +app.all_services = account.SERVICES #TODO: take that from our json file or so +app.username_blacklist = list() + +@app.before_request +def session_permanent(): + if app.config.get('PERMANENT_SESSION_LIFETIME'): + session.permanent = True + else: + session.permanent = False + +@app.before_request +def ldap_connect(): + g.ldap = account.AccountService(app.config['LDAP_HOST'], app.config['LDAP_BASE_DN'], + app.config['LDAP_ADMIN_USER'], app.config['LDAP_ADMIN_PASS'], app.all_services) + +@app.before_request +def initialize_user(): + g.user = None + + if 'username' in session and 'password' in session: + username = ensure_utf8(session['username']) + password = ensure_utf8(decrypt_password(session['password'])) + try: + g.user = g.ldap.auth(username, password) + except ldap.INVALID_CREDENTIALS: + # we had crap in the session, delete it + logout_user() + +@app.before_first_request +def read_blacklist(): + if app.config.get('USERNAME_BLACKLIST_FILE'): + with open(app.config['USERNAME_BLACKLIST_FILE']) as f: + app.username_blacklist = f.read().split('\n') + +@app.context_processor +def template_default_context(): + return { + 'app': app + } + + +@app.route('/', methods=['GET', 'POST']) +@templated('index.html') +def index(): + if not g.user: + form = LoginForm(request.form, csrf_enabled=False) + if request.method == 'POST' and form.validate(): + if login_user(form.username.data, form.password.data): + flash(u'Erfolgreich eingeloggt', 'success') + return redirect(url_for('settings')) + else: + flash(u'Ungültiger Benutzername und/oder Passwort', 'error') + else: + return redirect(url_for('settings')) + + return {'form': form} + + +@app.route('/register', methods=['GET', 'POST']) +@templated('register.html') +@logout_required +def register(): + form = RegisterForm(request.form, csrf_enabled=False) + if request.method == 'POST' and form.validate(): + send_register_confirmation_mail(form.username.data, form.mail.data) + + flash(u'Es wurde eine E-Mail an die angegebene Adresse geschickt, ' + u'um diese zu überprüfen. Bitte folge den Anweisungen in der ' + u'E-Mail.', 'success') + + return redirect(url_for('index')) + + return {'form': form} + + +@app.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 = http_verify_confirmation('register', token.encode('ascii'), timeout=3*24*60*60) + + try: + g.ldap.get_by_uid(username) + g.ldap.get_by_mail(mail) + except account.NoSuchUserError: + pass + else: + flash(u'Du hast den Benutzer bereits angelegt! Du kannst dich jetzt einfach einloggen:') + return redirect(url_for('index')) + + form = RegisterCompleteForm(request.form, csrf_enabled=False) + if request.method == 'POST' and form.validate(): + password = form.password.data + + user = account.Account(username, mail, password=form.password.data) + g.ldap.register(user) + + # populate request context and session + assert login_user(user.uid, user.password) + + if app.config.get('MAIL_REGISTER_NOTIFY'): + send_mail( + app.config['MAIL_REGISTER_NOTIFY'], + u'[accounts] Neuer Benutzer %s erstellt' % username, + u'Benutzername: %s\nE-Mail: %s\n\nSpammer? Deaktivieren: ' + u'%s\n' % (username, mail, + url_for('admin_disable_account', uid=username, _external=True)) + ) + + flash(u'Benutzer erfolgreich angelegt.', 'success') + return redirect(url_for('settings')) + + return { + 'form': form, + 'token': token, + 'username': username, + 'mail': mail, + } + + +@app.route('/lost_password', methods=['GET', 'POST']) +@templated('lost_password.html') +@logout_required +def lost_password(): + form = LostPasswordForm(request.form, csrf_enabled=False) + if request.method == 'POST' and form.validate(): + #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 + confirm_token = make_confirmation('lost_password', (form.user.uid,)) + confirm_link = url_for('lost_password_complete', token=confirm_token, _external=True) + + body = render_template('mail/lost_password.txt', username=form.user.uid, + link=confirm_link) + + send_mail(form.user.attributes['mail'], u'Passwort vergessen', body, + sender=app.config.get('MAIL_CONFIRM_SENDER')) + + flash(u'Wir haben dir eine E-Mail mit einem Link zum Passwort ändern ' + u'geschickt. Bitte folge den Anweisungen in der E-Mail.', 'success') + + return redirect(url_for('index')) + + return {'form': form} + + +@app.route('/lost_password/<token>', methods=['GET', 'POST']) +@templated('lost_password_complete.html') +@logout_required +def lost_password_complete(token): + username, = http_verify_confirmation('lost_password', token.encode('ascii'), timeout=4*60*60) + + form = RegisterCompleteForm(request.form, csrf_enabled=False) + if request.method == 'POST' and form.validate(): + user = g.ldap.get_by_uid(username) + user.change_password(form.password.data) + g.ldap.update(user, as_admin=True) + + session['username'] = username + session['password'] = encrypt_password(form.password.data) + flash(u'Passwort geändert.', 'success') + + return redirect(url_for('settings')) + + return { + 'form': form, + 'token': token, + 'username': username, + } + + +@app.route('/settings', methods=['GET', 'POST']) +@templated('settings.html') +@login_required +def settings(): + form = SettingsForm(request.form, mail=g.user.attributes['mail']) + if request.method == 'POST' and form.validate(): + changed = False + + if request.form.get('submit_services'): + for service in app.all_services: + field = form.get_servicedelete(service.id) + if(field.data): + g.user.reset_password(service.id) + changed = True + + elif request.form.get('submit_main'): + if form.mail.data and form.mail.data != g.user.attributes['mail']: + confirm_token = make_confirmation('change_mail', (g.user.uid, form.mail.data)) + confirm_link = url_for('change_mail', token=confirm_token, _external=True) + + body = render_template('mail/change_mail.txt', username=g.user.uid, + mail=form.mail.data, link=confirm_link) + + send_mail(form.mail.data, u'E-Mail-Adresse bestätigen', body, + sender=app.config.get('MAIL_CONFIRM_SENDER')) + + flash(u'Es wurde eine E-Mail an die angegebene Adresse geschickt, ' + u'um diese zu überprüfen. Bitte folge den Anweisungen in der ' + u'E-Mail.', 'success') + changed = True + + if form.password.data: + g.user.change_password(form.password.data, form.old_password.data) + session['password'] = encrypt_password(form.password.data) + + flash(u'Passwort geändert', 'success') + changed = True + + for service in app.all_services: + field = form.get_servicepassword(service.id) + if field.data: + changed = True + g.user.change_password(field.data, None, service.id) + + if changed: + g.ldap.update(g.user, as_admin=True) #XXX: as_admin wieder wegmachen sobald ACLs richtig gesetzt sind + return redirect(url_for('settings')) + else: + flash(u'Nichts geändert.') + + + services = deepcopy(app.all_services) + for s in services: + s.changed = s.id in g.user.services + + return { + 'form': form, + 'services': services, + } + +@app.route('/settings/change_mail/<token>') +@login_required +def change_mail(token): + username, mail = http_verify_confirmation('change_mail', token.encode('ascii'), timeout=3*24*60*60) + + if g.user.uid != username: + raise Forbidden(u'Bitte logge dich als der Benutzer ein, dessen E-Mail-Adresse du ändern willst.') + + results = g.ldap.find_by_mail(mail) + for user in results: + if user.uid != g.user.uid: + raise Forbidden(u'Diese E-Mail-Adresse wird schon von einem anderen account benutzt!') + + g.user.change_email(mail) + g.ldap.update(g.user) + + flash(u'E-Mail-Adresse geändert.', 'success') + return redirect(url_for('settings')) + + +@app.route('/logout') +def logout(): + logout_user() + flash(u'Erfolgreich ausgeloggt.', 'success') + return redirect(url_for('index')) + + +@app.route('/about') +@templated('about.html') +def about(): + return {} + + +@app.errorhandler(403) +@app.errorhandler(404) +def errorhandler(e): + return render_template('error.html', error=e), e.code + + +@app.route('/debug') +def debug(): + raise Exception() + + +# we need the app to exist before initializing the forms +from forms import RegisterForm, RegisterCompleteForm, LoginForm, SettingsForm,\ + LostPasswordForm, AdminCreateAccountForm,\ + AdminDisableAccountForm + + +if __name__ == '__main__': + app.run() |