From b7c8b95003ee18a9af449c31edcfe27cd46b9fde Mon Sep 17 00:00:00 2001 From: "byte[]" Date: Sat, 14 Dec 2019 17:07:43 -0500 Subject: [PATCH] more aliasing prep --- lib/philomena/tags.ex | 76 +++++++++++++++++++ lib/philomena/users/ability.ex | 4 + .../fingerprint_profile_controller.ex | 4 +- lib/philomena_web/plugs/load_topic_plug.ex | 2 +- 4 files changed, 83 insertions(+), 3 deletions(-) diff --git a/lib/philomena/tags.ex b/lib/philomena/tags.ex index 7bb6025a..84113f0f 100644 --- a/lib/philomena/tags.ex +++ b/lib/philomena/tags.ex @@ -11,6 +11,11 @@ defmodule Philomena.Tags do alias Philomena.Tags.Uploader alias Philomena.Images alias Philomena.Images.Image + alias Philomena.Users.User + alias Philomena.Filters.Filter + alias Philomena.Images.Tagging + alias Philomena.UserLinks.UserLink + alias Philomena.DnpEntries.DnpEntry @spec get_or_create_tags(String.t()) :: List.t() def get_or_create_tags(tag_list) do @@ -166,6 +171,77 @@ defmodule Philomena.Tags do |> Image.reindex() end + def alias_tag(%Tag{} = tag, attrs) do + target_tag = Repo.get_by!(Tag, name: attrs["target_tag"]) + + filters_hidden = where(Filter, [f], fragment("? @> ARRAY[?]", f.hidden_tag_ids, ^tag.id)) + filters_spoilered = where(Filter, [f], fragment("? @> ARRAY[?]", f.spoilered_tag_ids, ^tag.id)) + users_watching = where(User, [u], fragment("? @> ARRAY[?]", u.watched_tag_ids, ^tag.id)) + + array_replace(filters_hidden, :hidden_tag_ids, tag.id, target_tag.id) + array_replace(filters_spoilered, :spoilered_tag_ids, tag.id, target_tag.id) + array_replace(users_watching, :watched_tag_ids, tag.id, target_tag.id) + + # Manual insert all because ecto won't do it for us + Repo.query!( + "INSERT INTO image_taggings (image_id, tag_id) " <> + "SELECT i.id, #{target_tag.id} FROM images i " <> + "INNER JOIN image_tagging it on it.image_id = i.id " <> + "WHERE it.tag_id = #{tag.id} " <> + "ON CONFLICT DO NOTHING" + ) + + # Delete taggings on the source tag + Tagging + |> where(tag_id: ^tag.id) + |> Repo.delete_all() + + # Update other assocations + UserLink + |> where(tag_id: ^tag.id) + |> Repo.update_all(set: [tag_id: target_tag.id]) + + DnpEntry + |> where(tag_id: ^tag.id) + |> Repo.update_all(set: [tag_id: target_tag.id]) + + # Update counters + new_count = + Image + |> join(:inner, [i], _ in assoc(i, :tags)) + |> where([_i, t], t.id == ^target_tag.id) + |> Repo.aggregate(:count, :id) + + Tag + |> where(id: ^target_tag.id) + |> Repo.update_all(set: [images_count: new_count]) + + Tag + |> where(id: ^tag.id) + |> Repo.update_all(set: [images_count: 0, aliased_tag_id: target_tag.id, updated_at: DateTime.utc_now()]) + + # Finally, update images + Image + |> join(:inner, [i], _ in assoc(i, :tags)) + |> where([_i, t], t.id == ^target_tag.id) + |> preload(^Images.indexing_preloads()) + |> Image.reindex() + end + + defp array_replace(queryable, column, old_value, new_value) do + queryable + |> update( + [q], + set: [ + { + ^column, + fragment("ARRAY(SELECT DISTINCT unnest(array_replace(?, ?, ?)) ORDER BY 1)", field(q, ^column), ^old_value, ^new_value) + } + ] + ) + |> Repo.update_all([]) + end + @doc """ Returns an `%Ecto.Changeset{}` for tracking tag changes. diff --git a/lib/philomena/users/ability.ex b/lib/philomena/users/ability.ex index ff7e8d8a..4b6c465d 100644 --- a/lib/philomena/users/ability.ex +++ b/lib/philomena/users/ability.ex @@ -32,6 +32,7 @@ defimpl Canada.Can, for: [Atom, Philomena.Users.User] do # View images def can?(%User{role: "moderator"}, :show, %Image{}), do: true + def can?(%User{role: "moderator"}, :hide, %Image{}), do: true # View comments def can?(%User{role: "moderator"}, :show, %Comment{}), do: true @@ -67,7 +68,9 @@ defimpl Canada.Can, for: [Atom, Philomena.Users.User] do # Edit posts and comments def can?(%User{role: "moderator"}, :edit, %Post{}), do: true + def can?(%User{role: "moderator"}, :hide, %Post{}), do: true def can?(%User{role: "moderator"}, :edit, %Comment{}), do: true + def can?(%User{role: "moderator"}, :hide, %Comment{}), do: true # Show the DNP list def can?(%User{role: "moderator"}, :index, DnpEntry), do: true @@ -82,6 +85,7 @@ defimpl Canada.Can, for: [Atom, Philomena.Users.User] do def can?(%User{role: "moderator"}, _action, FingerprintBan), do: true # Hide topics + def can?(%User{role: "moderator"}, :show, %Topic{}), do: true def can?(%User{role: "moderator"}, :hide, %Topic{}), do: true # Edit tags diff --git a/lib/philomena_web/controllers/fingerprint_profile_controller.ex b/lib/philomena_web/controllers/fingerprint_profile_controller.ex index 168bcf9d..0c230516 100644 --- a/lib/philomena_web/controllers/fingerprint_profile_controller.ex +++ b/lib/philomena_web/controllers/fingerprint_profile_controller.ex @@ -21,7 +21,7 @@ defmodule PhilomenaWeb.FingerprintProfileController do |> where(fingerprint: ^fingerprint) |> Repo.all() - render(conn, "show.html", fingerprint: fingerprint, user_fps: user_fps, fp_bans: fp_bans) + render(conn, "show.html", fingerprint: fingerprint, user_fps: user_fps, fingerprint_bans: fp_bans) end defp authorize_ip(conn, _opts) do @@ -30,4 +30,4 @@ defmodule PhilomenaWeb.FingerprintProfileController do true -> conn end end -end \ No newline at end of file +end diff --git a/lib/philomena_web/plugs/load_topic_plug.ex b/lib/philomena_web/plugs/load_topic_plug.ex index 06c5dc7c..2135983f 100644 --- a/lib/philomena_web/plugs/load_topic_plug.ex +++ b/lib/philomena_web/plugs/load_topic_plug.ex @@ -15,7 +15,7 @@ defmodule PhilomenaWeb.LoadTopicPlug do Topic |> where(forum_id: ^forum.id, slug: ^to_string(conn.params[param])) - |> preload([:user, :poll, :forum]) + |> preload([:user, :poll, :forum, :deleted_by]) |> Repo.one() |> maybe_hide_topic(conn, show_hidden) end