From cf9b8d5f46631d442734fd8b23915ef144c8a281 Mon Sep 17 00:00:00 2001 From: Thomas Citharel Date: Wed, 14 Oct 2020 09:45:58 +0200 Subject: [PATCH] Fix events from former followed instances showing up Signed-off-by: Thomas Citharel --- lib/mobilizon/events/events.ex | 15 +++++--- test/mobilizon/events/events_test.exs | 51 ++++++++++++++++++++++++--- test/support/factory.ex | 22 ++++++++++++ 3 files changed, 78 insertions(+), 10 deletions(-) diff --git a/lib/mobilizon/events/events.ex b/lib/mobilizon/events/events.ex index 9810acfad..bb94c67e6 100644 --- a/lib/mobilizon/events/events.ex +++ b/lib/mobilizon/events/events.ex @@ -1643,12 +1643,17 @@ defmodule Mobilizon.Events do where(query, [q], q.local == true) end - @spec filter_local_or_from_followed_instances_events(Ecto.Query.t()) :: Ecto.Query.t() + @spec filter_local_or_from_followed_instances_events(Ecto.Query.t()) :: + Ecto.Query.t() defp filter_local_or_from_followed_instances_events(query) do - from(q in query, - left_join: s in Share, - on: s.uri == q.url, - where: q.local == true or not is_nil(s.uri) + follower_actor_id = Mobilizon.Config.relay_actor_id() + + query + |> join(:left, [q], s in Share, on: s.uri == q.url) + |> join(:left, [_q, ..., s], f in Follower, on: f.target_actor_id == s.actor_id) + |> where( + [q, ..., s, f], + q.local == true or (f.actor_id == ^follower_actor_id and not is_nil(s.uri)) ) end diff --git a/test/mobilizon/events/events_test.exs b/test/mobilizon/events/events_test.exs index 99c808c10..0ae99b403 100644 --- a/test/mobilizon/events/events_test.exs +++ b/test/mobilizon/events/events_test.exs @@ -6,6 +6,7 @@ defmodule Mobilizon.EventsTest do alias Mobilizon.Actors.Actor alias Mobilizon.Events alias Mobilizon.Events.{Event, Participant, Session, Tag, TagRelation, Track} + alias Mobilizon.Federation.ActivityPub.Relay alias Mobilizon.Service.Workers alias Mobilizon.Storage.Page @@ -19,10 +20,54 @@ defmodule Mobilizon.EventsTest do category: "meeting" } + describe "list_events/5" do + setup do + actor = insert(:actor) + event = insert(:event, organizer_actor: actor, visibility: :public, local: true) + Mobilizon.Config.clear_config_cache() + {:ok, actor: actor, event: event} + end + + test "list_events/0 returns all events", %{event: event} do + assert event.title == hd(Events.list_events()).title + end + + test "list_events/5 returns events from other instances if we follow them", + %{event: _event} do + events = Events.list_events() + assert length(events) == 1 + + %Actor{id: remote_instance_actor_id} = remote_instance_actor = insert(:instance_actor) + %Actor{id: remote_actor_id} = insert(:actor, domain: "somedomain.tld", user: nil) + %Event{url: remote_event_url} = insert(:event, local: false, title: "My Remote event") + Mobilizon.Share.create(remote_event_url, remote_instance_actor_id, remote_actor_id) + + %Actor{} = own_instance_actor = Relay.get_actor() + + insert(:follower, target_actor: remote_instance_actor, actor: own_instance_actor) + + events = Events.list_events() + assert length(events) == 2 + assert events |> Enum.any?(fn event -> event.title == "My Remote event" end) + end + + test "list_events/5 doesn't return events from other instances if we don't follow them anymore", + %{event: _event} do + %Actor{id: remote_instance_actor_id} = insert(:instance_actor) + %Actor{id: remote_actor_id} = insert(:actor, domain: "somedomain.tld", user: nil) + %Event{url: remote_event_url} = insert(:event, local: false, title: "My Remote event") + Mobilizon.Share.create(remote_event_url, remote_instance_actor_id, remote_actor_id) + + events = Events.list_events() + assert length(events) == 1 + assert events |> Enum.all?(fn event -> event.title != "My Remote event" end) + end + end + describe "events" do setup do actor = insert(:actor) - event = insert(:event, organizer_actor: actor, visibility: :public) + event = insert(:event, organizer_actor: actor, visibility: :public, local: true) Workers.BuildSearch.insert_search_event(event) {:ok, actor: actor, event: event} end @@ -41,10 +86,6 @@ defmodule Mobilizon.EventsTest do } @invalid_attrs %{begins_on: nil, description: nil, ends_on: nil, title: nil} - test "list_events/0 returns all events", %{event: event} do - assert event.title == hd(Events.list_events()).title - end - test "get_event!/1 returns the event with given id", %{event: event} do assert Events.get_event!(event.id).title == event.title refute Ecto.assoc_loaded?(Events.get_event!(event.id).organizer_actor) diff --git a/test/support/factory.ex b/test/support/factory.ex index 9ca5544c2..882bae017 100644 --- a/test/support/factory.ex +++ b/test/support/factory.ex @@ -78,6 +78,28 @@ defmodule Mobilizon.Factory do ) end + def instance_actor_factory do + preferred_username = "relay" + domain = "#{sequence("mydomain")}.com" + + struct!( + actor_factory(), + %{ + preferred_username: preferred_username, + type: :Application, + url: "http://#{domain}/#{preferred_username}", + followers_url: Actor.build_url(preferred_username, :followers), + following_url: Actor.build_url(preferred_username, :following), + members_url: Actor.build_url(preferred_username, :members), + resources_url: Actor.build_url(preferred_username, :resources), + inbox_url: Actor.build_url(preferred_username, :inbox), + outbox_url: Actor.build_url(preferred_username, :outbox), + user: nil, + domain: domain + } + ) + end + def follower_factory do uuid = Ecto.UUID.generate()