Merge remote-tracking branch 'origin/develop' into fork

Signed-off-by: marcin mikołajczak <git@mkljczk.pl>
This commit is contained in:
marcin mikołajczak 2024-07-21 12:36:25 +02:00
commit e0d0992e10
39 changed files with 450 additions and 91 deletions

1
changelog.d/fix-mrfs.add Normal file
View file

@ -0,0 +1 @@
Added a Mix task "pleroma.config fix_mrf_policies" which will remove erroneous MRF policies from ConfigDB.

View file

@ -0,0 +1 @@
Transmogrifier: handle non-validate errors on incoming Delete activities

View file

@ -0,0 +1 @@
Fix OpenGraph and Twitter metadata providers when parsing objects with no content or summary fields.

View file

@ -0,0 +1 @@
Deleting, Unfavoriting, Unrepeating, or Unreacting will cancel undelivered publishing jobs for the original activity.

View file

@ -0,0 +1 @@
Changed some jobs to return :cancel on unrecoverable errors that should not be retried

View file

@ -1 +1 @@
Discard Remote Fetcher jobs which errored due to an MRF rejection Discard Remote Fetcher jobs which errored due to an MRF rejection.

View file

@ -0,0 +1 @@
Oban jobs can now be viewed in the Live Dashboard

View file

@ -0,0 +1 @@
Prevent Rich Media backfill jobs from retrying in cases where it is likely they will fail again.

View file

@ -0,0 +1 @@
Ensure all Oban jobs have timeouts defined

View file

