Merge remote-tracking branch 'upstream/develop' into admin-create-users
[akkoma] / lib / pleroma / web / admin_api / admin_api_controller.ex
index 70a5b5c5d7dbf4cfaf3821f9978c0453c0345175..479fd5829087aee42db457af8195e066135d93ac 100644 (file)
@@ -4,11 +4,16 @@
 
 defmodule Pleroma.Web.AdminAPI.AdminAPIController do
   use Pleroma.Web, :controller
+  alias Pleroma.Activity
   alias Pleroma.User
   alias Pleroma.UserInviteToken
+  alias Pleroma.Web.ActivityPub.ActivityPub
   alias Pleroma.Web.ActivityPub.Relay
   alias Pleroma.Web.AdminAPI.AccountView
+  alias Pleroma.Web.AdminAPI.ReportView
   alias Pleroma.Web.AdminAPI.Search
+  alias Pleroma.Web.CommonAPI
+  alias Pleroma.Web.MastodonAPI.StatusView
 
   import Pleroma.Web.ControllerHelper, only: [json_response: 3]
 
@@ -19,7 +24,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
   action_fallback(:errors)
 
   def user_delete(conn, %{"nickname" => nickname}) do
-    User.get_by_nickname(nickname)
+    User.get_cached_by_nickname(nickname)
     |> User.delete()
 
     conn
@@ -27,8 +32,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
   end
 
   def user_follow(conn, %{"follower" => follower_nick, "followed" => followed_nick}) do
-    with %User{} = follower <- User.get_by_nickname(follower_nick),
-         %User{} = followed <- User.get_by_nickname(followed_nick) do
+    with %User{} = follower <- User.get_cached_by_nickname(follower_nick),
+         %User{} = followed <- User.get_cached_by_nickname(followed_nick) do
       User.follow(follower, followed)
     end
 
@@ -37,8 +42,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
   end
 
   def user_unfollow(conn, %{"follower" => follower_nick, "followed" => followed_nick}) do
-    with %User{} = follower <- User.get_by_nickname(follower_nick),
-         %User{} = followed <- User.get_by_nickname(followed_nick) do
+    with %User{} = follower <- User.get_cached_by_nickname(follower_nick),
+         %User{} = followed <- User.get_cached_by_nickname(followed_nick) do
       User.unfollow(follower, followed)
     end
 
@@ -46,28 +51,56 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
     |> json("ok")
   end
 
-  def user_create(
-        conn,
-        %{"nickname" => nickname, "email" => email, "password" => password}
-      ) do
-    user_data = %{
-      nickname: nickname,
-      name: nickname,
-      email: email,
-      password: password,
-      password_confirmation: password,
-      bio: "."
-    }
+  def users_create(conn, %{"users" => users}) do
+    changesets =
+      Enum.map(users, fn %{"nickname" => nickname, "email" => email, "password" => password} ->
+        user_data = %{
+          nickname: nickname,
+          name: nickname,
+          email: email,
+          password: password,
+          password_confirmation: password,
+          bio: "."
+        }
 
-    changeset = User.register_changeset(%User{}, user_data, confirmed: true)
-    {:ok, user} = User.register(changeset)
+        User.register_changeset(%User{}, user_data, need_confirmation: false)
+      end)
+      |> Enum.reduce(Ecto.Multi.new(), fn changeset, multi ->
+        Ecto.Multi.insert(multi, Ecto.UUID.generate(), changeset)
+      end)
+
+    case Pleroma.Repo.transaction(changesets) do
+      {:ok, users} ->
+        res =
+          users
+          |> Map.values()
+          |> Enum.map(fn user ->
+            {:ok, user} = User.post_register_action(user)
+            user
+          end)
+          |> Enum.map(&AccountView.render("created.json", %{user: &1}))
 
-    conn
-    |> json(user.nickname)
+        conn
+        |> json(res)
+
+      {:error, id, changeset, _} ->
+        res =
+          Enum.map(changesets.operations, fn
+            {current_id, {:changeset, _current_changeset, _}} when current_id == id ->
+              AccountView.render("create-error.json", %{changeset: changeset})
+
+            {_, {:changeset, current_changeset, _}} ->
+              AccountView.render("create-error.json", %{changeset: current_changeset})
+          end)
+
+        conn
+        |> put_status(:conflict)
+        |> json(res)
+    end
   end
 
   def user_show(conn, %{"nickname" => nickname}) do
-    with %User{} = user <- User.get_by_nickname(nickname) do
+    with %User{} = user <- User.get_cached_by_nickname(nickname) do
       conn
       |> json(AccountView.render("show.json", %{user: user}))
     else
@@ -76,7 +109,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
   end
 
   def user_toggle_activation(conn, %{"nickname" => nickname}) do
-    user = User.get_by_nickname(nickname)
+    user = User.get_cached_by_nickname(nickname)
 
     {:ok, updated_user} = User.deactivate(user, !user.info.deactivated)
 
@@ -101,7 +134,10 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
     search_params = %{
       query: params["query"],
       page: page,
-      page_size: page_size
+      page_size: page_size,
+      tags: params["tags"],
+      name: params["name"],
+      email: params["email"]
     }
 
     with {:ok, users, count} <- Search.user(Map.merge(search_params, filters)),
