diff --git a/cookbook/helper/permission_helper.py b/cookbook/helper/permission_helper.py index 108dbf83e..1c9f49f97 100644 --- a/cookbook/helper/permission_helper.py +++ b/cookbook/helper/permission_helper.py @@ -9,6 +9,7 @@ from django.utils.translation import gettext as _ from django.http import HttpResponseRedirect from django.urls import reverse_lazy, reverse from rest_framework import permissions +from rest_framework.permissions import SAFE_METHODS from cookbook.models import ShareLink @@ -154,6 +155,9 @@ class CustomIsGuest(permissions.BasePermission): def has_permission(self, request, view): return has_group_permission(request.user, ['guest']) + def has_object_permission(self, request, view, obj): + return has_group_permission(request.user, ['guest']) + class CustomIsUser(permissions.BasePermission): """ @@ -175,3 +179,20 @@ class CustomIsAdmin(permissions.BasePermission): def has_permission(self, request, view): return has_group_permission(request.user, ['admin']) + + +class CustomIsShare(permissions.BasePermission): + """ + Custom permission class for django rest framework views + verifies the requesting user provided a valid share link + """ + message = _('You do not have the required permissions to view this page!') + + def has_permission(self, request, view): + return request.method in SAFE_METHODS and 'pk' in view.kwargs + + def has_object_permission(self, request, view, obj): + share = request.query_params.get('share', None) + if share: + return share_link_valid(obj, share) + return False diff --git a/cookbook/templates/recipe_view.html b/cookbook/templates/recipe_view.html index 9211051fa..dc7fbc1ef 100644 --- a/cookbook/templates/recipe_view.html +++ b/cookbook/templates/recipe_view.html @@ -105,6 +105,8 @@
{% endif %} + +
@@ -482,7 +484,8 @@ }, methods: { loadRecipe: function () { - this.$http.get("{% url 'api:recipe-detail' recipe.pk %}").then((response) => { + this.$http.get("{% url 'api:recipe-detail' recipe.pk %}" {% if share %} + + "?share={{ share }}"{% endif %}).then((response) => { this.recipe = response.data; this.loading = false diff --git a/cookbook/views/api.py b/cookbook/views/api.py index 1ca5305c2..fed2350f7 100644 --- a/cookbook/views/api.py +++ b/cookbook/views/api.py @@ -23,7 +23,7 @@ from rest_framework.parsers import JSONParser, FileUploadParser, MultiPartParser from rest_framework.response import Response from rest_framework.viewsets import ViewSetMixin -from cookbook.helper.permission_helper import group_required, CustomIsOwner, CustomIsAdmin, CustomIsUser, CustomIsGuest +from cookbook.helper.permission_helper import group_required, CustomIsOwner, CustomIsAdmin, CustomIsUser, CustomIsGuest, CustomIsShare from cookbook.helper.recipe_url_import import get_from_html from cookbook.models import Recipe, Sync, Storage, CookLog, MealPlan, MealType, ViewLog, UserPreference, RecipeBook, Ingredient, Food, Step, Keyword, Unit, SyncLog from cookbook.provider.dropbox import Dropbox @@ -198,7 +198,7 @@ class RecipeViewSet(viewsets.ModelViewSet, StandardFilterMixin): """ queryset = Recipe.objects.all() serializer_class = RecipeSerializer - permission_classes = [permissions.IsAuthenticated] # TODO split read and write permission for meal plan guest + permission_classes = [CustomIsShare | CustomIsGuest] # TODO split read and write permission for meal plan guest @decorators.action( detail=True, diff --git a/cookbook/views/views.py b/cookbook/views/views.py index 2fbd869bf..95b846cf2 100644 --- a/cookbook/views/views.py +++ b/cookbook/views/views.py @@ -116,7 +116,7 @@ def recipe_view(request, pk, share=None): return render(request, 'recipe_view.html', {'recipe': recipe, 'comments': comments, 'comment_form': comment_form, - 'bookmark_form': bookmark_form}) + 'bookmark_form': bookmark_form, 'share': share}) @group_required('user')