@ -600,9 +600,9 @@
web_push: 50, web_push: 50,
transmogrifier: 20, transmogrifier: 20,
notifications: 20, notifications: 20,
background: 5, background: 20,
search_indexing: [limit: 10, paused: true], search_indexing: [limit: 10, paused: true],
slow: 1 slow: 5
], ],
plugins: [Oban.Plugins.Pruner], plugins: [Oban.Plugins.Pruner],
crontab: [ crontab: [

View file

@ -154,4 +154,19 @@ This forcibly removes all saved values in the database.
```sh ```sh
mix pleroma.config [--force] reset mix pleroma.config [--force] reset
``` ```
## Remove invalid MRF modules from the database
This forcibly removes any enabled MRF that does not exist and will fix the ability of the instance to start.
=== "OTP"
```sh
./bin/pleroma_ctl config fix_mrf_policies
```
=== "From Source"
```sh
mix pleroma.config fix_mrf_policies
```

View file

@ -205,6 +205,35 @@ def run(["delete", group]) do
end end
end end
# Removes any policies that are not a real module
# as they will prevent the server from starting
def run(["fix_mrf_policies"]) do
check_configdb(fn ->
start_pleroma()
group = :pleroma
key = :mrf
%{value: value} =
group
|> ConfigDB.get_by_group_and_key(key)
policies =
Keyword.get(value, :policies, [])
|> Enum.filter(&is_atom(&1))
|> Enum.filter(fn mrf ->
case Code.ensure_compiled(mrf) do
{:module, _} -> true
{:error, _} -> false
end
end)
value = Keyword.put(value, :policies, policies)
ConfigDB.update_or_create(%{group: group, key: key, value: value})
end)
end
@spec migrate_to_db(Path.t() | nil) :: any() @spec migrate_to_db(Path.t() | nil) :: any()
def migrate_to_db(file_path \\ nil) do def migrate_to_db(file_path \\ nil) do
with :ok <- Pleroma.Config.DeprecationWarnings.warn() do with :ok <- Pleroma.Config.DeprecationWarnings.warn() do

View file

@ -10,7 +10,7 @@ defmodule Pleroma.Instances.Instance do
alias Pleroma.Maps alias Pleroma.Maps
alias Pleroma.Repo alias Pleroma.Repo
alias Pleroma.User alias Pleroma.User
alias Pleroma.Workers.BackgroundWorker alias Pleroma.Workers.DeleteWorker
use Ecto.Schema use Ecto.Schema
@ -297,7 +297,7 @@ defp scrape_metadata(%URI{} = instance_uri) do
all of those users' activities and notifications. all of those users' activities and notifications.
""" """
def delete_users_and_activities(host) when is_binary(host) do def delete_users_and_activities(host) when is_binary(host) do
BackgroundWorker.enqueue("delete_instance", %{"host" => host}) DeleteWorker.enqueue("delete_instance", %{"host" => host})
end end
def perform(:delete_instance, host) when is_binary(host) do def perform(:delete_instance, host) when is_binary(host) do

View file

@ -59,6 +59,7 @@ def refetch_object(%Object{data: %{"id" => id}} = object) do
end end
# Note: will create a Create activity, which we need internally at the moment. # Note: will create a Create activity, which we need internally at the moment.
@spec fetch_object_from_id(String.t(), list()) :: {:ok, Object.t()} | {:error | :reject, any()}
def fetch_object_from_id(id, options \\ []) do def fetch_object_from_id(id, options \\ []) do
with {_, nil} <- {:fetch_object, Object.get_cached_by_ap_id(id)}, with {_, nil} <- {:fetch_object, Object.get_cached_by_ap_id(id)},
{_, true} <- {:allowed_depth, Federator.allowed_thread_distance?(options[:depth])}, {_, true} <- {:allowed_depth, Federator.allowed_thread_distance?(options[:depth])},

View file

@ -40,6 +40,7 @@ defmodule Pleroma.User do
alias Pleroma.Web.RelMe alias Pleroma.Web.RelMe
alias Pleroma.Webhook.Notify alias Pleroma.Webhook.Notify
alias Pleroma.Workers.BackgroundWorker alias Pleroma.Workers.BackgroundWorker
alias Pleroma.Workers.DeleteWorker
alias Pleroma.Workers.UserRefreshWorker alias Pleroma.Workers.UserRefreshWorker
require Logger require Logger
@ -2032,7 +2033,7 @@ def delete(users) when is_list(users) do
def delete(%User{} = user) do def delete(%User{} = user) do
# Purge the user immediately # Purge the user immediately
purge(user) purge(user)
BackgroundWorker.enqueue("delete_user", %{"user_id" => user.id}) DeleteWorker.enqueue("delete_user", %{"user_id" => user.id})
end end
# *Actually* delete the user from the DB # *Actually* delete the user from the DB

View file

@ -540,6 +540,9 @@ def handle_incoming(
else else
_ -> e _ -> e
end end
e ->
{:error, e}
end end
end end

View file

@ -19,6 +19,7 @@ defmodule Pleroma.Web.CommonAPI do
alias Pleroma.Web.ActivityPub.Visibility alias Pleroma.Web.ActivityPub.Visibility
alias Pleroma.Web.CommonAPI.ActivityDraft alias Pleroma.Web.CommonAPI.ActivityDraft
import Ecto.Query, only: [where: 3]
import Pleroma.Web.Gettext import Pleroma.Web.Gettext
import Pleroma.Web.CommonAPI.Utils import Pleroma.Web.CommonAPI.Utils
@ -156,6 +157,7 @@ def reject_follow_request(follower, followed) do
def delete(activity_id, user) do def delete(activity_id, user) do
with {_, %Activity{data: %{"object" => _, "type" => "Create"}} = activity} <- with {_, %Activity{data: %{"object" => _, "type" => "Create"}} = activity} <-
{:find_activity, Activity.get_by_id(activity_id, filter: [])}, {:find_activity, Activity.get_by_id(activity_id, filter: [])},
{_, {:ok, _}} <- {:cancel_jobs, maybe_cancel_jobs(activity)},
{_, %Object{} = object, _} <- {_, %Object{} = object, _} <-
{:find_object, Object.normalize(activity, fetch: false), activity}, {:find_object, Object.normalize(activity, fetch: false), activity},
true <- User.privileged?(user, :messages_delete) || user.ap_id == object.data["actor"], true <- User.privileged?(user, :messages_delete) || user.ap_id == object.data["actor"],
@ -223,6 +225,7 @@ def unrepeat(id, user) do
{:find_activity, Activity.get_by_id(id)}, {:find_activity, Activity.get_by_id(id)},
%Object{} = note <- Object.normalize(activity, fetch: false), %Object{} = note <- Object.normalize(activity, fetch: false),
%Activity{} = announce <- Utils.get_existing_announce(user.ap_id, note), %Activity{} = announce <- Utils.get_existing_announce(user.ap_id, note),
{_, {:ok, _}} <- {:cancel_jobs, maybe_cancel_jobs(announce)},
{:ok, undo, _} <- Builder.undo(user, announce), {:ok, undo, _} <- Builder.undo(user, announce),
{:ok, activity, _} <- Pipeline.common_pipeline(undo, local: true) do {:ok, activity, _} <- Pipeline.common_pipeline(undo, local: true) do
{:ok, activity} {:ok, activity}
@ -275,6 +278,7 @@ def unfavorite(id, user) do
{:find_activity, Activity.get_by_id(id)}, {:find_activity, Activity.get_by_id(id)},
%Object{} = note <- Object.normalize(activity, fetch: false), %Object{} = note <- Object.normalize(activity, fetch: false),
%Activity{} = like <- Utils.get_existing_like(user.ap_id, note), %Activity{} = like <- Utils.get_existing_like(user.ap_id, note),
{_, {:ok, _}} <- {:cancel_jobs, maybe_cancel_jobs(like)},
{:ok, undo, _} <- Builder.undo(user, like), {:ok, undo, _} <- Builder.undo(user, like),
{:ok, activity, _} <- Pipeline.common_pipeline(undo, local: true) do {:ok, activity, _} <- Pipeline.common_pipeline(undo, local: true) do
{:ok, activity} {:ok, activity}
@ -298,6 +302,7 @@ def react_with_emoji(id, user, emoji) do
def unreact_with_emoji(id, user, emoji) do def unreact_with_emoji(id, user, emoji) do
with %Activity{} = reaction_activity <- Utils.get_latest_reaction(id, user, emoji), with %Activity{} = reaction_activity <- Utils.get_latest_reaction(id, user, emoji),
{_, {:ok, _}} <- {:cancel_jobs, maybe_cancel_jobs(reaction_activity)},
{:ok, undo, _} <- Builder.undo(user, reaction_activity), {:ok, undo, _} <- Builder.undo(user, reaction_activity),
{:ok, activity, _} <- Pipeline.common_pipeline(undo, local: true) do {:ok, activity, _} <- Pipeline.common_pipeline(undo, local: true) do
{:ok, activity} {:ok, activity}
@ -807,4 +812,14 @@ defp make_update_event_data(user, orig_object, changes, location) do
_ -> {:error, nil} _ -> {:error, nil}
end end
end end
defp maybe_cancel_jobs(%Activity{data: %{"id" => ap_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)
|> Oban.cancel_all_jobs()
end
defp maybe_cancel_jobs(_), do: {:ok, 0}
end end

View file

@ -25,11 +25,14 @@ def scrub_html_and_truncate(%{data: %{"summary" => summary}} = object)
|> scrub_html_and_truncate_object_field(object) |> scrub_html_and_truncate_object_field(object)
end end
def scrub_html_and_truncate(%{data: %{"content" => content}} = object) do def scrub_html_and_truncate(%{data: %{"content" => content}} = object)
when is_binary(content) and content != "" do
content content
|> scrub_html_and_truncate_object_field(object) |> scrub_html_and_truncate_object_field(object)
end end
def scrub_html_and_truncate(%{}), do: ""
def scrub_html_and_truncate(content, max_length \\ 200, omission \\ "...") def scrub_html_and_truncate(content, max_length \\ 200, omission \\ "...")
when is_binary(content) do when is_binary(content) do
content content

View file

@ -4,6 +4,7 @@
defmodule Pleroma.Web.RichMedia.Backfill do defmodule Pleroma.Web.RichMedia.Backfill do
alias Pleroma.Web.RichMedia.Card alias Pleroma.Web.RichMedia.Card
alias Pleroma.Web.RichMedia.Helpers
alias Pleroma.Web.RichMedia.Parser alias Pleroma.Web.RichMedia.Parser
alias Pleroma.Web.RichMedia.Parser.TTL alias Pleroma.Web.RichMedia.Parser.TTL
alias Pleroma.Workers.RichMediaWorker alias Pleroma.Workers.RichMediaWorker
@ -16,8 +17,7 @@ defmodule Pleroma.Web.RichMedia.Backfill do
Pleroma.Web.ActivityPub.ActivityPub Pleroma.Web.ActivityPub.ActivityPub
) )
@spec run(map()) :: @spec run(map()) :: :ok | Parser.parse_errors() | Helpers.get_errors()
:ok | {:error, {:invalid_metadata, any()} | :body_too_large | {:content, any()} | any()}
def run(%{"url" => url} = args) do def run(%{"url" => url} = args) do
url_hash = Card.url_to_hash(url) url_hash = Card.url_to_hash(url)
@ -33,22 +33,16 @@ def run(%{"url" => url} = args) do
end end
warm_cache(url_hash, card) warm_cache(url_hash, card)
:ok
{:error, {:invalid_metadata, fields}} -> {:error, type} = error
Logger.debug("Rich media incomplete or invalid metadata for #{url}: #{inspect(fields)}") when type in [:invalid_metadata, :body_too_large, :content_type, :validate] ->
negative_cache(url_hash) negative_cache(url_hash)
error
{:error, :body_too_large} -> {:error, type} = error
Logger.error("Rich media error for #{url}: :body_too_large") when type in [:get, :head] ->
negative_cache(url_hash) error
{:error, {:content_type, type}} ->
Logger.debug("Rich media error for #{url}: :content_type is #{type}")
negative_cache(url_hash)
e ->
Logger.debug("Rich media error for #{url}: #{inspect(e)}")
{:error, e}
end end
end end

View file

@ -5,6 +5,12 @@
defmodule Pleroma.Web.RichMedia.Helpers do defmodule Pleroma.Web.RichMedia.Helpers do
alias Pleroma.Config alias Pleroma.Config
require Logger
@type get_errors :: {:error, :body_too_large | :content_type | :head | :get}
@spec rich_media_get(String.t()) :: {:ok, String.t()} | get_errors()
defp headers do defp headers do
user_agent = user_agent =
case Pleroma.Config.get([:rich_media, :user_agent], :default) do case Pleroma.Config.get([:rich_media, :user_agent], :default) do
@ -21,23 +27,30 @@ defp headers do
def rich_media_get(url) do def rich_media_get(url) do
headers = headers() headers = headers()
head_check = with {_, {:ok, %Tesla.Env{status: 200, headers: headers}}} <-
case Pleroma.HTTP.head(url, headers, http_options()) do {:head, Pleroma.HTTP.head(url, headers, http_options())},
# If the HEAD request didn't reach the server for whatever reason, {_, :ok} <- {:content_type, check_content_type(headers)},
# we assume the GET that comes right after won't either {_, :ok} <- {:content_length, check_content_length(headers)},
{:error, _} = e -> {_, {:ok, %Tesla.Env{status: 200, body: body}}} <-
e {:get, Pleroma.HTTP.get(url, headers, http_options())} do
{:ok, body}
else
{:head, _} ->
Logger.debug("Rich media error for #{url}: HTTP HEAD failed")
{:error, :head}
{:ok, %Tesla.Env{status: 200, headers: headers}} -> {:content_type, {_, type}} ->
with :ok <- check_content_type(headers), Logger.debug("Rich media error for #{url}: content-type is #{type}")
:ok <- check_content_length(headers), {:error, :content_type}
do: :ok
_ -> {:content_length, {_, length}} ->
:ok Logger.debug("Rich media error for #{url}: content-length is #{length}")
end {:error, :body_too_large}
with :ok <- head_check, do: Pleroma.HTTP.get(url, headers, http_options()) {:get, _} ->
Logger.debug("Rich media error for #{url}: HTTP GET failed")
{:error, :get}
end
end end
defp check_content_type(headers) do defp check_content_type(headers) do
@ -45,7 +58,7 @@ defp check_content_type(headers) do
{_, content_type} -> {_, content_type} ->
case Plug.Conn.Utils.media_type(content_type) do case Plug.Conn.Utils.media_type(content_type) do
{:ok, "text", "html", _} -> :ok {:ok, "text", "html", _} -> :ok
_ -> {:error, {:content_type, content_type}} _ -> {:error, content_type}
end end
_ -> _ ->
@ -60,7 +73,7 @@ defp check_content_length(headers) do
{_, maybe_content_length} -> {_, maybe_content_length} ->
case Integer.parse(maybe_content_length) do case Integer.parse(maybe_content_length) do
{content_length, ""} when content_length <= max_body -> :ok {content_length, ""} when content_length <= max_body -> :ok
{_, ""} -> {:error, :body_too_large} {_, ""} -> {:error, maybe_content_length}
_ -> :ok _ -> :ok
end end

View file

@ -3,6 +3,7 @@
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.RichMedia.Parser do defmodule Pleroma.Web.RichMedia.Parser do
alias Pleroma.Web.RichMedia.Helpers
require Logger require Logger
@config_impl Application.compile_env(:pleroma, [__MODULE__, :config_impl], Pleroma.Config) @config_impl Application.compile_env(:pleroma, [__MODULE__, :config_impl], Pleroma.Config)
@ -11,24 +12,26 @@ defp parsers do
Pleroma.Config.get([:rich_media, :parsers]) Pleroma.Config.get([:rich_media, :parsers])
end end
def parse(nil), do: nil @type parse_errors :: {:error, :rich_media_disabled | :validate}
@spec parse(String.t()) :: {:ok, map()} | {:error, any()} @spec parse(String.t()) ::
def parse(url) do {:ok, map()} | parse_errors() | Helpers.get_errors()
def parse(url) when is_binary(url) do
with {_, true} <- {:config, @config_impl.get([:rich_media, :enabled])}, with {_, true} <- {:config, @config_impl.get([:rich_media, :enabled])},
:ok <- validate_page_url(url), {_, :ok} <- {:validate, validate_page_url(url)},
{:ok, data} <- parse_url(url) do {_, {:ok, data}} <- {:parse, parse_url(url)} do
data = Map.put(data, "url", url) data = Map.put(data, "url", url)
{:ok, data} {:ok, data}
else else
{:config, _} -> {:error, :rich_media_disabled} {:config, _} -> {:error, :rich_media_disabled}
e -> e {:validate, _} -> {:error, :validate}
{:parse, error} -> error
end end
end end
defp parse_url(url) do defp parse_url(url) do
with {:ok, %Tesla.Env{body: html}} <- Pleroma.Web.RichMedia.Helpers.rich_media_get(url), with {:ok, body} <- Helpers.rich_media_get(url),
{:ok, html} <- Floki.parse_document(html) do {:ok, html} <- Floki.parse_document(body) do
html html
|> maybe_parse() |> maybe_parse()
|> clean_parsed_data() |> clean_parsed_data()
@ -50,8 +53,8 @@ defp check_parsed_data(%{"title" => title} = data)
{:ok, data} {:ok, data}
end end
defp check_parsed_data(data) do defp check_parsed_data(_data) do
{:error, {:invalid_metadata, data}} {:error, :invalid_metadata}
end end
defp clean_parsed_data(data) do defp clean_parsed_data(data) do

View file

@ -22,7 +22,7 @@ defp get_oembed_url([{"link", attributes, _children} | _]) do
end end
defp get_oembed_data(url) do defp get_oembed_data(url) do
with {:ok, %Tesla.Env{body: json}} <- Pleroma.Web.RichMedia.Helpers.rich_media_get(url) do with {:ok, json} <- Pleroma.Web.RichMedia.Helpers.rich_media_get(url) do
Jason.decode(json) Jason.decode(json)
end end
end end

View file

@ -1137,7 +1137,7 @@ defmodule Pleroma.Web.Router do
scope "/" do scope "/" do
pipe_through([:pleroma_html, :authenticate, :require_admin]) pipe_through([:pleroma_html, :authenticate, :require_admin])
live_dashboard("/phoenix/live_dashboard") live_dashboard("/phoenix/live_dashboard", additional_pages: [oban: Oban.LiveDashboard])
end end
# Test-only routes needed to test action dispatching and plug chain execution # Test-only routes needed to test action dispatching and plug chain execution

View file

@ -3,7 +3,6 @@
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Workers.BackgroundWorker do defmodule Pleroma.Workers.BackgroundWorker do
alias Pleroma.Instances.Instance
alias Pleroma.User alias Pleroma.User
use Pleroma.Workers.WorkerHelper, queue: "background" use Pleroma.Workers.WorkerHelper, queue: "background"
@ -15,11 +14,6 @@ def perform(%Job{args: %{"op" => "user_activation", "user_id" => user_id, "statu
User.perform(:set_activation_async, user, status) User.perform(:set_activation_async, user, status)
end end
def perform(%Job{args: %{"op" => "delete_user", "user_id" => user_id}}) do
user = User.get_cached_by_id(user_id)
User.perform(:delete, user)
end
def perform(%Job{args: %{"op" => "force_password_reset", "user_id" => user_id}}) do def perform(%Job{args: %{"op" => "force_password_reset", "user_id" => user_id}}) do
user = User.get_cached_by_id(user_id) user = User.get_cached_by_id(user_id)
User.perform(:force_password_reset, user) User.perform(:force_password_reset, user)
@ -45,10 +39,6 @@ def perform(%Job{args: %{"op" => "verify_fields_links", "user_id" => user_id}})
User.perform(:verify_fields_links, user) User.perform(:verify_fields_links, user)
end end
def perform(%Job{args: %{"op" => "delete_instance", "host" => host}}) do
Instance.perform(:delete_instance, host)
end
@impl Oban.Worker @impl Oban.Worker
def timeout(_job), do: :timer.seconds(900) def timeout(_job), do: :timer.seconds(5)
end end

View file

@ -58,4 +58,7 @@ def send_email(user) do
User.touch_last_digest_emailed_at(user) User.touch_last_digest_emailed_at(user)
end end
@impl Oban.Worker
def timeout(_job), do: :timer.seconds(5)
end end

View file

@ -60,4 +60,7 @@ def perform(_job) do
:ok :ok
end end
@impl Oban.Worker
def timeout(_job), do: :timer.seconds(5)
end end

View file

@ -0,0 +1,24 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Workers.DeleteWorker do
alias Pleroma.Instances.Instance
alias Pleroma.User
use Pleroma.Workers.WorkerHelper, queue: "slow"
@impl Oban.Worker
def perform(%Job{args: %{"op" => "delete_user", "user_id" => user_id}}) do
user = User.get_cached_by_id(user_id)
User.perform(:delete, user)
end
def perform(%Job{args: %{"op" => "delete_instance", "host" => host}}) do
Instance.perform(:delete_instance, host)
end
@impl Oban.Worker
def timeout(_job), do: :timer.seconds(900)
end

View file

@ -6,8 +6,8 @@ defmodule Pleroma.Workers.PurgeExpiredActivity do
@moduledoc """ @moduledoc """
Worker which purges expired activity. Worker which purges expired activity.
""" """
@queue :background
use Oban.Worker, queue: :slow, max_attempts: 1, unique: [period: :infinity] use Oban.Worker, queue: @queue, max_attempts: 1, unique: [period: :infinity]
import Ecto.Query import Ecto.Query
@ -46,20 +46,22 @@ defp enabled? do
defp find_activity(id) do defp find_activity(id) do
with nil <- Activity.get_by_id_with_object(id) do with nil <- Activity.get_by_id_with_object(id) do
{:error, :activity_not_found} {:cancel, :activity_not_found}
end end
end end
defp find_user(ap_id) do defp find_user(ap_id) do
with nil <- Pleroma.User.get_by_ap_id(ap_id) do with nil <- Pleroma.User.get_by_ap_id(ap_id) do
{:error, :user_not_found} {:cancel, :user_not_found}
end end
end end
def get_expiration(id) do def get_expiration(id) do
queue = Atom.to_string(@queue)
from(j in Oban.Job, from(j in Oban.Job,
where: j.state == "scheduled", where: j.state == "scheduled",
where: j.queue == "slow", where: j.queue == ^queue,
where: fragment("?->>'activity_id' = ?", j.args, ^id) where: fragment("?->>'activity_id' = ?", j.args, ^id)
) )
|> Pleroma.Repo.one() |> Pleroma.Repo.one()

View file

@ -13,7 +13,7 @@ def perform(%Job{args: %{"op" => "fetch_remote", "id" => id} = args}) do
{:ok, _object} -> {:ok, _object} ->
:ok :ok
{:rejected, reason} -> {:reject, reason} ->
{:cancel, reason} {:cancel, reason}
{:error, :forbidden} -> {:error, :forbidden} ->
@ -27,9 +27,6 @@ def perform(%Job{args: %{"op" => "fetch_remote", "id" => id} = args}) do
{:error, _} = e -> {:error, _} = e ->
e e
e ->
{:error, e}
end end
end end

View file

@ -14,6 +14,23 @@ def perform(%Job{args: %{"op" => "expire", "url" => url} = _args}) do
end end
def perform(%Job{args: %{"op" => "backfill", "url" => _url} = args}) do def perform(%Job{args: %{"op" => "backfill", "url" => _url} = args}) do
Backfill.run(args) case Backfill.run(args) do
:ok ->
:ok
{:error, type}
when type in [:invalid_metadata, :body_too_large, :content_type, :validate] ->
{:cancel, type}
{:error, type}
when type in [:get, :head] ->
{:error, type}
error ->
{:error, error}
end
end end
@impl Oban.Worker
def timeout(_job), do: :timer.seconds(5)
end end

View file

@ -20,4 +20,7 @@ def perform(%Job{args: %{"op" => "remove_from_index", "object" => object_id}}) d
search_module.remove_from_index(object) search_module.remove_from_index(object)
end end
@impl Oban.Worker
def timeout(_job), do: :timer.seconds(5)
end end

View file

@ -11,4 +11,7 @@ defmodule Pleroma.Workers.UserRefreshWorker do
def perform(%Job{args: %{"ap_id" => ap_id}}) do def perform(%Job{args: %{"ap_id" => ap_id}}) do
User.fetch_by_ap_id(ap_id) User.fetch_by_ap_id(ap_id)
end end
@impl Oban.Worker
def timeout(_job), do: :timer.seconds(5)
end end

View file

@ -204,6 +204,7 @@ defp deps do
{:exile, "~> 0.10.0"}, {:exile, "~> 0.10.0"},
{:bandit, "~> 1.5.2"}, {:bandit, "~> 1.5.2"},
{:websock_adapter, "~> 0.5.6"}, {:websock_adapter, "~> 0.5.6"},
{:oban_live_dashboard, "~> 0.1.1"},
{:icalendar, "~> 1.1"}, {:icalendar, "~> 1.1"},
{:geospatial, "~> 0.3.0"}, {:geospatial, "~> 0.3.0"},

View file

@ -27,7 +27,7 @@
"crypt": {:git, "https://github.com/msantos/crypt.git", "f75cd55325e33cbea198fb41fe41871392f8fb76", [ref: "f75cd55325e33cbea198fb41fe41871392f8fb76"]}, "crypt": {:git, "https://github.com/msantos/crypt.git", "f75cd55325e33cbea198fb41fe41871392f8fb76", [ref: "f75cd55325e33cbea198fb41fe41871392f8fb76"]},
"csv": {:hex, :csv, "2.4.1", "50e32749953b6bf9818dbfed81cf1190e38cdf24f95891303108087486c5925e", [:mix], [{:parallel_stream, "~> 1.0.4", [hex: :parallel_stream, repo: "hexpm", optional: false]}], "hexpm", "54508938ac67e27966b10ef49606e3ad5995d665d7fc2688efb3eab1307c9079"}, "csv": {:hex, :csv, "2.4.1", "50e32749953b6bf9818dbfed81cf1190e38cdf24f95891303108087486c5925e", [:mix], [{:parallel_stream, "~> 1.0.4", [hex: :parallel_stream, repo: "hexpm", optional: false]}], "hexpm", "54508938ac67e27966b10ef49606e3ad5995d665d7fc2688efb3eab1307c9079"},
"custom_base": {:hex, :custom_base, "0.2.1", "4a832a42ea0552299d81652aa0b1f775d462175293e99dfbe4d7dbaab785a706", [:mix], [], "hexpm", "8df019facc5ec9603e94f7270f1ac73ddf339f56ade76a721eaa57c1493ba463"}, "custom_base": {:hex, :custom_base, "0.2.1", "4a832a42ea0552299d81652aa0b1f775d462175293e99dfbe4d7dbaab785a706", [:mix], [], "hexpm", "8df019facc5ec9603e94f7270f1ac73ddf339f56ade76a721eaa57c1493ba463"},
"db_connection": {:hex, :db_connection, "2.6.0", "77d835c472b5b67fc4f29556dee74bf511bbafecdcaf98c27d27fa5918152086", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "c2f992d15725e721ec7fbc1189d4ecdb8afef76648c746a8e1cad35e3b8a35f3"}, "db_connection": {:hex, :db_connection, "2.7.0", "b99faa9291bb09892c7da373bb82cba59aefa9b36300f6145c5f201c7adf48ec", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "dcf08f31b2701f857dfc787fbad78223d61a32204f217f15e881dd93e4bdd3ff"},
"decimal": {:hex, :decimal, "2.1.1", "5611dca5d4b2c3dd497dec8f68751f1f1a54755e8ed2a966c2633cf885973ad6", [:mix], [], "hexpm", "53cfe5f497ed0e7771ae1a475575603d77425099ba5faef9394932b35020ffcc"}, "decimal": {:hex, :decimal, "2.1.1", "5611dca5d4b2c3dd497dec8f68751f1f1a54755e8ed2a966c2633cf885973ad6", [:mix], [], "hexpm", "53cfe5f497ed0e7771ae1a475575603d77425099ba5faef9394932b35020ffcc"},
"deep_merge": {:hex, :deep_merge, "1.0.0", "b4aa1a0d1acac393bdf38b2291af38cb1d4a52806cf7a4906f718e1feb5ee961", [:mix], [], "hexpm", "ce708e5f094b9cd4e8f2be4f00d2f4250c4095be93f8cd6d018c753894885430"}, "deep_merge": {:hex, :deep_merge, "1.0.0", "b4aa1a0d1acac393bdf38b2291af38cb1d4a52806cf7a4906f718e1feb5ee961", [:mix], [], "hexpm", "ce708e5f094b9cd4e8f2be4f00d2f4250c4095be93f8cd6d018c753894885430"},
"dialyxir": {:hex, :dialyxir, "1.4.3", "edd0124f358f0b9e95bfe53a9fcf806d615d8f838e2202a9f430d59566b6b53b", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "bf2cfb75cd5c5006bec30141b131663299c661a864ec7fbbc72dfa557487a986"}, "dialyxir": {:hex, :dialyxir, "1.4.3", "edd0124f358f0b9e95bfe53a9fcf806d615d8f838e2202a9f430d59566b6b53b", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "bf2cfb75cd5c5006bec30141b131663299c661a864ec7fbbc72dfa557487a986"},
@ -37,7 +37,7 @@
"ecto": {:hex, :ecto, "3.11.2", "e1d26be989db350a633667c5cda9c3d115ae779b66da567c68c80cfb26a8c9ee", [:mix], [{:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "3c38bca2c6f8d8023f2145326cc8a80100c3ffe4dcbd9842ff867f7fc6156c65"}, "ecto": {:hex, :ecto, "3.11.2", "e1d26be989db350a633667c5cda9c3d115ae779b66da567c68c80cfb26a8c9ee", [:mix], [{:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "3c38bca2c6f8d8023f2145326cc8a80100c3ffe4dcbd9842ff867f7fc6156c65"},
"ecto_enum": {:hex, :ecto_enum, "1.4.0", "d14b00e04b974afc69c251632d1e49594d899067ee2b376277efd8233027aec8", [:mix], [{:ecto, ">= 3.0.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:ecto_sql, "> 3.0.0", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:mariaex, ">= 0.0.0", [hex: :mariaex, repo: "hexpm", optional: true]}, {:postgrex, ">= 0.0.0", [hex: :postgrex, repo: "hexpm", optional: true]}], "hexpm", "8fb55c087181c2b15eee406519dc22578fa60dd82c088be376d0010172764ee4"}, "ecto_enum": {:hex, :ecto_enum, "1.4.0", "d14b00e04b974afc69c251632d1e49594d899067ee2b376277efd8233027aec8", [:mix], [{:ecto, ">= 3.0.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:ecto_sql, "> 3.0.0", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:mariaex, ">= 0.0.0", [hex: :mariaex, repo: "hexpm", optional: true]}, {:postgrex, ">= 0.0.0", [hex: :postgrex, repo: "hexpm", optional: true]}], "hexpm", "8fb55c087181c2b15eee406519dc22578fa60dd82c088be376d0010172764ee4"},
"ecto_psql_extras": {:hex, :ecto_psql_extras, "0.7.15", "0fc29dbae0e444a29bd6abeee4cf3c4c037e692a272478a234a1cc765077dbb1", [:mix], [{:ecto_sql, "~> 3.7", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.16.0 or ~> 0.17.0", [hex: :postgrex, repo: "hexpm", optional: false]}, {:table_rex, "~> 3.1.1 or ~> 4.0.0", [hex: :table_rex, repo: "hexpm", optional: false]}], "hexpm", "b6127f3a5c6fc3d84895e4768cc7c199f22b48b67d6c99b13fbf4a374e73f039"}, "ecto_psql_extras": {:hex, :ecto_psql_extras, "0.7.15", "0fc29dbae0e444a29bd6abeee4cf3c4c037e692a272478a234a1cc765077dbb1", [:mix], [{:ecto_sql, "~> 3.7", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.16.0 or ~> 0.17.0", [hex: :postgrex, repo: "hexpm", optional: false]}, {:table_rex, "~> 3.1.1 or ~> 4.0.0", [hex: :table_rex, repo: "hexpm", optional: false]}], "hexpm", "b6127f3a5c6fc3d84895e4768cc7c199f22b48b67d6c99b13fbf4a374e73f039"},
"ecto_sql": {:hex, :ecto_sql, "3.11.2", "c7cc7f812af571e50b80294dc2e535821b3b795ce8008d07aa5f336591a185a8", [:mix], [{:db_connection, "~> 2.4.1 or ~> 2.5", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.11.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.6.0", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.16 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1 or ~> 2.2", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "73c07f995ac17dbf89d3cfaaf688fcefabcd18b7b004ac63b0dc4ef39499ed6b"}, "ecto_sql": {:hex, :ecto_sql, "3.11.3", "4eb7348ff8101fbc4e6bbc5a4404a24fecbe73a3372d16569526b0cf34ebc195", [:mix], [{:db_connection, "~> 2.4.1 or ~> 2.5", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.11.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.6", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.16 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1 or ~> 2.2", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "e5f36e3d736b99c7fee3e631333b8394ade4bafe9d96d35669fca2d81c2be928"},
"eimp": {:hex, :eimp, "1.0.14", "fc297f0c7e2700457a95a60c7010a5f1dcb768a083b6d53f49cd94ab95a28f22", [:rebar3], [{:p1_utils, "1.0.18", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "501133f3112079b92d9e22da8b88bf4f0e13d4d67ae9c15c42c30bd25ceb83b6"}, "eimp": {:hex, :eimp, "1.0.14", "fc297f0c7e2700457a95a60c7010a5f1dcb768a083b6d53f49cd94ab95a28f22", [:rebar3], [{:p1_utils, "1.0.18", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "501133f3112079b92d9e22da8b88bf4f0e13d4d67ae9c15c42c30bd25ceb83b6"},
"elixir_make": {:hex, :elixir_make, "0.7.8", "505026f266552ee5aabca0b9f9c229cbb496c689537c9f922f3eb5431157efc7", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:certifi, "~> 2.0", [hex: :certifi, repo: "hexpm", optional: true]}], "hexpm", "7a71945b913d37ea89b06966e1342c85cfe549b15e6d6d081e8081c493062c07"}, "elixir_make": {:hex, :elixir_make, "0.7.8", "505026f266552ee5aabca0b9f9c229cbb496c689537c9f922f3eb5431157efc7", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:certifi, "~> 2.0", [hex: :certifi, repo: "hexpm", optional: true]}], "hexpm", "7a71945b913d37ea89b06966e1342c85cfe549b15e6d6d081e8081c493062c07"},
"erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"}, "erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"},
@ -73,7 +73,7 @@
"icalendar": {:hex, :icalendar, "1.1.2", "5d0afff5d0143c5bd43f18ae32a777bf0fb9a724543ab05229a460d368f0a5e7", [:mix], [{:timex, "~> 3.4", [hex: :timex, repo: "hexpm", optional: false]}], "hexpm", "2060f8e353fdf3047e95a3f012583dc3c0bbd7ca1010e32ed9e9fc5760ad4292"}, "icalendar": {:hex, :icalendar, "1.1.2", "5d0afff5d0143c5bd43f18ae32a777bf0fb9a724543ab05229a460d368f0a5e7", [:mix], [{:timex, "~> 3.4", [hex: :timex, repo: "hexpm", optional: false]}], "hexpm", "2060f8e353fdf3047e95a3f012583dc3c0bbd7ca1010e32ed9e9fc5760ad4292"},
"idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~>0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"}, "idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~>0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"},
"inet_cidr": {:hex, :inet_cidr, "1.0.8", "d26bb7bdbdf21ae401ead2092bf2bb4bf57fe44a62f5eaa5025280720ace8a40", [:mix], [], "hexpm", "d5b26da66603bb56c933c65214c72152f0de9a6ea53618b56d63302a68f6a90e"}, "inet_cidr": {:hex, :inet_cidr, "1.0.8", "d26bb7bdbdf21ae401ead2092bf2bb4bf57fe44a62f5eaa5025280720ace8a40", [:mix], [], "hexpm", "d5b26da66603bb56c933c65214c72152f0de9a6ea53618b56d63302a68f6a90e"},
"jason": {:hex, :jason, "1.4.1", "af1504e35f629ddcdd6addb3513c3853991f694921b1b9368b0bd32beb9f1b63", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "fbb01ecdfd565b56261302f7e1fcc27c4fb8f32d56eab74db621fc154604a7a1"}, "jason": {:hex, :jason, "1.4.3", "d3f984eeb96fe53b85d20e0b049f03e57d075b5acda3ac8d465c969a2536c17b", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "9a90e868927f7c777689baa16d86f4d0e086d968db5c05d917ccff6d443e58a3"},
"joken": {:hex, :joken, "2.6.0", "b9dd9b6d52e3e6fcb6c65e151ad38bf4bc286382b5b6f97079c47ade6b1bcc6a", [:mix], [{:jose, "~> 1.11.5", [hex: :jose, repo: "hexpm", optional: false]}], "hexpm", "5a95b05a71cd0b54abd35378aeb1d487a23a52c324fa7efdffc512b655b5aaa7"}, "joken": {:hex, :joken, "2.6.0", "b9dd9b6d52e3e6fcb6c65e151ad38bf4bc286382b5b6f97079c47ade6b1bcc6a", [:mix], [{:jose, "~> 1.11.5", [hex: :jose, repo: "hexpm", optional: false]}], "hexpm", "5a95b05a71cd0b54abd35378aeb1d487a23a52c324fa7efdffc512b655b5aaa7"},
"jose": {:hex, :jose, "1.11.6", "613fda82552128aa6fb804682e3a616f4bc15565a048dabd05b1ebd5827ed965", [:mix, :rebar3], [], "hexpm", "6275cb75504f9c1e60eeacb771adfeee4905a9e182103aa59b53fed651ff9738"}, "jose": {:hex, :jose, "1.11.6", "613fda82552128aa6fb804682e3a616f4bc15565a048dabd05b1ebd5827ed965", [:mix, :rebar3], [], "hexpm", "6275cb75504f9c1e60eeacb771adfeee4905a9e182103aa59b53fed651ff9738"},
"jumper": {:hex, :jumper, "1.0.2", "68cdcd84472a00ac596b4e6459a41b3062d4427cbd4f1e8c8793c5b54f1406a7", [:mix], [], "hexpm", "9b7782409021e01ab3c08270e26f36eb62976a38c1aa64b2eaf6348422f165e1"}, "jumper": {:hex, :jumper, "1.0.2", "68cdcd84472a00ac596b4e6459a41b3062d4427cbd4f1e8c8793c5b54f1406a7", [:mix], [], "hexpm", "9b7782409021e01ab3c08270e26f36eb62976a38c1aa64b2eaf6348422f165e1"},
@ -98,7 +98,8 @@
"nodex": {:git, "https://git.pleroma.social/pleroma/nodex", "cb6730f943cfc6aad674c92161be23a8411f15d1", [ref: "cb6730f943cfc6aad674c92161be23a8411f15d1"]}, "nodex": {:git, "https://git.pleroma.social/pleroma/nodex", "cb6730f943cfc6aad674c92161be23a8411f15d1", [ref: "cb6730f943cfc6aad674c92161be23a8411f15d1"]},
"oauth2": {:hex, :oauth2, "0.9.4", "632e8e8826a45e33ac2ea5ac66dcc019ba6bb5a0d2ba77e342d33e3b7b252c6e", [:mix], [{:hackney, "~> 1.7", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "407c6b9f60aa0d01b915e2347dc6be78adca706a37f0c530808942da3b62e7af"}, "oauth2": {:hex, :oauth2, "0.9.4", "632e8e8826a45e33ac2ea5ac66dcc019ba6bb5a0d2ba77e342d33e3b7b252c6e", [:mix], [{:hackney, "~> 1.7", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "407c6b9f60aa0d01b915e2347dc6be78adca706a37f0c530808942da3b62e7af"},
"oauther": {:hex, :oauther, "1.3.0", "82b399607f0ca9d01c640438b34d74ebd9e4acd716508f868e864537ecdb1f76", [:mix], [], "hexpm", "78eb888ea875c72ca27b0864a6f550bc6ee84f2eeca37b093d3d833fbcaec04e"}, "oauther": {:hex, :oauther, "1.3.0", "82b399607f0ca9d01c640438b34d74ebd9e4acd716508f868e864537ecdb1f76", [:mix], [], "hexpm", "78eb888ea875c72ca27b0864a6f550bc6ee84f2eeca37b093d3d833fbcaec04e"},
"oban": {:hex, :oban, "2.17.10", "c3e5bd739b5c3fdc38eba1d43ab270a8c6ca4463bb779b7705c69400b0d87678", [:mix], [{:ecto_sql, "~> 3.10", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:ecto_sqlite3, "~> 0.9", [hex: :ecto_sqlite3, repo: "hexpm", optional: true]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.16", [hex: :postgrex, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "4afd027b8e2bc3c399b54318b4f46ee8c40251fb55a285cb4e38b5363f0ee7c4"}, "oban": {:hex, :oban, "2.17.12", "33fb0cbfb92b910d48dd91a908590fe3698bb85eacec8cd0d9bc6aa13dddd6d6", [:mix], [{:ecto_sql, "~> 3.10", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:ecto_sqlite3, "~> 0.9", [hex: :ecto_sqlite3, repo: "hexpm", optional: true]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.16", [hex: :postgrex, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7a647d6cd6bb300073db17faabce22d80ae135da3baf3180a064fa7c4fa046e3"},
"oban_live_dashboard": {:hex, :oban_live_dashboard, "0.1.1", "8aa4ceaf381c818f7d5c8185cc59942b8ac82ef0cf559881aacf8d3f8ac7bdd3", [:mix], [{:oban, "~> 2.15", [hex: :oban, repo: "hexpm", optional: false]}, {:phoenix_live_dashboard, "~> 0.7", [hex: :phoenix_live_dashboard, repo: "hexpm", optional: false]}], "hexpm", "16dc4ce9c9a95aa2e655e35ed4e675652994a8def61731a18af85e230e1caa63"},
"octo_fetch": {:hex, :octo_fetch, "0.4.0", "074b5ecbc08be10b05b27e9db08bc20a3060142769436242702931c418695b19", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~> 1.1", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm", "cf8be6f40cd519d7000bb4e84adcf661c32e59369ca2827c4e20042eda7a7fc6"}, "octo_fetch": {:hex, :octo_fetch, "0.4.0", "074b5ecbc08be10b05b27e9db08bc20a3060142769436242702931c418695b19", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~> 1.1", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm", "cf8be6f40cd519d7000bb4e84adcf661c32e59369ca2827c4e20042eda7a7fc6"},
"open_api_spex": {:hex, :open_api_spex, "3.18.2", "8c855e83bfe8bf81603d919d6e892541eafece3720f34d1700b58024dadde247", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}, {:poison, "~> 3.0 or ~> 4.0 or ~> 5.0", [hex: :poison, repo: "hexpm", optional: true]}, {:ymlr, "~> 2.0 or ~> 3.0 or ~> 4.0", [hex: :ymlr, repo: "hexpm", optional: true]}], "hexpm", "aa3e6dcfc0ad6a02596b2172662da21c9dd848dac145ea9e603f54e3d81b8d2b"}, "open_api_spex": {:hex, :open_api_spex, "3.18.2", "8c855e83bfe8bf81603d919d6e892541eafece3720f34d1700b58024dadde247", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}, {:poison, "~> 3.0 or ~> 4.0 or ~> 5.0", [hex: :poison, repo: "hexpm", optional: true]}, {:ymlr, "~> 2.0 or ~> 3.0 or ~> 4.0", [hex: :ymlr, repo: "hexpm", optional: true]}], "hexpm", "aa3e6dcfc0ad6a02596b2172662da21c9dd848dac145ea9e603f54e3d81b8d2b"},
"parallel_stream": {:hex, :parallel_stream, "1.0.6", "b967be2b23f0f6787fab7ed681b4c45a215a81481fb62b01a5b750fa8f30f76c", [:mix], [], "hexpm", "639b2e8749e11b87b9eb42f2ad325d161c170b39b288ac8d04c4f31f8f0823eb"}, "parallel_stream": {:hex, :parallel_stream, "1.0.6", "b967be2b23f0f6787fab7ed681b4c45a215a81481fb62b01a5b750fa8f30f76c", [:mix], [], "hexpm", "639b2e8749e11b87b9eb42f2ad325d161c170b39b288ac8d04c4f31f8f0823eb"},

View file

@ -13,6 +13,7 @@ defmodule Pleroma.Web.CommonAPITest do
alias Pleroma.Object alias Pleroma.Object
alias Pleroma.Repo alias Pleroma.Repo
alias Pleroma.Rule alias Pleroma.Rule
alias Pleroma.Tests.ObanHelpers
alias Pleroma.UnstubbedConfigMock, as: ConfigMock alias Pleroma.UnstubbedConfigMock, as: ConfigMock
alias Pleroma.User alias Pleroma.User
alias Pleroma.Web.ActivityPub.ActivityPub alias Pleroma.Web.ActivityPub.ActivityPub
@ -22,7 +23,7 @@ defmodule Pleroma.Web.CommonAPITest do
alias Pleroma.Web.CommonAPI alias Pleroma.Web.CommonAPI
alias Pleroma.Workers.PollWorker alias Pleroma.Workers.PollWorker
import Ecto.Query, only: [from: 2] import Ecto.Query, only: [from: 2, where: 3]
import Mock import Mock
import Mox import Mox
import Pleroma.Factory import Pleroma.Factory
@ -1968,4 +1969,217 @@ test "it does not boost if group is blocking poster", %{poster: poster, group: g
assert [] = announces assert [] = announces
end end
end end
describe "Oban jobs are cancelled" do
setup do
clear_config([:instance, :federating], true)
local_user = insert(:user)
remote_one =
insert(:user, %{
local: false,
nickname: "nick1@domain.com",
ap_id: "https://domain.com/users/nick1",
inbox: "https://domain.com/users/nick1/inbox",
shared_inbox: "https://domain.com/inbox"
})
remote_two =
insert(:user, %{
local: false,
nickname: "nick2@example.com",
ap_id: "https://example.com/users/nick2",
inbox: "https://example.com/users/nick2/inbox",
shared_inbox: "https://example.com/inbox"
})
%{local_user: local_user, remote_one: remote_one, remote_two: remote_two}
end
test "when deleting posts", %{
local_user: local_user,
remote_one: remote_one,
remote_two: remote_two
} do
{:ok, _, _} = Pleroma.User.follow(remote_one, local_user)
{:ok, _, _} = Pleroma.User.follow(remote_two, local_user)
{:ok, %{data: %{"id" => ap_id}} = activity} =
CommonAPI.post(local_user, %{status: "Happy Friday everyone!"})
# Generate the publish_one jobs
ObanHelpers.perform_all()
publish_one_jobs =
all_enqueued()
|> Enum.filter(fn job ->
match?(
%{
state: "available",
queue: "federator_outgoing",
worker: "Pleroma.Workers.PublisherWorker",
args: %{"op" => "publish_one", "params" => %{"id" => ^ap_id}}
},
job
)
end)
assert length(publish_one_jobs) == 2
# The delete should have triggered cancelling the publish_one jobs
assert {:ok, _delete} = CommonAPI.delete(activity.id, local_user)
# all_enqueued/1 will not return cancelled jobs
cancelled_jobs =
Oban.Job
|> where([j], j.worker == "Pleroma.Workers.PublisherWorker")
|> where([j], j.state == "cancelled")
|> where([j], j.args["op"] == "publish_one")
|> where([j], j.args["params"]["id"] == ^ap_id)
|> Pleroma.Repo.all()
assert length(cancelled_jobs) == 2
end
test "when unfavoriting posts", %{
local_user: local_user,
remote_one: remote_user
} do
{:ok, activity} =
CommonAPI.post(remote_user, %{status: "I like turtles!"})
{:ok, %{data: %{"id" => ap_id}} = _favorite} =
CommonAPI.favorite(local_user, activity.id)
# Generate the publish_one jobs
ObanHelpers.perform_all()
publish_one_jobs =
all_enqueued()
|> Enum.filter(fn job ->
match?(
%{
state: "available",
queue: "federator_outgoing",
worker: "Pleroma.Workers.PublisherWorker",
args: %{"op" => "publish_one", "params" => %{"id" => ^ap_id}}
},
job
)
end)
assert length(publish_one_jobs) == 1
# The unfavorite should have triggered cancelling the publish_one jobs
assert {:ok, _unfavorite} = CommonAPI.unfavorite(activity.id, local_user)
# all_enqueued/1 will not return cancelled jobs
cancelled_jobs =
Oban.Job
|> where([j], j.worker == "Pleroma.Workers.PublisherWorker")
|> where([j], j.state == "cancelled")
|> where([j], j.args["op"] == "publish_one")
|> where([j], j.args["params"]["id"] == ^ap_id)
|> Pleroma.Repo.all()
assert length(cancelled_jobs) == 1
end
test "when unboosting posts", %{
local_user: local_user,
remote_one: remote_one,
remote_two: remote_two
} do
{:ok, _, _} = Pleroma.User.follow(remote_one, local_user)
{:ok, _, _} = Pleroma.User.follow(remote_two, local_user)
{:ok, activity} =
CommonAPI.post(remote_one, %{status: "This is an unpleasant post"})
{:ok, %{data: %{"id" => ap_id}} = _repeat} =
CommonAPI.repeat(activity.id, local_user)
# Generate the publish_one jobs
ObanHelpers.perform_all()
publish_one_jobs =
all_enqueued()
|> Enum.filter(fn job ->
match?(
%{
state: "available",
queue: "federator_outgoing",
worker: "Pleroma.Workers.PublisherWorker",
args: %{"op" => "publish_one", "params" => %{"id" => ^ap_id}}
},
job
)
end)
assert length(publish_one_jobs) == 2
# The unrepeat should have triggered cancelling the publish_one jobs
assert {:ok, _unfavorite} = CommonAPI.unrepeat(activity.id, local_user)
# all_enqueued/1 will not return cancelled jobs
cancelled_jobs =
Oban.Job
|> where([j], j.worker == "Pleroma.Workers.PublisherWorker")
|> where([j], j.state == "cancelled")
|> where([j], j.args["op"] == "publish_one")
|> where([j], j.args["params"]["id"] == ^ap_id)
|> Pleroma.Repo.all()
assert length(cancelled_jobs) == 2
end
test "when unreacting to posts", %{
local_user: local_user,
remote_one: remote_one,
remote_two: remote_two
} do
{:ok, _, _} = Pleroma.User.follow(remote_one, local_user)
{:ok, _, _} = Pleroma.User.follow(remote_two, local_user)
{:ok, activity} =
CommonAPI.post(remote_one, %{status: "Gang gang!!!!"})
{:ok, %{data: %{"id" => ap_id}} = _react} =
CommonAPI.react_with_emoji(activity.id, local_user, "👍")
# Generate the publish_one jobs
ObanHelpers.perform_all()
publish_one_jobs =
all_enqueued()
|> Enum.filter(fn job ->
match?(
%{
state: "available",
queue: "federator_outgoing",
worker: "Pleroma.Workers.PublisherWorker",
args: %{"op" => "publish_one", "params" => %{"id" => ^ap_id}}
},
job
)
end)
assert length(publish_one_jobs) == 2
# The unreact should have triggered cancelling the publish_one jobs
assert {:ok, _unreact} = CommonAPI.unreact_with_emoji(activity.id, local_user, "👍")
# all_enqueued/1 will not return cancelled jobs
cancelled_jobs =
Oban.Job
|> where([j], j.worker == "Pleroma.Workers.PublisherWorker")
|> where([j], j.state == "cancelled")
|> where([j], j.args["op"] == "publish_one")
|> where([j], j.args["params"]["id"] == ^ap_id)
|> Pleroma.Repo.all()
assert length(cancelled_jobs) == 2
end
end
end end

View file

@ -8,7 +8,7 @@ defmodule Pleroma.Web.Metadata.UtilsTest do
alias Pleroma.Web.Metadata.Utils alias Pleroma.Web.Metadata.Utils
describe "scrub_html_and_truncate/1" do describe "scrub_html_and_truncate/1" do
test "it returns content text without encode HTML if summary is nil" do test "it returns content text without HTML if summary is nil" do
user = insert(:user) user = insert(:user)
note = note =
@ -17,14 +17,14 @@ test "it returns content text without encode HTML if summary is nil" do
"actor" => user.ap_id, "actor" => user.ap_id,
"id" => "https://pleroma.gov/objects/whatever", "id" => "https://pleroma.gov/objects/whatever",
"summary" => nil, "summary" => nil,
"content" => "Pleroma's really cool!" "content" => "Pleroma's really cool!<br>"
} }
}) })
assert Utils.scrub_html_and_truncate(note) == "Pleroma's really cool!" assert Utils.scrub_html_and_truncate(note) == "Pleroma's really cool!"
end end
test "it returns context text without encode HTML if summary is empty" do test "it returns content text without HTML if summary is empty" do
user = insert(:user) user = insert(:user)
note = note =
@ -33,14 +33,14 @@ test "it returns context text without encode HTML if summary is empty" do
"actor" => user.ap_id, "actor" => user.ap_id,
"id" => "https://pleroma.gov/objects/whatever", "id" => "https://pleroma.gov/objects/whatever",
"summary" => "", "summary" => "",
"content" => "Pleroma's really cool!" "content" => "Pleroma's really cool!<br>"
} }
}) })
assert Utils.scrub_html_and_truncate(note) == "Pleroma's really cool!" assert Utils.scrub_html_and_truncate(note) == "Pleroma's really cool!"
end end
test "it returns summary text without encode HTML if summary is filled" do test "it returns summary text without HTML if summary is filled" do
user = insert(:user) user = insert(:user)
note = note =
@ -48,7 +48,7 @@ test "it returns summary text without encode HTML if summary is filled" do
data: %{ data: %{
"actor" => user.ap_id, "actor" => user.ap_id,
"id" => "https://pleroma.gov/objects/whatever", "id" => "https://pleroma.gov/objects/whatever",
"summary" => "Public service announcement on caffeine consumption", "summary" => "Public service announcement on caffeine consumption<br>",
"content" => "cofe" "content" => "cofe"
} }
}) })
@ -57,6 +57,22 @@ test "it returns summary text without encode HTML if summary is filled" do
"Public service announcement on caffeine consumption" "Public service announcement on caffeine consumption"
end end
test "it returns empty string if summary and content are absent" do
user = insert(:user)
note =
insert(:note, %{
data: %{
"actor" => user.ap_id,
"id" => "https://pleroma.gov/objects/whatever",
"content" => nil,
"summary" => nil
}
})
assert Utils.scrub_html_and_truncate(note) == ""
end
test "it does not return old content after editing" do test "it does not return old content after editing" do
user = insert(:user) user = insert(:user)

