Preserve internal fields when reinjecting

This commit is contained in:
rinpatch 2019-09-18 19:53:51 +03:00
parent d32894ae51
commit eb87a86b5b
2 changed files with 69 additions and 43 deletions

View File

@ -13,6 +13,7 @@ defmodule Pleroma.Object.Fetcher do
alias Pleroma.Web.OStatus alias Pleroma.Web.OStatus
require Logger require Logger
require Pleroma.Constants
defp touch_changeset(changeset) do defp touch_changeset(changeset) do
updated_at = updated_at =
@ -22,10 +23,19 @@ defp touch_changeset(changeset) do
Ecto.Changeset.put_change(changeset, :updated_at, updated_at) Ecto.Changeset.put_change(changeset, :updated_at, updated_at)
end end
defp maybe_reinject_internal_fields(data, %{data: %{} = old_data}) do
internal_fields = Map.take(old_data, Pleroma.Constants.object_internal_fields())
Map.merge(data, internal_fields)
end
defp maybe_reinject_internal_fields(data, _), do: data
defp reinject_object(struct, data) do defp reinject_object(struct, data) do
Logger.debug("Reinjecting object #{data["id"]}") Logger.debug("Reinjecting object #{data["id"]}")
with data <- Transmogrifier.fix_object(data), with data <- Transmogrifier.fix_object(data),
data <- maybe_reinject_internal_fields(data, struct),
changeset <- Object.change(struct, %{data: data}), changeset <- Object.change(struct, %{data: data}),
changeset <- touch_changeset(changeset), changeset <- touch_changeset(changeset),
{:ok, object} <- Repo.insert_or_update(changeset) do {:ok, object} <- Repo.insert_or_update(changeset) do

View File

