Django

Code

Ticket #4376 (closed: fixed)

Opened 1 year ago

Last modified 1 year ago

login_required doesn't work with bound methods

Reported by: steven.bethard@gmail.com Assigned to: nobody
Milestone: Component: Uncategorized
Version: SVN Keywords: auth login_required decorator
Cc: Triage Stage: Ready for checkin
Has patch: 1 Needs documentation: 0
Needs tests: 0 Patch needs improvement: 0

Description

The django.contrib.auth.decorators.login_required decorator doesn't work correctly with bound methods. If I have code like:

class ViewManager(object):
    @login_required
    def get_main_view(self, request):
        return HttpResponse('hello')

view_manager = ViewManager()
urlpatterns = patterns('',
    (r'^$', view_manager.get_main_view),
)

I'll get an error saying:

AttributeError at /
'ViewManager' object has no attribute 'user'

I believe this is because __get__ is being invoked on the _checklogin function returned by login_required and so the ViewManager? instance is being bound as the request argument of _checklogin instead of being bound as the self argument of get_main_view as it should be. To fix this, I had to replace the _dec function in django.contrib.auth.decorators.user_passes_test like so::

def user_passes_test(test_func, login_url=None):
    if not login_url:
        from django.conf import settings
        login_url = settings.LOGIN_URL
    class CheckLogin(object):
        def __init__(self, func):
            self.func = func
        def __get__(self, obj, cls=None):
            return CheckLogin(self.func.__get__(obj, cls))
        def __call__(self, request, *args, **kwargs):
            if test_func(request.user):
                return view_func(request, *args, **kwargs)
            return HttpResponseRedirect('%s?%s=%s' % (login_url, REDIRECT_FIELD_NAME, quote(request.get_full_path())))
    return CheckLogin

This simply redirects the __get__ call to the wrapped function, instead of allowing it to be called on the _checklogin function.

Attachments

django.contrib.auth.decorators.diff (2.7 kB) - added by steven.bethard@gmail.com on 05/23/07 22:24:48.
rewrite of django.contrib.auth.decorators to handle bound methods properly
django.contrib.auth.decorators.2.diff (2.7 kB) - added by steven.bethard@gmail.com on 05/23/07 22:29:49.
bugfix for last patch
django.contrib.auth.decorators.3.diff (8.9 kB) - added by anonymous on 05/24/07 00:40:38.
updated version with tests
django.contrib.auth.decorators.4.diff (9.6 kB) - added by steven.bethard@gmail.com on 09/16/07 12:11:53.
Patch against revision 6364. This should now apply cleanly.

Change History

05/23/07 22:24:48 changed by steven.bethard@gmail.com

  • attachment django.contrib.auth.decorators.diff added.

rewrite of django.contrib.auth.decorators to handle bound methods properly

05/23/07 22:29:49 changed by steven.bethard@gmail.com

  • attachment django.contrib.auth.decorators.2.diff added.

bugfix for last patch

05/23/07 22:32:22 changed by steven.bethard@gmail.com

  • needs_better_patch changed.
  • has_patch set to 1.
  • needs_tests set to 1.
  • needs_docs changed.

I don't know how to write unit tests for Django, but if someone can point me in the right direction, I can make some tests for this. I need to know know how to programatically visit, say, '/' and verify that it returns the appropriate output.

05/23/07 23:31:23 changed by Gary Wilson <gary.wilson@gmail.com>

have you seen the testing documentation?

05/24/07 00:40:38 changed by anonymous

  • attachment django.contrib.auth.decorators.3.diff added.

updated version with tests

05/24/07 00:48:27 changed by steven.bethard@gmail.com

  • needs_tests deleted.

Thanks for the pointer. I think I figured out how to modify modeltests.test_client where the only existing django.contrib.auth.decorators test I could find was. The patch I just uploaded rewrites the decorators module to handle methods properly, and adds three new tests: test_view_with_method_login, test_view_with_permissions and test_view_with_method_permissions.

Note that I didn't see the @permission_required decorator tested anywhere, so I added both a regular function test and a method test for that one. Both of these tests have TODO comments on them - I was able to test that when the permissions are wrong, they redirect to a login page, but I wasn't sure how to get a user with the right permissions to complete the tests. Of course, if @permission_required really wasn't tested at all before, half-way there is better than nothing, right? ;-)

05/26/07 08:13:05 changed by Simon G. <dev@simon.net.nz>

  • stage changed from Unreviewed to Ready for checkin.

09/16/07 06:49:42 changed by mtredinnick

  • needs_better_patch set to 1.
  • stage changed from Ready for checkin to Accepted.

I like this patch. Code looks code and everything.

Unfortunately, due to the changes during the sprint over the last few days, in particular, it no longer cleanly applies and at least one of the changes (django.contrib.auth.decorators) requires a bit of reworking of the code.

If somebody could update the patch, it's then ready to go in.

09/16/07 12:11:53 changed by steven.bethard@gmail.com

  • attachment django.contrib.auth.decorators.4.diff added.

Patch against revision 6364. This should now apply cleanly.

11/06/07 09:10:09 changed by scompt@scompt.com

  • needs_better_patch deleted.
  • stage changed from Accepted to Ready for checkin.

I think this patch may have fallen through the cracks. I've just applied it against revision 6652 and it still applies cleanly, so I'm going to tweak this ticket so somebody sees it. I hope that's cool with the powers that be.

11/07/07 16:45:08 changed by lukeplant

  • status changed from new to closed.
  • resolution set to fixed.

(In [6658]) Fixed #4376 -- login_required now works with bound methods. Thanks, Steven Bethard.


Add/Change #4376 (login_required doesn't work with bound methods)




Change Properties
Action