ActivityPub: Remove update
and switch to pipeline.
This commit is contained in:
parent
1e7ca24430
commit
e785cd5cae
5 changed files with 52 additions and 96 deletions
|
@ -321,28 +321,6 @@ defp accept_or_reject(type, %{to: to, actor: actor, object: object} = params) do
|
|||
end
|
||||
end
|
||||
|
||||
@spec update(map()) :: {:ok, Activity.t()} | {:error, any()}
|
||||
def update(%{to: to, cc: cc, actor: actor, object: object} = params) do
|
||||
local = !(params[:local] == false)
|
||||
activity_id = params[:activity_id]
|
||||
|
||||
data =
|
||||
%{
|
||||
"to" => to,
|
||||
"cc" => cc,
|
||||
"type" => "Update",
|
||||
"actor" => actor,
|
||||
"object" => object
|
||||
}
|
||||
|> Maps.put_if_present("id", activity_id)
|
||||
|
||||
with {:ok, activity} <- insert(data, local),
|
||||
_ <- notify_and_stream(activity),
|
||||
:ok <- maybe_federate(activity) do
|
||||
{:ok, activity}
|
||||
end
|
||||
end
|
||||
|
||||
@spec follow(User.t(), User.t(), String.t() | nil, boolean(), keyword()) ::
|
||||
{:ok, Activity.t()} | {:error, any()}
|
||||
def follow(follower, followed, activity_id \\ nil, local \\ true, opts \\ []) do
|
||||
|
|
|
@ -21,13 +21,21 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do
|
|||
def handle(object, meta \\ [])
|
||||
|
||||
# Tasks this handles:
|
||||
# Update the user
|
||||
# - Update the user
|
||||
#
|
||||
# For a local user, we also get a changeset with the full information, so we
|
||||
# can update non-federating, non-activitypub settings as well.
|
||||
def handle(%{data: %{"type" => "Update", "object" => updated_object}} = object, meta) do
|
||||
{:ok, new_user_data} = ActivityPub.user_data_from_user_object(updated_object)
|
||||
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()
|
||||
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
|
||||
|
|
|
@ -20,6 +20,8 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
|
|||
alias Pleroma.Plugs.RateLimiter
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||
alias Pleroma.Web.ActivityPub.Pipeline
|
||||
alias Pleroma.Web.ActivityPub.Builder
|
||||
alias Pleroma.Web.CommonAPI
|
||||
alias Pleroma.Web.MastodonAPI.ListView
|
||||
alias Pleroma.Web.MastodonAPI.MastodonAPI
|
||||
|
@ -179,34 +181,39 @@ def update_credentials(%{assigns: %{user: user}, body_params: params} = conn, _p
|
|||
|> Maps.put_if_present(:default_scope, params["source"]["privacy"])
|
||||
|> Maps.put_if_present(:actor_type, params[:actor_type])
|
||||
|
||||
changeset = User.update_changeset(user, user_params)
|
||||
|
||||
with {:ok, user} <- User.update_and_set_cache(changeset) do
|
||||
user
|
||||
|> build_update_activity_params()
|
||||
|> ActivityPub.update()
|
||||
|
||||
render(conn, "show.json", user: user, for: user, with_pleroma_settings: true)
|
||||
# What happens here:
|
||||
#
|
||||
# We want to update the user through the pipeline, but the ActivityPub
|
||||
# update information is not quite enough for this, because this also
|
||||
# contains local settings that don't federate and don't even appear
|
||||
# in the Update activity.
|
||||
#
|
||||
# So we first build the normal local changeset, then apply it to the
|
||||
# user data, but don't persist it. With this, we generate the object
|
||||
# data for our update activity. We feed this and the changeset as meta
|
||||
# inforation into the pipeline, where they will be properly updated and
|
||||
# federated.
|
||||
with changeset <- User.update_changeset(user, user_params),
|
||||
{:ok, unpersisted_user} <- Ecto.Changeset.apply_action(changeset, :update),
|
||||
updated_object <-
|
||||
Pleroma.Web.ActivityPub.UserView.render("user.json", user: user)
|
||||
|> Map.delete("@context"),
|
||||
{:ok, update_data, []} <- Builder.update(user, updated_object),
|
||||
{:ok, _update, _} <-
|
||||
Pipeline.common_pipeline(update_data,
|
||||
local: true,
|
||||
user_update_changeset: changeset
|
||||
) do
|
||||
render(conn, "show.json",
|
||||
user: unpersisted_user,
|
||||
for: unpersisted_user,
|
||||
with_pleroma_settings: true
|
||||
)
|
||||
else
|
||||
_e -> render_error(conn, :forbidden, "Invalid request")
|
||||
end
|
||||
end
|
||||
|
||||
# Hotfix, handling will be redone with the pipeline
|
||||
defp build_update_activity_params(user) do
|
||||
object =
|
||||
Pleroma.Web.ActivityPub.UserView.render("user.json", user: user)
|
||||
|> Map.delete("@context")
|
||||
|
||||
%{
|
||||
local: true,
|
||||
to: [user.follower_address],
|
||||
cc: [],
|
||||
object: object,
|
||||
actor: user.ap_id
|
||||
}
|
||||
end
|
||||
|
||||
defp normalize_fields_attributes(fields) do
|
||||
if Enum.all?(fields, &is_tuple/1) do
|
||||
Enum.map(fields, fn {_, v} -> v end)
|
||||
|
|
|
@ -1092,52 +1092,6 @@ test "it filters broken threads" do
|
|||
end
|
||||
end
|
||||
|
||||
describe "update" do
|
||||
setup do: clear_config([:instance, :max_pinned_statuses])
|
||||
|
||||
test "it creates an update activity with the new user data" do
|
||||
user = insert(:user)
|
||||
{:ok, user} = User.ensure_keys_present(user)
|
||||
user_data = Pleroma.Web.ActivityPub.UserView.render("user.json", %{user: user})
|
||||
|
||||
{:ok, update} =
|
||||
ActivityPub.update(%{
|
||||
actor: user_data["id"],
|
||||
to: [user.follower_address],
|
||||
cc: [],
|
||||
object: user_data
|
||||
})
|
||||
|
||||
assert update.data["actor"] == user.ap_id
|
||||
assert update.data["to"] == [user.follower_address]
|
||||
assert embedded_object = update.data["object"]
|
||||
assert embedded_object["id"] == user_data["id"]
|
||||
assert embedded_object["type"] == user_data["type"]
|
||||
end
|
||||
end
|
||||
|
||||
test "returned pinned statuses" do
|
||||
Config.put([:instance, :max_pinned_statuses], 3)
|
||||
user = insert(:user)
|
||||
|
||||
{:ok, activity_one} = CommonAPI.post(user, %{status: "HI!!!"})
|
||||
{:ok, activity_two} = CommonAPI.post(user, %{status: "HI!!!"})
|
||||
{:ok, activity_three} = CommonAPI.post(user, %{status: "HI!!!"})
|
||||
|
||||
CommonAPI.pin(activity_one.id, user)
|
||||
user = refresh_record(user)
|
||||
|
||||
CommonAPI.pin(activity_two.id, user)
|
||||
user = refresh_record(user)
|
||||
|
||||
CommonAPI.pin(activity_three.id, user)
|
||||
user = refresh_record(user)
|
||||
|
||||
activities = ActivityPub.fetch_user_activities(user, nil, %{pinned: true})
|
||||
|
||||
assert 3 = length(activities)
|
||||
end
|
||||
|
||||
describe "flag/1" do
|
||||
setup do
|
||||
reporter = insert(:user)
|
||||
|
|
|
@ -78,6 +78,15 @@ test "it updates the user", %{user: user, update: update} do
|
|||
user = User.get_by_id(user.id)
|
||||
assert user.name == "new name!"
|
||||
end
|
||||
|
||||
test "it uses a given changeset to update", %{user: user, update: update} do
|
||||
changeset = Ecto.Changeset.change(user, %{default_scope: "direct"})
|
||||
|
||||
assert user.default_scope == "public"
|
||||
{:ok, _, _} = SideEffects.handle(update, user_update_changeset: changeset)
|
||||
user = User.get_by_id(user.id)
|
||||
assert user.default_scope == "direct"
|
||||
end
|
||||
end
|
||||
|
||||
describe "delete objects" do
|
||||
|
|
Loading…
Reference in a new issue