Various event AP converter changes and add tests
Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
parent
caf9493a00
commit
ecf7bb1fef
|
@ -37,6 +37,7 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Event do
|
||||||
|
|
||||||
@online_address_name "Website"
|
@online_address_name "Website"
|
||||||
@banner_picture_name "Banner"
|
@banner_picture_name "Banner"
|
||||||
|
@ap_public "https://www.w3.org/ns/activitystreams#Public"
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Converts an AP object data to our internal data structure.
|
Converts an AP object data to our internal data structure.
|
||||||
|
@ -92,15 +93,15 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Event do
|
||||||
@impl Converter
|
@impl Converter
|
||||||
@spec model_to_as(EventModel.t()) :: map
|
@spec model_to_as(EventModel.t()) :: map
|
||||||
def model_to_as(%EventModel{} = event) do
|
def model_to_as(%EventModel{} = event) do
|
||||||
to =
|
{to, cc} =
|
||||||
if event.visibility == :public,
|
if event.visibility == :public,
|
||||||
do: ["https://www.w3.org/ns/activitystreams#Public"],
|
do: {[@ap_public], []},
|
||||||
else: [attributed_to_or_default(event).followers_url]
|
else: {[attributed_to_or_default(event).followers_url], [@ap_public]}
|
||||||
|
|
||||||
%{
|
%{
|
||||||
"type" => "Event",
|
"type" => "Event",
|
||||||
"to" => to,
|
"to" => to,
|
||||||
"cc" => [],
|
"cc" => cc,
|
||||||
"attributedTo" => attributed_to_or_default(event).url,
|
"attributedTo" => attributed_to_or_default(event).url,
|
||||||
"name" => event.title,
|
"name" => event.title,
|
||||||
"actor" =>
|
"actor" =>
|
||||||
|
|
|
@ -88,6 +88,8 @@ defmodule Mobilizon.Events do
|
||||||
:media
|
:media
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@participant_preloads [:event, :actor]
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Gets a single event.
|
Gets a single event.
|
||||||
"""
|
"""
|
||||||
|
@ -307,8 +309,9 @@ defmodule Mobilizon.Events do
|
||||||
"""
|
"""
|
||||||
@spec update_event(Event.t(), map) :: {:ok, Event.t()} | {:error, Changeset.t()}
|
@spec update_event(Event.t(), map) :: {:ok, Event.t()} | {:error, Changeset.t()}
|
||||||
def update_event(%Event{draft: old_draft} = old_event, attrs) do
|
def update_event(%Event{draft: old_draft} = old_event, attrs) do
|
||||||
with %Changeset{changes: changes} = changeset <-
|
with %Event{} = old_event <- Repo.preload(old_event, @event_preloads),
|
||||||
Event.update_changeset(Repo.preload(old_event, [:tags, :media]), attrs),
|
%Changeset{changes: changes} = changeset <-
|
||||||
|
Event.update_changeset(old_event, attrs),
|
||||||
{:ok, %{update: %Event{} = new_event}} <-
|
{:ok, %{update: %Event{} = new_event}} <-
|
||||||
Multi.new()
|
Multi.new()
|
||||||
|> Multi.update(:update, changeset)
|
|> Multi.update(:update, changeset)
|
||||||
|
@ -329,7 +332,8 @@ defmodule Mobilizon.Events do
|
||||||
err -> err
|
err -> err
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|> Repo.transaction() do
|
|> Repo.transaction(),
|
||||||
|
%Event{} = new_event <- Repo.preload(new_event, @event_preloads, force: true) do
|
||||||
Cachex.del(:ics, "event_#{new_event.uuid}")
|
Cachex.del(:ics, "event_#{new_event.uuid}")
|
||||||
|
|
||||||
Email.Event.calculate_event_diff_and_send_notifications(
|
Email.Event.calculate_event_diff_and_send_notifications(
|
||||||
|
@ -341,7 +345,7 @@ defmodule Mobilizon.Events do
|
||||||
unless new_event.draft,
|
unless new_event.draft,
|
||||||
do: Workers.BuildSearch.enqueue(:update_search_event, %{"event_id" => new_event.id})
|
do: Workers.BuildSearch.enqueue(:update_search_event, %{"event_id" => new_event.id})
|
||||||
|
|
||||||
{:ok, Repo.preload(new_event, @event_preloads)}
|
{:ok, new_event}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -728,7 +732,7 @@ defmodule Mobilizon.Events do
|
||||||
def get_participant(participant_id) do
|
def get_participant(participant_id) do
|
||||||
Participant
|
Participant
|
||||||
|> where([p], p.id == ^participant_id)
|
|> where([p], p.id == ^participant_id)
|
||||||
|> preload([p], [:event, :actor])
|
|> preload([p], ^@participant_preloads)
|
||||||
|> Repo.one()
|
|> Repo.one()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -744,6 +748,7 @@ defmodule Mobilizon.Events do
|
||||||
case Participant
|
case Participant
|
||||||
|> where([p], event_id: ^event_id, actor_id: ^actor_id)
|
|> where([p], event_id: ^event_id, actor_id: ^actor_id)
|
||||||
|> where([p], fragment("? ->>'email' = ?", p.metadata, ^email))
|
|> where([p], fragment("? ->>'email' = ?", p.metadata, ^email))
|
||||||
|
|> preload([p], ^@participant_preloads)
|
||||||
|> Repo.one() do
|
|> Repo.one() do
|
||||||
%Participant{} = participant ->
|
%Participant{} = participant ->
|
||||||
{:ok, participant}
|
{:ok, participant}
|
||||||
|
@ -758,6 +763,7 @@ defmodule Mobilizon.Events do
|
||||||
case Participant
|
case Participant
|
||||||
|> where([p], event_id: ^event_id, actor_id: ^actor_id)
|
|> where([p], event_id: ^event_id, actor_id: ^actor_id)
|
||||||
|> where([p], fragment("? ->>'cancellation_token' = ?", p.metadata, ^cancellation_token))
|
|> where([p], fragment("? ->>'cancellation_token' = ?", p.metadata, ^cancellation_token))
|
||||||
|
|> preload([p], ^@participant_preloads)
|
||||||
|> Repo.one() do
|
|> Repo.one() do
|
||||||
%Participant{} = participant ->
|
%Participant{} = participant ->
|
||||||
{:ok, participant}
|
{:ok, participant}
|
||||||
|
@ -768,7 +774,9 @@ defmodule Mobilizon.Events do
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_participant(event_id, actor_id, %{}) do
|
def get_participant(event_id, actor_id, %{}) do
|
||||||
case Repo.get_by(Participant, event_id: event_id, actor_id: actor_id) do
|
case Participant
|
||||||
|
|> Repo.get_by(event_id: event_id, actor_id: actor_id)
|
||||||
|
|> Repo.preload(@participant_preloads) do
|
||||||
%Participant{} = participant ->
|
%Participant{} = participant ->
|
||||||
{:ok, participant}
|
{:ok, participant}
|
||||||
|
|
||||||
|
@ -781,7 +789,7 @@ defmodule Mobilizon.Events do
|
||||||
def get_participant_by_confirmation_token(confirmation_token) do
|
def get_participant_by_confirmation_token(confirmation_token) do
|
||||||
Participant
|
Participant
|
||||||
|> where([p], fragment("? ->>'confirmation_token' = ?", p.metadata, ^confirmation_token))
|
|> where([p], fragment("? ->>'confirmation_token' = ?", p.metadata, ^confirmation_token))
|
||||||
|> preload([p], [:actor, :event])
|
|> preload([p], ^@participant_preloads)
|
||||||
|> Repo.one()
|
|> Repo.one()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
270
test/federation/activity_pub/types/events_test.exs
Normal file
270
test/federation/activity_pub/types/events_test.exs
Normal file
|
@ -0,0 +1,270 @@
|
||||||
|
defmodule Mobilizon.Federation.ActivityPub.Types.EventsTest do
|
||||||
|
use Mobilizon.DataCase
|
||||||
|
|
||||||
|
import Mobilizon.Factory
|
||||||
|
|
||||||
|
alias Mobilizon.Actors.Actor
|
||||||
|
alias Mobilizon.Events
|
||||||
|
alias Mobilizon.Events.Event
|
||||||
|
alias Mobilizon.Federation.ActivityPub.Types.Events
|
||||||
|
|
||||||
|
@ap_public "https://www.w3.org/ns/activitystreams#Public"
|
||||||
|
|
||||||
|
describe "test event creation" do
|
||||||
|
@event_begins_on "2021-07-28T15:04:22Z"
|
||||||
|
@event_title "hey"
|
||||||
|
@event_data %{title: @event_title, begins_on: @event_begins_on}
|
||||||
|
|
||||||
|
test "from a simple profile" do
|
||||||
|
%Actor{id: organizer_actor_id, url: actor_url, followers_url: followers_url} =
|
||||||
|
insert(:actor)
|
||||||
|
|
||||||
|
assert {:ok, %Event{}, data} =
|
||||||
|
Events.create(
|
||||||
|
Map.merge(@event_data, %{organizer_actor_id: organizer_actor_id}),
|
||||||
|
%{}
|
||||||
|
)
|
||||||
|
|
||||||
|
assert match?(
|
||||||
|
%{
|
||||||
|
"actor" => ^actor_url,
|
||||||
|
"attributedTo" => ^actor_url,
|
||||||
|
"cc" => [^followers_url],
|
||||||
|
"object" => %{
|
||||||
|
"actor" => ^actor_url,
|
||||||
|
"anonymousParticipationEnabled" => false,
|
||||||
|
"attachment" => [],
|
||||||
|
"attributedTo" => ^actor_url,
|
||||||
|
"category" => nil,
|
||||||
|
"cc" => [],
|
||||||
|
"commentsEnabled" => false,
|
||||||
|
"content" => nil,
|
||||||
|
"draft" => false,
|
||||||
|
"endTime" => nil,
|
||||||
|
"ical:status" => "CONFIRMED",
|
||||||
|
"joinMode" => "free",
|
||||||
|
"maximumAttendeeCapacity" => nil,
|
||||||
|
"mediaType" => "text/html",
|
||||||
|
"name" => @event_title,
|
||||||
|
"repliesModerationOption" => nil,
|
||||||
|
"startTime" => @event_begins_on,
|
||||||
|
"tag" => [],
|
||||||
|
"to" => [@ap_public],
|
||||||
|
"type" => "Event"
|
||||||
|
},
|
||||||
|
"to" => [@ap_public],
|
||||||
|
"type" => "Create"
|
||||||
|
},
|
||||||
|
data
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "an unlisted event" do
|
||||||
|
%Actor{id: organizer_actor_id, url: actor_url, followers_url: followers_url} =
|
||||||
|
insert(:actor)
|
||||||
|
|
||||||
|
assert {:ok, %Event{}, data} =
|
||||||
|
Events.create(
|
||||||
|
Map.merge(@event_data, %{
|
||||||
|
organizer_actor_id: organizer_actor_id,
|
||||||
|
visibility: :unlisted
|
||||||
|
}),
|
||||||
|
%{}
|
||||||
|
)
|
||||||
|
|
||||||
|
assert match?(
|
||||||
|
%{
|
||||||
|
"actor" => ^actor_url,
|
||||||
|
"attributedTo" => ^actor_url,
|
||||||
|
"cc" => [@ap_public],
|
||||||
|
"object" => %{
|
||||||
|
"actor" => ^actor_url,
|
||||||
|
"anonymousParticipationEnabled" => false,
|
||||||
|
"attachment" => [],
|
||||||
|
"attributedTo" => ^actor_url,
|
||||||
|
"category" => nil,
|
||||||
|
"cc" => [@ap_public],
|
||||||
|
"commentsEnabled" => false,
|
||||||
|
"content" => nil,
|
||||||
|
"draft" => false,
|
||||||
|
"endTime" => nil,
|
||||||
|
"ical:status" => "CONFIRMED",
|
||||||
|
"joinMode" => "free",
|
||||||
|
"maximumAttendeeCapacity" => nil,
|
||||||
|
"mediaType" => "text/html",
|
||||||
|
"name" => @event_title,
|
||||||
|
"repliesModerationOption" => nil,
|
||||||
|
"startTime" => @event_begins_on,
|
||||||
|
"tag" => [],
|
||||||
|
"to" => [^followers_url],
|
||||||
|
"type" => "Event"
|
||||||
|
},
|
||||||
|
"to" => [^followers_url],
|
||||||
|
"type" => "Create"
|
||||||
|
},
|
||||||
|
data
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "from a group member" do
|
||||||
|
%Actor{id: organizer_actor_id, url: actor_url} = actor = insert(:actor)
|
||||||
|
|
||||||
|
%Actor{
|
||||||
|
id: attributed_to_id,
|
||||||
|
url: group_url,
|
||||||
|
followers_url: followers_url,
|
||||||
|
members_url: members_url
|
||||||
|
} = group = insert(:group, domain: "somewhere.else", url: "https://somewhere.else/@someone")
|
||||||
|
|
||||||
|
insert(:member, parent: group, actor: actor, role: :moderator)
|
||||||
|
|
||||||
|
assert {:ok, %Event{}, data} =
|
||||||
|
Events.create(
|
||||||
|
Map.merge(@event_data, %{
|
||||||
|
organizer_actor_id: organizer_actor_id,
|
||||||
|
attributed_to_id: attributed_to_id
|
||||||
|
}),
|
||||||
|
%{}
|
||||||
|
)
|
||||||
|
|
||||||
|
assert match?(
|
||||||
|
%{
|
||||||
|
"actor" => ^actor_url,
|
||||||
|
"attributedTo" => ^group_url,
|
||||||
|
"cc" => [^members_url, ^followers_url],
|
||||||
|
"object" => %{
|
||||||
|
"actor" => ^actor_url,
|
||||||
|
"anonymousParticipationEnabled" => false,
|
||||||
|
"attachment" => [],
|
||||||
|
"attributedTo" => ^group_url,
|
||||||
|
"category" => nil,
|
||||||
|
"cc" => [],
|
||||||
|
"commentsEnabled" => false,
|
||||||
|
"content" => nil,
|
||||||
|
"draft" => false,
|
||||||
|
"endTime" => nil,
|
||||||
|
"ical:status" => "CONFIRMED",
|
||||||
|
"joinMode" => "free",
|
||||||
|
"maximumAttendeeCapacity" => nil,
|
||||||
|
"mediaType" => "text/html",
|
||||||
|
"name" => @event_title,
|
||||||
|
"repliesModerationOption" => nil,
|
||||||
|
"startTime" => @event_begins_on,
|
||||||
|
"tag" => [],
|
||||||
|
"to" => [@ap_public],
|
||||||
|
"type" => "Event"
|
||||||
|
},
|
||||||
|
"to" => [@ap_public],
|
||||||
|
"type" => "Create"
|
||||||
|
},
|
||||||
|
data
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
@event_updated_title "my event updated"
|
||||||
|
@event_update_data %{title: @event_updated_title}
|
||||||
|
|
||||||
|
describe "test event update" do
|
||||||
|
test "from a simple profile" do
|
||||||
|
%Actor{url: actor_url, followers_url: followers_url} = actor = insert(:actor)
|
||||||
|
|
||||||
|
{:ok, begins_on, _} = DateTime.from_iso8601(@event_begins_on)
|
||||||
|
%Event{} = event = insert(:event, organizer_actor: actor, begins_on: begins_on)
|
||||||
|
|
||||||
|
assert {:ok, %Event{}, data} =
|
||||||
|
Events.update(
|
||||||
|
event,
|
||||||
|
@event_update_data,
|
||||||
|
%{}
|
||||||
|
)
|
||||||
|
|
||||||
|
assert match?(
|
||||||
|
%{
|
||||||
|
"actor" => ^actor_url,
|
||||||
|
"attributedTo" => ^actor_url,
|
||||||
|
"cc" => [^followers_url],
|
||||||
|
"object" => %{
|
||||||
|
"actor" => ^actor_url,
|
||||||
|
"anonymousParticipationEnabled" => false,
|
||||||
|
"attributedTo" => ^actor_url,
|
||||||
|
"cc" => [],
|
||||||
|
"commentsEnabled" => false,
|
||||||
|
"draft" => false,
|
||||||
|
"ical:status" => "CONFIRMED",
|
||||||
|
"joinMode" => "free",
|
||||||
|
"maximumAttendeeCapacity" => nil,
|
||||||
|
"mediaType" => "text/html",
|
||||||
|
"name" => @event_updated_title,
|
||||||
|
"repliesModerationOption" => nil,
|
||||||
|
"startTime" => @event_begins_on,
|
||||||
|
"tag" => [],
|
||||||
|
"to" => [@ap_public],
|
||||||
|
"type" => "Event"
|
||||||
|
},
|
||||||
|
"to" => [@ap_public],
|
||||||
|
"type" => "Update"
|
||||||
|
},
|
||||||
|
data
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "from a group member" do
|
||||||
|
%Actor{} = actor_1 = insert(:actor)
|
||||||
|
%Actor{id: organizer_actor_2_id, url: actor_2_url} = actor_2 = insert(:actor)
|
||||||
|
|
||||||
|
%Actor{
|
||||||
|
url: group_url,
|
||||||
|
followers_url: followers_url,
|
||||||
|
members_url: members_url
|
||||||
|
} = group = insert(:group, domain: "somewhere.else", url: "https://somewhere.else/@someone")
|
||||||
|
|
||||||
|
insert(:member, parent: group, actor: actor_1, role: :moderator)
|
||||||
|
insert(:member, parent: group, actor: actor_2, role: :moderator)
|
||||||
|
|
||||||
|
{:ok, begins_on, _} = DateTime.from_iso8601(@event_begins_on)
|
||||||
|
|
||||||
|
%Event{} =
|
||||||
|
event =
|
||||||
|
insert(:event, organizer_actor: actor_1, begins_on: begins_on, attributed_to: group)
|
||||||
|
|
||||||
|
assert {:ok, %Event{}, data} =
|
||||||
|
Events.update(
|
||||||
|
event,
|
||||||
|
Map.merge(@event_update_data, %{
|
||||||
|
organizer_actor_id: organizer_actor_2_id
|
||||||
|
}),
|
||||||
|
%{}
|
||||||
|
)
|
||||||
|
|
||||||
|
assert match?(
|
||||||
|
%{
|
||||||
|
"actor" => ^actor_2_url,
|
||||||
|
"attributedTo" => ^group_url,
|
||||||
|
"cc" => [^members_url, ^followers_url],
|
||||||
|
"object" => %{
|
||||||
|
"actor" => ^actor_2_url,
|
||||||
|
"anonymousParticipationEnabled" => false,
|
||||||
|
"attributedTo" => ^group_url,
|
||||||
|
"cc" => [],
|
||||||
|
"commentsEnabled" => false,
|
||||||
|
"draft" => false,
|
||||||
|
"ical:status" => "CONFIRMED",
|
||||||
|
"joinMode" => "free",
|
||||||
|
"maximumAttendeeCapacity" => nil,
|
||||||
|
"mediaType" => "text/html",
|
||||||
|
"name" => @event_updated_title,
|
||||||
|
"repliesModerationOption" => nil,
|
||||||
|
"startTime" => @event_begins_on,
|
||||||
|
"tag" => [],
|
||||||
|
"to" => [@ap_public],
|
||||||
|
"type" => "Event"
|
||||||
|
},
|
||||||
|
"to" => [@ap_public],
|
||||||
|
"type" => "Update"
|
||||||
|
},
|
||||||
|
data
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in a new issue