Skip to content

Discussion_John_2020 05 11

Travis Risner edited this page May 13, 2020 · 2 revisions

Discussion with John Cassidy over Discord on May 11, 2020

Mostly about adding Permissions to the application

The comments below have been slightly edited.


John

Travis, Working on issue #173 ran into problem with test case that I'm trying to sort out. Was figuring I'd spend a little bit of time either working on #173 or taking a look at the permissions issue. Figured the first step in the permissions issue would be to put together a spreadsheet of the views and what permissions we want to require.

Travis

There are issues with the details of the permissions... Issues 208, 209, and 210

John

Thinking if we create some custom permissions for things like move box, empty box, move pallet (easy thing to do in the model) that would make enforcing those permissions straight-forward.

Travis

OK, I'm not sure how that would work, but go for it if that is easier. Is the details in issues 208 - 210 sufficient? Does that work with the permissions plan you have in mind?

John

Volunteer and staff fit with the permissions I'm thinking of.

Travis

Can you show me the code for one of the models to have the permissions you have in mind in a branch on your public repo? I would like to see the code so I can understand it better.

John

The admin group might be handled by either designating members as staff or maybe as superuser.

Travis

yes, we can go the way you designated for admin for now. If it turns out we need more granular control, we can add it later.

John

hang on, I'm trying to find section of documentation with how to define custom permissions.

[Customizing authenication in Django]( <https://docs.djangoproject.com/en/3.0/topics/auth/customizing#custom-permissions)

Travis

Let me take 10 min or so to skim through it before I ask questions....

John

so that's what defining a new permission looks like

class Pallet(models.Model):
    """
    Temporary file to build up a list of boxes on a pallet.
    """

    class Meta:
        ordering = ('name',)
        app_label = 'fpiweb'
        verbose_name_plural = 'Pallets'
        permissions = [
            ("move_pallet", "Can move pallet"),
    ]

On the view side you need to change the view from using a LoginRequired mixin to the PermissionRequiredMixin

Travis

I see. These permission elements can be grouped together, and then we assign people to the groups. Changing the mixin should not be a problem once we have the harness in place.

John

Using the Django authentication system will assign permissions to groups.

Travis

yes, assign to groups, that's what i meant. :slight_smile:

John

Here's what you do on the View side of things

class ManualPalletMoveView(PermissionRequiredMixin, View):

    pernission_required = (
        'fpiweb.move_pallet',
    )
Travis

Looks pretty straightforward.

John

Note that in permission_required the pattern is app_name.permission_name hence when defining custom permissions you want to do something like move_box instead of just move

Travis

Yes, I understand that each permission element needs to be unique to an action. Where or how do we collect the permission elements into groups? Is that done with the Django admin groups or in some other place?

John

I'd create a quick script to set up groups and grant permissions.

Travis

Does that reside in a table in fpiweb then? The data I mean?

John

If you look in database using ./manage.py dbshell you'll see some auth_... tables where authentication/authorization info is stored.

Travis

Yup, I see them. Would our custom permission elements go in auth_permission then?

John

    from django.contrib.auth.models import Group, Permission
    >>> group, created = Group.objects.get_or_create(name='Volunteers')
    >>> group
    <Group: Volunteers>
    >>> created
    True
    >>> from django.contrib.auth.models import Group, Permission
    >>> group, created = Group.objects.get_or_create(name='Volunteers')
    >>> group
    <Group: Volunteers>
    >>> created
    True

That's how you programatically create a group. Yes the permissions are added to there, but adding the permission will need a migration and that migration will insert the record for you.

Travis

OK. I had already created groups and assigned users in my local db. I was just wondering where our custom permissions were stored.

John
permission = Permission.objects.get(content_type__app_label='fpiweb', content_type__model='pallet', codename='move_pallet')

that's how you retrieve a permission from that database (note that the model name is in lowercase)

Travis

Thanks for the clarification. Do you want to go ahead and do the whole thing or is there some part of this you would like me to do?

John

To grant permission to group group.permissions.add(permission) Thinking about that.

Travis

Perhaps I could work on issue 175, or at least set up shell? Issue #175

John

I think that's a good one to start with. Would give you a chance to work with PermissionRequiredMixin

John

You won't need to define any custom permissions for that one. Use existing create, update, delete (they're probably 'auth.add_user' etc or something like that? Not sure if "user.email" is a required field. You might need to specify a bogus email "default@warm.org" or whatever.

Travis

I won't make it a required field. However, if someone wants to put it in, this would be the only place to do it. If Django makes it required, then yes, I will stick a bogus email in.

John

well, it might be optional in your form, but I'm not certain as to whether it's a nullable field in the database.

Travis

Django has it marked not null, so fakey time :slight_smile:

John
user = User.objects.create(username='volunteer1')

Note there's also the option of inactivating a user account instead of deleting the user record.

Travis

Hmmm, it let me create it that way, and the db does not have a visible value in it.

John

At work we have lots of tables with foreign keys to user so we just deactivate the user instead of deleting them.

Travis

it has an empty string I didn't plan on actually deleting the user record, just marking it inactive. Apparently that is what your work does?

John

Deactivating the user makes sense. I don't imagine staff and admin users will change much. If having a bunch of volunteer users in the system becomes a nuisance, we can consider deleting them.

Travis

Ok with group names of "Admin", "Staff", and "Volunteer"? Sorry, let's make the first "Administrator"

John

I'd hold off on creating an Admin group for now. It's close to just being a Django superuser. You probably will need to add logic to your view that only admin users can create admin users.

Travis

Yes, that was added as a comment to #175

Permitted roles (Permission levels)

*   Staff can set staff or volunteer
*   Admin can set any level
John
👍

I think that covers all the bases as far as 175 is concerned.

Travis

BTW, I will probably start by documenting this (at least the parts I understand). I will push that up to the main repository so you can see, adjust it as needed and let you know.

John

I'm going to see if I can wrap up #173. See you later.

Travis

Farewell, and thanks for your help!

John

You're welcome