WIP: post editing #103

Closed
Ghost wants to merge 48 commits from (deleted):feat/editing into develop
2 changed files with 95 additions and 10 deletions
Showing only changes of commit 9d9e765db2 - Show all commits

View file

@ -150,23 +150,25 @@ def handle(
# Tasks this handles:
# - Update the user
# - Update a non-user object (Note, Question, etc.)
#
# For a local user, we also get a changeset with the full information, so we
# can update non-federating, non-activitypub settings as well.
@impl true
def handle(%{data: %{"type" => "Update", "object" => updated_object}} = object, meta) do
if changeset = Keyword.get(meta, :user_update_changeset) do
changeset
|> User.update_and_set_cache()
updated_object_id = updated_object["id"]
with {_, true} <- {:has_id, is_binary(updated_object_id)},
{_, user} <- {:user, Pleroma.User.get_by_ap_id(updated_object_id)} do
if user do
handle_update_user(object, meta)
else
handle_update_object(object, meta)
end
else
{:ok, new_user_data} = ActivityPub.user_data_from_user_object(updated_object)
User.get_by_ap_id(updated_object["id"])
|> User.remote_user_changeset(new_user_data)
|> User.update_and_set_cache()
_ ->
{:ok, object, meta}
end
{:ok, object, meta}
end
# Tasks this handles:
@ -395,6 +397,66 @@ def handle(object, meta) do
{:ok, object, meta}
end
defp handle_update_user(
%{data: %{"type" => "Update", "object" => updated_object}} = object,
meta
) do
if changeset = Keyword.get(meta, :user_update_changeset) do
changeset
|> User.update_and_set_cache()
else
{:ok, new_user_data} = ActivityPub.user_data_from_user_object(updated_object)
User.get_by_ap_id(updated_object["id"])
|> User.remote_user_changeset(new_user_data)
|> User.update_and_set_cache()
end
{:ok, object, meta}
end
@updatable_object_types ["Note", "Question"]
# We do not allow poll options to be changed, but the poll description can be.
@updatable_fields [
"source",
"tag",
"updated",
"emoji",
"content",
"summary",
"sensitive",
"attachment",
"generator"
]
defp handle_update_object(
%{data: %{"type" => "Update", "object" => updated_object}} = object,
meta
) do
orig_object = Object.get_by_ap_id(updated_object["id"])
orig_object_data = orig_object.data
if orig_object_data["type"] in @updatable_object_types do
updated_object_data =
@updatable_fields
|> Enum.reduce(
orig_object_data,
fn field, acc ->
if Map.has_key?(updated_object, field) do
Map.put(acc, field, updated_object[field])
else
Map.drop(acc, [field])
end
end
)
orig_object
|> Object.change(%{data: updated_object_data})
|> Object.update_and_set_cache()
end
{:ok, object, meta}
end
def handle_object_creation(%{"type" => "Question"} = object, activity, meta) do
with {:ok, object, meta} <- Pipeline.common_pipeline(object, meta) do
PollWorker.schedule_poll_end(activity)

View file

@ -145,6 +145,29 @@ test "it uses a given changeset to update", %{user: user, update: update} do
end
end
describe "update notes" do
setup do
user = insert(:user)
note = insert(:note, user: user)
updated_note =
note.data
|> Map.put("summary", "edited summary")
|> Map.put("content", "edited content")
{:ok, update_data, []} = Builder.update(user, updated_note)
{:ok, update, _meta} = ActivityPub.persist(update_data, local: true)
%{user: user, object_id: note.id, update_data: update_data, update: update}
end
test "it updates the note", %{object_id: object_id, update: update} do
{:ok, _, _} = SideEffects.handle(update)
new_note = Pleroma.Object.get_by_id(object_id)
assert %{"summary" => "edited summary", "content" => "edited content"} = new_note.data
end
end
describe "EmojiReact objects" do
setup do
poster = insert(:user)