aboutsummaryrefslogtreecommitdiff
path: root/lib/pleroma/web/activity_pub
diff options
context:
space:
mode:
authorlain <lain@soykaf.club>2019-11-08 13:27:11 +0100
committerlain <lain@soykaf.club>2019-11-08 13:27:11 +0100
commitb22ee9d9666c49d1a3b1757b275e9d303eed4afc (patch)
treee7b4138a82c7382f2e2819f0a52481ec39cb12f3 /lib/pleroma/web/activity_pub
parentd7f9679ff2c9c4bd2b9967d7a32b5a4fe145305e (diff)
parent278674223d36f4d789dce92cd541c47b7e19b674 (diff)
downloadpleroma-b22ee9d9666c49d1a3b1757b275e9d303eed4afc.tar.gz
Merge remote-tracking branch 'origin/develop' into reactions
Diffstat (limited to 'lib/pleroma/web/activity_pub')
-rw-r--r--lib/pleroma/web/activity_pub/activity_pub.ex174
-rw-r--r--lib/pleroma/web/activity_pub/activity_pub_controller.ex10
-rw-r--r--lib/pleroma/web/activity_pub/mrf/anti_link_spam_policy.ex2
-rw-r--r--lib/pleroma/web/activity_pub/publisher.ex10
-rw-r--r--lib/pleroma/web/activity_pub/relay.ex25
-rw-r--r--lib/pleroma/web/activity_pub/transmogrifier.ex114
-rw-r--r--lib/pleroma/web/activity_pub/utils.ex98
-rw-r--r--lib/pleroma/web/activity_pub/views/user_view.ex31
-rw-r--r--lib/pleroma/web/activity_pub/visibility.ex5
9 files changed, 291 insertions, 178 deletions
diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex
index f92d5b398..3b75e9d85 100644
--- a/lib/pleroma/web/activity_pub/activity_pub.ex
+++ b/lib/pleroma/web/activity_pub/activity_pub.ex
@@ -7,6 +7,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
alias Pleroma.Activity.Ir.Topics
alias Pleroma.Config
alias Pleroma.Conversation
+ alias Pleroma.Conversation.Participation
alias Pleroma.Notification
alias Pleroma.Object
alias Pleroma.Object.Containment
@@ -68,7 +69,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
defp check_actor_is_active(actor) do
if not is_nil(actor) do
with user <- User.get_cached_by_ap_id(actor),
- false <- user.info.deactivated do
+ false <- user.deactivated do
true
else
_e -> false
@@ -131,7 +132,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
{:ok, map} <- MRF.filter(map),
{recipients, _, _} = get_recipients(map),
{:fake, false, map, recipients} <- {:fake, fake, map, recipients},
- :ok <- Containment.contain_child(map),
+ {:containment, :ok} <- {:containment, Containment.contain_child(map)},
{:ok, map, object} <- insert_full_object(map) do
{:ok, activity} =
Repo.insert(%Activity{
@@ -153,11 +154,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
Notification.create_notifications(activity)
- participations =
- activity
- |> Conversation.create_or_bump_for()
- |> get_participations()
-
+ conversation = create_or_bump_conversation(activity, map["actor"])
+ participations = get_participations(conversation)
stream_out(activity)
stream_out_participations(participations)
{:ok, activity}
@@ -182,7 +180,20 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
end
end
- defp get_participations({:ok, %{participations: participations}}), do: participations
+ defp create_or_bump_conversation(activity, actor) do
+ with {:ok, conversation} <- Conversation.create_or_bump_for(activity),
+ %User{} = user <- User.get_cached_by_ap_id(actor),
+ Participation.mark_as_read(user, conversation) do
+ {:ok, conversation}
+ end
+ end
+
+ defp get_participations({:ok, conversation}) do
+ conversation
+ |> Repo.preload(:participations, force: true)
+ |> Map.get(:participations)
+ end
+
defp get_participations(_), do: []
def stream_out_participations(participations) do
@@ -225,6 +236,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
# only accept false as false value
local = !(params[:local] == false)
published = params[:published]
+ quick_insert? = Pleroma.Config.get([:env]) == :benchmark
with create_data <-
make_create_data(
@@ -235,12 +247,14 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
{:fake, false, activity} <- {:fake, fake, activity},
_ <- increase_replies_count_if_reply(create_data),
_ <- increase_poll_votes_if_vote(create_data),
- # Changing note count prior to enqueuing federation task in order to avoid
- # race conditions on updating user.info
+ {:quick_insert, false, activity} <- {:quick_insert, quick_insert?, activity},
{:ok, _actor} <- increase_note_count_if_public(actor, activity),
:ok <- maybe_federate(activity) do
{:ok, activity}
else
+ {:quick_insert, true, activity} ->
+ {:ok, activity}
+
{:fake, true, activity} ->
{:ok, activity}
@@ -269,22 +283,21 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
end
end
- def accept(%{to: to, actor: actor, object: object} = params) do
- # only accept false as false value
- local = !(params[:local] == false)
+ def accept(params) do
+ accept_or_reject("Accept", params)
+ end
- with data <- %{"to" => to, "type" => "Accept", "actor" => actor.ap_id, "object" => object},
- {:ok, activity} <- insert(data, local),
- :ok <- maybe_federate(activity) do
- {:ok, activity}
- end
+ def reject(params) do
+ accept_or_reject("Reject", params)
end
- def reject(%{to: to, actor: actor, object: object} = params) do
- # only accept false as false value
- local = !(params[:local] == false)
+ def accept_or_reject(type, %{to: to, actor: actor, object: object} = params) do
+ local = Map.get(params, :local, true)
+ activity_id = Map.get(params, :activity_id, nil)
- with data <- %{"to" => to, "type" => "Reject", "actor" => actor.ap_id, "object" => object},
+ with data <-
+ %{"to" => to, "type" => type, "actor" => actor.ap_id, "object" => object}
+ |> Utils.maybe_put("id", activity_id),
{:ok, activity} <- insert(data, local),
:ok <- maybe_federate(activity) do
{:ok, activity}
@@ -435,23 +448,27 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
end
end
- def delete(%Object{data: %{"id" => id, "actor" => actor}} = object, local \\ true) do
+ def delete(%Object{data: %{"id" => id, "actor" => actor}} = object, options \\ []) do
+ local = Keyword.get(options, :local, true)
+ activity_id = Keyword.get(options, :activity_id, nil)
+ actor = Keyword.get(options, :actor, actor)
+
user = User.get_cached_by_ap_id(actor)
to = (object.data["to"] || []) ++ (object.data["cc"] || [])
with {:ok, object, activity} <- Object.delete(object),
- data <- %{
- "type" => "Delete",
- "actor" => actor,
- "object" => id,
- "to" => to,
- "deleted_activity_id" => activity && activity.id
- },
+ data <-
+ %{
+ "type" => "Delete",
+ "actor" => actor,
+ "object" => id,
+ "to" => to,
+ "deleted_activity_id" => activity && activity.id
+ }
+ |> maybe_put("id", activity_id),
{:ok, activity} <- insert(data, local, false),
stream_out_participations(object, user),
_ <- decrease_replies_count_if_reply(object),
- # Changing note count prior to enqueuing federation task in order to avoid
- # race conditions on updating user.info
{:ok, _actor} <- decrease_note_count_if_public(user, object),
:ok <- maybe_federate(activity) do
{:ok, activity}
@@ -512,7 +529,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
with flag_data <- make_flag_data(params, additional),
{:ok, activity} <- insert(flag_data, local),
- :ok <- maybe_federate(activity) do
+ {:ok, stripped_activity} <- strip_report_status_data(activity),
+ :ok <- maybe_federate(stripped_activity) do
Enum.each(User.all_superusers(), fn superuser ->
superuser
|> Pleroma.Emails.AdminEmail.report(actor, account, statuses, content)
@@ -527,7 +545,9 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
public = [Pleroma.Constants.as_public()]
recipients =
- if opts["user"], do: [opts["user"].ap_id | opts["user"].following] ++ public, else: public
+ if opts["user"],
+ do: [opts["user"].ap_id | User.following(opts["user"])] ++ public,
+ else: public
from(activity in Activity)
|> maybe_preload_objects(opts)
@@ -617,12 +637,55 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
defp restrict_visibility(query, _visibility), do: query
+ defp exclude_visibility(query, %{"exclude_visibilities" => visibility})
+ when is_list(visibility) do
+ if Enum.all?(visibility, &(&1 in @valid_visibilities)) do
+ from(
+ a in query,
+ where:
+ not fragment(
+ "activity_visibility(?, ?, ?) = ANY (?)",
+ a.actor,
+ a.recipients,
+ a.data,
+ ^visibility
+ )
+ )
+ else
+ Logger.error("Could not exclude visibility to #{visibility}")
+ query
+ end
+ end
+
+ defp exclude_visibility(query, %{"exclude_visibilities" => visibility})
+ when visibility in @valid_visibilities do
+ from(
+ a in query,
+ where:
+ not fragment(
+ "activity_visibility(?, ?, ?) = ?",
+ a.actor,
+ a.recipients,
+ a.data,
+ ^visibility
+ )
+ )
+ end
+
+ defp exclude_visibility(query, %{"exclude_visibilities" => visibility})
+ when visibility not in @valid_visibilities do
+ Logger.error("Could not exclude visibility to #{visibility}")
+ query
+ end
+
+ defp exclude_visibility(query, _visibility), do: query
+
defp restrict_thread_visibility(query, _, %{skip_thread_containment: true} = _),
do: query
defp restrict_thread_visibility(
query,
- %{"user" => %User{info: %{skip_thread_containment: true}}},
+ %{"user" => %User{skip_thread_containment: true}},
_
),
do: query
@@ -660,7 +723,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|> Map.put("user", reading_user)
|> Map.put("actor_id", user.ap_id)
|> Map.put("whole_db", true)
- |> Map.put("pinned_activity_ids", user.info.pinned_activities)
+ |> Map.put("pinned_activity_ids", user.pinned_activities)
recipients =
user_activities_recipients(%{
@@ -678,7 +741,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
defp user_activities_recipients(%{"reading_user" => reading_user}) do
if reading_user do
- [Pleroma.Constants.as_public()] ++ [reading_user.ap_id | reading_user.following]
+ [Pleroma.Constants.as_public()] ++ [reading_user.ap_id | User.following(reading_user)]
else
[Pleroma.Constants.as_public()]
end
@@ -821,8 +884,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
defp restrict_muted(query, %{"with_muted" => val}) when val in [true, "true", "1"], do: query
- defp restrict_muted(query, %{"muting_user" => %User{info: info}} = opts) do
- mutes = info.mutes
+ defp restrict_muted(query, %{"muting_user" => %User{} = user} = opts) do
+ mutes = user.mutes
query =
from([activity] in query,
@@ -839,9 +902,9 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
defp restrict_muted(query, _), do: query
- defp restrict_blocked(query, %{"blocking_user" => %User{info: info}}) do
- blocks = info.blocks || []
- domain_blocks = info.domain_blocks || []
+ defp restrict_blocked(query, %{"blocking_user" => %User{} = user}) do
+ blocks = user.blocks || []
+ domain_blocks = user.domain_blocks || []
query =
if has_named_binding?(query, :object), do: query, else: Activity.with_joined_object(query)
@@ -882,8 +945,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
defp restrict_pinned(query, _), do: query
- defp restrict_muted_reblogs(query, %{"muting_user" => %User{info: info}}) do
- muted_reblogs = info.muted_reblogs || []
+ defp restrict_muted_reblogs(query, %{"muting_user" => %User{} = user}) do
+ muted_reblogs = user.muted_reblogs || []
from(
activity in query,
@@ -981,6 +1044,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|> restrict_muted_reblogs(opts)
|> Activity.restrict_deactivated_users()
|> exclude_poll_votes(opts)
+ |> exclude_visibility(opts)
end
def fetch_activities(recipients, opts \\ %{}, pagination \\ :keyset) do
@@ -1067,17 +1131,17 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
locked = data["manuallyApprovesFollowers"] || false
data = Transmogrifier.maybe_fix_user_object(data)
discoverable = data["discoverable"] || false
+ invisible = data["invisible"] || false
user_data = %{
ap_id: data["id"],
- info: %{
- ap_enabled: true,
- source_data: data,
- banner: banner,
- fields: fields,
- locked: locked,
- discoverable: discoverable
- },
+ ap_enabled: true,
+ source_data: data,
+ banner: banner,
+ fields: fields,
+ locked: locked,
+ discoverable: discoverable,
+ invisible: invisible,
avatar: avatar,
name: data["name"],
follower_address: data["followers"],
@@ -1129,7 +1193,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
with {:enabled, true} <-
{:enabled, Pleroma.Config.get([:instance, :external_user_synchronization])},
{:ok, info} <- fetch_follow_information_for_user(data) do
- info = Map.merge(data.info, info)
+ info = Map.merge(data[:info] || %{}, info)
Map.put(data, :info, info)
else
{:enabled, false} ->
@@ -1180,7 +1244,9 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
data <- maybe_update_follow_information(data) do
{:ok, data}
else
- e -> Logger.error("Could not decode user at fetch #{ap_id}, #{inspect(e)}")
+ e ->
+ Logger.error("Could not decode user at fetch #{ap_id}, #{inspect(e)}")
+ {:error, e}
end
end
diff --git a/lib/pleroma/web/activity_pub/activity_pub_controller.ex b/lib/pleroma/web/activity_pub/activity_pub_controller.ex
index 080030eb5..b2cd965fe 100644
--- a/lib/pleroma/web/activity_pub/activity_pub_controller.ex
+++ b/lib/pleroma/web/activity_pub/activity_pub_controller.ex
@@ -137,7 +137,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
with %User{} = user <- User.get_cached_by_nickname(nickname),
{user, for_user} <- ensure_user_keys_present_and_maybe_refresh_for_user(user, for_user),
{:show_follows, true} <-
- {:show_follows, (for_user && for_user == user) || !user.info.hide_follows} do
+ {:show_follows, (for_user && for_user == user) || !user.hide_follows} do
{page, _} = Integer.parse(page)
conn
@@ -174,7 +174,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
with %User{} = user <- User.get_cached_by_nickname(nickname),
{user, for_user} <- ensure_user_keys_present_and_maybe_refresh_for_user(user, for_user),
{:show_followers, true} <-
- {:show_followers, (for_user && for_user == user) || !user.info.hide_followers} do
+ {:show_followers, (for_user && for_user == user) || !user.hide_followers} do
{page, _} = Integer.parse(page)
conn
@@ -319,12 +319,12 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
when page? in [true, "true"] do
activities =
if params["max_id"] do
- ActivityPub.fetch_activities([user.ap_id | user.following], %{
+ ActivityPub.fetch_activities([user.ap_id | User.following(user)], %{
"max_id" => params["max_id"],
"limit" => 10
})
else
- ActivityPub.fetch_activities([user.ap_id | user.following], %{"limit" => 10})
+ ActivityPub.fetch_activities([user.ap_id | User.following(user)], %{"limit" => 10})
end
conn
@@ -387,7 +387,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
def handle_user_activity(user, %{"type" => "Delete"} = params) do
with %Object{} = object <- Object.normalize(params["object"]),
- true <- user.info.is_moderator || user.ap_id == object.data["actor"],
+ true <- user.is_moderator || user.ap_id == object.data["actor"],
{:ok, delete} <- ActivityPub.delete(object) do
{:ok, delete}
else
diff --git a/lib/pleroma/web/activity_pub/mrf/anti_link_spam_policy.ex b/lib/pleroma/web/activity_pub/mrf/anti_link_spam_policy.ex
index b90193ca0..8abe18e29 100644
--- a/lib/pleroma/web/activity_pub/mrf/anti_link_spam_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/anti_link_spam_policy.ex
@@ -11,7 +11,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiLinkSpamPolicy do
# has the user successfully posted before?
defp old_user?(%User{} = u) do
- u.info.note_count > 0 || u.info.follower_count > 0
+ u.note_count > 0 || u.follower_count > 0
end
# does the post contain links?
diff --git a/lib/pleroma/web/activity_pub/publisher.ex b/lib/pleroma/web/activity_pub/publisher.ex
index 3866dacee..4ea37fc7b 100644
--- a/lib/pleroma/web/activity_pub/publisher.ex
+++ b/lib/pleroma/web/activity_pub/publisher.ex
@@ -129,7 +129,7 @@ defmodule Pleroma.Web.ActivityPub.Publisher do
[]
end
- Pleroma.Web.Salmon.remote_users(actor, activity) ++ followers ++ fetchers
+ Pleroma.Web.Federator.Publisher.remote_users(actor, activity) ++ followers ++ fetchers
end
defp get_cc_ap_ids(ap_id, recipients) do
@@ -140,7 +140,7 @@ defmodule Pleroma.Web.ActivityPub.Publisher do
|> Enum.map(& &1.ap_id)
end
- defp maybe_use_sharedinbox(%User{info: %{source_data: data}}),
+ defp maybe_use_sharedinbox(%User{source_data: data}),
do: (is_map(data["endpoints"]) && Map.get(data["endpoints"], "sharedInbox")) || data["inbox"]
@doc """
@@ -156,7 +156,7 @@ defmodule Pleroma.Web.ActivityPub.Publisher do
"""
def determine_inbox(
%Activity{data: activity_data},
- %User{info: %{source_data: data}} = user
+ %User{source_data: data} = user
) do
to = activity_data["to"] || []
cc = activity_data["cc"] || []
@@ -190,12 +190,12 @@ defmodule Pleroma.Web.ActivityPub.Publisher do
recipients
|> Enum.filter(&User.ap_enabled?/1)
- |> Enum.map(fn %{info: %{source_data: data}} -> data["inbox"] end)
+ |> Enum.map(fn %{source_data: data} -> data["inbox"] end)
|> Enum.filter(fn inbox -> should_federate?(inbox, public) end)
|> Instances.filter_reachable()
|> Enum.each(fn {inbox, unreachable_since} ->
%User{ap_id: ap_id} =
- Enum.find(recipients, fn %{info: %{source_data: data}} -> data["inbox"] == inbox end)
+ Enum.find(recipients, fn %{source_data: data} -> data["inbox"] == inbox end)
# Get all the recipients on the same host and add them to cc. Otherwise, a remote
# instance would only accept a first message for the first recipient and ignore the rest.
diff --git a/lib/pleroma/web/activity_pub/relay.ex b/lib/pleroma/web/activity_pub/relay.ex
index c2ac38907..fc2619680 100644
--- a/lib/pleroma/web/activity_pub/relay.ex
+++ b/lib/pleroma/web/activity_pub/relay.ex
@@ -10,8 +10,16 @@ defmodule Pleroma.Web.ActivityPub.Relay do
require Logger
def get_actor do
+ actor =
+ relay_ap_id()
+ |> User.get_or_create_service_actor_by_ap_id()
+
+ {:ok, actor} = User.set_invisible(actor, true)
+ actor
+ end
+
+ def relay_ap_id do
"#{Pleroma.Web.Endpoint.url()}/relay"
- |> User.get_or_create_service_actor_by_ap_id()
end
@spec follow(String.t()) :: {:ok, Activity.t()} | {:error, any()}
@@ -51,6 +59,21 @@ defmodule Pleroma.Web.ActivityPub.Relay do
def publish(_), do: {:error, "Not implemented"}
+ @spec list() :: {:ok, [String.t()]} | {:error, any()}
+ def list do
+ with %User{} = user <- get_actor() do
+ list =
+ user
+ |> User.following()
+ |> Enum.map(fn entry -> URI.parse(entry).host end)
+ |> Enum.uniq()
+
+ {:ok, list}
+ else
+ error -> format_error(error)
+ end
+ end
+
defp format_error({:error, error}), do: format_error(error)
defp format_error(error) do
diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex
index 2c1f01c18..15612545b 100644
--- a/lib/pleroma/web/activity_pub/transmogrifier.ex
+++ b/lib/pleroma/web/activity_pub/transmogrifier.ex
@@ -7,6 +7,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
A module to handle coding from internal to wire ActivityPub and back.
"""
alias Pleroma.Activity
+ alias Pleroma.FollowingRelationship
alias Pleroma.Object
alias Pleroma.Object.Containment
alias Pleroma.Repo
@@ -474,7 +475,8 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
{_, false} <- {:user_locked, User.locked?(followed)},
{_, {:ok, follower}} <- {:follow, User.follow(follower, followed)},
{_, {:ok, _}} <-
- {:follow_state_update, Utils.update_follow_state_for_all(activity, "accept")} do
+ {:follow_state_update, Utils.update_follow_state_for_all(activity, "accept")},
+ {:ok, _relationship} <- FollowingRelationship.update(follower, followed, "accept") do
ActivityPub.accept(%{
to: [follower.ap_id],
actor: followed,
@@ -484,6 +486,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
else
{:user_blocked, true} ->
{:ok, _} = Utils.update_follow_state_for_all(activity, "reject")
+ {:ok, _relationship} = FollowingRelationship.update(follower, followed, "reject")
ActivityPub.reject(%{
to: [follower.ap_id],
@@ -494,6 +497,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
{:follow, {:error, _}} ->
{:ok, _} = Utils.update_follow_state_for_all(activity, "reject")
+ {:ok, _relationship} = FollowingRelationship.update(follower, followed, "reject")
ActivityPub.reject(%{
to: [follower.ap_id],
@@ -503,6 +507,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
})
{:user_locked, true} ->
+ {:ok, _relationship} = FollowingRelationship.update(follower, followed, "pending")
:noop
end
@@ -514,7 +519,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
end
def handle_incoming(
- %{"type" => "Accept", "object" => follow_object, "actor" => _actor, "id" => _id} = data,
+ %{"type" => "Accept", "object" => follow_object, "actor" => _actor, "id" => id} = data,
_options
) do
with actor <- Containment.get_actor(data),
@@ -522,13 +527,14 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
{:ok, follow_activity} <- get_follow_activity(follow_object, followed),
{:ok, follow_activity} <- Utils.update_follow_state_for_all(follow_activity, "accept"),
%User{local: true} = follower <- User.get_cached_by_ap_id(follow_activity.data["actor"]),
- {:ok, _follower} = User.follow(follower, followed) do
+ {:ok, _relationship} <- FollowingRelationship.update(follower, followed, "accept") do
ActivityPub.accept(%{
to: follow_activity.data["to"],
type: "Accept",
actor: followed,
object: follow_activity.data["id"],
- local: false
+ local: false,
+ activity_id: id
})
else
_e -> :error
@@ -536,7 +542,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
end
def handle_incoming(
- %{"type" => "Reject", "object" => follow_object, "actor" => _actor, "id" => _id} = data,
+ %{"type" => "Reject", "object" => follow_object, "actor" => _actor, "id" => id} = data,
_options
) do
with actor <- Containment.get_actor(data),
@@ -544,16 +550,16 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
{:ok, follow_activity} <- get_follow_activity(follow_object, followed),
{:ok, follow_activity} <- Utils.update_follow_state_for_all(follow_activity, "reject"),
%User{local: true} = follower <- User.get_cached_by_ap_id(follow_activity.data["actor"]),
+ {:ok, _relationship} <- FollowingRelationship.update(follower, followed, "reject"),
{:ok, activity} <-
ActivityPub.reject(%{
to: follow_activity.data["to"],
type: "Reject",
actor: followed,
object: follow_activity.data["id"],
- local: false
+ local: false,
+ activity_id: id
}) do
- User.unfollow(follower, followed)
-
{:ok, activity}
else
_e -> :error
@@ -643,13 +649,18 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
data,
_options
)
- when object_type in ["Person", "Application", "Service", "Organization"] do
+ when object_type in [
+ "Person",
+ "Application",
+ "Service",
+ "Organization"
+ ] do
with %User{ap_id: ^actor_id} = actor <- User.get_cached_by_ap_id(object["id"]) do
{:ok, new_user_data} = ActivityPub.user_data_from_user_object(object)
- banner = new_user_data[:info][:banner]
- locked = new_user_data[:info][:locked] || false
- attachment = get_in(new_user_data, [:info, :source_data, "attachment"]) || []
+ locked = new_user_data[:locked] || false
+ attachment = get_in(new_user_data, [:source_data, "attachment"]) || []
+ invisible = new_user_data[:invisible] || false
fields =
attachment
@@ -658,8 +669,10 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
update_data =
new_user_data
- |> Map.take([:name, :bio, :avatar])
- |> Map.put(:info, %{banner: banner, locked: locked, fields: fields})
+ |> Map.take([:avatar, :banner, :bio, :name])
+ |> Map.put(:fields, fields)
+ |> Map.put(:locked, locked)
+ |> Map.put(:invisible, invisible)
actor
|> User.upgrade_changeset(update_data, true)
@@ -686,7 +699,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
# an error or a tombstone. This would allow us to verify that a deletion actually took
# place.
def handle_incoming(
- %{"type" => "Delete", "object" => object_id, "actor" => actor, "id" => _id} = data,
+ %{"type" => "Delete", "object" => object_id, "actor" => actor, "id" => id} = data,
_options
) do
object_id = Utils.get_ap_id(object_id)
@@ -695,7 +708,8 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
{:ok, %User{} = actor} <- User.get_or_fetch_by_ap_id(actor),
{:ok, object} <- get_obj_helper(object_id),
:ok <- Containment.contain_origin(actor.ap_id, object.data),
- {:ok, activity} <- ActivityPub.delete(object, false) do
+ {:ok, activity} <-
+ ActivityPub.delete(object, local: false, activity_id: id, actor: actor.ap_id) do
{:ok, activity}
else
nil ->
@@ -1047,7 +1061,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
%{"type" => "Mention", "href" => ap_id, "name" => "@#{nickname}"}
end
- def take_emoji_tags(%User{info: %{emoji: emoji} = _user_info} = _user) do
+ def take_emoji_tags(%User{emoji: emoji}) do
emoji
|> Enum.flat_map(&Map.to_list/1)
|> Enum.map(&build_emoji_tag/1)
@@ -1122,45 +1136,22 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
# we pass a fake user so that the followers collection is stripped away
old_follower_address = User.ap_followers(%User{nickname: user.nickname})
- q =
- from(
- u in User,
- where: ^old_follower_address in u.following,
- update: [
- set: [
- following:
- fragment(
- "array_replace(?,?,?)",
- u.following,
- ^old_follower_address,
- ^user.follower_address
- )
- ]
- ]
- )
-
- Repo.update_all(q, [])
-
- maybe_retire_websub(user.ap_id)
-
- q =
- from(
- a in Activity,
- where: ^old_follower_address in a.recipients,
- update: [
- set: [
- recipients:
- fragment(
- "array_replace(?,?,?)",
- a.recipients,
- ^old_follower_address,
- ^user.follower_address
- )
- ]
+ from(
+ a in Activity,
+ where: ^old_follower_address in a.recipients,
+ update: [
+ set: [
+ recipients:
+ fragment(
+ "array_replace(?,?,?)",
+ a.recipients,
+ ^old_follower_address,
+ ^user.follower_address
+ )
]
- )
-
- Repo.update_all(q, [])
+ ]
+ )
+ |> Repo.update_all([])
end
def upgrade_user_from_ap_id(ap_id) do
@@ -1185,19 +1176,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|> User.update_and_set_cache()
end
- def maybe_retire_websub(ap_id) do
- # some sanity checks
- if is_binary(ap_id) && String.length(ap_id) > 8 do
- q =
- from(
- ws in Pleroma.Web.Websub.WebsubClientSubscription,
- where: fragment("? like ?", ws.topic, ^"#{ap_id}%")
- )
-
- Repo.delete_all(q)
- end
- end
-
def maybe_fix_user_url(%{"url" => url} = data) when is_map(url) do
Map.put(data, "url", url["href"])
end
diff --git a/lib/pleroma/web/activity_pub/utils.ex b/lib/pleroma/web/activity_pub/utils.ex
index 6263f206b..91cfa2194 100644
--- a/lib/pleroma/web/activity_pub/utils.ex
+++ b/lib/pleroma/web/activity_pub/utils.ex
@@ -12,6 +12,7 @@ defmodule Pleroma.Web.ActivityPub.Utils do
alias Pleroma.User
alias Pleroma.Web
alias Pleroma.Web.ActivityPub.Visibility
+ alias Pleroma.Web.AdminAPI.AccountView
alias Pleroma.Web.Endpoint
alias Pleroma.Web.Router.Helpers
@@ -21,6 +22,7 @@ defmodule Pleroma.Web.ActivityPub.Utils do
require Pleroma.Constants
@supported_object_types ["Article", "Note", "Video", "Page", "Question", "Answer", "Audio"]
+ @strip_status_report_states ~w(closed resolved)
@supported_report_states ~w(open closed resolved)
@valid_visibilities ~w(public unlisted private direct)
@@ -49,26 +51,28 @@ defmodule Pleroma.Web.ActivityPub.Utils do
def determine_explicit_mentions(_), do: []
- @spec recipient_in_collection(any(), any()) :: boolean()
- defp recipient_in_collection(ap_id, coll) when is_binary(coll), do: ap_id == coll
- defp recipient_in_collection(ap_id, coll) when is_list(coll), do: ap_id in coll
- defp recipient_in_collection(_, _), do: false
+ @spec label_in_collection?(any(), any()) :: boolean()
+ defp label_in_collection?(ap_id, coll) when is_binary(coll), do: ap_id == coll
+ defp label_in_collection?(ap_id, coll) when is_list(coll), do: ap_id in coll
+ defp label_in_collection?(_, _), do: false
+
+ @spec label_in_message?(String.t(), map()) :: boolean()
+ def label_in_message?(label, params),
+ do:
+ [params["to"], params["cc"], params["bto"], params["bcc"]]
+ |> Enum.any?(&label_in_collection?(label, &1))
+
+ @spec unaddressed_message?(map()) :: boolean()
+ def unaddressed_message?(params),
+ do:
+ [params["to"], params["cc"], params["bto"], params["bcc"]]
+ |> Enum.all?(&is_nil(&1))
@spec recipient_in_message(User.t(), User.t(), map()) :: boolean()
- def recipient_in_message(%User{ap_id: ap_id} = recipient, %User{} = actor, params) do
- addresses = [params["to"], params["cc"], params["bto"], params["bcc"]]
-
- cond do
- Enum.any?(addresses, &recipient_in_collection(ap_id, &1)) -> true
- # if the message is unaddressed at all, then assume it is directly addressed
- # to the recipient
- Enum.all?(addresses, &is_nil(&1)) -> true
- # if the message is sent from somebody the user is following, then assume it
- # is addressed to the recipient
- User.following?(recipient, actor) -> true
- true -> false
- end
- end
+ def recipient_in_message(%User{ap_id: ap_id} = recipient, %User{} = actor, params),
+ do:
+ label_in_message?(ap_id, params) || unaddressed_message?(params) ||
+ User.following?(recipient, actor)
defp extract_list(target) when is_binary(target), do: [target]
defp extract_list(lst) when is_list(lst), do: lst
@@ -76,8 +80,8 @@ defmodule Pleroma.Web.ActivityPub.Utils do
def maybe_splice_recipient(ap_id, params) do
need_splice? =
- !recipient_in_collection(ap_id, params["to"]) &&
- !recipient_in_collection(ap_id, params["cc"])
+ !label_in_collection?(ap_id, params["to"]) &&
+ !label_in_collection?(ap_id, params["cc"])
if need_splice? do
cc_list = extract_list(params["cc"])
@@ -582,10 +586,14 @@ defmodule Pleroma.Web.ActivityPub.Utils do
%Activity{data: %{"actor" => actor}},
object
) do
- announcements = take_announcements(object)
+ unless actor |> User.get_cached_by_ap_id() |> User.invisible?() do
+ announcements = take_announcements(object)
- with announcements <- Enum.uniq([actor | announcements]) do
- update_element_in_object("announcement", announcements, object)
+ with announcements <- Enum.uniq([actor | announcements]) do
+ update_element_in_object("announcement", announcements, object)
+ end
+ else
+ {:ok, object}
end
end
@@ -699,10 +707,24 @@ defmodule Pleroma.Web.ActivityPub.Utils do
defp build_flag_object(%{account: account, statuses: statuses} = _) do
[account.ap_id] ++
- Enum.map(statuses || [], fn
- %Activity{} = act -> act.data["id"]
- act when is_map(act) -> act["id"]
- act when is_binary(act) -> act
+ Enum.map(statuses || [], fn act ->
+ id =
+ case act do
+ %Activity{} = act -> act.data["id"]
+ act when is_map(act) -> act["id"]
+ act when is_binary(act) -> act
+ end
+
+ activity = Activity.get_by_ap_id_with_object(id)
+ actor = User.get_by_ap_id(activity.object.data["actor"])
+
+ %{
+ "type" => "Note",
+ "id" => activity.data["id"],
+ "content" => activity.object.data["content"],
+ "published" => activity.object.data["published"],
+ "actor" => AccountView.render("show.json", %{user: actor})
+ }
end)
end
@@ -749,6 +771,20 @@ defmodule Pleroma.Web.ActivityPub.Utils do
#### Report-related helpers
+ def update_report_state(%Activity{} = activity, state)
+ when state in @strip_status_report_states do
+ {:ok, stripped_activity} = strip_report_status_data(activity)
+
+ new_data =
+ activity.data
+ |> Map.put("state", state)
+ |> Map.put("object", stripped_activity.data["object"])
+
+ activity
+ |> Changeset.change(data: new_data)
+ |> Repo.update()
+ end
+
def update_report_state(%Activity{} = activity, state) when state in @supported_report_states do
new_data = Map.put(activity.data, "state", state)
@@ -759,6 +795,14 @@ defmodule Pleroma.Web.ActivityPub.Utils do
def update_report_state(_, _), do: {:error, "Unsupported state"}
+ def strip_report_status_data(activity) do
+ [actor | reported_activities] = activity.data["object"]
+ stripped_activities = Enum.map(reported_activities, & &1["id"])
+ new_data = put_in(activity.data, ["object"], [actor | stripped_activities])
+
+ {:ok, %{activity | data: new_data}}
+ end
+
def update_activity_visibility(activity, visibility) when visibility in @valid_visibilities do
[to, cc, recipients] =
activity
diff --git a/lib/pleroma/web/activity_pub/views/user_view.ex b/lib/pleroma/web/activity_pub/views/user_view.ex
index 9b39d1629..cf08045c9 100644
--- a/lib/pleroma/web/activity_pub/views/user_view.ex
+++ b/lib/pleroma/web/activity_pub/views/user_view.ex
@@ -55,7 +55,8 @@ defmodule Pleroma.Web.ActivityPub.UserView do
"owner" => user.ap_id,
"publicKeyPem" => public_key
},
- "endpoints" => endpoints
+ "endpoints" => endpoints,
+ "invisible" => User.invisible?(user)
}
|> Map.merge(Utils.make_json_ld_header())
end
@@ -78,8 +79,8 @@ defmodule Pleroma.Web.ActivityPub.UserView do
emoji_tags = Transmogrifier.take_emoji_tags(user)
fields =
- user.info
- |> User.Info.fields()
+ user
+ |> User.fields()
|> Enum.map(fn %{"name" => name, "value" => value} ->
%{
"name" => Pleroma.HTML.strip_tags(name),
@@ -99,7 +100,7 @@ defmodule Pleroma.Web.ActivityPub.UserView do
"name" => user.name,
"summary" => user.bio,
"url" => user.ap_id,
- "manuallyApprovesFollowers" => user.info.locked,
+ "manuallyApprovesFollowers" => user.locked,
"publicKey" => %{
"id" => "#{user.ap_id}#main-key",
"owner" => user.ap_id,
@@ -107,8 +108,8 @@ defmodule Pleroma.Web.ActivityPub.UserView do
},
"endpoints" => endpoints,
"attachment" => fields,
- "tag" => (user.info.source_data["tag"] || []) ++ emoji_tags,
- "discoverable" => user.info.discoverable
+ "tag" => (user.source_data["tag"] || []) ++ emoji_tags,
+ "discoverable" => user.discoverable
}
|> Map.merge(maybe_make_image(&User.avatar_url/2, "icon", user))
|> Map.merge(maybe_make_image(&User.banner_url/2, "image", user))
@@ -116,8 +117,8 @@ defmodule Pleroma.Web.ActivityPub.UserView do
end
def render("following.json", %{user: user, page: page} = opts) do
- showing_items = (opts[:for] && opts[:for] == user) || !user.info.hide_follows
- showing_count = showing_items || !user.info.hide_follows_count
+ showing_items = (opts[:for] && opts[:for] == user) || !user.hide_follows
+ showing_count = showing_items || !user.hide_follows_count
query = User.get_friends_query(user)
query = from(user in query, select: [:ap_id])
@@ -135,8 +136,8 @@ defmodule Pleroma.Web.ActivityPub.UserView do
end
def render("following.json", %{user: user} = opts) do
- showing_items = (opts[:for] && opts[:for] == user) || !user.info.hide_follows
- showing_count = showing_items || !user.info.hide_follows_count
+ showing_items = (opts[:for] && opts[:for] == user) || !user.hide_follows
+ showing_count = showing_items || !user.hide_follows_count
query = User.get_friends_query(user)
query = from(user in query, select: [:ap_id])
@@ -155,7 +156,7 @@ defmodule Pleroma.Web.ActivityPub.UserView do
"totalItems" => total,
"first" =>
if showing_items do
- collection(following, "#{user.ap_id}/following", 1, !user.info.hide_follows)
+ collection(following, "#{user.ap_id}/following", 1, !user.hide_follows)
else
"#{user.ap_id}/following?page=1"
end
@@ -164,8 +165,8 @@ defmodule Pleroma.Web.ActivityPub.UserView do
end
def render("followers.json", %{user: user, page: page} = opts) do
- showing_items = (opts[:for] && opts[:for] == user) || !user.info.hide_followers
- showing_count = showing_items || !user.info.hide_followers_count
+ showing_items = (opts[:for] && opts[:for] == user) || !user.hide_followers
+ showing_count = showing_items || !user.hide_followers_count
query = User.get_followers_query(user)
query = from(user in query, select: [:ap_id])
@@ -183,8 +184,8 @@ defmodule Pleroma.Web.ActivityPub.UserView do
end
def render("followers.json", %{user: user} = opts) do
- showing_items = (opts[:for] && opts[:for] == user) || !user.info.hide_followers
- showing_count = showing_items || !user.info.hide_followers_count
+ showing_items = (opts[:for] && opts[:for] == user) || !user.hide_followers
+ showing_count = showing_items || !user.hide_followers_count
query = User.get_followers_query(user)
query = from(user in query, select: [:ap_id])
diff --git a/lib/pleroma/web/activity_pub/visibility.ex b/lib/pleroma/web/activity_pub/visibility.ex
index 270d0fa02..cd4097493 100644
--- a/lib/pleroma/web/activity_pub/visibility.ex
+++ b/lib/pleroma/web/activity_pub/visibility.ex
@@ -7,6 +7,7 @@ defmodule Pleroma.Web.ActivityPub.Visibility do
alias Pleroma.Object
alias Pleroma.Repo
alias Pleroma.User
+ alias Pleroma.Web.ActivityPub.Utils
require Pleroma.Constants
@@ -15,7 +16,7 @@ defmodule Pleroma.Web.ActivityPub.Visibility do
def is_public?(%Object{data: data}), do: is_public?(data)
def is_public?(%Activity{data: data}), do: is_public?(data)
def is_public?(%{"directMessage" => true}), do: false
- def is_public?(data), do: Pleroma.Constants.as_public() in (data["to"] ++ (data["cc"] || []))
+ def is_public?(data), do: Utils.label_in_message?(Pleroma.Constants.as_public(), data)
def is_private?(activity) do
with false <- is_public?(activity),
@@ -58,7 +59,7 @@ defmodule Pleroma.Web.ActivityPub.Visibility do
end
def visible_for_user?(activity, user) do
- x = [user.ap_id | user.following]
+ x = [user.ap_id | User.following(user)]
y = [activity.actor] ++ activity.data["to"] ++ (activity.data["cc"] || [])
visible_for_user?(activity, nil) || Enum.any?(x, &(&1 in y))
end