- Mastodon API: Add the `recipients` parameter to `GET /api/v1/conversations`
- Configuration: `feed` option for user atom feed.
- Pleroma API: Add Emoji reactions
+- Admin API: `PATCH /api/pleroma/users/confirm_email` to confirm email for multiple users, `PATCH /api/pleroma/users/resend_confirmation_email` to resend confirmation email for multiple users
</details>
### Fixed
- Authentication: required
- Params: None
- Response: JSON, "ok" and 200 status
+
+## `PATCH /api/pleroma/admin/users/confirm_email`
+
+### Confirm users' emails
+
+- Params:
+ - `nicknames`
+- Response: Array of user nicknames
+
+## `PATCH /api/pleroma/admin/users/resend_confirmation_email`
+
+### Resend confirmation email
+
+- Params:
+ - `nicknames`
+- Response: Array of user nicknames
"subject" => subjects
}
}) do
- "@#{actor_nickname} force password reset for users: #{users_to_nicknames_string(subjects)}"
+ "@#{actor_nickname} forced password reset for users: #{users_to_nicknames_string(subjects)}"
+ end
+
+ @spec get_log_entry_message(ModerationLog) :: String.t()
+ def get_log_entry_message(%ModerationLog{
+ data: %{
+ "actor" => %{"nickname" => actor_nickname},
+ "action" => "confirm_email",
+ "subject" => subjects
+ }
+ }) do
+ "@#{actor_nickname} confirmed email for users: #{users_to_nicknames_string(subjects)}"
+ end
+
+ @spec get_log_entry_message(ModerationLog) :: String.t()
+ def get_log_entry_message(%ModerationLog{
+ data: %{
+ "actor" => %{"nickname" => actor_nickname},
+ "action" => "resend_confirmation_email",
+ "subject" => subjects
+ }
+ }) do
+ "@#{actor_nickname} re-sent confirmation email for users: #{
+ users_to_nicknames_string(subjects)
+ }"
end
defp nicknames_to_string(nicknames) do
end
end
+ def try_send_confirmation_email(users) do
+ Enum.map(users, &try_send_confirmation_email/1)
+ end
+
def needs_update?(%User{local: true}), do: false
def needs_update?(%User{local: false, last_refreshed_at: nil}), do: true
|> update_and_set_cache()
end
+ @spec toggle_confirmation([User.t()]) :: [{:ok, User.t()} | {:error, Changeset.t()}]
+ def toggle_confirmation(users) do
+ Enum.map(users, &toggle_confirmation/1)
+ end
+
def get_mascot(%{mascot: %{} = mascot}) when not is_nil(mascot) do
mascot
end
}
with {:ok, users, count} <- Search.user(Map.merge(search_params, filters)),
- {:ok, users, count} <- filter_relay_user(users, count),
+ {:ok, users, count} <- filter_service_users(users, count),
do:
conn
|> json(
)
end
- defp filter_relay_user(users, count) do
- filtered_users = Enum.reject(users, &relay_user?/1)
- count = if Enum.any?(users, &relay_user?/1), do: length(filtered_users), else: count
+ defp filter_service_users(users, count) do
+ filtered_users = Enum.reject(users, &service_user?/1)
+ count = if Enum.any?(users, &service_user?/1), do: length(filtered_users), else: count
{:ok, filtered_users, count}
end
- defp relay_user?(user) do
- user.ap_id == Relay.relay_ap_id()
+ defp service_user?(user) do
+ String.match?(user.ap_id, ~r/.*\/relay$/) or
+ String.match?(user.ap_id, ~r/.*\/internal\/fetch$/)
end
@filters ~w(local external active deactivated is_admin is_moderator)
conn |> json("ok")
end
+ def confirm_email(%{assigns: %{user: admin}} = conn, %{"nicknames" => nicknames}) do
+ users = nicknames |> Enum.map(&User.get_cached_by_nickname/1)
+
+ User.toggle_confirmation(users)
+
+ ModerationLog.insert_log(%{
+ actor: admin,
+ subject: users,
+ action: "confirm_email"
+ })
+
+ conn |> json("")
+ end
+
+ def resend_confirmation_email(%{assigns: %{user: admin}} = conn, %{"nicknames" => nicknames}) do
+ users = nicknames |> Enum.map(&User.get_cached_by_nickname/1)
+
+ User.try_send_confirmation_email(users)
+
+ ModerationLog.insert_log(%{
+ actor: admin,
+ subject: users,
+ action: "resend_confirmation_email"
+ })
+
+ conn |> json("")
+ end
+
def errors(conn, {:error, :not_found}) do
conn
|> put_status(:not_found)
"deactivated" => user.deactivated,
"local" => user.local,
"roles" => User.roles(user),
- "tags" => user.tags || []
+ "tags" => user.tags || [],
+ "confirmation_pending" => user.confirmation_pending
}
end
get("/users/:nickname", AdminAPIController, :user_show)
get("/users/:nickname/statuses", AdminAPIController, :list_user_statuses)
+ patch("/users/confirm_email", AdminAPIController, :confirm_email)
+ patch("/users/resend_confirmation_email", AdminAPIController, :resend_confirmation_email)
+
get("/reports", AdminAPIController, :list_reports)
get("/grouped_reports", AdminAPIController, :list_grouped_reports)
get("/reports/:id", AdminAPIController, :report_show)
"@#{admin.nickname} unfollowed relay: http://mastodon.example.org/users/admin"
end
end
+
+ describe "PATCH /confirm_email" do
+ setup %{conn: conn} do
+ admin = insert(:user, is_admin: true)
+
+ %{conn: assign(conn, :user, admin), admin: admin}
+ end
+
+ test "it confirms emails of two users", %{admin: admin} do
+ [first_user, second_user] = insert_pair(:user, confirmation_pending: true)
+
+ assert first_user.confirmation_pending == true
+ assert second_user.confirmation_pending == true
+
+ build_conn()
+ |> assign(:user, admin)
+ |> patch("/api/pleroma/admin/users/confirm_email", %{
+ nicknames: [
+ first_user.nickname,
+ second_user.nickname
+ ]
+ })
+
+ assert first_user.confirmation_pending == true
+ assert second_user.confirmation_pending == true
+
+ log_entry = Repo.one(ModerationLog)
+
+ assert ModerationLog.get_log_entry_message(log_entry) ==
+ "@#{admin.nickname} confirmed email for users: @#{first_user.nickname}, @#{
+ second_user.nickname
+ }"
+ end
+ end
+
+ describe "PATCH /resend_confirmation_email" do
+ setup %{conn: conn} do
+ admin = insert(:user, is_admin: true)
+
+ %{conn: assign(conn, :user, admin), admin: admin}
+ end
+
+ test "it resend emails for two users", %{admin: admin} do
+ [first_user, second_user] = insert_pair(:user, confirmation_pending: true)
+
+ build_conn()
+ |> assign(:user, admin)
+ |> patch("/api/pleroma/admin/users/resend_confirmation_email", %{
+ nicknames: [
+ first_user.nickname,
+ second_user.nickname
+ ]
+ })
+
+ log_entry = Repo.one(ModerationLog)
+
+ assert ModerationLog.get_log_entry_message(log_entry) ==
+ "@#{admin.nickname} re-sent confirmation email for users: @#{first_user.nickname}, @#{
+ second_user.nickname
+ }"
+ end
+ end
end
# Needed for testing