diff --git a/djangoldp/permissions.py b/djangoldp/permissions.py index ef3ef90e0397beea0771af9cdd0fd2e2031940bd..78f65d19024f43374f3f1b64b821e6ef0ae6b234 100644 --- a/djangoldp/permissions.py +++ b/djangoldp/permissions.py @@ -235,7 +235,7 @@ class JoinMembersPermission(LDPBasePermission): class InheritPermissions(LDPBasePermission): - """Checks read access on a related objects""" + """Gets the permissions from a related objects""" @classmethod def get_parent_fields(cls, model: object) -> list: '''checks that the model is adequately configured and returns the associated model''' @@ -267,7 +267,7 @@ class InheritPermissions(LDPBasePermission): # For some reason if we copy the request itself, we go into an infinite loop, so take the native request instead _request = copy(request._request) _request.model = model - _request.method = 'HEAD' #only view access is checked on parent + _request.data = request.data #because the data is not present on the native request _request._request = _request #so that it can be nested _view = copy(view) _view.queryset = None #to make sure the model is taken into account @@ -348,8 +348,9 @@ class InheritPermissions(LDPBasePermission): for field in InheritPermissions.get_parent_fields(model): parent_model = InheritPermissions.get_parent_model(model, field) for parent_object in self.get_parent_objects(obj, field): - parent_perms = set.intersection(*[perm().get_permissions(user, parent_model, parent_object) - for perm in parent_model._meta.permission_classes]) - if not 'view' in parent_perms: # only give permissions if user has read access on the parent - return set() + parents.append(parent_object) + perms = perms.union(set.intersection(*[perm().get_permissions(user, parent_model, parent_object) + for perm in parent_model._meta.permission_classes])) + if parents: + return perms return super().get_permissions(user, model, obj) \ No newline at end of file diff --git a/djangoldp/tests/tests_permissions.py b/djangoldp/tests/tests_permissions.py index 6705378c2fb1bd41a4bed9256ebbdbb24fc95686..cd074be9904cc833d6d7fdcf46697024445f22f9 100644 --- a/djangoldp/tests/tests_permissions.py +++ b/djangoldp/tests/tests_permissions.py @@ -154,7 +154,7 @@ class TestPermissions(APITestCase): self.check_can_view('/doubleinheritmodels/', [myresource.urlid, some.urlid]) self.check_can_change(myresource.urlid) - self.check_can_change(some.urlid) + self.check_can_change(some.urlid, 403) self.check_can_change(other.urlid, 404) def test_inherit_permissions_none(self): diff --git a/docs/create_model.md b/docs/create_model.md index b78a221cee26889e083352f9feb185687fab41f7..92c0aec7642ff02d84fd20aad4eeea137b3d7258 100644 --- a/docs/create_model.md +++ b/docs/create_model.md @@ -317,7 +317,7 @@ DjangoLDP comes with a set of permission classes that you can use for standard b * PublicPermission: Give access based on a public flag on the object. This class must be used in conjonction with the Meta option `public_field`. This permission class is associated with a filter that only render objects that have the public flag set. * OwnerPermissions: Give access based on the owner of the object. This class must be used in conjonction with the Meta option `owner_field` or `owner_urlid_field`. This permission class is associated with a filter that only render objects of which the user is owner. When using a reverse ForeignKey or M2M field with no related_name specified, do not add the '_set' suffix in the `owner_field`. * OwnerCreatePermission: Refuse the creation of resources which owner is different from the request user. - * InheritPermissions: Give access based on view permissions on a related model. This class must be used in conjonction with the Meta option `inherit_permission`, which value must be a list of names of the `ForeignKey` or `OneToOneField` pointing to the objects bearing the permission classes. It also applies filter based on the related model. If several fields are given, at least one must give permission for the permission to be granted. + * InheritPermissions: Give access based on the permissions on a related model. This class must be used in conjonction with the Meta option `inherit_permission`, which value must be a list of names of the `ForeignKey` or `OneToOneField` pointing to the objects bearing the permission classes. It also applies filter based on the related model. If several fields are given, at least one must give permission for the permission to be granted. Permission classes can be chained together in a list, or through the | and & operators. Chaining in a list is equivalent to using the & operator.