Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django Per Object Permission for Your Own User Model

I have implemented my own User model class as follows. Note that is it NOT customizing django's auth.User model. I am new to this object permission knowledge and especially in this self-defined User model which is required in my project.

Could you give an example of adding per-object permission in this case?

from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin

class CustomUser(AbstractBaseUser, PermissionsMixin):
         email = models.EmailField(max_length=40, unique=True)
         #.... other fields are omitted

class Article(models.Model):
    title = models.CharField('title', max_length=120)
    body = models.TextField('body')
    author = models.ForeignKey(CustomUser)

Now, the object permission comes into play. Each user can create/update/delete/view their own article objects, but ONLY view others' articles without permission to update/delete them.

From the Django docs, the Model level permission does not apply here. If the Article is given model level update permission, then all users can update others' Articles.

I found out the django-guardian. However, there seems to be no hope for this self-defined CustomUser model, as it relies heavily on Django's auth.User model!

https://django-guardian.readthedocs.org/en/v1.2/userguide/custom-user-model.html

  1. My case is subclassing AbstractBaseUser instead of AbstractUser;
  2. This is not for the admin but only for my backend code logic;
  3. I am not using Django REST API here, but if REST API is proper, please give an example.
like image 736
thinkdeep Avatar asked Oct 20 '15 03:10

thinkdeep


People also ask

How do I add custom permissions to Django?

Django Admin Panel : In Admin Panel you will see Group in bold letter, Click on that and make 3-different group named level0, level1, level3 . Also, define the custom permissions according to the need. By Programmatically creating a group with permissions: Open python shell using python manage.py shell.

How do I give permission to a specific user in Django?

through django-adminopen your django-admin page and head to Users section and select your desired user . NOTE: Permission assigning process is a one-time thing, so you dont have to update it every time unless you need to change/re-assign the permissions.

How do I add permission to model in Django?

Add Permissions to a Group If you are using AbstractUser in Django, you must add AUTH_USER_MODEL = 'YourAppName. YourClassName' . This way, you are telling Django to use our custom user model instead of the default one. The code below should go in your admin.py file so that you can see your user model.

What is object level permissions in Django?

Object level permissions are used to determine if a user should be allowed to act on a particular object, which will typically be a model instance.


2 Answers

Object-level permissions are not built into Django, even when using the standard auth.User model. But the foundation is there in that Django's PermissionsMixin defines the has_perm method, which accepts a model instance. Django does nothing with it by default, but you can.

The has_perm method effectively passes the hard work off onto the registered authentication backends. So you can create a custom authentication backend specifically for performing your object-level permission checks. It does not need to actually handle authentication. It can be as simple as a single method on a basic class. Something like the following (untested) is all you should need:

class ObjectPermissionsBackend(object):

    def has_perm(self, user_obj, perm, obj=None):
        if not obj:
            return False # not dealing with non-object permissions

        if perm == 'view':
            return True # anyone can view
        elif obj.author_id == user_obj.pk:
            return True
        else:
            return False

Tell Django to use your custom backend using the AUTHENTICATION_BACKENDS setting. In settings.py:

AUTHENTICATION_BACKENDS = ('django.contrib.auth.backends.ModelBackend', 'path.to.ObjectPermissionsBackend')

Then, in your code:

if user.has_perm('edit', article_instance):
    # allow editing

See https://docs.djangoproject.com/en/1.8/topics/auth/customizing/#custom-users-and-permissions and https://docs.djangoproject.com/en/1.8/topics/auth/customizing/#specifying-authentication-backends

like image 63
oogles Avatar answered Sep 21 '22 01:09

oogles


I end up using logic based per-object permission so that it does not alter my database. It is django-rules which support my class based view. Remember to override the redirect_field_name, otherwise, you will end up with redirect loop if users are logged in.

like image 42
thinkdeep Avatar answered Sep 17 '22 01:09

thinkdeep