diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/pleroma/object.ex | 9 | ||||
-rw-r--r-- | lib/pleroma/web/activity_pub/activity_pub.ex | 9 | ||||
-rw-r--r-- | lib/pleroma/web/mastodon_api/mastodon_api_controller.ex | 34 | ||||
-rw-r--r-- | lib/pleroma/web/router.ex | 1 | ||||
-rw-r--r-- | lib/pleroma/web/twitter_api/twitter_api.ex | 4 | ||||
-rw-r--r-- | lib/pleroma/web/twitter_api/twitter_api_controller.ex | 45 |
6 files changed, 75 insertions, 27 deletions
diff --git a/lib/pleroma/object.ex b/lib/pleroma/object.ex index 03a75dfbd..31c8dd5bd 100644 --- a/lib/pleroma/object.ex +++ b/lib/pleroma/object.ex @@ -1,6 +1,6 @@ defmodule Pleroma.Object do use Ecto.Schema - alias Pleroma.{Repo, Object, Activity} + alias Pleroma.{Repo, Object, User, Activity} import Ecto.{Query, Changeset} schema "objects" do @@ -31,6 +31,13 @@ defmodule Pleroma.Object do def normalize(ap_id) when is_binary(ap_id), do: Object.get_by_ap_id(ap_id) def normalize(_), do: nil + # Owned objects can only be mutated by their owner + def authorize_mutation(%Object{data: %{"actor" => actor}}, %User{ap_id: ap_id}), + do: actor == ap_id + + # Legacy objects can be mutated by anybody + def authorize_mutation(%Object{}, %User{}), do: true + if Mix.env() == :test do def get_cached_by_ap_id(ap_id) do get_by_ap_id(ap_id) diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index 60253a715..28da57a10 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -574,7 +574,14 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do def upload(file, opts \\ []) do with {:ok, data} <- Upload.store(file, opts) do - Repo.insert(%Object{data: data}) + obj_data = + if opts[:actor] do + Map.put(data, "actor", opts[:actor]) + else + data + end + + Repo.insert(%Object{data: obj_data}) end end diff --git a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex index 15373dd90..eecfc742b 100644 --- a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex +++ b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex @@ -433,33 +433,31 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do |> json([]) end - def update_media(%{assigns: %{user: _}} = conn, data) do + def update_media(%{assigns: %{user: user}} = conn, data) do with %Object{} = object <- Repo.get(Object, data["id"]), + true <- Object.authorize_mutation(object, user), true <- is_binary(data["description"]), description <- data["description"] do new_data = %{object.data | "name" => description} - change = Object.change(object, %{data: new_data}) - {:ok, _} = Repo.update(change) + {:ok, _} = + object + |> Object.change(%{data: new_data}) + |> Repo.update() - data = - new_data - |> Map.put("id", object.id) - - render(conn, StatusView, "attachment.json", %{attachment: data}) + attachment_data = Map.put(new_data, "id", object.id) + render(conn, StatusView, "attachment.json", %{attachment: attachment_data}) end end - def upload(%{assigns: %{user: _}} = conn, %{"file" => file} = data) do - with {:ok, object} <- ActivityPub.upload(file, description: Map.get(data, "description")) do - change = Object.change(object, %{data: object.data}) - {:ok, object} = Repo.update(change) - - objdata = - object.data - |> Map.put("id", object.id) - - render(conn, StatusView, "attachment.json", %{attachment: objdata}) + def upload(%{assigns: %{user: user}} = conn, %{"file" => file} = data) do + with {:ok, object} <- + ActivityPub.upload(file, + actor: User.ap_id(user), + description: Map.get(data, "description") + ) do + attachment_data = Map.put(object.data, "id", object.id) + render(conn, StatusView, "attachment.json", %{attachment: attachment_data}) end end diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index d6a9d5779..b7c79d2eb 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -324,6 +324,7 @@ defmodule Pleroma.Web.Router do post("/statusnet/media/upload", TwitterAPI.Controller, :upload) post("/media/upload", TwitterAPI.Controller, :upload_json) + post("/media/metadata/create", TwitterAPI.Controller, :update_media) post("/favorites/create/:id", TwitterAPI.Controller, :favorite) post("/favorites/create", TwitterAPI.Controller, :favorite) diff --git a/lib/pleroma/web/twitter_api/twitter_api.ex b/lib/pleroma/web/twitter_api/twitter_api.ex index c19a4f084..9c485d965 100644 --- a/lib/pleroma/web/twitter_api/twitter_api.ex +++ b/lib/pleroma/web/twitter_api/twitter_api.ex @@ -93,8 +93,8 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI do end end - def upload(%Plug.Upload{} = file, format \\ "xml") do - {:ok, object} = ActivityPub.upload(file) + def upload(%Plug.Upload{} = file, %User{} = user, format \\ "xml") do + {:ok, object} = ActivityPub.upload(file, actor: User.ap_id(user)) url = List.first(object.data["url"]) href = url["href"] diff --git a/lib/pleroma/web/twitter_api/twitter_api_controller.ex b/lib/pleroma/web/twitter_api/twitter_api_controller.ex index 8fd6ea078..0ccf937b0 100644 --- a/lib/pleroma/web/twitter_api/twitter_api_controller.ex +++ b/lib/pleroma/web/twitter_api/twitter_api_controller.ex @@ -4,7 +4,7 @@ defmodule Pleroma.Web.TwitterAPI.Controller do alias Pleroma.Web.TwitterAPI.{TwitterAPI, UserView, ActivityView, NotificationView} alias Pleroma.Web.CommonAPI alias Pleroma.Web.CommonAPI.Utils, as: CommonUtils - alias Pleroma.{Repo, Activity, User, Notification} + alias Pleroma.{Repo, Activity, Object, User, Notification} alias Pleroma.Web.ActivityPub.ActivityPub alias Pleroma.Web.ActivityPub.Utils alias Ecto.Changeset @@ -226,16 +226,51 @@ defmodule Pleroma.Web.TwitterAPI.Controller do end end - def upload(conn, %{"media" => media}) do - response = TwitterAPI.upload(media) + @doc """ + Updates metadata of uploaded media object. + Derived from [Twitter API endpoint](https://developer.twitter.com/en/docs/media/upload-media/api-reference/post-media-metadata-create). + """ + def update_media(%{assigns: %{user: user}} = conn, %{"media_id" => id} = data) do + object = Repo.get(Object, id) + description = get_in(data, ["alt_text", "text"]) || data["name"] || data["description"] + + {conn, status, response_body} = + cond do + !object -> + {halt(conn), :not_found, ""} + + !Object.authorize_mutation(object, user) -> + {halt(conn), :forbidden, "You can only update your own uploads."} + + !is_binary(description) -> + {conn, :not_modified, ""} + + true -> + new_data = Map.put(object.data, "name", description) + + {:ok, _} = + object + |> Object.change(%{data: new_data}) + |> Repo.update() + + {conn, :no_content, ""} + end + + conn + |> put_status(status) + |> json(response_body) + end + + def upload(%{assigns: %{user: user}} = conn, %{"media" => media}) do + response = TwitterAPI.upload(media, user) conn |> put_resp_content_type("application/atom+xml") |> send_resp(200, response) end - def upload_json(conn, %{"media" => media}) do - response = TwitterAPI.upload(media, "json") + def upload_json(%{assigns: %{user: user}} = conn, %{"media" => media}) do + response = TwitterAPI.upload(media, user, "json") conn |> json_reply(200, response) |