[#210] Mastodon: actor storing for media uploads, ownership check to update_media.

Refactoring.
This commit is contained in:
Ivan Tashkinov 2018-12-06 10:26:17 +03:00
parent 3b5be09f45
commit 3e90f688f1
6 changed files with 38 additions and 27 deletions

View File

@ -1,6 +1,6 @@
defmodule Pleroma.Object do defmodule Pleroma.Object do
use Ecto.Schema use Ecto.Schema
alias Pleroma.{Repo, Object, Activity} alias Pleroma.{Repo, Object, User, Activity}
import Ecto.{Query, Changeset} import Ecto.{Query, Changeset}
schema "objects" do schema "objects" do
@ -31,6 +31,13 @@ def normalize(obj) when is_map(obj), do: Object.get_by_ap_id(obj["id"])
def normalize(ap_id) when is_binary(ap_id), do: Object.get_by_ap_id(ap_id) def normalize(ap_id) when is_binary(ap_id), do: Object.get_by_ap_id(ap_id)
def normalize(_), do: nil 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 if Mix.env() == :test do
def get_cached_by_ap_id(ap_id) do def get_cached_by_ap_id(ap_id) do
get_by_ap_id(ap_id) get_by_ap_id(ap_id)

View File

@ -574,7 +574,13 @@ def fetch_activities_bounded(recipients_to, recipients_cc, opts \\ %{}) do
def upload(file, opts \\ []) do def upload(file, opts \\ []) do
with {:ok, data} <- Upload.store(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}) Repo.insert(%Object{data: obj_data})
end end
end end

View File

@ -433,33 +433,31 @@ def relationships(%{assigns: %{user: user}} = conn, _) do
|> json([]) |> json([])
end 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"]), with %Object{} = object <- Repo.get(Object, data["id"]),
true <- Object.authorize_mutation(object, user),
true <- is_binary(data["description"]), true <- is_binary(data["description"]),
description <- data["description"] do description <- data["description"] do
new_data = %{object.data | "name" => description} new_data = %{object.data | "name" => description}
change = Object.change(object, %{data: new_data}) {:ok, _} =
{:ok, _} = Repo.update(change) object
|> Object.change(%{data: new_data})
|> Repo.update()
data = attachment_data = Map.put(new_data, "id", object.id)
new_data render(conn, StatusView, "attachment.json", %{attachment: attachment_data})
|> Map.put("id", object.id)
render(conn, StatusView, "attachment.json", %{attachment: data})
end end
end end
def upload(%{assigns: %{user: _}} = conn, %{"file" => file} = data) do def upload(%{assigns: %{user: user}} = conn, %{"file" => file} = data) do
with {:ok, object} <- ActivityPub.upload(file, description: Map.get(data, "description")) do with {:ok, object} <-
change = Object.change(object, %{data: object.data}) ActivityPub.upload(file,
{:ok, object} = Repo.update(change) actor: User.ap_id(user),
description: Map.get(data, "description")
objdata = ) do
object.data attachment_data = Map.put(object.data, "id", object.id)
|> Map.put("id", object.id) render(conn, StatusView, "attachment.json", %{attachment: attachment_data})
render(conn, StatusView, "attachment.json", %{attachment: objdata})
end end
end end

View File

@ -93,12 +93,8 @@ def unfav(%User{} = user, ap_id_or_id) do
end end
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 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"]) url = List.first(object.data["url"])
href = url["href"] href = url["href"]

View File

@ -239,7 +239,7 @@ def update_media(%{assigns: %{user: user}} = conn, %{"media_id" => id} = data) d
!object -> !object ->
{halt(conn), :not_found, ""} {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."} {halt(conn), :forbidden, "You can only update your own uploads."}
!is_binary(description) -> !is_binary(description) ->

View File

@ -2,7 +2,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
use Pleroma.Web.ConnCase use Pleroma.Web.ConnCase
alias Pleroma.Web.TwitterAPI.TwitterAPI 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.{OStatus, CommonAPI}
alias Pleroma.Web.ActivityPub.ActivityPub alias Pleroma.Web.ActivityPub.ActivityPub
@ -959,6 +959,10 @@ test "media upload", %{conn: conn} do
assert media["type"] == "image" assert media["type"] == "image"
assert media["description"] == desc assert media["description"] == desc
assert media["id"]
object = Repo.get(Object, media["id"])
assert object.data["actor"] == User.ap_id(user)
end end
test "hashtag timeline", %{conn: conn} do test "hashtag timeline", %{conn: conn} do