@@ -116,11 +152,11 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
            )
   end
 
-  @filters ~w(local external active deactivated)
+  @filters ~w(local external active deactivated is_admin is_moderator)
 
+  @spec maybe_parse_filters(String.t()) :: %{required(String.t()) => true} | %{}
   defp maybe_parse_filters(filters) when is_nil(filters) or filters == "", do: %{}
 
-  @spec maybe_parse_filters(String.t()) :: %{required(String.t()) => true} | %{}
   defp maybe_parse_filters(filters) do
     filters
     |> String.split(",")
@@ -131,7 +167,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
 
   def right_add(conn, %{"permission_group" => permission_group, "nickname" => nickname})
       when permission_group in ["moderator", "admin"] do
-    user = User.get_by_nickname(nickname)
+    user = User.get_cached_by_nickname(nickname)
 
     info =
       %{}
@@ -156,7 +192,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
   end
 
   def right_get(conn, %{"nickname" => nickname}) do
-    user = User.get_by_nickname(nickname)
+    user = User.get_cached_by_nickname(nickname)
 
     conn
     |> json(%{
@@ -178,7 +214,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
       |> put_status(403)
       |> json(%{error: "You can't revoke your own admin status."})
     else
-      user = User.get_by_nickname(nickname)
+      user = User.get_cached_by_nickname(nickname)
 
       info =
         %{}
@@ -204,7 +240,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
 
   def set_activation_status(conn, %{"nickname" => nickname, "status" => status}) do
     with {:ok, status} <- Ecto.Type.cast(:boolean, status),
-         %User{} = user <- User.get_by_nickname(nickname),
+         %User{} = user <- User.get_cached_by_nickname(nickname),
          {:ok, _} <- User.deactivate(user, !status),
          do: json_response(conn, :no_content, "")
   end
@@ -238,8 +274,13 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
              !Pleroma.Config.get([:instance, :registrations_open]),
          {:ok, invite_token} <- UserInviteToken.create_invite(),
          email <-
-           Pleroma.UserEmail.user_invitation_email(user, invite_token, email, params["name"]),
-         {:ok, _} <- Pleroma.Mailer.deliver(email) do
+           Pleroma.Emails.UserEmail.user_invitation_email(
+             user,
+             invite_token,
+             email,
+             params["name"]
+           ),
+         {:ok, _} <- Pleroma.Emails.Mailer.deliver(email) do
       json_response(conn, :no_content, "")
     end
   end
@@ -272,19 +313,95 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
 
   @doc "Get a password reset token (base64 string) for given nickname"
   def get_password_reset(conn, %{"nickname" => nickname}) do
-    (%User{local: true} = user) = User.get_by_nickname(nickname)
+    (%User{local: true} = user) = User.get_cached_by_nickname(nickname)
     {:ok, token} = Pleroma.PasswordResetToken.create_token(user)
 
     conn
     |> json(token.token)
   end
 
+  def list_reports(conn, params) do
+    params =
+      params
+      |> Map.put("type", "Flag")
+      |> Map.put("skip_preload", true)
+
+    reports =
+      []
+      |> ActivityPub.fetch_activities(params)
+      |> Enum.reverse()
+
+    conn
+    |> put_view(ReportView)
+    |> render("index.json", %{reports: reports})
+  end
+
+  def report_show(conn, %{"id" => id}) do
+    with %Activity{} = report <- Activity.get_by_id(id) do
+      conn
+      |> put_view(ReportView)
+      |> render("show.json", %{report: report})
+    else
+      _ -> {:error, :not_found}
+    end
+  end
+
+  def report_update_state(conn, %{"id" => id, "state" => state}) do
+    with {:ok, report} <- CommonAPI.update_report_state(id, state) do
+      conn
+      |> put_view(ReportView)
+      |> render("show.json", %{report: report})
+    end
+  end
+
+  def report_respond(%{assigns: %{user: user}} = conn, %{"id" => id} = params) do
+    with false <- is_nil(params["status"]),
+         %Activity{} <- Activity.get_by_id(id) do
+      params =
+        params
+        |> Map.put("in_reply_to_status_id", id)
+        |> Map.put("visibility", "direct")
+
+      {:ok, activity} = CommonAPI.post(user, params)
+
+      conn
+      |> put_view(StatusView)
+      |> render("status.json", %{activity: activity})
+    else
+      true ->
+        {:param_cast, nil}
+
+      nil ->
+        {:error, :not_found}
+    end
+  end
+
+  def status_update(conn, %{"id" => id} = params) do
+    with {:ok, activity} <- CommonAPI.update_activity_scope(id, params) do
+      conn
+      |> put_view(StatusView)
+      |> render("status.json", %{activity: activity})
+    end
+  end
+
+  def status_delete(%{assigns: %{user: user}} = conn, %{"id" => id}) do
+    with {:ok, %Activity{}} <- CommonAPI.delete(id, user) do
+      json(conn, %{})
+    end
+  end
+
   def errors(conn, {:error, :not_found}) do
     conn
     |> put_status(404)
     |> json("Not found")
   end
 
+  def errors(conn, {:error, reason}) do
+    conn
+    |> put_status(400)
+    |> json(reason)
+  end
+
   def errors(conn, {:param_cast, _}) do
     conn
     |> put_status(400)