Pass history items through ObjectValidator for updatable object types
This commit is contained in:
parent
4edc867b87
commit
4367489a3e
|
@ -128,15 +128,20 @@ def validate(%{"type" => type} = object, meta)
|
||||||
end
|
end
|
||||||
|
|
||||||
with {:ok, object} <-
|
with {:ok, object} <-
|
||||||
object
|
do_separate_with_history(object, fn object ->
|
||||||
|> validator.cast_and_validate()
|
with {:ok, object} <-
|
||||||
|> Ecto.Changeset.apply_action(:insert) do
|
object
|
||||||
object = stringify_keys(object)
|
|> validator.cast_and_validate()
|
||||||
|
|> Ecto.Changeset.apply_action(:insert) do
|
||||||
|
object = stringify_keys(object)
|
||||||
|
|
||||||
# Insert copy of hashtags as strings for the non-hashtag table indexing
|
# Insert copy of hashtags as strings for the non-hashtag table indexing
|
||||||
tag = (object["tag"] || []) ++ Object.hashtags(%Object{data: object})
|
tag = (object["tag"] || []) ++ Object.hashtags(%Object{data: object})
|
||||||
object = Map.put(object, "tag", tag)
|
object = Map.put(object, "tag", tag)
|
||||||
|
|
||||||
|
{:ok, object}
|
||||||
|
end
|
||||||
|
end) do
|
||||||
{:ok, object, meta}
|
{:ok, object, meta}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -262,4 +267,54 @@ def fetch_actor_and_object(object) do
|
||||||
Object.normalize(object["object"], fetch: true)
|
Object.normalize(object["object"], fetch: true)
|
||||||
:ok
|
:ok
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp for_each_history_item(
|
||||||
|
%{"type" => "OrderedCollection", "orderedItems" => items} = history,
|
||||||
|
object,
|
||||||
|
fun
|
||||||
|
) do
|
||||||
|
processed_items =
|
||||||
|
Enum.map(items, fn item ->
|
||||||
|
with item <- Map.put(item, "id", object["id"]),
|
||||||
|
{:ok, item} <- fun.(item) do
|
||||||
|
item
|
||||||
|
else
|
||||||
|
_ -> nil
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
if Enum.all?(processed_items, &(not is_nil(&1))) do
|
||||||
|
{:ok, Map.put(history, "orderedItems", processed_items)}
|
||||||
|
else
|
||||||
|
{:error, :invalid_history}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp for_each_history_item(nil, _object, _fun) do
|
||||||
|
{:ok, nil}
|
||||||
|
end
|
||||||
|
|
||||||
|
defp for_each_history_item(_, _object, _fun) do
|
||||||
|
{:error, :invalid_history}
|
||||||
|
end
|
||||||
|
|
||||||
|
# fun is (object -> {:ok, validated_object_with_string_keys})
|
||||||
|
defp do_separate_with_history(object, fun) do
|
||||||
|
with history <- object["formerRepresentations"],
|
||||||
|
object <- Map.drop(object, ["formerRepresentations"]),
|
||||||
|
{_, {:ok, object}} <- {:main_body, fun.(object)},
|
||||||
|
{_, {:ok, history}} <- {:history_items, for_each_history_item(history, object, fun)} do
|
||||||
|
object =
|
||||||
|
if history do
|
||||||
|
Map.put(object, "formerRepresentations", history)
|
||||||
|
else
|
||||||
|
object
|
||||||
|
end
|
||||||
|
|
||||||
|
{:ok, object}
|
||||||
|
else
|
||||||
|
{:main_body, e} -> e
|
||||||
|
{:history_items, e} -> e
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
defmodule Pleroma.Web.ActivityPub.ObjectValidators.ArticleNotePageValidatorTest do
|
defmodule Pleroma.Web.ActivityPub.ObjectValidators.ArticleNotePageValidatorTest do
|
||||||
use Pleroma.DataCase, async: true
|
use Pleroma.DataCase, async: true
|
||||||
|
|
||||||
|
alias Pleroma.Web.ActivityPub.ObjectValidator
|
||||||
alias Pleroma.Web.ActivityPub.ObjectValidators.ArticleNotePageValidator
|
alias Pleroma.Web.ActivityPub.ObjectValidators.ArticleNotePageValidator
|
||||||
alias Pleroma.Web.ActivityPub.Utils
|
alias Pleroma.Web.ActivityPub.Utils
|
||||||
|
|
||||||
|
@ -38,6 +39,49 @@ test "a note from factory validates" do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "Note with history" do
|
||||||
|
setup do
|
||||||
|
user = insert(:user)
|
||||||
|
{:ok, activity} = Pleroma.Web.CommonAPI.post(user, %{status: "mew mew :dinosaur:"})
|
||||||
|
{:ok, edit} = Pleroma.Web.CommonAPI.update(user, activity, %{status: "edited :blank:"})
|
||||||
|
|
||||||
|
{:ok, %{"object" => external_rep}} =
|
||||||
|
Pleroma.Web.ActivityPub.Transmogrifier.prepare_outgoing(edit.data)
|
||||||
|
|
||||||
|
%{external_rep: external_rep}
|
||||||
|
end
|
||||||
|
|
||||||
|
test "edited note", %{external_rep: external_rep} do
|
||||||
|
assert %{"formerRepresentations" => %{"orderedItems" => [%{"tag" => [_]}]}} = external_rep
|
||||||
|
|
||||||
|
{:ok, validate_res, []} = ObjectValidator.validate(external_rep, [])
|
||||||
|
|
||||||
|
assert %{"formerRepresentations" => %{"orderedItems" => [%{"emoji" => %{"dinosaur" => _}}]}} =
|
||||||
|
validate_res
|
||||||
|
end
|
||||||
|
|
||||||
|
test "edited note, badly-formed formerRepresentations", %{external_rep: external_rep} do
|
||||||
|
external_rep = Map.put(external_rep, "formerRepresentations", %{})
|
||||||
|
|
||||||
|
assert {:error, _} = ObjectValidator.validate(external_rep, [])
|
||||||
|
end
|
||||||
|
|
||||||
|
test "edited note, badly-formed history item", %{external_rep: external_rep} do
|
||||||
|
history_item =
|
||||||
|
Enum.at(external_rep["formerRepresentations"]["orderedItems"], 0)
|
||||||
|
|> Map.put("type", "Foo")
|
||||||
|
|
||||||
|
external_rep =
|
||||||
|
put_in(
|
||||||
|
external_rep,
|
||||||
|
["formerRepresentations", "orderedItems"],
|
||||||
|
[history_item]
|
||||||
|
)
|
||||||
|
|
||||||
|
assert {:error, _} = ObjectValidator.validate(external_rep, [])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
test "a Note from Roadhouse validates" do
|
test "a Note from Roadhouse validates" do
|
||||||
insert(:user, ap_id: "https://macgirvin.com/channel/mike")
|
insert(:user, ap_id: "https://macgirvin.com/channel/mike")
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue