Search code examples
djangourlpermissionsdecoratorgroup

Django : How do you check if an user has the rights on a pk value inserted in the URL - decorator


I am a newbee in django. In my website, when the user logs in, he is redirected to a page with a dropdown menu where he has to choose a contract on which he wants to work. After selecting the contract he is redirected to the specific homepage define with a ID in the url. The ID value comes from the ID of the contract in the database.

What How can I check by a function or a decorator that the user has the rights to be on this contract. Because any user could right the numbers in the url and access to a page where he should not have access. By example, an user has the right to the contracts 109 and 144, so he can go on the urls "home/109" and "home/144", but if is change the value in the url to another one, he should not have access

Here is my view of the dropdown menu :

@authenticated_user
def selectcontrat(request) :

    context = initialize_context(request)
    form_client = SelectClient(request.POST, user=request.user)
    if form_client.is_valid():
        id_contrat = request.POST.get("ID_Customer")
    
        return redirect(reverse('home', args=(id_contrat,)))

    context['form_client'] = form_client

    return render(request, 'base/selectcontrat.html', context)

Here the views of the home page :

@authenticated_user
def home(request, id_contrat=None):
    context = initialize_context(request)

    return render(request, 'home.html', context)

The urls :

from django.urls import path from . import views

urlpatterns = [
    path('home/<int:id_contrat>/', views.home, name="home"),
    path('', views.loginAD, name="login"),
    path('signin', views.sign_in, name='signin'),
    path('callback', views.callback, name='callback'),
    path('selectcontrat', views.selectcontrat, name='selectcontrat')

The model is the relation between a user and a group. which group the user has righs.

class Groups(models.Model):
    ID = models.AutoField(primary_key=True)  # Field name made lowercase.
    IDCustomer = models.IntegerField(blank=True, null=True)  # Field name made lowercase.
    GroupName = models.CharField(max_length=255, blank=True, null=True)  # Field name made lowercase.
    CreatedOn = models.DateTimeField(blank=True, null=True)  # Field name made lowercase.


class AADJNTGroup(models.Model):

    ID = models.AutoField(primary_key=True)
    ID_User = models.ForeignKey(User, on_delete=models.CASCADE)
    ID_Group = models.ForeignKey(Groups, on_delete=models.CASCADE)
    CreatedOn = models.DateTimeField(auto_now_add=True)
    CreatedBy = models.CharField(max_length=255)

To do that, I tried to do a decorator, but I do not know how to get the id_contrac value that is redirected after the form. How can I get this value in a decorator, like that then I could check the rights on the database.

The decorator not working :

def check_pk(view_func) :

    def wrapper_func(request, *args, **kwargs):

        list_user_rights = AADJNTGroup.objects.filter(ID_group_id=args[0]).values_list('ID_User_id', flat=True)
        print(list_user_rights)

    return wrapper_func

Anyone has an idea ?


Solution

  • I did a decorator, that requests the different database to check the rights

    Here is the decorator

    def check_user_rights():
        def wrapper_func(view_func):
            @wraps(view_func)
            def wrapper(request, *args, **kwargs):
               
                # THE ID THAT I CAN COLLECT
                ID_contrat = kwargs["id_contrat"]
                User_ID = request.user.id
                
                # THE SQL REQUEST TO GET THE VALUE
                list_user_rights = AADJNTGroup.objects.filter(ID_User_id=User_ID).values_list('ID_Group_id', flat=True)
                ID_contrat_list = list(list_user_rights)
                Contrat_right = Groups.objects.all().filter(ID__in=ID_contrat_list).values_list('IDCustomer', flat=True)
                
                # Compare the rights
                if ID_contrat in Contrat_right :
                    return view_func(request, *args, **kwargs)  
    
                else :
                    return HttpResponse("<h1> page not found</H1>")
                
            return wrapper
        return wrapper_func