Opened 4 years ago

Last modified 4 years ago

#31093 closed New feature

Extend permission backend with get_queryset(user, model) — at Version 2

Reported by: James Pic Owned by: nobody
Component: contrib.auth Version: dev
Severity: Normal Keywords:
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description (last modified by James Pic)

Permissions on objects are based on two mechanisms that developers have to implement:

  • returning if a user has a permission on an object instance
  • filtering a queryset based on a user object and eventually a permission name

Currently, permission backend allows developers to implement the first mechanism: you can allow a specific permission on an object with the permission backend.

This works extremely well even for complex use cases: you get an model object, a user, a permission name and you can return True.

Exemple:

    def has_perm(self, user_obj, perm, obj=None):    
        if not user_obj.is_authenticated or not isinstance(obj, MRSRequest):    
            return False
    
        return (    
            user_obj.profile == 'admin'    
            or obj.caisse in user_obj.caisses.all()    
        ) 

However, permission framework should also allow developers to implement the second security mechanism: getting a filtered queryset with objects a user should be able to see, eventually for a given permission. Such implementation could look like:

    def filter_queryset(self, user_obj, perm, queryset=None):
        if not queryset.model == MRSRequest:
            return queryset

        if not user_obj.is_authenticated:    
            return queryset.none()    
    
        return queryset.filter(caisse__in=user_obj.caisses.all())

The admin views could use this, and django.contrib.auth could provide generic views extensions which do check permissions, removing the need to share a mixin that just does return a Mixin with a get_queryset method to complement the code that they have in the permission backend. It would reduce chances to make a mistake when updating permission code if it's all at the same place, an opinion that I consider suited for a framework like Django.

Change History (2)

comment:1 by James Pic, 4 years ago

Description: modified (diff)

comment:2 by James Pic, 4 years ago

Description: modified (diff)
Note: See TracTickets for help on using tickets.
Back to Top