defmodule Mobilizon.Federation.ActivityPub.Transmogrifier.JoinTest do use Mobilizon.DataCase import Mobilizon.Factory import ExUnit.CaptureLog alias Mobilizon.Actors.Actor alias Mobilizon.Events alias Mobilizon.Events.{Event, Participant} alias Mobilizon.Federation.ActivityPub alias Mobilizon.Federation.ActivityPub.{Actions, Transmogrifier} describe "handle incoming join activities" do @join_message "I want to get in!" test "it accepts Join activities" do %Actor{url: organizer_url} = organizer = insert(:actor) %Actor{url: participant_url} = _participant = insert(:actor) %Event{url: event_url} = _event = insert(:event, organizer_actor: organizer) join_data = File.read!("test/fixtures/mobilizon-join-activity.json") |> Jason.decode!() |> Map.put("actor", participant_url) |> Map.put("object", event_url) |> Map.put("participationMessage", @join_message) assert {:ok, activity, %Participant{} = participant} = Transmogrifier.handle_incoming(join_data) assert participant.metadata.message == @join_message assert participant.role == :participant assert activity.data["type"] == "Accept" assert activity.data["object"]["object"] == event_url assert activity.data["object"]["id"] =~ "/join/event/" assert activity.data["object"]["type"] =~ "Join" assert activity.data["object"]["participationMessage"] == @join_message assert activity.data["actor"] == organizer_url assert activity.data["id"] =~ "/accept/join/" end end describe "handle incoming accept join activities" do test "it accepts Accept activities for Join activities" do %Actor{url: organizer_url} = organizer = insert(:actor) %Actor{} = participant_actor = insert(:actor) %Event{} = event = insert(:event, organizer_actor: organizer, join_options: :restricted) {:ok, join_activity, participation} = Actions.Join.join(event, participant_actor, false, %{ metadata: %{role: :not_approved} }) accept_data = File.read!("test/fixtures/mastodon-accept-activity.json") |> Jason.decode!() |> Map.put("actor", organizer_url) |> Map.put("object", participation.url) {:ok, accept_activity, _} = Transmogrifier.handle_incoming(accept_data) assert accept_activity.data["object"]["id"] == join_activity.data["id"] assert accept_activity.data["object"]["id"] =~ "/join/" assert accept_activity.data["id"] =~ "/accept/join/" # We don't accept already accepted Accept activities :error = Transmogrifier.handle_incoming(accept_data) end test "it accepts Accept activities with an inline Join from same origin" do %Actor{} = organizer = insert(:actor) %Actor{url: participant_actor_url} = insert(:actor, domain: "somewhere.else", url: "https://somewhere.else/@participant") %Actor{} = group = insert(:group, domain: "somewhere.else", url: "https://somewhere.else/@group") insert(:member, actor: organizer, parent: group, role: :moderator) %Actor{} = actor_member_2 = insert(:actor, domain: "somewhere.else", url: "https://somewhere.else/@member") insert(:member, actor: actor_member_2, parent: group, role: :moderator) %Event{url: event_url} = insert(:event, organizer_actor: organizer, join_options: :restricted, attributed_to: group) join_data = File.read!("test/fixtures/mobilizon-join-activity.json") |> Jason.decode!() |> Map.put("actor", participant_actor_url) |> Map.put("object", event_url) |> Map.put("participationMessage", @join_message) |> Map.put("id", "https://somewhere.else/@participant/join/event/1") accept_data = File.read!("test/fixtures/mastodon-accept-activity.json") |> Jason.decode!() |> Map.put("actor", actor_member_2.url) |> Map.put("object", join_data) {:ok, accept_activity, _} = Transmogrifier.handle_incoming(accept_data) assert accept_activity.data["object"]["id"] == join_data["id"] assert accept_activity.data["object"]["id"] =~ "/join/" assert accept_activity.data["id"] =~ "/accept/join/" end end describe "handle incoming reject join activities" do test "it accepts Reject activities for Join activities" do %Actor{url: organizer_url} = organizer = insert(:actor) %Actor{} = participant_actor = insert(:actor) %Event{} = event = insert(:event, organizer_actor: organizer, join_options: :restricted) {:ok, join_activity, participation} = Actions.Join.join(event, participant_actor) reject_data = File.read!("test/fixtures/mastodon-reject-activity.json") |> Jason.decode!() |> Map.put("actor", organizer_url) |> Map.put("object", participation.url) {:ok, reject_activity, _} = Transmogrifier.handle_incoming(reject_data) assert reject_activity.data["object"]["id"] == join_activity.data["id"] assert reject_activity.data["object"]["id"] =~ "/join/" assert reject_activity.data["id"] =~ "/reject/join/" # We don't accept already rejected Reject activities assert capture_log([level: :warn], fn -> assert :error == Transmogrifier.handle_incoming(reject_data) end) =~ "Tried to handle an Reject activity on a Join activity with a event object but the participant is already rejected" # Organiser is not present since we use factories directly assert event.id |> Events.list_participants_for_event() |> Map.get(:elements) |> Enum.map(& &1.role) == [:rejected] end end end