Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Permission case issues with CustomUser #132

Open
FeralRobot opened this issue Sep 26, 2021 · 3 comments
Open

Permission case issues with CustomUser #132

FeralRobot opened this issue Sep 26, 2021 · 3 comments

Comments

@FeralRobot
Copy link

FeralRobot commented Sep 26, 2021

Running` django 2.2.5 with django-role-permissions with the django default user - I can define an "Admin" role and logging into the django admin with that "Admin" role, I can view the set of Users that "Admin" role has permission to view.

Default User
roles.py                   permission generated                            permission required
'view_user'                    'View User'                                           'View User'     (apparently)

Now I update the application to use a CustomUser model. My template/admin/index.html stops working when using rolepermission template tags, specifically has_role, meaning the "Admin" role can no longer view Users (for example). has_role is still returning true though, so eventually I look at permissions. In the django admin change user form, I discover the User permissions have changed and I can bring back the views by manually adding the permission 'Can view user', note that only the first word in this permission is capitalized.

Custom User
roles.py                   permission generated                            permission required
'Can_view_user'            'Can View User'                                     'Can view user'     (apparently)

So I am unable to generate the required permissions with django-role-permissions for the groups that I am using in my application. In that application I'm using groups generated by roles.py to assign permissions for all user types. So this is a breaking change for me.

I am using the RolePermissionsUserAdmin to create the CustomAdmin, though I had to move the code into my application because I had a CustomUserAdmin in my app as well, and I needed all the UserAdmin customizations in one place.

Any suggestions about how I could generate the required permission capitalization 'Can view user', or is there some way to configure django to have case insensitive permissions?

@fjsj
Copy link
Member

fjsj commented Sep 27, 2021

I'm not sure if I understand the issue correctly. Could you please share the relevant parts of you roles.py and what behavior you expect?

Isn't this a case where your new CustomUser model doesn't have the right permissions, as the old one?

Check https://docs.djangoproject.com/en/3.2/topics/auth/default/#default-permissions

@FeralRobot
Copy link
Author

FeralRobot commented Sep 28, 2021

To answer your second question first, yes, my new CustomUser model doesn't have the right permissions. The issue is I cannot create the new permissions that I need using django-role-permissions.

Here is my original / current roles.py:

class Admin(AbstractUserRole):
    available_permissions = {
        'run_task': True,
        'run_scheduled_task': True,
        'view_cred': True,
        'create_cred': True,
        'delete_cred': True,
        'create_user': True,
        'delete_user': True,
        'view_user': True,
        'change_user': True,
        'add_user': True,
    }

This creates permissions named Add User, Change User, View User, Delete User, and this works fine with the default django user model. These permission names are created as Title Case by django-role-permissions, as the documentation describes.

Now I move the user model to CustomUser. The symptom appears, which is I can no longer see the users when I log into the django admin as "Admin" role. I use the template permission tags, with has_role in the template logic. We can come back to the template discussion, but I don't believe this is the heart of the issue.

With the CustomUser model implemented, I now log into the django admin as superuser. I now see eight permissions for the superuser associated with users: Add User, Change User, View User, Delete User (the four original ones), and four new ones Can add user, Can change user, Can view user, Can delete user. Notice the case of these last four permissions, it's like a sentence with just the first letter in the first word capitalized. In the django admin, I add the Can view user permission to my "Admin" user. Now I login again to the django admin as the "Admin" user. I can now view the users. Great! I think, I just need to create these new permissions with django-role-permissions.

I go to the roles file above and add:
'Can_view_user':True,

The permission django-role-permissions then creates is Can View User (note the Title Case) which does not match the case of Can view user. I login to the django admin after this change to the roles file, and I am still unable to view the users in the django admin.

Desired behavior from django-role-permission:

snake case in ===> Title Case out (no change, this is the current default behavior)
"sentence case" in ===> Sentence case out (not Title Case)

example:

'view_user':True, in roles.py ===> View User is the permission name created
'Can_view_user': True in roles.py ===> Can view user is the permission name created

@FeralRobot
Copy link
Author

Something like this in rolepermissions/utils.py

import re


def Sentence_case(s):
    return s[0].isupper() and sum([int(x[0].isupper()) for x in s.split('_')]) == 1


def camelToSnake(s):
    """
    https://gist.github.com/jaytaylor/3660565
    Is it ironic that this function is written in camel case, yet it
    converts to snake case? hmm..
    """
    if Sentence_case(s):
        return s
    else:
        _underscorer1 = re.compile(r'(.)([A-Z][a-z]+)')
        _underscorer2 = re.compile('([a-z0-9])([A-Z])')

        subbed = _underscorer1.sub(r'\1_\2', s)
        return _underscorer2.sub(r'\1_\2', subbed).lower()


def snake_to_title(s):
    if Sentence_case(s):
        return ' '.join(s.split('_'))
    else:
        return ' '.join(x.capitalize() for x in s.split('_'))


def camel_or_snake_to_title(s):
    return snake_to_title(camelToSnake(s))


tests = ['camelCase', 'snake_case', 'Can_add_user']
for t in tests:
    print(camel_or_snake_to_title(t))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants