more spaces work
This commit is contained in:
parent
ad163509b4
commit
96c963795e
@ -43,8 +43,7 @@ def has_group_permission(user, groups):
|
|||||||
return False
|
return False
|
||||||
groups_allowed = get_allowed_groups(groups)
|
groups_allowed = get_allowed_groups(groups)
|
||||||
if user.is_authenticated:
|
if user.is_authenticated:
|
||||||
if (user.is_superuser
|
if bool(user.groups.filter(name__in=groups_allowed)):
|
||||||
| bool(user.groups.filter(name__in=groups_allowed))):
|
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@ -59,18 +58,11 @@ def is_object_owner(user, obj):
|
|||||||
:param obj any object that should be tested
|
:param obj any object that should be tested
|
||||||
:return: true if user is owner of object, false otherwise
|
:return: true if user is owner of object, false otherwise
|
||||||
"""
|
"""
|
||||||
# TODO this could be improved/cleaned up by adding
|
|
||||||
# get_owner methods to all models that allow owner checks
|
|
||||||
if not user.is_authenticated:
|
if not user.is_authenticated:
|
||||||
return False
|
return False
|
||||||
if user.is_superuser:
|
try:
|
||||||
return True
|
|
||||||
if owner := getattr(obj, 'created_by', None):
|
|
||||||
return owner == user
|
|
||||||
if owner := getattr(obj, 'user', None):
|
|
||||||
return owner == user
|
|
||||||
if getattr(obj, 'get_owner', None):
|
|
||||||
return obj.get_owner() == user
|
return obj.get_owner() == user
|
||||||
|
except:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
@ -87,8 +79,6 @@ def is_object_shared(user, obj):
|
|||||||
# share checks for relevant objects
|
# share checks for relevant objects
|
||||||
if not user.is_authenticated:
|
if not user.is_authenticated:
|
||||||
return False
|
return False
|
||||||
if user.is_superuser:
|
|
||||||
return True
|
|
||||||
return user in obj.shared.all()
|
return user in obj.shared.all()
|
||||||
|
|
||||||
|
|
||||||
@ -100,11 +90,7 @@ def share_link_valid(recipe, share):
|
|||||||
:return: true if a share link with the given recipe and uuid exists
|
:return: true if a share link with the given recipe and uuid exists
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
return (
|
return True if ShareLink.objects.filter(recipe=recipe, uuid=share).exists() else False
|
||||||
True
|
|
||||||
if ShareLink.objects.filter(recipe=recipe, uuid=share).exists()
|
|
||||||
else False
|
|
||||||
)
|
|
||||||
except ValidationError:
|
except ValidationError:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@ -148,21 +134,11 @@ class OwnerRequiredMixin(object):
|
|||||||
|
|
||||||
def dispatch(self, request, *args, **kwargs):
|
def dispatch(self, request, *args, **kwargs):
|
||||||
if not request.user.is_authenticated:
|
if not request.user.is_authenticated:
|
||||||
messages.add_message(
|
messages.add_message(request, messages.ERROR, _('You are not logged in and therefore cannot view this page!'))
|
||||||
request,
|
return HttpResponseRedirect(reverse_lazy('account_login') + '?next=' + request.path)
|
||||||
messages.ERROR,
|
|
||||||
_('You are not logged in and therefore cannot view this page!')
|
|
||||||
)
|
|
||||||
return HttpResponseRedirect(
|
|
||||||
reverse_lazy('account_login') + '?next=' + request.path
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
if not is_object_owner(request.user, self.get_object()):
|
if not is_object_owner(request.user, self.get_object()):
|
||||||
messages.add_message(
|
messages.add_message(request, messages.ERROR, _('You cannot interact with this object as it is not owned by you!'))
|
||||||
request,
|
|
||||||
messages.ERROR,
|
|
||||||
_('You cannot interact with this object as it is not owned by you!') # noqa: E501
|
|
||||||
)
|
|
||||||
return HttpResponseRedirect(reverse('index'))
|
return HttpResponseRedirect(reverse('index'))
|
||||||
|
|
||||||
if self.get_object().get_space() != request.space:
|
if self.get_object().get_space() != request.space:
|
||||||
|
@ -27,7 +27,7 @@ class Dropbox(Provider):
|
|||||||
try:
|
try:
|
||||||
recipes = r.json()
|
recipes = r.json()
|
||||||
except ValueError:
|
except ValueError:
|
||||||
log_entry = SyncLog(status='ERROR', msg=str(r), sync=monitor)
|
log_entry = SyncLog(status='ERROR', msg=str(r), sync=monitor, space=monitor.space)
|
||||||
log_entry.save()
|
log_entry.save()
|
||||||
return r
|
return r
|
||||||
|
|
||||||
@ -35,14 +35,14 @@ class Dropbox(Provider):
|
|||||||
# TODO check if has_more is set and import that as well
|
# TODO check if has_more is set and import that as well
|
||||||
for recipe in recipes['entries']:
|
for recipe in recipes['entries']:
|
||||||
path = recipe['path_lower']
|
path = recipe['path_lower']
|
||||||
if not Recipe.objects.filter(file_path__iexact=path).exists() \
|
if not Recipe.objects.filter(file_path__iexact=path, space=monitor.space).exists() and not RecipeImport.objects.filter(file_path=path, space=monitor.space).exists():
|
||||||
and not RecipeImport.objects.filter(file_path=path).exists(): # noqa: E501
|
|
||||||
name = os.path.splitext(recipe['name'])[0]
|
name = os.path.splitext(recipe['name'])[0]
|
||||||
new_recipe = RecipeImport(
|
new_recipe = RecipeImport(
|
||||||
name=name,
|
name=name,
|
||||||
file_path=path,
|
file_path=path,
|
||||||
storage=monitor.storage,
|
storage=monitor.storage,
|
||||||
file_uid=recipe['id']
|
file_uid=recipe['id'],
|
||||||
|
space=monitor.space,
|
||||||
)
|
)
|
||||||
new_recipe.save()
|
new_recipe.save()
|
||||||
import_count += 1
|
import_count += 1
|
||||||
@ -50,7 +50,8 @@ class Dropbox(Provider):
|
|||||||
log_entry = SyncLog(
|
log_entry = SyncLog(
|
||||||
status='SUCCESS',
|
status='SUCCESS',
|
||||||
msg='Imported ' + str(import_count) + ' recipes',
|
msg='Imported ' + str(import_count) + ' recipes',
|
||||||
sync=monitor
|
sync=monitor,
|
||||||
|
space=monitor.space,
|
||||||
)
|
)
|
||||||
log_entry.save()
|
log_entry.save()
|
||||||
|
|
||||||
@ -104,9 +105,7 @@ class Dropbox(Provider):
|
|||||||
recipe.link = Dropbox.get_share_link(recipe)
|
recipe.link = Dropbox.get_share_link(recipe)
|
||||||
recipe.save()
|
recipe.save()
|
||||||
|
|
||||||
response = requests.get(
|
response = requests.get(recipe.link.replace('www.dropbox.', 'dl.dropboxusercontent.'))
|
||||||
recipe.link.replace('www.dropbox.', 'dl.dropboxusercontent.')
|
|
||||||
)
|
|
||||||
|
|
||||||
return io.BytesIO(response.content)
|
return io.BytesIO(response.content)
|
||||||
|
|
||||||
|
@ -18,13 +18,13 @@ class Local(Provider):
|
|||||||
import_count = 0
|
import_count = 0
|
||||||
for file in files:
|
for file in files:
|
||||||
path = monitor.path + '/' + file
|
path = monitor.path + '/' + file
|
||||||
if not Recipe.objects.filter(file_path__iexact=path).exists() \
|
if not Recipe.objects.filter(file_path__iexact=path, space=monitor.space).exists() and not RecipeImport.objects.filter(file_path=path, space=monitor.space).exists():
|
||||||
and not RecipeImport.objects.filter(file_path=path).exists(): # noqa: E501
|
|
||||||
name = os.path.splitext(file)[0]
|
name = os.path.splitext(file)[0]
|
||||||
new_recipe = RecipeImport(
|
new_recipe = RecipeImport(
|
||||||
name=name,
|
name=name,
|
||||||
file_path=path,
|
file_path=path,
|
||||||
storage=monitor.storage
|
storage=monitor.storage,
|
||||||
|
space=monitor.space,
|
||||||
)
|
)
|
||||||
new_recipe.save()
|
new_recipe.save()
|
||||||
import_count += 1
|
import_count += 1
|
||||||
@ -32,7 +32,8 @@ class Local(Provider):
|
|||||||
log_entry = SyncLog(
|
log_entry = SyncLog(
|
||||||
status='SUCCESS',
|
status='SUCCESS',
|
||||||
msg='Imported ' + str(import_count) + ' recipes',
|
msg='Imported ' + str(import_count) + ' recipes',
|
||||||
sync=monitor
|
sync=monitor,
|
||||||
|
space=monitor.space,
|
||||||
)
|
)
|
||||||
log_entry.save()
|
log_entry.save()
|
||||||
|
|
||||||
|
@ -34,13 +34,13 @@ class Nextcloud(Provider):
|
|||||||
import_count = 0
|
import_count = 0
|
||||||
for file in files:
|
for file in files:
|
||||||
path = monitor.path + '/' + file
|
path = monitor.path + '/' + file
|
||||||
if not Recipe.objects.filter(file_path__iexact=path).exists() \
|
if not Recipe.objects.filter(file_path__iexact=path, space=monitor.space).exists() and not RecipeImport.objects.filter(file_path=path, space=monitor.space).exists():
|
||||||
and not RecipeImport.objects.filter(file_path=path).exists(): # noqa: E501
|
|
||||||
name = os.path.splitext(file)[0]
|
name = os.path.splitext(file)[0]
|
||||||
new_recipe = RecipeImport(
|
new_recipe = RecipeImport(
|
||||||
name=name,
|
name=name,
|
||||||
file_path=path,
|
file_path=path,
|
||||||
storage=monitor.storage
|
storage=monitor.storage,
|
||||||
|
space=monitor.space,
|
||||||
)
|
)
|
||||||
new_recipe.save()
|
new_recipe.save()
|
||||||
import_count += 1
|
import_count += 1
|
||||||
@ -48,7 +48,8 @@ class Nextcloud(Provider):
|
|||||||
log_entry = SyncLog(
|
log_entry = SyncLog(
|
||||||
status='SUCCESS',
|
status='SUCCESS',
|
||||||
msg='Imported ' + str(import_count) + ' recipes',
|
msg='Imported ' + str(import_count) + ' recipes',
|
||||||
sync=monitor
|
sync=monitor,
|
||||||
|
space=monitor.space
|
||||||
)
|
)
|
||||||
log_entry.save()
|
log_entry.save()
|
||||||
|
|
||||||
@ -68,14 +69,7 @@ class Nextcloud(Provider):
|
|||||||
|
|
||||||
data = {'path': recipe.file_path, 'shareType': 3}
|
data = {'path': recipe.file_path, 'shareType': 3}
|
||||||
|
|
||||||
r = requests.post(
|
r = requests.post(url, headers=headers, auth=HTTPBasicAuth(recipe.storage.username, recipe.storage.password), data=data)
|
||||||
url,
|
|
||||||
headers=headers,
|
|
||||||
auth=HTTPBasicAuth(
|
|
||||||
recipe.storage.username, recipe.storage.password
|
|
||||||
),
|
|
||||||
data=data
|
|
||||||
)
|
|
||||||
|
|
||||||
response_json = r.json()
|
response_json = r.json()
|
||||||
|
|
||||||
|
@ -27,10 +27,7 @@ from cookbook.tables import SyncTable
|
|||||||
def sync(request):
|
def sync(request):
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
if not has_group_permission(request.user, ['admin']):
|
if not has_group_permission(request.user, ['admin']):
|
||||||
messages.add_message(
|
messages.add_message(request, messages.ERROR, _('You do not have the required permissions to view this page!'))
|
||||||
request, messages.ERROR,
|
|
||||||
_('You do not have the required permissions to view this page!') # noqa: E501
|
|
||||||
)
|
|
||||||
return HttpResponseRedirect(reverse('data_sync'))
|
return HttpResponseRedirect(reverse('data_sync'))
|
||||||
form = SyncForm(request.POST)
|
form = SyncForm(request.POST)
|
||||||
if form.is_valid():
|
if form.is_valid():
|
||||||
@ -38,21 +35,16 @@ def sync(request):
|
|||||||
new_path.path = form.cleaned_data['path']
|
new_path.path = form.cleaned_data['path']
|
||||||
new_path.storage = form.cleaned_data['storage']
|
new_path.storage = form.cleaned_data['storage']
|
||||||
new_path.last_checked = datetime.now()
|
new_path.last_checked = datetime.now()
|
||||||
|
new_path.space = request.space
|
||||||
new_path.save()
|
new_path.save()
|
||||||
return redirect('data_sync')
|
return redirect('data_sync')
|
||||||
else:
|
else:
|
||||||
form = SyncForm()
|
form = SyncForm()
|
||||||
|
|
||||||
monitored_paths = SyncTable(Sync.objects.all())
|
monitored_paths = SyncTable(Sync.objects.fitler(space=request.space).all())
|
||||||
RequestConfig(
|
RequestConfig(request, paginate={'per_page': 25}).configure(monitored_paths)
|
||||||
request, paginate={'per_page': 25}
|
|
||||||
).configure(monitored_paths)
|
|
||||||
|
|
||||||
return render(
|
return render(request, 'batch/monitor.html', {'form': form, 'monitored_paths': monitored_paths})
|
||||||
request,
|
|
||||||
'batch/monitor.html',
|
|
||||||
{'form': form, 'monitored_paths': monitored_paths}
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@group_required('user')
|
@group_required('user')
|
||||||
@ -62,14 +54,15 @@ def sync_wait(request):
|
|||||||
|
|
||||||
@group_required('user')
|
@group_required('user')
|
||||||
def batch_import(request):
|
def batch_import(request):
|
||||||
imports = RecipeImport.objects.all()
|
imports = RecipeImport.objects.filter(space=request.space).all()
|
||||||
for new_recipe in imports:
|
for new_recipe in imports:
|
||||||
recipe = Recipe(
|
recipe = Recipe(
|
||||||
name=new_recipe.name,
|
name=new_recipe.name,
|
||||||
file_path=new_recipe.file_path,
|
file_path=new_recipe.file_path,
|
||||||
storage=new_recipe.storage,
|
storage=new_recipe.storage,
|
||||||
file_uid=new_recipe.file_uid,
|
file_uid=new_recipe.file_uid,
|
||||||
created_by=request.user
|
created_by=request.user,
|
||||||
|
space=request.space
|
||||||
)
|
)
|
||||||
recipe.save()
|
recipe.save()
|
||||||
new_recipe.delete()
|
new_recipe.delete()
|
||||||
@ -85,7 +78,7 @@ def batch_edit(request):
|
|||||||
word = form.cleaned_data['search']
|
word = form.cleaned_data['search']
|
||||||
keywords = form.cleaned_data['keywords']
|
keywords = form.cleaned_data['keywords']
|
||||||
|
|
||||||
recipes = Recipe.objects.filter(name__icontains=word)
|
recipes = Recipe.objects.filter(name__icontains=word, space=request.space)
|
||||||
count = 0
|
count = 0
|
||||||
for recipe in recipes:
|
for recipe in recipes:
|
||||||
edit = False
|
edit = False
|
||||||
@ -125,6 +118,7 @@ def import_url(request):
|
|||||||
servings=data['servings'],
|
servings=data['servings'],
|
||||||
internal=True,
|
internal=True,
|
||||||
created_by=request.user,
|
created_by=request.user,
|
||||||
|
space=request.space,
|
||||||
)
|
)
|
||||||
|
|
||||||
step = Step.objects.create(
|
step = Step.objects.create(
|
||||||
@ -134,11 +128,10 @@ def import_url(request):
|
|||||||
recipe.steps.add(step)
|
recipe.steps.add(step)
|
||||||
|
|
||||||
for kw in data['keywords']:
|
for kw in data['keywords']:
|
||||||
if kw['id'] != "null" \
|
if kw['id'] != "null" and (k := Keyword.objects.filter(id=kw['id'], space=request.space).first()):
|
||||||
and (k := Keyword.objects.filter(id=kw['id']).first()):
|
|
||||||
recipe.keywords.add(k)
|
recipe.keywords.add(k)
|
||||||
elif data['all_keywords']:
|
elif data['all_keywords']:
|
||||||
k = Keyword.objects.create(name=kw['text'])
|
k = Keyword.objects.create(name=kw['text'], space=request.space)
|
||||||
recipe.keywords.add(k)
|
recipe.keywords.add(k)
|
||||||
|
|
||||||
for ing in data['recipeIngredient']:
|
for ing in data['recipeIngredient']:
|
||||||
@ -146,12 +139,12 @@ def import_url(request):
|
|||||||
|
|
||||||
if ing['ingredient']['text'] != '':
|
if ing['ingredient']['text'] != '':
|
||||||
ingredient.food, f_created = Food.objects.get_or_create(
|
ingredient.food, f_created = Food.objects.get_or_create(
|
||||||
name=ing['ingredient']['text']
|
name=ing['ingredient']['text'], space=request.space
|
||||||
)
|
)
|
||||||
|
|
||||||
if ing['unit'] and ing['unit']['text'] != '':
|
if ing['unit'] and ing['unit']['text'] != '':
|
||||||
ingredient.unit, u_created = Unit.objects.get_or_create(
|
ingredient.unit, u_created = Unit.objects.get_or_create(
|
||||||
name=ing['unit']['text']
|
name=ing['unit']['text'], space=request.space
|
||||||
)
|
)
|
||||||
|
|
||||||
# TODO properly handle no_amount recipes
|
# TODO properly handle no_amount recipes
|
||||||
@ -202,16 +195,16 @@ class Object(object):
|
|||||||
@group_required('user')
|
@group_required('user')
|
||||||
def statistics(request):
|
def statistics(request):
|
||||||
counts = Object()
|
counts = Object()
|
||||||
counts.recipes = Recipe.objects.count()
|
counts.recipes = Recipe.objects.filter(space=request.space).count()
|
||||||
counts.keywords = Keyword.objects.count()
|
counts.keywords = Keyword.objects.filter(space=request.space).count()
|
||||||
counts.recipe_import = RecipeImport.objects.count()
|
counts.recipe_import = RecipeImport.objects.filter(space=request.space).count()
|
||||||
counts.units = Unit.objects.count()
|
counts.units = Unit.objects.filter(space=request.space).count()
|
||||||
counts.ingredients = Food.objects.count()
|
counts.ingredients = Food.objects.filter(space=request.space).count()
|
||||||
counts.comments = Comment.objects.count()
|
counts.comments = Comment.objects.filter(recipe__space=request.space).count()
|
||||||
|
|
||||||
counts.recipes_internal = Recipe.objects.filter(internal=True).count()
|
counts.recipes_internal = Recipe.objects.filter(internal=True, space=request.space).count()
|
||||||
counts.recipes_external = counts.recipes - counts.recipes_internal
|
counts.recipes_external = counts.recipes - counts.recipes_internal
|
||||||
|
|
||||||
counts.recipes_no_keyword = Recipe.objects.filter(keywords=None).count()
|
counts.recipes_no_keyword = Recipe.objects.filter(keywords=None, space=request.space).count()
|
||||||
|
|
||||||
return render(request, 'stats.html', {'counts': counts})
|
return render(request, 'stats.html', {'counts': counts})
|
||||||
|
@ -31,7 +31,7 @@ class RecipeDelete(GroupRequiredMixin, DeleteView):
|
|||||||
|
|
||||||
@group_required('user')
|
@group_required('user')
|
||||||
def delete_recipe_source(request, pk):
|
def delete_recipe_source(request, pk):
|
||||||
recipe = get_object_or_404(Recipe, pk=pk)
|
recipe = get_object_or_404(Recipe, pk=pk, space=request.space)
|
||||||
|
|
||||||
if recipe.storage.method == Storage.DROPBOX:
|
if recipe.storage.method == Storage.DROPBOX:
|
||||||
# TODO central location to handle storage type switches
|
# TODO central location to handle storage type switches
|
||||||
@ -130,25 +130,12 @@ class RecipeBookDelete(OwnerRequiredMixin, DeleteView):
|
|||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
||||||
class RecipeBookEntryDelete(GroupRequiredMixin, DeleteView):
|
class RecipeBookEntryDelete(OwnerRequiredMixin, DeleteView):
|
||||||
groups_required = ['user']
|
groups_required = ['user']
|
||||||
template_name = "generic/delete_template.html"
|
template_name = "generic/delete_template.html"
|
||||||
model = RecipeBookEntry
|
model = RecipeBookEntry
|
||||||
success_url = reverse_lazy('view_books')
|
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 it is not owned by you!') # noqa: E501
|
|
||||||
)
|
|
||||||
return HttpResponseRedirect(reverse('index'))
|
|
||||||
return super(RecipeBookEntryDelete, self) \
|
|
||||||
.dispatch(request, *args, **kwargs)
|
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
context = super(RecipeBookEntryDelete, self).get_context_data(**kwargs)
|
context = super(RecipeBookEntryDelete, self).get_context_data(**kwargs)
|
||||||
context['title'] = _("Bookmarks")
|
context['title'] = _("Bookmarks")
|
||||||
|
Loading…
Reference in New Issue
Block a user