diff --git a/accounts/templates/accounts/change_password_form.html b/accounts/templates/accounts/change_password_form.html index 406fbab9..6d3f2dae 100644 --- a/accounts/templates/accounts/change_password_form.html +++ b/accounts/templates/accounts/change_password_form.html @@ -1,34 +1,39 @@ {% extends "base.html" %} - {% load django_bootstrap5 %} {% load i18n %} -{% load bootstrap_icons %} -{% block title %}{%trans "Change Password" %}{% endblock title %} +{% block title %}{% trans "Change Password" %}{% endblock title %} + +{% block page_heading %}{% trans "Change Password" %}{% endblock page_heading %} {% block content %} -
-
-
-
-

{%trans "Change Password" %}: {{ user }}

+{# a user changes their own password; one who must (a new or reset account) cannot go elsewhere first #} +
+ {% csrf_token %} + {% bootstrap_form_errors form type="non_fields" %} + +
+
+
+

{{ request.user.username }}

+

+ {% if must_change %}{% trans "Choose a new password before you go on." %}{% else %}{% trans "You stay signed in here; your other sessions end." %}{% endif %} +

-
- - {% csrf_token %} - {% bootstrap_form form layout='horizontal' horizontal_label_class='col-sm-4' horizontal_field_class='col-sm-8' horizontal_field_offset_class='offset-sm-4' %} - -
-
+ +
+ {% if not must_change %}{% trans "Cancel" %}{% endif %} +
-
-{% endblock content %} \ No newline at end of file + +{% endblock content %} diff --git a/accounts/tests/test_change_password_permission.py b/accounts/tests/test_change_password_permission.py index 01bb1d43..4c40279a 100644 --- a/accounts/tests/test_change_password_permission.py +++ b/accounts/tests/test_change_password_permission.py @@ -34,6 +34,19 @@ class ChangePasswordPermissionTestCase(TestCase): self.client.force_login(user) self.assertEqual(self.client.get(reverse("accounts:change_password")).status_code, 403) + def test_a_user_who_must_change_it_has_no_cancel(self): + from accounts.models import UserAttributes + + user = get_user_model().objects.create_user("forced", password="pw") + self.client.force_login(user) + page = self.client.get(reverse("accounts:change_password")) + self.assertContains(page, "your other sessions end") + self.assertContains(page, f'href="{reverse("accounts:profile")}">Cancel') + UserAttributes.objects.create(user=user, must_change_password=True) + page = self.client.get(reverse("accounts:change_password")) + self.assertContains(page, "Choose a new password before you go on.") + self.assertNotContains(page, f'href="{reverse("accounts:profile")}">Cancel') + def test_a_user_without_a_local_password_cannot_change_it(self): user = get_user_model().objects.create_user("ldap-user") # as django-auth-ldap makes them self.client.force_login(user) diff --git a/accounts/views.py b/accounts/views.py index d29571bb..52a29a02 100644 --- a/accounts/views.py +++ b/accounts/views.py @@ -212,7 +212,7 @@ def change_password(request): messages.success(request, _("Password Changed")) return redirect("accounts:profile") - return render(request, "accounts/change_password_form.html", {"form": form}) + return render(request, "accounts/change_password_form.html", {"form": form, "must_change": must_change}) @superuser_only diff --git a/admin/forms.py b/admin/forms.py index e5962a39..331a181d 100644 --- a/admin/forms.py +++ b/admin/forms.py @@ -232,6 +232,8 @@ class AdminPasswordForm(AdminPasswordChangeForm): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.fields["must_change_password"] = self.fields.pop("must_change_password") # last, after Django's own + # Django's "Password-based authentication: Enabled/Disabled", said as how the user signs in + self.fields["usable_password"].choices = [("true", _("With a password")), ("false", _("Without a password"))] def clean(self): cleaned = super().clean() diff --git a/admin/templates/admin/group_form.html b/admin/templates/admin/group_form.html index cb322ed6..2880d660 100644 --- a/admin/templates/admin/group_form.html +++ b/admin/templates/admin/group_form.html @@ -7,39 +7,30 @@ {% block page_heading %}{{ title }}{% endblock page_heading %} -{% block style %} - -{% endblock style %} - {% block content %}
{% csrf_token %} {% bootstrap_form_errors form type="non_fields" %} -
+

{% trans "Group" %}

{% trans "Users who share a set of permissions." %}

-
+
{% bootstrap_field form.name %}
-
+

{% trans "Permissions" %}

{% trans "Each member has these permissions besides their own." %}

-
+
{% for box, help in form.permission_rows %}
@@ -57,13 +48,13 @@
-
+

{% trans "Members" %}

{% trans "Who gets these permissions." %}

-
+
{% trans "Members" %} {# the members first, then everyone else; each by username #} @@ -77,7 +68,7 @@
-
+
{% trans "Cancel" %}
diff --git a/admin/templates/admin/user_form.html b/admin/templates/admin/user_form.html index 392420b4..fa467720 100644 --- a/admin/templates/admin/user_form.html +++ b/admin/templates/admin/user_form.html @@ -7,23 +7,13 @@ {% block page_heading %}{{ title }}{% endblock page_heading %} -{% block style %} - -{% endblock style %} - {% block content %} {# who the user is, what they manage, what they may use, then what more they may do #} {% csrf_token %} {% bootstrap_form_errors user_form type="non_fields" %} -
+

{% trans "Account" %}

@@ -33,7 +23,7 @@

{% trans "What the user signs in with." %}

{% endif %}
-
+
{% bootstrap_field user_form.username %}
@@ -61,20 +51,20 @@
-
+

{% trans "Role" %}

{% trans "What the user manages." %}

-
+
{% trans "Uses the VMs given to them, within their quota." as user_help %} {% trans "May change and delete the template VMs given to them." as editor_help %} {% trans "Manages the panel: every permission, no quota." as superuser_help %}
{% for choice in user_form.role %}
-