mirror of
https://github.com/TandoorRecipes/recipes.git
synced 2026-01-01 12:18:45 -05:00
Add ConnectorManager component which allows for Connectors to listen to triggers and do actions on them. Also add HomeAssistantConfig which stores the configuration for the HomeAssistantConnector
This commit is contained in:
@@ -460,6 +460,16 @@ class StorageViewSet(viewsets.ModelViewSet):
|
||||
return self.queryset.filter(space=self.request.space)
|
||||
|
||||
|
||||
class HomeAssistantConfigViewSet(viewsets.ModelViewSet):
|
||||
# TODO handle delete protect error and adjust test
|
||||
queryset = HomeAssistantConfig.objects
|
||||
serializer_class = HomeAssistantConfigSerializer
|
||||
permission_classes = [CustomIsAdmin & CustomTokenHasReadWriteScope]
|
||||
|
||||
def get_queryset(self):
|
||||
return self.queryset.filter(space=self.request.space)
|
||||
|
||||
|
||||
class SyncViewSet(viewsets.ModelViewSet):
|
||||
queryset = Sync.objects
|
||||
serializer_class = SyncSerializer
|
||||
|
||||
@@ -9,7 +9,7 @@ from django.views.generic import DeleteView
|
||||
|
||||
from cookbook.helper.permission_helper import GroupRequiredMixin, OwnerRequiredMixin, group_required
|
||||
from cookbook.models import (Comment, InviteLink, MealPlan, Recipe, RecipeBook, RecipeBookEntry,
|
||||
RecipeImport, Space, Storage, Sync, UserSpace)
|
||||
RecipeImport, Space, Storage, Sync, UserSpace, HomeAssistantConfig)
|
||||
from cookbook.provider.dropbox import Dropbox
|
||||
from cookbook.provider.local import Local
|
||||
from cookbook.provider.nextcloud import Nextcloud
|
||||
@@ -122,6 +122,29 @@ class StorageDelete(GroupRequiredMixin, DeleteView):
|
||||
return HttpResponseRedirect(reverse('list_storage'))
|
||||
|
||||
|
||||
class HomeAssistantConfigDelete(GroupRequiredMixin, DeleteView):
|
||||
groups_required = ['admin']
|
||||
template_name = "generic/delete_template.html"
|
||||
model = HomeAssistantConfig
|
||||
success_url = reverse_lazy('list_storage')
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(HomeAssistantConfigDelete, self).get_context_data(**kwargs)
|
||||
context['title'] = _("HomeAssistant Config Backend")
|
||||
return context
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
try:
|
||||
return self.delete(request, *args, **kwargs)
|
||||
except ProtectedError:
|
||||
messages.add_message(
|
||||
request,
|
||||
messages.WARNING,
|
||||
_('Could not delete this storage backend as it is used in at least one monitor.') # noqa: E501
|
||||
)
|
||||
return HttpResponseRedirect(reverse('list_storage'))
|
||||
|
||||
|
||||
class CommentDelete(OwnerRequiredMixin, DeleteView):
|
||||
template_name = "generic/delete_template.html"
|
||||
model = Comment
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import copy
|
||||
import os
|
||||
|
||||
from django.contrib import messages
|
||||
@@ -8,15 +9,17 @@ from django.utils.translation import gettext as _
|
||||
from django.views.generic import UpdateView
|
||||
from django.views.generic.edit import FormMixin
|
||||
|
||||
from cookbook.forms import CommentForm, ExternalRecipeForm, StorageForm, SyncForm
|
||||
from cookbook.forms import CommentForm, ExternalRecipeForm, StorageForm, SyncForm, HomeAssistantConfigForm
|
||||
from cookbook.helper.permission_helper import (GroupRequiredMixin, OwnerRequiredMixin,
|
||||
above_space_limit, group_required)
|
||||
from cookbook.models import Comment, Recipe, RecipeImport, Storage, Sync
|
||||
from cookbook.models import Comment, Recipe, RecipeImport, Storage, Sync, HomeAssistantConfig
|
||||
from cookbook.provider.dropbox import Dropbox
|
||||
from cookbook.provider.local import Local
|
||||
from cookbook.provider.nextcloud import Nextcloud
|
||||
from recipes import settings
|
||||
|
||||
VALUE_NOT_CHANGED = '__NO__CHANGE__'
|
||||
|
||||
|
||||
@group_required('guest')
|
||||
def switch_recipe(request, pk):
|
||||
@@ -76,7 +79,7 @@ class SyncUpdate(GroupRequiredMixin, UpdateView, SpaceFormMixing):
|
||||
|
||||
@group_required('admin')
|
||||
def edit_storage(request, pk):
|
||||
instance = get_object_or_404(Storage, pk=pk, space=request.space)
|
||||
instance: Storage = get_object_or_404(Storage, pk=pk, space=request.space)
|
||||
|
||||
if not (instance.created_by == request.user or request.user.is_superuser):
|
||||
messages.add_message(request, messages.ERROR, _('You cannot edit this storage!'))
|
||||
@@ -87,17 +90,18 @@ def edit_storage(request, pk):
|
||||
return redirect('index')
|
||||
|
||||
if request.method == "POST":
|
||||
form = StorageForm(request.POST, instance=instance)
|
||||
form = StorageForm(request.POST, instance=copy.deepcopy(instance))
|
||||
if form.is_valid():
|
||||
instance.name = form.cleaned_data['name']
|
||||
instance.method = form.cleaned_data['method']
|
||||
instance.username = form.cleaned_data['username']
|
||||
instance.url = form.cleaned_data['url']
|
||||
instance.path = form.cleaned_data['path']
|
||||
|
||||
if form.cleaned_data['password'] != '__NO__CHANGE__':
|
||||
if form.cleaned_data['password'] != VALUE_NOT_CHANGED:
|
||||
instance.password = form.cleaned_data['password']
|
||||
|
||||
if form.cleaned_data['token'] != '__NO__CHANGE__':
|
||||
if form.cleaned_data['token'] != VALUE_NOT_CHANGED:
|
||||
instance.token = form.cleaned_data['token']
|
||||
|
||||
instance.save()
|
||||
@@ -113,8 +117,8 @@ def edit_storage(request, pk):
|
||||
)
|
||||
else:
|
||||
pseudo_instance = instance
|
||||
pseudo_instance.password = '__NO__CHANGE__'
|
||||
pseudo_instance.token = '__NO__CHANGE__'
|
||||
pseudo_instance.password = VALUE_NOT_CHANGED
|
||||
pseudo_instance.token = VALUE_NOT_CHANGED
|
||||
form = StorageForm(instance=pseudo_instance)
|
||||
|
||||
return render(
|
||||
@@ -124,6 +128,47 @@ def edit_storage(request, pk):
|
||||
)
|
||||
|
||||
|
||||
@group_required('admin')
|
||||
def edit_home_assistant_config(request, pk):
|
||||
instance: HomeAssistantConfig = get_object_or_404(HomeAssistantConfig, pk=pk, space=request.space)
|
||||
|
||||
if not (instance.created_by == request.user or request.user.is_superuser):
|
||||
messages.add_message(request, messages.ERROR, _('You cannot edit this homeassistant config!'))
|
||||
return HttpResponseRedirect(reverse('edit_home_assistant_config'))
|
||||
|
||||
if request.space.demo or settings.HOSTED:
|
||||
messages.add_message(request, messages.ERROR, _('This feature is not yet available in the hosted version of tandoor!'))
|
||||
return redirect('index')
|
||||
|
||||
if request.method == "POST":
|
||||
form = HomeAssistantConfigForm(request.POST, instance=copy.deepcopy(instance))
|
||||
if form.is_valid():
|
||||
instance.name = form.cleaned_data['name']
|
||||
instance.url = form.cleaned_data['url']
|
||||
instance.todo_entity = form.cleaned_data['todo_entity']
|
||||
instance.on_shopping_list_entry_created_enabled = form.cleaned_data['on_shopping_list_entry_created_enabled']
|
||||
instance.on_shopping_list_entry_updated_enabled = form.cleaned_data['on_shopping_list_entry_updated_enabled']
|
||||
instance.on_shopping_list_entry_deleted_enabled = form.cleaned_data['on_shopping_list_entry_deleted_enabled']
|
||||
|
||||
if form.cleaned_data['token'] != VALUE_NOT_CHANGED:
|
||||
instance.token = form.cleaned_data['token']
|
||||
|
||||
instance.save()
|
||||
|
||||
messages.add_message(request, messages.SUCCESS, _('HomeAssistant config saved!'))
|
||||
else:
|
||||
messages.add_message(request, messages.ERROR, _('There was an error updating this config!'))
|
||||
else:
|
||||
instance.token = VALUE_NOT_CHANGED
|
||||
form = HomeAssistantConfigForm(instance=instance)
|
||||
|
||||
return render(
|
||||
request,
|
||||
'generic/edit_template.html',
|
||||
{'form': form, 'title': _('HomeAssistantConfig')}
|
||||
)
|
||||
|
||||
|
||||
class CommentUpdate(OwnerRequiredMixin, UpdateView):
|
||||
template_name = "generic/edit_template.html"
|
||||
model = Comment
|
||||
|
||||
@@ -6,8 +6,8 @@ from django.utils.translation import gettext as _
|
||||
from django_tables2 import RequestConfig
|
||||
|
||||
from cookbook.helper.permission_helper import group_required
|
||||
from cookbook.models import InviteLink, RecipeImport, Storage, SyncLog, UserFile
|
||||
from cookbook.tables import ImportLogTable, InviteLinkTable, RecipeImportTable, StorageTable
|
||||
from cookbook.models import InviteLink, RecipeImport, Storage, SyncLog, UserFile, HomeAssistantConfig
|
||||
from cookbook.tables import ImportLogTable, InviteLinkTable, RecipeImportTable, StorageTable, HomeAssistantConfigTable
|
||||
|
||||
|
||||
@group_required('admin')
|
||||
@@ -65,17 +65,31 @@ def storage(request):
|
||||
)
|
||||
|
||||
|
||||
@group_required('admin')
|
||||
def home_assistant_config(request):
|
||||
table = HomeAssistantConfigTable(HomeAssistantConfig.objects.filter(space=request.space).all())
|
||||
RequestConfig(request, paginate={'per_page': 25}).configure(table)
|
||||
|
||||
return render(
|
||||
request, 'generic/list_template.html', {
|
||||
'title': _("HomeAssistant Config Backend"),
|
||||
'table': table,
|
||||
'create_url': 'new_home_assistant_config'
|
||||
})
|
||||
|
||||
|
||||
@group_required('admin')
|
||||
def invite_link(request):
|
||||
table = InviteLinkTable(
|
||||
InviteLink.objects.filter(valid_until__gte=datetime.today(), used_by=None, space=request.space).all())
|
||||
RequestConfig(request, paginate={'per_page': 25}).configure(table)
|
||||
|
||||
return render(request, 'generic/list_template.html', {
|
||||
'title': _("Invite Links"),
|
||||
'table': table,
|
||||
'create_url': 'new_invite_link'
|
||||
})
|
||||
return render(
|
||||
request, 'generic/list_template.html', {
|
||||
'title': _("Invite Links"),
|
||||
'table': table,
|
||||
'create_url': 'new_invite_link'
|
||||
})
|
||||
|
||||
|
||||
@group_required('user')
|
||||
@@ -195,7 +209,7 @@ def custom_filter(request):
|
||||
def user_file(request):
|
||||
try:
|
||||
current_file_size_mb = UserFile.objects.filter(space=request.space).aggregate(Sum('file_size_kb'))[
|
||||
'file_size_kb__sum'] / 1000
|
||||
'file_size_kb__sum'] / 1000
|
||||
except TypeError:
|
||||
current_file_size_mb = 0
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
from django.contrib import messages
|
||||
from django.http import HttpResponseRedirect
|
||||
from django.shortcuts import get_object_or_404, redirect, render
|
||||
@@ -6,9 +5,9 @@ from django.urls import reverse, reverse_lazy
|
||||
from django.utils.translation import gettext as _
|
||||
from django.views.generic import CreateView
|
||||
|
||||
from cookbook.forms import ImportRecipeForm, Storage, StorageForm
|
||||
from cookbook.forms import ImportRecipeForm, Storage, StorageForm, HomeAssistantConfigForm
|
||||
from cookbook.helper.permission_helper import GroupRequiredMixin, above_space_limit, group_required
|
||||
from cookbook.models import Recipe, RecipeImport, ShareLink, Step
|
||||
from cookbook.models import Recipe, RecipeImport, ShareLink, Step, HomeAssistantConfig
|
||||
from recipes import settings
|
||||
|
||||
|
||||
@@ -71,6 +70,30 @@ class StorageCreate(GroupRequiredMixin, CreateView):
|
||||
return context
|
||||
|
||||
|
||||
class HomeAssistantConfigCreate(GroupRequiredMixin, CreateView):
|
||||
groups_required = ['admin']
|
||||
template_name = "generic/new_template.html"
|
||||
model = HomeAssistantConfig
|
||||
form_class = HomeAssistantConfigForm
|
||||
success_url = reverse_lazy('list_home_assistant_config')
|
||||
|
||||
def form_valid(self, form):
|
||||
if self.request.space.demo or settings.HOSTED:
|
||||
messages.add_message(self.request, messages.ERROR, _('This feature is not yet available in the hosted version of tandoor!'))
|
||||
return redirect('index')
|
||||
|
||||
obj = form.save(commit=False)
|
||||
obj.created_by = self.request.user
|
||||
obj.space = self.request.space
|
||||
obj.save()
|
||||
return HttpResponseRedirect(reverse('edit_home_assistant_config', kwargs={'pk': obj.pk}))
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(HomeAssistantConfigCreate, self).get_context_data(**kwargs)
|
||||
context['title'] = _("HomeAssistant Config Backend")
|
||||
return context
|
||||
|
||||
|
||||
@group_required('user')
|
||||
def create_new_external_recipe(request, import_id):
|
||||
if request.method == "POST":
|
||||
|
||||
Reference in New Issue
Block a user