summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/mix/tasks/pleroma/database.ex10
-rw-r--r--lib/mix/tasks/pleroma/test_runner.ex25
-rw-r--r--lib/pleroma/ecto_enums.ex8
-rw-r--r--lib/pleroma/emails/mailer.ex3
-rw-r--r--lib/pleroma/emails/user_email.ex35
-rw-r--r--lib/pleroma/filter.ex11
-rw-r--r--lib/pleroma/instances/instance.ex3
-rw-r--r--lib/pleroma/mfa/token.ex13
-rw-r--r--lib/pleroma/object.ex3
-rw-r--r--lib/pleroma/object/fetcher.ex38
-rw-r--r--lib/pleroma/search.ex6
-rw-r--r--lib/pleroma/user.ex21
-rw-r--r--lib/pleroma/user/backup.ex360
-rw-r--r--lib/pleroma/user/import.ex30
-rw-r--r--lib/pleroma/web/activity_pub/activity_pub.ex18
-rw-r--r--lib/pleroma/web/activity_pub/mrf/anti_followbot_policy.ex8
-rw-r--r--lib/pleroma/web/activity_pub/mrf/anti_link_spam_policy.ex10
-rw-r--r--lib/pleroma/web/activity_pub/mrf/anti_mention_spam_policy.ex8
-rw-r--r--lib/pleroma/web/activity_pub/mrf/dnsrbl_policy.ex14
-rw-r--r--lib/pleroma/web/activity_pub/mrf/drop_policy.ex6
-rw-r--r--lib/pleroma/web/activity_pub/mrf/emoji_policy.ex30
-rw-r--r--lib/pleroma/web/activity_pub/mrf/ensure_re_prepended.ex14
-rw-r--r--lib/pleroma/web/activity_pub/mrf/fo_direct_reply.ex53
-rw-r--r--lib/pleroma/web/activity_pub/mrf/follow_bot_policy.ex20
-rw-r--r--lib/pleroma/web/activity_pub/mrf/force_bot_unlisted_policy.ex12
-rw-r--r--lib/pleroma/web/activity_pub/mrf/force_mention.ex2
-rw-r--r--lib/pleroma/web/activity_pub/mrf/force_mentions_in_content.ex12
-rw-r--r--lib/pleroma/web/activity_pub/mrf/hashtag_policy.ex51
-rw-r--r--lib/pleroma/web/activity_pub/mrf/hellthread_policy.ex54
-rw-r--r--lib/pleroma/web/activity_pub/mrf/inline_quote_policy.ex4
-rw-r--r--lib/pleroma/web/activity_pub/mrf/keyword_policy.ex48
-rw-r--r--lib/pleroma/web/activity_pub/mrf/media_proxy_warming_policy.ex10
-rw-r--r--lib/pleroma/web/activity_pub/mrf/mention_policy.ex12
-rw-r--r--lib/pleroma/web/activity_pub/mrf/no_empty_policy.ex14
-rw-r--r--lib/pleroma/web/activity_pub/mrf/no_op_policy.ex4
-rw-r--r--lib/pleroma/web/activity_pub/mrf/no_placeholder_text_policy.ex8
-rw-r--r--lib/pleroma/web/activity_pub/mrf/normalize_markup.ex10
-rw-r--r--lib/pleroma/web/activity_pub/mrf/nsfw_api_policy.ex48
-rw-r--r--lib/pleroma/web/activity_pub/mrf/object_age_policy.ex58
-rw-r--r--lib/pleroma/web/activity_pub/mrf/policy.ex2
-rw-r--r--lib/pleroma/web/activity_pub/mrf/quiet_reply.ex60
-rw-r--r--lib/pleroma/web/activity_pub/mrf/quote_to_link_tag_policy.ex10
-rw-r--r--lib/pleroma/web/activity_pub/mrf/simple_policy.ex150
-rw-r--r--lib/pleroma/web/activity_pub/mrf/steal_emoji_policy.ex6
-rw-r--r--lib/pleroma/web/activity_pub/mrf/subchain_policy.ex10
-rw-r--r--lib/pleroma/web/activity_pub/mrf/tag_policy.ex62
-rw-r--r--lib/pleroma/web/activity_pub/mrf/user_allow_list_policy.ex12
-rw-r--r--lib/pleroma/web/activity_pub/mrf/vocabulary_policy.ex30
-rw-r--r--lib/pleroma/web/activity_pub/object_validators/accept_reject_validator.ex2
-rw-r--r--lib/pleroma/web/activity_pub/object_validators/block_validator.ex2
-rw-r--r--lib/pleroma/web/activity_pub/object_validators/follow_validator.ex2
-rw-r--r--lib/pleroma/web/activity_pub/publisher.ex124
-rw-r--r--lib/pleroma/web/activity_pub/publisher/prepared.ex8
-rw-r--r--lib/pleroma/web/activity_pub/side_effects.ex14
-rw-r--r--lib/pleroma/web/admin_api/controllers/admin_api_controller.ex5
-rw-r--r--lib/pleroma/web/api_spec/operations/account_operation.ex16
-rw-r--r--lib/pleroma/web/api_spec/operations/pleroma_account_operation.ex8
-rw-r--r--lib/pleroma/web/api_spec/operations/pleroma_backup_operation.ex10
-rw-r--r--lib/pleroma/web/api_spec/operations/status_operation.ex8
-rw-r--r--lib/pleroma/web/common_api.ex12
-rw-r--r--lib/pleroma/web/federator.ex32
-rw-r--r--lib/pleroma/web/mastodon_api/controllers/account_controller.ex6
-rw-r--r--lib/pleroma/web/mastodon_api/controllers/marker_controller.ex10
-rw-r--r--lib/pleroma/web/mastodon_api/controllers/status_controller.ex3
-rw-r--r--lib/pleroma/web/mastodon_api/mastodon_api.ex12
-rw-r--r--lib/pleroma/web/o_auth/token.ex9
-rw-r--r--lib/pleroma/web/pleroma_api/controllers/backup_controller.ex2
-rw-r--r--lib/pleroma/web/pleroma_api/views/backup_view.ex10
-rw-r--r--lib/pleroma/web/plugs/o_auth_plug.ex2
-rw-r--r--lib/pleroma/web/push.ex3
-rw-r--r--lib/pleroma/web/router.ex1
-rw-r--r--lib/pleroma/web/views/streamer_view.ex32
-rw-r--r--lib/pleroma/workers/attachments_cleanup_worker.ex6
-rw-r--r--lib/pleroma/workers/background_worker.ex8
-rw-r--r--lib/pleroma/workers/backup_worker.ex54
-rw-r--r--lib/pleroma/workers/cron/digest_emails_worker.ex4
-rw-r--r--lib/pleroma/workers/cron/new_users_digest_worker.ex6
-rw-r--r--lib/pleroma/workers/delete_worker.ex7
-rw-r--r--lib/pleroma/workers/mailer_worker.ex6
-rw-r--r--lib/pleroma/workers/mute_expire_worker.ex6
-rw-r--r--lib/pleroma/workers/poll_worker.ex6
-rw-r--r--lib/pleroma/workers/publisher_worker.ex22
-rw-r--r--lib/pleroma/workers/purge_expired_activity.ex11
-rw-r--r--lib/pleroma/workers/purge_expired_filter.ex2
-rw-r--r--lib/pleroma/workers/purge_expired_token.ex12
-rw-r--r--lib/pleroma/workers/receiver_worker.ex6
-rw-r--r--lib/pleroma/workers/remote_fetcher_worker.ex29
-rw-r--r--lib/pleroma/workers/rich_media_worker.ex4
-rw-r--r--lib/pleroma/workers/scheduled_activity_worker.ex6
-rw-r--r--lib/pleroma/workers/search_indexing_worker.ex6
-rw-r--r--lib/pleroma/workers/user_refresh_worker.ex2
-rw-r--r--lib/pleroma/workers/web_pusher_worker.ex6
-rw-r--r--lib/pleroma/workers/worker_helper.ex48
93 files changed, 1018 insertions, 1008 deletions
diff --git a/lib/mix/tasks/pleroma/database.ex b/lib/mix/tasks/pleroma/database.ex
index b82d1f079..e52b5e0a7 100644
--- a/lib/mix/tasks/pleroma/database.ex
+++ b/lib/mix/tasks/pleroma/database.ex
@@ -295,10 +295,12 @@ defmodule Mix.Tasks.Pleroma.Database do
|> DateTime.from_naive!("Etc/UTC")
|> Timex.shift(days: days)
- Pleroma.Workers.PurgeExpiredActivity.enqueue(%{
- activity_id: activity.id,
- expires_at: expires_at
- })
+ Pleroma.Workers.PurgeExpiredActivity.enqueue(
+ %{
+ activity_id: activity.id
+ },
+ scheduled_at: expires_at
+ )
end)
end)
|> Stream.run()
diff --git a/lib/mix/tasks/pleroma/test_runner.ex b/lib/mix/tasks/pleroma/test_runner.ex
deleted file mode 100644
index 69fefb001..000000000
--- a/lib/mix/tasks/pleroma/test_runner.ex
+++ /dev/null
@@ -1,25 +0,0 @@
-defmodule Mix.Tasks.Pleroma.TestRunner do
- @shortdoc "Retries tests once if they fail"
-
- use Mix.Task
-
- def run(args \\ []) do
- case System.cmd("mix", ["test"] ++ args, into: IO.stream(:stdio, :line)) do
- {_, 0} ->
- :ok
-
- _ ->
- retry(args)
- end
- end
-
- def retry(args) do
- case System.cmd("mix", ["test", "--failed"] ++ args, into: IO.stream(:stdio, :line)) do
- {_, 0} ->
- :ok
-
- _ ->
- exit(1)
- end
- end
-end
diff --git a/lib/pleroma/ecto_enums.ex b/lib/pleroma/ecto_enums.ex
index b346b39d6..a4890b489 100644
--- a/lib/pleroma/ecto_enums.ex
+++ b/lib/pleroma/ecto_enums.ex
@@ -27,11 +27,3 @@ defenum(Pleroma.DataMigration.State,
failed: 4,
manual: 5
)
-
-defenum(Pleroma.User.Backup.State,
- pending: 1,
- running: 2,
- complete: 3,
- failed: 4,
- invalid: 5
-)
diff --git a/lib/pleroma/emails/mailer.ex b/lib/pleroma/emails/mailer.ex
index 101442130..2a80f8547 100644
--- a/lib/pleroma/emails/mailer.ex
+++ b/lib/pleroma/emails/mailer.ex
@@ -25,7 +25,8 @@ defmodule Pleroma.Emails.Mailer do
|> :erlang.term_to_binary()
|> Base.encode64()
- MailerWorker.enqueue("email", %{"encoded_email" => encoded_email, "config" => config})
+ MailerWorker.new(%{"op" => "email", "encoded_email" => encoded_email, "config" => config})
+ |> Oban.insert()
end
@doc "callback to perform send email from queue"
diff --git a/lib/pleroma/emails/user_email.ex b/lib/pleroma/emails/user_email.ex
index 95b963764..10d89d2f3 100644
--- a/lib/pleroma/emails/user_email.ex
+++ b/lib/pleroma/emails/user_email.ex
@@ -345,37 +345,22 @@ defmodule Pleroma.Emails.UserEmail do
Router.Helpers.subscription_url(Endpoint, :unsubscribe, token)
end
- def backup_is_ready_email(backup, admin_user_id \\ nil) do
+ def backup_is_ready_email(backup) do
%{user: user} = Pleroma.Repo.preload(backup, :user)
Gettext.with_locale_or_default user.language do
download_url = Pleroma.Web.PleromaAPI.BackupView.download_url(backup)
html_body =
- if is_nil(admin_user_id) do
- Gettext.dpgettext(
- "static_pages",
- "account archive email body - self-requested",
- """
- <p>You requested a full backup of your Pleroma account. It's ready for download:</p>
- <p><a href="%{download_url}">%{download_url}</a></p>
- """,
- download_url: download_url
- )
- else
- admin = Pleroma.Repo.get(User, admin_user_id)
-
- Gettext.dpgettext(
- "static_pages",
- "account archive email body - admin requested",
- """
- <p>Admin @%{admin_nickname} requested a full backup of your Pleroma account. It's ready for download:</p>
- <p><a href="%{download_url}">%{download_url}</a></p>
- """,
- admin_nickname: admin.nickname,
- download_url: download_url
- )
- end
+ Gettext.dpgettext(
+ "static_pages",
+ "account archive email body",
+ """
+ <p>A full backup of your Pleroma account was requested. It's ready for download:</p>
+ <p><a href="%{download_url}">%{download_url}</a></p>
+ """,
+ download_url: download_url
+ )
new()
|> to(recipient(user))
diff --git a/lib/pleroma/filter.ex b/lib/pleroma/filter.ex
index e827d3cbc..77ed64d4f 100644
--- a/lib/pleroma/filter.ex
+++ b/lib/pleroma/filter.ex
@@ -133,10 +133,13 @@ defmodule Pleroma.Filter do
defp maybe_add_expires_at(changeset, _), do: changeset
defp maybe_add_expiration_job(%{expires_at: %NaiveDateTime{} = expires_at} = filter) do
- Pleroma.Workers.PurgeExpiredFilter.enqueue(%{
- filter_id: filter.id,
- expires_at: DateTime.from_naive!(expires_at, "Etc/UTC")
- })
+ Pleroma.Workers.PurgeExpiredFilter.new(
+ %{
+ filter_id: filter.id
+ },
+ scheduled_at: DateTime.from_naive!(expires_at, "Etc/UTC")
+ )
+ |> Oban.insert()
end
defp maybe_add_expiration_job(_), do: {:ok, nil}
diff --git a/lib/pleroma/instances/instance.ex b/lib/pleroma/instances/instance.ex
index 288555146..33f1229d0 100644
--- a/lib/pleroma/instances/instance.ex
+++ b/lib/pleroma/instances/instance.ex
@@ -297,7 +297,8 @@ defmodule Pleroma.Instances.Instance do
all of those users' activities and notifications.
"""
def delete_users_and_activities(host) when is_binary(host) do
- DeleteWorker.enqueue("delete_instance", %{"host" => host})
+ DeleteWorker.new(%{"op" => "delete_instance", "host" => host})
+ |> Oban.insert()
end
def perform(:delete_instance, host) when is_binary(host) do
diff --git a/lib/pleroma/mfa/token.ex b/lib/pleroma/mfa/token.ex
index 57bc11ed5..b53e1c7d0 100644
--- a/lib/pleroma/mfa/token.ex
+++ b/lib/pleroma/mfa/token.ex
@@ -52,11 +52,14 @@ defmodule Pleroma.MFA.Token do
@spec create(User.t(), Authorization.t() | nil) :: {:ok, t()} | {:error, Ecto.Changeset.t()}
def create(user, authorization \\ nil) do
with {:ok, token} <- do_create(user, authorization) do
- Pleroma.Workers.PurgeExpiredToken.enqueue(%{
- token_id: token.id,
- valid_until: DateTime.from_naive!(token.valid_until, "Etc/UTC"),
- mod: __MODULE__
- })
+ Pleroma.Workers.PurgeExpiredToken.new(
+ %{
+ token_id: token.id,
+ mod: __MODULE__
+ },
+ scheduled_at: DateTime.from_naive!(token.valid_until, "Etc/UTC")
+ )
+ |> Oban.insert()
{:ok, token}
end
diff --git a/lib/pleroma/object.ex b/lib/pleroma/object.ex
index eb44b3855..748f18e6c 100644
--- a/lib/pleroma/object.ex
+++ b/lib/pleroma/object.ex
@@ -255,7 +255,8 @@ defmodule Pleroma.Object do
@spec cleanup_attachments(boolean(), Object.t()) ::
{:ok, Oban.Job.t() | nil}
def cleanup_attachments(true, %Object{} = object) do
- AttachmentsCleanupWorker.enqueue("cleanup_attachments", %{"object" => object})
+ AttachmentsCleanupWorker.new(%{"op" => "cleanup_attachments", "object" => object})
+ |> Oban.insert()
end
def cleanup_attachments(_, _), do: {:ok, nil}
diff --git a/lib/pleroma/object/fetcher.ex b/lib/pleroma/object/fetcher.ex
index c0f671dd4..9d9a201ca 100644
--- a/lib/pleroma/object/fetcher.ex
+++ b/lib/pleroma/object/fetcher.ex
@@ -73,50 +73,22 @@ defmodule Pleroma.Object.Fetcher do
{:object, data, Object.normalize(activity, fetch: false)} do
{:ok, object}
else
- {:allowed_depth, false} = e ->
- log_fetch_error(id, e)
- {:error, :allowed_depth}
-
- {:containment, reason} = e ->
- log_fetch_error(id, e)
- {:error, reason}
-
- {:transmogrifier, {:error, {:reject, reason}}} = e ->
- log_fetch_error(id, e)
- {:reject, reason}
-
- {:transmogrifier, {:reject, reason}} = e ->
- log_fetch_error(id, e)
- {:reject, reason}
-
- {:transmogrifier, reason} = e ->
- log_fetch_error(id, e)
- {:error, reason}
-
- {:object, data, nil} ->
- reinject_object(%Object{}, data)
-
{:normalize, object = %Object{}} ->
{:ok, object}
{:fetch_object, %Object{} = object} ->
{:ok, object}
- {:fetch, {:error, reason}} = e ->
- log_fetch_error(id, e)
- {:error, reason}
+ {:object, data, nil} ->
+ reinject_object(%Object{}, data)
e ->
- log_fetch_error(id, e)
- {:error, e}
+ Logger.metadata(object: id)
+ Logger.error("Object rejected while fetching #{id} #{inspect(e)}")
+ e
end
end
- defp log_fetch_error(id, error) do
- Logger.metadata(object: id)
- Logger.error("Object rejected while fetching #{id} #{inspect(error)}")
- end
-
defp prepare_activity_params(data) do
%{
"type" => "Create",
diff --git a/lib/pleroma/search.ex b/lib/pleroma/search.ex
index b9d2a0188..30b3ba958 100644
--- a/lib/pleroma/search.ex
+++ b/lib/pleroma/search.ex
@@ -2,11 +2,13 @@ defmodule Pleroma.Search do
alias Pleroma.Workers.SearchIndexingWorker
def add_to_index(%Pleroma.Activity{id: activity_id}) do
- SearchIndexingWorker.enqueue("add_to_index", %{"activity" => activity_id})
+ SearchIndexingWorker.new(%{"op" => "add_to_index", "activity" => activity_id})
+ |> Oban.insert()
end
def remove_from_index(%Pleroma.Object{id: object_id}) do
- SearchIndexingWorker.enqueue("remove_from_index", %{"object" => object_id})
+ SearchIndexingWorker.new(%{"op" => "remove_from_index", "object" => object_id})
+ |> Oban.insert()
end
def search(query, options) do
diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex
index e28d76a7c..c6c536943 100644
--- a/lib/pleroma/user.ex
+++ b/lib/pleroma/user.ex
@@ -463,6 +463,7 @@ defmodule Pleroma.User do
def remote_user_changeset(struct \\ %User{local: false}, params) do
bio_limit = Config.get([:instance, :user_bio_length], 5000)
name_limit = Config.get([:instance, :user_name_length], 100)
+ fields_limit = Config.get([:instance, :max_remote_account_fields], 0)
name =
case params[:name] do
@@ -476,6 +477,7 @@ defmodule Pleroma.User do
|> Map.put_new(:last_refreshed_at, NaiveDateTime.utc_now())
|> truncate_if_exists(:name, name_limit)
|> truncate_if_exists(:bio, bio_limit)
+ |> Map.update(:fields, [], &Enum.take(&1, fields_limit))
|> truncate_fields_param()
|> fix_follower_address()
@@ -736,7 +738,8 @@ defmodule Pleroma.User do
end
def force_password_reset_async(user) do
- BackgroundWorker.enqueue("force_password_reset", %{"user_id" => user.id})
+ BackgroundWorker.new(%{"op" => "force_password_reset", "user_id" => user.id})
+ |> Oban.insert()
end
@spec force_password_reset(User.t()) :: {:ok, User.t()} | {:error, Ecto.Changeset.t()}
@@ -1218,7 +1221,8 @@ defmodule Pleroma.User do
def update_and_set_cache(changeset) do
with {:ok, user} <- Repo.update(changeset, stale_error_field: :id) do
if get_change(changeset, :raw_fields) do
- BackgroundWorker.enqueue("verify_fields_links", %{"user_id" => user.id})
+ BackgroundWorker.new(%{"op" => "verify_fields_links", "user_id" => user.id})
+ |> Oban.insert()
end
set_cache(user)
@@ -1589,11 +1593,11 @@ defmodule Pleroma.User do
)) ||
{:ok, nil} do
if duration > 0 do
- Pleroma.Workers.MuteExpireWorker.enqueue(
- "unmute_user",
- %{"muter_id" => muter.id, "mutee_id" => mutee.id},
+ Pleroma.Workers.MuteExpireWorker.new(
+ %{"op" => "unmute_user", "muter_id" => muter.id, "mutee_id" => mutee.id},
scheduled_at: expires_at
)
+ |> Oban.insert()
end
@cachex.del(:user_cache, "muted_users_ap_ids:#{muter.ap_id}")
@@ -1836,7 +1840,8 @@ defmodule Pleroma.User do
defp maybe_filter_on_ap_id(query, _ap_ids), do: query
def set_activation_async(user, status \\ true) do
- BackgroundWorker.enqueue("user_activation", %{"user_id" => user.id, "status" => status})
+ BackgroundWorker.new(%{"op" => "user_activation", "user_id" => user.id, "status" => status})
+ |> Oban.insert()
end
@spec set_activation([User.t()], boolean()) :: {:ok, User.t()} | {:error, Ecto.Changeset.t()}
@@ -1983,7 +1988,9 @@ defmodule Pleroma.User do
def delete(%User{} = user) do
# Purge the user immediately
purge(user)
- DeleteWorker.enqueue("delete_user", %{"user_id" => user.id})
+
+ DeleteWorker.new(%{"op" => "delete_user", "user_id" => user.id})
+ |> Oban.insert()
end
# *Actually* delete the user from the DB
diff --git a/lib/pleroma/user/backup.ex b/lib/pleroma/user/backup.ex
index 1821de667..7feaa22bf 100644
--- a/lib/pleroma/user/backup.ex
+++ b/lib/pleroma/user/backup.ex
@@ -14,9 +14,10 @@ defmodule Pleroma.User.Backup do
alias Pleroma.Activity
alias Pleroma.Bookmark
+ alias Pleroma.Config
alias Pleroma.Repo
+ alias Pleroma.Uploaders.Uploader
alias Pleroma.User
- alias Pleroma.User.Backup.State
alias Pleroma.Web.ActivityPub.ActivityPub
alias Pleroma.Web.ActivityPub.Transmogrifier
alias Pleroma.Web.ActivityPub.UserView
@@ -29,71 +30,111 @@ defmodule Pleroma.User.Backup do
field(:file_name, :string)
field(:file_size, :integer, default: 0)
field(:processed, :boolean, default: false)
- field(:state, State, default: :invalid)
- field(:processed_number, :integer, default: 0)
+ field(:tempdir, :string)
belongs_to(:user, User, type: FlakeId.Ecto.CompatType)
timestamps()
end
- @config_impl Application.compile_env(:pleroma, [__MODULE__, :config_impl], Pleroma.Config)
+ @doc """
+ Schedules a job to backup a user if the number of backup requests has not exceeded the limit.
- def create(user, admin_id \\ nil) do
- with :ok <- validate_limit(user, admin_id),
- {:ok, backup} <- user |> new() |> Repo.insert() do
- BackupWorker.process(backup, admin_id)
+ Admins can directly call new/1 and schedule_backup/1 to bypass the limit.
+ """
+ @spec user(User.t()) :: {:ok, t()} | {:error, any()}
+ def user(user) do
+ days = Config.get([__MODULE__, :limit_days])
+
+ with true <- permitted?(user),
+ %__MODULE__{} = backup <- new(user),
+ {:ok, inserted_backup} <- Repo.insert(backup),
+ {:ok, %Oban.Job{}} <- schedule_backup(inserted_backup) do
+ {:ok, inserted_backup}
+ else
+ false ->
+ {:error,
+ dngettext(
+ "errors",
+ "Last export was less than a day ago",
+ "Last export was less than %{days} days ago",
+ days,
+ days: days
+ )}
+
+ e ->
+ {:error, e}
end
end
+ @doc "Generates a %Backup{} for a user with a random file name"
+ @spec new(User.t()) :: t()
def new(user) do
rand_str = :crypto.strong_rand_bytes(32) |> Base.url_encode64(padding: false)
datetime = Calendar.NaiveDateTime.Format.iso8601_basic(NaiveDateTime.utc_now())
name = "archive-#{user.nickname}-#{datetime}-#{rand_str}.zip"
%__MODULE__{
- user_id: user.id,
content_type: "application/zip",
file_name: name,
- state: :pending
+ tempdir: tempdir(),
+ user: user
}
end
- def delete(backup) do
- uploader = Pleroma.Config.get([Pleroma.Upload, :uploader])
+ @doc "Schedules the execution of the provided backup"
+ @spec schedule_backup(t()) :: {:ok, Oban.Job.t()} | {:error, any()}
+ def schedule_backup(backup) do
+ with false <- is_nil(backup.id) do
+ %{"op" => "process", "backup_id" => backup.id}
+ |> BackupWorker.new()
+ |> Oban.insert()
+ else
+ true ->
+ {:error, "Backup is missing id. Please insert it into the Repo first."}
+
+ e ->
+ {:error, e}
+ end
+ end
+
+ @doc "Deletes the backup archive file and removes the database record"
+ @spec delete_archive(t()) :: {:ok, Ecto.Schema.t()} | {:error, Ecto.Changeset.t()}
+ def delete_archive(backup) do
+ uploader = Config.get([Pleroma.Upload, :uploader])
with :ok <- uploader.delete_file(Path.join("backups", backup.file_name)) do
Repo.delete(backup)
end
end
- defp validate_limit(_user, admin_id) when is_binary(admin_id), do: :ok
-
- defp validate_limit(user, nil) do
- case get_last(user.id) do
- %__MODULE__{inserted_at: inserted_at} ->
- days = Pleroma.Config.get([__MODULE__, :limit_days])
- diff = Timex.diff(NaiveDateTime.utc_now(), inserted_at, :days)
-
- if diff > days do
- :ok
- else
- {:error,
- dngettext(
- "errors",
- "Last export was less than a day ago",
- "Last export was less than %{days} days ago",
- days,
- days: days
- )}
- end
+ @doc "Schedules a job to delete the backup archive"
+ @spec schedule_delete(t()) :: {:ok, Oban.Job.t()} | {:error, any()}
+ def schedule_delete(backup) do
+ days = Config.get([__MODULE__, :purge_after_days])
+ time = 60 * 60 * 24 * days
+ scheduled_at = Calendar.NaiveDateTime.add!(backup.inserted_at, time)
- nil ->
- :ok
+ %{"op" => "delete", "backup_id" => backup.id}
+ |> BackupWorker.new(scheduled_at: scheduled_at)
+ |> Oban.insert()
+ end
+
+ defp permitted?(user) do
+ with {_, %__MODULE__{inserted_at: inserted_at}} <- {:last, get_last(user)},
+ days = Config.get([__MODULE__, :limit_days]),
+ diff = Timex.diff(NaiveDateTime.utc_now(), inserted_at, :days),
+ {_, true} <- {:diff, diff > days} do
+ true
+ else
+ {:last, nil} -> true
+ {:diff, false} -> false
end
end
- def get_last(user_id) do
+ @doc "Returns last backup for the provided user"
+ @spec get_last(User.t()) :: t()
+ def get_last(%User{id: user_id}) do
__MODULE__
|> where(user_id: ^user_id)
|> order_by(desc: :id)
@@ -101,6 +142,8 @@ defmodule Pleroma.User.Backup do
|> Repo.one()
end
+ @doc "Lists all existing backups for a user"
+ @spec list(User.t()) :: [Ecto.Schema.t() | term()]
def list(%User{id: user_id}) do
__MODULE__
|> where(user_id: ^user_id)
@@ -108,92 +151,35 @@ defmodule Pleroma.User.Backup do
|> Repo.all()
end
- def remove_outdated(%__MODULE__{id: latest_id, user_id: user_id}) do
- __MODULE__
- |> where(user_id: ^user_id)
- |> where([b], b.id != ^latest_id)
- |> Repo.all()
- |> Enum.each(&BackupWorker.delete/1)
+ @doc "Schedules deletion of all but the the most recent backup"
+ @spec remove_outdated(User.t()) :: :ok
+ def remove_outdated(user) do
+ with %__MODULE__{} = latest_backup <- get_last(user) do
+ __MODULE__
+ |> where(user_id: ^user.id)
+ |> where([b], b.id != ^latest_backup.id)
+ |> Repo.all()
+ |> Enum.each(&schedule_delete/1)
+ else
+ _ -> :ok
+ end
end
- def get(id), do: Repo.get(__MODULE__, id)
-
- defp set_state(backup, state, processed_number \\ nil) do
- struct =
- %{state: state}
- |> Pleroma.Maps.put_if_present(:processed_number, processed_number)
+ def get_by_id(id), do: Repo.get(__MODULE__, id)
+ @doc "Generates changeset for %Pleroma.User.Backup{}"
+ @spec changeset(%__MODULE__{}, map()) :: %Ecto.Changeset{}
+ def changeset(backup \\ %__MODULE__{}, attrs) do
backup
- |> cast(struct, [:state, :processed_number])
- |> Repo.update()
- end
-
- def process(
- %__MODULE__{} = backup,
- processor_module \\ __MODULE__.Processor
- ) do
- set_state(backup, :running, 0)
-
- current_pid = self()
-
- task =
- Task.Supervisor.async_nolink(
- Pleroma.TaskSupervisor,
- processor_module,
- :do_process,
- [backup, current_pid]
- )
-
- wait_backup(backup, backup.processed_number, task)
+ |> cast(attrs, [:content_type, :file_name, :file_size, :processed, :tempdir])
end
- defp wait_backup(backup, current_processed, task) do
- wait_time = @config_impl.get([__MODULE__, :process_wait_time])
-
- receive do
- {:progress, new_processed} ->
- total_processed = current_processed + new_processed
-
- set_state(backup, :running, total_processed)
- wait_backup(backup, total_processed, task)
-
- {:DOWN, _ref, _proc, _pid, reason} ->
- backup = get(backup.id)
-
- if reason != :normal do
- Logger.error("Backup #{backup.id} process ended abnormally: #{inspect(reason)}")
-
- {:ok, backup} = set_state(backup, :failed)
-
- cleanup(backup)
-
- {:error,
- %{
- backup: backup,
- reason: :exit,
- details: reason
- }}
- else
- {:ok, backup}
- end
- after
- wait_time ->
- Logger.error(
- "Backup #{backup.id} timed out after no response for #{wait_time}ms, terminating"
- )
-
- Task.Supervisor.terminate_child(Pleroma.TaskSupervisor, task.pid)
-
- {:ok, backup} = set_state(backup, :failed)
-
- cleanup(backup)
-
- {:error,
- %{
- backup: backup,
- reason: :timeout
- }}
- end
+ @doc "Updates the backup record"
+ @spec update_record(%__MODULE__{}, map()) :: {:ok, %__MODULE__{}} | {:error, %Ecto.Changeset{}}
+ def update_record(%__MODULE__{} = backup, attrs) do
+ backup
+ |> changeset(attrs)
+ |> Repo.update()
end
@files [
@@ -204,53 +190,68 @@ defmodule Pleroma.User.Backup do
~c"followers.json",
~c"following.json"
]
- @spec export(Pleroma.User.Backup.t(), pid()) :: {:ok, String.t()} | :error
- def export(%__MODULE__{} = backup, caller_pid) do
+
+ @spec run(t()) :: {:ok, t()} | {:error, :failed}
+ def run(%__MODULE__{} = backup) do
backup = Repo.preload(backup, :user)
- dir = backup_tempdir(backup)
-
- with :ok <- File.mkdir(dir),
- :ok <- actor(dir, backup.user, caller_pid),
- :ok <- statuses(dir, backup.user, caller_pid),
- :ok <- likes(dir, backup.user, caller_pid),
- :ok <- bookmarks(dir, backup.user, caller_pid),
- :ok <- followers(dir, backup.user, caller_pid),
- :ok <- following(dir, backup.user, caller_pid),
- {:ok, zip_path} <- :zip.create(backup.file_name, @files, cwd: dir),
- {:ok, _} <- File.rm_rf(dir) do
- {:ok, zip_path}
+ tempfile = Path.join([backup.tempdir, backup.file_name])
+
+ with {_, :ok} <- {:mkdir, File.mkdir_p(backup.tempdir)},
+ {_, :ok} <- {:actor, actor(backup.tempdir, backup.user)},
+ {_, :ok} <- {:statuses, statuses(backup.tempdir, backup.user)},
+ {_, :ok} <- {:likes, likes(backup.tempdir, backup.user)},
+ {_, :ok} <- {:bookmarks, bookmarks(backup.tempdir, backup.user)},
+ {_, :ok} <- {:followers, followers(backup.tempdir, backup.user)},
+ {_, :ok} <- {:following, following(backup.tempdir, backup.user)},
+ {_, {:ok, _zip_path}} <-
+ {:zip, :zip.create(to_charlist(tempfile), @files, cwd: to_charlist(backup.tempdir))},
+ {_, {:ok, %File.Stat{size: zip_size}}} <- {:filestat, File.stat(tempfile)},
+ {:ok, updated_backup} <- update_record(backup, %{file_size: zip_size}) do
+ {:ok, updated_backup}
else
- _ -> :error
+ _ ->
+ File.rm_rf(backup.tempdir)
+ {:error, :failed}
end
end
- def dir(name) do
- dir = Pleroma.Config.get([__MODULE__, :dir]) || System.tmp_dir!()
- Path.join(dir, name)
+ defp tempdir do
+ rand = :crypto.strong_rand_bytes(8) |> Base.url_encode64(padding: false)
+ subdir = "backup-#{rand}"
+
+ case Config.get([__MODULE__, :tempdir]) do
+ nil ->
+ Path.join([System.tmp_dir!(), subdir])
+
+ path ->
+ Path.join([path, subdir])
+ end
end
- def upload(%__MODULE__{} = backup, zip_path) do
- uploader = Pleroma.Config.get([Pleroma.Upload, :uploader])
+ @doc "Uploads the completed backup and marks it as processed"
+ @spec upload(t()) :: {:ok, t()}
+ def upload(%__MODULE__{tempdir: tempdir} = backup) when is_binary(tempdir) do
+ uploader = Config.get([Pleroma.Upload, :uploader])
upload = %Pleroma.Upload{
name: backup.file_name,
- tempfile: zip_path,
+ tempfile: Path.join([tempdir, backup.file_name]),
content_type: backup.content_type,
path: Path.join("backups", backup.file_name)
}
- with {:ok, _} <- Pleroma.Uploaders.Uploader.put_file(uploader, upload),
- :ok <- File.rm(zip_path) do
- {:ok, upload}
+ with {:ok, _} <- Uploader.put_file(uploader, upload),
+ {:ok, uploaded_backup} <- update_record(backup, %{processed: true}),
+ {:ok, _} <- File.rm_rf(tempdir) do
+ {:ok, uploaded_backup}
end
end
- defp actor(dir, user, caller_pid) do
+ defp actor(dir, user) do
with {:ok, json} <-
UserView.render("user.json", %{user: user})
|> Map.merge(%{"likes" => "likes.json", "bookmarks" => "bookmarks.json"})
|> Jason.encode() do
- send(caller_pid, {:progress, 1})
File.write(Path.join(dir, "actor.json"), json)
end
end
@@ -269,22 +270,10 @@ defmodule Pleroma.User.Backup do
)
end
- defp should_report?(num, chunk_size), do: rem(num, chunk_size) == 0
-
- defp backup_tempdir(backup) do
- name = String.trim_trailing(backup.file_name, ".zip")
- dir(name)
- end
-
- defp cleanup(backup) do
- dir = backup_tempdir(backup)
- File.rm_rf(dir)
- end
-
- defp write(query, dir, name, fun, caller_pid) do
+ defp write(query, dir, name, fun) do
path = Path.join(dir, "#{name}.json")
- chunk_size = Pleroma.Config.get([__MODULE__, :process_chunk_size])
+ chunk_size = Config.get([__MODULE__, :process_chunk_size])
with {:ok, file} <- File.open(path, [:write, :utf8]),
:ok <- write_header(file, name) do
@@ -300,10 +289,6 @@ defmodule Pleroma.User.Backup do
end),
{:ok, str} <- Jason.encode(data),
:ok <- IO.write(file, str <> ",\n") do
- if should_report?(acc + 1, chunk_size) do
- send(caller_pid, {:progress, chunk_size})
- end
-
acc + 1
else
{:error, e} ->
@@ -318,31 +303,29 @@ defmodule Pleroma.User.Backup do
end
end)
- send(caller_pid, {:progress, rem(total, chunk_size)})
-
with :ok <- :file.pwrite(file, {:eof, -2}, "\n],\n \"totalItems\": #{total}}") do
File.close(file)
end
end
end
- defp bookmarks(dir, %{id: user_id} = _user, caller_pid) do
+ defp bookmarks(dir, %{id: user_id} = _user) do
Bookmark
|> where(user_id: ^user_id)
|> join(:inner, [b], activity in assoc(b, :activity))
|> select([b, a], %{id: b.id, object: fragment("(?)->>'object'", a.data)})
- |> write(dir, "bookmarks", fn a -> {:ok, a.object} end, caller_pid)
+ |> write(dir, "bookmarks", fn a -> {:ok, a.object} end)
end
- defp likes(dir, user, caller_pid) do
+ defp likes(dir, user) do
user.ap_id
|> Activity.Queries.by_actor()
|> Activity.Queries.by_type("Like")
|> select([like], %{id: like.id, object: fragment("(?)->>'object'", like.data)})
- |> write(dir, "likes", fn a -> {:ok, a.object} end, caller_pid)
+ |> write(dir, "likes", fn a -> {:ok, a.object} end)
end
- defp statuses(dir, user, caller_pid) do
+ defp statuses(dir, user) do
opts =
%{}
|> Map.put(:type, ["Create", "Announce"])
@@ -362,52 +345,17 @@ defmodule Pleroma.User.Backup do
with {:ok, activity} <- Transmogrifier.prepare_outgoing(a.data) do
{:ok, Map.delete(activity, "@context")}
end
- end,
- caller_pid
+ end
)
end
- defp followers(dir, user, caller_pid) do
+ defp followers(dir, user) do
User.get_followers_query(user)
- |> write(dir, "followers", fn a -> {:ok, a.ap_id} end, caller_pid)
+ |> write(dir, "followers", fn a -> {:ok, a.ap_id} end)
end
- defp following(dir, user, caller_pid) do
+ defp following(dir, user) do
User.get_friends_query(user)
- |> write(dir, "following", fn a -> {:ok, a.ap_id} end, caller_pid)
- end
-end
-
-defmodule Pleroma.User.Backup.ProcessorAPI do
- @callback do_process(%Pleroma.User.Backup{}, pid()) ::
- {:ok, %Pleroma.User.Backup{}} | {:error, any()}
-end
-
-defmodule Pleroma.User.Backup.Processor do
- @behaviour Pleroma.User.Backup.ProcessorAPI
-
- alias Pleroma.Repo
- alias Pleroma.User.Backup
-
- import Ecto.Changeset
-
- @impl true
- def do_process(backup, current_pid) do
- with {:ok, zip_file} <- Backup.export(backup, current_pid),
- {:ok, %{size: size}} <- File.stat(zip_file),
- {:ok, _upload} <- Backup.upload(backup, zip_file) do
- backup
- |> cast(
- %{
- file_size: size,
- processed: true,
- state: :complete
- },
- [:file_size, :processed, :state]
- )
- |> Repo.update()
- else
- e -> {:error, e}
- end
+ |> write(dir, "following", fn a -> {:ok, a.ap_id} end)
end
end
diff --git a/lib/pleroma/user/import.ex b/lib/pleroma/user/import.ex
index 53ffd1ab3..11905237c 100644
--- a/lib/pleroma/user/import.ex
+++ b/lib/pleroma/user/import.ex
@@ -63,23 +63,29 @@ defmodule Pleroma.User.Import do
end
def blocks_import(%User{} = blocker, [_ | _] = identifiers) do
- BackgroundWorker.enqueue(
- "blocks_import",
- %{"user_id" => blocker.id, "identifiers" => identifiers}
- )
+ BackgroundWorker.new(%{
+ "op" => "blocks_import",
+ "user_id" => blocker.id,
+ "identifiers" => identifiers
+ })
+ |> Oban.insert()
end
def follow_import(%User{} = follower, [_ | _] = identifiers) do
- BackgroundWorker.enqueue(
- "follow_import",
- %{"user_id" => follower.id, "identifiers" => identifiers}
- )
+ BackgroundWorker.new(%{
+ "op" => "follow_import",
+ "user_id" => follower.id,
+ "identifiers" => identifiers
+ })
+ |> Oban.insert()
end
def mutes_import(%User{} = user, [_ | _] = identifiers) do
- BackgroundWorker.enqueue(
- "mutes_import",
- %{"user_id" => user.id, "identifiers" => identifiers}
- )
+ BackgroundWorker.new(%{
+ "op" => "mutes_import",
+ "user_id" => user.id,
+ "identifiers" => identifiers
+ })
+ |> Oban.insert()
end
end
diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex
index b30b0cabe..a2a94a0ff 100644
--- a/lib/pleroma/web/activity_pub/activity_pub.ex
+++ b/lib/pleroma/web/activity_pub/activity_pub.ex
@@ -222,10 +222,12 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
%{data: %{"expires_at" => %DateTime{} = expires_at}} = activity
) do
with {:ok, _job} <-
- Pleroma.Workers.PurgeExpiredActivity.enqueue(%{
- activity_id: activity.id,
- expires_at: expires_at
- }) do
+ Pleroma.Workers.PurgeExpiredActivity.enqueue(
+ %{
+ activity_id: activity.id
+ },
+ scheduled_at: expires_at
+ ) do
{:ok, activity}
end
end
@@ -446,10 +448,12 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
_ <- notify_and_stream(activity) do
maybe_federate(activity)
- BackgroundWorker.enqueue("move_following", %{
+ BackgroundWorker.new(%{
+ "op" => "move_following",
"origin_id" => origin.id,
"target_id" => target.id
})
+ |> Oban.insert()
{:ok, activity}
else
@@ -1797,10 +1801,12 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
# enqueue a task to fetch all pinned objects
Enum.each(pins, fn {ap_id, _} ->
if is_nil(Object.get_cached_by_ap_id(ap_id)) do
- Pleroma.Workers.RemoteFetcherWorker.enqueue("fetch_remote", %{
+ Pleroma.Workers.RemoteFetcherWorker.new(%{
+ "op" => "fetch_remote",
"id" => ap_id,
"depth" => 1
})
+ |> Oban.insert()
end
end)
end
diff --git a/lib/pleroma/web/activity_pub/mrf/anti_followbot_policy.ex b/lib/pleroma/web/activity_pub/mrf/anti_followbot_policy.ex
index df4ba819c..8ea61aec2 100644
--- a/lib/pleroma/web/activity_pub/mrf/anti_followbot_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/anti_followbot_policy.ex
@@ -63,20 +63,20 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiFollowbotPolicy do
end
@impl true
- def filter(%{"type" => "Follow", "actor" => actor_id} = message) do
+ def filter(%{"type" => "Follow", "actor" => actor_id} = activity) do
%User{} = actor = normalize_by_ap_id(actor_id)
score = determine_if_followbot(actor)
- if score < 0.8 || bot_allowed?(message, actor) do
- {:ok, message}
+ if score < 0.8 || bot_allowed?(activity, actor) do
+ {:ok, activity}
else
{:reject, "[AntiFollowbotPolicy] Scored #{actor_id} as #{score}"}
end
end
@impl true
- def filter(message), do: {:ok, message}
+ def filter(activity), do: {:ok, activity}
@impl true
def describe, do: {:ok, %{}}
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 3ec9c52ee..2be6d8df4 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
@@ -29,17 +29,17 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiLinkSpamPolicy do
defp contains_links?(_), do: false
@impl true
- def filter(%{"type" => "Create", "actor" => actor, "object" => object} = message) do
+ def filter(%{"type" => "Create", "actor" => actor, "object" => object} = activity) do
with {:ok, %User{local: false} = u} <- User.get_or_fetch_by_ap_id(actor),
{:contains_links, true} <- {:contains_links, contains_links?(object)},
{:old_user, true} <- {:old_user, old_user?(u)} do
- {:ok, message}
+ {:ok, activity}
else
{:ok, %User{local: true}} ->
- {:ok, message}
+ {:ok, activity}
{:contains_links, false} ->
- {:ok, message}
+ {:ok, activity}
{:old_user, false} ->
{:reject, "[AntiLinkSpamPolicy] User has no posts nor followers"}
@@ -53,7 +53,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiLinkSpamPolicy do
end
# in all other cases, pass through
- def filter(message), do: {:ok, message}
+ def filter(activity), do: {:ok, activity}
@impl true
def describe, do: {:ok, %{}}
diff --git a/lib/pleroma/web/activity_pub/mrf/anti_mention_spam_policy.ex b/lib/pleroma/web/activity_pub/mrf/anti_mention_spam_policy.ex
index 531e75ce8..1d76a307b 100644
--- a/lib/pleroma/web/activity_pub/mrf/anti_mention_spam_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/anti_mention_spam_policy.ex
@@ -22,11 +22,11 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiMentionSpamPolicy do
end
# copied from HellthreadPolicy
- defp get_recipient_count(message) do
- recipients = (message["to"] || []) ++ (message["cc"] || [])
+ defp get_recipient_count(activity) do
+ recipients = (activity["to"] || []) ++ (activity["cc"] || [])
follower_collection =
- User.get_cached_by_ap_id(message["actor"] || message["attributedTo"]).follower_address
+ User.get_cached_by_ap_id(activity["actor"] || activity["attributedTo"]).follower_address
if Enum.member?(recipients, Pleroma.Constants.as_public()) do
recipients =
@@ -80,7 +80,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiMentionSpamPolicy do
end
# in all other cases, pass through
- def filter(message), do: {:ok, message}
+ def filter(activity), do: {:ok, activity}
@impl true
def describe, do: {:ok, %{}}
diff --git a/lib/pleroma/web/activity_pub/mrf/dnsrbl_policy.ex b/lib/pleroma/web/activity_pub/mrf/dnsrbl_policy.ex
index 7c6bb888f..ca41c464c 100644
--- a/lib/pleroma/web/activity_pub/mrf/dnsrbl_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/dnsrbl_policy.ex
@@ -38,18 +38,18 @@ defmodule Pleroma.Web.ActivityPub.MRF.DNSRBLPolicy do
@query_timeout 500
@impl true
- def filter(%{"actor" => actor} = object) do
+ def filter(%{"actor" => actor} = activity) do
actor_info = URI.parse(actor)
- with {:ok, object} <- check_rbl(actor_info, object) do
- {:ok, object}
+ with {:ok, activity} <- check_rbl(actor_info, activity) do
+ {:ok, activity}
else
_ -> {:reject, "[DNSRBLPolicy]"}
end
end
@impl true
- def filter(object), do: {:ok, object}
+ def filter(activity), do: {:ok, activity}
@impl true
def describe do
@@ -90,7 +90,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.DNSRBLPolicy do
}
end
- defp check_rbl(%{host: actor_host}, object) do
+ defp check_rbl(%{host: actor_host}, activity) do
with false <- match?(^actor_host, Pleroma.Web.Endpoint.host()),
zone when not is_nil(zone) <- Keyword.get(Config.get([:mrf_dnsrbl]), :zone) do
query =
@@ -100,7 +100,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.DNSRBLPolicy do
rbl_response = rblquery(query)
if Enum.empty?(rbl_response) do
- {:ok, object}
+ {:ok, activity}
else
Task.start(fn ->
reason =
@@ -117,7 +117,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.DNSRBLPolicy do
:error
end
else
- _ -> {:ok, object}
+ _ -> {:ok, activity}
end
end
diff --git a/lib/pleroma/web/activity_pub/mrf/drop_policy.ex b/lib/pleroma/web/activity_pub/mrf/drop_policy.ex
index ad0936839..e4fcc9935 100644
--- a/lib/pleroma/web/activity_pub/mrf/drop_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/drop_policy.ex
@@ -8,9 +8,9 @@ defmodule Pleroma.Web.ActivityPub.MRF.DropPolicy do
@behaviour Pleroma.Web.ActivityPub.MRF.Policy
@impl true
- def filter(object) do
- Logger.debug("REJECTING #{inspect(object)}")
- {:reject, object}
+ def filter(activity) do
+ Logger.debug("REJECTING #{inspect(activity)}")
+ {:reject, activity}
end
@impl true
diff --git a/lib/pleroma/web/activity_pub/mrf/emoji_policy.ex b/lib/pleroma/web/activity_pub/mrf/emoji_policy.ex
index f884962b9..1de5280d9 100644
--- a/lib/pleroma/web/activity_pub/mrf/emoji_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/emoji_policy.ex
@@ -28,11 +28,11 @@ defmodule Pleroma.Web.ActivityPub.MRF.EmojiPolicy do
Pleroma.Config.get([:mrf_emoji, :federated_timeline_removal_shortcode], [])
end
- @impl Pleroma.Web.ActivityPub.MRF.Policy
+ @impl true
def history_awareness, do: :manual
- @impl Pleroma.Web.ActivityPub.MRF.Policy
- def filter(%{"type" => type, "object" => %{"type" => objtype} = object} = message)
+ @impl true
+ def filter(%{"type" => type, "object" => %{"type" => objtype} = object} = activity)
when type in ["Create", "Update"] and objtype in Pleroma.Constants.status_object_types() do
with {:ok, object} <-
Updater.do_with_history(object, fn object ->
@@ -42,13 +42,13 @@ defmodule Pleroma.Web.ActivityPub.MRF.EmojiPolicy do
Updater.do_with_history(object, fn object ->
{:ok, process_remove(object, :shortcode, config_remove_shortcode())}
end),
- activity <- Map.put(message, "object", object),
+ activity <- Map.put(activity, "object", object),
activity <- maybe_delist(activity) do
{:ok, activity}
end
end
- @impl Pleroma.Web.ActivityPub.MRF.Policy
+ @impl true
def filter(%{"type" => type} = object) when type in Pleroma.Constants.actor_types() do
with object <- process_remove(object, :url, config_remove_url()),
object <- process_remove(object, :shortcode, config_remove_shortcode()) do
@@ -56,7 +56,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.EmojiPolicy do
end
end
- @impl Pleroma.Web.ActivityPub.MRF.Policy
+ @impl true
def filter(%{"type" => "EmojiReact"} = object) do
with {:ok, _} <-
matched_emoji_checker(config_remove_url(), config_remove_shortcode()).(object) do
@@ -67,9 +67,9 @@ defmodule Pleroma.Web.ActivityPub.MRF.EmojiPolicy do
end
end
- @impl Pleroma.Web.ActivityPub.MRF.Policy
- def filter(message) do
- {:ok, message}
+ @impl true
+ def filter(activity) do
+ {:ok, activity}
end
defp match_string?(string, pattern) when is_binary(pattern) do
@@ -214,7 +214,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.EmojiPolicy do
)
end
- @impl Pleroma.Web.ActivityPub.MRF.Policy
+ @impl true
def describe do
mrf_emoji =
Pleroma.Config.get(:mrf_emoji, [])
@@ -226,7 +226,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.EmojiPolicy do
{:ok, %{mrf_emoji: mrf_emoji}}
end
- @impl Pleroma.Web.ActivityPub.MRF.Policy
+ @impl true
def config_description do
%{
key: :mrf_emoji,
@@ -239,7 +239,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.EmojiPolicy do
key: :remove_url,
type: {:list, :string},
description: """
- A list of patterns which result in emoji whose URL matches being removed from the message. This will apply to statuses, emoji reactions, and user profiles.
+ A list of patterns which result in emoji whose URL matches being removed from the activity. This will apply to statuses, emoji reactions, and user profiles.
Each pattern can be a string or [Regex](https://hexdocs.pm/elixir/Regex.html) in the format of `~r/PATTERN/`.
""",
@@ -249,7 +249,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.EmojiPolicy do
key: :remove_shortcode,
type: {:list, :string},
description: """
- A list of patterns which result in emoji whose shortcode matches being removed from the message. This will apply to statuses, emoji reactions, and user profiles.
+ A list of patterns which result in emoji whose shortcode matches being removed from the activity. This will apply to statuses, emoji reactions, and user profiles.
Each pattern can be a string or [Regex](https://hexdocs.pm/elixir/Regex.html) in the format of `~r/PATTERN/`.
""",
@@ -259,7 +259,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.EmojiPolicy do
key: :federated_timeline_removal_url,
type: {:list, :string},
description: """
- A list of patterns which result in message with emojis whose URLs match being removed from federated timelines (a.k.a unlisted). This will apply only to statuses.
+ A list of patterns which result in activity with emojis whose URLs match being removed from federated timelines (a.k.a unlisted). This will apply only to statuses.
Each pattern can be a string or [Regex](https://hexdocs.pm/elixir/Regex.html) in the format of `~r/PATTERN/`.
""",
@@ -269,7 +269,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.EmojiPolicy do
key: :federated_timeline_removal_shortcode,
type: {:list, :string},
description: """
- A list of patterns which result in message with emojis whose shortcodes match being removed from federated timelines (a.k.a unlisted). This will apply only to statuses.
+ A list of patterns which result in activities with emojis whose shortcodes match being removed from federated timelines (a.k.a unlisted). This will apply only to statuses.
Each pattern can be a string or [Regex](https://hexdocs.pm/elixir/Regex.html) in the format of `~r/PATTERN/`.
""",
diff --git a/lib/pleroma/web/activity_pub/mrf/ensure_re_prepended.ex b/lib/pleroma/web/activity_pub/mrf/ensure_re_prepended.ex
index a148cc1e7..f5983c8a7 100644
--- a/lib/pleroma/web/activity_pub/mrf/ensure_re_prepended.ex
+++ b/lib/pleroma/web/activity_pub/mrf/ensure_re_prepended.ex
@@ -29,19 +29,19 @@ defmodule Pleroma.Web.ActivityPub.MRF.EnsureRePrepended do
def filter_by_summary(_in_reply_to, child), do: child
- def filter(%{"type" => type, "object" => child_object} = object)
- when type in ["Create", "Update"] and is_map(child_object) do
+ def filter(%{"type" => type, "object" => object} = activity)
+ when type in ["Create", "Update"] and is_map(object) do
child =
- child_object["inReplyTo"]
+ object["inReplyTo"]
|> Object.normalize(fetch: false)
- |> filter_by_summary(child_object)
+ |> filter_by_summary(object)
- object = Map.put(object, "object", child)
+ activity = Map.put(activity, "object", child)
- {:ok, object}
+ {:ok, activity}
end
- def filter(object), do: {:ok, object}
+ def filter(activity), do: {:ok, activity}
def describe, do: {:ok, %{}}
end
diff --git a/lib/pleroma/web/activity_pub/mrf/fo_direct_reply.ex b/lib/pleroma/web/activity_pub/mrf/fo_direct_reply.ex
new file mode 100644
index 000000000..2cf22745a
--- /dev/null
+++ b/lib/pleroma/web/activity_pub/mrf/fo_direct_reply.ex
@@ -0,0 +1,53 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2024 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.ActivityPub.MRF.FODirectReply do
+ @moduledoc """
+ FODirectReply alters the scope of replies to activities which are Followers Only to be Direct. The purpose of this policy is to prevent broken threads for followers of the reply author because their response was to a user that they are not also following.
+ """
+
+ alias Pleroma.Object
+ alias Pleroma.User
+ alias Pleroma.Web.ActivityPub.Visibility
+
+ @behaviour Pleroma.Web.ActivityPub.MRF.Policy
+
+ @impl true
+ def filter(
+ %{
+ "type" => "Create",
+ "to" => to,
+ "object" => %{
+ "actor" => actor,
+ "type" => "Note",
+ "inReplyTo" => in_reply_to
+ }
+ } = activity
+ ) do
+ with true <- is_binary(in_reply_to),
+ %User{follower_address: followers_collection, local: true} <- User.get_by_ap_id(actor),
+ %Object{} = in_reply_to_object <- Object.get_by_ap_id(in_reply_to),
+ "private" <- Visibility.get_visibility(in_reply_to_object) do
+ direct_to = to -- [followers_collection]
+
+ updated_activity =
+ activity
+ |> Map.put("cc", [])
+ |> Map.put("to", direct_to)
+ |> Map.put("directMessage", true)
+ |> put_in(["object", "cc"], [])
+ |> put_in(["object", "to"], direct_to)
+
+ {:ok, updated_activity}
+ else
+ _ -> {:ok, activity}
+ end
+ end
+
+ @impl true
+ def filter(activity), do: {:ok, activity}
+
+ @impl true
+ def describe, do: {:ok, %{}}
+end
diff --git a/lib/pleroma/web/activity_pub/mrf/follow_bot_policy.ex b/lib/pleroma/web/activity_pub/mrf/follow_bot_policy.ex
index 55ea2683c..480a03ef6 100644
--- a/lib/pleroma/web/activity_pub/mrf/follow_bot_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/follow_bot_policy.ex
@@ -11,12 +11,12 @@ defmodule Pleroma.Web.ActivityPub.MRF.FollowBotPolicy do
require Logger
@impl true
- def filter(message) do
+ def filter(activity) do
with follower_nickname <- Config.get([:mrf_follow_bot, :follower_nickname]),
%User{actor_type: "Service"} = follower <-
User.get_cached_by_nickname(follower_nickname),
- %{"type" => "Create", "object" => %{"type" => "Note"}} <- message do
- try_follow(follower, message)
+ %{"type" => "Create", "object" => %{"type" => "Note"}} <- activity do
+ try_follow(follower, activity)
else
nil ->
Logger.warning(
@@ -24,17 +24,17 @@ defmodule Pleroma.Web.ActivityPub.MRF.FollowBotPolicy do
account does not exist, or the account is not correctly configured as a bot."
)
- {:ok, message}
+ {:ok, activity}
_ ->
- {:ok, message}
+ {:ok, activity}
end
end
- defp try_follow(follower, message) do
- to = Map.get(message, "to", [])
- cc = Map.get(message, "cc", [])
- actor = [message["actor"]]
+ defp try_follow(follower, activity) do
+ to = Map.get(activity, "to", [])
+ cc = Map.get(activity, "cc", [])
+ actor = [activity["actor"]]
Enum.concat([to, cc, actor])
|> List.flatten()
@@ -53,7 +53,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.FollowBotPolicy do
end
end)
- {:ok, message}
+ {:ok, activity}
end
@impl true
diff --git a/lib/pleroma/web/activity_pub/mrf/force_bot_unlisted_policy.ex b/lib/pleroma/web/activity_pub/mrf/force_bot_unlisted_policy.ex
index 8cec8eabe..3b3251dc3 100644
--- a/lib/pleroma/web/activity_pub/mrf/force_bot_unlisted_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/force_bot_unlisted_policy.ex
@@ -22,7 +22,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.ForceBotUnlistedPolicy do
"cc" => cc,
"actor" => actor,
"object" => object
- } = message
+ } = activity
) do
user = User.get_cached_by_ap_id(actor)
isbot = check_if_bot(user)
@@ -36,20 +36,20 @@ defmodule Pleroma.Web.ActivityPub.MRF.ForceBotUnlistedPolicy do
|> Map.put("to", to)
|> Map.put("cc", cc)
- message =
- message
+ activity =
+ activity
|> Map.put("to", to)
|> Map.put("cc", cc)
|> Map.put("object", object)
- {:ok, message}
+ {:ok, activity}
else
- {:ok, message}
+ {:ok, activity}
end
end
@impl true
- def filter(message), do: {:ok, message}
+ def filter(activity), do: {:ok, activity}
@impl true
def describe, do: {:ok, %{}}
diff --git a/lib/pleroma/web/activity_pub/mrf/force_mention.ex b/lib/pleroma/web/activity_pub/mrf/force_mention.ex
index 3853489fc..4ea23540d 100644
--- a/lib/pleroma/web/activity_pub/mrf/force_mention.ex
+++ b/lib/pleroma/web/activity_pub/mrf/force_mention.ex
@@ -52,7 +52,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.ForceMention do
end
@impl true
- def filter(object), do: {:ok, object}
+ def filter(activity), do: {:ok, activity}
@impl true
def describe, do: {:ok, %{}}
diff --git a/lib/pleroma/web/activity_pub/mrf/force_mentions_in_content.ex b/lib/pleroma/web/activity_pub/mrf/force_mentions_in_content.ex
index 5532093cb..caae365e5 100644
--- a/lib/pleroma/web/activity_pub/mrf/force_mentions_in_content.ex
+++ b/lib/pleroma/web/activity_pub/mrf/force_mentions_in_content.ex
@@ -79,18 +79,18 @@ defmodule Pleroma.Web.ActivityPub.MRF.ForceMentionsInContent do
%{
"type" => type,
"object" => %{"type" => "Note", "to" => to, "inReplyTo" => in_reply_to}
- } = object
+ } = activity
)
when type in ["Create", "Update"] and is_list(to) and is_binary(in_reply_to) do
# image-only posts from pleroma apparently reach this MRF without the content field
- content = object["object"]["content"] || ""
+ content = activity["object"]["content"] || ""
# Get the replied-to user for sorting
- replied_to_user = get_replied_to_user(object["object"])
+ replied_to_user = get_replied_to_user(activity["object"])
mention_users =
to
- |> clean_recipients(object)
+ |> clean_recipients(activity)
|> Enum.map(&User.get_cached_by_ap_id/1)
|> Enum.reject(&is_nil/1)
|> sort_replied_user(replied_to_user)
@@ -126,11 +126,11 @@ defmodule Pleroma.Web.ActivityPub.MRF.ForceMentionsInContent do
content
end
- {:ok, put_in(object["object"]["content"], content)}
+ {:ok, put_in(activity["object"]["content"], content)}
end
@impl true
- def filter(object), do: {:ok, object}
+ def filter(activity), do: {:ok, activity}
@impl true
def describe, do: {:ok, %{}}
diff --git a/lib/pleroma/web/activity_pub/mrf/hashtag_policy.ex b/lib/pleroma/web/activity_pub/mrf/hashtag_policy.ex
index fdb9a9dba..72f2274ed 100644
--- a/lib/pleroma/web/activity_pub/mrf/hashtag_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/hashtag_policy.ex
@@ -9,7 +9,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.HashtagPolicy do
alias Pleroma.Object
@moduledoc """
- Reject, TWKN-remove or Set-Sensitive messages with specific hashtags (without the leading #)
+ Reject, TWKN-remove or Set-Sensitive activities with specific hashtags (without the leading #)
Note: This MRF Policy is always enabled, if you want to disable it you have to set empty lists.
"""
@@ -19,40 +19,40 @@ defmodule Pleroma.Web.ActivityPub.MRF.HashtagPolicy do
@impl true
def history_awareness, do: :manual
- defp check_reject(message, hashtags) do
+ defp check_reject(activity, hashtags) do
if Enum.any?(Config.get([:mrf_hashtag, :reject]), fn match -> match in hashtags end) do
{:reject, "[HashtagPolicy] Matches with rejected keyword"}
else
- {:ok, message}
+ {:ok, activity}
end
end
- defp check_ftl_removal(%{"to" => to} = message, hashtags) do
+ defp check_ftl_removal(%{"to" => to} = activity, hashtags) do
if Pleroma.Constants.as_public() in to and
Enum.any?(Config.get([:mrf_hashtag, :federated_timeline_removal]), fn match ->
match in hashtags
end) do
to = List.delete(to, Pleroma.Constants.as_public())
- cc = [Pleroma.Constants.as_public() | message["cc"] || []]
+ cc = [Pleroma.Constants.as_public() | activity["cc"] || []]
- message =
- message
+ activity =
+ activity
|> Map.put("to", to)
|> Map.put("cc", cc)
|> Kernel.put_in(["object", "to"], to)
|> Kernel.put_in(["object", "cc"], cc)
- {:ok, message}
+ {:ok, activity}
else
- {:ok, message}
+ {:ok, activity}
end
end
- defp check_ftl_removal(message, _hashtags), do: {:ok, message}
+ defp check_ftl_removal(activity, _hashtags), do: {:ok, activity}
- defp check_sensitive(message) do
+ defp check_sensitive(activity) do
{:ok, new_object} =
- Object.Updater.do_with_history(message["object"], fn object ->
+ Object.Updater.do_with_history(activity["object"], fn object ->
hashtags = Object.hashtags(%Object{data: object})
if Enum.any?(Config.get([:mrf_hashtag, :sensitive]), fn match -> match in hashtags end) do
@@ -62,11 +62,12 @@ defmodule Pleroma.Web.ActivityPub.MRF.HashtagPolicy do
end
end)
- {:ok, Map.put(message, "object", new_object)}
+ {:ok, Map.put(activity, "object", new_object)}
end
@impl true
- def filter(%{"type" => type, "object" => object} = message) when type in ["Create", "Update"] do
+ def filter(%{"type" => type, "object" => object} = activity)
+ when type in ["Create", "Update"] do
history_items =
with %{"formerRepresentations" => %{"orderedItems" => items}} <- object do
items
@@ -82,23 +83,23 @@ defmodule Pleroma.Web.ActivityPub.MRF.HashtagPolicy do
hashtags = Object.hashtags(%Object{data: object}) ++ historical_hashtags
if hashtags != [] do
- with {:ok, message} <- check_reject(message, hashtags),
- {:ok, message} <-
+ with {:ok, activity} <- check_reject(activity, hashtags),
+ {:ok, activity} <-
(if type == "Create" do
- check_ftl_removal(message, hashtags)
+ check_ftl_removal(activity, hashtags)
else
- {:ok, message}
+ {:ok, activity}
end),
- {:ok, message} <- check_sensitive(message) do
- {:ok, message}
+ {:ok, activity} <- check_sensitive(activity) do
+ {:ok, activity}
end
else
- {:ok, message}
+ {:ok, activity}
end
end
@impl true
- def filter(message), do: {:ok, message}
+ def filter(activity), do: {:ok, activity}
@impl true
def describe do
@@ -120,21 +121,21 @@ defmodule Pleroma.Web.ActivityPub.MRF.HashtagPolicy do
%{
key: :reject,
type: {:list, :string},
- description: "A list of hashtags which result in message being rejected.",
+ description: "A list of hashtags which result in the activity being rejected.",
suggestions: ["foo"]
},
%{
key: :federated_timeline_removal,
type: {:list, :string},
description:
- "A list of hashtags which result in message being removed from federated timelines (a.k.a unlisted).",
+ "A list of hashtags which result in the activity being removed from federated timelines (a.k.a unlisted).",
suggestions: ["foo"]
},
%{
key: :sensitive,
type: {:list, :string},
description:
- "A list of hashtags which result in message being set as sensitive (a.k.a NSFW/R-18)",
+ "A list of hashtags which result in the activity being set as sensitive (a.k.a NSFW/R-18)",
suggestions: ["nsfw", "r18"]
}
]
diff --git a/lib/pleroma/web/activity_pub/mrf/hellthread_policy.ex b/lib/pleroma/web/activity_pub/mrf/hellthread_policy.ex
index 80e235d6e..3a80d0a69 100644
--- a/lib/pleroma/web/activity_pub/mrf/hellthread_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/hellthread_policy.ex
@@ -7,54 +7,54 @@ defmodule Pleroma.Web.ActivityPub.MRF.HellthreadPolicy do
require Pleroma.Constants
- @moduledoc "Block messages with too much mentions (configurable)"
+ @moduledoc "Block activities with too much mentions (configurable)"
@behaviour Pleroma.Web.ActivityPub.MRF.Policy
- defp delist_message(message, threshold) when threshold > 0 do
- follower_collection = User.get_cached_by_ap_id(message["actor"]).follower_address
- to = message["to"] || []
- cc = message["cc"] || []
+ defp delist_activity(activity, threshold) when threshold > 0 do
+ follower_collection = User.get_cached_by_ap_id(activity["actor"]).follower_address
+ to = activity["to"] || []
+ cc = activity["cc"] || []
follower_collection? = Enum.member?(to ++ cc, follower_collection)
- message =
- case get_recipient_count(message) do
+ activity =
+ case get_recipient_count(activity) do
{:public, recipients}
when follower_collection? and recipients > threshold ->
- message
+ activity
|> Map.put("to", [follower_collection])
|> Map.put("cc", [Pleroma.Constants.as_public()])
{:public, recipients} when recipients > threshold ->
- message
+ activity
|> Map.put("to", [])
|> Map.put("cc", [Pleroma.Constants.as_public()])
_ ->
- message
+ activity
end
- {:ok, message}
+ {:ok, activity}
end
- defp delist_message(message, _threshold), do: {:ok, message}
+ defp delist_activity(activity, _threshold), do: {:ok, activity}
- defp reject_message(message, threshold) when threshold > 0 do
- with {_, recipients} <- get_recipient_count(message) do
+ defp reject_activity(activity, threshold) when threshold > 0 do
+ with {_, recipients} <- get_recipient_count(activity) do
if recipients > threshold do
{:reject, "[HellthreadPolicy] #{recipients} recipients is over the limit of #{threshold}"}
else
- {:ok, message}
+ {:ok, activity}
end
end
end
- defp reject_message(message, _threshold), do: {:ok, message}
+ defp reject_activity(activity, _threshold), do: {:ok, activity}
- defp get_recipient_count(message) do
- recipients = (message["to"] || []) ++ (message["cc"] || [])
- follower_collection = User.get_cached_by_ap_id(message["actor"]).follower_address
+ defp get_recipient_count(activity) do
+ recipients = (activity["to"] || []) ++ (activity["cc"] || [])
+ follower_collection = User.get_cached_by_ap_id(activity["actor"]).follower_address
if Enum.member?(recipients, Pleroma.Constants.as_public()) do
recipients =
@@ -73,7 +73,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.HellthreadPolicy do
end
@impl true
- def filter(%{"type" => "Create", "object" => %{"type" => object_type}} = message)
+ def filter(%{"type" => "Create", "object" => %{"type" => object_type}} = activity)
when object_type in ~w{Note Article} do
reject_threshold =
Pleroma.Config.get(
@@ -83,16 +83,16 @@ defmodule Pleroma.Web.ActivityPub.MRF.HellthreadPolicy do
delist_threshold = Pleroma.Config.get([:mrf_hellthread, :delist_threshold])
- with {:ok, message} <- reject_message(message, reject_threshold),
- {:ok, message} <- delist_message(message, delist_threshold) do
- {:ok, message}
+ with {:ok, activity} <- reject_activity(activity, reject_threshold),
+ {:ok, activity} <- delist_activity(activity, delist_threshold) do
+ {:ok, activity}
else
e -> e
end
end
@impl true
- def filter(message), do: {:ok, message}
+ def filter(activity), do: {:ok, activity}
@impl true
def describe,
@@ -104,13 +104,13 @@ defmodule Pleroma.Web.ActivityPub.MRF.HellthreadPolicy do
key: :mrf_hellthread,
related_policy: "Pleroma.Web.ActivityPub.MRF.HellthreadPolicy",
label: "MRF Hellthread",
- description: "Block messages with excessive user mentions",
+ description: "Block activities with excessive user mentions",
children: [
%{
key: :delist_threshold,
type: :integer,
description:
- "Number of mentioned users after which the message gets removed from timelines and" <>
+ "Number of mentioned users after which the activity gets removed from timelines and" <>
"disables notifications. Set to 0 to disable.",
suggestions: [10]
},
@@ -118,7 +118,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.HellthreadPolicy do
key: :reject_threshold,
type: :integer,
description:
- "Number of mentioned users after which the messaged gets rejected. Set to 0 to disable.",
+ "Number of mentioned users after which the activity gets rejected. Set to 0 to disable.",
suggestions: [20]
}
]
diff --git a/lib/pleroma/web/activity_pub/mrf/inline_quote_policy.ex b/lib/pleroma/web/activity_pub/mrf/inline_quote_policy.ex
index b7a01c27c..469d06ef6 100644
--- a/lib/pleroma/web/activity_pub/mrf/inline_quote_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/inline_quote_policy.ex
@@ -48,12 +48,12 @@ defmodule Pleroma.Web.ActivityPub.MRF.InlineQuotePolicy do
end
@impl true
- def filter(object), do: {:ok, object}
+ def filter(activity), do: {:ok, activity}
@impl true
def describe, do: {:ok, %{}}
- @impl Pleroma.Web.ActivityPub.MRF.Policy
+ @impl true
def history_awareness, do: :auto
@impl true
diff --git a/lib/pleroma/web/activity_pub/mrf/keyword_policy.ex b/lib/pleroma/web/activity_pub/mrf/keyword_policy.ex
index 729da4e9c..6ba6fd509 100644
--- a/lib/pleroma/web/activity_pub/mrf/keyword_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/keyword_policy.ex
@@ -7,7 +7,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicy do
alias Pleroma.Web.ActivityPub.MRF.Utils
- @moduledoc "Reject or Word-Replace messages with a keyword or regex"
+ @moduledoc "Reject or Word-Replace activities with a keyword or regex"
@behaviour Pleroma.Web.ActivityPub.MRF.Policy
@@ -25,7 +25,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicy do
|> Enum.join("\n")
end
- defp check_reject(%{"object" => %{} = object} = message) do
+ defp check_reject(%{"object" => %{} = object} = activity) do
with {:ok, _new_object} <-
Pleroma.Object.Updater.do_with_history(object, fn object ->
payload = object_payload(object)
@@ -35,16 +35,16 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicy do
end) do
{:reject, "[KeywordPolicy] Matches with rejected keyword"}
else
- {:ok, message}
+ {:ok, activity}
end
end) do
- {:ok, message}
+ {:ok, activity}
else
e -> e
end
end
- defp check_ftl_removal(%{"type" => "Create", "to" => to, "object" => %{} = object} = message) do
+ defp check_ftl_removal(%{"type" => "Create", "to" => to, "object" => %{} = object} = activity) do
check_keyword = fn object ->
payload = object_payload(object)
@@ -67,24 +67,24 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicy do
if Pleroma.Constants.as_public() in to and should_delist?.(object) do
to = List.delete(to, Pleroma.Constants.as_public())
- cc = [Pleroma.Constants.as_public() | message["cc"] || []]
+ cc = [Pleroma.Constants.as_public() | activity["cc"] || []]
- message =
- message
+ activity =
+ activity
|> Map.put("to", to)
|> Map.put("cc", cc)
- {:ok, message}
+ {:ok, activity}
else
- {:ok, message}
+ {:ok, activity}
end
end
- defp check_ftl_removal(message) do
- {:ok, message}
+ defp check_ftl_removal(activity) do
+ {:ok, activity}
end
- defp check_replace(%{"object" => %{} = object} = message) do
+ defp check_replace(%{"object" => %{} = object} = activity) do
replace_kw = fn object ->
["content", "name", "summary"]
|> Enum.filter(fn field -> Map.has_key?(object, field) && object[field] end)
@@ -103,18 +103,18 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicy do
{:ok, object} = Pleroma.Object.Updater.do_with_history(object, replace_kw)
- message = Map.put(message, "object", object)
+ activity = Map.put(activity, "object", object)
- {:ok, message}
+ {:ok, activity}
end
@impl true
- def filter(%{"type" => type, "object" => %{"content" => _content}} = message)
+ def filter(%{"type" => type, "object" => %{"content" => _content}} = activity)
when type in ["Create", "Update"] do
- with {:ok, message} <- check_reject(message),
- {:ok, message} <- check_ftl_removal(message),
- {:ok, message} <- check_replace(message) do
- {:ok, message}
+ with {:ok, activity} <- check_reject(activity),
+ {:ok, activity} <- check_ftl_removal(activity),
+ {:ok, activity} <- check_replace(activity) do
+ {:ok, activity}
else
{:reject, nil} -> {:reject, "[KeywordPolicy] "}
{:reject, _} = e -> e
@@ -123,7 +123,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicy do
end
@impl true
- def filter(message), do: {:ok, message}
+ def filter(activity), do: {:ok, activity}
@impl true
def describe do
@@ -154,13 +154,13 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicy do
related_policy: "Pleroma.Web.ActivityPub.MRF.KeywordPolicy",
label: "MRF Keyword",
description:
- "Reject or Word-Replace messages matching a keyword or [Regex](https://hexdocs.pm/elixir/Regex.html).",
+ "Reject or Word-Replace activities matching a keyword or [Regex](https://hexdocs.pm/elixir/Regex.html).",
children: [
%{
key: :reject,
type: {:list, :string},
description: """
- A list of patterns which result in message being rejected.
+ A list of patterns which result in the activity being rejected.
Each pattern can be a string or [Regex](https://hexdocs.pm/elixir/Regex.html) in the format of `~r/PATTERN/`.
""",
@@ -170,7 +170,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicy do
key: :federated_timeline_removal,
type: {:list, :string},
description: """
- A list of patterns which result in message being removed from federated timelines (a.k.a unlisted).
+ A list of patterns which result in the activity being removed from federated timelines (a.k.a unlisted).
Each pattern can be a string or [Regex](https://hexdocs.pm/elixir/Regex.html) in the format of `~r/PATTERN/`.
""",
diff --git a/lib/pleroma/web/activity_pub/mrf/media_proxy_warming_policy.ex b/lib/pleroma/web/activity_pub/mrf/media_proxy_warming_policy.ex
index 0c5b53def..b0d07a6f8 100644
--- a/lib/pleroma/web/activity_pub/mrf/media_proxy_warming_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/media_proxy_warming_policy.ex
@@ -31,7 +31,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.MediaProxyWarmingPolicy do
HTTP.get(url, [], http_client_opts)
end
- defp preload(%{"object" => %{"attachment" => attachments}} = _message) do
+ defp preload(%{"object" => %{"attachment" => attachments}} = _activity) do
Enum.each(attachments, fn
%{"url" => url} when is_list(url) ->
url
@@ -49,15 +49,15 @@ defmodule Pleroma.Web.ActivityPub.MRF.MediaProxyWarmingPolicy do
end
@impl true
- def filter(%{"type" => type, "object" => %{"attachment" => attachments} = _object} = message)
+ def filter(%{"type" => type, "object" => %{"attachment" => attachments} = _object} = activity)
when type in ["Create", "Update"] and is_list(attachments) and length(attachments) > 0 do
- preload(message)
+ preload(activity)
- {:ok, message}
+ {:ok, activity}
end
@impl true
- def filter(message), do: {:ok, message}
+ def filter(activity), do: {:ok, activity}
@impl true
def describe, do: {:ok, %{}}
diff --git a/lib/pleroma/web/activity_pub/mrf/mention_policy.ex b/lib/pleroma/web/activity_pub/mrf/mention_policy.ex
index 8aa4f347f..f7bff121f 100644
--- a/lib/pleroma/web/activity_pub/mrf/mention_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/mention_policy.ex
@@ -3,25 +3,25 @@
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.MRF.MentionPolicy do
- @moduledoc "Block messages which mention a user"
+ @moduledoc "Block activities which mention a user"
@behaviour Pleroma.Web.ActivityPub.MRF.Policy
@impl true
- def filter(%{"type" => "Create"} = message) do
+ def filter(%{"type" => "Create"} = activity) do
reject_actors = Pleroma.Config.get([:mrf_mention, :actors], [])
- recipients = (message["to"] || []) ++ (message["cc"] || [])
+ recipients = (activity["to"] || []) ++ (activity["cc"] || [])
if rejected_mention =
Enum.find(recipients, fn recipient -> Enum.member?(reject_actors, recipient) end) do
{:reject, "[MentionPolicy] Rejected for mention of #{rejected_mention}"}
else
- {:ok, message}
+ {:ok, activity}
end
end
@impl true
- def filter(message), do: {:ok, message}
+ def filter(activity), do: {:ok, activity}
@impl true
def describe, do: {:ok, %{}}
@@ -32,7 +32,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.MentionPolicy do
key: :mrf_mention,
related_policy: "Pleroma.Web.ActivityPub.MRF.MentionPolicy",
label: "MRF Mention",
- description: "Block messages which mention a specific user",
+ description: "Block activities which mention a specific user",
children: [
%{
key: :actors,
diff --git a/lib/pleroma/web/activity_pub/mrf/no_empty_policy.ex b/lib/pleroma/web/activity_pub/mrf/no_empty_policy.ex
index 12bf4ddd2..08dd39878 100644
--- a/lib/pleroma/web/activity_pub/mrf/no_empty_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/no_empty_policy.ex
@@ -9,20 +9,20 @@ defmodule Pleroma.Web.ActivityPub.MRF.NoEmptyPolicy do
alias Pleroma.Web.Endpoint
@impl true
- def filter(%{"actor" => actor} = object) do
+ def filter(%{"actor" => actor} = activity) do
with true <- local?(actor),
- true <- eligible_type?(object),
- true <- note?(object),
- false <- has_attachment?(object),
- true <- only_mentions?(object) do
+ true <- eligible_type?(activity),
+ true <- note?(activity),
+ false <- has_attachment?(activity),
+ true <- only_mentions?(activity) do
{:reject, "[NoEmptyPolicy]"}
else
_ ->
- {:ok, object}
+ {:ok, activity}
end
end
- def filter(object), do: {:ok, object}
+ def filter(activity), do: {:ok, activity}
defp local?(actor) do
if actor |> String.starts_with?("#{Endpoint.url()}") do
diff --git a/lib/pleroma/web/activity_pub/mrf/no_op_policy.ex b/lib/pleroma/web/activity_pub/mrf/no_op_policy.ex
index 8840c4fac..64a5872bc 100644
--- a/lib/pleroma/web/activity_pub/mrf/no_op_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/no_op_policy.ex
@@ -7,8 +7,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.NoOpPolicy do
@behaviour Pleroma.Web.ActivityPub.MRF.Policy
@impl true
- def filter(object) do
- {:ok, object}
+ def filter(activity) do
+ {:ok, activity}
end
@impl true
diff --git a/lib/pleroma/web/activity_pub/mrf/no_placeholder_text_policy.ex b/lib/pleroma/web/activity_pub/mrf/no_placeholder_text_policy.ex
index f81e9e52a..c6f239a5e 100644
--- a/lib/pleroma/web/activity_pub/mrf/no_placeholder_text_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/no_placeholder_text_policy.ex
@@ -13,15 +13,15 @@ defmodule Pleroma.Web.ActivityPub.MRF.NoPlaceholderTextPolicy do
def filter(
%{
"type" => type,
- "object" => %{"content" => content, "attachment" => _} = _child_object
- } = object
+ "object" => %{"content" => content, "attachment" => _} = _object
+ } = activity
)
when type in ["Create", "Update"] and content in [".", "<p>.</p>"] do
- {:ok, put_in(object, ["object", "content"], "")}
+ {:ok, put_in(activity, ["object", "content"], "")}
end
@impl true
- def filter(object), do: {:ok, object}
+ def filter(activity), do: {:ok, activity}
@impl true
def describe, do: {:ok, %{}}
diff --git a/lib/pleroma/web/activity_pub/mrf/normalize_markup.ex b/lib/pleroma/web/activity_pub/mrf/normalize_markup.ex
index 2dfc9a901..91855ef84 100644
--- a/lib/pleroma/web/activity_pub/mrf/normalize_markup.ex
+++ b/lib/pleroma/web/activity_pub/mrf/normalize_markup.ex
@@ -12,20 +12,20 @@ defmodule Pleroma.Web.ActivityPub.MRF.NormalizeMarkup do
def history_awareness, do: :auto
@impl true
- def filter(%{"type" => type, "object" => child_object} = object)
+ def filter(%{"type" => type, "object" => object} = activity)
when type in ["Create", "Update"] do
scrub_policy = Pleroma.Config.get([:mrf_normalize_markup, :scrub_policy])
content =
- child_object["content"]
+ object["content"]
|> HTML.filter_tags(scrub_policy)
- object = put_in(object, ["object", "content"], content)
+ activity = put_in(activity, ["object", "content"], content)
- {:ok, object}
+ {:ok, activity}
end
- def filter(object), do: {:ok, object}
+ def filter(activity), do: {:ok, activity}
@impl true
def describe, do: {:ok, %{}}
diff --git a/lib/pleroma/web/activity_pub/mrf/nsfw_api_policy.ex b/lib/pleroma/web/activity_pub/mrf/nsfw_api_policy.ex
index 451a212d4..52aaf05aa 100644
--- a/lib/pleroma/web/activity_pub/mrf/nsfw_api_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/nsfw_api_policy.ex
@@ -122,52 +122,52 @@ defmodule Pleroma.Web.ActivityPub.MRF.NsfwApiPolicy do
end
end
- def check_object_nsfw(%{"object" => %{} = child_object} = object) do
- case check_object_nsfw(child_object) do
- {:sfw, _} -> {:sfw, object}
- {:nsfw, _} -> {:nsfw, object}
+ def check_object_nsfw(%{"object" => %{} = object} = activity) do
+ case check_object_nsfw(object) do
+ {:sfw, _} -> {:sfw, activity}
+ {:nsfw, _} -> {:nsfw, activity}
end
end
def check_object_nsfw(object), do: {:sfw, object}
@impl true
- def filter(object) do
- with {:sfw, object} <- check_object_nsfw(object) do
- {:ok, object}
+ def filter(activity) do
+ with {:sfw, activity} <- check_object_nsfw(activity) do
+ {:ok, activity}
else
- {:nsfw, _data} -> handle_nsfw(object)
+ {:nsfw, _data} -> handle_nsfw(activity)
end
end
- defp handle_nsfw(object) do
+ defp handle_nsfw(activity) do
if Config.get([@policy, :reject]) do
- {:reject, object}
+ {:reject, activity}
else
{:ok,
- object
+ activity
|> maybe_unlist()
|> maybe_mark_sensitive()}
end
end
- defp maybe_unlist(object) do
+ defp maybe_unlist(activity) do
if Config.get([@policy, :unlist]) do
- unlist(object)
+ unlist(activity)
else
- object
+ activity
end
end
- defp maybe_mark_sensitive(object) do
+ defp maybe_mark_sensitive(activity) do
if Config.get([@policy, :mark_sensitive]) do
- mark_sensitive(object)
+ mark_sensitive(activity)
else
- object
+ activity
end
end
- def unlist(%{"to" => to, "cc" => cc, "actor" => actor} = object) do
+ def unlist(%{"to" => to, "cc" => cc, "actor" => actor} = activity) do
with %User{} = user <- User.get_cached_by_ap_id(actor) do
to =
[user.follower_address | to]
@@ -179,7 +179,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.NsfwApiPolicy do
|> List.delete(user.follower_address)
|> Enum.uniq()
- object
+ activity
|> Map.put("to", to)
|> Map.put("cc", cc)
else
@@ -187,14 +187,14 @@ defmodule Pleroma.Web.ActivityPub.MRF.NsfwApiPolicy do
end
end
- def mark_sensitive(%{"object" => child_object} = object) when is_map(child_object) do
- Map.put(object, "object", mark_sensitive(child_object))
+ def mark_sensitive(%{"object" => object} = activity) when is_map(object) do
+ Map.put(activity, "object", mark_sensitive(object))
end
- def mark_sensitive(object) when is_map(object) do
- tags = (object["tag"] || []) ++ ["nsfw"]
+ def mark_sensitive(activity) when is_map(activity) do
+ tags = (activity["tag"] || []) ++ ["nsfw"]
- object
+ activity
|> Map.put("tag", tags)
|> Map.put("sensitive", true)
end
diff --git a/lib/pleroma/web/activity_pub/mrf/object_age_policy.ex b/lib/pleroma/web/activity_pub/mrf/object_age_policy.ex
index df1a6dcbb..34905fc21 100644
--- a/lib/pleroma/web/activity_pub/mrf/object_age_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/object_age_policy.ex
@@ -11,12 +11,12 @@ defmodule Pleroma.Web.ActivityPub.MRF.ObjectAgePolicy do
@moduledoc "Filter activities depending on their age"
@behaviour Pleroma.Web.ActivityPub.MRF.Policy
- defp check_date(%{"object" => %{"published" => published}} = message) do
+ defp check_date(%{"object" => %{"published" => published}} = activity) do
with %DateTime{} = now <- DateTime.utc_now(),
{:ok, %DateTime{} = then, _} <- DateTime.from_iso8601(published),
max_ttl <- Config.get([:mrf_object_age, :threshold]),
{:ttl, false} <- {:ttl, DateTime.diff(now, then) > max_ttl} do
- {:ok, message}
+ {:ok, activity}
else
{:ttl, true} ->
{:reject, nil}
@@ -26,73 +26,73 @@ defmodule Pleroma.Web.ActivityPub.MRF.ObjectAgePolicy do
end
end
- defp check_reject(message, actions) do
+ defp check_reject(activity, actions) do
if :reject in actions do
{:reject, "[ObjectAgePolicy]"}
else
- {:ok, message}
+ {:ok, activity}
end
end
- defp check_delist(message, actions) do
+ defp check_delist(activity, actions) do
if :delist in actions do
- with %User{} = user <- User.get_cached_by_ap_id(message["actor"]) do
+ with %User{} = user <- User.get_cached_by_ap_id(activity["actor"]) do
to =
- List.delete(message["to"] || [], Pleroma.Constants.as_public()) ++
+ List.delete(activity["to"] || [], Pleroma.Constants.as_public()) ++
[user.follower_address]
cc =
- List.delete(message["cc"] || [], user.follower_address) ++
+ List.delete(activity["cc"] || [], user.follower_address) ++
[Pleroma.Constants.as_public()]
- message =
- message
+ activity =
+ activity
|> Map.put("to", to)
|> Map.put("cc", cc)
|> Kernel.put_in(["object", "to"], to)
|> Kernel.put_in(["object", "cc"], cc)
- {:ok, message}
+ {:ok, activity}
else
_e ->
{:reject, "[ObjectAgePolicy] Unhandled error"}
end
else
- {:ok, message}
+ {:ok, activity}
end
end
- defp check_strip_followers(message, actions) do
+ defp check_strip_followers(activity, actions) do
if :strip_followers in actions do
- with %User{} = user <- User.get_cached_by_ap_id(message["actor"]) do
- to = List.delete(message["to"] || [], user.follower_address)
- cc = List.delete(message["cc"] || [], user.follower_address)
+ with %User{} = user <- User.get_cached_by_ap_id(activity["actor"]) do
+ to = List.delete(activity["to"] || [], user.follower_address)
+ cc = List.delete(activity["cc"] || [], user.follower_address)
- message =
- message
+ activity =
+ activity
|> Map.put("to", to)
|> Map.put("cc", cc)
|> Kernel.put_in(["object", "to"], to)
|> Kernel.put_in(["object", "cc"], cc)
- {:ok, message}
+ {:ok, activity}
else
_e ->
{:reject, "[ObjectAgePolicy] Unhandled error"}
end
else
- {:ok, message}
+ {:ok, activity}
end
end
@impl true
- def filter(%{"type" => "Create", "object" => %{"published" => _}} = message) do
+ def filter(%{"type" => "Create", "object" => %{"published" => _}} = activity) do
with actions <- Config.get([:mrf_object_age, :actions]),
- {:reject, _} <- check_date(message),
- {:ok, message} <- check_reject(message, actions),
- {:ok, message} <- check_delist(message, actions),
- {:ok, message} <- check_strip_followers(message, actions) do
- {:ok, message}
+ {:reject, _} <- check_date(activity),
+ {:ok, activity} <- check_reject(activity, actions),
+ {:ok, activity} <- check_delist(activity, actions),
+ {:ok, activity} <- check_strip_followers(activity, actions) do
+ {:ok, activity}
else
# check_date() is allowed to short-circuit the pipeline
e -> e
@@ -100,7 +100,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.ObjectAgePolicy do
end
@impl true
- def filter(message), do: {:ok, message}
+ def filter(activity), do: {:ok, activity}
@impl true
def describe do
@@ -131,8 +131,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.ObjectAgePolicy do
type: {:list, :atom},
description:
"A list of actions to apply to the post. `:delist` removes the post from public timelines; " <>
- "`:strip_followers` removes followers from the ActivityPub recipient list ensuring they won't be delivered to home timelines, additionally for followers-only it degrades to a direct message; " <>
- "`:reject` rejects the message entirely",
+ "`:strip_followers` removes followers from the ActivityPub recipient list ensuring they won't be delivered to home timelines, additionally for followers-only it degrades to a direct activity; " <>
+ "`:reject` rejects the activity entirely",
suggestions: [:delist, :strip_followers, :reject]
}
]
diff --git a/lib/pleroma/web/activity_pub/mrf/policy.ex b/lib/pleroma/web/activity_pub/mrf/policy.ex
index 1f34883e7..54ca4b735 100644
--- a/lib/pleroma/web/activity_pub/mrf/policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/policy.ex
@@ -3,7 +3,7 @@
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.MRF.Policy do
- @callback filter(map()) :: {:ok | :reject, map()}
+ @callback filter(Pleroma.Activity.t()) :: {:ok | :reject, Pleroma.Activity.t()}
@callback describe() :: {:ok | :error, map()}
@callback config_description() :: %{
optional(:children) => [map()],
diff --git a/lib/pleroma/web/activity_pub/mrf/quiet_reply.ex b/lib/pleroma/web/activity_pub/mrf/quiet_reply.ex
new file mode 100644
index 000000000..b07dc3b56
--- /dev/null
+++ b/lib/pleroma/web/activity_pub/mrf/quiet_reply.ex
@@ -0,0 +1,60 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2023 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.ActivityPub.MRF.QuietReply do
+ @moduledoc """
+ QuietReply alters the scope of activities from local users when replying by enforcing them to be "Unlisted" or "Quiet Public". This delivers the activity to all the expected recipients and instances, but it will not be published in the Federated / The Whole Known Network timelines. It will still be published to the Home timelines of the user's followers and visible to anyone who opens the thread.
+ """
+ require Pleroma.Constants
+
+ alias Pleroma.User
+
+ @behaviour Pleroma.Web.ActivityPub.MRF.Policy
+
+ @impl true
+ def history_awareness, do: :auto
+
+ @impl true
+ def filter(
+ %{
+ "type" => "Create",
+ "to" => to,
+ "cc" => cc,
+ "object" => %{
+ "actor" => actor,
+ "type" => "Note",
+ "inReplyTo" => in_reply_to
+ }
+ } = activity
+ ) do
+ with true <- is_binary(in_reply_to),
+ false <- match?([], cc),
+ %User{follower_address: followers_collection, local: true} <-
+ User.get_by_ap_id(actor) do
+ updated_to =
+ to
+ |> Kernel.++([followers_collection])
+ |> Kernel.--([Pleroma.Constants.as_public()])
+
+ updated_cc = [Pleroma.Constants.as_public()]
+
+ updated_activity =
+ activity
+ |> Map.put("to", updated_to)
+ |> Map.put("cc", updated_cc)
+ |> put_in(["object", "to"], updated_to)
+ |> put_in(["object", "cc"], updated_cc)
+
+ {:ok, updated_activity}
+ else
+ _ -> {:ok, activity}
+ end
+ end
+
+ @impl true
+ def filter(activity), do: {:ok, activity}
+
+ @impl true
+ def describe, do: {:ok, %{}}
+end
diff --git a/lib/pleroma/web/activity_pub/mrf/quote_to_link_tag_policy.ex b/lib/pleroma/web/activity_pub/mrf/quote_to_link_tag_policy.ex
index ac353f03f..2a17b6761 100644
--- a/lib/pleroma/web/activity_pub/mrf/quote_to_link_tag_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/quote_to_link_tag_policy.ex
@@ -10,18 +10,18 @@ defmodule Pleroma.Web.ActivityPub.MRF.QuoteToLinkTagPolicy do
require Pleroma.Constants
- @impl Pleroma.Web.ActivityPub.MRF.Policy
+ @impl true
def filter(%{"object" => %{"quoteUrl" => _} = object} = activity) do
{:ok, Map.put(activity, "object", filter_object(object))}
end
- @impl Pleroma.Web.ActivityPub.MRF.Policy
- def filter(object), do: {:ok, object}
+ @impl true
+ def filter(activity), do: {:ok, activity}
- @impl Pleroma.Web.ActivityPub.MRF.Policy
+ @impl true
def describe, do: {:ok, %{}}
- @impl Pleroma.Web.ActivityPub.MRF.Policy
+ @impl true
def history_awareness, do: :auto
defp filter_object(%{"quoteUrl" => quote_url} = object) do
diff --git a/lib/pleroma/web/activity_pub/mrf/simple_policy.ex b/lib/pleroma/web/activity_pub/mrf/simple_policy.ex
index d708c99eb..ae7f18bfe 100644
--- a/lib/pleroma/web/activity_pub/mrf/simple_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/simple_policy.ex
@@ -13,20 +13,20 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicy do
require Pleroma.Constants
- defp check_accept(%{host: actor_host} = _actor_info, object) do
+ defp check_accept(%{host: actor_host} = _actor_info, activity) do
accepts =
instance_list(:accept)
|> MRF.subdomains_regex()
cond do
- accepts == [] -> {:ok, object}
- actor_host == Config.get([Pleroma.Web.Endpoint, :url, :host]) -> {:ok, object}
- MRF.subdomain_match?(accepts, actor_host) -> {:ok, object}
+ accepts == [] -> {:ok, activity}
+ actor_host == Config.get([Pleroma.Web.Endpoint, :url, :host]) -> {:ok, activity}
+ MRF.subdomain_match?(accepts, actor_host) -> {:ok, activity}
true -> {:reject, "[SimplePolicy] host not in accept list"}
end
end
- defp check_reject(%{host: actor_host} = _actor_info, object) do
+ defp check_reject(%{host: actor_host} = _actor_info, activity) do
rejects =
instance_list(:reject)
|> MRF.subdomains_regex()
@@ -34,109 +34,109 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicy do
if MRF.subdomain_match?(rejects, actor_host) do
{:reject, "[SimplePolicy] host in reject list"}
else
- {:ok, object}
+ {:ok, activity}
end
end
defp check_media_removal(
%{host: actor_host} = _actor_info,
- %{"type" => type, "object" => %{"attachment" => child_attachment}} = object
+ %{"type" => type, "object" => %{"attachment" => object_attachment}} = activity
)
- when length(child_attachment) > 0 and type in ["Create", "Update"] do
+ when length(object_attachment) > 0 and type in ["Create", "Update"] do
media_removal =
instance_list(:media_removal)
|> MRF.subdomains_regex()
- object =
+ activity =
if MRF.subdomain_match?(media_removal, actor_host) do
- child_object = Map.delete(object["object"], "attachment")
- Map.put(object, "object", child_object)
+ object = Map.delete(activity["object"], "attachment")
+ Map.put(activity, "object", object)
else
- object
+ activity
end
- {:ok, object}
+ {:ok, activity}
end
- defp check_media_removal(_actor_info, object), do: {:ok, object}
+ defp check_media_removal(_actor_info, activity), do: {:ok, activity}
defp check_media_nsfw(
%{host: actor_host} = _actor_info,
%{
"type" => type,
- "object" => %{} = _child_object
- } = object
+ "object" => %{} = _object
+ } = activity
)
when type in ["Create", "Update"] do
media_nsfw =
instance_list(:media_nsfw)
|> MRF.subdomains_regex()
- object =
+ activity =
if MRF.subdomain_match?(media_nsfw, actor_host) do
- Kernel.put_in(object, ["object", "sensitive"], true)
+ Kernel.put_in(activity, ["object", "sensitive"], true)
else
- object
+ activity
end
- {:ok, object}
+ {:ok, activity}
end
- defp check_media_nsfw(_actor_info, object), do: {:ok, object}
+ defp check_media_nsfw(_actor_info, activity), do: {:ok, activity}
- defp check_ftl_removal(%{host: actor_host} = _actor_info, object) do
+ defp check_ftl_removal(%{host: actor_host} = _actor_info, activity) do
timeline_removal =
instance_list(:federated_timeline_removal)
|> MRF.subdomains_regex()
- object =
+ activity =
with true <- MRF.subdomain_match?(timeline_removal, actor_host),
- user <- User.get_cached_by_ap_id(object["actor"]),
- true <- Pleroma.Constants.as_public() in object["to"] do
- to = List.delete(object["to"], Pleroma.Constants.as_public()) ++ [user.follower_address]
+ user <- User.get_cached_by_ap_id(activity["actor"]),
+ true <- Pleroma.Constants.as_public() in activity["to"] do
+ to = List.delete(activity["to"], Pleroma.Constants.as_public()) ++ [user.follower_address]
- cc = List.delete(object["cc"], user.follower_address) ++ [Pleroma.Constants.as_public()]
+ cc = List.delete(activity["cc"], user.follower_address) ++ [Pleroma.Constants.as_public()]
- object
+ activity
|> Map.put("to", to)
|> Map.put("cc", cc)
else
- _ -> object
+ _ -> activity
end
- {:ok, object}
+ {:ok, activity}
end
defp intersection(list1, list2) do
list1 -- list1 -- list2
end
- defp check_followers_only(%{host: actor_host} = _actor_info, object) do
+ defp check_followers_only(%{host: actor_host} = _actor_info, activity) do
followers_only =
instance_list(:followers_only)
|> MRF.subdomains_regex()
- object =
+ activity =
with true <- MRF.subdomain_match?(followers_only, actor_host),
- user <- User.get_cached_by_ap_id(object["actor"]) do
+ user <- User.get_cached_by_ap_id(activity["actor"]) do
# Don't use Map.get/3 intentionally, these must not be nil
- fixed_to = object["to"] || []
- fixed_cc = object["cc"] || []
+ fixed_to = activity["to"] || []
+ fixed_cc = activity["cc"] || []
to = FollowingRelationship.followers_ap_ids(user, fixed_to)
cc = FollowingRelationship.followers_ap_ids(user, fixed_cc)
- object
+ activity
|> Map.put("to", intersection([user.follower_address | to], fixed_to))
|> Map.put("cc", intersection([user.follower_address | cc], fixed_cc))
else
- _ -> object
+ _ -> activity
end
- {:ok, object}
+ {:ok, activity}
end
- defp check_report_removal(%{host: actor_host} = _actor_info, %{"type" => "Flag"} = object) do
+ defp check_report_removal(%{host: actor_host} = _actor_info, %{"type" => "Flag"} = activity) do
report_removal =
instance_list(:report_removal)
|> MRF.subdomains_regex()
@@ -144,39 +144,39 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicy do
if MRF.subdomain_match?(report_removal, actor_host) do
{:reject, "[SimplePolicy] host in report_removal list"}
else
- {:ok, object}
+ {:ok, activity}
end
end
- defp check_report_removal(_actor_info, object), do: {:ok, object}
+ defp check_report_removal(_actor_info, activity), do: {:ok, activity}
- defp check_avatar_removal(%{host: actor_host} = _actor_info, %{"icon" => _icon} = object) do
+ defp check_avatar_removal(%{host: actor_host} = _actor_info, %{"icon" => _icon} = activity) do
avatar_removal =
instance_list(:avatar_removal)
|> MRF.subdomains_regex()
if MRF.subdomain_match?(avatar_removal, actor_host) do
- {:ok, Map.delete(object, "icon")}
+ {:ok, Map.delete(activity, "icon")}
else
- {:ok, object}
+ {:ok, activity}
end
end
- defp check_avatar_removal(_actor_info, object), do: {:ok, object}
+ defp check_avatar_removal(_actor_info, activity), do: {:ok, activity}
- defp check_banner_removal(%{host: actor_host} = _actor_info, %{"image" => _image} = object) do
+ defp check_banner_removal(%{host: actor_host} = _actor_info, %{"image" => _image} = activity) do
banner_removal =
instance_list(:banner_removal)
|> MRF.subdomains_regex()
if MRF.subdomain_match?(banner_removal, actor_host) do
- {:ok, Map.delete(object, "image")}
+ {:ok, Map.delete(activity, "image")}
else
- {:ok, object}
+ {:ok, activity}
end
end
- defp check_banner_removal(_actor_info, object), do: {:ok, object}
+ defp check_banner_removal(_actor_info, activity), do: {:ok, activity}
defp check_object(%{"object" => object} = activity) do
with {:ok, _object} <- filter(object) do
@@ -184,7 +184,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicy do
end
end
- defp check_object(object), do: {:ok, object}
+ defp check_object(activity), do: {:ok, activity}
defp instance_list(config_key) do
Config.get([:mrf_simple, config_key])
@@ -192,7 +192,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicy do
end
@impl true
- def filter(%{"type" => "Delete", "actor" => actor} = object) do
+ def filter(%{"type" => "Delete", "actor" => actor} = activity) do
%{host: actor_host} = URI.parse(actor)
reject_deletes =
@@ -202,54 +202,54 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicy do
if MRF.subdomain_match?(reject_deletes, actor_host) do
{:reject, "[SimplePolicy] host in reject_deletes list"}
else
- {:ok, object}
+ {:ok, activity}
end
end
@impl true
- def filter(%{"actor" => actor} = object) do
+ def filter(%{"actor" => actor} = activity) do
actor_info = URI.parse(actor)
- with {:ok, object} <- check_accept(actor_info, object),
- {:ok, object} <- check_reject(actor_info, object),
- {:ok, object} <- check_media_removal(actor_info, object),
- {:ok, object} <- check_media_nsfw(actor_info, object),
- {:ok, object} <- check_ftl_removal(actor_info, object),
- {:ok, object} <- check_followers_only(actor_info, object),
- {:ok, object} <- check_report_removal(actor_info, object),
- {:ok, object} <- check_object(object) do
- {:ok, object}
+ with {:ok, activity} <- check_accept(actor_info, activity),
+ {:ok, activity} <- check_reject(actor_info, activity),
+ {:ok, activity} <- check_media_removal(actor_info, activity),
+ {:ok, activity} <- check_media_nsfw(actor_info, activity),
+ {:ok, activity} <- check_ftl_removal(actor_info, activity),
+ {:ok, activity} <- check_followers_only(actor_info, activity),
+ {:ok, activity} <- check_report_removal(actor_info, activity),
+ {:ok, activity} <- check_object(activity) do
+ {:ok, activity}
else
{:reject, _} = e -> e
end
end
- def filter(%{"id" => actor, "type" => obj_type} = object)
- when obj_type in ["Application", "Group", "Organization", "Person", "Service"] do
+ def filter(%{"id" => actor, "type" => actor_type} = activity)
+ when actor_type in ["Application", "Group", "Organization", "Person", "Service"] do
actor_info = URI.parse(actor)
- with {:ok, object} <- check_accept(actor_info, object),
- {:ok, object} <- check_reject(actor_info, object),
- {:ok, object} <- check_avatar_removal(actor_info, object),
- {:ok, object} <- check_banner_removal(actor_info, object) do
- {:ok, object}
+ with {:ok, activity} <- check_accept(actor_info, activity),
+ {:ok, activity} <- check_reject(actor_info, activity),
+ {:ok, activity} <- check_avatar_removal(actor_info, activity),
+ {:ok, activity} <- check_banner_removal(actor_info, activity) do
+ {:ok, activity}
else
{:reject, _} = e -> e
end
end
- def filter(object) when is_binary(object) do
- uri = URI.parse(object)
+ def filter(activity) when is_binary(activity) do
+ uri = URI.parse(activity)
- with {:ok, object} <- check_accept(uri, object),
- {:ok, object} <- check_reject(uri, object) do
- {:ok, object}
+ with {:ok, activity} <- check_accept(uri, activity),
+ {:ok, activity} <- check_reject(uri, activity) do
+ {:ok, activity}
else
{:reject, _} = e -> e
end
end
- def filter(object), do: {:ok, object}
+ def filter(activity), do: {:ok, activity}
@impl true
def describe do
diff --git a/lib/pleroma/web/activity_pub/mrf/steal_emoji_policy.ex b/lib/pleroma/web/activity_pub/mrf/steal_emoji_policy.ex
index fa6b595ea..6edfb124e 100644
--- a/lib/pleroma/web/activity_pub/mrf/steal_emoji_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/steal_emoji_policy.ex
@@ -62,7 +62,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.StealEmojiPolicy do
end
@impl true
- def filter(%{"object" => %{"emoji" => foreign_emojis, "actor" => actor}} = message) do
+ def filter(%{"object" => %{"emoji" => foreign_emojis, "actor" => actor}} = activity) do
host = URI.parse(actor).host
if host != Pleroma.Web.Endpoint.host() and accept_host?(host) do
@@ -97,10 +97,10 @@ defmodule Pleroma.Web.ActivityPub.MRF.StealEmojiPolicy do
end
end
- {:ok, message}
+ {:ok, activity}
end
- def filter(message), do: {:ok, message}
+ def filter(activity), do: {:ok, activity}
@impl true
@spec config_description :: %{
diff --git a/lib/pleroma/web/activity_pub/mrf/subchain_policy.ex b/lib/pleroma/web/activity_pub/mrf/subchain_policy.ex
index fdb9e5176..97acca7e8 100644
--- a/lib/pleroma/web/activity_pub/mrf/subchain_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/subchain_policy.ex
@@ -20,20 +20,20 @@ defmodule Pleroma.Web.ActivityPub.MRF.SubchainPolicy do
end
@impl true
- def filter(%{"actor" => actor} = message) do
+ def filter(%{"actor" => actor} = activity) do
with {:ok, match, subchain} <- lookup_subchain(actor) do
Logger.debug(
"[SubchainPolicy] Matched #{actor} against #{inspect(match)} with subchain #{inspect(subchain)}"
)
- MRF.filter(subchain, message)
+ MRF.filter(subchain, activity)
else
- _e -> {:ok, message}
+ _e -> {:ok, activity}
end
end
@impl true
- def filter(message), do: {:ok, message}
+ def filter(activity), do: {:ok, activity}
@impl true
def describe, do: {:ok, %{}}
@@ -45,7 +45,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SubchainPolicy do
related_policy: "Pleroma.Web.ActivityPub.MRF.SubchainPolicy",
label: "MRF Subchain",
description:
- "This policy processes messages through an alternate pipeline when a given message matches certain criteria." <>
+ "This policy processes activities through an alternate pipeline when a given activity matches certain criteria." <>
" All criteria are configured as a map of regular expressions to lists of policy modules.",
children: [
%{
diff --git a/lib/pleroma/web/activity_pub/mrf/tag_policy.ex b/lib/pleroma/web/activity_pub/mrf/tag_policy.ex
index 73760ca8f..c236a5a99 100644
--- a/lib/pleroma/web/activity_pub/mrf/tag_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/tag_policy.ex
@@ -28,25 +28,25 @@ defmodule Pleroma.Web.ActivityPub.MRF.TagPolicy do
"mrf_tag:media-force-nsfw",
%{
"type" => type,
- "object" => %{"attachment" => child_attachment}
- } = message
+ "object" => %{"attachment" => object_attachment}
+ } = activity
)
- when length(child_attachment) > 0 and type in ["Create", "Update"] do
- {:ok, Kernel.put_in(message, ["object", "sensitive"], true)}
+ when length(object_attachment) > 0 and type in ["Create", "Update"] do
+ {:ok, Kernel.put_in(activity, ["object", "sensitive"], true)}
end
defp process_tag(
"mrf_tag:media-strip",
%{
"type" => type,
- "object" => %{"attachment" => child_attachment} = object
- } = message
+ "object" => %{"attachment" => object_attachment} = object
+ } = activity
)
- when length(child_attachment) > 0 and type in ["Create", "Update"] do
+ when length(object_attachment) > 0 and type in ["Create", "Update"] do
object = Map.delete(object, "attachment")
- message = Map.put(message, "object", object)
+ activity = Map.put(activity, "object", object)
- {:ok, message}
+ {:ok, activity}
end
defp process_tag(
@@ -57,7 +57,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.TagPolicy do
"cc" => cc,
"actor" => actor,
"object" => object
- } = message
+ } = activity
) do
user = User.get_cached_by_ap_id(actor)
@@ -70,15 +70,15 @@ defmodule Pleroma.Web.ActivityPub.MRF.TagPolicy do
|> Map.put("to", to)
|> Map.put("cc", cc)
- message =
- message
+ activity =
+ activity
|> Map.put("to", to)
|> Map.put("cc", cc)
|> Map.put("object", object)
- {:ok, message}
+ {:ok, activity}
else
- {:ok, message}
+ {:ok, activity}
end
end
@@ -90,7 +90,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.TagPolicy do
"cc" => cc,
"actor" => actor,
"object" => object
- } = message
+ } = activity
) do
user = User.get_cached_by_ap_id(actor)
@@ -104,26 +104,26 @@ defmodule Pleroma.Web.ActivityPub.MRF.TagPolicy do
|> Map.put("to", to)
|> Map.put("cc", cc)
- message =
- message
+ activity =
+ activity
|> Map.put("to", to)
|> Map.put("cc", cc)
|> Map.put("object", object)
- {:ok, message}
+ {:ok, activity}
else
- {:ok, message}
+ {:ok, activity}
end
end
defp process_tag(
"mrf_tag:disable-remote-subscription",
- %{"type" => "Follow", "actor" => actor} = message
+ %{"type" => "Follow", "actor" => actor} = activity
) do
user = User.get_cached_by_ap_id(actor)
if user.local == true do
- {:ok, message}
+ {:ok, activity}
else
{:reject,
"[TagPolicy] Follow from #{actor} tagged with mrf_tag:disable-remote-subscription"}
@@ -133,14 +133,14 @@ defmodule Pleroma.Web.ActivityPub.MRF.TagPolicy do
defp process_tag("mrf_tag:disable-any-subscription", %{"type" => "Follow", "actor" => actor}),
do: {:reject, "[TagPolicy] Follow from #{actor} tagged with mrf_tag:disable-any-subscription"}
- defp process_tag(_, message), do: {:ok, message}
+ defp process_tag(_, activity), do: {:ok, activity}
- def filter_message(actor, message) do
+ def filter_activity(actor, activity) do
User.get_cached_by_ap_id(actor)
|> get_tags()
- |> Enum.reduce({:ok, message}, fn
- tag, {:ok, message} ->
- process_tag(tag, message)
+ |> Enum.reduce({:ok, activity}, fn
+ tag, {:ok, activity} ->
+ process_tag(tag, activity)
_, error ->
error
@@ -148,15 +148,15 @@ defmodule Pleroma.Web.ActivityPub.MRF.TagPolicy do
end
@impl true
- def filter(%{"object" => target_actor, "type" => "Follow"} = message),
- do: filter_message(target_actor, message)
+ def filter(%{"object" => target_actor, "type" => "Follow"} = activity),
+ do: filter_activity(target_actor, activity)
@impl true
- def filter(%{"actor" => actor, "type" => type} = message) when type in ["Create", "Update"],
- do: filter_message(actor, message)
+ def filter(%{"actor" => actor, "type" => type} = activity) when type in ["Create", "Update"],
+ do: filter_activity(actor, activity)
@impl true
- def filter(message), do: {:ok, message}
+ def filter(activity), do: {:ok, activity}
@impl true
def describe, do: {:ok, %{}}
diff --git a/lib/pleroma/web/activity_pub/mrf/user_allow_list_policy.ex b/lib/pleroma/web/activity_pub/mrf/user_allow_list_policy.ex
index e14047d4e..10cc0e09d 100644
--- a/lib/pleroma/web/activity_pub/mrf/user_allow_list_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/user_allow_list_policy.ex
@@ -8,18 +8,18 @@ defmodule Pleroma.Web.ActivityPub.MRF.UserAllowListPolicy do
@moduledoc "Accept-list of users from specified instances"
@behaviour Pleroma.Web.ActivityPub.MRF.Policy
- defp filter_by_list(object, []), do: {:ok, object}
+ defp filter_by_list(activity, []), do: {:ok, activity}
- defp filter_by_list(%{"actor" => actor} = object, allow_list) do
+ defp filter_by_list(%{"actor" => actor} = activity, allow_list) do
if actor in allow_list do
- {:ok, object}
+ {:ok, activity}
else
{:reject, "[UserAllowListPolicy] #{actor} not in the list"}
end
end
@impl true
- def filter(%{"actor" => actor} = object) do
+ def filter(%{"actor" => actor} = activity) do
actor_info = URI.parse(actor)
allow_list =
@@ -28,10 +28,10 @@ defmodule Pleroma.Web.ActivityPub.MRF.UserAllowListPolicy do
[]
)
- filter_by_list(object, allow_list)
+ filter_by_list(activity, allow_list)
end
- def filter(object), do: {:ok, object}
+ def filter(activity), do: {:ok, activity}
@impl true
def describe do
diff --git a/lib/pleroma/web/activity_pub/mrf/vocabulary_policy.ex b/lib/pleroma/web/activity_pub/mrf/vocabulary_policy.ex
index 1c114558e..5671e4cf3 100644
--- a/lib/pleroma/web/activity_pub/mrf/vocabulary_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/vocabulary_policy.ex
@@ -3,38 +3,38 @@
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.MRF.VocabularyPolicy do
- @moduledoc "Filter messages which belong to certain activity vocabularies"
+ @moduledoc "Filter activities which belong to certain activity vocabularies"
@behaviour Pleroma.Web.ActivityPub.MRF.Policy
@impl true
- def filter(%{"type" => "Undo", "object" => child_message} = message) do
- with {:ok, _} <- filter(child_message) do
- {:ok, message}
+ def filter(%{"type" => "Undo", "object" => object} = activity) do
+ with {:ok, _} <- filter(object) do
+ {:ok, activity}
else
{:reject, _} = e -> e
end
end
- def filter(%{"type" => message_type} = message) do
+ def filter(%{"type" => activity_type} = activity) do
with accepted_vocabulary <- Pleroma.Config.get([:mrf_vocabulary, :accept]),
rejected_vocabulary <- Pleroma.Config.get([:mrf_vocabulary, :reject]),
{_, true} <-
{:accepted,
- Enum.empty?(accepted_vocabulary) || Enum.member?(accepted_vocabulary, message_type)},
+ Enum.empty?(accepted_vocabulary) || Enum.member?(accepted_vocabulary, activity_type)},
{_, false} <-
{:rejected,
- length(rejected_vocabulary) > 0 && Enum.member?(rejected_vocabulary, message_type)},
- {:ok, _} <- filter(message["object"]) do
- {:ok, message}
+ length(rejected_vocabulary) > 0 && Enum.member?(rejected_vocabulary, activity_type)},
+ {:ok, _} <- filter(activity["object"]) do
+ {:ok, activity}
else
{:reject, _} = e -> e
- {:accepted, _} -> {:reject, "[VocabularyPolicy] #{message_type} not in accept list"}
- {:rejected, _} -> {:reject, "[VocabularyPolicy] #{message_type} in reject list"}
+ {:accepted, _} -> {:reject, "[VocabularyPolicy] #{activity_type} not in accept list"}
+ {:rejected, _} -> {:reject, "[VocabularyPolicy] #{activity_type} in reject list"}
end
end
- def filter(message), do: {:ok, message}
+ def filter(activity), do: {:ok, activity}
@impl true
def describe,
@@ -46,20 +46,20 @@ defmodule Pleroma.Web.ActivityPub.MRF.VocabularyPolicy do
key: :mrf_vocabulary,
related_policy: "Pleroma.Web.ActivityPub.MRF.VocabularyPolicy",
label: "MRF Vocabulary",
- description: "Filter messages which belong to certain activity vocabularies",
+ description: "Filter activities which belong to certain activity vocabularies",
children: [
%{
key: :accept,
type: {:list, :string},
description:
- "A list of ActivityStreams terms to accept. If empty, all supported messages are accepted.",
+ "A list of ActivityStreams terms to accept. If empty, all supported activities are accepted.",
suggestions: ["Create", "Follow", "Mention", "Announce", "Like"]
},
%{
key: :reject,
type: {:list, :string},
description:
- "A list of ActivityStreams terms to reject. If empty, no messages are rejected.",
+ "A list of ActivityStreams terms to reject. If empty, no activities are rejected.",
suggestions: ["Create", "Follow", "Mention", "Announce", "Like"]
}
]
diff --git a/lib/pleroma/web/activity_pub/object_validators/accept_reject_validator.ex b/lib/pleroma/web/activity_pub/object_validators/accept_reject_validator.ex
index d611da051..03ab83347 100644
--- a/lib/pleroma/web/activity_pub/object_validators/accept_reject_validator.ex
+++ b/lib/pleroma/web/activity_pub/object_validators/accept_reject_validator.ex
@@ -29,7 +29,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AcceptRejectValidator do
defp validate_data(cng) do
cng
- |> validate_required([:id, :type, :actor, :to, :cc, :object])
+ |> validate_required([:id, :type, :actor, :to, :object])
|> validate_inclusion(:type, ["Accept", "Reject"])
|> validate_actor_presence()
|> validate_object_presence(allowed_types: ["Follow"])
diff --git a/lib/pleroma/web/activity_pub/object_validators/block_validator.ex b/lib/pleroma/web/activity_pub/object_validators/block_validator.ex
index 0de87a27e..98340545c 100644
--- a/lib/pleroma/web/activity_pub/object_validators/block_validator.ex
+++ b/lib/pleroma/web/activity_pub/object_validators/block_validator.ex
@@ -29,7 +29,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.BlockValidator do
defp validate_data(cng) do
cng
- |> validate_required([:id, :type, :actor, :to, :cc, :object])
+ |> validate_required([:id, :type, :actor, :to, :object])
|> validate_inclusion(:type, ["Block"])
|> CommonValidations.validate_actor_presence()
|> CommonValidations.validate_actor_presence(field_name: :object)
diff --git a/lib/pleroma/web/activity_pub/object_validators/follow_validator.ex b/lib/pleroma/web/activity_pub/object_validators/follow_validator.ex
index b3ca5b691..e4e97bf72 100644
--- a/lib/pleroma/web/activity_pub/object_validators/follow_validator.ex
+++ b/lib/pleroma/web/activity_pub/object_validators/follow_validator.ex
@@ -29,7 +29,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.FollowValidator do
defp validate_data(cng) do
cng
- |> validate_required([:id, :type, :actor, :to, :cc, :object])
+ |> validate_required([:id, :type, :actor, :to, :object])
|> validate_inclusion(:type, ["Follow"])
|> validate_inclusion(:state, ~w{pending reject accept})
|> validate_actor_presence()
diff --git a/lib/pleroma/web/activity_pub/publisher.ex b/lib/pleroma/web/activity_pub/publisher.ex
index c8bdf2250..0de3a0d43 100644
--- a/lib/pleroma/web/activity_pub/publisher.ex
+++ b/lib/pleroma/web/activity_pub/publisher.ex
@@ -11,6 +11,7 @@ defmodule Pleroma.Web.ActivityPub.Publisher do
alias Pleroma.Object
alias Pleroma.Repo
alias Pleroma.User
+ alias Pleroma.Web.ActivityPub.Publisher.Prepared
alias Pleroma.Web.ActivityPub.Relay
alias Pleroma.Web.ActivityPub.Transmogrifier
alias Pleroma.Workers.PublisherWorker
@@ -30,11 +31,11 @@ defmodule Pleroma.Web.ActivityPub.Publisher do
"""
@spec enqueue_one(map(), Keyword.t()) :: {:ok, %Oban.Job{}}
def enqueue_one(%{} = params, worker_args \\ []) do
- PublisherWorker.enqueue(
- "publish_one",
- %{"params" => params},
+ PublisherWorker.new(
+ %{"op" => "publish_one", "params" => params},
worker_args
)
+ |> Oban.insert()
end
@doc """
@@ -76,17 +77,29 @@ defmodule Pleroma.Web.ActivityPub.Publisher do
end
@doc """
- Publish a single message to a peer. Takes a struct with the following
- parameters set:
-
+ Prepare an activity for publishing from an Oban job
* `inbox`: the inbox to publish to
- * `json`: the JSON message body representing the ActivityPub message
- * `actor`: the actor which is signing the message
- * `id`: the ActivityStreams URI of the message
+ * `activity_id`: the internal activity id
+ * `cc`: the cc recipients relevant to this inbox (optional)
"""
- def publish_one(%{inbox: inbox, json: json, actor: %User{} = actor, id: id} = params) do
- Logger.debug("Federating #{id} to #{inbox}")
+ @spec prepare_one(map()) :: Prepared.t()
+ def prepare_one(%{inbox: inbox, activity_id: activity_id} = params) do
+ activity = Activity.get_by_id_with_user_actor(activity_id)
+ actor = activity.user_actor
+
+ ap_id = activity.data["id"]
+ Logger.debug("Federating #{ap_id} to #{inbox}")
uri = %{path: path} = URI.parse(inbox)
+
+ {:ok, data} = Transmogrifier.prepare_outgoing(activity.data)
+
+ cc = Map.get(params, :cc, [])
+
+ json =
+ data
+ |> Map.put("cc", cc)
+ |> Jason.encode!()
+
digest = "SHA-256=" <> (:crypto.hash(:sha256, json) |> Base.encode64())
date = Pleroma.Signature.signed_date()
@@ -100,27 +113,54 @@ defmodule Pleroma.Web.ActivityPub.Publisher do
date: date
})
+ %Prepared{
+ activity_id: activity_id,
+ json: json,
+ date: date,
+ signature: signature,
+ digest: digest,
+ inbox: inbox,
+ unreachable_since: params[:unreachable_since]
+ }
+ end
+
+ @doc """
+ Publish a single message to a peer. Takes a struct with the following
+ parameters set:
+ * `activity_id`: the activity id
+ * `json`: the json payload
+ * `date`: the signed date from Pleroma.Signature.signed_date()
+ * `signature`: the signature from Pleroma.Signature.sign/2
+ * `digest`: base64 encoded the hash of the json payload prefixed with "SHA-256="
+ * `inbox`: the inbox URI of this delivery
+ * `unreachable_since`: timestamp the instance was marked unreachable
+
+ """
+ def publish_one(%Prepared{} = p) do
with {:ok, %{status: code}} = result when code in 200..299 <-
HTTP.post(
- inbox,
- json,
+ p.inbox,
+ p.json,
[
{"Content-Type", "application/activity+json"},
- {"Date", date},
- {"signature", signature},
- {"digest", digest}
+ {"Date", p.date},
+ {"signature", p.signature},
+ {"digest", p.digest}
]
) do
- if not Map.has_key?(params, :unreachable_since) || params[:unreachable_since] do
- Instances.set_reachable(inbox)
+ if not is_nil(p.unreachable_since) do
+ Instances.set_reachable(p.inbox)
end
result
else
{_post_result, %{status: code} = response} = e ->
- unless params[:unreachable_since], do: Instances.set_unreachable(inbox)
- Logger.metadata(activity: id, inbox: inbox, status: code)
- Logger.error("Publisher failed to inbox #{inbox} with status #{code}")
+ if is_nil(p.unreachable_since) do
+ Instances.set_unreachable(p.inbox)
+ end
+
+ Logger.metadata(activity: p.activity_id, inbox: p.inbox, status: code)
+ Logger.error("Publisher failed to inbox #{p.inbox} with status #{code}")
case response do
%{status: 400} -> {:cancel, :bad_request}
@@ -130,26 +170,26 @@ defmodule Pleroma.Web.ActivityPub.Publisher do
_ -> {:error, e}
end
+ {:error, {:already_started, _}} ->
+ Logger.debug("Publisher snoozing worker job due worker :already_started race condition")
+ connection_pool_snooze()
+
{:error, :pool_full} ->
Logger.debug("Publisher snoozing worker job due to full connection pool")
- {:snooze, 30}
+ connection_pool_snooze()
e ->
- unless params[:unreachable_since], do: Instances.set_unreachable(inbox)
- Logger.metadata(activity: id, inbox: inbox)
- Logger.error("Publisher failed to inbox #{inbox} #{inspect(e)}")
+ if is_nil(p.unreachable_since) do
+ Instances.set_unreachable(p.inbox)
+ end
+
+ Logger.metadata(activity: p.activity_id, inbox: p.inbox)
+ Logger.error("Publisher failed to inbox #{p.inbox} #{inspect(e)}")
{:error, e}
end
end
- def publish_one(%{actor_id: actor_id} = params) do
- actor = User.get_cached_by_id(actor_id)
-
- params
- |> Map.delete(:actor_id)
- |> Map.put(:actor, actor)
- |> publish_one()
- end
+ defp connection_pool_snooze, do: {:snooze, 3}
defp signature_host(%URI{port: port, scheme: scheme, host: host}) do
if port == URI.default_port(scheme) do
@@ -251,7 +291,6 @@ defmodule Pleroma.Web.ActivityPub.Publisher do
def publish(%User{} = actor, %{data: %{"bcc" => bcc}} = activity)
when is_list(bcc) and bcc != [] do
public = public?(activity)
- {:ok, data} = Transmogrifier.prepare_outgoing(activity.data)
[priority_recipients, recipients] = recipients(actor, activity)
@@ -276,16 +315,10 @@ defmodule Pleroma.Web.ActivityPub.Publisher do
# instance would only accept a first message for the first recipient and ignore the rest.
cc = get_cc_ap_ids(ap_id, recipients)
- json =
- data
- |> Map.put("cc", cc)
- |> Jason.encode!()
-
__MODULE__.enqueue_one(%{
inbox: inbox,
- json: json,
- actor_id: actor.id,
- id: activity.data["id"],
+ cc: cc,
+ activity_id: activity.id,
unreachable_since: unreachable_since
})
end)
@@ -302,9 +335,6 @@ defmodule Pleroma.Web.ActivityPub.Publisher do
Relay.publish(activity)
end
- {:ok, data} = Transmogrifier.prepare_outgoing(activity.data)
- json = Jason.encode!(data)
-
[priority_inboxes, inboxes] =
recipients(actor, activity)
|> Enum.map(fn recipients ->
@@ -326,9 +356,7 @@ defmodule Pleroma.Web.ActivityPub.Publisher do
__MODULE__.enqueue_one(
%{
inbox: inbox,
- json: json,
- actor_id: actor.id,
- id: activity.data["id"],
+ activity_id: activity.id,
unreachable_since: unreachable_since
},
priority: priority
diff --git a/lib/pleroma/web/activity_pub/publisher/prepared.ex b/lib/pleroma/web/activity_pub/publisher/prepared.ex
new file mode 100644
index 000000000..ddd8167e1
--- /dev/null
+++ b/lib/pleroma/web/activity_pub/publisher/prepared.ex
@@ -0,0 +1,8 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.ActivityPub.Publisher.Prepared do
+ @type t :: %__MODULE__{}
+ defstruct [:activity_id, :json, :date, :signature, :digest, :inbox, :unreachable_since]
+end
diff --git a/lib/pleroma/web/activity_pub/side_effects.ex b/lib/pleroma/web/activity_pub/side_effects.ex
index cc1c7a0af..d6d403671 100644
--- a/lib/pleroma/web/activity_pub/side_effects.ex
+++ b/lib/pleroma/web/activity_pub/side_effects.ex
@@ -223,10 +223,12 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do
if Pleroma.Web.Federator.allowed_thread_distance?(reply_depth) and
object.data["replies"] != nil do
for reply_id <- object.data["replies"] do
- Pleroma.Workers.RemoteFetcherWorker.enqueue("fetch_remote", %{
+ Pleroma.Workers.RemoteFetcherWorker.new(%{
+ "op" => "fetch_remote",
"id" => reply_id,
"depth" => reply_depth
})
+ |> Oban.insert()
end
end
@@ -410,10 +412,12 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do
{:ok, expires_at} =
Pleroma.EctoType.ActivityPub.ObjectValidators.DateTime.cast(meta[:expires_at])
- Pleroma.Workers.PurgeExpiredActivity.enqueue(%{
- activity_id: meta[:activity_id],
- expires_at: expires_at
- })
+ Pleroma.Workers.PurgeExpiredActivity.enqueue(
+ %{
+ activity_id: meta[:activity_id]
+ },
+ scheduled_at: expires_at
+ )
end
{:ok, object, meta}
diff --git a/lib/pleroma/web/admin_api/controllers/admin_api_controller.ex b/lib/pleroma/web/admin_api/controllers/admin_api_controller.ex
index 1894000ff..0f22dd538 100644
--- a/lib/pleroma/web/admin_api/controllers/admin_api_controller.ex
+++ b/lib/pleroma/web/admin_api/controllers/admin_api_controller.ex
@@ -13,6 +13,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
alias Pleroma.ModerationLog
alias Pleroma.Stats
alias Pleroma.User
+ alias Pleroma.User.Backup
alias Pleroma.Web.ActivityPub.ActivityPub
alias Pleroma.Web.AdminAPI
alias Pleroma.Web.AdminAPI.AccountView
@@ -429,7 +430,9 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
def create_backup(%{assigns: %{user: admin}} = conn, %{"nickname" => nickname}) do
with %User{} = user <- User.get_by_nickname(nickname),
- {:ok, _} <- Pleroma.User.Backup.create(user, admin.id) do
+ %Backup{} = backup <- Backup.new(user),
+ {:ok, inserted_backup} <- Pleroma.Repo.insert(backup),
+ {:ok, %Oban.Job{}} <- Backup.schedule_backup(inserted_backup) do
ModerationLog.insert_log(%{actor: admin, subject: user, action: "create_backup"})
json(conn, "")
diff --git a/lib/pleroma/web/api_spec/operations/account_operation.ex b/lib/pleroma/web/api_spec/operations/account_operation.ex
index 85f02166f..d9614bc48 100644
--- a/lib/pleroma/web/api_spec/operations/account_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/account_operation.ex
@@ -498,22 +498,6 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do
}
end
- def identity_proofs_operation do
- %Operation{
- tags: ["Retrieve account information"],
- summary: "Identity proofs",
- operationId: "AccountController.identity_proofs",
- # Validators complains about unused path params otherwise
- parameters: [
- %Reference{"$ref": "#/components/parameters/accountIdOrNickname"}
- ],
- description: "Not implemented",
- responses: %{
- 200 => empty_array_response()
- }
- }
- end
-
def familiar_followers_operation do
%Operation{
tags: ["Retrieve account information"],
diff --git a/lib/pleroma/web/api_spec/operations/pleroma_account_operation.ex b/lib/pleroma/web/api_spec/operations/pleroma_account_operation.ex
index 7340653fb..b8b37d7cf 100644
--- a/lib/pleroma/web/api_spec/operations/pleroma_account_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/pleroma_account_operation.ex
@@ -85,9 +85,11 @@ defmodule Pleroma.Web.ApiSpec.PleromaAccountOperation do
def subscribe_operation do
%Operation{
+ deprecated: true,
tags: ["Account actions"],
summary: "Subscribe",
- description: "Receive notifications for all statuses posted by the account.",
+ description:
+ "Receive notifications for all statuses posted by the account. Deprecated, use `notify: true` in follow operation instead.",
operationId: "PleromaAPI.AccountController.subscribe",
parameters: [id_param()],
security: [%{"oAuth" => ["follow", "write:follows"]}],
@@ -100,9 +102,11 @@ defmodule Pleroma.Web.ApiSpec.PleromaAccountOperation do
def unsubscribe_operation do
%Operation{
+ deprecated: true,
tags: ["Account actions"],
summary: "Unsubscribe",
- description: "Stop receiving notifications for all statuses posted by the account.",
+ description:
+ "Stop receiving notifications for all statuses posted by the account. Deprecated, use `notify: false` in follow operation instead.",
operationId: "PleromaAPI.AccountController.unsubscribe",
parameters: [id_param()],
security: [%{"oAuth" => ["follow", "write:follows"]}],
diff --git a/lib/pleroma/web/api_spec/operations/pleroma_backup_operation.ex b/lib/pleroma/web/api_spec/operations/pleroma_backup_operation.ex
index 400f3825d..86f709515 100644
--- a/lib/pleroma/web/api_spec/operations/pleroma_backup_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/pleroma_backup_operation.ex
@@ -65,12 +65,7 @@ defmodule Pleroma.Web.ApiSpec.PleromaBackupOperation do
file_name: %Schema{type: :string},
file_size: %Schema{type: :integer},
processed: %Schema{type: :boolean, description: "whether this backup has succeeded"},
- state: %Schema{
- type: :string,
- description: "the state of the backup",
- enum: ["pending", "running", "complete", "failed"]
- },
- processed_number: %Schema{type: :integer, description: "the number of records processed"}
+ tempdir: %Schema{type: :string}
},
example: %{
"content_type" => "application/zip",
@@ -79,8 +74,7 @@ defmodule Pleroma.Web.ApiSpec.PleromaBackupOperation do
"file_size" => 4105,
"inserted_at" => "2020-09-08T16:42:07.000Z",
"processed" => true,
- "state" => "complete",
- "processed_number" => 20
+ "tempdir" => "/tmp/PZIMw40vmpM"
}
}
end
diff --git a/lib/pleroma/web/api_spec/operations/status_operation.ex b/lib/pleroma/web/api_spec/operations/status_operation.ex
index 1717c68c8..ef828feee 100644
--- a/lib/pleroma/web/api_spec/operations/status_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/status_operation.ex
@@ -31,12 +31,18 @@ defmodule Pleroma.Web.ApiSpec.StatusOperation do
security: [%{"oAuth" => ["read:statuses"]}],
parameters: [
Operation.parameter(
- :ids,
+ :id,
:query,
%Schema{type: :array, items: FlakeID},
"Array of status IDs"
),
Operation.parameter(
+ :ids,
+ :query,
+ %Schema{type: :array, items: FlakeID},
+ "Deprecated, use `id` instead"
+ ),
+ Operation.parameter(
:with_muted,
:query,
BooleanLike.schema(),
diff --git a/lib/pleroma/web/common_api.ex b/lib/pleroma/web/common_api.ex
index 06faf845e..921e414c3 100644
--- a/lib/pleroma/web/common_api.ex
+++ b/lib/pleroma/web/common_api.ex
@@ -130,7 +130,7 @@ defmodule Pleroma.Web.CommonAPI do
if activity.data["state"] == "reject" do
{:error, :rejected}
else
- {:ok, follower, followed, activity}
+ {:ok, followed, follower, activity}
end
end
end
@@ -559,11 +559,11 @@ defmodule Pleroma.Web.CommonAPI do
with {:ok, _} <- ThreadMute.add_mute(user.id, activity.data["context"]),
_ <- Pleroma.Notification.mark_context_as_read(user, activity.data["context"]) do
if expires_in > 0 do
- Pleroma.Workers.MuteExpireWorker.enqueue(
- "unmute_conversation",
- %{"user_id" => user.id, "activity_id" => activity.id},
+ Pleroma.Workers.MuteExpireWorker.new(
+ %{"op" => "unmute_conversation", "user_id" => user.id, "activity_id" => activity.id},
schedule_in: expires_in
)
+ |> Oban.insert()
end
{:ok, activity}
@@ -714,11 +714,11 @@ defmodule Pleroma.Web.CommonAPI do
end
end
- defp maybe_cancel_jobs(%Activity{data: %{"id" => ap_id}}) do
+ defp maybe_cancel_jobs(%Activity{id: activity_id}) do
Oban.Job
|> where([j], j.worker == "Pleroma.Workers.PublisherWorker")
|> where([j], j.args["op"] == "publish_one")
- |> where([j], j.args["params"]["id"] == ^ap_id)
+ |> where([j], j.args["params"]["activity_id"] == ^activity_id)
|> Oban.cancel_all_jobs()
end
diff --git a/lib/pleroma/web/federator.ex b/lib/pleroma/web/federator.ex
index 3d3101d61..2df716556 100644
--- a/lib/pleroma/web/federator.ex
+++ b/lib/pleroma/web/federator.ex
@@ -35,22 +35,30 @@ defmodule Pleroma.Web.Federator do
end
# Client API
- def incoming_ap_doc(%{params: _params, req_headers: _req_headers} = args) do
- job_args = Enum.into(args, %{}, fn {k, v} -> {Atom.to_string(k), v} end)
-
- ReceiverWorker.enqueue(
- "incoming_ap_doc",
- Map.put(job_args, "timeout", :timer.seconds(20)),
+ def incoming_ap_doc(%{params: params, req_headers: req_headers}) do
+ ReceiverWorker.new(
+ %{
+ "op" => "incoming_ap_doc",
+ "req_headers" => req_headers,
+ "params" => params,
+ "timeout" => :timer.seconds(20)
+ },
priority: 2
)
+ |> Oban.insert()
end
def incoming_ap_doc(%{"type" => "Delete"} = params) do
- ReceiverWorker.enqueue("incoming_ap_doc", %{"params" => params}, priority: 3, queue: :slow)
+ ReceiverWorker.new(%{"op" => "incoming_ap_doc", "params" => params},
+ priority: 3,
+ queue: :slow
+ )
+ |> Oban.insert()
end
def incoming_ap_doc(params) do
- ReceiverWorker.enqueue("incoming_ap_doc", %{"params" => params})
+ ReceiverWorker.new(%{"op" => "incoming_ap_doc", "params" => params})
+ |> Oban.insert()
end
@impl true
@@ -60,9 +68,10 @@ defmodule Pleroma.Web.Federator do
@impl true
def publish(%Pleroma.Activity{data: %{"type" => type}} = activity) do
- PublisherWorker.enqueue("publish", %{"activity_id" => activity.id},
+ PublisherWorker.new(%{"op" => "publish", "activity_id" => activity.id},
priority: publish_priority(type)
)
+ |> Oban.insert()
end
defp publish_priority("Delete"), do: 3
@@ -71,7 +80,10 @@ defmodule Pleroma.Web.Federator do
# Job Worker Callbacks
@spec perform(atom(), any()) :: {:ok, any()} | {:error, any()}
- def perform(:publish_one, params), do: Publisher.publish_one(params)
+ def perform(:publish_one, params) do
+ Publisher.prepare_one(params)
+ |> Publisher.publish_one()
+ end
def perform(:publish, activity) do
Logger.debug(fn -> "Running publish for #{activity.data["id"]}" end)
diff --git a/lib/pleroma/web/mastodon_api/controllers/account_controller.ex b/lib/pleroma/web/mastodon_api/controllers/account_controller.ex
index 80ab95a57..54d46c86b 100644
--- a/lib/pleroma/web/mastodon_api/controllers/account_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/account_controller.ex
@@ -22,7 +22,6 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
alias Pleroma.Web.CommonAPI
alias Pleroma.Web.MastodonAPI.ListView
alias Pleroma.Web.MastodonAPI.MastodonAPI
- alias Pleroma.Web.MastodonAPI.MastodonAPIController
alias Pleroma.Web.MastodonAPI.StatusView
alias Pleroma.Web.OAuth.OAuthController
alias Pleroma.Web.Plugs.OAuthScopesPlug
@@ -51,7 +50,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
plug(
OAuthScopesPlug,
%{scopes: ["read:accounts"]}
- when action in [:verify_credentials, :endorsements, :identity_proofs]
+ when action in [:verify_credentials, :endorsements]
)
plug(
@@ -660,7 +659,4 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
defp get_familiar_followers(user, current_user) do
User.get_familiar_followers(user, current_user)
end
-
- @doc "GET /api/v1/identity_proofs"
- def identity_proofs(conn, params), do: MastodonAPIController.empty_array(conn, params)
end
diff --git a/lib/pleroma/web/mastodon_api/controllers/marker_controller.ex b/lib/pleroma/web/mastodon_api/controllers/marker_controller.ex
index 4ad30f330..42b2a201d 100644
--- a/lib/pleroma/web/mastodon_api/controllers/marker_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/marker_controller.ex
@@ -4,6 +4,7 @@
defmodule Pleroma.Web.MastodonAPI.MarkerController do
use Pleroma.Web, :controller
+
alias Pleroma.Web.Plugs.OAuthScopesPlug
plug(Pleroma.Web.ApiSpec.CastAndValidate)
@@ -30,9 +31,16 @@ defmodule Pleroma.Web.MastodonAPI.MarkerController do
def upsert(%{assigns: %{user: user}, body_params: params} = conn, _) do
params = Map.new(params, fn {key, value} -> {to_string(key), value} end)
- with {:ok, result} <- Pleroma.Marker.upsert(user, params),
+ with {:ok, _} <- mark_notifications_read(user, params),
+ {:ok, result} <- Pleroma.Marker.upsert(user, params),
markers <- Map.values(result) do
render(conn, "markers.json", %{markers: markers})
end
end
+
+ defp mark_notifications_read(user, %{"notifications" => %{last_read_id: last_read_id}}) do
+ Pleroma.Notification.set_read_up_to(user, last_read_id)
+ end
+
+ defp mark_notifications_read(_, _), do: {:ok, :noop}
end
diff --git a/lib/pleroma/web/mastodon_api/controllers/status_controller.ex b/lib/pleroma/web/mastodon_api/controllers/status_controller.ex
index b9b236920..d5aef5ad2 100644
--- a/lib/pleroma/web/mastodon_api/controllers/status_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/status_controller.ex
@@ -111,10 +111,11 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do
`ids` query param is required
"""
def index(
- %{assigns: %{user: user}, private: %{open_api_spex: %{params: %{ids: ids} = params}}} =
+ %{assigns: %{user: user}, private: %{open_api_spex: %{params: params}}} =
conn,
_
) do
+ ids = Map.get(params, :id, Map.get(params, :ids))
limit = 100
activities =
diff --git a/lib/pleroma/web/mastodon_api/mastodon_api.ex b/lib/pleroma/web/mastodon_api/mastodon_api.ex
index 6dcbfb097..c9e045d23 100644
--- a/lib/pleroma/web/mastodon_api/mastodon_api.ex
+++ b/lib/pleroma/web/mastodon_api/mastodon_api.ex
@@ -18,10 +18,10 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPI do
if not User.following?(follower, followed) do
CommonAPI.follow(followed, follower)
else
- {:ok, follower, followed, nil}
+ {:ok, followed, follower, nil}
end
- with {:ok, follower, _followed, _} <- result do
+ with {:ok, _followed, follower, _} <- result do
options = cast_params(params)
set_reblogs_visibility(options[:reblogs], result)
set_subscription(options[:notify], result)
@@ -29,19 +29,19 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPI do
end
end
- defp set_reblogs_visibility(false, {:ok, follower, followed, _}) do
+ defp set_reblogs_visibility(false, {:ok, followed, follower, _}) do
CommonAPI.hide_reblogs(followed, follower)
end
- defp set_reblogs_visibility(_, {:ok, follower, followed, _}) do
+ defp set_reblogs_visibility(_, {:ok, followed, follower, _}) do
CommonAPI.show_reblogs(followed, follower)
end
- defp set_subscription(true, {:ok, follower, followed, _}) do
+ defp set_subscription(true, {:ok, followed, follower, _}) do
User.subscribe(follower, followed)
end
- defp set_subscription(false, {:ok, follower, followed, _}) do
+ defp set_subscription(false, {:ok, followed, follower, _}) do
User.unsubscribe(follower, followed)
end
diff --git a/lib/pleroma/web/o_auth/token.ex b/lib/pleroma/web/o_auth/token.ex
index 9b1198b42..d96425094 100644
--- a/lib/pleroma/web/o_auth/token.ex
+++ b/lib/pleroma/web/o_auth/token.ex
@@ -100,11 +100,10 @@ defmodule Pleroma.Web.OAuth.Token do
def create(%App{} = app, %User{} = user, attrs \\ %{}) do
with {:ok, token} <- do_create(app, user, attrs) do
if Pleroma.Config.get([:oauth2, :clean_expired_tokens]) do
- Pleroma.Workers.PurgeExpiredToken.enqueue(%{
- token_id: token.id,
- valid_until: DateTime.from_naive!(token.valid_until, "Etc/UTC"),
- mod: __MODULE__
- })
+ Pleroma.Workers.PurgeExpiredToken.new(%{token_id: token.id, mod: __MODULE__},
+ scheduled_at: DateTime.from_naive!(token.valid_until, "Etc/UTC")
+ )
+ |> Oban.insert()
end
{:ok, token}
diff --git a/lib/pleroma/web/pleroma_api/controllers/backup_controller.ex b/lib/pleroma/web/pleroma_api/controllers/backup_controller.ex
index b9daed22b..0115ec645 100644
--- a/lib/pleroma/web/pleroma_api/controllers/backup_controller.ex
+++ b/lib/pleroma/web/pleroma_api/controllers/backup_controller.ex
@@ -20,7 +20,7 @@ defmodule Pleroma.Web.PleromaAPI.BackupController do
end
def create(%{assigns: %{user: user}} = conn, _params) do
- with {:ok, _} <- Backup.create(user) do
+ with {:ok, _} <- Backup.user(user) do
backups = Backup.list(user)
render(conn, "index.json", backups: backups)
end
diff --git a/lib/pleroma/web/pleroma_api/views/backup_view.ex b/lib/pleroma/web/pleroma_api/views/backup_view.ex
index 20403aeee..d778590f0 100644
--- a/lib/pleroma/web/pleroma_api/views/backup_view.ex
+++ b/lib/pleroma/web/pleroma_api/views/backup_view.ex
@@ -9,22 +9,12 @@ defmodule Pleroma.Web.PleromaAPI.BackupView do
alias Pleroma.Web.CommonAPI.Utils
def render("show.json", %{backup: %Backup{} = backup}) do
- # To deal with records before the migration
- state =
- if backup.state == :invalid do
- if backup.processed, do: :complete, else: :failed
- else
- backup.state
- end
-
%{
id: backup.id,
content_type: backup.content_type,
url: download_url(backup),
file_size: backup.file_size,
processed: backup.processed,
- state: to_string(state),
- processed_number: backup.processed_number,
inserted_at: Utils.to_masto_date(backup.inserted_at)
}
end
diff --git a/lib/pleroma/web/plugs/o_auth_plug.ex b/lib/pleroma/web/plugs/o_auth_plug.ex
index b59ac9d3e..488968691 100644
--- a/lib/pleroma/web/plugs/o_auth_plug.ex
+++ b/lib/pleroma/web/plugs/o_auth_plug.ex
@@ -52,7 +52,7 @@ defmodule Pleroma.Web.Plugs.OAuthPlug do
where: t.token == ^token
)
- with %Token{user_id: user_id} = token_record <- Repo.one(token_query),
+ with %Token{user_id: user_id} = token_record <- Repo.one(token_query) |> Repo.preload(:user),
false <- is_nil(user_id),
%User{} = user <- User.get_cached_by_id(user_id) do
{:ok, user, token_record}
diff --git a/lib/pleroma/web/push.ex b/lib/pleroma/web/push.ex
index d4693f63e..6d777142e 100644
--- a/lib/pleroma/web/push.ex
+++ b/lib/pleroma/web/push.ex
@@ -28,6 +28,7 @@ defmodule Pleroma.Web.Push do
@spec send(Pleroma.Notification.t()) ::
{:ok, Oban.Job.t()} | {:error, Oban.Job.changeset() | term()}
def send(notification) do
- WebPusherWorker.enqueue("web_push", %{"notification_id" => notification.id})
+ WebPusherWorker.new(%{"op" => "web_push", "notification_id" => notification.id})
+ |> Oban.insert()
end
end
diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex
index fc40a1143..6492e3861 100644
--- a/lib/pleroma/web/router.ex
+++ b/lib/pleroma/web/router.ex
@@ -648,7 +648,6 @@ defmodule Pleroma.Web.Router do
get("/accounts/relationships", AccountController, :relationships)
get("/accounts/familiar_followers", AccountController, :familiar_followers)
get("/accounts/:id/lists", AccountController, :lists)
- get("/accounts/:id/identity_proofs", AccountController, :identity_proofs)
get("/endorsements", AccountController, :endorsements)
get("/blocks", AccountController, :blocks)
get("/mutes", AccountController, :mutes)
diff --git a/lib/pleroma/web/views/streamer_view.ex b/lib/pleroma/web/views/streamer_view.ex
index f97570b0a..079a37351 100644
--- a/lib/pleroma/web/views/streamer_view.ex
+++ b/lib/pleroma/web/views/streamer_view.ex
@@ -109,7 +109,25 @@ defmodule Pleroma.Web.StreamerView do
|> Jason.encode!()
end
- def render("follow_relationships_update.json", item, topic) do
+ def render(
+ "follow_relationships_update.json",
+ %{follower: follower, following: following} = item,
+ topic
+ ) do
+ following_follower_count =
+ if Enum.any?([following.hide_followers_count, following.hide_followers]) do
+ 0
+ else
+ following.follower_count
+ end
+
+ following_following_count =
+ if Enum.any?([following.hide_follows_count, following.hide_follows]) do
+ 0
+ else
+ following.following_count
+ end
+
%{
stream: render("stream.json", %{topic: topic}),
event: "pleroma:follow_relationships_update",
@@ -117,14 +135,14 @@ defmodule Pleroma.Web.StreamerView do
%{
state: item.state,
follower: %{
- id: item.follower.id,
- follower_count: item.follower.follower_count,
- following_count: item.follower.following_count
+ id: follower.id,
+ follower_count: follower.follower_count,
+ following_count: follower.following_count
},
following: %{
- id: item.following.id,
- follower_count: item.following.follower_count,
- following_count: item.following.following_count
+ id: following.id,
+ follower_count: following_follower_count,
+ following_count: following_following_count
}
}
|> Jason.encode!()
diff --git a/lib/pleroma/workers/attachments_cleanup_worker.ex b/lib/pleroma/workers/attachments_cleanup_worker.ex
index 0b570b70b..e2f92b1fd 100644
--- a/lib/pleroma/workers/attachments_cleanup_worker.ex
+++ b/lib/pleroma/workers/attachments_cleanup_worker.ex
@@ -8,9 +8,9 @@ defmodule Pleroma.Workers.AttachmentsCleanupWorker do
alias Pleroma.Object
alias Pleroma.Repo
- use Pleroma.Workers.WorkerHelper, queue: "slow"
+ use Oban.Worker, queue: :slow
- @impl Oban.Worker
+ @impl true
def perform(%Job{
args: %{
"op" => "cleanup_attachments",
@@ -31,7 +31,7 @@ defmodule Pleroma.Workers.AttachmentsCleanupWorker do
def perform(%Job{args: %{"op" => "cleanup_attachments", "object" => _object}}), do: {:ok, :skip}
- @impl Oban.Worker
+ @impl true
def timeout(_job), do: :timer.seconds(900)
defp do_clean({object_ids, attachment_urls}) do
diff --git a/lib/pleroma/workers/background_worker.ex b/lib/pleroma/workers/background_worker.ex
index 870aef3c6..60da2d5ca 100644
--- a/lib/pleroma/workers/background_worker.ex
+++ b/lib/pleroma/workers/background_worker.ex
@@ -5,9 +5,9 @@
defmodule Pleroma.Workers.BackgroundWorker do
alias Pleroma.User
- use Pleroma.Workers.WorkerHelper, queue: "background"
+ use Oban.Worker, queue: :background
- @impl Oban.Worker
+ @impl true
def perform(%Job{args: %{"op" => "user_activation", "user_id" => user_id, "status" => status}}) do
user = User.get_cached_by_id(user_id)
@@ -39,6 +39,6 @@ defmodule Pleroma.Workers.BackgroundWorker do
User.perform(:verify_fields_links, user)
end
- @impl Oban.Worker
- def timeout(_job), do: :timer.seconds(15)
+ @impl true
+ def timeout(_job), do: :timer.seconds(900)
end
diff --git a/lib/pleroma/workers/backup_worker.ex b/lib/pleroma/workers/backup_worker.ex
index 54ac31a3c..6466d8d73 100644
--- a/lib/pleroma/workers/backup_worker.ex
+++ b/lib/pleroma/workers/backup_worker.ex
@@ -6,64 +6,46 @@ defmodule Pleroma.Workers.BackupWorker do
use Oban.Worker, queue: :slow, max_attempts: 1
alias Oban.Job
+ alias Pleroma.Config.Getting, as: Config
alias Pleroma.User.Backup
- def process(backup, admin_user_id \\ nil) do
- %{"op" => "process", "backup_id" => backup.id, "admin_user_id" => admin_user_id}
- |> new()
- |> Oban.insert()
- end
-
- def schedule_deletion(backup) do
- days = Pleroma.Config.get([Backup, :purge_after_days])
- time = 60 * 60 * 24 * days
- scheduled_at = Calendar.NaiveDateTime.add!(backup.inserted_at, time)
-
- %{"op" => "delete", "backup_id" => backup.id}
- |> new(scheduled_at: scheduled_at)
- |> Oban.insert()
- end
-
- def delete(backup) do
- %{"op" => "delete", "backup_id" => backup.id}
- |> new()
- |> Oban.insert()
- end
-
- @impl Oban.Worker
+ @impl true
def perform(%Job{
- args: %{"op" => "process", "backup_id" => backup_id, "admin_user_id" => admin_user_id}
+ args: %{"op" => "process", "backup_id" => backup_id}
}) do
- with {:ok, %Backup{} = backup} <-
- backup_id |> Backup.get() |> Backup.process(),
- {:ok, _job} <- schedule_deletion(backup),
- :ok <- Backup.remove_outdated(backup),
- :ok <- maybe_deliver_email(backup, admin_user_id) do
- {:ok, backup}
+ with {_, %Backup{} = backup} <- {:get, Backup.get_by_id(backup_id)},
+ {_, {:ok, updated_backup}} <- {:run, Backup.run(backup)},
+ {_, {:ok, uploaded_backup}} <- {:upload, Backup.upload(updated_backup)},
+ {_, {:ok, _job}} <- {:delete, Backup.schedule_delete(uploaded_backup)},
+ {_, :ok} <- {:outdated, Backup.remove_outdated(uploaded_backup.user)},
+ {_, :ok} <- {:email, maybe_deliver_email(uploaded_backup)} do
+ {:ok, uploaded_backup}
+ else
+ e -> {:error, e}
end
end
def perform(%Job{args: %{"op" => "delete", "backup_id" => backup_id}}) do
- case Backup.get(backup_id) do
- %Backup{} = backup -> Backup.delete(backup)
+ case Backup.get_by_id(backup_id) do
+ %Backup{} = backup -> Backup.delete_archive(backup)
nil -> :ok
end
end
- @impl Oban.Worker
- def timeout(_job), do: :infinity
+ @impl true
+ def timeout(_job), do: Config.get([Backup, :timeout], :timer.minutes(30))
defp has_email?(user) do
not is_nil(user.email) and user.email != ""
end
- defp maybe_deliver_email(backup, admin_user_id) do
+ defp maybe_deliver_email(backup) do
has_mailer = Pleroma.Config.get([Pleroma.Emails.Mailer, :enabled])
backup = backup |> Pleroma.Repo.preload(:user)
if has_email?(backup.user) and has_mailer do
backup
- |> Pleroma.Emails.UserEmail.backup_is_ready_email(admin_user_id)
+ |> Pleroma.Emails.UserEmail.backup_is_ready_email()
|> Pleroma.Emails.Mailer.deliver()
:ok
diff --git a/lib/pleroma/workers/cron/digest_emails_worker.ex b/lib/pleroma/workers/cron/digest_emails_worker.ex
index 17e92d10b..b50b52a7b 100644
--- a/lib/pleroma/workers/cron/digest_emails_worker.ex
+++ b/lib/pleroma/workers/cron/digest_emails_worker.ex
@@ -18,7 +18,7 @@ defmodule Pleroma.Workers.Cron.DigestEmailsWorker do
require Logger
- @impl Oban.Worker
+ @impl true
def perform(_job) do
config = Config.get([:email_notifications, :digest])
@@ -59,6 +59,6 @@ defmodule Pleroma.Workers.Cron.DigestEmailsWorker do
User.touch_last_digest_emailed_at(user)
end
- @impl Oban.Worker
+ @impl true
def timeout(_job), do: :timer.seconds(5)
end
diff --git a/lib/pleroma/workers/cron/new_users_digest_worker.ex b/lib/pleroma/workers/cron/new_users_digest_worker.ex
index 1f57aad4a..787649983 100644
--- a/lib/pleroma/workers/cron/new_users_digest_worker.ex
+++ b/lib/pleroma/workers/cron/new_users_digest_worker.ex
@@ -9,9 +9,9 @@ defmodule Pleroma.Workers.Cron.NewUsersDigestWorker do
import Ecto.Query
- use Pleroma.Workers.WorkerHelper, queue: "background"
+ use Oban.Worker, queue: :background
- @impl Oban.Worker
+ @impl true
def perform(_job) do
if Pleroma.Config.get([Pleroma.Emails.NewUsersDigestEmail, :enabled]) do
today = NaiveDateTime.utc_now() |> Timex.beginning_of_day()
@@ -61,6 +61,6 @@ defmodule Pleroma.Workers.Cron.NewUsersDigestWorker do
:ok
end
- @impl Oban.Worker
+ @impl true
def timeout(_job), do: :timer.seconds(5)
end
diff --git a/lib/pleroma/workers/delete_worker.ex b/lib/pleroma/workers/delete_worker.ex
index 97003fb69..6a1c7bb38 100644
--- a/lib/pleroma/workers/delete_worker.ex
+++ b/lib/pleroma/workers/delete_worker.ex
@@ -6,10 +6,9 @@ defmodule Pleroma.Workers.DeleteWorker do
alias Pleroma.Instances.Instance
alias Pleroma.User
- use Pleroma.Workers.WorkerHelper, queue: "slow"
-
- @impl Oban.Worker
+ use Oban.Worker, queue: :slow
+ @impl true
def perform(%Job{args: %{"op" => "delete_user", "user_id" => user_id}}) do
user = User.get_cached_by_id(user_id)
User.perform(:delete, user)
@@ -19,6 +18,6 @@ defmodule Pleroma.Workers.DeleteWorker do
Instance.perform(:delete_instance, host)
end
- @impl Oban.Worker
+ @impl true
def timeout(_job), do: :timer.seconds(900)
end
diff --git a/lib/pleroma/workers/mailer_worker.ex b/lib/pleroma/workers/mailer_worker.ex
index 652bf77e0..b0259b191 100644
--- a/lib/pleroma/workers/mailer_worker.ex
+++ b/lib/pleroma/workers/mailer_worker.ex
@@ -3,9 +3,9 @@
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Workers.MailerWorker do
- use Pleroma.Workers.WorkerHelper, queue: "background"
+ use Oban.Worker, queue: :background
- @impl Oban.Worker
+ @impl true
def perform(%Job{args: %{"op" => "email", "encoded_email" => encoded_email, "config" => config}}) do
encoded_email
|> Base.decode64!()
@@ -13,6 +13,6 @@ defmodule Pleroma.Workers.MailerWorker do
|> Pleroma.Emails.Mailer.deliver(config)
end
- @impl Oban.Worker
+ @impl true
def timeout(_job), do: :timer.seconds(5)
end
diff --git a/lib/pleroma/workers/mute_expire_worker.ex b/lib/pleroma/workers/mute_expire_worker.ex
index a7ab5883a..8356a775d 100644
--- a/lib/pleroma/workers/mute_expire_worker.ex
+++ b/lib/pleroma/workers/mute_expire_worker.ex
@@ -3,9 +3,9 @@
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Workers.MuteExpireWorker do
- use Pleroma.Workers.WorkerHelper, queue: "background"
+ use Oban.Worker, queue: :background
- @impl Oban.Worker
+ @impl true
def perform(%Job{args: %{"op" => "unmute_user", "muter_id" => muter_id, "mutee_id" => mutee_id}}) do
Pleroma.User.unmute(muter_id, mutee_id)
:ok
@@ -18,6 +18,6 @@ defmodule Pleroma.Workers.MuteExpireWorker do
:ok
end
- @impl Oban.Worker
+ @impl true
def timeout(_job), do: :timer.seconds(5)
end
diff --git a/lib/pleroma/workers/poll_worker.ex b/lib/pleroma/workers/poll_worker.ex
index af8997e70..d263aa1b9 100644
--- a/lib/pleroma/workers/poll_worker.ex
+++ b/lib/pleroma/workers/poll_worker.ex
@@ -6,13 +6,13 @@ defmodule Pleroma.Workers.PollWorker do
@moduledoc """
Generates notifications when a poll ends.
"""
- use Pleroma.Workers.WorkerHelper, queue: "background"
+ use Oban.Worker, queue: :background
alias Pleroma.Activity
alias Pleroma.Notification
alias Pleroma.Object
- @impl Oban.Worker
+ @impl true
def perform(%Job{args: %{"op" => "poll_end", "activity_id" => activity_id}}) do
with %Activity{} = activity <- find_poll_activity(activity_id),
{:ok, notifications} <- Notification.create_poll_notifications(activity) do
@@ -23,7 +23,7 @@ defmodule Pleroma.Workers.PollWorker do
end
end
- @impl Oban.Worker
+ @impl true
def timeout(_job), do: :timer.seconds(5)
defp find_poll_activity(activity_id) do
diff --git a/lib/pleroma/workers/publisher_worker.ex b/lib/pleroma/workers/publisher_worker.ex
index 63fcf4ac2..7d9b022de 100644
--- a/lib/pleroma/workers/publisher_worker.ex
+++ b/lib/pleroma/workers/publisher_worker.ex
@@ -6,13 +6,9 @@ defmodule Pleroma.Workers.PublisherWorker do
alias Pleroma.Activity
alias Pleroma.Web.Federator
- use Pleroma.Workers.WorkerHelper, queue: "federator_outgoing"
+ use Oban.Worker, queue: :federator_outgoing, max_attempts: 5
- def backoff(%Job{attempt: attempt}) when is_integer(attempt) do
- Pleroma.Workers.WorkerHelper.sidekiq_backoff(attempt, 5)
- end
-
- @impl Oban.Worker
+ @impl true
def perform(%Job{args: %{"op" => "publish", "activity_id" => activity_id}}) do
activity = Activity.get_by_id(activity_id)
Federator.perform(:publish, activity)
@@ -23,6 +19,18 @@ defmodule Pleroma.Workers.PublisherWorker do
Federator.perform(:publish_one, params)
end
- @impl Oban.Worker
+ @impl true
def timeout(_job), do: :timer.seconds(10)
+
+ @base_backoff 15
+ @pow 5
+ @impl true
+ def backoff(%Job{attempt: attempt}) when is_integer(attempt) do
+ backoff =
+ :math.pow(attempt, @pow) +
+ @base_backoff +
+ :rand.uniform(2 * @base_backoff) * attempt
+
+ trunc(backoff)
+ end
end
diff --git a/lib/pleroma/workers/purge_expired_activity.ex b/lib/pleroma/workers/purge_expired_activity.ex
index f48e34042..f05e75f46 100644
--- a/lib/pleroma/workers/purge_expired_activity.ex
+++ b/lib/pleroma/workers/purge_expired_activity.ex
@@ -13,16 +13,13 @@ defmodule Pleroma.Workers.PurgeExpiredActivity do
alias Pleroma.Activity
- @spec enqueue(map()) ::
+ @spec enqueue(map(), list()) ::
{:ok, Oban.Job.t()}
| {:error, :expired_activities_disabled}
| {:error, :expiration_too_close}
- def enqueue(args) do
+ def enqueue(params, worker_args) do
with true <- enabled?() do
- {scheduled_at, args} = Map.pop(args, :expires_at)
-
- args
- |> new(scheduled_at: scheduled_at)
+ new(params, worker_args)
|> Oban.insert()
end
end
@@ -35,7 +32,7 @@ defmodule Pleroma.Workers.PurgeExpiredActivity do
end
end
- @impl Oban.Worker
+ @impl true
def timeout(_job), do: :timer.seconds(5)
defp enabled? do
diff --git a/lib/pleroma/workers/purge_expired_filter.ex b/lib/pleroma/workers/purge_expired_filter.ex
index 1f6931e4c..0405f6684 100644
--- a/lib/pleroma/workers/purge_expired_filter.ex
+++ b/lib/pleroma/workers/purge_expired_filter.ex
@@ -31,7 +31,7 @@ defmodule Pleroma.Workers.PurgeExpiredFilter do
|> Repo.delete()
end
- @impl Oban.Worker
+ @impl true
def timeout(_job), do: :timer.seconds(5)
@spec get_expiration(pos_integer()) :: Job.t() | nil
diff --git a/lib/pleroma/workers/purge_expired_token.ex b/lib/pleroma/workers/purge_expired_token.ex
index 1854bf561..ff962f21b 100644
--- a/lib/pleroma/workers/purge_expired_token.ex
+++ b/lib/pleroma/workers/purge_expired_token.ex
@@ -9,16 +9,6 @@ defmodule Pleroma.Workers.PurgeExpiredToken do
use Oban.Worker, queue: :background, max_attempts: 1
- @spec enqueue(%{token_id: integer(), valid_until: DateTime.t(), mod: module()}) ::
- {:ok, Oban.Job.t()} | {:error, Ecto.Changeset.t()}
- def enqueue(args) do
- {scheduled_at, args} = Map.pop(args, :valid_until)
-
- args
- |> __MODULE__.new(scheduled_at: scheduled_at)
- |> Oban.insert()
- end
-
@impl true
def perform(%Oban.Job{args: %{"token_id" => id, "mod" => module}}) do
module
@@ -27,6 +17,6 @@ defmodule Pleroma.Workers.PurgeExpiredToken do
|> Pleroma.Repo.delete()
end
- @impl Oban.Worker
+ @impl true
def timeout(_job), do: :timer.seconds(5)
end
diff --git a/lib/pleroma/workers/receiver_worker.ex b/lib/pleroma/workers/receiver_worker.ex
index fd5c13fca..d4db97b63 100644
--- a/lib/pleroma/workers/receiver_worker.ex
+++ b/lib/pleroma/workers/receiver_worker.ex
@@ -7,9 +7,9 @@ defmodule Pleroma.Workers.ReceiverWorker do
alias Pleroma.User
alias Pleroma.Web.Federator
- use Pleroma.Workers.WorkerHelper, queue: "federator_incoming"
+ use Oban.Worker, queue: :federator_incoming, max_attempts: 5
- @impl Oban.Worker
+ @impl true
def perform(%Job{
args: %{
@@ -51,7 +51,7 @@ defmodule Pleroma.Workers.ReceiverWorker do
end
end
- @impl Oban.Worker
+ @impl true
def timeout(%_{args: %{"timeout" => timeout}}), do: timeout
def timeout(_job), do: :timer.seconds(5)
diff --git a/lib/pleroma/workers/remote_fetcher_worker.ex b/lib/pleroma/workers/remote_fetcher_worker.ex
index 60096e14b..9d3f1ec53 100644
--- a/lib/pleroma/workers/remote_fetcher_worker.ex
+++ b/lib/pleroma/workers/remote_fetcher_worker.ex
@@ -5,31 +5,40 @@
defmodule Pleroma.Workers.RemoteFetcherWorker do
alias Pleroma.Object.Fetcher
- use Pleroma.Workers.WorkerHelper, queue: "background"
+ use Oban.Worker, queue: :background
- @impl Oban.Worker
+ @impl true
def perform(%Job{args: %{"op" => "fetch_remote", "id" => id} = args}) do
case Fetcher.fetch_object_from_id(id, depth: args["depth"]) do
{:ok, _object} ->
:ok
- {:reject, reason} ->
+ {:allowed_depth, false} ->
+ {:cancel, :allowed_depth}
+
+ {:containment, reason} ->
{:cancel, reason}
- {:error, :forbidden} ->
- {:cancel, :forbidden}
+ {:transmogrifier, reason} ->
+ {:cancel, reason}
- {:error, :not_found} ->
- {:cancel, :not_found}
+ {:fetch, {:error, :forbidden = reason}} ->
+ {:cancel, reason}
- {:error, :allowed_depth} ->
- {:cancel, :allowed_depth}
+ {:fetch, {:error, :not_found = reason}} ->
+ {:cancel, reason}
+
+ {:fetch, {:error, {:content_type, _}} = reason} ->
+ {:cancel, reason}
+
+ {:fetch, {:error, reason}} ->
+ {:error, reason}
{:error, _} = e ->
e
end
end
- @impl Oban.Worker
+ @impl true
def timeout(_job), do: :timer.seconds(15)
end
diff --git a/lib/pleroma/workers/rich_media_worker.ex b/lib/pleroma/workers/rich_media_worker.ex
index 2ebf42d4f..d5ba7b63e 100644
--- a/lib/pleroma/workers/rich_media_worker.ex
+++ b/lib/pleroma/workers/rich_media_worker.ex
@@ -9,7 +9,7 @@ defmodule Pleroma.Workers.RichMediaWorker do
use Oban.Worker, queue: :background, max_attempts: 3, unique: [period: 300]
- @impl Oban.Worker
+ @impl true
def perform(%Job{args: %{"op" => "expire", "url" => url} = _args}) do
Card.delete(url)
end
@@ -33,7 +33,7 @@ defmodule Pleroma.Workers.RichMediaWorker do
# a slow/infinite data stream and insert a negative cache entry for the URL
# We pad it by 2 seconds to be certain a slow connection is detected and we
# can inject a negative cache entry for the URL
- @impl Oban.Worker
+ @impl true
def timeout(_job) do
Config.get!([:rich_media, :timeout]) + :timer.seconds(2)
end
diff --git a/lib/pleroma/workers/scheduled_activity_worker.ex b/lib/pleroma/workers/scheduled_activity_worker.ex
index ab62686f4..da386e0c3 100644
--- a/lib/pleroma/workers/scheduled_activity_worker.ex
+++ b/lib/pleroma/workers/scheduled_activity_worker.ex
@@ -7,7 +7,7 @@ defmodule Pleroma.Workers.ScheduledActivityWorker do
The worker to post scheduled activity.
"""
- use Pleroma.Workers.WorkerHelper, queue: "federator_outgoing"
+ use Oban.Worker, queue: :federator_outgoing, max_attempts: 5
alias Pleroma.Repo
alias Pleroma.ScheduledActivity
@@ -15,7 +15,7 @@ defmodule Pleroma.Workers.ScheduledActivityWorker do
require Logger
- @impl Oban.Worker
+ @impl true
def perform(%Job{args: %{"activity_id" => activity_id}}) do
with %ScheduledActivity{} = scheduled_activity <- find_scheduled_activity(activity_id),
%User{} = user <- find_user(scheduled_activity.user_id) do
@@ -37,7 +37,7 @@ defmodule Pleroma.Workers.ScheduledActivityWorker do
end
end
- @impl Oban.Worker
+ @impl true
def timeout(_job), do: :timer.seconds(5)
defp find_scheduled_activity(id) do
diff --git a/lib/pleroma/workers/search_indexing_worker.ex b/lib/pleroma/workers/search_indexing_worker.ex
index 8969ae378..001f5254d 100644
--- a/lib/pleroma/workers/search_indexing_worker.ex
+++ b/lib/pleroma/workers/search_indexing_worker.ex
@@ -1,7 +1,7 @@
defmodule Pleroma.Workers.SearchIndexingWorker do
- use Pleroma.Workers.WorkerHelper, queue: "search_indexing"
+ use Oban.Worker, queue: :search_indexing, max_attempts: 2
- @impl Oban.Worker
+ @impl true
alias Pleroma.Config.Getting, as: Config
@@ -21,6 +21,6 @@ defmodule Pleroma.Workers.SearchIndexingWorker do
search_module.remove_from_index(object)
end
- @impl Oban.Worker
+ @impl true
def timeout(_job), do: :timer.seconds(5)
end
diff --git a/lib/pleroma/workers/user_refresh_worker.ex b/lib/pleroma/workers/user_refresh_worker.ex
index fb90e9c9c..222a4a8f7 100644
--- a/lib/pleroma/workers/user_refresh_worker.ex
+++ b/lib/pleroma/workers/user_refresh_worker.ex
@@ -12,6 +12,6 @@ defmodule Pleroma.Workers.UserRefreshWorker do
User.fetch_by_ap_id(ap_id)
end
- @impl Oban.Worker
+ @impl true
def timeout(_job), do: :timer.seconds(15)
end
diff --git a/lib/pleroma/workers/web_pusher_worker.ex b/lib/pleroma/workers/web_pusher_worker.ex
index c549d3cd6..f4232d02a 100644
--- a/lib/pleroma/workers/web_pusher_worker.ex
+++ b/lib/pleroma/workers/web_pusher_worker.ex
@@ -7,9 +7,9 @@ defmodule Pleroma.Workers.WebPusherWorker do
alias Pleroma.Repo
alias Pleroma.Web.Push.Impl
- use Pleroma.Workers.WorkerHelper, queue: "web_push"
+ use Oban.Worker, queue: :web_push
- @impl Oban.Worker
+ @impl true
def perform(%Job{args: %{"op" => "web_push", "notification_id" => notification_id}}) do
notification =
Notification
@@ -20,6 +20,6 @@ defmodule Pleroma.Workers.WebPusherWorker do
|> Enum.each(&Impl.deliver(&1))
end
- @impl Oban.Worker
+ @impl true
def timeout(_job), do: :timer.seconds(5)
end
diff --git a/lib/pleroma/workers/worker_helper.ex b/lib/pleroma/workers/worker_helper.ex
deleted file mode 100644
index 1d20cbd89..000000000
--- a/lib/pleroma/workers/worker_helper.ex
+++ /dev/null
@@ -1,48 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Workers.WorkerHelper do
- alias Pleroma.Config
- alias Pleroma.Workers.WorkerHelper
-
- def worker_args(queue) do
- case Config.get([:workers, :retries, queue]) do
- nil -> []
- max_attempts -> [max_attempts: max_attempts]
- end
- end
-
- def sidekiq_backoff(attempt, pow \\ 4, base_backoff \\ 15) do
- backoff =
- :math.pow(attempt, pow) +
- base_backoff +
- :rand.uniform(2 * base_backoff) * attempt
-
- trunc(backoff)
- end
-
- defmacro __using__(opts) do
- caller_module = __CALLER__.module
- queue = Keyword.fetch!(opts, :queue)
-
- quote do
- # Note: `max_attempts` is intended to be overridden in `new/2` call
- use Oban.Worker,
- queue: unquote(queue),
- max_attempts: 1
-
- alias Oban.Job
-
- def enqueue(op, params, worker_args \\ []) do
- params = Map.merge(%{"op" => op}, params)
- queue_atom = String.to_atom(unquote(queue))
- worker_args = worker_args ++ WorkerHelper.worker_args(queue_atom)
-
- unquote(caller_module)
- |> apply(:new, [params, worker_args])
- |> Oban.insert()
- end
- end
- end
-end