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

Add support for filter+permission approach to handle all request methods #1

Open
devmonkey22 opened this issue Apr 13, 2021 · 0 comments
Labels
enhancement New feature or request

Comments

@devmonkey22
Copy link
Owner

devmonkey22 commented Apr 13, 2021

To complete proper support for creating new objects (i.e. POST methods), it isn't sufficient to just use DRF filter_backends against a given model. There isn't a model yet created. There are probably several approaches, but the one I recommend (that has been working well in a different app) is the following:

  • Add a get_parent_object() view method
    • (May need cached at the view/request level because it'll get called several times)
  • Add a custom DRF Permission class:
    • To check if a user is allowed to do a POST request by:
      • Get parent object from view, if available (for example, if the URL contains a related (parent) field's PK, that would be the parent object to get). In some cases, I default to the current user as the parent (like a root-level object).
      • Check if the user is allowed to add the new model/object (ie: does the user have the "add_{model}" permission by checking the parent object's policy implicitly like allow(user, "add_case", client))
    • Pairing this permission class with the Filter backend should cover add (POST), view (GET), change (PUT/PATCH), and delete (DELETE) actions that need checked.

To support this more generic approach, models may need a few details embedded on their class like:

  • Create a custom meta class like class AuthorizeMeta:
    • Define if model supports authorization directly (has its own policies) or if a parent (related) object/field should be used (one that does support authorization). This can help support ancillary models that may not need their own policy, but can piggyback on its parent - ie: to add an ancillary model, check if the user can "change" the parent object.
    • The permission/filter classes and/or lower level functions can inspect the model's meta class to see if it needs to find this related/parent object instead.

A generic approach obviously can be very powerful, but can be complex to implement. Your use case may vary.

As extensions to this approach, I also have implemented elsewhere things like:

  • A decorator like authorized_view to apply to the APIView or GenericAPIView (subclasses) which will auto-add the base authorization filter and permission classes, if one isn't explicitly added to the view's filter_backends or permission_classes.
  • Custom permission and filter classes that act like a manual authorization marker, which indicates to the decorator not to add the filter and/or permission class. I have to use this in cases where I need to manually check policies within the get() etc handlers with information that just isn't feasible to expose through generic permission or filter classes.
@devmonkey22 devmonkey22 added the enhancement New feature or request label Apr 13, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

1 participant