Repository: jazzband/django-axes

Issue:
Ensure staff_member_required always works
specifically, make sure it's compatible with Django 1.2 and Django 1.3



Discussion:
@aclark4life what do you think about changing this:

https://github.com/codekoala/django-axes/blob/master/axes/decorators.py#L414

for a user_passes_test decorator, at this moment i don't see any good reason to make that custom method here. So what do you think?

@camilnova not sure, maybe @MichaelBlume can take a look and send a pull request :-)

@MichaelBlume Django 1.2 and Django 1.3 doesn't worth the effort to maintain anymore, @aclark4life do you think will be better to remove that code from axes?

Fine with me CC: @codekoala 

@codekoala Just say yes and i will release the kraken :squirrel: 

Hah!

@codekoala seems MIA so I'd say go ahead with this


Resolving patch:
diff --git a/axes/decorators.py b/axes/decorators.py
--- a/axes/decorators.py
+++ b/axes/decorators.py
@@ -1,32 +1,24 @@
-try:
-    from functools import wraps
-except ImportError:
-    from django.utils.functional import wraps  # Python 2.4 fallback.
+import logging
 
 from datetime import timedelta
-import logging
 
+from django import template
 from django.conf import settings
-from django.contrib.auth import authenticate, login, logout
+from django.contrib.auth import logout
 from django.db.models.loading import get_model
-from django import http
-from django.http import HttpResponse, HttpResponseRedirect
+from django.http import HttpResponse
+from django.http import HttpResponseRedirect
 from django.shortcuts import render_to_response
-from django import template
 from django.template import RequestContext
+from django.utils import timezone as datetime
 from django.utils.translation import ugettext_lazy, ugettext as _
 
-# Use the timezone support in Django >= 1.4 if it's available.
-try:
-    from django.utils import timezone as datetime
-except ImportError:
-    # Fallback for Django < 1.4.
-    from datetime import datetime
-
-from axes.models import AccessAttempt, AccessLog
+from axes.models import AccessLog
+from axes.models import AccessAttempt
 from axes.signals import user_locked_out
 import axes
 
+
 # user model compatible with Django 1.5
 AUTH_USER_MODEL = getattr(settings, 'AUTH_USER_MODEL', 'auth.User')
 
@@ -423,93 +415,3 @@ def _display_login_form(request, error_message=''):
         'app_path': request.get_full_path(),
         'error_message': error_message
     }, context_instance=template.RequestContext(request))
-
-
-def staff_member_required(view_func):
-    """
-    Decorator for views that checks that the user is logged in and is a staff
-    member, displaying the login page if necessary.  Mostly quoted from
-    django.contrib.auth.decorators.staff_member_required.  License for
-    Django-extracted code follows:
-
-    Copyright (c) Django Software Foundation and individual contributors.  All
-    rights reserved.
-
-    Redistribution and use in source and binary forms, with or without
-    modification, are permitted provided that the following conditions are met:
-
-        1. Redistributions of source code must retain the above copyright
-           notice, this list of conditions and the following disclaimer.
-
-        2. Redistributions in binary form must reproduce the above copyright
-           notice, this list of conditions and the following disclaimer in the
-           documentation and/or other materials provided with the distribution.
-
-        3. Neither the name of Django nor the names of its contributors may be
-           used to endorse or promote products derived from this software
-           without specific prior written permission.
-
-    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-    ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-    LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-    CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-    SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-    INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-    CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-    POSSIBILITY OF SUCH DAMAGE."""
-
-    def _checklogin(request, *args, **kwargs):
-        if request.user.is_active and request.user.is_staff:
-            # The user is valid. Continue to the admin page.
-            return view_func(request, *args, **kwargs)
-
-        assert hasattr(request, 'session'), "The Django admin requires session middleware to be installed. Edit your MIDDLEWARE_CLASSES setting to insert 'django.contrib.sessions.middleware.SessionMiddleware'."
-
-        # If this isn't already the login page, display it.
-        if LOGIN_FORM_KEY not in request.POST:
-            if request.POST:
-                message = _("Please log in again, because your session has expired.")
-            else:
-                message = ""
-            return _display_login_form(request, message)
-
-        # Check that the user accepts cookies.
-        if not request.session.test_cookie_worked():
-            message = _("Looks like your browser isn't configured to accept cookies. Please enable cookies, reload this page, and try again.")
-            return _display_login_form(request, message)
-        else:
-            request.session.delete_test_cookie()
-
-        # Check the password.
-        username = request.POST.get('username', None)
-        password = request.POST.get('password', None)
-        user = authenticate(username=username, password=password)
-        # next two lines are where this differs from django's
-        # @staff_member_required -- ready?
-        if not check_request(request, not user):
-            return lockout_response(request)
-        if user is None:
-            message = ERROR_MESSAGE
-            if '@' in username:
-                # Mistakenly entered e-mail address instead of username? Look it up.
-                users = list(User.objects.filter(email=username))
-                if len(users) == 1 and users[0].check_password(password):
-                    message = _("Your e-mail address is not your username. Try '%s' instead.") % users[0].username
-                else:
-                    # Either we cannot find the user, or if more than 1
-                    # we cannot guess which user is the correct one.
-                    message = _("Usernames cannot contain the '@' character.")
-            return _display_login_form(request, message)
-
-        # The user data is correct; log in the user in and continue.
-        else:
-            if user.is_active and user.is_staff:
-                login(request, user)
-                return http.HttpResponseRedirect(request.get_full_path())
-            else:
-                return _display_login_form(request, ERROR_MESSAGE)
-
-    return wraps(view_func)(_checklogin)


Test patch: