diff --git a/djangoldp/permissions.py b/djangoldp/permissions.py index 7ff76745b1fe461ce1ebff886d58556a5a3d561e..7b5c1345a60808f019aac5c518c57eb4029e7a40 100644 --- a/djangoldp/permissions.py +++ b/djangoldp/permissions.py @@ -34,6 +34,13 @@ class WACPermissions(permissions.DjangoObjectPermissions): else: return super().has_permission(request, view) + # This method should be overriden by other permission classes + def user_permissions(self, request, obj): + return [] + + def filter_user_perms(self, request, obj, permissions): + return [perm for perm in permissions if perm in self.user_permissions(request, obj)] + class ObjectFilter(filters.BaseFilterBackend): def filter_queryset(self, request, queryset, view): @@ -51,25 +58,33 @@ class ObjectPermission(WACPermissions): class InboxPermissions(WACPermissions): """ - Anonymous users: can create notifications but can't read - Logged in users: can create notifications but can't read - Inbox owners: can read + update all notifications + Everybody can create + Author can edit """ - filter_class = ObjectFilter + anonymous_perms = ['view', 'create'] + authenticated_perms = ['view', 'create'] + author_perms = ['view'] def has_permission(self, request, view): - if view.action in ['create', 'retrieve', 'update', 'partial_update', 'destroy']: + if view.action in ['create', 'list', 'retrieve']: return True else: return super().has_permission(request, view) def has_object_permission(self, request, view, obj): - if view.action == "create": - return True - if hasattr(obj._meta, 'auto_author'): - if request.user == getattr(obj, obj._meta.auto_author): - return True - return super().has_object_permission(request, view) + if view.action in ['update', 'partial_update', 'destroy']: + return False + else: + return super().has_object_permission(request, view) + + def user_permissions(self, request, obj): + if request.user.is_anonymous: + return self.anonymous_perms + else: + if hasattr(obj._meta, 'auto_author') and getattr(obj, obj._meta.auto_author) == request.user: + return self.author_perms + else: + return self.authenticated_perms class AnonymousReadOnly(WACPermissions): @@ -79,9 +94,9 @@ class AnonymousReadOnly(WACPermissions): Author: can read all posts + create new posts + update their own """ - anonymous_perms = [{'mode': {'@type': 'view'}}] - authenticated_perms = [{'mode': {'@type': 'view'}}, {'mode': {'@type': 'add'}}] - author_perms = [{'mode': {'@type': 'view'}}, {'mode': {'@type': 'add'}}, {'mode': {'@type': 'change'}}] + anonymous_perms = ['view'] + authenticated_perms = ['view', 'add'] + author_perms = ['view', 'add', 'change', 'control', 'delete'] def has_permission(self, request, view): if view.action in ['list', 'retrieve']: @@ -94,7 +109,7 @@ class AnonymousReadOnly(WACPermissions): def has_object_permission(self, request, view, obj): if view.action == "create" and request.user.is_authenticated(): return True - elif view.action == ["list", "retrieve"]: + elif view.action in ["list", "retrieve"]: return True elif view.action in ['update', 'partial_update', 'destroy']: if hasattr(obj._meta, 'auto_author'): @@ -103,3 +118,12 @@ class AnonymousReadOnly(WACPermissions): return True else: return super().has_object_permission(request, view, obj) + + def user_permissions(self, request, obj): + if request.user.is_anonymous: + return self.anonymous_perms + else: + if hasattr(obj._meta, 'auto_author') and getattr(obj, obj._meta.auto_author) == request.user: + return self.author_perms + else: + return self.authenticated_perms diff --git a/djangoldp/serializers.py b/djangoldp/serializers.py index 29043b50ccc064ef28d37ebb9260bfebe0d0b00c..5c167c0dc0e35f9e69121de2add1b8823e08bf0b 100644 --- a/djangoldp/serializers.py +++ b/djangoldp/serializers.py @@ -204,25 +204,26 @@ class LDPSerializer(HyperlinkedModelSerializer): pass return fields + list(getattr(self.Meta, 'extra_fields', [])) + def get_permissions(self, obj): + permissions = ['view', 'add', 'change', 'control', 'delete'] + + if hasattr(obj._meta, 'permission_classes'): + for permission_class in obj._meta.permission_classes: + permissions = permission_class().filter_user_perms(self.context['request'], obj, permissions) + + permissions += get_perms(self.context['request'].user, obj) + return [{'mode': {'@type': name.split('_')[0]}} for name in permissions] + def to_representation(self, obj): data = super().to_representation(obj) if hasattr(obj._meta, 'rdf_type'): data['@type'] = obj._meta.rdf_type - data['permissions'] = [{'mode': {'@type': name.split('_')[0]}} for name in - get_perms(self.context['request'].user, obj)] - - if self.context['request'].user.is_anonymous: - data['permissions'] += permissions.AnonymousReadOnly.anonymous_perms - elif self.context['request'].user.is_authenticated: - if hasattr(obj._meta, 'auto_author'): - data['permissions'] += permissions.AnonymousReadOnly.author_perms - else: - data['permissions'] += permissions.AnonymousReadOnly.authenticated_perms - if hasattr(obj._meta, 'rdf_context'): data['@context'] = obj._meta.rdf_context - + + data['permissions'] = self.get_permissions(obj) + return data def build_field(self, field_name, info, model_class, nested_depth): diff --git a/djangoldp/tests/tests_user_permissions.py b/djangoldp/tests/tests_user_permissions.py index 9f510926f6146eb85dc3934df149cd1308f33988..5bda0e5880cc96337b74e0344cf8f3f087e882d8 100644 --- a/djangoldp/tests/tests_user_permissions.py +++ b/djangoldp/tests/tests_user_permissions.py @@ -7,6 +7,7 @@ from djangoldp.views import LDPViewSet import json + class TestUserPermissions(APITestCase): def setUp(self):