fixed permissions and tests
This commit is contained in:
parent
f02eac8ac6
commit
e7de6f62b6
@ -206,6 +206,14 @@ class CustomIsOwner(permissions.BasePermission):
|
|||||||
return is_object_owner(request.user, obj)
|
return is_object_owner(request.user, obj)
|
||||||
|
|
||||||
|
|
||||||
|
class CustomIsOwnerReadOnly(CustomIsOwner):
|
||||||
|
def has_permission(self, request, view):
|
||||||
|
return super().has_permission(request, view) and request.method in SAFE_METHODS
|
||||||
|
|
||||||
|
def has_object_permission(self, request, view, obj):
|
||||||
|
return super().has_object_permission(request, view) and request.method in SAFE_METHODS
|
||||||
|
|
||||||
|
|
||||||
class CustomIsSpaceOwner(permissions.BasePermission):
|
class CustomIsSpaceOwner(permissions.BasePermission):
|
||||||
"""
|
"""
|
||||||
Custom permission class for django rest framework views
|
Custom permission class for django rest framework views
|
||||||
@ -214,7 +222,7 @@ class CustomIsSpaceOwner(permissions.BasePermission):
|
|||||||
message = _('You cannot interact with this object as it is not owned by you!')
|
message = _('You cannot interact with this object as it is not owned by you!')
|
||||||
|
|
||||||
def has_permission(self, request, view):
|
def has_permission(self, request, view):
|
||||||
return request.user.is_authenticated
|
return request.user.is_authenticated and request.space.created_by == request.user
|
||||||
|
|
||||||
def has_object_permission(self, request, view, obj):
|
def has_object_permission(self, request, view, obj):
|
||||||
return is_space_owner(request.user, obj)
|
return is_space_owner(request.user, obj)
|
||||||
|
@ -2,11 +2,13 @@ import json
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from django.contrib import auth
|
from django.contrib import auth
|
||||||
|
from django.contrib.auth.models import AnonymousUser
|
||||||
from django.db.models import OuterRef, Subquery
|
from django.db.models import OuterRef, Subquery
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django_scopes import scopes_disabled
|
from django_scopes import scopes_disabled
|
||||||
|
|
||||||
from cookbook.models import Ingredient, Step, InviteLink
|
from cookbook.helper.permission_helper import switch_user_active_space
|
||||||
|
from cookbook.models import Ingredient, Step, InviteLink, UserSpace
|
||||||
|
|
||||||
LIST_URL = 'api:invitelink-list'
|
LIST_URL = 'api:invitelink-list'
|
||||||
DETAIL_URL = 'api:invitelink-detail'
|
DETAIL_URL = 'api:invitelink-detail'
|
||||||
@ -17,7 +19,7 @@ DETAIL_URL = 'api:invitelink-detail'
|
|||||||
['g1_s1', 403, 0],
|
['g1_s1', 403, 0],
|
||||||
['u1_s1', 403, 0],
|
['u1_s1', 403, 0],
|
||||||
['a1_s1', 200, 1],
|
['a1_s1', 200, 1],
|
||||||
['a2_s1', 200, 0],
|
['a2_s1', 403, 0],
|
||||||
])
|
])
|
||||||
def test_list_permission(arg, request, space_1, g1_s1, u1_s1, a1_s1):
|
def test_list_permission(arg, request, space_1, g1_s1, u1_s1, a1_s1):
|
||||||
space_1.created_by = auth.get_user(a1_s1)
|
space_1.created_by = auth.get_user(a1_s1)
|
||||||
@ -38,7 +40,7 @@ def test_list_permission(arg, request, space_1, g1_s1, u1_s1, a1_s1):
|
|||||||
['a1_s1', 200],
|
['a1_s1', 200],
|
||||||
['g1_s2', 403],
|
['g1_s2', 403],
|
||||||
['u1_s2', 403],
|
['u1_s2', 403],
|
||||||
['a1_s2', 404],
|
['a1_s2', 403],
|
||||||
])
|
])
|
||||||
def test_update(arg, request, space_1, u1_s1, a1_s1):
|
def test_update(arg, request, space_1, u1_s1, a1_s1):
|
||||||
with scopes_disabled():
|
with scopes_disabled():
|
||||||
@ -75,6 +77,7 @@ def test_add(arg, request, a1_s1, space_1):
|
|||||||
space_1.created_by = auth.get_user(a1_s1)
|
space_1.created_by = auth.get_user(a1_s1)
|
||||||
space_1.save()
|
space_1.save()
|
||||||
c = request.getfixturevalue(arg[0])
|
c = request.getfixturevalue(arg[0])
|
||||||
|
|
||||||
r = c.post(
|
r = c.post(
|
||||||
reverse(LIST_URL),
|
reverse(LIST_URL),
|
||||||
{'group': {'id': 3, 'name': 'admin'}},
|
{'group': {'id': 3, 'name': 'admin'}},
|
||||||
@ -107,7 +110,7 @@ def test_delete(u1_s1, u1_s2, a1_s1, a2_s1, space_1):
|
|||||||
args={il.id}
|
args={il.id}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
assert r.status_code == 404
|
assert r.status_code == 403
|
||||||
|
|
||||||
# owner can delete
|
# owner can delete
|
||||||
r = a1_s1.delete(
|
r = a1_s1.delete(
|
||||||
|
@ -29,20 +29,23 @@ def test_list_permission(arg, request, space_1, a1_s1):
|
|||||||
assert len(json.loads(result.content)) == arg[2]
|
assert len(json.loads(result.content)) == arg[2]
|
||||||
|
|
||||||
|
|
||||||
def test_list_permission_owner(u1_s1, space_1):
|
def test_list_permission_owner(u1_s1, a1_s1, space_1):
|
||||||
assert len(json.loads(u1_s1.get(reverse(LIST_URL)).content)) == 0
|
space_1.created_by = auth.get_user(a1_s1)
|
||||||
|
space_1.save()
|
||||||
|
assert len(json.loads(a1_s1.get(reverse(LIST_URL)).content)) == 1
|
||||||
|
assert u1_s1.get(reverse(LIST_URL)).status_code == 403
|
||||||
space_1.created_by = auth.get_user(u1_s1)
|
space_1.created_by = auth.get_user(u1_s1)
|
||||||
space_1.save()
|
space_1.save()
|
||||||
assert len(json.loads(u1_s1.get(reverse(LIST_URL)).content)) == 1
|
assert u1_s1.get(reverse(LIST_URL)).status_code == 403
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("arg", [
|
@pytest.mark.parametrize("arg", [
|
||||||
['a_u', 403],
|
['a_u', 403],
|
||||||
['g1_s1', 404],
|
['g1_s1', 403],
|
||||||
['u1_s1', 404],
|
['u1_s1', 403],
|
||||||
['a1_s1', 200],
|
['a1_s1', 200],
|
||||||
['g1_s2', 404],
|
['g1_s2', 403],
|
||||||
['u1_s2', 404],
|
['u1_s2', 403],
|
||||||
['a1_s2', 404],
|
['a1_s2', 404],
|
||||||
])
|
])
|
||||||
def test_update(arg, request, space_1, a1_s1):
|
def test_update(arg, request, space_1, a1_s1):
|
||||||
@ -66,8 +69,8 @@ def test_update(arg, request, space_1, a1_s1):
|
|||||||
|
|
||||||
@pytest.mark.parametrize("arg", [
|
@pytest.mark.parametrize("arg", [
|
||||||
['a_u', 403],
|
['a_u', 403],
|
||||||
['g1_s1', 405],
|
['g1_s1', 403],
|
||||||
['u1_s1', 405],
|
['u1_s1', 403],
|
||||||
['a1_s1', 405],
|
['a1_s1', 405],
|
||||||
])
|
])
|
||||||
def test_add(arg, request, u1_s2):
|
def test_add(arg, request, u1_s2):
|
||||||
@ -90,7 +93,7 @@ def test_delete(u1_s1, u1_s2, a1_s1, space_1):
|
|||||||
args={space_1.id}
|
args={space_1.id}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
assert r.status_code == 405
|
assert r.status_code == 403
|
||||||
|
|
||||||
# event the space owner cannot delete his space over the api (this might change later but for now it's only available in the UI)
|
# event the space owner cannot delete his space over the api (this might change later but for now it's only available in the UI)
|
||||||
r = a1_s1.delete(
|
r = a1_s1.delete(
|
||||||
@ -99,4 +102,4 @@ def test_delete(u1_s1, u1_s2, a1_s1, space_1):
|
|||||||
args={space_1.id}
|
args={space_1.id}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
assert r.status_code == 204
|
assert r.status_code == 405
|
||||||
|
@ -78,9 +78,9 @@ def test_update_space_owner(a1_s1, space_1):
|
|||||||
|
|
||||||
@pytest.mark.parametrize("arg", [
|
@pytest.mark.parametrize("arg", [
|
||||||
['a_u', 403],
|
['a_u', 403],
|
||||||
['g1_s1', 405],
|
['g1_s1', 403],
|
||||||
['u1_s1', 405],
|
['u1_s1', 403],
|
||||||
['a1_s1', 405],
|
['a1_s1', 403],
|
||||||
])
|
])
|
||||||
def test_add(arg, request, u1_s1, space_1):
|
def test_add(arg, request, u1_s1, space_1):
|
||||||
c = request.getfixturevalue(arg[0])
|
c = request.getfixturevalue(arg[0])
|
||||||
|
@ -45,7 +45,7 @@ from cookbook.helper.image_processing import handle_image
|
|||||||
from cookbook.helper.ingredient_parser import IngredientParser
|
from cookbook.helper.ingredient_parser import IngredientParser
|
||||||
from cookbook.helper.permission_helper import (CustomIsAdmin, CustomIsGuest, CustomIsOwner,
|
from cookbook.helper.permission_helper import (CustomIsAdmin, CustomIsGuest, CustomIsOwner,
|
||||||
CustomIsShare, CustomIsShared, CustomIsUser,
|
CustomIsShare, CustomIsShared, CustomIsUser,
|
||||||
group_required, CustomIsSpaceOwner, switch_user_active_space, is_space_owner)
|
group_required, CustomIsSpaceOwner, switch_user_active_space, is_space_owner, CustomIsOwnerReadOnly)
|
||||||
from cookbook.helper.recipe_html_import import get_recipe_from_source
|
from cookbook.helper.recipe_html_import import get_recipe_from_source
|
||||||
from cookbook.helper.recipe_search import RecipeFacet, RecipeSearch, old_search
|
from cookbook.helper.recipe_search import RecipeFacet, RecipeSearch, old_search
|
||||||
from cookbook.helper.shopping_helper import RecipeShoppingEditor, shopping_helper
|
from cookbook.helper.shopping_helper import RecipeShoppingEditor, shopping_helper
|
||||||
@ -386,7 +386,7 @@ class SpaceViewSet(viewsets.ModelViewSet):
|
|||||||
class UserSpaceViewSet(viewsets.ModelViewSet):
|
class UserSpaceViewSet(viewsets.ModelViewSet):
|
||||||
queryset = UserSpace.objects
|
queryset = UserSpace.objects
|
||||||
serializer_class = UserSpaceSerializer
|
serializer_class = UserSpaceSerializer
|
||||||
permission_classes = [CustomIsSpaceOwner]
|
permission_classes = [CustomIsSpaceOwner | CustomIsOwnerReadOnly]
|
||||||
http_method_names = ['get', 'patch', 'delete']
|
http_method_names = ['get', 'patch', 'delete']
|
||||||
|
|
||||||
def destroy(self, request, *args, **kwargs):
|
def destroy(self, request, *args, **kwargs):
|
||||||
|
Loading…
Reference in New Issue
Block a user