# HG changeset patch # User Peter Sanchez # Date 1601940043 25200 # Mon Oct 05 16:20:43 2020 -0700 # Node ID a55d14a05fd6aceda806f840f86a60237b48edcb # Parent 9b8f81576adb8450ac6e470172eb80536a051dbd Adding READ_ONLY impersonation mode support. Closes #58 diff --git a/README.md b/README.md --- a/README.md +++ b/README.md @@ -237,6 +237,14 @@ LOGIN_REDIRECT_URL setting and fall back to '/' if neither is present. Value should be a string containing the redirect path. + READ_ONLY + +A boolean that if set to `True` any requests that are not either `GET` or +`HEAD` will result in a "Bad Request" response (status code 405). Use this if +you want to limit your impersonating users to read only impersonation sessions. + +Value should be a boolean, defaults to `False` + USE_HTTP_REFERER If this is set to `True`, then the app will attempt to be redirect you to @@ -441,15 +449,15 @@ And you should see: - py36-django1.11: commands succeeded py36-django2.2: commands succeeded py36-django3.0: commands succeeded - py37-django1.11: commands succeeded + py36-django3.1: commands succeeded py37-django2.2: commands succeeded py37-django3.0: commands succeeded - py38-django1.11: commands succeeded + py37-django3.1: commands succeeded py38-django2.2: commands succeeded py38-django3.0: commands succeeded + py38-django3.1: commands succeeded congratulations :) # Contributing diff --git a/README.rst b/README.rst --- a/README.rst +++ b/README.rst @@ -4,7 +4,7 @@ Simple application to allow superusers to "impersonate" other non-superuser accounts. -**Version:** 1.5.1 +**Version:** 1.6 **Project Links:** `Issues `__ @@ -17,7 +17,7 @@ Python / Django Support ======================= -- Python 3.6+ for Django versions 1.11, 2.2 and 3.0 +- Python 3.6+ for Django versions 2.2+ **Note:** As of version 1.4 we are only officially supporting Python 3.6+ and following the Django support schedule. Meaning we can only @@ -32,6 +32,9 @@ **NOTE:** +- **Version 1.6** has officially removed support for the old settings + format. Please see the `settings <#settings>`__ section for how + settings should be configured. - **Version 1.5 is now only officially supporting Django's 1.11, 2.2, and 3.0** - **Version 1.4 is now officially supporting Python 3.6+ and Django @@ -264,6 +267,17 @@ :: + READ_ONLY + +A boolean that if set to ``True`` any requests that are not either +``GET`` or ``HEAD`` will result in a "Bad Request" response (status code +405). Use this if you want to limit your impersonating users to read +only impersonation sessions. + +Value should be a boolean, defaults to ``False`` + +:: + USE_HTTP_REFERER If this is set to ``True``, then the app will attempt to be redirect you @@ -417,11 +431,39 @@ MAX_FILTER_SIZE The max number of items acceptable in the admin list filters. If the -number of items exceeds this, then the filter is removed (just shows -all). This is used by the "Filter by impersonator" filter. +number of items exceeds this, then the filter list is the size of the +settings value. This is used by the "Filter by impersonator" filter. It is optional, and defaults to 100. +:: + + ADMIN_DELETE_PERMISSION + +A boolean to enable/disable deletion of impersonation logs in the Django +admin. + +Default is ``False`` + +:: + + ADMIN_ADD_PERMISSION + +A boolean to enable/disable ability to add impersonation logs in the +Django admin. + +Default is ``False`` + +:: + + ADMIN_READ_ONLY + +A boolean to enable/disable "read only" mode of impersonation logs in +the Django admin. Generally you want to leave this enabled otherwise +admin users can alter logs within the Django admin area. + +Default is ``True`` + Admin ===== @@ -486,15 +528,15 @@ :: - py36-django1.11: commands succeeded py36-django2.2: commands succeeded py36-django3.0: commands succeeded - py37-django1.11: commands succeeded + py36-django3.1: commands succeeded py37-django2.2: commands succeeded py37-django3.0: commands succeeded - py38-django1.11: commands succeeded + py37-django3.1: commands succeeded py38-django2.2: commands succeeded py38-django3.0: commands succeeded + py38-django3.1: commands succeeded congratulations :) Contributing diff --git a/impersonate/middleware.py b/impersonate/middleware.py --- a/impersonate/middleware.py +++ b/impersonate/middleware.py @@ -1,9 +1,11 @@ # -*- coding: utf-8 -*- +from django.http import HttpResponseNotAllowed from django.utils.deprecation import MiddlewareMixin from .helpers import ( User, check_allow_for_uri, check_allow_for_user, is_authenticated, ) +from .settings import settings class ImpersonateMiddleware(MiddlewareMixin): @@ -25,6 +27,9 @@ except User.DoesNotExist: return + if settings.READ_ONLY and request.method not in ['GET', 'HEAD']: + return HttpResponseNotAllowed(['GET', 'HEAD']) + if check_allow_for_user(request, new_user) and check_allow_for_uri( request.path ): diff --git a/impersonate/settings.py b/impersonate/settings.py --- a/impersonate/settings.py +++ b/impersonate/settings.py @@ -19,6 +19,7 @@ 'LOOKUP_TYPE': 'icontains', 'SEARCH_FIELDS': [username_field, 'first_name', 'last_name', 'email'], 'REDIRECT_URL': getattr(django_settings, 'LOGIN_REDIRECT_URL', u'/'), + 'READ_ONLY': False, 'ADMIN_DELETE_PERMISSION': False, 'ADMIN_ADD_PERMISSION': False, 'ADMIN_READ_ONLY': True, diff --git a/impersonate/tests.py b/impersonate/tests.py --- a/impersonate/tests.py +++ b/impersonate/tests.py @@ -757,3 +757,9 @@ self.assertTrue(model_admin.has_change_permission(request)) request.method = 'POST' self.assertTrue(model_admin.has_change_permission(request)) + + @override_settings(IMPERSONATE={'READ_ONLY': True}) + def test_impersonate_read_only(self): + self._impersonate_helper('user1', 'foobar', 4) + resp = self.client.post('/not/real/url/') + self.assertEqual(resp.status_code, 405)