From a2ae24d0ae4cce1aaf3f1b39f735ea9b8ae035bc Mon Sep 17 00:00:00 2001 From: Patrick Mayr Date: Fri, 6 Jan 2023 16:03:33 +0000 Subject: [PATCH] add change password --- fet2020/authentications/authentications.py | 32 ++++++++++++++++--- fet2020/authentications/forms.py | 25 +++++++++++++-- fet2020/authentications/urls.py | 10 ++++++ fet2020/authentications/views.py | 15 +++++++-- .../authentications/change_password.html | 29 +++++++++++++++++ .../authentications/change_password_done.html | 15 +++++++++ 6 files changed, 117 insertions(+), 9 deletions(-) create mode 100644 fet2020/templates/authentications/change_password.html create mode 100644 fet2020/templates/authentications/change_password_done.html diff --git a/fet2020/authentications/authentications.py b/fet2020/authentications/authentications.py index 785dd028..6ec441f9 100644 --- a/fet2020/authentications/authentications.py +++ b/fet2020/authentications/authentications.py @@ -1,9 +1,12 @@ import logging -from ldap3 import Server, Connection +from ldap3 import Server, Connection, HASHED_SALTED_SHA, MODIFY_REPLACE from ldap3.core.exceptions import LDAPBindError +from ldap3.utils.hashed import hashed logger = logging.getLogger(__name__) +host = "ldap://juri.fet.htu.tuwien.ac.at" +port = 389 def authentication(username, password): @@ -11,8 +14,7 @@ def authentication(username, password): if password is None or password.strip() == "": return None - server_uri = "ldap://juri.fet.htu.tuwien.ac.at" - server = Server(server_uri, port=389, use_ssl=True) + server = Server(host, port=port, use_ssl=True) userdn = f"uid={username},ou=user,dc=fet,dc=htu,dc=tuwien,dc=ac,dc=at" try: @@ -21,9 +23,29 @@ def authentication(username, password): return username except LDAPBindError as e: - logger.info(f"LDAP Bind Error. Error: {e}") + logger.info(f"LDAP Bind error. Error: {e}") except Exception as e: - logger.info(f"Auth Exception. Error: {e}") + logger.info(f"Auth exception. Error: {e}") logger.info(f"This username has been typed: '{username}'") return None + + +def change_password(username, old_password, new_password): + server = Server(host, port=port, use_ssl=True) + userdn = f"uid={username},ou=user,dc=fet,dc=htu,dc=tuwien,dc=ac,dc=at" + + try: + c = Connection(server, user=userdn, password=old_password, auto_bind=True) + + hashed_password = hashed(HASHED_SALTED_SHA, new_password) + c.modify(userdn, {"userPassword": [(MODIFY_REPLACE, [hashed_password])]}) + + return username + + except LDAPBindError as e: + logger.info(f"LDAP Bind error. Error: {e}") + except Exception as e: + logger.info(f"Auth change-password exception. Error: {e}") + + return None diff --git a/fet2020/authentications/forms.py b/fet2020/authentications/forms.py index 2e87e7c4..c340a8d8 100644 --- a/fet2020/authentications/forms.py +++ b/fet2020/authentications/forms.py @@ -1,7 +1,8 @@ -from django.contrib.auth.forms import AuthenticationForm +from django.contrib.auth.forms import AuthenticationForm, PasswordChangeForm from django.contrib.auth.models import User +from django.core.validators import ValidationError -from .authentications import authentication +from .authentications import authentication, change_password class LoginForm(AuthenticationForm): @@ -26,3 +27,23 @@ class LoginForm(AuthenticationForm): self.confirm_login_allowed(self.user_cache) return self.cleaned_data + + +class LdapPasswordChangeForm(PasswordChangeForm): + def clean_old_password(self): + old_password = self.cleaned_data["old_password"] + if not authentication(self.user.username, old_password): + raise ValidationError( + self.error_messages["password_incorrect"], + code="password_incorrect", + ) + return old_password + + def clean(self): + old_password = self.cleaned_data["old_password"] + new_password = self.cleaned_data["new_password1"] + if not change_password(self.user, old_password, new_password): + raise ValidationError("Passwort im LDAP ändern funktioniert nicht.") + + def save(self): + return self.user diff --git a/fet2020/authentications/urls.py b/fet2020/authentications/urls.py index 723dd2d8..58b5496d 100644 --- a/fet2020/authentications/urls.py +++ b/fet2020/authentications/urls.py @@ -8,4 +8,14 @@ app_name = apps.AuthenticationsConfig.name urlpatterns = [ path("login/", views.AuthLoginView.as_view(), name="login"), path("logout/", views.logoutUser, name="logout"), + path( + "change-password/", + views.LdapPasswordChangeView.as_view(), + name="change-password", + ), + path( + "change-password/done/", + views.LdapPasswordChangeDoneView.as_view(), + name="password-change-done", + ), ] diff --git a/fet2020/authentications/views.py b/fet2020/authentications/views.py index 719e1c1a..e080158e 100644 --- a/fet2020/authentications/views.py +++ b/fet2020/authentications/views.py @@ -1,12 +1,13 @@ from django.contrib.auth import logout -from django.contrib.auth.views import LoginView +from django.contrib.auth.views import LoginView, PasswordChangeDoneView, PasswordChangeView from django.shortcuts import redirect from documents.etherpadlib import del_ep_cookie from .decorators import authenticated_user -from .forms import LoginForm +from .forms import LdapPasswordChangeForm, LoginForm +from django.urls import reverse_lazy, reverse class AuthLoginView(LoginView): authentication_form = LoginForm @@ -26,3 +27,13 @@ def logoutUser(request): response = del_ep_cookie(request, response) return response + + +class LdapPasswordChangeView(PasswordChangeView): + form_class = LdapPasswordChangeForm + success_url = reverse_lazy('authentications:password-change-done') + template_name = "authentications/change_password.html" + + +class LdapPasswordChangeDoneView(PasswordChangeDoneView): + template_name = "authentications/change_password_done.html" diff --git a/fet2020/templates/authentications/change_password.html b/fet2020/templates/authentications/change_password.html new file mode 100644 index 00000000..c4e816ff --- /dev/null +++ b/fet2020/templates/authentications/change_password.html @@ -0,0 +1,29 @@ +{% extends 'base.html' %} + +{% block title %}LDAP Passwort ändern{% endblock %} + +{% block content %} + +
+

LDAP Passwort ändern

+ +
+ Aus Sicherheitsgründen bitte zuerst das alte Passwort und darunter dann zweimal das neue Passwort eingeben, um sicherzustellen, dass es es korrekt eingegeben wurde. +
+ + +
+
+ {% csrf_token %} + + {% include "baseform/non_field_errors.html" %} + + {% include "baseform/password.html" with field=form.old_password %} + {% include "baseform/password.html" with field=form.new_password1 %} + {% include "baseform/password.html" with field=form.new_password2 %} + + +
+
+
+{% endblock %} diff --git a/fet2020/templates/authentications/change_password_done.html b/fet2020/templates/authentications/change_password_done.html new file mode 100644 index 00000000..fc349959 --- /dev/null +++ b/fet2020/templates/authentications/change_password_done.html @@ -0,0 +1,15 @@ +{% extends 'base.html' %} + +{% block title %}LDAP Passwort erfolgreich geändert{% endblock %} + +{% block content %} + +
+

LDAP Passwort erfolgreich geändert

+ +
+ Ihr Passwort wurde geändert. +
+ +
+{% endblock %}