@ -7,8 +7,10 @@ defmodule Pleroma.ObjectTest do
import ExUnit.CaptureLog import ExUnit.CaptureLog
import Pleroma.Factory import Pleroma.Factory
import Tesla.Mock import Tesla.Mock
alias Pleroma.Activity
alias Pleroma.Object alias Pleroma.Object
alias Pleroma.Repo alias Pleroma.Repo
alias Pleroma.Web.CommonAPI
setup do setup do
mock(fn env -> apply(HttpRequestMock, :request, [env]) end) mock(fn env -> apply(HttpRequestMock, :request, [env]) end)
@ -92,7 +94,7 @@ test "does not fetch unknown objects when fetch_remote is false" do
end end
describe "get_by_id_and_maybe_refetch" do describe "get_by_id_and_maybe_refetch" do
test "refetches if the time since the last refetch is greater than the interval" do setup do
mock(fn mock(fn
%{method: :get, url: "https://patch.cx/objects/9a172665-2bc5-452d-8428-2361d4c33b1d"} -> %{method: :get, url: "https://patch.cx/objects/9a172665-2bc5-452d-8428-2361d4c33b1d"} ->
%Tesla.Env{status: 200, body: File.read!("test/fixtures/tesla_mock/poll_original.json")} %Tesla.Env{status: 200, body: File.read!("test/fixtures/tesla_mock/poll_original.json")}
@ -101,34 +103,41 @@ test "refetches if the time since the last refetch is greater than the interval"
apply(HttpRequestMock, :request, [env]) apply(HttpRequestMock, :request, [env])
end) end)
mock_modified = fn resp ->
mock(fn
%{method: :get, url: "https://patch.cx/objects/9a172665-2bc5-452d-8428-2361d4c33b1d"} ->
resp
env ->
apply(HttpRequestMock, :request, [env])
end)
end
on_exit(fn -> mock(fn env -> apply(HttpRequestMock, :request, [env]) end) end)
[mock_modified: mock_modified]
end
test "refetches if the time since the last refetch is greater than the interval", %{
mock_modified: mock_modified
} do
%Object{} = %Object{} =
object = Object.normalize("https://patch.cx/objects/9a172665-2bc5-452d-8428-2361d4c33b1d") object = Object.normalize("https://patch.cx/objects/9a172665-2bc5-452d-8428-2361d4c33b1d")
assert Enum.at(object.data["oneOf"], 0)["replies"]["totalItems"] == 4 assert Enum.at(object.data["oneOf"], 0)["replies"]["totalItems"] == 4
assert Enum.at(object.data["oneOf"], 1)["replies"]["totalItems"] == 0 assert Enum.at(object.data["oneOf"], 1)["replies"]["totalItems"] == 0
mock(fn mock_modified.(%Tesla.Env{
%{method: :get, url: "https://patch.cx/objects/9a172665-2bc5-452d-8428-2361d4c33b1d"} -> status: 200,
%Tesla.Env{status: 200, body: File.read!("test/fixtures/tesla_mock/poll_modified.json")} body: File.read!("test/fixtures/tesla_mock/poll_modified.json")
})
env ->
apply(HttpRequestMock, :request, [env])
end)
updated_object = Object.get_by_id_and_maybe_refetch(object.id, interval: -1) updated_object = Object.get_by_id_and_maybe_refetch(object.id, interval: -1)
assert Enum.at(updated_object.data["oneOf"], 0)["replies"]["totalItems"] == 8 assert Enum.at(updated_object.data["oneOf"], 0)["replies"]["totalItems"] == 8
assert Enum.at(updated_object.data["oneOf"], 1)["replies"]["totalItems"] == 3 assert Enum.at(updated_object.data["oneOf"], 1)["replies"]["totalItems"] == 3
end end
test "returns the old object if refetch fails" do test "returns the old object if refetch fails", %{mock_modified: mock_modified} do
mock(fn
%{method: :get, url: "https://patch.cx/objects/9a172665-2bc5-452d-8428-2361d4c33b1d"} ->
%Tesla.Env{status: 200, body: File.read!("test/fixtures/tesla_mock/poll_original.json")}
env ->
apply(HttpRequestMock, :request, [env])
end)
%Object{} = %Object{} =
object = Object.normalize("https://patch.cx/objects/9a172665-2bc5-452d-8428-2361d4c33b1d") object = Object.normalize("https://patch.cx/objects/9a172665-2bc5-452d-8428-2361d4c33b1d")
@ -136,16 +145,7 @@ test "returns the old object if refetch fails" do
assert Enum.at(object.data["oneOf"], 1)["replies"]["totalItems"] == 0 assert Enum.at(object.data["oneOf"], 1)["replies"]["totalItems"] == 0
assert capture_log(fn -> assert capture_log(fn ->
mock(fn mock_modified.(%Tesla.Env{status: 404, body: ""})
%{
method: :get,
url: "https://patch.cx/objects/9a172665-2bc5-452d-8428-2361d4c33b1d"
} ->
%Tesla.Env{status: 404, body: ""}
env ->
apply(HttpRequestMock, :request, [env])
end)
updated_object = Object.get_by_id_and_maybe_refetch(object.id, interval: -1) updated_object = Object.get_by_id_and_maybe_refetch(object.id, interval: -1)
assert Enum.at(updated_object.data["oneOf"], 0)["replies"]["totalItems"] == 4 assert Enum.at(updated_object.data["oneOf"], 0)["replies"]["totalItems"] == 4
@ -154,32 +154,48 @@ test "returns the old object if refetch fails" do
"[error] Couldn't refresh https://patch.cx/objects/9a172665-2bc5-452d-8428-2361d4c33b1d" "[error] Couldn't refresh https://patch.cx/objects/9a172665-2bc5-452d-8428-2361d4c33b1d"
end end
test "does not refetch if the time since the last refetch is greater than the interval" do test "does not refetch if the time since the last refetch is greater than the interval", %{
mock(fn mock_modified: mock_modified
%{method: :get, url: "https://patch.cx/objects/9a172665-2bc5-452d-8428-2361d4c33b1d"} -> } do
%Tesla.Env{status: 200, body: File.read!("test/fixtures/tesla_mock/poll_original.json")}
env ->
apply(HttpRequestMock, :request, [env])
end)
%Object{} = %Object{} =
object = Object.normalize("https://patch.cx/objects/9a172665-2bc5-452d-8428-2361d4c33b1d") object = Object.normalize("https://patch.cx/objects/9a172665-2bc5-452d-8428-2361d4c33b1d")
assert Enum.at(object.data["oneOf"], 0)["replies"]["totalItems"] == 4 assert Enum.at(object.data["oneOf"], 0)["replies"]["totalItems"] == 4
assert Enum.at(object.data["oneOf"], 1)["replies"]["totalItems"] == 0 assert Enum.at(object.data["oneOf"], 1)["replies"]["totalItems"] == 0
mock(fn mock_modified.(%Tesla.Env{
%{method: :get, url: "https://patch.cx/objects/9a172665-2bc5-452d-8428-2361d4c33b1d"} -> status: 200,
%Tesla.Env{status: 200, body: File.read!("test/fixtures/tesla_mock/poll_modified.json")} body: File.read!("test/fixtures/tesla_mock/poll_modified.json")
})
env ->
apply(HttpRequestMock, :request, [env])
end)
updated_object = Object.get_by_id_and_maybe_refetch(object.id, interval: 100) updated_object = Object.get_by_id_and_maybe_refetch(object.id, interval: 100)
assert Enum.at(updated_object.data["oneOf"], 0)["replies"]["totalItems"] == 4 assert Enum.at(updated_object.data["oneOf"], 0)["replies"]["totalItems"] == 4
assert Enum.at(updated_object.data["oneOf"], 1)["replies"]["totalItems"] == 0 assert Enum.at(updated_object.data["oneOf"], 1)["replies"]["totalItems"] == 0
end end
test "preserves internal fields on refetch", %{mock_modified: mock_modified} do
%Object{} =
object = Object.normalize("https://patch.cx/objects/9a172665-2bc5-452d-8428-2361d4c33b1d")
assert Enum.at(object.data["oneOf"], 0)["replies"]["totalItems"] == 4
assert Enum.at(object.data["oneOf"], 1)["replies"]["totalItems"] == 0
user = insert(:user)
activity = Activity.get_create_by_object_ap_id(object.data["id"])
{:ok, _activity, object} = CommonAPI.favorite(activity.id, user)
assert object.data["like_count"] == 1
mock_modified.(%Tesla.Env{
status: 200,
body: File.read!("test/fixtures/tesla_mock/poll_modified.json")
})
updated_object = Object.get_by_id_and_maybe_refetch(object.id, interval: -1)
assert Enum.at(updated_object.data["oneOf"], 0)["replies"]["totalItems"] == 8
assert Enum.at(updated_object.data["oneOf"], 1)["replies"]["totalItems"] == 3
assert updated_object.data["like_count"] == 1
end
end end
end end