2020-07-09 17:24:28 +02:00
|
|
|
defmodule Mobilizon.Federation.ActivityPub.Transmogrifier.FollowTest do
|
|
|
|
use Mobilizon.DataCase
|
2021-11-13 18:45:01 +01:00
|
|
|
import Mox
|
2021-01-22 19:44:37 +01:00
|
|
|
import ExUnit.CaptureLog
|
2020-07-09 17:24:28 +02:00
|
|
|
import Mobilizon.Factory
|
|
|
|
alias Mobilizon.Actors
|
2021-01-20 18:16:44 +01:00
|
|
|
alias Mobilizon.Actors.Follower
|
2022-05-03 12:58:07 +02:00
|
|
|
alias Mobilizon.Federation.ActivityPub.{Actions, Activity, Relay, Transmogrifier}
|
2021-11-13 18:45:01 +01:00
|
|
|
alias Mobilizon.Service.HTTP.ActivityPub.Mock
|
2022-05-03 12:58:07 +02:00
|
|
|
alias Mobilizon.Users.User
|
|
|
|
|
|
|
|
import Swoosh.TestAssertions
|
2020-07-09 17:24:28 +02:00
|
|
|
|
2021-01-20 18:16:44 +01:00
|
|
|
describe "handle incoming follow requests" do
|
2021-01-22 19:44:37 +01:00
|
|
|
test "it works only for groups" do
|
2021-01-20 18:16:44 +01:00
|
|
|
actor = insert(:actor)
|
|
|
|
|
2021-11-13 18:45:01 +01:00
|
|
|
actor_data =
|
|
|
|
File.read!("test/fixtures/mastodon-actor.json")
|
|
|
|
|> Jason.decode!()
|
|
|
|
|
|
|
|
Mock
|
|
|
|
|> expect(:call, fn
|
|
|
|
%{method: :get, url: "https://social.tcit.fr/users/tcit"}, _opts ->
|
|
|
|
{:ok,
|
|
|
|
%Tesla.Env{
|
|
|
|
status: 200,
|
|
|
|
body: Map.put(actor_data, "id", "https://social.tcit.fr/users/tcit")
|
|
|
|
}}
|
|
|
|
end)
|
|
|
|
|
2021-01-22 19:44:37 +01:00
|
|
|
data =
|
|
|
|
File.read!("test/fixtures/mastodon-follow-activity.json")
|
|
|
|
|> Jason.decode!()
|
|
|
|
|> Map.put("object", actor.url)
|
|
|
|
|
|
|
|
assert capture_log(fn ->
|
|
|
|
:error = Transmogrifier.handle_incoming(data)
|
|
|
|
end) =~ "Only group and instances can be followed"
|
|
|
|
|
|
|
|
actor = Actors.get_actor_with_preload(actor.id)
|
2021-12-29 14:59:33 +01:00
|
|
|
refute Actors.check_follow(Actors.get_actor_by_url!(data["actor"], true), actor)
|
2021-01-22 19:44:37 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
test "it works for incoming follow requests" do
|
|
|
|
actor = insert(:group)
|
|
|
|
|
2021-11-13 18:45:01 +01:00
|
|
|
actor_data =
|
|
|
|
File.read!("test/fixtures/mastodon-actor.json")
|
|
|
|
|> Jason.decode!()
|
|
|
|
|
|
|
|
Mock
|
2024-08-20 21:43:41 +02:00
|
|
|
|> expect(:call, 2, fn
|
2021-11-13 18:45:01 +01:00
|
|
|
%{method: :get, url: "https://social.tcit.fr/users/tcit"}, _opts ->
|
|
|
|
{:ok,
|
|
|
|
%Tesla.Env{
|
|
|
|
status: 200,
|
|
|
|
body: Map.put(actor_data, "id", "https://social.tcit.fr/users/tcit")
|
|
|
|
}}
|
2024-08-20 21:43:41 +02:00
|
|
|
|
|
|
|
%{method: :post, url: "https://framapiaf.org/inbox"} = args, _opts ->
|
|
|
|
{:ok, args}
|
2021-11-13 18:45:01 +01:00
|
|
|
end)
|
|
|
|
|
2021-01-20 18:16:44 +01:00
|
|
|
data =
|
|
|
|
File.read!("test/fixtures/mastodon-follow-activity.json")
|
|
|
|
|> Jason.decode!()
|
|
|
|
|> Map.put("object", actor.url)
|
|
|
|
|
|
|
|
{:ok, %Activity{data: data, local: false}, _} = Transmogrifier.handle_incoming(data)
|
|
|
|
|
|
|
|
assert data["actor"] == "https://social.tcit.fr/users/tcit"
|
|
|
|
assert data["type"] == "Follow"
|
|
|
|
assert data["id"] == "https://social.tcit.fr/users/tcit#follows/2"
|
|
|
|
|
|
|
|
actor = Actors.get_actor_with_preload(actor.id)
|
2021-12-29 14:59:33 +01:00
|
|
|
assert Actors.check_follow(Actors.get_actor_by_url!(data["actor"], true), actor)
|
2021-01-20 18:16:44 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
test "it rejects activities without a valid ID" do
|
2021-01-22 19:44:37 +01:00
|
|
|
actor = insert(:group)
|
2021-01-20 18:16:44 +01:00
|
|
|
|
|
|
|
data =
|
|
|
|
File.read!("test/fixtures/mastodon-follow-activity.json")
|
|
|
|
|> Jason.decode!()
|
|
|
|
|> Map.put("object", actor.url)
|
|
|
|
|> Map.put("id", "")
|
|
|
|
|
|
|
|
:error = Transmogrifier.handle_incoming(data)
|
|
|
|
end
|
|
|
|
|
|
|
|
# test "it works for incoming follow requests from hubzilla" do
|
|
|
|
# user = insert(:user)
|
|
|
|
|
|
|
|
# data =
|
|
|
|
# File.read!("test/fixtures/hubzilla-follow-activity.json")
|
|
|
|
# |> Jason.decode!()
|
|
|
|
# |> Map.put("object", user.ap_id)
|
|
|
|
# |> Utils.normalize_params()
|
|
|
|
|
|
|
|
# {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
|
|
|
|
|
|
|
|
# assert data["actor"] == "https://hubzilla.example.org/channel/kaniini"
|
|
|
|
# assert data["type"] == "Follow"
|
|
|
|
# assert data["id"] == "https://hubzilla.example.org/channel/kaniini#follows/2"
|
2021-12-29 14:59:33 +01:00
|
|
|
# assert User.check_follow(User.get_by_ap_id(data["actor"]), user)
|
2021-01-20 18:16:44 +01:00
|
|
|
# end
|
2022-05-03 12:58:07 +02:00
|
|
|
|
|
|
|
test "it works for accepting instance follow from user" do
|
|
|
|
%User{} = insert(:user, email: "loulou@example.com", role: :administrator)
|
|
|
|
relay = Relay.get_actor()
|
|
|
|
|
|
|
|
actor_data =
|
|
|
|
File.read!("test/fixtures/mastodon-actor.json")
|
|
|
|
|> Jason.decode!()
|
|
|
|
|
|
|
|
Mock
|
|
|
|
|> expect(:call, fn
|
|
|
|
%{method: :get, url: "https://social.tcit.fr/users/tcit"}, _opts ->
|
|
|
|
{:ok,
|
|
|
|
%Tesla.Env{
|
|
|
|
status: 200,
|
|
|
|
body: Map.put(actor_data, "id", "https://social.tcit.fr/users/tcit")
|
|
|
|
}}
|
|
|
|
end)
|
|
|
|
|
|
|
|
data =
|
|
|
|
File.read!("test/fixtures/mastodon-follow-activity.json")
|
|
|
|
|> Jason.decode!()
|
|
|
|
|> Map.put("object", relay.url)
|
|
|
|
|
|
|
|
{:ok, %Activity{data: data, local: false}, _} = Transmogrifier.handle_incoming(data)
|
|
|
|
|
|
|
|
assert data["actor"] == "https://social.tcit.fr/users/tcit"
|
|
|
|
assert data["type"] == "Follow"
|
|
|
|
assert data["id"] == "https://social.tcit.fr/users/tcit#follows/2"
|
|
|
|
|
|
|
|
follow = Actors.check_follow(Actors.get_actor_by_url!(data["actor"], true), relay)
|
|
|
|
assert follow
|
|
|
|
refute follow.approved
|
|
|
|
|
|
|
|
refute_email_sent()
|
|
|
|
end
|
|
|
|
|
|
|
|
test "it works for accepting instance follow from other instance" do
|
|
|
|
%User{email: admin_email} = insert(:user, email: "loulou@example.com", role: :administrator)
|
|
|
|
relay = Relay.get_actor()
|
|
|
|
|
|
|
|
actor_data =
|
|
|
|
File.read!("test/fixtures/mastodon-actor.json")
|
|
|
|
|> Jason.decode!()
|
|
|
|
|
|
|
|
Mock
|
|
|
|
|> expect(:call, fn
|
|
|
|
%{method: :get, url: "https://mobilizon.fr/relay"}, _opts ->
|
|
|
|
{:ok,
|
|
|
|
%Tesla.Env{
|
|
|
|
status: 200,
|
|
|
|
body:
|
|
|
|
actor_data
|
|
|
|
|> Map.put("id", "https://mobilizon.fr/relay")
|
|
|
|
|> Map.put("type", "Application")
|
|
|
|
}}
|
|
|
|
end)
|
|
|
|
|
|
|
|
data =
|
|
|
|
File.read!("test/fixtures/mastodon-follow-activity.json")
|
|
|
|
|> Jason.decode!()
|
|
|
|
|> Map.put("actor", "https://mobilizon.fr/relay")
|
|
|
|
|> Map.put("id", "https://mobilizon.fr/relay#follows/2")
|
|
|
|
|> Map.put("object", relay.url)
|
|
|
|
|
|
|
|
{:ok, %Activity{data: data, local: false}, _} = Transmogrifier.handle_incoming(data)
|
|
|
|
|
|
|
|
assert data["actor"] == "https://mobilizon.fr/relay"
|
|
|
|
assert data["type"] == "Follow"
|
|
|
|
assert data["id"] == "https://mobilizon.fr/relay#follows/2"
|
|
|
|
|
|
|
|
follow = Actors.check_follow(Actors.get_actor_by_url!(data["actor"], true), relay)
|
|
|
|
assert follow
|
|
|
|
refute follow.approved
|
|
|
|
|
|
|
|
assert_email_sent(to: admin_email)
|
|
|
|
end
|
2021-01-20 18:16:44 +01:00
|
|
|
end
|
|
|
|
|
2020-07-09 17:24:28 +02:00
|
|
|
describe "handle incoming follow accept activities" do
|
2021-01-20 18:16:44 +01:00
|
|
|
test "it works for incoming accepts" do
|
|
|
|
follower = insert(:actor)
|
2021-01-22 19:44:37 +01:00
|
|
|
followed = insert(:group, manually_approves_followers: false)
|
2021-01-20 18:16:44 +01:00
|
|
|
|
2021-12-29 14:59:33 +01:00
|
|
|
refute Actors.check_follow(follower, followed)
|
2021-01-20 18:16:44 +01:00
|
|
|
|
2021-09-28 19:40:37 +02:00
|
|
|
{:ok, follow_activity, _} = Actions.Follow.follow(follower, followed)
|
2021-12-29 14:59:33 +01:00
|
|
|
assert Actors.check_follow(follower, followed)
|
2021-01-20 18:16:44 +01:00
|
|
|
|
|
|
|
follow_object_id = follow_activity.data["id"]
|
|
|
|
|
|
|
|
assert %Follower{} = Actors.get_follower_by_url(follow_object_id)
|
|
|
|
|
|
|
|
accept_data =
|
|
|
|
File.read!("test/fixtures/mastodon-accept-activity.json")
|
|
|
|
|> Jason.decode!()
|
|
|
|
|> Map.put("actor", followed.url)
|
|
|
|
|
|
|
|
object =
|
|
|
|
accept_data["object"]
|
|
|
|
|> Map.put("actor", follower.url)
|
|
|
|
|> Map.put("id", follow_object_id)
|
|
|
|
|
|
|
|
accept_data = Map.put(accept_data, "object", object)
|
|
|
|
|
|
|
|
:error = Transmogrifier.handle_incoming(accept_data)
|
|
|
|
|
|
|
|
{:ok, follower} = Actors.get_actor_by_url(follower.url)
|
|
|
|
|
2021-12-29 14:59:33 +01:00
|
|
|
assert Actors.check_follow(follower, followed)
|
2021-01-20 18:16:44 +01:00
|
|
|
end
|
|
|
|
|
2020-07-09 17:24:28 +02:00
|
|
|
test "it works for incoming accepts which were pre-accepted" do
|
|
|
|
follower = insert(:actor)
|
2021-01-22 19:44:37 +01:00
|
|
|
followed = insert(:group, manually_approves_followers: true)
|
2020-07-09 17:24:28 +02:00
|
|
|
|
2021-12-29 14:59:33 +01:00
|
|
|
refute Actors.check_follow(follower, followed)
|
2020-07-09 17:24:28 +02:00
|
|
|
|
2021-09-28 19:40:37 +02:00
|
|
|
{:ok, follow_activity, _} = Actions.Follow.follow(follower, followed)
|
2021-12-29 14:59:33 +01:00
|
|
|
assert Actors.check_follow(follower, followed)
|
2020-07-09 17:24:28 +02:00
|
|
|
|
2021-01-20 18:16:44 +01:00
|
|
|
follow_object_id = follow_activity.data["id"]
|
|
|
|
|
|
|
|
assert %Follower{} = Actors.get_follower_by_url(follow_object_id)
|
|
|
|
|
2020-07-09 17:24:28 +02:00
|
|
|
accept_data =
|
|
|
|
File.read!("test/fixtures/mastodon-accept-activity.json")
|
|
|
|
|> Jason.decode!()
|
|
|
|
|> Map.put("actor", followed.url)
|
|
|
|
|
|
|
|
object =
|
|
|
|
accept_data["object"]
|
|
|
|
|> Map.put("actor", follower.url)
|
2021-01-20 18:16:44 +01:00
|
|
|
|> Map.put("id", follow_object_id)
|
2020-07-09 17:24:28 +02:00
|
|
|
|
|
|
|
accept_data = Map.put(accept_data, "object", object)
|
|
|
|
|
|
|
|
{:ok, activity, _} = Transmogrifier.handle_incoming(accept_data)
|
|
|
|
refute activity.local
|
|
|
|
|
|
|
|
assert activity.data["object"]["id"] == follow_activity.data["id"]
|
|
|
|
|
|
|
|
{:ok, follower} = Actors.get_actor_by_url(follower.url)
|
|
|
|
|
2021-12-29 14:59:33 +01:00
|
|
|
assert Actors.check_follow(follower, followed)
|
2020-07-09 17:24:28 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
test "it works for incoming accepts which are referenced by IRI only" do
|
|
|
|
follower = insert(:actor)
|
2021-01-22 19:44:37 +01:00
|
|
|
followed = insert(:group, manually_approves_followers: true)
|
2020-07-09 17:24:28 +02:00
|
|
|
|
2021-09-28 19:40:37 +02:00
|
|
|
{:ok, follow_activity, _} = Actions.Follow.follow(follower, followed)
|
2020-07-09 17:24:28 +02:00
|
|
|
|
|
|
|
accept_data =
|
|
|
|
File.read!("test/fixtures/mastodon-accept-activity.json")
|
|
|
|
|> Jason.decode!()
|
|
|
|
|> Map.put("actor", followed.url)
|
|
|
|
|> Map.put("object", follow_activity.data["id"])
|
|
|
|
|
|
|
|
{:ok, activity, _} = Transmogrifier.handle_incoming(accept_data)
|
|
|
|
assert activity.data["object"]["id"] == follow_activity.data["id"]
|
|
|
|
assert activity.data["object"]["id"] =~ "/follow/"
|
|
|
|
assert activity.data["id"] =~ "/accept/follow/"
|
|
|
|
|
|
|
|
{:ok, follower} = Actors.get_actor_by_url(follower.url)
|
|
|
|
|
2021-12-29 14:59:33 +01:00
|
|
|
assert Actors.check_follow(follower, followed)
|
2020-07-09 17:24:28 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
test "it fails for incoming accepts which cannot be correlated" do
|
|
|
|
follower = insert(:actor)
|
2021-01-22 19:44:37 +01:00
|
|
|
followed = insert(:group)
|
2020-07-09 17:24:28 +02:00
|
|
|
|
|
|
|
accept_data =
|
|
|
|
File.read!("test/fixtures/mastodon-accept-activity.json")
|
|
|
|
|> Jason.decode!()
|
|
|
|
|> Map.put("actor", followed.url)
|
|
|
|
|
|
|
|
accept_data =
|
|
|
|
Map.put(accept_data, "object", Map.put(accept_data["object"], "actor", follower.url))
|
|
|
|
|
|
|
|
:error = Transmogrifier.handle_incoming(accept_data)
|
|
|
|
|
|
|
|
{:ok, follower} = Actors.get_actor_by_url(follower.url)
|
|
|
|
|
2021-12-29 14:59:33 +01:00
|
|
|
refute Actors.check_follow(follower, followed)
|
2020-07-09 17:24:28 +02:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "handle incoming follow reject activities" do
|
|
|
|
test "it fails for incoming rejects which cannot be correlated" do
|
|
|
|
follower = insert(:actor)
|
2021-01-22 19:44:37 +01:00
|
|
|
followed = insert(:group)
|
2020-07-09 17:24:28 +02:00
|
|
|
|
|
|
|
accept_data =
|
|
|
|
File.read!("test/fixtures/mastodon-reject-activity.json")
|
|
|
|
|> Jason.decode!()
|
|
|
|
|> Map.put("actor", followed.url)
|
|
|
|
|
|
|
|
accept_data =
|
|
|
|
Map.put(accept_data, "object", Map.put(accept_data["object"], "actor", follower.url))
|
|
|
|
|
|
|
|
:error = Transmogrifier.handle_incoming(accept_data)
|
|
|
|
|
|
|
|
{:ok, follower} = Actors.get_actor_by_url(follower.url)
|
|
|
|
|
2021-12-29 14:59:33 +01:00
|
|
|
refute Actors.check_follow(follower, followed)
|
2020-07-09 17:24:28 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
test "it works for incoming rejects which are referenced by IRI only" do
|
|
|
|
follower = insert(:actor)
|
2021-01-22 19:44:37 +01:00
|
|
|
followed = insert(:group)
|
2020-07-09 17:24:28 +02:00
|
|
|
|
2021-09-28 19:40:37 +02:00
|
|
|
{:ok, follow_activity, _} = Actions.Follow.follow(follower, followed)
|
2020-07-09 17:24:28 +02:00
|
|
|
|
2021-12-29 14:59:33 +01:00
|
|
|
assert Actors.check_follow(follower, followed)
|
2020-07-09 17:24:28 +02:00
|
|
|
|
|
|
|
reject_data =
|
|
|
|
File.read!("test/fixtures/mastodon-reject-activity.json")
|
|
|
|
|> Jason.decode!()
|
|
|
|
|> Map.put("actor", followed.url)
|
|
|
|
|> Map.put("object", follow_activity.data["id"])
|
|
|
|
|
|
|
|
{:ok, %Activity{data: _}, _} = Transmogrifier.handle_incoming(reject_data)
|
|
|
|
|
2021-12-29 14:59:33 +01:00
|
|
|
refute Actors.check_follow(follower, followed)
|
2020-07-09 17:24:28 +02:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|