From c95a22a8460efcfcf0ab14f8ccf25bb9571e9a2e Mon Sep 17 00:00:00 2001 From: Katherine Domingo Date: Wed, 4 Mar 2026 14:48:04 +0800 Subject: [PATCH 01/21] Set package requirement versions the same as setup.py --- sandbox/requirements.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sandbox/requirements.txt b/sandbox/requirements.txt index aebb00e..010059c 100644 --- a/sandbox/requirements.txt +++ b/sandbox/requirements.txt @@ -1,4 +1,4 @@ -Django>=3.2 -wagtail>=4.1 -django-debug-toolbar==3.2.2 +Django>=5.2 +Wagtail>=7.0 +django-debug-toolbar==6.2.0 -e .[docs,test] From 75c3f86ecc4df57d540e5af0184a972d2ae6be11 Mon Sep 17 00:00:00 2001 From: Katherine Domingo Date: Wed, 4 Mar 2026 14:48:32 +0800 Subject: [PATCH 02/21] Run django-upgrade (target version 5.2) --- sandbox/sandbox/settings.py | 1 - sandbox/sandbox/urls.py | 9 +++++---- src/wagtail_2fa/wagtail_hooks.py | 18 +++++++++--------- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/sandbox/sandbox/settings.py b/sandbox/sandbox/settings.py index 5ce9f87..8289b02 100644 --- a/sandbox/sandbox/settings.py +++ b/sandbox/sandbox/settings.py @@ -119,7 +119,6 @@ USE_I18N = True -USE_L10N = True USE_TZ = True diff --git a/sandbox/sandbox/urls.py b/sandbox/sandbox/urls.py index 7439f5a..8553305 100644 --- a/sandbox/sandbox/urls.py +++ b/sandbox/sandbox/urls.py @@ -1,6 +1,7 @@ import debug_toolbar from django.conf import settings from django.contrib import admin +from django.urls import path from django.urls import include, re_path from wagtail import urls as wagtail_urls @@ -9,9 +10,9 @@ urlpatterns = [ re_path(r'^admin/', admin.site.urls), - re_path(r'^cms/', include(wagtailadmin_urls)), - re_path(r'^documents/', include(wagtaildocs_urls)), - re_path(r'', include(wagtail_urls)), + path('cms/', include(wagtailadmin_urls)), + path('documents/', include(wagtaildocs_urls)), + path('', include(wagtail_urls)), ] @@ -24,5 +25,5 @@ urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) urlpatterns = [ - re_path(r'^__debug__/', include(debug_toolbar.urls)), + path('__debug__/', include(debug_toolbar.urls)), ] + urlpatterns diff --git a/src/wagtail_2fa/wagtail_hooks.py b/src/wagtail_2fa/wagtail_hooks.py index 17284cf..680eabc 100644 --- a/src/wagtail_2fa/wagtail_hooks.py +++ b/src/wagtail_2fa/wagtail_hooks.py @@ -1,6 +1,6 @@ from django.conf import settings from django.contrib.auth.models import Permission -from django.urls import path, re_path, reverse +from django.urls import path, reverse from django.utils.translation import gettext_lazy as _ from wagtail import hooks @@ -16,8 +16,8 @@ def urlpatterns(): return [ path("2fa/auth", views.LoginView.as_view(), name="wagtail_2fa_auth"), - re_path( - r"^2fa/devices/(?P\d+)$", + path( + "2fa/devices/", views.DeviceListView.as_view(), name="wagtail_2fa_device_list", ), @@ -26,18 +26,18 @@ def urlpatterns(): views.DeviceCreateView.as_view(), name="wagtail_2fa_device_new", ), - re_path( - r"^2fa/devices/(?P\d+)/update$", + path( + "2fa/devices//update", views.DeviceUpdateView.as_view(), name="wagtail_2fa_device_update", ), - re_path( - r"^2fa/devices/(?P\d+)/remove$", + path( + "2fa/devices//remove", views.DeviceDeleteView.as_view(), name="wagtail_2fa_device_remove", ), - re_path( - r"^2fa/devices/qr-code$", + path( + "2fa/devices/qr-code", views.DeviceQRCodeView.as_view(), name="wagtail_2fa_device_qrcode", ), From c96d48be511f7004c1a42fe6be84e44e4892a4a2 Mon Sep 17 00:00:00 2001 From: Katherine Domingo Date: Wed, 4 Mar 2026 14:52:30 +0800 Subject: [PATCH 03/21] Update classifiers to be compatible with the requirement versions --- setup.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/setup.py b/setup.py index 37b8836..aec8f68 100644 --- a/setup.py +++ b/setup.py @@ -57,19 +57,18 @@ "Development Status :: 4 - Beta", "Environment :: Web Environment", "Framework :: Django", - "Framework :: Django :: 3.2", - "Framework :: Django :: 4.1", - "Framework :: Django :: 4.2", + "Framework :: Django :: 5.2", "Framework :: Wagtail", - "Framework :: Wagtail :: 2", - "Framework :: Wagtail :: 3", - "Framework :: Wagtail :: 4", + "Framework :: Wagtail :: 7", "License :: OSI Approved :: MIT License", "Programming Language :: Python", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", ], zip_safe=False, ) From 9c8d21c2c21713121877b437684b042b739161d7 Mon Sep 17 00:00:00 2001 From: Katherine Domingo Date: Wed, 4 Mar 2026 14:56:09 +0800 Subject: [PATCH 04/21] Update test matrix on tox.ini --- tox.ini | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index 53f6768..94ae607 100644 --- a/tox.ini +++ b/tox.ini @@ -1,6 +1,7 @@ [tox] envlist = - python{3.13,3.14}-django{5.2}-wagtail{7.0} + python{3.13}-django{5.2}-wagtail{7.0,7.1,7.2,7.3}, + python{3.14}-django{5.2}-wagtail{7.2,7.3}, [gh-actions] python = @@ -17,6 +18,9 @@ basepython = deps = django5.2: Django>=5.2,<6.0 wagtail7.0: wagtail>=7.0,<7.1 + wagtail7.1: wagtail>=7.1,<7.2 + wagtail7.2: wagtail>=7.2,<7.3 + wagtail7.3: wagtail>=7.3,<7.4 extras = test From f0d1871361510e7f5a8c9c4a6255608ce75fa6dc Mon Sep 17 00:00:00 2001 From: Katherine Domingo Date: Wed, 4 Mar 2026 15:00:53 +0800 Subject: [PATCH 05/21] Wagtail 5.0: Progress button-longrunning now relies on data attributes - The `button-longrunning` class usage has been updated to use the newly adopted Stimulus approach --- src/wagtail_2fa/templates/wagtail_2fa/legacy/otp_form.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wagtail_2fa/templates/wagtail_2fa/legacy/otp_form.html b/src/wagtail_2fa/templates/wagtail_2fa/legacy/otp_form.html index 05b3dd1..1241add 100644 --- a/src/wagtail_2fa/templates/wagtail_2fa/legacy/otp_form.html +++ b/src/wagtail_2fa/templates/wagtail_2fa/legacy/otp_form.html @@ -43,7 +43,7 @@

{% block branding_login %}{% trans "Enter your two-factor authentication cod {% endblock %}
{% block submit_buttons %} - + {% trans 'Sign out' %} From 5bd447efa34571a72eecf659d56f3dc12dd5428e Mon Sep 17 00:00:00 2001 From: Katherine Domingo Date: Wed, 4 Mar 2026 15:08:05 +0800 Subject: [PATCH 06/21] Update logo to the latest version --- src/wagtail_2fa/templates/wagtail_2fa/legacy/otp_form.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wagtail_2fa/templates/wagtail_2fa/legacy/otp_form.html b/src/wagtail_2fa/templates/wagtail_2fa/legacy/otp_form.html index 1241add..4699b9c 100644 --- a/src/wagtail_2fa/templates/wagtail_2fa/legacy/otp_form.html +++ b/src/wagtail_2fa/templates/wagtail_2fa/legacy/otp_form.html @@ -55,7 +55,7 @@

{% block branding_login %}{% trans "Enter your two-factor authentication cod {% block branding_logo %} {% endblock %} From ba35f5c7f69788b287f85119d9767fed263745c2 Mon Sep 17 00:00:00 2001 From: Katherine Domingo Date: Wed, 4 Mar 2026 15:17:23 +0800 Subject: [PATCH 07/21] Wagtail 6.0: Introduce an internal {% formattedfield %} tag to replace direct use of wagtailadmin/shared/field.html --- src/wagtail_2fa/templates/wagtail_2fa/legacy/otp_form.html | 4 ++-- src/wagtail_2fa/templates/wagtail_2fa/otp_form.html | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/wagtail_2fa/templates/wagtail_2fa/legacy/otp_form.html b/src/wagtail_2fa/templates/wagtail_2fa/legacy/otp_form.html index 4699b9c..4473e46 100644 --- a/src/wagtail_2fa/templates/wagtail_2fa/legacy/otp_form.html +++ b/src/wagtail_2fa/templates/wagtail_2fa/legacy/otp_form.html @@ -31,11 +31,11 @@

{% block branding_login %}{% trans "Enter your two-factor authentication cod {% block fields %} - {% field field=form.otp_token %}{% endfield %} + {% formattedfield form.otp_token %} {% block extra_fields %} {% for field_name, field in form.extra_fields %} - {% field field=field %}{% endfield %} + {% formattedfield field %} {% endfor %} {% endblock extra_fields %} diff --git a/src/wagtail_2fa/templates/wagtail_2fa/otp_form.html b/src/wagtail_2fa/templates/wagtail_2fa/otp_form.html index 4186232..03a5da1 100644 --- a/src/wagtail_2fa/templates/wagtail_2fa/otp_form.html +++ b/src/wagtail_2fa/templates/wagtail_2fa/otp_form.html @@ -31,11 +31,11 @@

{% block branding_login %}{% trans "Enter your two-factor authentication cod {% block fields %} - {% field field=form.otp_token %}{% endfield %} + {% formattedfield form.otp_token %} {% block extra_fields %} {% for field_name, field in form.extra_fields %} - {% field field=field %}{% endfield %} + {% formattedfield field %} {% endfor %} {% endblock extra_fields %} From 678489f918d1220500f1a3e44fa6ae7864793a20 Mon Sep 17 00:00:00 2001 From: Katherine Domingo Date: Wed, 4 Mar 2026 15:23:00 +0800 Subject: [PATCH 08/21] Fix missing icon --- src/wagtail_2fa/templates/wagtail_2fa/device_list.html | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/wagtail_2fa/templates/wagtail_2fa/device_list.html b/src/wagtail_2fa/templates/wagtail_2fa/device_list.html index 918812e..ada83a0 100644 --- a/src/wagtail_2fa/templates/wagtail_2fa/device_list.html +++ b/src/wagtail_2fa/templates/wagtail_2fa/device_list.html @@ -46,7 +46,10 @@

{# Users can only add devices to their own account #} {% if user_id == request.user.id %} - {% trans 'New device' %} + + + {% trans 'New device' %} + {% endif %} {% endblock %} From 9336a976055ef9e14ad6ea5b5d173f0cf7eadae0 Mon Sep 17 00:00:00 2001 From: Katherine Domingo Date: Wed, 4 Mar 2026 15:53:53 +0800 Subject: [PATCH 09/21] Update otp_form.html, Django 5.0: Support for logging out via GET requests in the django.contrib.auth.views.LogoutView and django.contrib.auth.views.logout_then_login() is removed --- src/wagtail_2fa/templates/wagtail_2fa/otp_form.html | 6 ++++-- src/wagtail_2fa/views.py | 9 +-------- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/src/wagtail_2fa/templates/wagtail_2fa/otp_form.html b/src/wagtail_2fa/templates/wagtail_2fa/otp_form.html index 03a5da1..1cd69da 100644 --- a/src/wagtail_2fa/templates/wagtail_2fa/otp_form.html +++ b/src/wagtail_2fa/templates/wagtail_2fa/otp_form.html @@ -1,4 +1,4 @@ -{% extends "wagtailadmin/admin_base.html" %} +{% extends "wagtailadmin/base.html" %} {% load i18n wagtailadmin_tags %} {% block titletag %}{% trans "Sign in" %}{% endblock %} {% block bodyclass %}login{% endblock %} @@ -45,7 +45,9 @@

{% block branding_login %}{% trans "Enter your two-factor authentication cod {% block submit_buttons %} - {% trans 'Sign out' %} + {% endblock %}

diff --git a/src/wagtail_2fa/views.py b/src/wagtail_2fa/views.py index ef0b348..e59db1b 100644 --- a/src/wagtail_2fa/views.py +++ b/src/wagtail_2fa/views.py @@ -30,14 +30,7 @@ class LoginView(RedirectURLMixin, FormView): - - if WAGTAIL_VERSION >= (6, 0): - template_name = "wagtail_2fa/otp_form_v6.html" - elif WAGTAIL_VERSION < (6, 0) and WAGTAIL_VERSION >= (5, 0): - template_name = "wagtail_2fa/otp_form.html" - else: - template_name = "wagtail_2fa/legacy/otp_form.html" - + template_name = "wagtail_2fa/otp_form.html" form_class = forms.TokenForm redirect_field_name = REDIRECT_FIELD_NAME From ec0e31d144b3968e96515f7cccebb12c9cdbc417 Mon Sep 17 00:00:00 2001 From: Katherine Domingo Date: Wed, 4 Mar 2026 16:00:36 +0800 Subject: [PATCH 10/21] Wagtail 7.1: Deprecation of UserListingButton --- src/wagtail_2fa/wagtail_hooks.py | 38 +++++++++++++------------------- 1 file changed, 15 insertions(+), 23 deletions(-) diff --git a/src/wagtail_2fa/wagtail_hooks.py b/src/wagtail_2fa/wagtail_hooks.py index 680eabc..d475bb4 100644 --- a/src/wagtail_2fa/wagtail_hooks.py +++ b/src/wagtail_2fa/wagtail_hooks.py @@ -3,13 +3,16 @@ from django.urls import path, reverse from django.utils.translation import gettext_lazy as _ -from wagtail import hooks +from wagtail import hooks, VERSION as WAGTAIL_VERSION from wagtail.admin.menu import MenuItem -from wagtail.users.widgets import UserListingButton -from wagtail_2fa import views +if WAGTAIL_VERSION >= (7, 1): + from wagtail.admin.widgets import ListingButton +else: + from wagtail.users.widgets import UserListingButton as ListingButton -from wagtail import VERSION as WAGTAIL_VERSION + +from wagtail_2fa import views @hooks.register("register_admin_urls") @@ -70,25 +73,14 @@ def register(request): } -if WAGTAIL_VERSION >= (6, 0): - @hooks.register("register_user_listing_buttons") - def register_user_listing_buttons(user, request_user): - yield UserListingButton( - _("Manage 2FA"), - reverse("wagtail_2fa_device_list", kwargs={"user_id": user.id}), - attrs={"title": _("Edit this user")}, - priority=100, - ) -else: - @hooks.register("register_user_listing_buttons") - def register_user_listing_buttons(context, user): - yield UserListingButton( - _("Manage 2FA"), - reverse("wagtail_2fa_device_list", kwargs={"user_id": user.id}), - attrs={"title": _("Edit this user")}, - priority=100, - ) - +@hooks.register("register_user_listing_buttons") +def register_user_listing_buttons(user, request_user): + yield ListingButton( + _("Manage 2FA"), + reverse("wagtail_2fa_device_list", kwargs={"user_id": user.id}), + attrs={"title": _("Edit this user")}, + priority=100, + ) @hooks.register("register_permissions") From 416abe2f2f540bb1affc739f60b387a4b2371457 Mon Sep 17 00:00:00 2001 From: Katherine Domingo Date: Wed, 4 Mar 2026 16:03:07 +0800 Subject: [PATCH 11/21] Remove legacy and unused otp form templates --- .../wagtail_2fa/legacy/otp_form.html | 62 ----------------- .../templates/wagtail_2fa/otp_form_v6.html | 66 ------------------- 2 files changed, 128 deletions(-) delete mode 100644 src/wagtail_2fa/templates/wagtail_2fa/legacy/otp_form.html delete mode 100644 src/wagtail_2fa/templates/wagtail_2fa/otp_form_v6.html diff --git a/src/wagtail_2fa/templates/wagtail_2fa/legacy/otp_form.html b/src/wagtail_2fa/templates/wagtail_2fa/legacy/otp_form.html deleted file mode 100644 index 4473e46..0000000 --- a/src/wagtail_2fa/templates/wagtail_2fa/legacy/otp_form.html +++ /dev/null @@ -1,62 +0,0 @@ -{% extends "wagtailadmin/admin_base.html" %} -{% load i18n wagtailadmin_tags %} -{% block titletag %}{% trans "Sign in" %}{% endblock %} -{% block bodyclass %}login{% endblock %} - -{% block furniture %} -
-

{% block branding_login %}{% trans "Enter your two-factor authentication code" %}{% endblock %}

- -
- {# Always show messages div so it can be appended to by JS #} - {% if messages or form.errors %} -
    - {% if form.errors %} -
  • {% blocktrans %}Invalid code{% endblocktrans %}
  • - {% endif %} - {% for message in messages %} -
  • {{ message }}
  • - {% endfor %} -
- {% endif %} -
- - {% block above_login %}{% endblock %} - -
- {% block login_form %} - {% csrf_token %} - - {% url 'wagtailadmin_home' as home_url %} - - - {% block fields %} - {% formattedfield form.otp_token %} - - {% block extra_fields %} - {% for field_name, field in form.extra_fields %} - {% formattedfield field %} - {% endfor %} - {% endblock extra_fields %} - - {% endblock %} - {% endblock %} -
- {% block submit_buttons %} - - - {% trans 'Sign out' %} - - {% endblock %} -
-
- - {% block below_login %}{% endblock %} - - {% block branding_logo %} - - {% endblock %} -
-{% endblock %} diff --git a/src/wagtail_2fa/templates/wagtail_2fa/otp_form_v6.html b/src/wagtail_2fa/templates/wagtail_2fa/otp_form_v6.html deleted file mode 100644 index d114d95..0000000 --- a/src/wagtail_2fa/templates/wagtail_2fa/otp_form_v6.html +++ /dev/null @@ -1,66 +0,0 @@ -{% extends "wagtailadmin/base.html" %} -{% load i18n wagtailadmin_tags %} -{% block titletag %}{% trans "Sign in" %}{% endblock %} -{% block bodyclass %}login{% endblock %} - -{% block furniture %} -
-

{% block branding_login %}{% trans "Enter your two-factor authentication code" %}{% endblock %}

- -
- {# Always show messages div so it can be appended to by JS #} - {% if messages or form.errors %} -
    - {% if form.errors %} -
  • {% blocktrans %}Invalid code{% endblocktrans %}
  • - {% endif %} - {% for message in messages %} -
  • {{ message }}
  • - {% endfor %} -
- {% endif %} -
- - {% block above_login %}{% endblock %} - -
- {% block login_form %} - {% csrf_token %} - - {% url 'wagtailadmin_home' as home_url %} - - - {% block fields %} - {% formattedfield field=form.otp_token %} - {% block extra_fields %} - {% for field_name, field in form.extra_fields %} - {% formattedfield field=field %} - {% endfor %} - {% endblock extra_fields %} - {% endblock %} - {% endblock %} -
- {% block submit_buttons %} - - - - - - {% endblock %} -
-
- - {% block below_login %}{% endblock %} - - {% block branding_logo %} - - {% endblock %} - - -
-{% endblock %} \ No newline at end of file From b9b5b81e22206106a5dbba0b3323853e2ff64403 Mon Sep 17 00:00:00 2001 From: Katherine Domingo Date: Wed, 4 Mar 2026 16:16:38 +0800 Subject: [PATCH 12/21] Switch button type to make it appear under the more menu --- src/wagtail_2fa/wagtail_hooks.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/wagtail_2fa/wagtail_hooks.py b/src/wagtail_2fa/wagtail_hooks.py index d475bb4..9401ccc 100644 --- a/src/wagtail_2fa/wagtail_hooks.py +++ b/src/wagtail_2fa/wagtail_hooks.py @@ -7,9 +7,9 @@ from wagtail.admin.menu import MenuItem if WAGTAIL_VERSION >= (7, 1): - from wagtail.admin.widgets import ListingButton + from wagtail.admin.widgets import Button else: - from wagtail.users.widgets import UserListingButton as ListingButton + from wagtail.users.widgets import UserListingButton as Button from wagtail_2fa import views @@ -75,7 +75,7 @@ def register(request): @hooks.register("register_user_listing_buttons") def register_user_listing_buttons(user, request_user): - yield ListingButton( + yield Button( _("Manage 2FA"), reverse("wagtail_2fa_device_list", kwargs={"user_id": user.id}), attrs={"title": _("Edit this user")}, From b8d89c215bc9e144f068075392c4914949d5f994 Mon Sep 17 00:00:00 2001 From: Katherine Domingo Date: Wed, 4 Mar 2026 16:25:22 +0800 Subject: [PATCH 13/21] Update CHANGES --- CHANGES | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGES b/CHANGES index 7dc216c..fe48d46 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,9 @@ +Unreleased +================== + - Add testing for Python 3.14, Wagtail 7.2, and Wagtail 7.3 + - Update dependencies to latest versions + + 1.8.0 (2026-02-05) ================== - bump required version of django-otp and update middleware From d2c5f94b980c854b59f86714de96e84830435bf7 Mon Sep 17 00:00:00 2001 From: Katherine Domingo Date: Wed, 4 Mar 2026 16:29:45 +0800 Subject: [PATCH 14/21] Update package versions on dependabot.yml --- .github/dependabot.yml | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 5f4d7c7..f8433e0 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -9,20 +9,19 @@ updates: ignore: - dependency-name: flake8 versions: - - 3.8.4 - - 3.9.0 + - 7.3.0 - dependency-name: coverage versions: - - "5.4" + - "7.13.4" - dependency-name: pytest versions: - - 6.2.2 + - 9.0.2 - dependency-name: isort versions: - - 5.7.0 + - 8.0.1 - dependency-name: django-debug-toolbar versions: - - "3.2" + - "6.2.0" - dependency-name: pytest-django versions: - - 4.1.0 + - 4.12.0 From d1be0bacd5480b366b9a39fb34b11eaecc1efd92 Mon Sep 17 00:00:00 2001 From: Katherine Domingo Date: Wed, 4 Mar 2026 19:37:13 +0800 Subject: [PATCH 15/21] Make allowed URL names configurable through WAGTAIL_2FA_ALLOWED_URL_NAMES --- src/wagtail_2fa/middleware.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/wagtail_2fa/middleware.py b/src/wagtail_2fa/middleware.py index 9773a78..f506190 100644 --- a/src/wagtail_2fa/middleware.py +++ b/src/wagtail_2fa/middleware.py @@ -17,6 +17,10 @@ class VerifyUserMiddleware(_OTPMiddleware): "wagtailadmin_sprite", ] + def get_allowed_url_names(self): + extra = getattr(settings, "WAGTAIL_2FA_ALLOWED_URL_NAMES", []) + return self._allowed_url_names + list(extra) + # These URLs do not require verification if the user has no devices _allowed_url_names_no_device = [ "wagtail_2fa_device_list", @@ -75,7 +79,7 @@ def _require_verified_user(self, request): # Don't require verification for specified URL names request_url_name = resolve(request.path_info).url_name - if request_url_name in self._allowed_url_names: + if request_url_name in self.get_allowed_url_names(): return False # If the user does not have a device, don't require verification From 6d2a41b2454b69c3fb43dedbb18f383afaaad99b Mon Sep 17 00:00:00 2001 From: nickmoreton Date: Thu, 16 Apr 2026 15:06:03 +0100 Subject: [PATCH 16/21] Remove Python 3.8 and 3.9 from classifiers --- setup.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/setup.py b/setup.py index aec8f68..292bb94 100644 --- a/setup.py +++ b/setup.py @@ -62,8 +62,6 @@ "Framework :: Wagtail :: 7", "License :: OSI Approved :: MIT License", "Programming Language :: Python", - "Programming Language :: Python :: 3.8", - "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", From 1517ab30d45f2f506ec521f9dd7784086426ef6f Mon Sep 17 00:00:00 2001 From: nickmoreton Date: Thu, 28 May 2026 17:19:45 +0100 Subject: [PATCH 17/21] Add Wagtail 7.4 + Django 6.0 support and expand test matrix - Declare Django>=5.2,<7 and Wagtail>=7.0,<8 (adds Wagtail 7.4 LTS and Django 6.0). - Expand tox matrix to cover Python 3.10/3.11/3.12 (previously claimed in classifiers but never exercised) and Django 6.0 on 3.13/3.14. - Remove unused six install dep and dead Django<4.1 RedirectURLMixin guard. - Note dropped users (Wagtail 7.0 + Django 4.2) in CHANGES; fix Python 3.8 reference in README sandbox section. Co-Authored-By: Claude Opus 4.7 (1M context) --- CHANGES | 11 +++++++++++ README.rst | 4 ++-- setup.py | 6 +++--- src/wagtail_2fa/views.py | 10 +--------- tox.ini | 13 +++++++++++-- 5 files changed, 28 insertions(+), 16 deletions(-) diff --git a/CHANGES b/CHANGES index fe48d46..c5c7e91 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,17 @@ Unreleased ================== - Add testing for Python 3.14, Wagtail 7.2, and Wagtail 7.3 + - Add support for Wagtail 7.4 (LTS) and Django 6.0 + - Expand test matrix to cover Python 3.10, 3.11, and 3.12 (previously + declared in classifiers but not exercised in tox) + - Declare upper bounds: ``Django>=5.2,<7`` and ``Wagtail>=7.0,<8``. + Users on Wagtail 7.0 with Django 4.2 should remain on ``wagtail-2fa + 1.8.x``; this release requires Django 5.2 or newer + - Remove vestigial ``six`` install dependency (unused since the Python 2 + compatibility shim was dropped) + - Remove dead ``DJANGO_VERSION`` import guard in ``views.py`` (the + ``Django < 4.1`` branch is unreachable now that ``Django>=5.2`` is + required) - Update dependencies to latest versions diff --git a/README.rst b/README.rst index fa22f84..6b65108 100644 --- a/README.rst +++ b/README.rst @@ -114,8 +114,8 @@ and 2FA can be enabled or disabled per group. Sandbox ======= -First create a new virtualenv with Python 3.8 and activate it. Then run -the following commands: +First create a new virtualenv with Python 3.10 or newer and activate it. +Then run the following commands: .. code-block:: shell diff --git a/setup.py b/setup.py index 292bb94..1169632 100644 --- a/setup.py +++ b/setup.py @@ -3,10 +3,9 @@ from setuptools import find_packages, setup install_requires = [ - "Django>=5.2", - "Wagtail>=7.0", + "Django>=5.2,<7", + "Wagtail>=7.0,<8", "django-otp>=1.7.0", - "six>=1.14.0", "qrcode>=6.1", ] @@ -58,6 +57,7 @@ "Environment :: Web Environment", "Framework :: Django", "Framework :: Django :: 5.2", + "Framework :: Django :: 6.0", "Framework :: Wagtail", "Framework :: Wagtail :: 7", "License :: OSI Approved :: MIT License", diff --git a/src/wagtail_2fa/views.py b/src/wagtail_2fa/views.py index e59db1b..a044b46 100644 --- a/src/wagtail_2fa/views.py +++ b/src/wagtail_2fa/views.py @@ -1,16 +1,8 @@ import qrcode import qrcode.image.svg -from django import VERSION as DJANGO_VERSION from django.conf import settings from django.contrib.auth import REDIRECT_FIELD_NAME - -if DJANGO_VERSION >= (4, 1): - from django.contrib.auth.views import RedirectURLMixin -else: - from django.contrib.auth.views import SuccessURLAllowedHostsMixin as RedirectURLMixin - -from wagtail import VERSION as WAGTAIL_VERSION - +from django.contrib.auth.views import RedirectURLMixin from django.core.exceptions import PermissionDenied from django.http import HttpResponse from django.shortcuts import resolve_url diff --git a/tox.ini b/tox.ini index 94ae607..1d1313d 100644 --- a/tox.ini +++ b/tox.ini @@ -1,10 +1,14 @@ [tox] envlist = - python{3.13}-django{5.2}-wagtail{7.0,7.1,7.2,7.3}, - python{3.14}-django{5.2}-wagtail{7.2,7.3}, + python{3.10,3.11,3.12}-django{5.2}-wagtail{7.0,7.1,7.2,7.3,7.4}, + python{3.13}-django{5.2,6.0}-wagtail{7.2,7.3,7.4}, + python{3.14}-django{5.2,6.0}-wagtail{7.2,7.3,7.4}, [gh-actions] python = + 3.10: python3.10 + 3.11: python3.11 + 3.12: python3.12 3.13: python3.13 3.14: python3.14 @@ -12,15 +16,20 @@ python = commands = coverage run --parallel -m pytest {posargs} -vvv basepython = + python3.10: python3.10 + python3.11: python3.11 + python3.12: python3.12 python3.13: python3.13 python3.14: python3.14 deps = django5.2: Django>=5.2,<6.0 + django6.0: Django>=6.0,<6.1 wagtail7.0: wagtail>=7.0,<7.1 wagtail7.1: wagtail>=7.1,<7.2 wagtail7.2: wagtail>=7.2,<7.3 wagtail7.3: wagtail>=7.3,<7.4 + wagtail7.4: wagtail>=7.4,<7.5 extras = test From d703b7d318a88d364d6699eeb254b8e28e7765bd Mon Sep 17 00:00:00 2001 From: nickmoreton Date: Thu, 28 May 2026 17:21:35 +0100 Subject: [PATCH 18/21] Narrow tox matrix to Wagtail 7.0, 7.3, 7.4 Drop Wagtail 7.1 and 7.2 from the test matrix. 7.0 (LTS), 7.3 (previous current), and 7.4 (current LTS) cover the supported range; 7.1 and 7.2 sit between and don't add meaningful coverage given the package's small surface area. Co-Authored-By: Claude Opus 4.7 (1M context) --- CHANGES | 4 ++-- tox.ini | 9 ++++----- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/CHANGES b/CHANGES index c5c7e91..a54dfa5 100644 --- a/CHANGES +++ b/CHANGES @@ -1,9 +1,9 @@ Unreleased ================== - - Add testing for Python 3.14, Wagtail 7.2, and Wagtail 7.3 - Add support for Wagtail 7.4 (LTS) and Django 6.0 - Expand test matrix to cover Python 3.10, 3.11, and 3.12 (previously - declared in classifiers but not exercised in tox) + declared in classifiers but not exercised in tox); CI now tests against + Wagtail 7.0, 7.3, and 7.4 (LTS + current + previous current) - Declare upper bounds: ``Django>=5.2,<7`` and ``Wagtail>=7.0,<8``. Users on Wagtail 7.0 with Django 4.2 should remain on ``wagtail-2fa 1.8.x``; this release requires Django 5.2 or newer diff --git a/tox.ini b/tox.ini index 1d1313d..d92f78e 100644 --- a/tox.ini +++ b/tox.ini @@ -1,8 +1,9 @@ [tox] envlist = - python{3.10,3.11,3.12}-django{5.2}-wagtail{7.0,7.1,7.2,7.3,7.4}, - python{3.13}-django{5.2,6.0}-wagtail{7.2,7.3,7.4}, - python{3.14}-django{5.2,6.0}-wagtail{7.2,7.3,7.4}, + python{3.10,3.11,3.12}-django{5.2}-wagtail{7.0,7.3,7.4}, + python{3.13}-django{5.2}-wagtail{7.0}, + python{3.13}-django{5.2,6.0}-wagtail{7.3,7.4}, + python{3.14}-django{5.2,6.0}-wagtail{7.3,7.4}, [gh-actions] python = @@ -26,8 +27,6 @@ deps = django5.2: Django>=5.2,<6.0 django6.0: Django>=6.0,<6.1 wagtail7.0: wagtail>=7.0,<7.1 - wagtail7.1: wagtail>=7.1,<7.2 - wagtail7.2: wagtail>=7.2,<7.3 wagtail7.3: wagtail>=7.3,<7.4 wagtail7.4: wagtail>=7.4,<7.5 From 35dc47af980c1900d65c162be3d3b00cf919ff46 Mon Sep 17 00:00:00 2001 From: nickmoreton Date: Thu, 28 May 2026 17:21:47 +0100 Subject: [PATCH 19/21] Refresh test, docs, and CI tooling versions - Bump test-extra floors: coverage>=7.0,<8 (drops legacy ==5.5 pin), pytest>=8.0, pytest-cov>=5.0, pytest-django>=4.8, flake8>=7.0, isort>=5.13, flake8-blind-except>=0.2.1, flake8-debugger>=4.1. - Bump docs-extra floors: sphinx>=7.0, sphinx_rtd_theme>=2.0. - Bump actions/setup-python from v4.9.1 to v6.2.0 (one major behind) in both python-tox.yml and python-release.yml. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/python-release.yml | 2 +- .github/workflows/python-tox.yml | 2 +- setup.py | 20 ++++++++++---------- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/python-release.yml b/.github/workflows/python-release.yml index bfb3838..a43dc0d 100644 --- a/.github/workflows/python-release.yml +++ b/.github/workflows/python-release.yml @@ -11,7 +11,7 @@ jobs: - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - name: Set up Python 3.11 - uses: actions/setup-python@7f4fc3e22c37d6ff65e88745f38bd3157c663f7c # v4.9.1 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: 3.11 diff --git a/.github/workflows/python-tox.yml b/.github/workflows/python-tox.yml index 0130ae7..50c1559 100644 --- a/.github/workflows/python-tox.yml +++ b/.github/workflows/python-tox.yml @@ -12,7 +12,7 @@ jobs: - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - name: Set up Python ${{ matrix.python }} - uses: actions/setup-python@7f4fc3e22c37d6ff65e88745f38bd3157c663f7c # v4.9.1 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: ${{ matrix.python }} diff --git a/setup.py b/setup.py index 1169632..8fb92bd 100644 --- a/setup.py +++ b/setup.py @@ -10,20 +10,20 @@ ] docs_require = [ - "sphinx>=1.4.1", - "sphinx_rtd_theme>=0.4.3", + "sphinx>=7.0", + "sphinx_rtd_theme>=2.0", ] tests_require = [ - "coverage==5.5", - "pytest>=7.2.2", - "pytest-cov>=2.12.1", - "pytest-django>=4.4.0", + "coverage>=7.0,<8", + "pytest>=8.0", + "pytest-cov>=5.0", + "pytest-django>=4.8", # Linting - "flake8>=3.9.2", # 3.7.9 - "isort>=5.12.0", - "flake8-blind-except>=0.2.0", - "flake8-debugger>=4.0.0", + "flake8>=7.0", + "isort>=5.13", + "flake8-blind-except>=0.2.1", + "flake8-debugger>=4.1", ] with open("README.rst") as fh: From 42eef7fb6f24a04a8f6de92539cc1e21f2b2a5b4 Mon Sep 17 00:00:00 2001 From: nickmoreton Date: Thu, 28 May 2026 17:23:39 +0100 Subject: [PATCH 20/21] Remove some upper version limits --- setup.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/setup.py b/setup.py index 8fb92bd..d5fe4c8 100644 --- a/setup.py +++ b/setup.py @@ -3,8 +3,8 @@ from setuptools import find_packages, setup install_requires = [ - "Django>=5.2,<7", - "Wagtail>=7.0,<8", + "Django>=5.2", + "Wagtail>=7.0", "django-otp>=1.7.0", "qrcode>=6.1", ] @@ -15,7 +15,7 @@ ] tests_require = [ - "coverage>=7.0,<8", + "coverage>=7.0", "pytest>=8.0", "pytest-cov>=5.0", "pytest-django>=4.8", From 8c3e95927c375cdb6e8f376a791c91129a63692d Mon Sep 17 00:00:00 2001 From: nickmoreton Date: Thu, 28 May 2026 17:28:42 +0100 Subject: [PATCH 21/21] A more optimal tox testing range --- tox.ini | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/tox.ini b/tox.ini index d92f78e..9c79832 100644 --- a/tox.ini +++ b/tox.ini @@ -1,9 +1,8 @@ [tox] envlist = - python{3.10,3.11,3.12}-django{5.2}-wagtail{7.0,7.3,7.4}, - python{3.13}-django{5.2}-wagtail{7.0}, - python{3.13}-django{5.2,6.0}-wagtail{7.3,7.4}, - python{3.14}-django{5.2,6.0}-wagtail{7.3,7.4}, + py{310,311,312,313}-dj52-wt{70,73,74} + py314-dj52-wt{73,74} + py{312,313,314}-dj60-wt{73,74} [gh-actions] python =