diff --git a/cookbook/helper/permission_helper.py b/cookbook/helper/permission_helper.py index 9393292f..b701f543 100644 --- a/cookbook/helper/permission_helper.py +++ b/cookbook/helper/permission_helper.py @@ -2,7 +2,7 @@ from django.conf import settings from django.contrib import messages from django.contrib.auth.decorators import user_passes_test from django.core.cache import caches -from django.core.exceptions import ValidationError +from django.core.exceptions import ValidationError, ObjectDoesNotExist from django.http import HttpResponseRedirect from django.urls import reverse, reverse_lazy from django.utils.translation import gettext as _ @@ -326,13 +326,21 @@ def above_space_user_limit(space): return False, '' -def switch_user_active_space(user, user_space): +def switch_user_active_space(user, space): """ Switch the currently active space of a user by setting all spaces to inactive and activating the one passed :param user: user to change active space for - :param user_space: user space object to activate + :param space: space to activate user for + :return user space object or none if not found/no permission """ - if not user_space.active: - UserSpace.objects.filter(user=user).update(active=False) # make sure to deactivate all spaces for a user - user_space.active = True - user_space.save() + try: + us = UserSpace.objects.get(space=space, user=user) + if not us.active: + UserSpace.objects.filter(user=user).update(active=False) + us.active = True + us.save() + return us + else: + return us + except ObjectDoesNotExist: + return None diff --git a/cookbook/tests/other/test_permission_helper.py b/cookbook/tests/other/test_permission_helper.py index e12ec201..c2217f3c 100644 --- a/cookbook/tests/other/test_permission_helper.py +++ b/cookbook/tests/other/test_permission_helper.py @@ -6,8 +6,8 @@ from django_scopes import scopes_disabled from cookbook.forms import ImportExportBase from cookbook.helper.ingredient_parser import IngredientParser -from cookbook.helper.permission_helper import has_group_permission -from cookbook.models import ExportLog, UserSpace +from cookbook.helper.permission_helper import has_group_permission, is_space_owner, switch_user_active_space +from cookbook.models import ExportLog, UserSpace, Food def test_has_group_permission(u1_s1, a_u, space_2): @@ -36,3 +36,39 @@ def test_has_group_permission(u1_s1, a_u, space_2): assert not has_group_permission(auth.get_user(a_u), ('guest',)) assert not has_group_permission(auth.get_user(a_u), ('user',)) assert not has_group_permission(auth.get_user(a_u), ('admin',)) + + +def test_is_space_owner(u1_s1, u2_s1, space_1, space_2): + with scopes_disabled(): + f = Food.objects.create(name='Test', space=space_1) + space_1.created_by = auth.get_user(u1_s1) + space_1.save() + + assert is_space_owner(auth.get_user(u1_s1), f) + assert is_space_owner(space_1.created_by, f) + assert not is_space_owner(auth.get_user(u2_s1), f) + + f.space = space_2 + f.save() + + assert not is_space_owner(auth.get_user(u1_s1), f) + assert not is_space_owner(space_1.created_by, f) + assert not is_space_owner(auth.get_user(u2_s1), f) + + +def test_switch_user_active_space(u1_s1, u1_s2, space_1, space_2): + with scopes_disabled(): + # can switch to already active space + assert switch_user_active_space(auth.get_user(u1_s1), space_1) == auth.get_user(u1_s1).userspace_set.filter(active=True).get() + + # cannot switch to a space the user does not belong to + assert switch_user_active_space(auth.get_user(u1_s1), space_2) is None + + # can join another space and be member of two spaces + us = UserSpace.objects.create(user=auth.get_user(u1_s1), space=space_2, active=False) + assert len(auth.get_user(u1_s1).userspace_set.all()) == 2 + + # can switch into newly created space + assert switch_user_active_space(auth.get_user(u1_s1), space_2) == us + + diff --git a/cookbook/views/api.py b/cookbook/views/api.py index 81a050d4..9ea68a28 100644 --- a/cookbook/views/api.py +++ b/cookbook/views/api.py @@ -1189,9 +1189,12 @@ def switch_active_space(request, space_id): api endpoint to switch space function """ try: - user_space = get_object_or_404(UserSpace, space=space_id, user=request.user) - switch_user_active_space(request.user, user_space) - return Response(UserSpaceSerializer().to_representation(instance=user_space), status=status.HTTP_200_OK) + space = get_object_or_404(Space, id=space_id) + user_space = switch_user_active_space(request.user, space) + if user_space: + return Response(UserSpaceSerializer().to_representation(instance=user_space), status=status.HTTP_200_OK) + else: + return Response("not found", status=status.HTTP_404_NOT_FOUND) except Exception as e: traceback.print_exc() return Response(str(e), status=status.HTTP_400_BAD_REQUEST) diff --git a/cookbook/views/views.py b/cookbook/views/views.py index 9b73e520..6a4aac7a 100644 --- a/cookbook/views/views.py +++ b/cookbook/views/views.py @@ -142,8 +142,8 @@ def space_overview(request): @login_required def switch_space(request, space_id): - user_space = get_object_or_404(UserSpace, space=space_id, user=request.user) - switch_user_active_space(request.user, user_space) + space = get_object_or_404(Space, id=space_id) + switch_user_active_space(request.user, space) return HttpResponseRedirect(reverse('index')) @@ -519,8 +519,8 @@ def invite_link(request, token): @group_required('admin') def space_manage(request, space_id): - user_space = get_object_or_404(UserSpace, space=space_id, user=request.user) - switch_user_active_space(request.user, user_space) + space = get_object_or_404(Space, id=space_id) + switch_user_active_space(request.user, space) return render(request, 'space_manage.html', {})