mirror of
https://github.com/philomena-dev/philomena.git
synced 2024-11-23 20:18:00 +01:00
add irreversible admin-only action to permanently delete an image file
This commit is contained in:
parent
90a16b3317
commit
3ba38edf0b
7 changed files with 74 additions and 0 deletions
|
@ -138,6 +138,20 @@ defmodule Philomena.Images do
|
|||
|> Repo.isolated_transaction(:serializable)
|
||||
end
|
||||
|
||||
def destroy_image(%Image{} = image) do
|
||||
changeset = Image.remove_image_changeset(image)
|
||||
|
||||
Multi.new()
|
||||
|> Multi.update(:image, changeset)
|
||||
|> Multi.run(:remove_file, fn _repo, %{image: image} ->
|
||||
Uploader.unpersist_old_upload(image)
|
||||
Hider.destroy_thumbnails(image)
|
||||
|
||||
{:ok, nil}
|
||||
end)
|
||||
|> Repo.isolated_transaction(:serializable)
|
||||
end
|
||||
|
||||
def lock_comments(%Image{} = image, locked) do
|
||||
image
|
||||
|> Image.lock_comments_changeset(locked)
|
||||
|
|
|
@ -21,6 +21,14 @@ defmodule Philomena.Images.Hider do
|
|||
File.rename(source, target)
|
||||
end
|
||||
|
||||
def destroy_thumbnails(image) do
|
||||
hidden = image_thumb_dir(image, image.hidden_image_key)
|
||||
normal = image_thumb_dir(image)
|
||||
|
||||
File.rm_rf(hidden)
|
||||
File.rm_rf(normal)
|
||||
end
|
||||
|
||||
# fixme: these are copied from the thumbnailer
|
||||
defp image_thumb_dir(%Image{created_at: created_at, id: id}),
|
||||
do: Path.join([image_thumbnail_root(), time_identifier(created_at), to_string(id)])
|
||||
|
|
|
@ -166,6 +166,12 @@ defmodule Philomena.Images.Image do
|
|||
|> unsafe_validate_unique([:image_orig_sha512_hash], Repo)
|
||||
end
|
||||
|
||||
def remove_image_changeset(image) do
|
||||
image
|
||||
|> change(removed_image: image.image)
|
||||
|> change(image: nil)
|
||||
end
|
||||
|
||||
def source_changeset(image, attrs) do
|
||||
image
|
||||
|> cast(attrs, [:source_url])
|
||||
|
|
|
@ -45,6 +45,7 @@ defimpl Canada.Can, for: [Atom, Philomena.Users.User] do
|
|||
def can?(%User{role: "moderator"}, :show, %Filter{}), do: true
|
||||
|
||||
# Manage images
|
||||
def can?(%User{role: "moderator"}, :destroy, %Image{}), do: false
|
||||
def can?(%User{role: "moderator"}, _action, Image), do: true
|
||||
def can?(%User{role: "moderator"}, _action, %Image{}), do: true
|
||||
|
||||
|
|
39
lib/philomena_web/controllers/image/destroy_controller.ex
Normal file
39
lib/philomena_web/controllers/image/destroy_controller.ex
Normal file
|
@ -0,0 +1,39 @@
|
|||
defmodule PhilomenaWeb.Image.DestroyController do
|
||||
use PhilomenaWeb, :controller
|
||||
|
||||
alias Philomena.Images.Image
|
||||
alias Philomena.Images
|
||||
|
||||
plug PhilomenaWeb.CanaryMapPlug, create: :destroy
|
||||
plug :load_and_authorize_resource, model: Image, id_name: "image_id", persisted: true
|
||||
plug :verify_deleted when action in [:create]
|
||||
|
||||
def create(conn, _params) do
|
||||
image = conn.assigns.image
|
||||
|
||||
case Images.destroy_image(image) do
|
||||
{:ok, %{image: image}} ->
|
||||
conn
|
||||
|> put_flash(:info, "Image contents destroyed.")
|
||||
|> redirect(to: Routes.image_path(conn, :show, image))
|
||||
|
||||
_error ->
|
||||
conn
|
||||
|> put_flash(:error, "Failed to destroy image.")
|
||||
|> redirect(to: Routes.image_path(conn, :show, image))
|
||||
end
|
||||
end
|
||||
|
||||
defp verify_deleted(conn, _opts) do
|
||||
case conn.assigns.image.hidden_from_users do
|
||||
true ->
|
||||
conn
|
||||
|
||||
_false ->
|
||||
conn
|
||||
|> put_flash(:error, "Cannot destroy a non-hidden image!")
|
||||
|> redirect(to: Routes.image_path(conn, :show, conn.assigns.image))
|
||||
|> halt()
|
||||
end
|
||||
end
|
||||
end
|
|
@ -201,6 +201,7 @@ defmodule PhilomenaWeb.Router do
|
|||
resources "/scratchpad", Image.ScratchpadController, only: [:edit, :update], singleton: true
|
||||
resources "/uploader", Image.UploaderController, only: [:update], singleton: true
|
||||
resources "/anonymous", Image.AnonymousController, only: [:create, :delete], singleton: true
|
||||
resources "/destroy", Image.DestroyController, only: [:create], singleton: true
|
||||
|
||||
resources "/comment_lock", Image.CommentLockController,
|
||||
only: [:create, :delete],
|
||||
|
|
|
@ -141,3 +141,8 @@
|
|||
= button_to "Lock tag editing", Routes.image_tag_lock_path(@conn, :create, @image), method: "post", class: "button"
|
||||
- else
|
||||
= button_to "Unlock tag editing", Routes.image_tag_lock_path(@conn, :delete, @image), method: "delete", class: "button"
|
||||
|
||||
= if @image.hidden_from_users and can?(@conn, :destroy, @image) do
|
||||
br
|
||||
.flex.flex--spaced-out
|
||||
= button_to "Destroy image", Routes.image_destroy_path(@conn, :create, @image), method: "post", class: "button button--state-danger", data: [confirm: "This action is IRREVERSIBLE. Are you sure?"]
|
||||
|
|
Loading…
Reference in a new issue