Django User doesn't inherit permissions from its group

Django 4.0.1

I when through the Django documentation in order to learn how groups and permissions are
used in Django.

I have set up an AbastractUser with a custom manager:

class User(AbstractUser):
    ...
    objects = UserManager()
    ... 

The manager:

INITIAL_REGISTRATION_GROUP = 'non_subscriber'
class UserManager(BaseUserManager):
    def create_user(....)
      ....
      user.save(using=self._db)
      non_subscriber_group = Group.objects.get(name=INITIAL_REGISTRATION_GROUP)
      user.groups.add(non_subscriber_group)
      return user

Now, I have a script that creates groups and permissions:

groups = [
    'subscriber',
    'free_trial',
    'non_subscriber'
]

groups_permissions_mapping = {
    'subscriber': 'subscriber_permissions',
    'free_trial': 'free_trial_permissions',
    'non_subscriber': 'non_subscriber_permissions'
}


class Command(BaseCommand):

    help ='Setup user groups and permissions'

    @transaction.atomic
    def handle(self, *args, **options):
        for group in groups:
            new_group, created = Group.objects.get_or_create(name=group)
            ct = ContentType.objects.get_for_model(User)
            permission = Permission.objects.create(
                codename=groups_permissions_mapping[group],
                name=groups_permissions_mapping[group].replace("_", " ").title(),
                content_type=ct
            )
            new_group.permissions.add(permission)

The problem is that the user instance that is created (or any other existing user that I have added to the non_subscriber group) doesn’t inherit the group permission non_subscriber_permissions.

On filtering the permission model with a given user it returns an empty queryset

Permission.objects.filter(user=user)
<QuerySet []>

user.get_user_permissions()
set()

But I can see that the user’s group has the missing permission:

user.groups.first().permissions.all()
<QuerySet [<Permission: users | user | Non Subscriber Permissions>]>```

Any idea why permissions are not inherited from the group that the user is assigned on user creation?

They are inherited, they just aren’t directly assigned.

If you test for user.has_perm(…), it should return True. Or, you can all call user.get_group_permissions() to get the list of permissions granted to that user through their group membership.

That is the thing, calling

user.get_group_permissions()
set()

or calling

user.has_perm("non_subscriber_permissions")
False

So I won’t be able to show/hide content based on the group permissions because they both result in False or empty

That’s the wrong format for that call - it’s “app.permission” name - in this case ‘users.non_subscriber_permissions’ from what I can see.

Still False though :confused:

In the admin panel I cannot see the permission being assigned to the user

Correct. You will never see it directly assigned. The rights don’t get copied to the user. The user is assigned to the group, and the group has the permissions.

Now, if you look at the group, you should see that permission assigned.

Yes, the group has the permissions. I might be missing the point then of
the Django’s permissions and groups.

What is the point to have a user assigned to a group if I can’t do user.has_perm(some_perm) in a
view or API in order to give this user rights to do or not to do something?

You can do user.has_perm. That’s exactly how it works.

If you’re getting a False, then you’ve got something else wrong.
(Verify that user.is_active is True - that’s something commonly missed.)

1 Like

Yes, testing the user’s permissions through the shell won’t give me user.is_active…

Thank you again for your quick solution :slight_smile:

I have the same problem and my user is active. what should I do?

This topic is marked as solved. If you’re having an issue with the permissions system, I would recommend you open up a new topic for discussion.

When you do, please include all the relevant details - including a description of what you want to see happen compared to what’s currently happening. If you’re getting any kind of error message or traceback, please include that in your post as well.

When posting code, templates, error messages, etc, enclose each block of text (code, etc) between lines of three backtick - ` characters. This means you’ll have a line of ```, then your text, then another line of ```. This forces the forum software to keep that text properly formatted, which is critical with Python.

1 Like