diff --git a/cookbook/helper/permission_helper.py b/cookbook/helper/permission_helper.py index 5a131bffa..e1df06ada 100644 --- a/cookbook/helper/permission_helper.py +++ b/cookbook/helper/permission_helper.py @@ -455,3 +455,9 @@ class IsReadOnlyDRF(permissions.BasePermission): def has_permission(self, request, view): return request.method in SAFE_METHODS + +class IsCreateDRF(permissions.BasePermission): + message = 'You cannot interact with this object, you can only create' + + def has_permission(self, request, view): + return request.method == 'POST' \ No newline at end of file diff --git a/cookbook/helper/scope_middleware.py b/cookbook/helper/scope_middleware.py index b0efdfab4..92b8baee8 100644 --- a/cookbook/helper/scope_middleware.py +++ b/cookbook/helper/scope_middleware.py @@ -46,13 +46,15 @@ class ScopeMiddleware: # get active user space, if for some reason more than one space is active select first (group permission checks will fail, this is not intended at this point) user_space = request.user.userspace_set.filter(active=True).first() - if not user_space: - if request.user.userspace_set.count() > 0: - # if the users has a userspace but nothing is active, activate the first one - user_space = request.user.userspace_set.filter(active=True).first() + if not user_space and request.user.userspace_set.count() > 0: + # if the users has a userspace but nothing is active, activate the first one + user_space = request.user.userspace_set.first() + if user_space: user_space.active = True user_space.save() - elif 'signup_token' in request.session: + + if not user_space: + if 'signup_token' in request.session: # if user is authenticated, has no space but a signup token (InviteLink) is present, redirect to invite link logic return HttpResponseRedirect(reverse('view_invite', args=[request.session.pop('signup_token', '')])) else: diff --git a/cookbook/views/api.py b/cookbook/views/api.py index 0c93c04ba..3d3421e27 100644 --- a/cookbook/views/api.py +++ b/cookbook/views/api.py @@ -75,7 +75,7 @@ from cookbook.helper.permission_helper import (CustomIsAdmin, CustomIsOwner, Cus CustomTokenHasScope, CustomUserPermission, IsReadOnlyDRF, above_space_limit, group_required, has_group_permission, is_space_owner, - switch_user_active_space, CustomAiProviderPermission + switch_user_active_space, CustomAiProviderPermission, IsCreateDRF ) from cookbook.helper.recipe_search import RecipeSearch from cookbook.helper.recipe_url_import import clean_dict, get_from_youtube_scraper, get_images_from_soup @@ -546,7 +546,7 @@ class GroupViewSet(LoggingMixin, viewsets.ModelViewSet): class SpaceViewSet(LoggingMixin, viewsets.ModelViewSet): queryset = Space.objects serializer_class = SpaceSerializer - permission_classes = [IsReadOnlyDRF & CustomIsGuest | CustomIsOwner & CustomIsAdmin & CustomTokenHasReadWriteScope] + permission_classes = [((IsReadOnlyDRF | IsCreateDRF) & CustomIsGuest) | CustomIsOwner & CustomIsAdmin & CustomTokenHasReadWriteScope] pagination_class = DefaultPagination http_method_names = ['get', 'post', 'put', 'patch'] @@ -567,7 +567,7 @@ class SpaceViewSet(LoggingMixin, viewsets.ModelViewSet): class UserSpaceViewSet(LoggingMixin, viewsets.ModelViewSet): queryset = UserSpace.objects serializer_class = UserSpaceSerializer - permission_classes = [(CustomIsSpaceOwner | CustomIsOwnerReadOnly) & CustomTokenHasReadWriteScope] + permission_classes = [(CustomIsSpaceOwner | (IsReadOnlyDRF & CustomIsUser) | CustomIsOwnerReadOnly) & CustomTokenHasReadWriteScope] http_method_names = ['get', 'put', 'patch', 'delete'] pagination_class = DefaultPagination @@ -581,10 +581,23 @@ class UserSpaceViewSet(LoggingMixin, viewsets.ModelViewSet): if internal_note is not None: self.queryset = self.queryset.filter(internal_note=internal_note) - if is_space_owner(self.request.user, self.request.space): + # starting with users you can SEE all other users in a space, guests only see themselves + if has_group_permission(self.request.user, ['user']): return self.queryset.filter(space=self.request.space) else: - return self.queryset.filter(user=self.request.user, space=self.request.space) + return self.queryset.filter(space=self.request.space, user=self.request.user) + + @extend_schema(responses=UserSpaceSerializer(many=True)) + @decorators.action(detail=False, pagination_class=DefaultPagination, methods=['GET'], serializer_class=UserSpaceSerializer, ) + def all_personal(self, request): + """ + return all userspaces for the user requesting the endpoint + :param request: + :return: + """ + with scopes_disabled(): + self.queryset = self.queryset.filter(user=self.request.user) + return Response(self.serializer_class(self.queryset.all(), many=True, context={'request': self.request}).data) class UserPreferenceViewSet(LoggingMixin, viewsets.ModelViewSet): diff --git a/vue3/src/apps/tandoor/Tandoor.vue b/vue3/src/apps/tandoor/Tandoor.vue index 541cdb6ed..241611856 100644 --- a/vue3/src/apps/tandoor/Tandoor.vue +++ b/vue3/src/apps/tandoor/Tandoor.vue @@ -163,7 +163,7 @@ onMounted(() => { * global title update handler, might be overridden by page specific handlers */ router.afterEach((to, from) => { - if(to.name != 'WelcomePage' && !useUserPreferenceStore().activeSpace.spaceSetupCompleted && useUserPreferenceStore().activeSpace.createdBy.id! == useUserPreferenceStore().userSettings.user.id!){ + if(to.name == 'StartPage' && !useUserPreferenceStore().activeSpace.spaceSetupCompleted && useUserPreferenceStore().activeSpace.createdBy.id! == useUserPreferenceStore().userSettings.user.id!){ router.push({name: 'WelcomePage'}) } nextTick(() => { diff --git a/vue3/src/components/inputs/UserFileField.vue b/vue3/src/components/inputs/UserFileField.vue index 99ca367db..dbdac091c 100644 --- a/vue3/src/components/inputs/UserFileField.vue +++ b/vue3/src/components/inputs/UserFileField.vue @@ -98,7 +98,7 @@