Coverage for cookbook/views/edit.py: 78%

132 statements  

« prev     ^ index     » next       coverage.py v7.4.0, created at 2023-12-29 01:02 +0100

1import os 

2 

3from django.contrib import messages 

4from django.http import HttpResponseRedirect 

5from django.shortcuts import get_object_or_404, redirect, render 

6from django.urls import reverse 

7from django.utils.translation import gettext as _ 

8from django.views.generic import UpdateView 

9from django.views.generic.edit import FormMixin 

10 

11from cookbook.forms import CommentForm, ExternalRecipeForm, StorageForm, SyncForm 

12from cookbook.helper.permission_helper import (GroupRequiredMixin, OwnerRequiredMixin, 

13 above_space_limit, group_required) 

14from cookbook.models import Comment, Recipe, RecipeImport, Storage, Sync 

15from cookbook.provider.dropbox import Dropbox 

16from cookbook.provider.local import Local 

17from cookbook.provider.nextcloud import Nextcloud 

18from recipes import settings 

19 

20 

21@group_required('guest') 

22def switch_recipe(request, pk): 

23 recipe = get_object_or_404(Recipe, pk=pk, space=request.space) 

24 if recipe.internal: 

25 return HttpResponseRedirect(reverse('edit_internal_recipe', args=[pk])) 

26 else: 

27 return HttpResponseRedirect(reverse('edit_external_recipe', args=[pk])) 

28 

29 

30@group_required('user') 

31def convert_recipe(request, pk): 

32 recipe = get_object_or_404(Recipe, pk=pk, space=request.space) 

33 if not recipe.internal: 

34 recipe.internal = True 

35 recipe.save() 

36 

37 return HttpResponseRedirect(reverse('edit_internal_recipe', args=[pk])) 

38 

39 

40@group_required('user') 

41def internal_recipe_update(request, pk): 

42 limit, msg = above_space_limit(request.space) 

43 if limit: 

44 messages.add_message(request, messages.WARNING, msg) 

45 return HttpResponseRedirect(reverse('view_recipe', args=[pk])) 

46 

47 recipe_instance = get_object_or_404(Recipe, pk=pk, space=request.space) 

48 

49 return render(request, 'forms/edit_internal_recipe.html', {'recipe': recipe_instance}) 

50 

51 

52class SpaceFormMixing(FormMixin): 

53 

54 def get_form_kwargs(self): 

55 kwargs = super().get_form_kwargs() 

56 kwargs.update({'space': self.request.space}) 

57 return kwargs 

58 

59 

60class SyncUpdate(GroupRequiredMixin, UpdateView, SpaceFormMixing): 

61 groups_required = ['admin'] 

62 template_name = "generic/edit_template.html" 

63 model = Sync 

64 form_class = SyncForm 

65 

66 # TODO add msg box 

67 

68 def get_success_url(self): 

69 return reverse('edit_sync', kwargs={'pk': self.object.pk}) 

70 

71 def get_context_data(self, **kwargs): 

72 context = super().get_context_data(**kwargs) 

73 context['title'] = _("Sync") 

74 return context 

75 

76 

77@group_required('admin') 

78def edit_storage(request, pk): 

79 instance = get_object_or_404(Storage, pk=pk, space=request.space) 

80 

81 if not (instance.created_by == request.user or request.user.is_superuser): 

82 messages.add_message(request, messages.ERROR, _('You cannot edit this storage!')) 

83 return HttpResponseRedirect(reverse('list_storage')) 

84 

85 if request.space.demo or settings.HOSTED: 

86 messages.add_message(request, messages.ERROR, _('This feature is not yet available in the hosted version of tandoor!')) 

87 return redirect('index') 

88 

89 if request.method == "POST": 

90 form = StorageForm(request.POST, instance=instance) 

91 if form.is_valid(): 

92 instance.name = form.cleaned_data['name'] 

93 instance.method = form.cleaned_data['method'] 

94 instance.username = form.cleaned_data['username'] 

95 instance.url = form.cleaned_data['url'] 

96 

97 if form.cleaned_data['password'] != '__NO__CHANGE__': 

