[#210] Mastodon: actor storing for media uploads, ownership check to update_media.
authorIvan Tashkinov <ivantashkinov@gmail.com>
Thu, 6 Dec 2018 07:26:17 +0000 (10:26 +0300)
committerIvan Tashkinov <ivantashkinov@gmail.com>
Thu, 6 Dec 2018 07:26:17 +0000 (10:26 +0300)
Refactoring.

lib/pleroma/object.ex
lib/pleroma/web/activity_pub/activity_pub.ex
lib/pleroma/web/mastodon_api/mastodon_api_controller.ex
lib/pleroma/web/twitter_api/twitter_api.ex
lib/pleroma/web/twitter_api/twitter_api_controller.ex
test/web/mastodon_api/mastodon_api_controller_test.exs

index 03a75dfbdbbcdcf00bbf9493b1c8cc9272868266..31c8dd5bd13cba9913d322729b34621999da9d98 100644 (file)
@@ -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)
index 39692163f168363bab1ec6f3c7263e0de8ff53a5..aaf9d3854b1b80d229f0c04324988fbab2494d08 100644 (file)
@@ -574,7 +574,13 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
 
   def upload(file, opts \\ []) do
     with {:ok, data} <- Upload.store(file, opts) do
-      obj_data = if opts[:actor], do: Map.put(data, "actor", opts[:actor]), else: data
+      obj_data =
+        if opts[:actor] do
+          Map.put(data, "actor", opts[:actor])
+        else
+          data
+        end
+
       Repo.insert(%Object{data: obj_data})
     end
   end
index 543fdf4161cad45020110262c1820abcc7d7ea3c..ef204f7f3c0d4aa4f4d52af7eda7e5c43ae07ed6 100644 (file)
@@ -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
 
index b9468ab0369aae55a3e4503c65615244dceefccf..9c485d965592b8d2b587414b3637848218a109c7 100644 (file)
@@ -93,12 +93,8 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI do
     end
   end
 
-  def ap_upload(%Plug.Upload{} = file, %User{} = user) do
-    ActivityPub.upload(file, actor: User.ap_id(user))
-  end
-
   def upload(%Plug.Upload{} = file, %User{} = user, format \\ "xml") do
-    {:ok, object} = ap_upload(file, user)
+    {:ok, object} = ActivityPub.upload(file, actor: User.ap_id(user))
 
     url = List.first(object.data["url"])
     href = url["href"]
index 2f12131e7cb20949966845199e165c33e76a6e2b..c19ee230f2ca5034099562e424599d3a0d0187fc 100644 (file)
@@ -239,7 +239,7 @@ defmodule Pleroma.Web.TwitterAPI.Controller do
         !object ->
           {halt(conn), :not_found, ""}
 
-        object.data["actor"] != User.ap_id(user) ->
+        !Object.authorize_mutation(object, user) ->
           {halt(conn), :forbidden, "You can only update your own uploads."}
 
         !is_binary(description) ->
index b5839cff10059d1264ebd1d873ebbfd1e41e8315..d952cecc86dceff76d0d3e5356efd60d94542e77 100644 (file)
@@ -2,7 +2,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
   use Pleroma.Web.ConnCase
 
   alias Pleroma.Web.TwitterAPI.TwitterAPI
-  alias Pleroma.{Repo, User, Activity, Notification}
+  alias Pleroma.{Repo, User, Object, Activity, Notification}
   alias Pleroma.Web.{OStatus, CommonAPI}
   alias Pleroma.Web.ActivityPub.ActivityPub
 
@@ -959,6 +959,10 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
 
     assert media["type"] == "image"
     assert media["description"] == desc
+    assert media["id"]
+
+    object = Repo.get(Object, media["id"])
+    assert object.data["actor"] == User.ap_id(user)
   end
 
   test "hashtag timeline", %{conn: conn} do