From 1617fa7a3f9e76ccf0300cd485cbf550e2deac47 Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Mon, 27 Apr 2020 16:50:05 +0200 Subject: [PATCH] fixed permissions comments, books --- cookbook/admin.py | 4 +-- .../{group_helper.py => permission_helper.py} | 17 ++++++++++- .../migrations/0035_auto_20200427_1637.py | 28 +++++++++++++++++++ cookbook/models.py | 4 +-- cookbook/views/api.py | 2 +- cookbook/views/data.py | 2 +- cookbook/views/delete.py | 18 ++++++++---- cookbook/views/edit.py | 25 ++++------------- cookbook/views/import_export.py | 2 +- cookbook/views/lists.py | 2 +- cookbook/views/new.py | 6 ++-- cookbook/views/views.py | 4 +-- 12 files changed, 75 insertions(+), 39 deletions(-) rename cookbook/helper/{group_helper.py => permission_helper.py} (72%) create mode 100644 cookbook/migrations/0035_auto_20200427_1637.py diff --git a/cookbook/admin.py b/cookbook/admin.py index 8127f0ad9..d91d6ad55 100644 --- a/cookbook/admin.py +++ b/cookbook/admin.py @@ -80,7 +80,7 @@ class RecipeBookAdmin(admin.ModelAdmin): @staticmethod def user_name(obj): - return obj.user.get_user_name() + return obj.created_by.get_user_name() admin.site.register(RecipeBook, RecipeBookAdmin) @@ -98,7 +98,7 @@ class MealPlanAdmin(admin.ModelAdmin): @staticmethod def user(obj): - return obj.user.get_user_name() + return obj.created_by.get_user_name() admin.site.register(MealPlan, MealPlanAdmin) diff --git a/cookbook/helper/group_helper.py b/cookbook/helper/permission_helper.py similarity index 72% rename from cookbook/helper/group_helper.py rename to cookbook/helper/permission_helper.py index a7474e649..10a310cc9 100644 --- a/cookbook/helper/group_helper.py +++ b/cookbook/helper/permission_helper.py @@ -5,7 +5,7 @@ from django.contrib import messages from django.contrib.auth.decorators import user_passes_test from django.utils.translation import gettext as _ from django.http import HttpResponseRedirect -from django.urls import reverse_lazy +from django.urls import reverse_lazy, reverse def get_allowed_groups(groups_required): @@ -51,3 +51,18 @@ class GroupRequiredMixin(object): messages.add_message(request, messages.ERROR, _('You do not have the required permissions to view this page!')) return HttpResponseRedirect(reverse_lazy('index')) return super(GroupRequiredMixin, self).dispatch(request, *args, **kwargs) + + +class OwnerRequiredMixin(object): + + def dispatch(self, request, *args, **kwargs): + if not request.user.is_authenticated: + messages.add_message(request, messages.ERROR, _('You are not logged in and therefore cannot view this page!')) + return HttpResponseRedirect(reverse_lazy('login')) + else: + obj = self.get_object() + if not (obj.created_by == request.user or request.user.is_superuser): + messages.add_message(request, messages.ERROR, _('You cannot interact with this object as its not owned by you!')) + return HttpResponseRedirect(reverse('index')) + + return super(OwnerRequiredMixin, self).dispatch(request, *args, **kwargs) diff --git a/cookbook/migrations/0035_auto_20200427_1637.py b/cookbook/migrations/0035_auto_20200427_1637.py new file mode 100644 index 000000000..c388c7d6e --- /dev/null +++ b/cookbook/migrations/0035_auto_20200427_1637.py @@ -0,0 +1,28 @@ +# Generated by Django 3.0.5 on 2020-04-27 14:37 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('cookbook', '0034_auto_20200426_1614'), + ] + + operations = [ + migrations.RenameField( + model_name='mealplan', + old_name='user', + new_name='created_by', + ), + migrations.RenameField( + model_name='recipebook', + old_name='user', + new_name='created_by', + ), + migrations.AlterField( + model_name='userpreference', + name='default_page', + field=models.CharField(choices=[('SEARCH', 'Search'), ('PLAN', 'Meal-Plan'), ('BOOKS', 'Books')], default='SEARCH', max_length=64), + ), + ] diff --git a/cookbook/models.py b/cookbook/models.py index 3befd9b35..1e0f400a2 100644 --- a/cookbook/models.py +++ b/cookbook/models.py @@ -188,7 +188,7 @@ class RecipeImport(models.Model): class RecipeBook(models.Model): name = models.CharField(max_length=128) - user = models.ForeignKey(User, on_delete=models.CASCADE) + created_by = models.ForeignKey(User, on_delete=models.CASCADE) def __str__(self): return self.name @@ -209,7 +209,7 @@ class MealPlan(models.Model): OTHER = 'OTHER' MEAL_TYPES = ((BREAKFAST, _('Breakfast')), (LUNCH, _('Lunch')), (DINNER, _('Dinner')), (OTHER, _('Other')),) - user = models.ForeignKey(User, on_delete=models.CASCADE) + created_by = models.ForeignKey(User, on_delete=models.CASCADE) recipe = models.ForeignKey(Recipe, on_delete=models.CASCADE) meal = models.CharField(choices=MEAL_TYPES, max_length=128, default=BREAKFAST) note = models.TextField(blank=True) diff --git a/cookbook/views/api.py b/cookbook/views/api.py index 8206d4c67..ca72488e1 100644 --- a/cookbook/views/api.py +++ b/cookbook/views/api.py @@ -5,7 +5,7 @@ from django.utils.translation import gettext as _ from django.contrib.auth.decorators import login_required from django.shortcuts import redirect -from cookbook.helper.group_helper import group_required +from cookbook.helper.permission_helper import group_required from cookbook.models import Recipe, Sync, Storage from cookbook.provider.dropbox import Dropbox from cookbook.provider.nextcloud import Nextcloud diff --git a/cookbook/views/data.py b/cookbook/views/data.py index cfe6c70f6..e0bde3449 100644 --- a/cookbook/views/data.py +++ b/cookbook/views/data.py @@ -7,7 +7,7 @@ from django.utils.translation import ngettext from django_tables2 import RequestConfig from cookbook.forms import SyncForm, BatchEditForm -from cookbook.helper.group_helper import group_required +from cookbook.helper.permission_helper import group_required from cookbook.models import * from cookbook.tables import SyncTable diff --git a/cookbook/views/delete.py b/cookbook/views/delete.py index c2d00d704..9f2d3337f 100644 --- a/cookbook/views/delete.py +++ b/cookbook/views/delete.py @@ -1,3 +1,4 @@ +from django.contrib import messages from django.contrib.auth.mixins import LoginRequiredMixin from django.http import HttpResponseRedirect from django.shortcuts import get_object_or_404 @@ -5,7 +6,7 @@ from django.urls import reverse_lazy, reverse from django.utils.translation import gettext as _ from django.views.generic import DeleteView -from cookbook.helper.group_helper import GroupRequiredMixin +from cookbook.helper.permission_helper import GroupRequiredMixin, OwnerRequiredMixin from cookbook.models import Recipe, Sync, Keyword, RecipeImport, Storage, Comment, RecipeBook, \ RecipeBookEntry, MealPlan, Ingredient from cookbook.provider.dropbox import Dropbox @@ -101,7 +102,7 @@ class StorageDelete(GroupRequiredMixin, DeleteView): return context -class CommentDelete(LoginRequiredMixin, DeleteView): +class CommentDelete(OwnerRequiredMixin, DeleteView): template_name = "generic/delete_template.html" model = Comment success_url = reverse_lazy('index') @@ -112,8 +113,7 @@ class CommentDelete(LoginRequiredMixin, DeleteView): return context -class RecipeBookDelete(GroupRequiredMixin, DeleteView): - groups_required = ['user'] +class RecipeBookDelete(OwnerRequiredMixin, DeleteView): template_name = "generic/delete_template.html" model = RecipeBook success_url = reverse_lazy('view_books') @@ -130,14 +130,20 @@ class RecipeBookEntryDelete(GroupRequiredMixin, DeleteView): model = RecipeBookEntry success_url = reverse_lazy('view_books') + def dispatch(self, request, *args, **kwargs): + obj = self.get_object() + if not (obj.book.created_by == request.user or request.user.is_superuser): + messages.add_message(request, messages.ERROR, _('You cannot interact with this object as its not owned by you!')) + return HttpResponseRedirect(reverse('index')) + return super(RecipeBookEntryDelete, self).dispatch(request, *args, **kwargs) + def get_context_data(self, **kwargs): context = super(RecipeBookEntryDelete, self).get_context_data(**kwargs) context['title'] = _("Bookmarks") return context -class MealPlanDelete(GroupRequiredMixin, DeleteView): - groups_required = ['user'] +class MealPlanDelete(OwnerRequiredMixin, DeleteView): template_name = "generic/delete_template.html" model = MealPlan success_url = reverse_lazy('view_plan') diff --git a/cookbook/views/edit.py b/cookbook/views/edit.py index 018937324..2bbf9dfe5 100644 --- a/cookbook/views/edit.py +++ b/cookbook/views/edit.py @@ -15,7 +15,9 @@ from django.views.generic import UpdateView from cookbook.forms import ExternalRecipeForm, KeywordForm, StorageForm, SyncForm, InternalRecipeForm, CommentForm, \ MealPlanForm, UnitMergeForm, IngredientMergeForm, IngredientForm -from cookbook.helper.group_helper import group_required, GroupRequiredMixin +from cookbook.helper.permission_helper import group_required, GroupRequiredMixin + +from cookbook.helper.permission_helper import OwnerRequiredMixin from cookbook.models import Recipe, Sync, Keyword, RecipeImport, Storage, Comment, RecipeIngredient, RecipeBook, \ MealPlan, Unit, Ingredient from cookbook.provider.dropbox import Dropbox @@ -218,20 +220,11 @@ def edit_storage(request, pk): return render(request, 'generic/edit_template.html', {'form': form}) -class CommentUpdate(LoginRequiredMixin, UpdateView): +class CommentUpdate(OwnerRequiredMixin, UpdateView): template_name = "generic/edit_template.html" model = Comment form_class = CommentForm - # TODO add msg box - - def dispatch(self, request, *args, **kwargs): - obj = self.get_object() - if not (obj.created_by == request.user or request.user.is_superuser): - messages.add_message(request, messages.ERROR, _('You cannot edit this comment!')) - return HttpResponseRedirect(reverse('view_recipe', args=[obj.recipe.pk])) - return super(CommentUpdate, self).dispatch(request, *args, **kwargs) - def get_success_url(self): return reverse('edit_comment', kwargs={'pk': self.object.pk}) @@ -259,14 +252,11 @@ class ImportUpdate(GroupRequiredMixin, UpdateView): return context -class RecipeBookUpdate(GroupRequiredMixin, UpdateView): - groups_required = ['user'] +class RecipeBookUpdate(OwnerRequiredMixin, UpdateView): template_name = "generic/edit_template.html" model = RecipeBook fields = ['name'] - # TODO add msg box - def get_success_url(self): return reverse('view_books') @@ -276,14 +266,11 @@ class RecipeBookUpdate(GroupRequiredMixin, UpdateView): return context -class MealPlanUpdate(GroupRequiredMixin, UpdateView): - groups_required = ['user'] +class MealPlanUpdate(OwnerRequiredMixin, UpdateView): template_name = "generic/edit_template.html" model = MealPlan form_class = MealPlanForm - # TODO add msg box - def get_success_url(self): return reverse('view_plan') diff --git a/cookbook/views/import_export.py b/cookbook/views/import_export.py index fdebbda3f..4c7e68f9e 100644 --- a/cookbook/views/import_export.py +++ b/cookbook/views/import_export.py @@ -11,7 +11,7 @@ from django.urls import reverse_lazy from django.utils.translation import gettext as _ from cookbook.forms import ExportForm, ImportForm -from cookbook.helper.group_helper import group_required +from cookbook.helper.permission_helper import group_required from cookbook.models import RecipeIngredient, Recipe, Unit, Ingredient, Keyword diff --git a/cookbook/views/lists.py b/cookbook/views/lists.py index e33b23211..e7b052b90 100644 --- a/cookbook/views/lists.py +++ b/cookbook/views/lists.py @@ -5,7 +5,7 @@ from django.utils.translation import gettext as _ from django_tables2 import RequestConfig from cookbook.filters import IngredientFilter -from cookbook.helper.group_helper import group_required +from cookbook.helper.permission_helper import group_required from cookbook.models import Keyword, SyncLog, RecipeImport, Storage, Ingredient from cookbook.tables import KeywordTable, ImportLogTable, RecipeImportTable, StorageTable, IngredientTable diff --git a/cookbook/views/new.py b/cookbook/views/new.py index f68d9c9e6..b33ab34d2 100644 --- a/cookbook/views/new.py +++ b/cookbook/views/new.py @@ -10,7 +10,7 @@ from django.views.generic import CreateView from cookbook.forms import ImportRecipeForm, RecipeImport, KeywordForm, Storage, StorageForm, InternalRecipeForm, \ RecipeBookForm, MealPlanForm -from cookbook.helper.group_helper import GroupRequiredMixin, group_required +from cookbook.helper.permission_helper import GroupRequiredMixin, group_required from cookbook.models import Keyword, Recipe, RecipeBook, MealPlan @@ -108,7 +108,7 @@ class RecipeBookCreate(GroupRequiredMixin, CreateView): def form_valid(self, form): obj = form.save(commit=False) - obj.user = self.request.user + obj.created_by = self.request.user obj.save() return HttpResponseRedirect(reverse('view_books')) @@ -133,7 +133,7 @@ class MealPlanCreate(GroupRequiredMixin, CreateView): def form_valid(self, form): obj = form.save(commit=False) - obj.user = self.request.user + obj.created_by = self.request.user obj.save() return HttpResponseRedirect(reverse('view_plan')) diff --git a/cookbook/views/views.py b/cookbook/views/views.py index f76703b42..d953f84db 100644 --- a/cookbook/views/views.py +++ b/cookbook/views/views.py @@ -12,7 +12,7 @@ from django.utils.translation import gettext as _ from cookbook.filters import RecipeFilter from cookbook.forms import * -from cookbook.helper.group_helper import group_required +from cookbook.helper.permission_helper import group_required from cookbook.tables import RecipeTable @@ -83,7 +83,7 @@ def recipe_view(request, pk): def books(request): book_list = [] - books = RecipeBook.objects.filter(user=request.user).all() + books = RecipeBook.objects.filter(created_by=request.user).all() for b in books: book_list.append({'book': b, 'recipes': RecipeBookEntry.objects.filter(book=b).all()})