View file

@ -20,7 +20,7 @@ test "returns error when no metadata present" do
end end
test "doesn't just add a title" do test "doesn't just add a title" do
assert {:error, {:invalid_metadata, _}} = Parser.parse("https://example.com/non-ogp") assert {:error, :invalid_metadata} = Parser.parse("https://example.com/non-ogp")
end end
test "parses ogp" do test "parses ogp" do
@ -96,7 +96,7 @@ test "rejects invalid OGP data" do
end end
test "returns error if getting page was not successful" do test "returns error if getting page was not successful" do
assert {:error, :overload} = Parser.parse("https://example.com/error") assert {:error, :get} = Parser.parse("https://example.com/error")
end end
test "does a HEAD request to check if the body is too large" do test "does a HEAD request to check if the body is too large" do
@ -104,17 +104,17 @@ test "does a HEAD request to check if the body is too large" do
end end
test "does a HEAD request to check if the body is html" do test "does a HEAD request to check if the body is html" do
assert {:error, {:content_type, _}} = Parser.parse("https://example.com/pdf-file") assert {:error, :content_type} = Parser.parse("https://example.com/pdf-file")
end end
test "refuses to crawl incomplete URLs" do test "refuses to crawl incomplete URLs" do
url = "example.com/ogp" url = "example.com/ogp"
assert :error == Parser.parse(url) assert {:error, :validate} == Parser.parse(url)
end end
test "refuses to crawl malformed URLs" do test "refuses to crawl malformed URLs" do
url = "example.com[]/ogp" url = "example.com[]/ogp"
assert :error == Parser.parse(url) assert {:error, :validate} == Parser.parse(url)
end end
test "refuses to crawl URLs of private network from posts" do test "refuses to crawl URLs of private network from posts" do
@ -126,7 +126,7 @@ test "refuses to crawl URLs of private network from posts" do
"https://pleroma.local/notice/9kCP7V" "https://pleroma.local/notice/9kCP7V"
] ]
|> Enum.each(fn url -> |> Enum.each(fn url ->
assert :error == Parser.parse(url) assert {:error, :validate} == Parser.parse(url)
end) end)
end end

