aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/pleroma/tag.ex35
-rw-r--r--lib/pleroma/user.ex127
-rw-r--r--lib/pleroma/user/query.ex4
-rw-r--r--lib/pleroma/web/activity_pub/mrf/tag_policy.ex6
-rw-r--r--lib/pleroma/web/admin_api/views/account_view.ex3
-rw-r--r--lib/pleroma/web/mastodon_api/views/account_view.ex4
6 files changed, 125 insertions, 54 deletions
diff --git a/lib/pleroma/tag.ex b/lib/pleroma/tag.ex
index 5185a907b..3b01f1119 100644
--- a/lib/pleroma/tag.ex
+++ b/lib/pleroma/tag.ex
@@ -22,11 +22,23 @@ defmodule Pleroma.Tag do
@spec upsert(String.t()) :: {:ok, t()} | {:error, Ecto.Changeset.t()}
def upsert(name) do
%__MODULE__{}
- |> Ecto.Changeset.change(name: name)
+ |> Ecto.Changeset.change(name: normalize_tag(name))
|> Ecto.Changeset.unique_constraint(:name)
|> Repo.insert(on_conflict: :nothing, conflict_target: :name)
end
+ @spec upsert_tags(list(String.t())) :: {integer(), nil | [term()]}
+ def upsert_tags(names) do
+ date = NaiveDateTime.utc_now()
+
+ tags =
+ names
+ |> normalize_tags()
+ |> Enum.map(&%{name: &1, inserted_at: date, updated_at: date})
+
+ Repo.insert_all("tags", tags, on_conflict: :nothing, conflict_target: :name)
+ end
+
@spec list_tags() :: list(String.t())
def list_tags do
from(u in __MODULE__, select: u.name)
@@ -35,4 +47,25 @@ defmodule Pleroma.Tag do
|> Enum.uniq()
|> Enum.sort()
end
+
+ def get_tag_ids(tag_names) do
+ names = normalize_tags(tag_names)
+
+ from(
+ u in __MODULE__,
+ select: u.id,
+ where: u.name in ^names
+ )
+ |> Repo.all()
+ end
+
+ def normalize_tags(tag_names) do
+ tag_names
+ |> List.wrap()
+ |> Enum.map(&normalize_tag/1)
+ end
+
+ defp normalize_tag(tag_name) do
+ String.trim(String.downcase(tag_name))
+ end
end
diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex
index e4cb8e5c1..9396815e9 100644
--- a/lib/pleroma/user.ex
+++ b/lib/pleroma/user.ex
@@ -1674,43 +1674,51 @@ defmodule Pleroma.User do
def purge_user_changeset(user) do
# "Right to be forgotten"
# https://gdpr.eu/right-to-be-forgotten/
- change(user, %{
- bio: "",
- raw_bio: nil,
- email: nil,
- name: nil,
- password_hash: nil,
- keys: nil,
- public_key: nil,
- avatar: %{},
- tags: [],
- last_refreshed_at: nil,
- last_digest_emailed_at: nil,
- banner: %{},
- background: %{},
- note_count: 0,
- follower_count: 0,
- following_count: 0,
- is_locked: false,
- is_confirmed: true,
- password_reset_pending: false,
- is_approved: true,
- registration_reason: nil,
- confirmation_token: nil,
- domain_blocks: [],
- is_active: false,
- ap_enabled: false,
- is_moderator: false,
- is_admin: false,
- mastofe_settings: nil,
- mascot: nil,
- emoji: %{},
- pleroma_settings_store: %{},
- fields: [],
- raw_fields: [],
- is_discoverable: false,
- also_known_as: []
- })
+
+ default_user_attrs =
+ Map.take(
+ %__MODULE__{},
+ [
+ :registration_reason,
+ :is_discoverable,
+ :mastofe_settings,
+ :email,
+ :background,
+ :is_approved,
+ :avatar,
+ :password_hash,
+ :public_key,
+ :mascot,
+ :is_confirmed,
+ :is_locked,
+ :ap_enabled,
+ :note_count,
+ :pleroma_settings_store,
+ :follower_count,
+ :bio,
+ :name,
+ :is_admin,
+ :is_moderator,
+ :also_known_as,
+ :keys,
+ :confirmation_token,
+ :banner,
+ :raw_fields,
+ :fields,
+ :password_reset_pending,
+ :domain_blocks,
+ :last_digest_emailed_at,
+ :raw_bio,
+ :last_refreshed_at,
+ :emoji,
+ :following_count
+ ]
+ )
+
+ user
+ |> Repo.preload([:tags])
+ |> change(Map.merge(default_user_attrs, %{is_active: false}))
+ |> put_assoc(:tags, [])
end
def delete(users) when is_list(users) do
@@ -2007,8 +2015,11 @@ defmodule Pleroma.User do
def tag(nickname, tags) when is_binary(nickname),
do: tag(get_by_nickname(nickname), tags)
- def tag(%User{} = user, tags),
- do: update_tags(user, Enum.uniq((user.tags || []) ++ normalize_tags(tags)))
+ def tag(%User{} = user, tags) do
+ tag_names = Pleroma.Tag.normalize_tags(tags)
+ Pleroma.Tag.upsert_tags(tag_names)
+ update_tags(user, tag_names)
+ end
def untag(user_identifiers, tags) when is_list(user_identifiers) do
Repo.transaction(fn ->
@@ -2019,24 +2030,42 @@ defmodule Pleroma.User do
def untag(nickname, tags) when is_binary(nickname),
do: untag(get_by_nickname(nickname), tags)
- def untag(%User{} = user, tags),
- do: update_tags(user, (user.tags || []) -- normalize_tags(tags))
+ def untag(%User{} = user, remove_tags) do
+ tag_ids = Pleroma.Tag.get_tag_ids(remove_tags)
+ {:ok, user_id} = FlakeId.Ecto.Type.dump(user.id)
+
+ from(
+ ut in "users_tags",
+ where: ut.user_id == ^user_id,
+ where: ut.tag_id in ^tag_ids
+ )
+ |> Repo.delete_all()
+
+ preload_tags_and_set_cache(user)
+ end
defp update_tags(%User{} = user, new_tags) do
+ {:ok, user_id} = FlakeId.Ecto.Type.dump(user.id)
+
+ tags =
+ new_tags
+ |> Pleroma.Tag.normalize_tags()
+ |> Pleroma.Tag.get_tag_ids()
+ |> Enum.map(&%{user_id: user_id, tag_id: &1})
+
+ Repo.insert_all("users_tags", tags, on_conflict: :nothing)
+ preload_tags_and_set_cache(user)
+ end
+
+ defp preload_tags_and_set_cache(user) do
{:ok, updated_user} =
user
- |> change(%{tags: new_tags})
- |> update_and_set_cache()
+ |> Repo.preload([:tags], force: true)
+ |> set_cache()
updated_user
end
- defp normalize_tags(tags) do
- [tags]
- |> List.flatten()
- |> Enum.map(&String.downcase/1)
- end
-
defp local_nickname_regex do
if Config.get([:instance, :extended_nickname_format]) do
@extended_local_nickname_regex
diff --git a/lib/pleroma/user/query.ex b/lib/pleroma/user/query.ex
index fa46545da..36e03466a 100644
--- a/lib/pleroma/user/query.ex
+++ b/lib/pleroma/user/query.ex
@@ -109,7 +109,9 @@ defmodule Pleroma.User.Query do
end
defp compose_query({:tags, tags}, query) when is_list(tags) and length(tags) > 0 do
- where(query, [u], fragment("? && ?", u.tags, ^tags))
+ query
+ |> join(:inner, [u], t in assoc(u, :tags), as: :tags)
+ |> where([tags: t], t.name in ^tags)
end
defp compose_query({:is_admin, bool}, query) do
diff --git a/lib/pleroma/web/activity_pub/mrf/tag_policy.ex b/lib/pleroma/web/activity_pub/mrf/tag_policy.ex
index 316ea0368..dc445add2 100644
--- a/lib/pleroma/web/activity_pub/mrf/tag_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/tag_policy.ex
@@ -32,7 +32,11 @@ defmodule Pleroma.Web.ActivityPub.MRF.TagPolicy do
]
end
- defp get_tags(%User{tags: tags}) when is_list(tags), do: tags
+ defp get_tags(%User{} = user) do
+ {:ok, tags} = Pleroma.Repo.get_assoc(user, :tags)
+ Enum.map(tags, & &1.name)
+ end
+
defp get_tags(_), do: []
defp process_tag(
diff --git a/lib/pleroma/web/admin_api/views/account_view.ex b/lib/pleroma/web/admin_api/views/account_view.ex
index e053a9b67..ac8c952d9 100644
--- a/lib/pleroma/web/admin_api/views/account_view.ex
+++ b/lib/pleroma/web/admin_api/views/account_view.ex
@@ -66,6 +66,7 @@ defmodule Pleroma.Web.AdminAPI.AccountView do
avatar = User.avatar_url(user) |> MediaProxy.url()
display_name = Pleroma.HTML.strip_tags(user.name || user.nickname)
user = User.sanitize_html(user, FastSanitize.Sanitizer.StripTags)
+ {:ok, user_tags} = Pleroma.Repo.get_assoc(user, :tags)
%{
"id" => user.id,
@@ -76,7 +77,7 @@ defmodule Pleroma.Web.AdminAPI.AccountView do
"is_active" => user.is_active,
"local" => user.local,
"roles" => roles(user),
- "tags" => user.tags || [],
+ "tags" => Enum.map(user_tags, & &1.name),
"is_confirmed" => user.is_confirmed,
"is_approved" => user.is_approved,
"url" => user.uri || user.ap_id,
diff --git a/lib/pleroma/web/mastodon_api/views/account_view.ex b/lib/pleroma/web/mastodon_api/views/account_view.ex
index ac25aefdd..7e5a5d732 100644
--- a/lib/pleroma/web/mastodon_api/views/account_view.ex
+++ b/lib/pleroma/web/mastodon_api/views/account_view.ex
@@ -233,6 +233,8 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do
nil
end
+ {:ok, user_tags} = Pleroma.Repo.get_assoc(user, :tags)
+
%{
id: to_string(user.id),
username: username_from_nickname(user.nickname),
@@ -269,7 +271,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do
ap_id: user.ap_id,
also_known_as: user.also_known_as,
is_confirmed: user.is_confirmed,
- tags: user.tags,
+ tags: Enum.map(user_tags, & &1.name),
hide_followers_count: user.hide_followers_count,
hide_follows_count: user.hide_follows_count,
hide_followers: user.hide_followers,