[#534] Federation reachability filtering tests.

This commit is contained in:
Ivan Tashkinov 2019-01-25 20:38:54 +03:00
parent 060d280e64
commit d99650270b
5 changed files with 243 additions and 64 deletions

View file

@ -193,7 +193,7 @@ def follow_activity_factory do
def websub_subscription_factory do def websub_subscription_factory do
%Pleroma.Web.Websub.WebsubServerSubscription{ %Pleroma.Web.Websub.WebsubServerSubscription{
topic: "http://example.org", topic: "http://example.org",
callback: "http://example/org/callback", callback: "http://example.org/callback",
secret: "here's a secret", secret: "here's a secret",
valid_until: NaiveDateTime.add(NaiveDateTime.utc_now(), 100), valid_until: NaiveDateTime.add(NaiveDateTime.utc_now(), 100),
state: "requested" state: "requested"

View file

@ -6,8 +6,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
use Pleroma.Web.ConnCase use Pleroma.Web.ConnCase
import Pleroma.Factory import Pleroma.Factory
alias Pleroma.Web.ActivityPub.{UserView, ObjectView} alias Pleroma.Web.ActivityPub.{UserView, ObjectView}
alias Pleroma.{Object, Repo, User} alias Pleroma.{Object, Repo, Activity, User, Instances}
alias Pleroma.Activity
setup_all do setup_all do
Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end) Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
@ -144,6 +143,24 @@ test "it inserts an incoming activity into the database", %{conn: conn} do
:timer.sleep(500) :timer.sleep(500)
assert Activity.get_by_ap_id(data["id"]) assert Activity.get_by_ap_id(data["id"])
end end
test "it clears `unreachable` federation status of the sender", %{conn: conn} do
sender_url = "https://pleroma.soykaf.com"
Instances.set_unreachable(sender_url, Instances.reachability_datetime_threshold())
refute Instances.reachable?(sender_url)
data = File.read!("test/fixtures/mastodon-post-activity.json") |> Poison.decode!()
conn =
conn
|> assign(:valid_signature, true)
|> put_req_header("content-type", "application/activity+json")
|> put_req_header("referer", sender_url)
|> post("/inbox", data)
assert "ok" == json_response(conn, 200)
assert Instances.reachable?(sender_url)
end
end end
describe "/users/:nickname/inbox" do describe "/users/:nickname/inbox" do
@ -191,6 +208,29 @@ test "it returns a note activity in a collection", %{conn: conn} do
assert response(conn, 200) =~ note_activity.data["object"]["content"] assert response(conn, 200) =~ note_activity.data["object"]["content"]
end end
test "it clears `unreachable` federation status of the sender", %{conn: conn} do
sender_host = "pleroma.soykaf.com"
Instances.set_unreachable(sender_host, Instances.reachability_datetime_threshold())
refute Instances.reachable?(sender_host)
user = insert(:user)
data =
File.read!("test/fixtures/mastodon-post-activity.json")
|> Poison.decode!()
|> Map.put("bcc", [user.ap_id])
conn =
conn
|> assign(:valid_signature, true)
|> put_req_header("content-type", "application/activity+json")
|> put_req_header("referer", "https://#{sender_host}")
|> post("/users/#{user.nickname}/inbox", data)
assert "ok" == json_response(conn, 200)
assert Instances.reachable?(sender_host)
end
end end
describe "/users/:nickname/outbox" do describe "/users/:nickname/outbox" do

View file

@ -3,8 +3,8 @@
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.FederatorTest do defmodule Pleroma.Web.FederatorTest do
alias Pleroma.Web.Federator alias Pleroma.Web.{CommonAPI, Federator}
alias Pleroma.Web.CommonAPI alias Pleroma.Instances
use Pleroma.DataCase use Pleroma.DataCase
import Pleroma.Factory import Pleroma.Factory
import Mock import Mock
@ -71,6 +71,103 @@ test "with relays deactivated, it does not publish to the relay", %{
end end
end end
describe "Targets reachability filtering in `publish`" do
test_with_mock "it federates only to reachable instances via AP",
Federator,
[:passthrough],
[] do
user = insert(:user)
{inbox1, inbox2} =
{"https://domain.com/users/nick1/inbox", "https://domain2.com/users/nick2/inbox"}
insert(:user, %{
local: false,
nickname: "nick1@domain.com",
ap_id: "https://domain.com/users/nick1",
info: %{ap_enabled: true, source_data: %{"inbox" => inbox1}}
})
insert(:user, %{
local: false,
nickname: "nick2@domain2.com",
ap_id: "https://domain2.com/users/nick2",
info: %{ap_enabled: true, source_data: %{"inbox" => inbox2}}
})
Instances.set_unreachable(
URI.parse(inbox2).host,
Instances.reachability_datetime_threshold()
)
{:ok, _activity} =
CommonAPI.post(user, %{"status" => "HI @nick1@domain.com, @nick2@domain2.com!"})
assert called(Federator.enqueue(:publish_single_ap, %{inbox: inbox1}))
refute called(Federator.enqueue(:publish_single_ap, %{inbox: inbox2}))
end
test_with_mock "it federates only to reachable instances via Websub",
Federator,
[:passthrough],
[] do
user = insert(:user)
websub_topic = Pleroma.Web.OStatus.feed_path(user)
sub1 =
insert(:websub_subscription, %{
topic: websub_topic,
state: "active",
callback: "http://pleroma.soykaf.com/cb"
})
sub2 =
insert(:websub_subscription, %{
topic: websub_topic,
state: "active",
callback: "https://pleroma2.soykaf.com/cb"
})
Instances.set_unreachable(sub1.callback, Instances.reachability_datetime_threshold())
{:ok, _activity} = CommonAPI.post(user, %{"status" => "HI"})
assert called(Federator.enqueue(:publish_single_websub, %{callback: sub2.callback}))
refute called(Federator.enqueue(:publish_single_websub, %{callback: sub1.callback}))
end
test_with_mock "it federates only to reachable instances via Salmon",
Federator,
[:passthrough],
[] do
user = insert(:user)
remote_user1 =
insert(:user, %{
local: false,
nickname: "nick1@domain.com",
ap_id: "https://domain.com/users/nick1",
info: %{salmon: "https://domain.com/salmon"}
})
remote_user2 =
insert(:user, %{
local: false,
nickname: "nick2@domain2.com",
ap_id: "https://domain2.com/users/nick2",
info: %{salmon: "https://domain2.com/salmon"}
})
Instances.set_unreachable("domain.com", Instances.reachability_datetime_threshold())
{:ok, _activity} =
CommonAPI.post(user, %{"status" => "HI @nick1@domain.com, @nick2@domain2.com!"})
assert called(Federator.enqueue(:publish_single_salmon, {remote_user2, :_, :_}))
refute called(Federator.enqueue(:publish_single_websub, {remote_user1, :_, :_}))
end
end
describe "Receive an activity" do describe "Receive an activity" do
test "successfully processes incoming AP docs with correct origin" do test "successfully processes incoming AP docs with correct origin" do
params = %{ params = %{

View file

@ -5,7 +5,7 @@
defmodule Pleroma.Web.OStatus.OStatusControllerTest do defmodule Pleroma.Web.OStatus.OStatusControllerTest do
use Pleroma.Web.ConnCase use Pleroma.Web.ConnCase
import Pleroma.Factory import Pleroma.Factory
alias Pleroma.{User, Repo, Object} alias Pleroma.{User, Repo, Object, Instances}
alias Pleroma.Web.CommonAPI alias Pleroma.Web.CommonAPI
alias Pleroma.Web.OStatus.ActivityRepresenter alias Pleroma.Web.OStatus.ActivityRepresenter
@ -14,49 +14,69 @@ defmodule Pleroma.Web.OStatus.OStatusControllerTest do
:ok :ok
end end
test "decodes a salmon", %{conn: conn} do describe "salmon_incoming" do
user = insert(:user) test "decodes a salmon", %{conn: conn} do
salmon = File.read!("test/fixtures/salmon.xml") user = insert(:user)
salmon = File.read!("test/fixtures/salmon.xml")
conn = conn =
conn conn
|> put_req_header("content-type", "application/atom+xml") |> put_req_header("content-type", "application/atom+xml")
|> post("/users/#{user.nickname}/salmon", salmon) |> post("/users/#{user.nickname}/salmon", salmon)
assert response(conn, 200) assert response(conn, 200)
end end
test "decodes a salmon with a changed magic key", %{conn: conn} do test "decodes a salmon with a changed magic key", %{conn: conn} do
user = insert(:user) user = insert(:user)
salmon = File.read!("test/fixtures/salmon.xml") salmon = File.read!("test/fixtures/salmon.xml")
conn = conn =
conn conn
|> put_req_header("content-type", "application/atom+xml") |> put_req_header("content-type", "application/atom+xml")
|> post("/users/#{user.nickname}/salmon", salmon) |> post("/users/#{user.nickname}/salmon", salmon)
assert response(conn, 200) assert response(conn, 200)
# Set a wrong magic-key for a user so it has to refetch # Set a wrong magic-key for a user so it has to refetch
salmon_user = User.get_by_ap_id("http://gs.example.org:4040/index.php/user/1") salmon_user = User.get_by_ap_id("http://gs.example.org:4040/index.php/user/1")
# Wrong key # Wrong key
info_cng = info_cng =
User.Info.remote_user_creation(salmon_user.info, %{ User.Info.remote_user_creation(salmon_user.info, %{
magic_key: magic_key:
"RSA.pu0s-halox4tu7wmES1FVSx6u-4wc0YrUFXcqWXZG4-27UmbCOpMQftRCldNRfyA-qLbz-eqiwrong1EwUvjsD4cYbAHNGHwTvDOyx5AKthQUP44ykPv7kjKGh3DWKySJvcs9tlUG87hlo7AvnMo9pwRS_Zz2CacQ-MKaXyDepk=.AQAB" "RSA.pu0s-halox4tu7wmES1FVSx6u-4wc0YrUFXcqWXZG4-27UmbCOpMQftRCldNRfyA-qLbz-eqiwrong1EwUvjsD4cYbAHNGHwTvDOyx5AKthQUP44ykPv7kjKGh3DWKySJvcs9tlUG87hlo7AvnMo9pwRS_Zz2CacQ-MKaXyDepk=.AQAB"
}) })
salmon_user salmon_user
|> Ecto.Changeset.change() |> Ecto.Changeset.change()
|> Ecto.Changeset.put_embed(:info, info_cng) |> Ecto.Changeset.put_embed(:info, info_cng)
|> Repo.update() |> Repo.update()
conn = conn =
build_conn() build_conn()
|> put_req_header("content-type", "application/atom+xml") |> put_req_header("content-type", "application/atom+xml")
|> post("/users/#{user.nickname}/salmon", salmon) |> post("/users/#{user.nickname}/salmon", salmon)
assert response(conn, 200) assert response(conn, 200)
end
test "it clears `unreachable` federation status of the sender", %{conn: conn} do
sender_url = "https://pleroma.soykaf.com"
Instances.set_unreachable(sender_url, Instances.reachability_datetime_threshold())
refute Instances.reachable?(sender_url)
user = insert(:user)
salmon = File.read!("test/fixtures/salmon.xml")
conn =
conn
|> put_req_header("content-type", "application/atom+xml")
|> put_req_header("referer", sender_url)
|> post("/users/#{user.nickname}/salmon", salmon)
assert response(conn, 200)
assert Instances.reachable?(sender_url)
end
end end
test "gets a feed", %{conn: conn} do test "gets a feed", %{conn: conn} do

View file

@ -6,7 +6,7 @@ defmodule Pleroma.Web.Websub.WebsubControllerTest do
use Pleroma.Web.ConnCase use Pleroma.Web.ConnCase
import Pleroma.Factory import Pleroma.Factory
alias Pleroma.Web.Websub.WebsubClientSubscription alias Pleroma.Web.Websub.WebsubClientSubscription
alias Pleroma.{Repo, Activity} alias Pleroma.{Repo, Activity, Instances}
alias Pleroma.Web.Websub alias Pleroma.Web.Websub
test "websub subscription request", %{conn: conn} do test "websub subscription request", %{conn: conn} do
@ -50,35 +50,57 @@ test "websub subscription confirmation", %{conn: conn} do
assert_in_delta NaiveDateTime.diff(websub.valid_until, NaiveDateTime.utc_now()), 100, 5 assert_in_delta NaiveDateTime.diff(websub.valid_until, NaiveDateTime.utc_now()), 100, 5
end end
test "handles incoming feed updates", %{conn: conn} do describe "websub_incoming" do
websub = insert(:websub_client_subscription) test "handles incoming feed updates", %{conn: conn} do
doc = "some stuff" websub = insert(:websub_client_subscription)
signature = Websub.sign(websub.secret, doc) doc = "some stuff"
signature = Websub.sign(websub.secret, doc)
conn = conn =
conn conn
|> put_req_header("x-hub-signature", "sha1=" <> signature) |> put_req_header("x-hub-signature", "sha1=" <> signature)
|> put_req_header("content-type", "application/atom+xml") |> put_req_header("content-type", "application/atom+xml")
|> post("/push/subscriptions/#{websub.id}", doc) |> post("/push/subscriptions/#{websub.id}", doc)
assert response(conn, 200) == "OK" assert response(conn, 200) == "OK"
assert length(Repo.all(Activity)) == 1 assert length(Repo.all(Activity)) == 1
end end
test "rejects incoming feed updates with the wrong signature", %{conn: conn} do test "rejects incoming feed updates with the wrong signature", %{conn: conn} do
websub = insert(:websub_client_subscription) websub = insert(:websub_client_subscription)
doc = "some stuff" doc = "some stuff"
signature = Websub.sign("wrong secret", doc) signature = Websub.sign("wrong secret", doc)
conn = conn =
conn conn
|> put_req_header("x-hub-signature", "sha1=" <> signature) |> put_req_header("x-hub-signature", "sha1=" <> signature)
|> put_req_header("content-type", "application/atom+xml") |> put_req_header("content-type", "application/atom+xml")
|> post("/push/subscriptions/#{websub.id}", doc) |> post("/push/subscriptions/#{websub.id}", doc)
assert response(conn, 500) == "Error" assert response(conn, 500) == "Error"
assert length(Repo.all(Activity)) == 0 assert length(Repo.all(Activity)) == 0
end
test "it clears `unreachable` federation status of the sender", %{conn: conn} do
sender_url = "https://pleroma.soykaf.com"
Instances.set_unreachable(sender_url, Instances.reachability_datetime_threshold())
refute Instances.reachable?(sender_url)
websub = insert(:websub_client_subscription)
doc = "some stuff"
signature = Websub.sign(websub.secret, doc)
conn =
conn
|> put_req_header("x-hub-signature", "sha1=" <> signature)
|> put_req_header("content-type", "application/atom+xml")
|> put_req_header("referer", sender_url)
|> post("/push/subscriptions/#{websub.id}", doc)
assert response(conn, 200) == "OK"
assert Instances.reachable?(sender_url)
end
end end
end end