more aliasing prep

This commit is contained in:
byte[] 2019-12-14 17:07:43 -05:00
parent 05c427e013
commit b7c8b95003
4 changed files with 83 additions and 3 deletions

View file

@ -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.

View file

@ -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

View file

@ -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

View file

@ -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