From 012eae6af817af1d1984d2eb6619dbeef3937122 Mon Sep 17 00:00:00 2001 From: mdashlw <mdashlw@gmail.com> Date: Sat, 22 Feb 2025 09:39:09 +0000 Subject: [PATCH] New permission to access duplicates --- lib/philomena/users/ability.ex | 8 + .../templates/image/_image_meta.html.slime | 10 +- .../templates/image/_image_target.html.slime | 2 +- .../templates/image/deleted.html.slime | 2 +- .../templates/image/show.html.slime | 2 +- lib/philomena_web/views/admin/user_view.ex | 3 + .../views/api/json/image_view.ex | 140 +++++++++--------- lib/philomena_web/views/image_view.ex | 15 +- priv/repo/seeds.json | 3 +- 9 files changed, 95 insertions(+), 90 deletions(-) diff --git a/lib/philomena/users/ability.ex b/lib/philomena/users/ability.ex index 527dea95..51eeac18 100644 --- a/lib/philomena/users/ability.ex +++ b/lib/philomena/users/ability.ex @@ -436,6 +436,14 @@ defimpl Canada.Can, for: [Atom, Philomena.Users.User] do when action in [:show, :index], do: true + def can?( + %User{role_map: %{"Image" => %{"duplicate_access" => _}}}, + action, + %Image{hidden_from_users: true, duplicate_id: duplicate_id} + ) + when action in [:show, :index] and not is_nil(duplicate_id), + do: true + def can?(_user, :show, %Tag{}), do: true # Comment on images where that is allowed diff --git a/lib/philomena_web/templates/image/_image_meta.html.slime b/lib/philomena_web/templates/image/_image_meta.html.slime index 23c88c19..2a81e03c 100644 --- a/lib/philomena_web/templates/image/_image_meta.html.slime +++ b/lib/philomena_web/templates/image/_image_meta.html.slime @@ -38,16 +38,18 @@ i.fa.fa-sitemap> span.hide-limited-desktop.hide-mobile Related .stretched-mobile-links - a href="#{pretty_url(@image, false, false)}" rel="nofollow" title="View (tags in filename)" + - can_show = can?(@conn, :show, @image) + + a href="#{pretty_url(@image, can_show, false, false)}" rel="nofollow" title="View (tags in filename)" i.fa.fa-eye> | View - a href="#{pretty_url(@image, true, false)}" rel="nofollow" title="View (no tags in filename)" + a href="#{pretty_url(@image, can_show, true, false)}" rel="nofollow" title="View (no tags in filename)" i.fa.fa-eye> | VS - a href="#{pretty_url(@image, false, true)}" rel="nofollow" title="Download (tags in filename)" + a href="#{pretty_url(@image, can_show, false, true)}" rel="nofollow" title="Download (tags in filename)" i.fa.fa-download> | Download - a href="#{pretty_url(@image, true, true)}" title="Download (no tags in filename)" + a href="#{pretty_url(@image, can_show, true, true)}" title="Download (no tags in filename)" i.fa.fa-download> | DS .image-metabar.flex.flex--wrap.block__header--user-credit.center--layout#extrameta diff --git a/lib/philomena_web/templates/image/_image_target.html.slime b/lib/philomena_web/templates/image/_image_target.html.slime index fba84b3a..0fe486dc 100644 --- a/lib/philomena_web/templates/image/_image_target.html.slime +++ b/lib/philomena_web/templates/image/_image_target.html.slime @@ -12,7 +12,7 @@ ' . = if size == :full and not embed_display do - .image-target.hidden.image-show data-scaled=scaled_value(@conn.assigns.current_user) data-uris=Jason.encode!(thumb_urls(@image, can?(@conn, :hide, @image))) data-width=@image.image_width data-height=@image.image_height data-image-size=@image.image_size data-mime-type=@image.image_mime_type + .image-target.hidden.image-show data-scaled=scaled_value(@conn.assigns.current_user) data-uris=Jason.encode!(thumb_urls(@image, can?(@conn, :show, @image))) data-width=@image.image_width data-height=@image.image_height data-image-size=@image.image_size data-mime-type=@image.image_mime_type = if @image.image_mime_type == "video/webm" do video controls=true - else diff --git a/lib/philomena_web/templates/image/deleted.html.slime b/lib/philomena_web/templates/image/deleted.html.slime index fc425b36..b01fb656 100644 --- a/lib/philomena_web/templates/image/deleted.html.slime +++ b/lib/philomena_web/templates/image/deleted.html.slime @@ -32,7 +32,7 @@ = link "rules of the site", to: "/pages/rules" ' . Other useful links can be found at the bottom of the page. -= if can?(@conn, :hide, @image) do += if can?(@conn, :show, @image) do = render PhilomenaWeb.ImageView, "show.html", assigns - else p diff --git a/lib/philomena_web/templates/image/show.html.slime b/lib/philomena_web/templates/image/show.html.slime index 2c2a8f23..1c0789b4 100644 --- a/lib/philomena_web/templates/image/show.html.slime +++ b/lib/philomena_web/templates/image/show.html.slime @@ -19,7 +19,7 @@ - @conn.assigns.current_ban -> = render PhilomenaWeb.BanView, "_ban_reason.html", conn: @conn - - @image.commenting_allowed -> + - can?(@conn, :create_comment, @image) -> = render PhilomenaWeb.Image.CommentView, "_form.html", image: @image, changeset: @comment_changeset, remote: true, conn: @conn - true -> diff --git a/lib/philomena_web/views/admin/user_view.ex b/lib/philomena_web/views/admin/user_view.ex index 19f33b48..68d8cd9c 100644 --- a/lib/philomena_web/views/admin/user_view.ex +++ b/lib/philomena_web/views/admin/user_view.ex @@ -58,6 +58,8 @@ defmodule PhilomenaWeb.Admin.UserView do def description("admin", "StaticPage"), do: "Manage static pages" def description("admin", "Image"), do: "Hard-delete images" + def description("duplicate_access", "Image"), do: "View duplicate images" + def description(_name, _resource_type), do: "(unknown permission)" def filtered_roles(permission_set, roles) do @@ -68,6 +70,7 @@ defmodule PhilomenaWeb.Admin.UserView do def general_permissions do [ + ["duplicate_access", "Image"], ["batch_update", "Tag"] ] end diff --git a/lib/philomena_web/views/api/json/image_view.ex b/lib/philomena_web/views/api/json/image_view.ex index f72a676e..cc199b1a 100644 --- a/lib/philomena_web/views/api/json/image_view.ex +++ b/lib/philomena_web/views/api/json/image_view.ex @@ -17,81 +17,75 @@ defmodule PhilomenaWeb.Api.Json.ImageView do } end - def render("image.json", %{ - image: %{hidden_from_users: true, duplicate_id: duplicate_id} = image - }) - when not is_nil(duplicate_id) do - %{ - id: image.id, - created_at: image.created_at, - updated_at: image.updated_at, - first_seen_at: image.first_seen_at, - duplicate_of: image.duplicate_id, - deletion_reason: nil, - hidden_from_users: true - } - end + def render("image.json", %{image: image} = assigns) do + user = + case assigns do + %{conn: %{assigns: %{current_user: current_user}}} -> current_user + _ -> nil + end - def render("image.json", %{image: %{hidden_from_users: true} = image}) do - %{ - id: image.id, - created_at: image.created_at, - updated_at: image.updated_at, - first_seen_at: image.first_seen_at, - deletion_reason: image.deletion_reason, - duplicate_of: nil, - hidden_from_users: true - } - end + case Canada.Can.can?(user, :show, image) do + true -> + %{ + id: image.id, + created_at: image.created_at, + updated_at: image.updated_at, + first_seen_at: image.first_seen_at, + width: image.image_width, + height: image.image_height, + mime_type: image.image_mime_type, + size: image.image_size, + orig_size: image.image_orig_size, + duration: image.image_duration, + animated: image.image_is_animated, + format: image.image_format, + aspect_ratio: image.image_aspect_ratio, + name: image.image_name, + sha512_hash: image.image_sha512_hash, + orig_sha512_hash: image.image_orig_sha512_hash, + tags: Enum.map(image.tags, & &1.name), + tag_ids: Enum.map(image.tags, & &1.id), + uploader: if(!!image.user and !image.anonymous, do: image.user.name), + uploader_id: if(!!image.user and !image.anonymous, do: image.user.id), + wilson_score: Philomena.Images.SearchIndex.wilson_score(image), + intensities: intensities(image), + score: image.score, + upvotes: image.upvotes_count, + downvotes: image.downvotes_count, + faves: image.faves_count, + comment_count: image.comments_count, + tag_count: length(image.tags), + description: image.description, + source_url: + if(Enum.count(image.sources) > 0, do: Enum.at(image.sources, 0).source, else: ""), + source_urls: Enum.map(image.sources, & &1.source), + view_url: ImageView.pretty_url(image, true, false, false), + representations: ImageView.thumb_urls(image, true), + thumbnails_generated: image.thumbnails_generated, + processed: image.processed, + deletion_reason: nil, + duplicate_of: image.duplicate_id, + hidden_from_users: image.hidden_from_users + } + |> Map.put( + :spoilered, + case assigns do + %{conn: conn} -> ImageView.filter_or_spoiler_hits?(conn, image) + _ -> false + end + ) - def render("image.json", %{conn: conn, image: %{hidden_from_users: false} = image}) do - result = render_one(image, PhilomenaWeb.Api.Json.ImageView, "image.json", %{image: image}) - - Map.put(result, :spoilered, ImageView.filter_or_spoiler_hits?(conn, image)) - end - - def render("image.json", %{image: %{hidden_from_users: false} = image}) do - %{ - id: image.id, - created_at: image.created_at, - updated_at: image.updated_at, - first_seen_at: image.first_seen_at, - width: image.image_width, - height: image.image_height, - mime_type: image.image_mime_type, - size: image.image_size, - orig_size: image.image_orig_size, - duration: image.image_duration, - animated: image.image_is_animated, - format: image.image_format, - aspect_ratio: image.image_aspect_ratio, - name: image.image_name, - sha512_hash: image.image_sha512_hash, - orig_sha512_hash: image.image_orig_sha512_hash, - tags: Enum.map(image.tags, & &1.name), - tag_ids: Enum.map(image.tags, & &1.id), - uploader: if(!!image.user and !image.anonymous, do: image.user.name), - uploader_id: if(!!image.user and !image.anonymous, do: image.user.id), - wilson_score: Philomena.Images.SearchIndex.wilson_score(image), - intensities: intensities(image), - score: image.score, - upvotes: image.upvotes_count, - downvotes: image.downvotes_count, - faves: image.faves_count, - comment_count: image.comments_count, - tag_count: length(image.tags), - description: image.description, - source_url: - if(Enum.count(image.sources) > 0, do: Enum.at(image.sources, 0).source, else: ""), - source_urls: Enum.map(image.sources, & &1.source), - view_url: ImageView.pretty_url(image, false, false), - representations: ImageView.thumb_urls(image, false), - thumbnails_generated: image.thumbnails_generated, - processed: image.processed, - deletion_reason: nil, - duplicate_of: nil, - hidden_from_users: false - } + false -> + %{ + id: image.id, + created_at: image.created_at, + updated_at: image.updated_at, + first_seen_at: image.first_seen_at, + deletion_reason: image.deletion_reason, + duplicate_of: image.duplicate_id, + hidden_from_users: image.hidden_from_users + } + end end def render("error.json", %{changeset: changeset}) do diff --git a/lib/philomena_web/views/image_view.ex b/lib/philomena_web/views/image_view.ex index a10cad01..b795fec5 100644 --- a/lib/philomena_web/views/image_view.ex +++ b/lib/philomena_web/views/image_view.ex @@ -70,14 +70,8 @@ defmodule PhilomenaWeb.ImageView do |> Map.get(version_name, :full) end - defp append_full_url(urls, %{hidden_from_users: false} = image, _show_hidden), - do: Map.put(urls, :full, pretty_url(image, true, false)) - - defp append_full_url(urls, %{hidden_from_users: true} = image, true), - do: Map.put(urls, :full, thumb_url(image, true, :full)) - - defp append_full_url(urls, _image, _show_hidden), - do: urls + defp append_full_url(urls, image, show_hidden), + do: Map.put(urls, :full, pretty_url(image, show_hidden, true, false)) defp append_gif_urls(urls, %{image_mime_type: "image/gif"} = image, show_hidden) do full_url = thumb_url(image, show_hidden, :full) @@ -114,7 +108,10 @@ defmodule PhilomenaWeb.ImageView do "#{root}/#{year}/#{month}/#{day}/#{id_fragment}/#{name}.#{format}" end - def pretty_url(image, short, download) do + def pretty_url(%{hidden_from_users: true} = image, true, _short, _download), + do: thumb_url(image, true, :full) + + def pretty_url(image, _show_hidden, short, download) do %{year: year, month: month, day: day} = image.created_at root = image_url_root() diff --git a/priv/repo/seeds.json b/priv/repo/seeds.json index 3c5f06d9..315cdd97 100644 --- a/priv/repo/seeds.json +++ b/priv/repo/seeds.json @@ -90,7 +90,8 @@ {"name": "moderator", "resource_type": "Topic"}, {"name": "admin", "resource_type": "Advert"}, {"name": "admin", "resource_type": "StaticPage"}, - {"name": "admin", "resource_type": "Image"} + {"name": "admin", "resource_type": "Image"}, + {"name": "duplicate_access", "resource_type": "Image"} ], "pages": [] }