diff options
-rw-r--r-- | account.py | 64 | ||||
-rw-r--r-- | app.py | 21 | ||||
-rw-r--r-- | templates/settings.html | 2 | ||||
-rw-r--r-- | utils.py | 14 |
4 files changed, 59 insertions, 42 deletions
@@ -6,7 +6,7 @@ LDAP_HOST = 'ldap://localhost:5678' LDAP_BASE_DN = 'dc=account,dc=spline,dc=inf,dc=fu-berlin,dc=de' LDAP_ADMIN_USER = 'admin' LDAP_ADMIN_PASS = 'admin' -SERVICES = ['foren','jabber''gitlab'] +SERVICES = ['foren','jabber', 'gitlab'] @@ -35,7 +35,7 @@ class AccountService: >> service.update(foo) # save changes in ldap backend # save changes in ldap backend as admin user >> service.update(foo, LDAP_ADMIN_USER, LDAP_ADMIN_PASS) - + * delete an account >> service = AccountService(LDAP_HOST, LDAP_BASE_DN,SERVICES) >> service.delete(Account) @@ -47,9 +47,11 @@ class AccountService: >> print([x.uid for x in all_accounts]) """ - def __init__(self, ldap_host, base_dn, services): + def __init__(self, ldap_host, base_dn, admin_user, admin_pass, services): self.ldap_host = ldap_host self.base_dn = base_dn + self.admin_user = admin_user + self.admin_pass = admin_pass self.services = services @@ -80,11 +82,11 @@ class AccountService: return acc - def find(self, admin_user, admin_pass, filterstr = '(objectClass=*)'): + def find(self, filterstr = '(objectClass=*)'): """ Find accounts with raw ldap filter syntax """ - self._bind('cn=%s,%s' % (admin_user, self.base_dn), admin_pass) + self._bind_as_admin() dn = 'ou=users,%s' % self.base_dn data = self.connection.search_s(dn,ldap.SCOPE_SUBTREE,filterstr) @@ -98,11 +100,11 @@ class AccountService: return accounts - def register(self, account, admin_user, admin_pass): + def register(self, account): """ Persists an account in the ldap backend """ - self._bind('cn=%s,%s' % (admin_user, self.base_dn), admin_pass) + self._bind_as_admin() dn = 'uid=%s,ou=users,%s' % (account.uid, self.base_dn) attr = [ @@ -118,19 +120,16 @@ class AccountService: self._unbind() - def update(self, account, admin_user = None, admin_pass = None): + def update(self, account, as_admin=False): """ Updates account informations like passwords or email. """ - user = 'uid=%s,ou=users' % account.uid - if admin_user: - user = 'cn=%s' % admin_user - - password = account.password - if admin_pass: - password = admin_pass - - self._bind('%s,%s' % (user, self.base_dn), password) + if as_admin: + self._bind_as_admin() + else: + user = 'uid=%s,ou=users' % account.uid + password = account.password + self._bind('%s,%s' % (user, self.base_dn), password) attr = [(ldap.MOD_REPLACE, 'mail', account.mail)] dn = 'uid=%s,ou=users,%s' % (account.uid, self.base_dn) @@ -144,18 +143,16 @@ class AccountService: """ Deletes an account permanently. """ - try: dn_user = account.dn - except: dn_user = 'uid=%s,ou=users,%s' % (account, self.base_dn) - user = dn_user - if admin_user: - user = 'cn=%s,%s' % (admin_user, self.base_dn) - - password = account.password - if admin_pass: - password = admin_pass + if as_admin: + self._bind_as_admin() + else: + try: dn_user = account.dn + except: dn_user = 'uid=%s,ou=users,%s' % (account, self.base_dn) + user = dn_user - self._bind(user, password) + password = account.password + self._bind('%s,%s' % (user, self.base_dn), password) dn = ['uid=%s,cn=%s,ou=services,%s' % (account.uid,s,self.base_dn) for s in account.services] dn.append(dn_user) @@ -171,6 +168,9 @@ class AccountService: self.connection.simple_bind_s(dn, password) + def _bind_as_admin(): + self._bind('cn=%s,%s' % (self.admin_user, self.base_dn), self.admin_pass) + def _unbind(self): self.connection.unbind_s() @@ -218,9 +218,9 @@ class Account: def change_password(self, new_password, service = None): """ - Changes a password for a given service. You have to use the Ldap class - to make the changes permanent. If no service is given, the root - password will be changed. + Changes a password for a given service. You have to use the + AccountService class to make the changes permanent. If no service is + given, the root password will be changed. """ if not service: self.new_password_root = new_password @@ -230,7 +230,7 @@ class Account: def change_email(self, new_mail): """ - Changes the mail address of an account. You have to use the Ldap class - to make changes permanent. + Changes the mail address of an account. You have to use the + AccountService class to make changes permanent. """ self.mail = new_mail @@ -3,8 +3,9 @@ import flaskext_compat flaskext_compat.activate() +import account import os -from flask import Flask, request, redirect, url_for, flash, session +from flask import flash, Flask, g, redirect, request, session, url_for from utils import templated, login_required, encrypt_password, decrypt_password, login_user, logout_user from forms import RegisterForm, LoginForm, SettingsForm @@ -14,6 +15,18 @@ app.config.from_object('default_settings') if 'SPLINE_ACCOUNT_WEB_SETTINGS' in os.environ: app.config.from_envvar('SPLINE_ACCOUNT_WEB_SETTINGS') +@app.before_request +def ldap_connect(): + g.ldap = account.AccountService(account.LDAP_HOST, account.LDAP_BASE_DN, + account.LDAP_ADMIN_USER, account.LDAP_ADMIN_PASS, account.SERVICES) + + if 'username' in session and 'password' in session: + try: + g.user = g.ldap.auth(session['username'], decrypt_password(session['password'])) + except ldap.INVALID_CREDENTIALS: + # we had crap in the session, delete it + logout_user() + @app.route('/', methods=['GET', 'POST']) @templated('index.html') @@ -21,8 +34,8 @@ def index(): form = LoginForm(request.form) if request.method == 'POST' and form.validate(): if login_user(form.username.data, form.password.data): - flash(u'Erfolgreich eingeloggt (%s)' % session['username']) - return redirect(url_for('index')) + flash(u'Erfolgreich eingeloggt (als %s)' % session['username']) + return redirect(url_for('settings')) else: flash(u'Ungültiger Benutzername und/oder Passwort', 'error') @@ -47,7 +60,7 @@ def register(): @templated('settings.html') @login_required def settings(): - form = SettingsForm(request.form, mail='mail aus ldap #TODO') + form = SettingsForm(request.form, mail=g.user.mail) if request.method == 'POST' and form.validate(): flash(u'Gespeichert. Nicht.') return redirect(url_for('index')) diff --git a/templates/settings.html b/templates/settings.html index addd137..de7f898 100644 --- a/templates/settings.html +++ b/templates/settings.html @@ -24,5 +24,7 @@ {%- else %} setzen {%- endif %} + </li> + {%- endfor %} </form> {%- endblock %} @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- +import ldap from functools import wraps -from flask import flash, request, redirect, render_template, session, url_for +from flask import flash, g, redirect, render_template, request, session, url_for from random import randint from Crypto.Cipher import AES from werkzeug.exceptions import Forbidden @@ -28,21 +29,21 @@ def templated(template=None): def login_required(f): @wraps(f) def login_required_(*args, **kwargs): - if 'username' not in session: + if not g.user: raise Forbidden return f(*args, **kwargs) return login_required_ def login_user(username, password): -# if not ldap_bind(): -# return False + try: + g.user = g.ldap.auth(username, password) + except ldap.INVALID_CREDENTIALS: + return False session['username'] = username session['password'] = encrypt_password(password) - #ldap_unbind() - return True @@ -74,5 +75,6 @@ def decrypt_password(ciphertext): return encryptor.decrypt(ciphertext[16:]).rstrip('\0') + # circular import from app import app |