+ 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
+ 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, %{
+ token_type: "Bearer",
+ access_token: token.token,
+ scope: app.scopes,
+ created_at: Token.Utils.format_created_at(token)
+ })
+ else
+ {:error, error} -> json_response(conn, :bad_request, %{error: error})
+ end
+ end
+
+ def create(%{assigns: %{app: _app}} = conn, _) do
+ render_error(conn, :bad_request, "Missing parameters")
+ end
+
+ def create(conn, _) 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(_) do
+ case Pleroma.Config.get([:instance, :account_activation_required]) do
+ true -> {:error, dgettext("errors", "Missing parameter: %{name}", name: "email")}
+ _ -> :ok
+ end
+ end
+
+ @doc "GET /api/v1/accounts/verify_credentials"
+ def verify_credentials(%{assigns: %{user: user}} = conn, _) do
+ chat_token = Phoenix.Token.sign(conn, "user socket", user.id)
+
+ render(conn, "show.json",
+ user: user,
+ for: user,
+ with_pleroma_settings: true,
+ with_chat_token: chat_token
+ )
+ end
+
+ @doc "PATCH /api/v1/accounts/update_credentials"
+ def update_credentials(%{assigns: %{user: user}, body_params: params} = conn, _params) do
+ params =
+ params
+ |> Enum.filter(fn {_, value} -> not is_nil(value) end)
+ |> Enum.into(%{})
+
+ user_params =
+ [
+ :no_rich_text,
+ :locked,
+ :hide_followers_count,
+ :hide_follows_count,
+ :hide_followers,
+ :hide_follows,
+ :hide_favorites,
+ :show_role,
+ :skip_thread_containment,
+ :allow_following_move,
+ :discoverable
+ ]
+ |> Enum.reduce(%{}, fn key, acc ->
+ Maps.put_if_present(acc, key, params[key], &{:ok, truthy_param?(&1)})
+ end)
+ |> Maps.put_if_present(:name, params[:display_name])
+ |> Maps.put_if_present(:bio, params[:note])
+ |> Maps.put_if_present(:raw_bio, params[:note])
+ |> Maps.put_if_present(:avatar, params[:avatar])
+ |> Maps.put_if_present(:banner, params[:header])
+ |> Maps.put_if_present(:background, params[:pleroma_background_image])
+ |> Maps.put_if_present(
+ :raw_fields,
+ params[:fields_attributes],
+ &{:ok, normalize_fields_attributes(&1)}
+ )
+ |> Maps.put_if_present(:pleroma_settings_store, params[:pleroma_settings_store])
+ |> Maps.put_if_present(:default_scope, params[:default_scope])
+ |> Maps.put_if_present(:default_scope, params["source"]["privacy"])
+ |> Maps.put_if_present(:actor_type, params[:actor_type])
+
+ changeset = User.update_changeset(user, user_params)
+
+ with {:ok, user} <- User.update_and_set_cache(changeset) do
+ user
+ |> build_update_activity_params()
+ |> ActivityPub.update()
+
+ render(conn, "show.json", user: user, for: user, with_pleroma_settings: true)
+ else
+ _e -> render_error(conn, :forbidden, "Invalid request")
+ end
+ end
+
+ # Hotfix, handling will be redone with the pipeline
+ defp build_update_activity_params(user) do
+ object =
+ Pleroma.Web.ActivityPub.UserView.render("user.json", user: user)
+ |> Map.delete("@context")
+
+ %{
+ local: true,
+ to: [user.follower_address],
+ cc: [],
+ object: object,
+ actor: user.ap_id
+ }
+ end
+
+ defp normalize_fields_attributes(fields) do
+ if Enum.all?(fields, &is_tuple/1) do
+ Enum.map(fields, fn {_, v} -> v end)
+ else
+ Enum.map(fields, fn
+ %{} = field -> %{"name" => field.name, "value" => field.value}
+ field -> field
+ end)
+ end
+ end
+
+ @doc "GET /api/v1/accounts/relationships"
+ def relationships(%{assigns: %{user: user}} = conn, %{id: id}) do
+ targets = User.get_all_by_ids(List.wrap(id))
+
+ render(conn, "relationships.json", user: user, targets: targets)
+ end
+
+ # Instead of returning a 400 when no "id" params is present, Mastodon returns an empty array.
+ def relationships(%{assigns: %{user: _user}} = conn, _), do: json(conn, [])
+