From 54ae41809e844009bbbc4977acdd086a6a60c00b Mon Sep 17 00:00:00 2001 From: Arthur Date: Mon, 26 Jun 2023 13:13:53 -0700 Subject: [PATCH] 12589 change password --- netbox/users/forms/model_forms.py | 14 ++++++--- netbox/users/urls.py | 1 + netbox/users/views.py | 47 +++++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+), 4 deletions(-) diff --git a/netbox/users/forms/model_forms.py b/netbox/users/forms/model_forms.py index 1a91a239f..f7f026bd6 100644 --- a/netbox/users/forms/model_forms.py +++ b/netbox/users/forms/model_forms.py @@ -1,10 +1,11 @@ from django import forms from django.conf import settings from django.contrib.auth import get_user_model -from django.contrib.auth.forms import AuthenticationForm, PasswordChangeForm as DjangoPasswordChangeForm +from django.contrib.auth.forms import AuthenticationForm, PasswordChangeForm as DjangoPasswordChangeForm, SetPasswordForm as DjangoPasswordSetForm from django.contrib.auth.models import Group from django.contrib.contenttypes.models import ContentType from django.contrib.postgres.forms import SimpleArrayField +from django.urls import reverse from django.utils.html import mark_safe from django.utils.translation import gettext as _ @@ -24,6 +25,7 @@ __all__ = ( 'LoginForm', 'ObjectPermissionForm', 'PasswordChangeForm', + 'PasswordSetForm', 'TokenForm', 'UserConfigForm', 'UserForm', @@ -38,6 +40,10 @@ class PasswordChangeForm(BootstrapMixin, DjangoPasswordChangeForm): pass +class PasswordSetForm(BootstrapMixin, DjangoPasswordSetForm): + pass + + class UserConfigFormMetaclass(forms.models.ModelFormMetaclass): def __new__(mcs, name, bases, attrs): @@ -192,9 +198,9 @@ class UserForm(BootstrapMixin, forms.ModelForm): self.fields['password'].help_text = _( "Raw passwords are not stored, so there is no way to see this " "user’s password, but you can change the password using " - 'this form.' - ) - + 'this form.' + ).format(url=reverse('users:change_user_password', args=[self.instance.pk])) + print(self.fields['password'].help_text) del self.fields['confirm_password'] def save(self, *args, **kwargs): diff --git a/netbox/users/urls.py b/netbox/users/urls.py index 6b13748ba..031c38c44 100644 --- a/netbox/users/urls.py +++ b/netbox/users/urls.py @@ -17,6 +17,7 @@ urlpatterns = [ path('users/edit/', views.NetBoxUserBulkEditView.as_view(), name='netboxuser_bulk_edit'), path('users/delete/', views.NetBoxUserBulkDeleteView.as_view(), name='netboxuser_bulk_delete'), path('users//', include(get_model_urls('users', 'netboxuser'))), + path('users/password//', views.NetBoxUserChangePasswordView.as_view(), name='change_user_password'), # Groups path('groups/', views.NetBoxGroupListView.as_view(), name='netboxgroup_list'), diff --git a/netbox/users/views.py b/netbox/users/views.py index 99feeef20..a316985e9 100644 --- a/netbox/users/views.py +++ b/netbox/users/views.py @@ -6,6 +6,7 @@ from django.contrib.auth import login as auth_login, logout as auth_logout, upda from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib.auth.models import Group, User, update_last_login from django.contrib.auth.signals import user_logged_in +from django.core.exceptions import ImproperlyConfigured from django.db.models import Count from django.http import HttpResponseRedirect from django.shortcuts import get_object_or_404, redirect, render, resolve_url @@ -397,6 +398,52 @@ class NetBoxUserBulkDeleteView(generic.BulkDeleteView): return get_permission_for_model(User, 'delete') +class NetBoxUserChangePasswordView(LoginRequiredMixin, View): + template_name = 'users/passworduser.html' + queryset = User.objects.all() + + def get_object(self, **kwargs): + """ + Return an object for editing. If no keyword arguments have been specified, this will be a new instance. + """ + if not kwargs: + # We're creating a new object + return self.queryset.model() + return get_object_or_404(self.queryset, **kwargs) + + def get(self, request, *args, **kwargs): + obj = self.get_object(**kwargs) + + # LDAP users cannot change their password here + if getattr(obj, 'ldap_username', None): + messages.warning(request, "LDAP-authenticated user credentials cannot be changed within NetBox.") + return redirect('users:netboxuser_list') + + form = forms.PasswordSetForm(user=obj) + + return render(request, self.template_name, { + 'form': form, + 'active_tab': 'password', + 'object': obj, + }) + + def post(self, request, *args, **kwargs): + obj = self.get_object(**kwargs) + + form = forms.PasswordSetForm(user=obj, data=request.POST) + if form.is_valid(): + form.save() + update_session_auth_hash(request, form.user) + messages.success(request, "The password has been changed successfully.") + return redirect('users:netboxuser_list') + + return render(request, self.template_name, { + 'form': form, + 'active_tab': 'password', + 'object': obj, + }) + + # # Groups #