Django is_staff permission decorator
Asked Answered
C

4

58

I am trying to limit access to pages using 2 user levels. Superuser and admin. Super user is a regular Django user with 'is_superuser' assigned. Admin user is also a regular user with only the 'is_staff' permission assigned.

The problem is that when i use this decorator for an admin user, it doesn't pass the test:

@permission_required('is_staff')
def my_view(....)

@permission_required('is_staff') returns false for anonymous users. (correct)
@permission_required('is_superuser') only returns true for superusers (correct)
@permission_required('is_staff') returns FALSE for users with the 'is_staff' perm assigned. (wrong).

Any thoughts?

Crabby answered 29/4, 2011 at 14:10 Comment(1)
I should note i am using Django 1.3 with python 2.6.1Crabby
S
127

is_staff isn't a permission so instead of permission_required you could use:

@user_passes_test(lambda u: u.is_staff)

or

from django.contrib.admin.views.decorators import staff_member_required

@staff_member_required
Salaidh answered 29/4, 2011 at 14:18 Comment(8)
That did it, though the fact that is_superuser exists and is_staff doesn't is quite misleading.Crabby
i added another option which is more intuitive (staff_member_required).Salaidh
@permission_required('is_superuser') returns True for superusers because @permission_required always returns True for superusers regardless of whether that permission exists or not (which it does not in this case). This is assuming you are using the default authentication backend.Jon
The build-in decorator "staff_member_required" is convinient, but I would use it with care, as it seems not to be officially documented.Infiltrate
@Infiltrate I'd say staff_member_required is safe to use now by your standards. I found it via a "See Also" block in the "Using the Django authentication system" page of the manual.Epicotyl
@Epicotyl Yes, you are right, the staff_member_required decorator is documented by now: docs.djangoproject.com/en/1.9/ref/contrib/admin/…Infiltrate
how can I say raise_exception=True with any of these?Ry
django-braces provides mixins for CBVs for superuser/staff "requirement": django-braces.readthedocs.io/en/latest/…Radiosurgery
H
10

for Class Based Views you can add permission_required('is_staff') to the urls.py:

from django.contrib.auth.decorators import permission_required

url(r'^your-url$', permission_required('is_staff')(YourView.as_view()), name='my-view'),
Haile answered 24/6, 2014 at 11:2 Comment(1)
I didn't try, but I wonder if 'is_staff' works as expected here.Audreyaudri
K
9

For class-based views, the UserPassesTestMixin is convenient, e.g.

class ImportFilePostView(LoginRequiredMixin, UserPassesTestMixin):
  def test_func(self):
    return self.request.user.is_staff
  ...
Kochi answered 18/4, 2018 at 13:44 Comment(2)
Lol just came across my own answer only a few days later ... early signs of alzheimer :DKochi
Lol just came across it again :/Kochi
S
0

A variant of @arie 's answer without lambda which might be a tad faster (but I didn't check):

import operator
from django.contrib.auth.decorators import user_passes_test

@user_passes_test(operator.attrgetter('is_staff'))
def my_view(....)

Having said that, I think the better approach is to create a Permission for your view and use it with the permission_required decorator.

Scriptwriter answered 8/2, 2021 at 21:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.