98 instance.password = form.cleaned_data['password'] 

99 

100 if form.cleaned_data['token'] != '__NO__CHANGE__': 

101 instance.token = form.cleaned_data['token'] 

102 

103 instance.save() 

104 

105 messages.add_message( 

106 request, messages.SUCCESS, _('Storage saved!') 

107 ) 

108 else: 

109 messages.add_message( 

110 request, 

111 messages.ERROR, 

112 _('There was an error updating this storage backend!') 

113 ) 

114 else: 

115 pseudo_instance = instance 

116 pseudo_instance.password = '__NO__CHANGE__' 

117 pseudo_instance.token = '__NO__CHANGE__' 

118 form = StorageForm(instance=pseudo_instance) 

119 

120 return render( 

121 request, 

122 'generic/edit_template.html', 

123 {'form': form, 'title': _('Storage')} 

124 ) 

125 

126 

127class CommentUpdate(OwnerRequiredMixin, UpdateView): 

128 template_name = "generic/edit_template.html" 

129 model = Comment 

130 form_class = CommentForm 

131 

132 def get_success_url(self): 

133 return reverse('edit_comment', kwargs={'pk': self.object.pk}) 

134 

135 def get_context_data(self, **kwargs): 

136 context = super(CommentUpdate, self).get_context_data(**kwargs) 

137 context['title'] = _("Comment") 

138 context['view_url'] = reverse( 

139 'view_recipe', args=[self.object.recipe.pk] 

140 ) 

141 return context 

142 

143 

144class ImportUpdate(GroupRequiredMixin, UpdateView): 

145 groups_required = ['user'] 

146 template_name = "generic/edit_template.html" 

147 model = RecipeImport 

148 fields = ['name', 'path'] 

149 

150 # TODO add msg box 

151 

152 def get_success_url(self): 

153 return reverse('edit_import', kwargs={'pk': self.object.pk}) 

154 

155 def get_context_data(self, **kwargs): 

156 context = super(ImportUpdate, self).get_context_data(**kwargs) 

157 context['title'] = _("Import") 

158 return context 

159 

160 

161class ExternalRecipeUpdate(GroupRequiredMixin, UpdateView, SpaceFormMixing): 

162 groups_required = ['user'] 

163 model = Recipe 

164 form_class = ExternalRecipeForm 

165 template_name = "generic/edit_template.html" 

166 

167 def form_valid(self, form): 

168 self.object = form.save(commit=False) 

169 old_recipe = Recipe.objects.get(pk=self.object.pk, space=self.request.space) 

170 if not old_recipe.name == self.object.name: 

171 # TODO central location to handle storage type switches 

172 if self.object.storage.method == Storage.DROPBOX: 

173 Dropbox.rename_file(old_recipe, self.object.name) 

174 if self.object.storage.method == Storage.NEXTCLOUD: 

175 Nextcloud.rename_file(old_recipe, self.object.name) 

176 if self.object.storage.method == Storage.LOCAL: 

177 Local.rename_file(old_recipe, self.object.name) 

178 

179 self.object.file_path = "%s/%s%s" % ( 

180 os.path.dirname(self.object.file_path), 

181 self.object.name, 

182 os.path.splitext(self.object.file_path)[1] 

183 ) 

184 

185 messages.add_message(self.request, messages.SUCCESS, _('Changes saved!')) 

186 return super(ExternalRecipeUpdate, self).form_valid(form) 

187 

188 def form_invalid(self, form): 

189 messages.add_message(self.request, messages.ERROR, _('Error saving changes!')) 

190 return super(ExternalRecipeUpdate, self).form_valid(form) 

191 

192 def get_success_url(self): 

193 return reverse('edit_recipe', kwargs={'pk': self.object.pk}) 

194 

195 def get_context_data(self, **kwargs): 

196 context = super().get_context_data(**kwargs) 

197 context['title'] = _("Recipe") 

198 context['view_url'] = reverse('view_recipe', args=[self.object.pk]) 

199 if self.object.storage: 

200 context['delete_external_url'] = reverse( 

201 'delete_recipe_source', args=[self.object.pk] 

202 ) 

203 return context