X-Git-Url: https://git.squeep.com/?a=blobdiff_plain;f=lib%2Fpleroma%2Fweb%2Fmastodon_api%2Fmastodon_api_controller.ex;h=8a7b75025700e9fc64913abba3bd800e581e7faa;hb=f4c001062e51c207bf84f56473ddf6120e3b50fb;hp=7cdba4cc03c2ed6a7c054568729e588074e25e44;hpb=2286f62a36a0f5d738892a9283a696b8a45b45a6;p=akkoma diff --git a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex index 7cdba4cc0..8a7b75025 100644 --- a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex +++ b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex @@ -15,6 +15,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do alias Pleroma.Notification alias Pleroma.Object alias Pleroma.Pagination + alias Pleroma.Plugs.RateLimiter alias Pleroma.Repo alias Pleroma.ScheduledActivity alias Pleroma.Stats @@ -46,8 +47,24 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do require Logger - plug(Pleroma.Plugs.RateLimiter, :app_account_creation when action == :account_register) - plug(Pleroma.Plugs.RateLimiter, :search when action in [:search, :search2, :account_search]) + @rate_limited_status_actions ~w(reblog_status unreblog_status fav_status unfav_status + post_status delete_status)a + + plug( + RateLimiter, + {:status_id_action, bucket_name: "status_id_action:reblog_unreblog", params: ["id"]} + when action in ~w(reblog_status unreblog_status)a + ) + + plug( + RateLimiter, + {:status_id_action, bucket_name: "status_id_action:fav_unfav", params: ["id"]} + when action in ~w(fav_status unfav_status)a + ) + + plug(RateLimiter, :statuses_actions when action in @rate_limited_status_actions) + plug(RateLimiter, :app_account_creation when action == :account_register) + plug(RateLimiter, :search when action in [:search, :search2, :account_search]) @local_mastodon_name "Mastodon-Local" @@ -160,10 +177,70 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do AccountView.render("account.json", %{user: user, for: user, with_pleroma_settings: true}) ) else - _e -> - conn - |> put_status(403) - |> json(%{error: "Invalid request"}) + _e -> render_error(conn, :forbidden, "Invalid request") + end + end + + def update_avatar(%{assigns: %{user: user}} = conn, %{"img" => ""}) do + change = Changeset.change(user, %{avatar: nil}) + {:ok, user} = User.update_and_set_cache(change) + CommonAPI.update(user) + + json(conn, %{url: nil}) + end + + def update_avatar(%{assigns: %{user: user}} = conn, params) do + {:ok, object} = ActivityPub.upload(params, type: :avatar) + change = Changeset.change(user, %{avatar: object.data}) + {:ok, user} = User.update_and_set_cache(change) + CommonAPI.update(user) + %{"url" => [%{"href" => href} | _]} = object.data + + json(conn, %{url: href}) + end + + def update_banner(%{assigns: %{user: user}} = conn, %{"banner" => ""}) do + with new_info <- %{"banner" => %{}}, + info_cng <- User.Info.profile_update(user.info, new_info), + changeset <- Ecto.Changeset.change(user) |> Ecto.Changeset.put_embed(:info, info_cng), + {:ok, user} <- User.update_and_set_cache(changeset) do + CommonAPI.update(user) + + json(conn, %{url: nil}) + end + end + + def update_banner(%{assigns: %{user: user}} = conn, params) do + with {:ok, object} <- ActivityPub.upload(%{"img" => params["banner"]}, type: :banner), + new_info <- %{"banner" => object.data}, + info_cng <- User.Info.profile_update(user.info, new_info), + changeset <- Ecto.Changeset.change(user) |> Ecto.Changeset.put_embed(:info, info_cng), + {:ok, user} <- User.update_and_set_cache(changeset) do + CommonAPI.update(user) + %{"url" => [%{"href" => href} | _]} = object.data + + json(conn, %{url: href}) + end + end + + def update_background(%{assigns: %{user: user}} = conn, %{"img" => ""}) do + with new_info <- %{"background" => %{}}, + info_cng <- User.Info.profile_update(user.info, new_info), + changeset <- Ecto.Changeset.change(user) |> Ecto.Changeset.put_embed(:info, info_cng), + {:ok, _user} <- User.update_and_set_cache(changeset) do + json(conn, %{url: nil}) + end + end + + def update_background(%{assigns: %{user: user}} = conn, params) do + with {:ok, object} <- ActivityPub.upload(params, type: :background), + new_info <- %{"background" => object.data}, + info_cng <- User.Info.profile_update(user.info, new_info), + changeset <- Ecto.Changeset.change(user) |> Ecto.Changeset.put_embed(:info, info_cng), + {:ok, _user} <- User.update_and_set_cache(changeset) do + %{"url" => [%{"href" => href} | _]} = object.data + + json(conn, %{url: href}) end end @@ -195,10 +272,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do account = AccountView.render("account.json", %{user: user, for: for_user}) json(conn, account) else - _e -> - conn - |> put_status(404) - |> json(%{error: "Can't find user"}) + _e -> render_error(conn, :not_found, "Can't find user") end end @@ -242,7 +316,9 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do "static_url" => url, "visible_in_picker" => true, "url" => url, - "tags" => tags + "tags" => tags, + # Assuming that a comma is authorized in the category name + "category" => (tags -- ["Custom"]) |> Enum.join(",") } end) end @@ -356,6 +432,10 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do def user_statuses(%{assigns: %{user: reading_user}} = conn, params) do with %User{} = user <- User.get_cached_by_id(params["id"]) do + params = + params + |> Map.put("tag", params["tagged"]) + activities = ActivityPub.fetch_user_activities(user, reading_user, params) conn @@ -442,15 +522,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do |> put_view(StatusView) |> try_render("poll.json", %{object: object, for: user}) else - nil -> - conn - |> put_status(404) - |> json(%{error: "Record not found"}) - - false -> - conn - |> put_status(404) - |> json(%{error: "Record not found"}) + nil -> render_error(conn, :not_found, "Record not found") + false -> render_error(conn, :not_found, "Record not found") end end @@ -479,18 +552,14 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do |> try_render("poll.json", %{object: object, for: user}) else nil -> - conn - |> put_status(404) - |> json(%{error: "Record not found"}) + render_error(conn, :not_found, "Record not found") false -> - conn - |> put_status(404) - |> json(%{error: "Record not found"}) + render_error(conn, :not_found, "Record not found") {:error, message} -> conn - |> put_status(422) + |> put_status(:unprocessable_entity) |> json(%{error: message}) end end @@ -579,10 +648,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do with {:ok, %Activity{}} <- CommonAPI.delete(id, user) do json(conn, %{}) else - _e -> - conn - |> put_status(403) - |> json(%{error: "Can't delete this post"}) + _e -> render_error(conn, :forbidden, "Can't delete this post") end end @@ -630,8 +696,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do else {:error, reason} -> conn - |> put_resp_content_type("application/json") - |> send_resp(:bad_request, Jason.encode!(%{"error" => reason})) + |> put_status(:bad_request) + |> json(%{"error" => reason}) end end @@ -707,8 +773,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do else {:error, reason} -> conn - |> put_resp_content_type("application/json") - |> send_resp(403, Jason.encode!(%{"error" => reason})) + |> put_status(:forbidden) + |> json(%{"error" => reason}) end end @@ -723,8 +789,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do else {:error, reason} -> conn - |> put_resp_content_type("application/json") - |> send_resp(403, Jason.encode!(%{"error" => reason})) + |> put_status(:forbidden) + |> json(%{"error" => reason}) end end @@ -802,9 +868,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do conn |> json(rendered) else - conn - |> put_resp_content_type("application/json") - |> send_resp(415, Jason.encode!(%{"error" => "mascots can only be images"})) + render_error(conn, :unsupported_media_type, "mascots can only be images") end end end @@ -933,8 +997,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do else {:error, message} -> conn - |> put_resp_content_type("application/json") - |> send_resp(403, Jason.encode!(%{"error" => message})) + |> put_status(:forbidden) + |> json(%{error: message}) end end @@ -947,8 +1011,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do else {:error, message} -> conn - |> put_resp_content_type("application/json") - |> send_resp(403, Jason.encode!(%{"error" => message})) + |> put_status(:forbidden) + |> json(%{error: message}) end end @@ -965,8 +1029,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do {:error, message} -> conn - |> put_resp_content_type("application/json") - |> send_resp(403, Jason.encode!(%{"error" => message})) + |> put_status(:forbidden) + |> json(%{error: message}) end end @@ -983,8 +1047,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do {:error, message} -> conn - |> put_resp_content_type("application/json") - |> send_resp(403, Jason.encode!(%{"error" => message})) + |> put_status(:forbidden) + |> json(%{error: message}) end end @@ -1013,8 +1077,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do else {:error, message} -> conn - |> put_resp_content_type("application/json") - |> send_resp(403, Jason.encode!(%{"error" => message})) + |> put_status(:forbidden) + |> json(%{error: message}) end end @@ -1027,8 +1091,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do else {:error, message} -> conn - |> put_resp_content_type("application/json") - |> send_resp(403, Jason.encode!(%{"error" => message})) + |> put_status(:forbidden) + |> json(%{error: message}) end end @@ -1049,8 +1113,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do else {:error, message} -> conn - |> put_resp_content_type("application/json") - |> send_resp(403, Jason.encode!(%{"error" => message})) + |> put_status(:forbidden) + |> json(%{error: message}) end end @@ -1064,8 +1128,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do else {:error, message} -> conn - |> put_resp_content_type("application/json") - |> send_resp(403, Jason.encode!(%{"error" => message})) + |> put_status(:forbidden) + |> json(%{error: message}) end end @@ -1099,8 +1163,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do else {:error, message} -> conn - |> put_resp_content_type("application/json") - |> send_resp(403, Jason.encode!(%{"error" => message})) + |> put_status(:forbidden) + |> json(%{error: message}) end end @@ -1113,8 +1177,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do else {:error, message} -> conn - |> put_resp_content_type("application/json") - |> send_resp(403, Jason.encode!(%{"error" => message})) + |> put_status(:forbidden) + |> json(%{error: message}) end end @@ -1162,13 +1226,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do |> put_view(StatusView) |> render("index.json", %{activities: activities, for: for_user, as: :activity}) else - nil -> - {:error, :not_found} - - true -> - conn - |> put_status(403) - |> json(%{error: "Can't get favorites"}) + nil -> {:error, :not_found} + true -> render_error(conn, :forbidden, "Can't get favorites") end end @@ -1200,10 +1259,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do res = ListView.render("list.json", list: list) json(conn, res) else - _e -> - conn - |> put_status(404) - |> json(%{error: "Record not found"}) + _e -> render_error(conn, :not_found, "Record not found") end end @@ -1219,7 +1275,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do json(conn, %{}) else _e -> - json(conn, "error") + json(conn, dgettext("errors", "error")) end end @@ -1270,7 +1326,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do json(conn, res) else _e -> - json(conn, "error") + json(conn, dgettext("errors", "error")) end end @@ -1294,10 +1350,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do |> put_view(StatusView) |> render("index.json", %{activities: activities, for: user, as: :activity}) else - _e -> - conn - |> put_status(403) - |> json(%{error: "Error."}) + _e -> render_error(conn, :forbidden, "Error.") end end @@ -1416,8 +1469,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do else e -> conn - |> put_resp_content_type("application/json") - |> send_resp(500, Jason.encode!(%{"error" => inspect(e)})) + |> put_status(:internal_server_error) + |> json(%{error: inspect(e)}) end end @@ -1585,20 +1638,18 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do |> Enum.map_join(", ", fn {_k, v} -> v end) conn - |> put_status(422) + |> put_status(:unprocessable_entity) |> json(%{error: error_message}) end def errors(conn, {:error, :not_found}) do - conn - |> put_status(404) - |> json(%{error: "Record not found"}) + render_error(conn, :not_found, "Record not found") end def errors(conn, _) do conn - |> put_status(500) - |> json("Something went wrong") + |> put_status(:internal_server_error) + |> json(dgettext("errors", "Something went wrong")) end def suggestions(%{assigns: %{user: user}} = conn, _) do @@ -1718,21 +1769,17 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do else {:error, errors} -> conn - |> put_status(400) - |> json(Jason.encode!(errors)) + |> put_status(:bad_request) + |> json(errors) end end def account_register(%{assigns: %{app: _app}} = conn, _params) do - conn - |> put_status(400) - |> json(%{error: "Missing parameters"}) + render_error(conn, :bad_request, "Missing parameters") end def account_register(conn, _) do - conn - |> put_status(403) - |> json(%{error: "Invalid credentials"}) + render_error(conn, :forbidden, "Invalid credentials") end def conversations(%{assigns: %{user: user}} = conn, params) do @@ -1762,21 +1809,14 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do def try_render(conn, target, params) when is_binary(target) do - res = render(conn, target, params) - - if res == nil do - conn - |> put_status(501) - |> json(%{error: "Can't display this activity"}) - else - res + case render(conn, target, params) do + nil -> render_error(conn, :not_implemented, "Can't display this activity") + res -> res end end def try_render(conn, _, _) do - conn - |> put_status(501) - |> json(%{error: "Can't display this activity"}) + render_error(conn, :not_implemented, "Can't display this activity") end defp present?(nil), do: false