src/templates/people/base.html \
src/templates/people/calls.html \
src/templates/people/index.html \
+ src/templates/people/passwd.html \
src/templates/people/registrations.html \
src/templates/people/search.html \
src/templates/people/user.html \
import PIL
import PIL.ImageOps
+import datetime
import io
import ldap
import ldap.modlist
def _set_string(self, key, value):
return self._set_strings(key, [value,])
+ def passwd(self, new_password):
+ """
+ Sets a new password
+ """
+ self.ldap.passwd_s(self.dn, None, new_password)
+
def check_password(self, password):
"""
Bind to the server with given credentials and return
Raises exceptions from the server on any other errors.
"""
-
logging.debug("Checking credentials for %s" % self.dn)
+
+ # Create a new LDAP connection
+ ldap_uri = self.backend.settings.get("ldap_uri")
+ conn = ldap.initialize(ldap_uri)
+
try:
- self.ldap.simple_bind_s(self.dn, password.encode("utf-8"))
+ conn.simple_bind_s(self.dn, password.encode("utf-8"))
except ldap.INVALID_CREDENTIALS:
- logging.debug("Account credentials are invalid.")
+ logging.debug("Account credentials are invalid for %s" % self)
return False
- logging.debug("Successfully authenticated.")
+ logging.info("Successfully authenticated %s" % self)
+
return True
def is_admin(self):
--- /dev/null
+{% extends "base.html" %}
+
+{% block title %}{{ _("Change Password for %s") % account }}{% end block %}
+
+{% block main %}
+ <div class="row justify-content-center">
+ <div class="col col-md-8">
+ <h4 class="mb-4">{{ _("Change Password for %s") % account }}</h4>
+
+ <form method="POST" action="">
+ {% raw xsrf_form_html() %}
+
+ <fieldset>
+ <div class="form-group">
+ <label>{{ _("New Password") }}</label>
+
+ <input type="password" class="form-control" name="password1"
+ placeholder="{{ _("New Password") }}">
+ </div>
+
+ <div class="form-group">
+ <input type="password" class="form-control" name="password2"
+ placeholder="{{ _("Repeat Password") }}">
+ </div>
+ </fieldset>
+
+ <div class="form-group">
+ <label>{{ _("Current Password") }}</label>
+
+ <input type="password" class="form-control" name="password"
+ placeholder="{{ _("Current Password") }}">
+ </div>
+
+ <input class="btn btn-primary btn-block" type="submit" value="{{ _("Change Password") }}">
+ </form>
+ </div>
+ </div>
+{% end block %}
(r"/users/(\w+)\.jpg", people.AvatarHandler),
(r"/users/(\w+)/calls(?:/(\d{4}-\d{2}-\d{2}))?", people.CallsHandler),
(r"/users/(\w+)/edit", people.UserEditHandler),
+ (r"/users/(\w+)/passwd", people.UserPasswdHandler),
(r"/users/(\w+)/registrations", people.RegistrationsHandler),
] + authentication_handlers)
self.redirect("/users/%s" % account.uid)
+class UserPasswdHandler(base.BaseHandler):
+ @tornado.web.authenticated
+ def get(self, uid):
+ account = self.backend.accounts.get_by_uid(uid)
+ if not account:
+ raise tornado.web.HTTPError(404, "Could not find account %s" % uid)
+
+ # Check for permissions
+ if not account.can_be_managed_by(self.current_user):
+ raise tornado.web.HTTPError(403, "%s cannot manage %s" % (self.current_user, account))
+
+ self.render("people/passwd.html", account=account)
+
+ @tornado.web.authenticated
+ def post(self, uid):
+ account = self.backend.accounts.get_by_uid(uid)
+ if not account:
+ raise tornado.web.HTTPError(404, "Could not find account %s" % uid)
+
+ # Check for permissions
+ if not account.can_be_managed_by(self.current_user):
+ raise tornado.web.HTTPError(403, "%s cannot manage %s" % (self.current_user, account))
+
+ # Get current password
+ password = self.get_argument("password")
+
+ # Get new password
+ password1 = self.get_argument("password1")
+ password2 = self.get_argument("password2")
+
+ # Passwords must match
+ if not password1 == password2:
+ raise tornado.web.HTTPError(400, "Passwords do not match")
+
+ # XXX Check password complexity
+
+ # Check if old password matches
+ if not account.check_password(password):
+ raise tornado.web.HTTPError(403, "Incorrect password for %s" % account)
+
+ # Save new password
+ account.passwd(password1)
+
+ # Redirect back to user's page
+ self.redirect("/users/%s" % account.uid)
+
+
class AccountsListModule(ui_modules.UIModule):
def render(self, accounts=None):
if accounts is None: