1

My views.py have a mix of def and ClassViews:

@login_required(login_url='login')
@allowed_users(allowed_roles=['Admin', 'Staff', 'Lite Scan'])
def litescan(request):
    filteredOutput = Stock.objects.all()
    val = {}...

@method_decorator(login_required(login_url='login'), name='dispatch')
class HomeView(ListView):
    model = Post
    template_name = 'community.html'
    ordering = ['-id']

And here's my decorators.py if that is helpful:

from django.shortcuts import redirect
from django.http import HttpResponseRedirect


def unauthenticated_user(view_func):
    def wrapper_func(request, *args, **kwargs):
        if request.user.is_authenticated:
            return redirect('home')
        else:
            return view_func(request, *args, **kwargs)

    return wrapper_func

def allowed_users(allowed_roles=[]):
    def decorator(view_func):
        def wrapper_func(request, *args, **kwargs):

            group = None
            if request.user.groups.exists():
                group = request.user.groups.all()[0].name

            if group in allowed_roles:
                return view_func(request, *args, **kwargs)
            else:
                url = ('/forbidden')
                return HttpResponseRedirect(url)
        return wrapper_func
    return decorator

I found out that @login_required and @allowed_users give out an error when used with ClassView. So i used @method_decorator which brings me to the login page before redirecting to the page. However, I can not find a way to restrict access to only certain groups like Admin, Staff, Lite Scan with my ClassView.

Little help will be appreciated. Thanks!

Ramsey
  • 181
  • 1
  • 9

2 Answers2

4

You can use AccessMixin for your class views.

Example I found:

from django.contrib.auth.mixins import AccessMixin
from django.http import HttpResponseRedirect 

class FinanceOverview(AccessMixin, TemplateMixin):

    def dispatch(self, request, *args, **kwargs):
        if not request.user.is_authenticated:
            # This will redirect to the login view
            return self.handle_no_permission()
        if not self.request.user.groups.filter(name="FinanceGrp").exists():
            # Redirect the user to somewhere else - add your URL here
            return HttpResponseRedirect(...)

        # Checks pass, let http method handlers process the request
        return super().dispatch(request, *args, **kwargs)

More info found here: Use LoginRequiredMixin and UserPassesTestMixin at the same time

Shyrtle
  • 647
  • 5
  • 20
  • That's fine but when i put `if not self.request.user.groups.filter(name="Admin", "Lite Scan").exists():` it gives out an errot – Ramsey Jan 29 '21 at 17:33
  • I can't put in multiple groups – Ramsey Jan 29 '21 at 17:33
  • Could you use `and`? `if not self.request.user.groups.filter(name="Admin") and not self.request.user.groups.filter(name="OtherGroup") – Shyrtle Jan 29 '21 at 17:35
  • `And` did not work but ur suggestion gave me the idea to put the second line after a break and it works fine. Thanks man! – Ramsey Jan 29 '21 at 17:42
2

Relying on Django Permissions may be a far simpler approach to giving access to such a view. Rather than checking for a specific list of groups, you can assign permissions to those groups and give access to the view based on whether the user's groups have the appropriate permissions.

views.py

from django.contrib.auth.decorators import permission_required
from django.contrib.auth.mixins import PermissionsRequiredMixin


@permission_required('foo.view_bar')
def my_view(request):
    ...


class MyView(PermissionRequiredMixin, DetailView):
    permission_required = ('foo.view_bar', )
    ...
thirdjal
  • 21
  • 2