From 20cc6cb9088e6927e16277e29088622948c0b222 Mon Sep 17 00:00:00 2001 From: "byte[]" Date: Mon, 7 Feb 2022 22:58:52 -0500 Subject: [PATCH] Finish thumbnailer, integrate hider --- lib/philomena/images/hider.ex | 54 --------------------- lib/philomena/images/thumbnailer.ex | 74 +++++++++++++++++++++++++---- lib/philomena/processors.ex | 8 ++-- 3 files changed, 68 insertions(+), 68 deletions(-) delete mode 100644 lib/philomena/images/hider.ex diff --git a/lib/philomena/images/hider.ex b/lib/philomena/images/hider.ex deleted file mode 100644 index aba0100d..00000000 --- a/lib/philomena/images/hider.ex +++ /dev/null @@ -1,54 +0,0 @@ -defmodule Philomena.Images.Hider do - @moduledoc """ - Hiding logic for images. - """ - - alias Philomena.Images.Image - - # sobelow_skip ["Traversal.FileModule"] - def hide_thumbnails(image, key) do - source = image_thumb_dir(image) - target = image_thumb_dir(image, key) - - File.rm_rf(target) - File.rename(source, target) - end - - # sobelow_skip ["Traversal.FileModule"] - def unhide_thumbnails(image, key) do - source = image_thumb_dir(image, key) - target = image_thumb_dir(image) - - File.rm_rf(target) - File.rename(source, target) - end - - # sobelow_skip ["Traversal.FileModule"] - 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 - - def purge_cache(files) do - {_out, 0} = System.cmd("purge-cache", [Jason.encode!(%{files: files})]) - - :ok - 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)]) - - defp image_thumb_dir(%Image{created_at: created_at, id: id}, key), - do: - Path.join([image_thumbnail_root(), time_identifier(created_at), to_string(id) <> "-" <> key]) - - defp time_identifier(time), - do: Enum.join([time.year, time.month, time.day], "/") - - defp image_thumbnail_root, - do: Application.get_env(:philomena, :image_file_root) <> "/thumbs" -end diff --git a/lib/philomena/images/thumbnailer.ex b/lib/philomena/images/thumbnailer.ex index 8ea1da72..2a14a4cb 100644 --- a/lib/philomena/images/thumbnailer.ex +++ b/lib/philomena/images/thumbnailer.ex @@ -22,6 +22,8 @@ defmodule Philomena.Images.Thumbnailer do tall: {1024, 4096} ] + @acl [acl: :public_read] + def thumbnail_versions do @versions end @@ -34,6 +36,34 @@ defmodule Philomena.Images.Thumbnailer do end) end + def hide_thumbnails(image, key) do + moved_files = Processors.versions(image.image_mime_type, generated_sizes(image)) + + source_prefix = visible_image_thumb_prefix(image) + target_prefix = hidden_image_thumb_prefix(image, key) + + bulk_rename(moved_files, source_prefix, target_prefix) + end + + def unhide_thumbnails(image, key) do + moved_files = Processors.versions(image.image_mime_type, generated_sizes(image)) + + source_prefix = hidden_image_thumb_prefix(image, key) + target_prefix = visible_image_thumb_prefix(image) + + bulk_rename(moved_files, source_prefix, target_prefix) + end + + def destroy_thumbnails(image) do + affected_files = Processors.versions(image.image_mime_type, generated_sizes(image)) + + hidden_prefix = hidden_image_thumb_prefix(image, image.hidden_image_key) + visible_prefix = visible_image_thumb_prefix(image) + + bulk_delete(affected_files, hidden_prefix) + bulk_delete(affected_files, visible_prefix) + end + def generate_thumbnails(image_id) do image = Repo.get!(Image, image_id) file = download_image_file(image) @@ -82,7 +112,7 @@ defmodule Philomena.Images.Thumbnailer do end defp download_image_file(image) do - tempfile = Briefly.create!(extname: "." <> image.image_format) + tempfile = Briefly.create!(extname: ".#{image.image_format}") path = Path.join(image_thumb_prefix(image), "full.#{image.image_format}") ExAws.request!(S3.download_file(bucket(), path, tempfile)) @@ -95,19 +125,43 @@ defmodule Philomena.Images.Thumbnailer do file |> S3.Upload.stream_file() - |> S3.upload(bucket(), path, acl: :public_read) + |> S3.upload(bucket(), path, @acl) |> ExAws.request!() end - defp image_thumb_prefix(%Image{ - created_at: created_at, - id: id, - hidden_from_users: true, - hidden_image_key: key - }), - do: Path.join([image_file_root(), time_identifier(created_at), "#{id}-#{key}"]) + def bulk_rename(file_names, source_prefix, target_prefix) do + Enum.map(file_names, fn name -> + source = Path.join(source_prefix, name) + target = Path.join(target_prefix, name) - defp image_thumb_prefix(%Image{created_at: created_at, id: id}), + ExAws.request!(S3.put_object_copy(bucket(), target, bucket(), source, @acl)) + ExAws.request!(S3.delete_object(bucket(), source)) + end) + end + + def bulk_delete(file_names, prefix) do + Enum.map(file_names, fn name -> + target = Path.join(prefix, name) + + ExAws.request!(S3.delete_object(bucket(), target)) + end) + end + + # This method wraps the following two for code that doesn't care + # and just wants the files (most code should take this path) + + defp image_thumb_prefix(%{hidden_from_users: true} = image), + do: hidden_image_thumb_prefix(image, image.hidden_image_key) + + defp image_thumb_prefix(image), + do: visible_image_thumb_prefix(image) + + # These methods handle the actual distinction between the two + + defp hidden_image_thumb_prefix(%Image{created_at: created_at, id: id}, key), + do: Path.join([image_file_root(), time_identifier(created_at), "#{id}-#{key}"]) + + defp visible_image_thumb_prefix(%Image{created_at: created_at, id: id}), do: Path.join([image_file_root(), time_identifier(created_at), to_string(id)]) defp time_identifier(time), diff --git a/lib/philomena/processors.ex b/lib/philomena/processors.ex index 531d0533..202da1d4 100644 --- a/lib/philomena/processors.ex +++ b/lib/philomena/processors.ex @@ -41,12 +41,12 @@ defmodule Philomena.Processors do def processor(_content_type), do: nil @doc """ - Takes an analyzer and version list and generates a list of versions to be + Takes a MIME type and version list and generates a list of versions to be generated (e.g., ["thumb.png"]). List contents differ based on file type. """ - @spec versions(map(), keyword) :: [String.t()] - def versions(analysis, valid_sizes) do - processor(analysis.mime_type).versions(valid_sizes) + @spec versions(String.t(), keyword) :: [String.t()] + def versions(mime_type, valid_sizes) do + processor(mime_type).versions(valid_sizes) end @doc """