View file

@ -42,7 +42,7 @@ test "error if user was not found" do
user = Pleroma.User.get_by_ap_id(activity.actor) user = Pleroma.User.get_by_ap_id(activity.actor)
Pleroma.Repo.delete(user) Pleroma.Repo.delete(user)
assert {:error, :user_not_found} = assert {:cancel, :user_not_found} =
perform_job(Pleroma.Workers.PurgeExpiredActivity, %{activity_id: activity.id}) perform_job(Pleroma.Workers.PurgeExpiredActivity, %{activity_id: activity.id})
end end
@ -53,7 +53,7 @@ test "error if actiivity was not found" do
expires_at: DateTime.add(DateTime.utc_now(), 3601) expires_at: DateTime.add(DateTime.utc_now(), 3601)
}) })
assert {:error, :activity_not_found} = assert {:cancel, :activity_not_found} =
perform_job(Pleroma.Workers.PurgeExpiredActivity, %{activity_id: "some_if"}) perform_job(Pleroma.Workers.PurgeExpiredActivity, %{activity_id: "some_if"})
end end
end end

View file

@ -1782,7 +1782,7 @@ def post(url, query, body, headers) do
] ]
def head(url, _query, _body, _headers) when url in @rich_media_mocks do def head(url, _query, _body, _headers) when url in @rich_media_mocks do
{:ok, %Tesla.Env{status: 404, body: ""}} {:ok, %Tesla.Env{status: 200, body: ""}}
end end
def head("https://example.com/pdf-file", _, _, _) do def head("https://example.com/pdf-file", _, _, _) do