Merge branch 'develop' into issue/1276-2
[akkoma] / lib / pleroma / web / mastodon_api / controllers / account_controller.ex
index 1ecce292871f5ddebd458f5d3909a255d1ff614d..61b0e2f633c939599ca1d0ee56cb49e7eb523114 100644 (file)
@@ -14,6 +14,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
       skip_relationships?: 1
     ]
 
+  alias Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug
   alias Pleroma.Plugs.OAuthScopesPlug
   alias Pleroma.Plugs.RateLimiter
   alias Pleroma.User
@@ -21,20 +22,33 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
   alias Pleroma.Web.CommonAPI
   alias Pleroma.Web.MastodonAPI.ListView
   alias Pleroma.Web.MastodonAPI.MastodonAPI
+  alias Pleroma.Web.MastodonAPI.MastodonAPIController
   alias Pleroma.Web.MastodonAPI.StatusView
   alias Pleroma.Web.OAuth.Token
   alias Pleroma.Web.TwitterAPI.TwitterAPI
 
+  plug(OpenApiSpex.Plug.CastAndValidate, render_error: Pleroma.Web.ApiSpec.RenderError)
+
+  plug(:skip_plug, [OAuthScopesPlug, EnsurePublicOrAuthenticatedPlug] when action == :create)
+
+  plug(:skip_plug, EnsurePublicOrAuthenticatedPlug when action in [:show, :statuses])
+
   plug(
     OAuthScopesPlug,
     %{fallback: :proceed_unauthenticated, scopes: ["read:accounts"]}
-    when action == :show
+    when action in [:show, :followers, :following]
+  )
+
+  plug(
+    OAuthScopesPlug,
+    %{fallback: :proceed_unauthenticated, scopes: ["read:statuses"]}
+    when action == :statuses
   )
 
   plug(
     OAuthScopesPlug,
     %{scopes: ["read:accounts"]}
-    when action in [:endorsements, :verify_credentials, :followers, :following]
+    when action in [:verify_credentials, :endorsements, :identity_proofs]
   )
 
   plug(OAuthScopesPlug, %{scopes: ["write:accounts"]} when action == :update_credentials)
@@ -53,21 +67,15 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
 
   plug(OAuthScopesPlug, %{scopes: ["read:follows"]} when action == :relationships)
 
-  # Note: :follows (POST /api/v1/follows) is the same as :follow, consider removing :follows
   plug(
     OAuthScopesPlug,
-    %{scopes: ["follow", "write:follows"]} when action in [:follows, :follow, :unfollow]
+    %{scopes: ["follow", "write:follows"]} when action in [:follow_by_uri, :follow, :unfollow]
   )
 
   plug(OAuthScopesPlug, %{scopes: ["follow", "read:mutes"]} when action == :mutes)
 
   plug(OAuthScopesPlug, %{scopes: ["follow", "write:mutes"]} when action in [:mute, :unmute])
 
-  plug(
-    Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug
-    when action not in [:create, :show, :statuses]
-  )
-
   @relationship_actions [:follow, :unfollow]
   @needs_account ~W(followers following lists follow unfollow mute unmute block unblock)a
 
@@ -80,48 +88,14 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
   plug(RateLimiter, [name: :app_account_creation] when action == :create)
   plug(:assign_account_by_id when action in @needs_account)
 
-  plug(
-    OpenApiSpex.Plug.CastAndValidate,
-    [render_error: Pleroma.Web.ApiSpec.RenderError]
-    when action in [
-           :create,
-           :verify_credentials,
-           :update_credentials,
-           :relationships,
-           :show,
-           :statuses,
-           :followers,
-           :following,
-           :lists,
-           :follow,
-           :unfollow
-         ]
-  )
-
   action_fallback(Pleroma.Web.MastodonAPI.FallbackController)
 
   defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.AccountOperation
 
   @doc "POST /api/v1/accounts"
   def create(%{assigns: %{app: app}, body_params: params} = conn, _params) do
-    params =
-      params
-      |> Map.take([
-        :email,
-        :bio,
-        :captcha_solution,
-        :captcha_token,
-        :captcha_answer_data,
-        :token,
-        :password,
-        :fullname
-      ])
-      |> Map.put(:nickname, params.username)
-      |> Map.put(:fullname, params.fullname || params.username)
-      |> Map.put(:bio, params.bio || "")
-      |> Map.put(:confirm, params.password)
-
     with :ok <- validate_email_param(params),
+         :ok <- TwitterAPI.validate_captcha(app, params),
          {:ok, user} <- TwitterAPI.register_user(params, need_confirmation: true),
          {:ok, token} <- Token.create_token(app, user, %{scopes: app.scopes}) do
       json(conn, %{
@@ -131,7 +105,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
         created_at: Token.Utils.format_created_at(token)
       })
     else
