From: Michael Tremer Date: Wed, 17 Oct 2018 00:51:29 +0000 (+0100) Subject: people: Allow users to change their own passwords X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=3ea97943cf4a60501246683735a6239df1cc1771;p=ipfire.org.git people: Allow users to change their own passwords Signed-off-by: Michael Tremer --- diff --git a/Makefile.am b/Makefile.am index 679d340f..1738171d 100644 --- a/Makefile.am +++ b/Makefile.am @@ -155,6 +155,7 @@ templates_people_DATA = \ 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 \ diff --git a/src/backend/accounts.py b/src/backend/accounts.py index a33063bc..6b8c1757 100644 --- a/src/backend/accounts.py +++ b/src/backend/accounts.py @@ -3,6 +3,7 @@ import PIL import PIL.ImageOps +import datetime import io import ldap import ldap.modlist @@ -245,6 +246,12 @@ class Account(Object): 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 @@ -252,15 +259,20 @@ class Account(Object): 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): diff --git a/src/templates/people/passwd.html b/src/templates/people/passwd.html new file mode 100644 index 00000000..43dec885 --- /dev/null +++ b/src/templates/people/passwd.html @@ -0,0 +1,38 @@ +{% extends "base.html" %} + +{% block title %}{{ _("Change Password for %s") % account }}{% end block %} + +{% block main %} +
+
+

{{ _("Change Password for %s") % account }}

+ +
+ {% raw xsrf_form_html() %} + +
+
+ + + +
+ +
+ +
+
+ +
+ + + +
+ + +
+
+
+{% end block %} diff --git a/src/web/__init__.py b/src/web/__init__.py index 717e6751..46c7fe57 100644 --- a/src/web/__init__.py +++ b/src/web/__init__.py @@ -256,6 +256,7 @@ class Application(tornado.web.Application): (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) diff --git a/src/web/people.py b/src/web/people.py index 303559f7..e54753d8 100644 --- a/src/web/people.py +++ b/src/web/people.py @@ -176,6 +176,53 @@ class UserEditHandler(base.BaseHandler): 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: