Is there a way I can extend Django login_required decorator to check for a boolean field in my custom model?

Issue

I am working on a web application that has 5 different kinds of users, which are being differentiated by boolean fields in my custom user model.

is_estate_vendor = models.BooleanField(
        _('estate_vendor'),
        null=True,
        blank=True,
        help_text=_(
            'Designates whether this user should be treated as an estate admin.'
        ),
    )
    is_estate_admin = models.BooleanField(
        _('estate_admin'),
        null=True,
        blank=True,
        help_text=_(
            'Designates whether this user should be treated as an estate admin.'
        ),
    )
    is_estate_security = models.BooleanField(
        _('estate_security'),
        null=True,
        blank=True,
        help_text=_(
            'Designates whether this user should be treated as estate security.'
        ),
    )
    is_estate_residence = models.BooleanField(
        _('estate_residence'),
        null=True,
        blank=True,
        help_text=_('Designates whether this user should be treated as estate residence.'
                    ),
    )
    is_estate_head_security = models.BooleanField(
        _('estate_head_security'),
        null=True,
        blank=True,
        help_text=_(
            'Designates whether this user should be treated as estate head security.'
        ),
    )
    is_super_admin = models.BooleanField(
        _('super_admin'),
        null=True,
        blank=True,
        help_text=_(
            'Designates whether this user should be treated as superadmin.'
        ),
    )  

I’m trying to extend Django login_decorator to check for which user is logged-in base on which of that boolean fields is true and redirect any authenticated user to the login page if he/she tries to access the dashboard of another kind of user. I tried to create a custom decorator that checks for those fields:

def vendor_login_required(function):
   def wrapper(request, *args, **kwargs):
     vendor=request.user.is_estate_vendor
     userAuth = request.user.isAuthenticated:  
     if not userAuth:
        message.success(request, "Please login")
        return HttpResponseRedirect('/login')
     elif userAuth and not vendor:
        message.error(request, "You are not authorized to be here, login as a vendor to 
                      continue")
        return HttpResponseRedirect('/login')
     else:
        return function(request, *args, **kwargs)
   return wrapper

For some reason this is not working, I’ll appreciate a way around this.

Solution

Your usecase is more applicable to the decorator @user_passes_test where you just have to return either True or False whether the view must be continued or if must be redirected to the login page, no more need to manually perform the HttpResponseRedirect or the calling of the view.

user_passes_test(test_func, login_url=None, redirect_field_name='next')

As a shortcut, you can use the convenient user_passes_test decorator which performs a redirect when the callable returns False:

It would look something like:

from django.contrib.auth.decorators import login_required, user_passes_test

def is_estate_vendor(user):
    return user.is_estate_vendor

@login_required  # This will check if a user is currently logged-in, whether estate vendor, admin, security, etc.
@user_passes_test(lambda user: user.is_estate_vendor)  # This will check of the user has the correct boolean fields set to access this view
# @user_passes_test(is_estate_vendor)  # Use this if you need to use the function above to perform more complex checks
def my_view_for_estate_vendor(request):
    ...

Answered By – Niel Godfrey Ponciano

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published