#!/usr/bin/env python3 import os from os import path from configparser import ConfigParser import bottle from bottle import get, post, static_file, request, route, template from bottle import SimpleTemplate import ldap @get('/') def get_index(): return index_tpl() @post('/') def post_index(): form = request.forms.getunicode def error(msg): return index_tpl(username=form('username'), alerts=[('error', msg)]) if form('new-password') != form('confirm-password'): return error("Password doesn't match the confirmation!") if len(form('new-password')) < 8: return error("Password must be at least 8 characters long!") try: ldap_change_password(form('username'), form('old-password'), form('new-password')) except Error as e: print("Unsuccessful attemp to change password for {}: {}" .format(form('username'), str(e))) return error(str(e)) print("Password successfully changed for: {}" .format(form('username'))) return index_tpl(alerts=[('success', "Password has been changed")]) @route('/static/', name='static') def serve_static(filename): return static_file(filename, root=path.join(BASE_DIR, 'static')) def index_tpl(**kwargs): return template('index', **kwargs) def ldap_change_password(username, old, new): dn_name = "uid={},{}".format(username, CONF['ldap']['base']) l = ldap.initialize(CONF['ldap']['host']) l.set_option(ldap.OPT_X_TLS_CACERTFILE, CONF['ldap']['tls_cacert']) l.set_option(ldap.OPT_X_TLS, ldap.OPT_X_TLS_DEMAND) l.start_tls_s() l.simple_bind_s(dn_name, old) l.passwd_s(dn_name, old, new) l.unbind_s() def read_config(): config = ConfigParser() config.read([path.join(BASE_DIR, 'settings.ini'), os.getenv('CONF_FILE', '')]) return config class Error(Exception): pass BASE_DIR = path.dirname(__file__) CONF = read_config() ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_NEVER) bottle.TEMPLATE_PATH = [BASE_DIR] # Set default attributes to pass into templates. SimpleTemplate.defaults = dict(CONF['html']) SimpleTemplate.defaults['url'] = bottle.url # Run bottle internal server when invoked directly (mainly for development). if __name__ == '__main__': bottle.run(**CONF['server']) # Run bottle in application mode (in production under uWSGI server). else: application = bottle.default_app()