-      {:error, errors} -> json_response(conn, :bad_request, errors)
+      {:error, error} -> json_response(conn, :bad_request, %{error: error})
     end
   end
 
@@ -143,11 +117,11 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
     render_error(conn, :forbidden, "Invalid credentials")
   end
 
-  defp validate_email_param(%{:email => email}) when not is_nil(email), do: :ok
+  defp validate_email_param(%{email: email}) when not is_nil(email), do: :ok
 
   defp validate_email_param(_) do
     case Pleroma.Config.get([:instance, :account_activation_required]) do
-      true -> {:error, %{"error" => "Missing parameters"}}
+      true -> {:error, dgettext("errors", "Missing parameter: %{name}", name: "email")}
       _ -> :ok
     end
   end
@@ -170,7 +144,6 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
 
     params =
       params
-      |> Map.from_struct()
       |> Enum.filter(fn {_, value} -> not is_nil(value) end)
       |> Enum.into(%{})
 
@@ -209,8 +182,6 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
     changeset = User.update_changeset(user, user_params)
 
     with {:ok, user} <- User.update_and_set_cache(changeset) do
-      if original_user != user, do: CommonAPI.update(user)
-
       render(conn, "show.json", user: user, for: user, with_pleroma_settings: true)
     else
       _e -> render_error(conn, :forbidden, "Invalid request")
@@ -231,11 +202,8 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
       Enum.map(fields, fn {_, v} -> v end)
     else
       Enum.map(fields, fn
-        %Pleroma.Web.ApiSpec.Schemas.AccountAttributeField{} = field ->
-          %{"name" => field.name, "value" => field.value}
-
-        field ->
-          field
+        %{} = field -> %{"name" => field.name, "value" => field.value}
+        field -> field
       end)
     end
   end
@@ -336,7 +304,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
 
   @doc "POST /api/v1/accounts/:id/follow"
   def follow(%{assigns: %{user: %{id: id}, account: %{id: id}}}, _params) do
-    {:error, :not_found}
+    {:error, "Can not follow yourself"}
   end
 
   def follow(%{assigns: %{user: follower, account: followed}} = conn, params) do
@@ -349,7 +317,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
 
   @doc "POST /api/v1/accounts/:id/unfollow"
   def unfollow(%{assigns: %{user: %{id: id}, account: %{id: id}}}, _params) do
-    {:error, :not_found}
+    {:error, "Can not unfollow yourself"}
   end
 
   def unfollow(%{assigns: %{user: follower, account: followed}} = conn, _params) do
@@ -359,10 +327,8 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
   end
 
   @doc "POST /api/v1/accounts/:id/mute"
-  def mute(%{assigns: %{user: muter, account: muted}} = conn, params) do
-    notifications? = params |> Map.get("notifications", true) |> truthy_param?()
-
-    with {:ok, _user_relationships} <- User.mute(muter, muted, notifications?) do
+  def mute(%{assigns: %{user: muter, account: muted}, body_params: params} = conn, _params) do
+    with {:ok, _user_relationships} <- User.mute(muter, muted, params.notifications) do
       render(conn, "relationship.json", user: muter, target: muted)
     else
       {:error, message} -> json_response(conn, :forbidden, %{error: message})
@@ -399,14 +365,15 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
   end
 
   @doc "POST /api/v1/follows"
-  def follows(%{assigns: %{user: follower}} = conn, %{"uri" => uri}) do
-    with {_, %User{} = followed} <- {:followed, User.get_cached_by_nickname(uri)},
-         {_, true} <- {:followed, follower.id != followed.id},
-         {:ok, follower, followed, _} <- CommonAPI.follow(follower, followed) do
-      render(conn, "show.json", user: followed, for: follower)
-    else
-      {:followed, _} -> {:error, :not_found}
-      {:error, message} -> json_response(conn, :forbidden, %{error: message})
+  def follow_by_uri(%{body_params: %{uri: uri}} = conn, _) do
+    case User.get_cached_by_nickname(uri) do
+      %User{} = user ->
+        conn
+        |> assign(:account, user)
+        |> follow(%{})
+
+      nil ->
+        {:error, :not_found}
     end
   end
 
@@ -423,6 +390,8 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
   end
 
   @doc "GET /api/v1/endorsements"
-  def endorsements(conn, params),
-    do: Pleroma.Web.MastodonAPI.MastodonAPIController.empty_array(conn, params)
+  def endorsements(conn, params), do: MastodonAPIController.empty_array(conn, params)
+
+  @doc "GET /api/v1/identity_proofs"
+  def identity_proofs(conn, params), do: MastodonAPIController.empty_array(conn, params)
 end