diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 0a59d99..fc7c228 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -6,10 +6,10 @@ on: - develop - master - main - - 'release/**' + - "release/**" pull_request: branches: - - '*' + - "*" workflow_dispatch: jobs: @@ -34,4 +34,4 @@ jobs: - name: Security run: make bandit - name: Testing - run: make tests + run: make test diff --git a/pyproject.toml b/pyproject.toml index 1108cf2..04cf916 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "django-security" -version = "1.0.7" +version = "1.1.0" homepage = "https://github.com/sdelements/django-security" description = "Models, views, middlewares and forms to facilitate security hardening of Django applications." authors = ["Security Compass "] diff --git a/security/middleware.py b/security/middleware.py index b984c0f..61856bd 100644 --- a/security/middleware.py +++ b/security/middleware.py @@ -3,6 +3,7 @@ import json import logging import pstats +from urllib.parse import quote_plus import warnings from io import StringIO from re import compile @@ -1058,6 +1059,8 @@ def process_request(self, request): else: login_url = self.login_url next_url = request.path + if len(request.META["QUERY_STRING"]): + next_url += quote_plus("?" + request.META["QUERY_STRING"]) if request.headers.get("x-requested-with") == "XMLHttpRequest": return HttpResponse( diff --git a/tests/settings.py b/tests/settings.py index 55aea59..de827a6 100644 --- a/tests/settings.py +++ b/tests/settings.py @@ -50,6 +50,8 @@ "security.middleware.ProfilingMiddleware", ) +ENABLE_PROFILING = True + ROOT_URLCONF = "tests.urls" TEMPLATES = [ diff --git a/tests/tests.py b/tests/tests.py index 82f2db2..b4c8736 100644 --- a/tests/tests.py +++ b/tests/tests.py @@ -1,6 +1,7 @@ import datetime import json import time # We monkeypatch this. +from urllib.parse import quote_plus from django.conf import settings from django.contrib.auth import logout @@ -16,16 +17,23 @@ from security.auth import min_length from security.auth_throttling import Middleware as AuthThrottlingMiddleware -from security.auth_throttling import (attempt_count, default_delay_function, - delay_message, increment_counters, - reset_counters, throttling_delay) -from security.middleware import (BaseMiddleware, - ContentSecurityPolicyMiddleware, - DoNotTrackMiddleware, - MandatoryPasswordChangeMiddleware, - ReferrerPolicyMiddleware, - SessionExpiryPolicyMiddleware, - XFrameOptionsMiddleware) +from security.auth_throttling import ( + attempt_count, + default_delay_function, + delay_message, + increment_counters, + reset_counters, + throttling_delay, +) +from security.middleware import ( + BaseMiddleware, + ContentSecurityPolicyMiddleware, + DoNotTrackMiddleware, + MandatoryPasswordChangeMiddleware, + ReferrerPolicyMiddleware, + SessionExpiryPolicyMiddleware, + XFrameOptionsMiddleware, +) from security.models import PasswordExpiry from security.password_expiry import never_expire_password from security.views import csp_report, require_ajax @@ -152,6 +160,14 @@ def test_redirects_unauthenticated_request(self): response = self.client.get("/home/") self.assertRedirects(response, self.login_url + "?next=/home/") + def test_redirects_unauthenticated_request_to_custom_path_with_query_url(self): + path = "/custom-path/" + query = "priority=7,8,9,10&type=Custom" + response = self.client.get(f"{path}?{query}") + + expected_redirect = f"{self.login_url}?next={path}{quote_plus("?" + query)}" + self.assertRedirects(response, expected_redirect) + def test_redirects_unauthenticated_ajax_request(self): response = self.client.get( "/home/",