field(:local, :boolean, default: true)
field(:follower_address, :string)
field(:search_distance, :float, virtual: true)
+ field(:tags, {:array, :string}, default: [])
field(:last_refreshed_at, :naive_datetime)
has_many(:notifications, Notification)
embeds_one(:info, Pleroma.User.Info)
CommonUtils.format_input(bio, mentions, tags, "text/plain") |> Formatter.emojify(emoji)
end
+
+ def tag(user_identifiers, tags), do: tag_or_untag(user_identifiers, tags, :tag)
+
+ def untag(user_identifiers, tags), do: tag_or_untag(user_identifiers, tags, :untag)
+
+ defp tag_or_untag(user_identifier, tags, action) when not is_list(user_identifier),
+ do: tag_or_untag([user_identifier], tags, action)
+
+ defp tag_or_untag([hd | _] = nicknames, tags, action) when is_binary(hd) do
+ users = Repo.all(from(u in User, where: u.nickname in ^nicknames))
+
+ if length(users) == length(nicknames) do
+ tag_or_untag(users, tags, action)
+ else
+ {:error, :not_found}
+ end
+ end
+
+ defp tag_or_untag([hd | _] = users, tags, action) when is_map(hd) do
+ tags =
+ [tags]
+ |> List.flatten()
+ |> Enum.map(&String.downcase(&1))
+
+ Repo.transaction(fn ->
+ for user <- users do
+ new_tags =
+ if action == :tag do
+ Enum.uniq(user.tags ++ tags)
+ else
+ user.tags -- tags
+ end
+
+ {:ok, updated_user} =
+ user
+ |> change(%{tags: new_tags})
+ |> Repo.update()
+
+ updated_user
+ end
+ end)
+ end
end
alias Pleroma.{User, Repo}
alias Pleroma.Web.ActivityPub.Relay
+ import Pleroma.Web.ControllerHelper, only: [json_response: 3]
+
require Logger
action_fallback(:errors)
|> json(new_user.nickname)
end
+ def tag_users(conn, %{"nicknames" => nicknames, "tags" => tags}) do
+ with {:ok, _} <- User.tag(nicknames, tags),
+ do: json_response(conn, :no_content, "")
+ end
+
+ def untag_users(conn, %{"nicknames" => nicknames, "tags" => tags}) do
+ with {:ok, _} <- User.untag(nicknames, tags),
+ do: json_response(conn, :no_content, "")
+ end
+
def right_add(conn, %{"permission_group" => permission_group, "nickname" => nickname})
when permission_group in ["moderator", "admin"] do
user = User.get_by_nickname(nickname)
--- /dev/null
+defmodule Pleroma.Web.ControllerHelper do
+ use Pleroma.Web, :controller
+
+ def json_response(conn, status, json) do
+ conn
+ |> put_status(status)
+ |> json(json)
+ end
+end
note: "",
privacy: user_info.default_scope,
sensitive: false
- }
+ },
+ # Note: Mastodon does not return this field:
+ tags: user.tags
}
end
pipe_through(:admin_api)
delete("/user", AdminAPIController, :user_delete)
post("/user", AdminAPIController, :user_create)
+ put("/users/tag", AdminAPIController, :tag_users)
+ put("/users/untag", AdminAPIController, :untag_users)
get("/permission_group/:nickname", AdminAPIController, :right_get)
get("/permission_group/:nickname/:permission_group", AdminAPIController, :right_get)
"locked" => user.info.locked,
"default_scope" => user.info.default_scope,
"no_rich_text" => user.info.no_rich_text,
- "fields" => fields
+ "fields" => fields,
+ # Note: twitter.com does not return this field:
+ "tags" => user.tags
}
if assigns[:token] do
--- /dev/null
+defmodule Pleroma.Repo.Migrations.AddTagsToUsers do
+ use Ecto.Migration
+
+ def change do
+ alter table(:users) do
+ add :tags, {:array, :string}
+ end
+
+ create index(:users, [:tags], using: :gin)
+ end
+end
end
end
+ describe "/api/pleroma/admin//users/tag" do
+ setup do
+ admin = insert(:user, info: %{is_admin: true})
+ user1 = insert(:user, %{tags: ["x"]})
+ user2 = insert(:user, %{tags: ["y"]})
+ user3 = insert(:user, %{tags: ["unchanged"]})
+
+ conn =
+ build_conn()
+ |> assign(:user, admin)
+ |> put_req_header("accept", "application/json")
+ |> put("/api/pleroma/admin/users/tag?nicknames[]=#{user1.nickname}&nicknames[]=#{user2.nickname}&tags[]=foo&tags[]=bar")
+
+ %{conn: conn, user1: user1, user2: user2, user3: user3}
+ end
+
+ test "it appends specified tags to users with specified nicknames", %{conn: conn, user1: user1, user2: user2} do
+ assert json_response(conn, :no_content)
+ assert Repo.get(User, user1.id).tags == ["x", "foo", "bar"]
+ assert Repo.get(User, user2.id).tags == ["y", "foo", "bar"]
+ end
+
+ test "it does not modify tags of not specified users", %{conn: conn, user3: user3} do
+ assert json_response(conn, :no_content)
+ assert Repo.get(User, user3.id).tags == ["unchanged"]
+ end
+ end
+
+ describe "/api/pleroma/admin//users/untag" do
+ setup do
+ admin = insert(:user, info: %{is_admin: true})
+ user1 = insert(:user, %{tags: ["x"]})
+ user2 = insert(:user, %{tags: ["y", "z"]})
+ user3 = insert(:user, %{tags: ["unchanged"]})
+
+ conn =
+ build_conn()
+ |> assign(:user, admin)
+ |> put_req_header("accept", "application/json")
+ |> put("/api/pleroma/admin/users/untag?nicknames[]=#{user1.nickname}&nicknames[]=#{user2.nickname}&tags[]=x&tags[]=z")
+
+ %{conn: conn, user1: user1, user2: user2, user3: user3}
+ end
+
+ test "it removes specified tags from users with specified nicknames", %{conn: conn, user1: user1, user2: user2} do
+ assert json_response(conn, :no_content)
+ assert Repo.get(User, user1.id).tags == []
+ assert Repo.get(User, user2.id).tags == ["y"]
+ end
+
+ test "it does not modify tags of not specified users", %{conn: conn, user3: user3} do
+ assert json_response(conn, :no_content)
+ assert Repo.get(User, user3.id).tags == ["unchanged"]
+ end
+ end
+
describe "/api/pleroma/admin/permission_group" do
test "GET is giving user_info" do
admin = insert(:user, info: %{is_admin: true})