diff --git a/lib/pleroma/tag.ex b/lib/pleroma/tag.ex new file mode 100644 index 000000000..16d0b0eda --- /dev/null +++ b/lib/pleroma/tag.ex @@ -0,0 +1,37 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Tag do + use Ecto.Schema + + import Ecto.Query + + alias Pleroma.Repo + alias Pleroma.Web.ActivityPub.MRF + + @type t :: %__MODULE__{} + + schema "tags" do + field(:name, :string) + + timestamps() + end + + @spec upsert(String.t()) :: {:ok, t()} | {:error, Ecto.Changeset.t()} + def upsert(name) do + %__MODULE__{} + |> Ecto.Changeset.change(name: name) + |> Ecto.Changeset.unique_constraint(:name) + |> Repo.insert(on_conflict: :nothing, conflict_target: :name) + end + + @spec list_tags() :: list(String.t()) + def list_tags do + from(u in __MODULE__, select: u.name) + |> Repo.all() + |> Kernel.++(MRF.TagPolicy.policy_tags()) + |> Enum.uniq() + |> Enum.sort() + end +end diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index 5cbe5bb75..c1aa0f716 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -1259,15 +1259,6 @@ defmodule Pleroma.User do |> Repo.all() end - @spec list_tags() :: list(String.t()) - def list_tags do - from( - u in __MODULE__, - select: type(fragment("DISTINCT unnest(?)", u.tags), :string) - ) - |> Repo.all() - end - def increase_note_count(%User{} = user) do User |> where(id: ^user.id) diff --git a/lib/pleroma/web/admin_api/controllers/tag_controller.ex b/lib/pleroma/web/admin_api/controllers/tag_controller.ex index 9419bf31e..60b5d2ab9 100644 --- a/lib/pleroma/web/admin_api/controllers/tag_controller.ex +++ b/lib/pleroma/web/admin_api/controllers/tag_controller.ex @@ -25,11 +25,7 @@ defmodule Pleroma.Web.AdminAPI.TagController do action_fallback(AdminAPI.FallbackController) def list(%{assigns: %{user: _admin}} = conn, _) do - tags = - Pleroma.User.list_tags() - |> Kernel.++(Pleroma.Web.ActivityPub.MRF.TagPolicy.policy_tags()) - |> Enum.uniq() - |> Enum.sort() + tags = Pleroma.Tag.list_tags() json(conn, tags) end diff --git a/priv/repo/migrations/20201012093959_create_tags.exs b/priv/repo/migrations/20201012093959_create_tags.exs new file mode 100644 index 000000000..54bf8a2ce --- /dev/null +++ b/priv/repo/migrations/20201012093959_create_tags.exs @@ -0,0 +1,27 @@ +defmodule Pleroma.Repo.Migrations.CreateTags do + use Ecto.Migration + + def up do + create_if_not_exists table(:tags) do + add(:name, :string, null: false) + timestamps() + end + + create_if_not_exists(unique_index(:tags, :name)) + flush() + + execute(collect_user_tags_query()) + end + + def down do + drop_if_exists(table(:tags)) + end + + defp collect_user_tags_query do + """ + INSERT INTO tags(name, inserted_at, updated_at) + SELECT DISTINCT unnest(tags), now(), now() from users + ON CONFLICT DO NOTHING + """ + end +end diff --git a/test/support/factory.ex b/test/support/factory.ex index af4fff45b..88a4fcb4d 100644 --- a/test/support/factory.ex +++ b/test/support/factory.ex @@ -490,4 +490,8 @@ defmodule Pleroma.Factory do context: ["home"] } end + + def tag_factory do + %Pleroma.Tag{name: "verify"} + end end diff --git a/test/web/admin_api/controllers/tag_controller_test.exs b/test/web/admin_api/controllers/tag_controller_test.exs index 671bda53a..88eeafac0 100644 --- a/test/web/admin_api/controllers/tag_controller_test.exs +++ b/test/web/admin_api/controllers/tag_controller_test.exs @@ -32,9 +32,9 @@ defmodule Pleroma.Web.AdminAPI.TagControllerTest do describe "GET /api/pleroma/admin/users/tag" do test "it returns user tags and mrf policy tags", %{conn: conn} do - insert(:user, %{tags: ["x"]}) - insert(:user, %{tags: ["y"]}) - insert(:user, %{tags: ["unchanged"]}) + insert(:tag, name: "x") + insert(:tag, name: "y") + insert(:tag, name: "unchanged") response = conn