]> git.ipfire.org Git - ipfire.org.git/commitdiff
people: Allow users to change their own passwords
authorMichael Tremer <michael.tremer@ipfire.org>
Wed, 17 Oct 2018 00:51:29 +0000 (01:51 +0100)
committerMichael Tremer <michael.tremer@ipfire.org>
Wed, 17 Oct 2018 00:51:29 +0000 (01:51 +0100)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
Makefile.am
src/backend/accounts.py
src/templates/people/passwd.html [new file with mode: 0644]
src/web/__init__.py
src/web/people.py

index 679d340f89ebb1ed284c68472b208b27e8135468..1738171dba03524aadc11700b24395f7c81d5604 100644 (file)
@@ -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 \
index a33063bcd775f1cb57e6a503355b488ef4e4de96..6b8c1757082667d7c075350db300c9f830e4da67 100644 (file)
@@ -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 (file)
index 0000000..43dec88
--- /dev/null
@@ -0,0 +1,38 @@
+{% 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 %}
index 717e67514fbe57feda13b2a5be48864b616fb093..46c7fe572fb833b79fd68b1470b77020371db9d9 100644 (file)
@@ -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)
 
index 303559f72529641a9bd91f1edd090b755f1ad490..e54753d805168d480fe5ce3dbffa88a1571c4ac3 100644 (file)
@@ -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: