Prevent redirect loop when MAX_DURATION is used - Refs #67
2 files changed, 29 insertions(+), 1 deletions(-)

M impersonate/middleware.py
M impersonate/tests.py
M impersonate/middleware.py +4 -1
@@ 2,7 2,7 @@ 
 from datetime import datetime, timedelta
 
 from django.http import HttpResponseNotAllowed
-from django.shortcuts import redirect
+from django.shortcuts import redirect, reverse
 from django.utils import timezone
 from django.utils.deprecation import MiddlewareMixin
 from django.utils.functional import SimpleLazyObject

          
@@ 26,6 26,9 @@ class ImpersonateMiddleware(MiddlewareMi
 
         if '_impersonate' in request.session and request.user.is_authenticated:
             if settings.MAX_DURATION:
+                if request.path == reverse('impersonate-stop'):
+                    return
+
                 if '_impersonate_start' not in request.session:
                     return
 

          
M impersonate/tests.py +25 -0
@@ 150,6 150,31 @@ class TestMiddleware(TestCase):
             _impersonate_start=datetime.now(timezone.utc).timestamp()
         )
 
+    @override_settings(IMPERSONATE={'MAX_DURATION': 5, 'REDIRECT_URL': '/foo/'})
+    def test_impersonate_timeout_not_redirect_loop(self):
+        ''' Test to ensure that when MAX_DURATION is reached dont create a redirect loop.
+            See Issue #67
+        '''
+        self._impersonated_request(
+            _impersonate_start=datetime.now(timezone.utc).timestamp()
+        )
+        # new request to see if the redirect to stop
+        request = self.factory.get('/')
+        request.user = self.superuser
+        past_time = datetime.now(timezone.utc) - timedelta(hours=1)
+        request.session = {
+            '_impersonate': self.user,
+            '_impersonate_start': past_time.timestamp(),
+        }
+        request = self.middleware.process_request(request)
+        # Check does the redirect to stop the impersonate
+        self.assertEqual(request.status_code, 302)
+        self.assertEqual(request.url, reverse('impersonate-stop'))
+        # Check impersonate stop redirects to the REDIRECT_URL
+        request = self.client.get(reverse('impersonate-stop'))
+        self.assertEqual(request.status_code, 302)
+        self.assertEqual(request.url, '/foo/')
+
     @override_settings(IMPERSONATE={'MAX_DURATION': 3600})
     def test_reject_without_start_time(self):
         ''' Test to ensure that requests without a start time