- Follow/Block/Mute imports now spin off into *n* tasks to avoid the oban timeout
- Transient activities recieved from remote servers are no longer persisted in the database
- Overhauled static-fe view for logged-out users
+- Blocked instances will now not be sent _any_ requests, even fetch ones that would get rejected by MRF anyhow
## Removed
- FollowBotPolicy
# Note: will create a Create activity, which we need internally at the moment.
def fetch_object_from_id(id, options \\ []) do
- with {_, nil} <- {:fetch_object, Object.get_cached_by_ap_id(id)},
+ with %URI{} = uri <- URI.parse(id),
+ # If we have instance restrictions, apply them here to prevent fetching from unwanted instances
+ {:ok, nil} <- Pleroma.Web.ActivityPub.MRF.SimplePolicy.check_reject(uri),
+ {:ok, _} <- Pleroma.Web.ActivityPub.MRF.SimplePolicy.check_accept(uri),
+ {_, nil} <- {:fetch_object, Object.get_cached_by_ap_id(id)},
{_, true} <- {:allowed_depth, Federator.allowed_thread_distance?(options[:depth])},
{_, {:ok, data}} <- {:fetch, fetch_and_contain_remote_object_from_id(id)},
{_, nil} <- {:normalize, Object.normalize(data, fetch: false)},
{:fetch, {:error, error}} ->
{:error, error}
+ {:reject, reason} ->
+ {:reject, reason}
+
e ->
e
end
{:ok, user}
e ->
- Logger.error("Could not fetch user, #{inspect(e)}")
+ Logger.error("Could not fetch user #{ap_id}, #{inspect(e)}")
{:error, :not_found}
end
end
{:ok, maybe_update_follow_information(data)}
else
# If this has been deleted, only log a debug and not an error
- {:error, {"Object has been deleted" = e, _, _}} ->
+ {:error, {"Object has been deleted", _, _} = e} ->
Logger.debug("Could not decode user at fetch #{ap_id}, #{inspect(e)}")
{:error, e}
require Pleroma.Constants
- defp check_accept(%{host: actor_host} = _actor_info) do
+ def check_accept(%{host: actor_host} = _actor_info) do
accepts =
instance_list(:accept)
|> MRF.subdomains_regex()
end
end
- defp check_reject(%{host: actor_host} = _actor_info) do
+ def check_reject(%{host: actor_host} = _actor_info) do
rejects =
instance_list(:reject)
|> MRF.subdomains_regex()
|> Map.drop(["conversation", "inReplyToAtomUri"])
else
e ->
- Logger.warn("Couldn't fetch #{inspect(in_reply_to_id)}, error: #{inspect(e)}")
+ Logger.warn("Couldn't fetch reply@#{inspect(in_reply_to_id)}, error: #{inspect(e)}")
object
end
else
|> Map.put("quoteUri", quoted_object.data["id"])
else
e ->
- Logger.warn("Couldn't fetch #{inspect(quote_url)}, error: #{inspect(e)}")
+ Logger.warn("Couldn't fetch quote@#{inspect(quote_url)}, error: #{inspect(e)}")
object
end
else
Map.put(data, "object", external_url)
else
{:fetch, e} ->
- Logger.error("Couldn't fetch #{object} #{inspect(e)}")
+ Logger.error("Couldn't fetch fixed_object@#{object} #{inspect(e)}")
data
_ ->
)
end
+ test "does not fetch anything from a rejected instance" do
+ clear_config([:mrf_simple, :reject], [{"evil.example.org", "i said so"}])
+
+ assert {:reject, _} =
+ Fetcher.fetch_object_from_id("http://evil.example.org/@admin/99541947525187367")
+ end
+
+ test "does not fetch anything if mrf_simple accept is on" do
+ clear_config([:mrf_simple, :accept], [{"mastodon.example.org", "i said so"}])
+ clear_config([:mrf_simple, :reject], [])
+
+ assert {:reject, _} =
+ Fetcher.fetch_object_from_id(
+ "http://notlisted.example.org/@admin/99541947525187367"
+ )
+
+ assert {:ok, _object} =
+ Fetcher.fetch_object_from_id(
+ "http://mastodon.example.org/@admin/99541947525187367"
+ )
+ end
+
test "it resets instance reachability on successful fetch" do
id = "http://mastodon.example.org/@admin/99541947525187367"
Instances.set_consistently_unreachable(id)