Sprint02 Django Object Model‐based Permissions - Sloathking/Foolish-Wizardz GitHub Wiki

Object/Model-based Permissions

Author: Joshua Edwards


TL;DR

I ended up using a decorator that compares the currently logged-in user to the user associated with the Artist of the function being accessed. So all I need to do is decorate functions in views.py that only the Artist owner can access (like create/edit/delete posts) and the decorator will do the object relationship test to determine if the user has permission to access the view. Here is the code of the decorator I made and an example usage.

def user_is_owner():
    def decorator(view_func):
        def wrapper_func(request, *args, **kwargs):
            print('args', args) # displays args and kwargs for debugging purposes
            print('kwargs', kwargs)
            # grab the current user from 'request'
            user = request.user
            # use the kwarg pk from the view_func to get the artist object
            artist = Artist.objects.get(id=kwargs['pk'])
            # check if the user is associated to the artist
            if user == artist.user:
                return view_func(request, *args, **kwargs)
            else:
                messages.warning(request, 'You do not have permission to perform that action ')
                return redirect('index')
        return wrapper_func
    return decorator

image


More detailed documentation

• Description of your technical task Implement permissions with Django model/object relationships. • A summary of what you have learned so far This type of permission system is most useful when you have your model relationships set up in a way where one model “owns” models or “has” other models related to them. For example, having a “Student” model that owns a “Portfolio” model that has “Project” models. When the relationships are set up in this way, the permissions can be used to only allow changes or viewing if the base model (Student) “owns” the model being viewed. It seems pretty simple and you can check ownership using a simple if statement to see if the student associated with the project is equal to the current student who is logged in. The logic gets a little tricky when figuring out where exactly is the best spot to check the association of the student to the project, decorators are the best/easiest way I found

• Resources you used so far Great video on Python Decorators (15m) and this 1m Decorators vid Managing User Permissions Django Custom Permissions in Django Conversation with ChatGPT about implementing object-based perms

• Technical documentation you have so far To use object-based permissions, your models must be set up so you have internal relationships between them both. You need to be able to get the related student from the profile model or the related profile from the student model. I have the Artist class to contain a OneToOne relation to the user who contains the login info. This way, I can verify the current logged in user against the user in the Artist they are trying to access to verify perms.

image image

• A screenshot of code I have implemented in my “Artist” class (comparable to a student class):

I ended up using a decorator that compares the currently logged-in user to the user associated with the Artist of the function being accessed. So all I need to do is decorate functions in views.py that only the Artist owner can access (like create/edit/delete posts) and the decorator will do the object relationship test to determine if the user has permission to access the view. Here is the code of the decorator I made and an example usage.

def user_is_owner():
    def decorator(view_func):
        def wrapper_func(request, *args, **kwargs):
            print('args', args) # displays args and kwargs for debugging purposes
            print('kwargs', kwargs)
            # grab the current user from 'request'
            user = request.user
            # use the kwarg pk from the view_func to get the artist object
            artist = Artist.objects.get(id=kwargs['pk'])
            # check if the user is associated to the artist
            if user == artist.user:
                return view_func(request, *args, **kwargs)
            else:
                messages.warning(request, 'You do not have permission to perform that action ')
                return redirect('index')
        return wrapper_func
    return decorator

image

So I would decorate any function that I only want the owner of said model to be able to access. For instance, I could decorate the editProfile() function with @user_is_owner which would only allow the user to edit the profile if they are the owner of said profile.