def dispatch(self, request, *args, **kwargs): if self.permission_policy is not None: if self.permission_required is not None: if not self.permission_policy.user_has_permission( request.user, self.permission_required): return permission_denied(request) if self.any_permission_required is not None: if not self.permission_policy.user_has_any_permission( request.user, self.any_permission_required): return permission_denied(request) return super().dispatch(request, *args, **kwargs)
def edit(request, redirect_id): theredirect = get_object_or_404(models.Redirect, id=redirect_id) if not permission_policy.user_has_permission_for_instance( request.user, 'change', theredirect): return permission_denied(request) if request.method == 'POST': form = RedirectForm(request.POST, request.FILES, instance=theredirect) if form.is_valid(): form.save() messages.success( request, _("Redirect '{0}' updated.").format(theredirect.title), buttons=[ messages.button( reverse('wagtailredirects:edit', args=(theredirect.id, )), _('Edit')) ]) return redirect('wagtailredirects:index') else: messages.error(request, _("The redirect could not be saved due to errors.")) else: form = RedirectForm(instance=theredirect) return render( request, "wagtailredirects/edit.html", { 'redirect': theredirect, 'form': form, 'user_can_delete': permission_policy.user_has_permission(request.user, 'delete'), })
def copy(request, app_label, model_name, id): # Validate snippet has been registered and title_field is set. meta = snippet_copy_registry.get(app_label, model_name) if meta is None: raise Exception("This snippet isn't registered as copyable") try: model = apps.get_model(app_label, model_name) except LookupError: raise Http404 permission = get_permission_name('change', model) if not request.user.has_perm(permission): return permission_denied(request) snippet = get_object_or_404(model, id=id) # Create the form form = meta['copy_form_class'](request.POST or None, snippet=snippet, title_field_name=meta['title_field_name']) next_url = get_valid_next_url_from_request(request) for fn in hooks.get_hooks('before_copy_snippet'): result = fn(request, snippet) if hasattr(result, 'status_code'): return result # Check if user is submitting if request.method == 'POST': if form.is_valid(): # Copy the snippet new_snippet = form.copy() # Give a success message back to the user messages.success(request, _(f"{snippet.get_snippet_verbose_name()} '{snippet}' has been copied.").format(snippet)) for fn in hooks.get_hooks('after_copy_snippet'): result = fn(request, snippet, new_snippet) if hasattr(result, 'status_code'): return result if next_url: return redirect(next_url) if 'wagtail.contrib.modeladmin' in settings.INSTALLED_APPS: url_helper = AdminURLHelper(new_snippet) return redirect(url_helper.get_action_url('edit', quote(new_snippet.pk))) return redirect('wagtailsnippets:edit', app_label, model_name, new_snippet.id) return render(request, 'wagtailsnippetscopy/copy.html', { 'snippet': snippet, 'app_label': app_label, 'model_name': model_name, 'form': form, 'next': next_url, })
def edit(request, app_label, model_name, pk): model = get_snippet_model_from_url_params(app_label, model_name) permission = get_permission_name('change', model) if not request.user.has_perm(permission): return permission_denied(request) instance = get_object_or_404(model, pk=unquote(pk)) for fn in hooks.get_hooks('before_edit_snippet'): result = fn(request, instance) if hasattr(result, 'status_code'): return result edit_handler = get_snippet_edit_handler(model) edit_handler = edit_handler.bind_to(instance=instance, request=request) form_class = edit_handler.get_form_class() if request.method == 'POST': form = form_class(request.POST, request.FILES, instance=instance) if form.is_valid(): form.save() messages.success( request, _("%(snippet_type)s '%(instance)s' updated.") % { 'snippet_type': capfirst(model._meta.verbose_name), 'instance': instance }, buttons=[ messages.button( reverse('wagtailsnippets:edit', args=(app_label, model_name, quote(instance.pk))), _('Edit')) ]) for fn in hooks.get_hooks('after_edit_snippet'): result = fn(request, instance) if hasattr(result, 'status_code'): return result return redirect('wagtailsnippets:list', app_label, model_name) else: messages.validation_error( request, _("The snippet could not be saved due to errors."), form) else: form = form_class(instance=instance) edit_handler = edit_handler.bind_to(form=form) return TemplateResponse( request, 'wagtailsnippets/snippets/edit.html', { 'model_opts': model._meta, 'instance': instance, 'edit_handler': edit_handler, 'form': form, })
def multi_image_edit(request): images = Image.objects.filter(id__in=request.GET.getlist("id")) if request.method == "GET": forms = [] for image in images: instance = get_object_or_404(Image, id=image.id) if not permission_policy.user_has_permission_for_instance( request.user, "change", instance): return permission_denied(request) form = MultiImageEditForm(request.POST or None, instance=instance, prefix="image-%d" % instance.id) forms.append(form) return render(request, "wagtail_multi_image_edit/multi_edit.html", {"forms": forms}) elif request.method == "POST": image_id = request.POST["image_id"] instance = Image.objects.get(id=image_id) if not permission_policy.user_has_permission_for_instance( request.user, "change", instance): return permission_denied(request) form = MultiImageEditForm(request.POST, instance=instance, prefix="image-%d" % instance.id) if form.is_valid(): form.save() return JsonResponse({"success": True}) else: return JsonResponse({ "success": False, "form": render_to_string( "wagtail_multi_image_edit/_multi_edit_form.html", { "image": instance, "form": form }, request=request, ), })
def delete(request, app_label, model_name, pk=None): model = get_snippet_model_from_url_params(app_label, model_name) permission = get_permission_name('delete', model) if not request.user.has_perm(permission): return permission_denied(request) if pk: instances = [get_object_or_404(model, pk=unquote(pk))] else: ids = request.GET.getlist('id') instances = model.objects.filter(pk__in=ids) count = len(instances) if request.method == 'POST': for instance in instances: instance.delete() if count == 1: message_content = _("%(snippet_type)s '%(instance)s' deleted.") % { 'snippet_type': capfirst(model._meta.verbose_name), 'instance': instance } else: # This message is only used in plural form, but we'll define it with ngettext so that # languages with multiple plural forms can be handled correctly (or, at least, as # correctly as possible within the limitations of verbose_name_plural...) message_content = ngettext( "%(count)d %(snippet_type)s deleted.", "%(count)d %(snippet_type)s deleted.", count) % { 'snippet_type': capfirst(model._meta.verbose_name_plural), 'count': count } messages.success(request, message_content) for fn in hooks.get_hooks('after_delete_snippet'): result = fn(request, instances) if hasattr(result, 'status_code'): return result return redirect('wagtailsnippets:list', app_label, model_name) return TemplateResponse( request, 'wagtailsnippets/snippets/confirm_delete.html', { 'model_opts': model._meta, 'count': count, 'instances': instances, 'submit_url': (reverse('wagtailsnippets:delete-multiple', args=(app_label, model_name)) + '?' + urlencode([('id', instance.pk) for instance in instances])), })
def list(request, app_label, model_name): model = get_snippet_model_from_url_params(app_label, model_name) permissions = [ get_permission_name(action, model) for action in ['add', 'change', 'delete'] ] if not any([request.user.has_perm(perm) for perm in permissions]): return permission_denied(request) items = model.objects.all() # Preserve the snippet's model-level ordering if specified, but fall back on PK if not # (to ensure pagination is consistent) if not items.ordered: items = items.order_by('pk') # Search is_searchable = class_is_indexed(model) is_searching = False search_query = None if is_searchable and 'q' in request.GET: search_form = SearchForm(request.GET, placeholder=_("Search %(snippet_type_name)s") % { 'snippet_type_name': model._meta.verbose_name_plural }) if search_form.is_valid(): search_query = search_form.cleaned_data['q'] search_backend = get_search_backend() items = search_backend.search(search_query, items) is_searching = True else: search_form = SearchForm(placeholder=_("Search %(snippet_type_name)s") % { 'snippet_type_name': model._meta.verbose_name_plural }) paginator = Paginator(items, per_page=20) paginated_items = paginator.get_page(request.GET.get('p')) # Template if request.is_ajax(): template = 'wagtailsnippets/snippets/results.html' else: template = 'wagtailsnippets/snippets/type_index.html' return render(request, template, { 'model_opts': model._meta, 'items': paginated_items, 'can_add_snippet': request.user.has_perm(get_permission_name('add', model)), 'can_delete_snippets': request.user.has_perm(get_permission_name('delete', model)), 'is_searchable': is_searchable, 'search_form': search_form, 'is_searching': is_searching, 'query_string': search_query, })
def edit(request, app_label, model_name, pk): model = get_snippet_model_from_url_params(app_label, model_name) permission = get_permission_name('change', model) if not request.user.has_perm(permission): return permission_denied(request) instance = get_object_or_404(model, pk=unquote(pk)) edit_handler = get_snippet_edit_handler(model) edit_handler = edit_handler.bind_to(instance=instance, request=request) form_class = edit_handler.get_form_class() if request.method == 'POST': form = form_class(request.POST, request.FILES, instance=instance) if form.is_valid(): form.save() messages.success(request, _("{snippet_type} '{instance}' updated.").format( snippet_type=capfirst( model._meta.verbose_name_plural), instance=instance), buttons=[ messages.button( reverse('wagtailsnippets:edit', args=(app_label, model_name, quote(instance.pk))), _('Edit')) ]) return redirect('wagtailsnippets:list', app_label, model_name) else: messages.validation_error( request, _("The snippet could not be saved due to errors."), form) else: form = form_class(instance=instance) edit_handler = edit_handler.bind_to(form=form) return render( request, 'wagtailsnippets/snippets/edit.html', { # original version of snippets.py does not include 'can delete snippets' 'can_delete_snippets': request.user.has_perm(get_permission_name('delete', model)), 'model_opts': model._meta, 'instance': instance, 'edit_handler': edit_handler, 'form': form, })
def delete(request, image_id): image = get_object_or_404(get_image_model(), id=image_id) if not permission_policy.user_has_permission_for_instance(request.user, 'delete', image): return permission_denied(request) if request.method == 'POST': image.delete() messages.success(request, _("Image '{0}' deleted.").format(image.title)) return redirect('wagtailimages:index') return TemplateResponse(request, "wagtailimages/images/confirm_delete.html", { 'image': image, })
def delete(request, video_id): Video = get_video_model() video = get_object_or_404(Video, id=video_id) if not permission_policy.user_has_permission_for_instance(request.user, 'delete', video): return permission_denied(request) if request.POST: video.delete() messages.success(request, _("Video file '{0}' deleted.").format(video.title)) return redirect('wagtail_video:index') return render(request, "wagtail_video/video/confirm_delete.html", { 'video': video, })
def delete(request, document_id): Document = get_document_model() doc = get_object_or_404(Document, id=document_id) if not permission_policy.user_has_permission_for_instance(request.user, 'delete', doc): return permission_denied(request) if request.method == 'POST': doc.delete() messages.success(request, _("Document '{0}' deleted.").format(doc.title)) return redirect('wagtaildocs:index') return render(request, "wagtaildocs/documents/confirm_delete.html", { 'document': doc, })
def url_generator(request, image_id): image = get_object_or_404(get_image_model(), id=image_id) if not permission_policy.user_has_permission_for_instance(request.user, 'change', image): return permission_denied(request) form = URLGeneratorForm(initial={ 'filter_method': 'original', 'width': image.width, 'height': image.height, }) return TemplateResponse(request, "wagtailimages/images/url_generator.html", { 'image': image, 'form': form, })
def delete(request, redirect_id): theredirect = get_object_or_404(models.Redirect, id=redirect_id) if not permission_policy.user_has_permission_for_instance( request.user, 'delete', theredirect): return permission_denied(request) if request.method == 'POST': theredirect.delete() messages.success( request, _("Redirect '{0}' deleted.").format(theredirect.title)) return redirect('wagtailredirects:index') return render(request, "wagtailredirects/confirm_delete.html", { 'redirect': theredirect, })
def delete(request, media_id): Media = get_media_model() media = get_object_or_404(Media, id=media_id) if not permission_policy.user_has_permission_for_instance( request.user, 'delete', media): return permission_denied(request) if request.POST: media.delete() messages.success(request, _("Media file '{0}' deleted.").format(media.title)) return redirect('wagtailmedia:index') return render(request, "wagtailmedia/media/confirm_delete.html", { 'media': media, })
def create(request, app_label, model_name): model = get_snippet_model_from_url_params(app_label, model_name) permission = get_permission_name('add', model) if not request.user.has_perm(permission): return permission_denied(request) instance = model() edit_handler = get_snippet_edit_handler(model) edit_handler = edit_handler.bind_to(request=request) form_class = edit_handler.get_form_class() if request.method == 'POST': form = form_class(request.POST, request.FILES, instance=instance) if form.is_valid(): form.save() messages.success( request, _("%(snippet_type)s '%(instance)s' created.") % { 'snippet_type': capfirst(model._meta.verbose_name), 'instance': instance }, buttons=[ messages.button( reverse('wagtailsnippets:edit', args=(app_label, model_name, quote(instance.pk))), _('Edit')) ]) return redirect('wagtailsnippets:list', app_label, model_name) else: messages.validation_error( request, _("The snippet could not be created due to errors."), form) else: form = form_class(instance=instance) edit_handler = edit_handler.bind_to(instance=instance, form=form) return render(request, 'wagtailsnippets/snippets/create.html', { 'model_opts': model._meta, 'edit_handler': edit_handler, 'form': form, })
def delete(request, app_label, model_name, pk=None): model = get_snippet_model_from_url_params(app_label, model_name) permission = get_permission_name('delete', model) if not request.user.has_perm(permission): return permission_denied(request) if pk: instances = [get_object_or_404(model, pk=unquote(pk))] else: ids = request.GET.getlist('id') instances = model.objects.filter(pk__in=ids) count = len(instances) if request.method == 'POST': for instance in instances: instance.delete() if count == 1: message_content = _("{snippet_type} '{instance}' deleted.").format( snippet_type=capfirst(model._meta.verbose_name_plural), instance=instance ) else: message_content = _("{count} {snippet_type} deleted.").format( snippet_type=capfirst(model._meta.verbose_name_plural), count=count ) messages.success(request, message_content) return redirect('wagtailsnippets:list', app_label, model_name) return render(request, 'wagtailsnippets/snippets/confirm_delete.html', { 'model_opts': model._meta, 'count': count, 'instances': instances, 'submit_url': ( reverse('wagtailsnippets:delete-multiple', args=(app_label, model_name)) + '?' + urlencode([('id', instance.pk) for instance in instances]) ), })
def delete(request, user_id): user = get_object_or_404(User, pk=user_id) if not user_can_delete_user(request.user, user): return permission_denied(request) for fn in hooks.get_hooks('before_delete_user'): result = fn(request, user) if hasattr(result, 'status_code'): return result if request.method == 'POST': user.delete() messages.success(request, _("User '{0}' deleted.").format(user)) for fn in hooks.get_hooks('after_delete_user'): result = fn(request, user) if hasattr(result, 'status_code'): return result return redirect('wagtailusers_users:index') return render(request, "wagtailusers/users/confirm_delete.html", { 'user': user, })
def edit(request, image_id): Image = get_image_model() ImageForm = get_image_form(Image) image = get_object_or_404(Image, id=image_id) if not permission_policy.user_has_permission_for_instance( request.user, 'change', image): return permission_denied(request) if request.method == 'POST': original_file = image.file form = ImageForm(request.POST, request.FILES, instance=image, user=request.user) if form.is_valid(): if 'file' in form.changed_data: # Set new image file size image.file_size = image.file.size # Set new image file hash image.file.seek(0) image._set_file_hash(image.file.read()) image.file.seek(0) form.save() if 'file' in form.changed_data: # if providing a new image file, delete the old one and all renditions. # NB Doing this via original_file.delete() clears the file field, # which definitely isn't what we want... original_file.storage.delete(original_file.name) image.renditions.all().delete() # Reindex the image to make sure all tags are indexed search_index.insert_or_update_object(image) messages.success(request, _("Image '{0}' updated.").format(image.title), buttons=[ messages.button( reverse('wagtailimages:edit', args=(image.id, )), _('Edit again')) ]) return redirect('wagtailimages:index') else: messages.error(request, _("The image could not be saved due to errors.")) else: form = ImageForm(instance=image, user=request.user) # Check if we should enable the frontend url generator try: reverse('wagtailimages_serve', args=('foo', '1', 'bar')) url_generator_enabled = True except NoReverseMatch: url_generator_enabled = False if image.is_stored_locally(): # Give error if image file doesn't exist if not os.path.isfile(image.file.path): messages.error( request, _("The source image file could not be found. Please change the source or delete the image." ).format(image.title), buttons=[ messages.button( reverse('wagtailimages:delete', args=(image.id, )), _('Delete')) ]) try: filesize = image.get_file_size() except SourceImageIOError: filesize = None return render( request, "wagtailimages/images/edit.html", { 'image': image, 'form': form, 'url_generator_enabled': url_generator_enabled, 'filesize': filesize, 'user_can_delete': permission_policy.user_has_permission_for_instance( request.user, 'delete', image), })
def edit(request, media_id): Media = get_media_model() MediaForm = get_media_form(Media) media = get_object_or_404(Media, id=media_id) if not permission_policy.user_has_permission_for_instance( request.user, "change", media): return permission_denied(request) if request.POST: original_file = media.file form = MediaForm(request.POST, request.FILES, instance=media, user=request.user) if form.is_valid(): if "file" in form.changed_data: # if providing a new media file, delete the old one. # NB Doing this via original_file.delete() clears the file field, # which definitely isn't what we want... original_file.storage.delete(original_file.name) media = form.save() # Reindex the media entry to make sure all tags are indexed for backend in get_search_backends(): backend.add(media) messages.success( request, _("Media file '{0}' updated").format(media.title), buttons=[ messages.button( reverse("wagtailmedia:edit", args=(media.id, )), _("Edit")) ], ) return redirect("wagtailmedia:index") else: messages.error(request, _("The media could not be saved due to errors.")) else: form = MediaForm(instance=media, user=request.user) filesize = None # Get file size when there is a file associated with the Media object if media.file: try: filesize = media.file.size except OSError: # File doesn't exist pass if not filesize: messages.error( request, _("The file could not be found. Please change the source or delete the media file" ), buttons=[ messages.button( reverse("wagtailmedia:delete", args=(media.id, )), _("Delete")) ], ) return render( request, "wagtailmedia/media/edit.html", { "media": media, "filesize": filesize, "form": form, "user_can_delete": permission_policy.user_has_permission_for_instance( request.user, "delete", media), }, )
def edit(request, video_id): Video = get_video_model() VideoForm = get_video_form(Video) video = get_object_or_404(Video, id=video_id) if not permission_policy.user_has_permission_for_instance(request.user, 'change', video): return permission_denied(request) if request.POST: original_file = video.mp4 form = VideoForm(request.POST, request.FILES, instance=video, user=request.user) if form.is_valid(): if 'file' in form.changed_data: # if providing a new video file, delete the old one. # NB Doing this via original_file.delete() clears the file field, # which definitely isn't what we want... original_file.storage.delete(original_file.name) video = form.save() # Reindex the video entry to make sure all tags are indexed for backend in get_search_backends(): backend.add(video) messages.success(request, _("Video file '{0}' updated").format(video.title), buttons=[ messages.button(reverse('wagtail_video:edit', args=(video.id,)), _('Edit')) ]) return redirect('wagtail_video:index') else: messages.error(request, _("The video could not be saved due to errors.")) else: form = VideoForm(instance=video, user=request.user) filesize = None # Get file size when there is a file associated with the Video object if video.mp4: try: filesize = video.mp4.size except OSError: # File doesn't exist pass if video.ogg: try: filesize = video.ogg.size except OSError: # File doesn't exist pass if video.webm: try: filesize = video.webm.size except OSError: # File doesn't exist pass if not filesize: messages.error( request, _("The file could not be found. Please change the source or delete the video file"), buttons=[messages.button(reverse('wagtail_video:delete', args=(video.id,)), _('Delete'))] ) return render(request, "wagtail_video/video/edit.html", { 'video': video, 'filesize': filesize, 'form': form, 'user_can_delete': permission_policy.user_has_permission_for_instance( request.user, 'delete', video ), })
def edit(request, document_id): Document = get_document_model() DocumentForm = get_document_form(Document) doc = get_object_or_404(Document, id=document_id) if not permission_policy.user_has_permission_for_instance(request.user, 'change', doc): return permission_denied(request) if request.method == 'POST': original_file = doc.file form = DocumentForm(request.POST, request.FILES, instance=doc, user=request.user) if form.is_valid(): doc = form.save() if 'file' in form.changed_data: doc.file_size = doc.file.size # Set new document file hash doc.file.seek(0) doc._set_file_hash(doc.file.read()) doc.file.seek(0) # if providing a new document file, delete the old one. # NB Doing this via original_file.delete() clears the file field, # which definitely isn't what we want... original_file.storage.delete(original_file.name) # Reindex the document to make sure all tags are indexed search_index.insert_or_update_object(doc) messages.success(request, _("Document '{0}' updated").format(doc.title), buttons=[ messages.button(reverse('wagtaildocs:edit', args=(doc.id,)), _('Edit')) ]) return redirect('wagtaildocs:index') else: messages.error(request, _("The document could not be saved due to errors.")) else: form = DocumentForm(instance=doc, user=request.user) try: local_path = doc.file.path except NotImplementedError: # Document is hosted externally (eg, S3) local_path = None if local_path: # Give error if document file doesn't exist if not os.path.isfile(local_path): messages.error( request, _("The file could not be found. Please change the source or delete the document"), buttons=[messages.button(reverse('wagtaildocs:delete', args=(doc.id,)), _('Delete'))] ) return render(request, "wagtaildocs/documents/edit.html", { 'document': doc, 'filesize': doc.get_file_size(), 'form': form, 'user_can_delete': permission_policy.user_has_permission_for_instance( request.user, 'delete', doc ), })
def dispatch(self, request, *args, **kwargs): if not UserPagePermissionsProxy(request.user).can_remove_locks(): return permission_denied(request) return super().dispatch(request, *args, **kwargs)