fix(backend): only send announcement event emails when the comment author has the right to do so

Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
Thomas Citharel
2024-01-09 14:49:11 +01:00
parent aa388a7a47
commit 0bd00de501
2 changed files with 197 additions and 14 deletions

View File

@@ -2,7 +2,7 @@ defmodule Mobilizon.Service.Activity.Conversation do
@moduledoc """ @moduledoc """
Insert a conversation activity Insert a conversation activity
""" """
alias Mobilizon.Conversations alias Mobilizon.{Actors, Conversations}
alias Mobilizon.Conversations.{Conversation, ConversationParticipant} alias Mobilizon.Conversations.{Conversation, ConversationParticipant}
alias Mobilizon.Discussions.Comment alias Mobilizon.Discussions.Comment
alias Mobilizon.Events.Event alias Mobilizon.Events.Event
@@ -38,7 +38,7 @@ defmodule Mobilizon.Service.Activity.Conversation do
%Conversation{ %Conversation{
id: conversation_id id: conversation_id
} = conversation, } = conversation,
%Comment{actor_id: actor_id, text: last_comment_text}, %Comment{actor_id: actor_id, text: last_comment_text} = comment,
_options _options
) )
when subject in [ when subject in [
@@ -55,7 +55,8 @@ defmodule Mobilizon.Service.Activity.Conversation do
actor_id: conversation_participant_actor_id actor_id: conversation_participant_actor_id
} = } =
conversation_participant -> conversation_participant ->
if actor_id != conversation_participant_actor_id do if actor_id != conversation_participant_actor_id and
can_send_event_announcement?(conversation, comment) do
LegacyNotifierBuilder.enqueue( LegacyNotifierBuilder.enqueue(
:legacy_notify, :legacy_notify,
%{ %{
@@ -98,4 +99,31 @@ defmodule Mobilizon.Service.Activity.Conversation do
} }
defp event_subject_params(_), do: %{} defp event_subject_params(_), do: %{}
@spec can_send_event_announcement?(Conversation.t(), Comment.t()) :: boolean()
defp can_send_event_announcement?(
%Conversation{
event: %Event{
attributed_to_id: attributed_to_id
}
},
%Comment{actor_id: actor_id}
)
when not is_nil(attributed_to_id) do
attributed_to_id == actor_id or Actors.member?(actor_id, attributed_to_id)
end
defp can_send_event_announcement?(
%Conversation{
event: %Event{
organizer_actor_id: organizer_actor_id
}
},
%Comment{actor_id: actor_id}
)
when not is_nil(organizer_actor_id) do
organizer_actor_id == actor_id
end
defp can_send_event_announcement?(_, _), do: false
end end

View File

@@ -7,6 +7,7 @@ defmodule Mobilizon.Service.Activity.ConversationTest do
alias Mobilizon.Conversations alias Mobilizon.Conversations
alias Mobilizon.Conversations.{Conversation, ConversationParticipant} alias Mobilizon.Conversations.{Conversation, ConversationParticipant}
alias Mobilizon.Discussions.Comment alias Mobilizon.Discussions.Comment
alias Mobilizon.Events.Event
alias Mobilizon.Service.Activity.Conversation, as: ConversationActivity alias Mobilizon.Service.Activity.Conversation, as: ConversationActivity
alias Mobilizon.Service.Workers.LegacyNotifierBuilder alias Mobilizon.Service.Workers.LegacyNotifierBuilder
alias Mobilizon.Users.User alias Mobilizon.Users.User
@@ -15,16 +16,93 @@ defmodule Mobilizon.Service.Activity.ConversationTest do
use Oban.Testing, repo: Mobilizon.Storage.Repo use Oban.Testing, repo: Mobilizon.Storage.Repo
import Mobilizon.Factory import Mobilizon.Factory
describe "handle conversation" do describe "handle activity from event private announcement conversation" do
test "with participants" do test "when conversation initial comment author is not an organizer" do
%User{} = user = insert(:user) %User{} = user = insert(:user)
%Actor{id: actor_id} = actor = insert(:actor, user: user) %Actor{id: actor_id} = actor = insert(:actor, user: user)
%Conversation{ %Actor{} = organizer_actor = insert(:actor)
id: conversation_id,
last_comment: %Comment{actor_id: last_comment_actor_id} %Event{} = event = insert(:event)
} =
conversation = insert(:conversation, event: nil) %Comment{} = comment = insert(:comment, actor: organizer_actor)
%Conversation{id: conversation_id} =
conversation =
insert(:conversation, event: event, last_comment: comment, origin_comment: comment)
%ConversationParticipant{id: conversation_participant_actor_id} =
insert(:conversation_participant, actor: actor, conversation: conversation)
%ConversationParticipant{
id: conversation_participant_id,
actor: %Actor{id: conversation_other_participant_actor_id}
} = insert(:conversation_participant, conversation: conversation)
conversation = Conversations.get_conversation(conversation_id)
assert {:ok, _} =
ConversationActivity.insert_activity(conversation, subject: "conversation_created")
refute_enqueued(
worker: LegacyNotifierBuilder,
args: %{
"author_id" => organizer_actor.id,
"participant" => %{"actor_id" => actor_id, "id" => conversation_participant_actor_id},
"object_id" => to_string(conversation_id),
"object_type" => "conversation",
"op" => "legacy_notify",
"subject" => "conversation_created",
"subject_params" => %{
"conversation_id" => conversation_id,
"conversation_participant_id" => conversation_participant_actor_id,
"conversation_event_id" => event.id,
"conversation_event_title" => event.title,
"conversation_event_uuid" => event.uuid
},
"type" => "conversation"
}
)
refute_enqueued(
worker: LegacyNotifierBuilder,
args: %{
"author_id" => organizer_actor.id,
"participant" => %{
"actor_id" => conversation_other_participant_actor_id,
"id" => conversation_participant_id
},
"object_id" => to_string(conversation_id),
"object_type" => "conversation",
"op" => "legacy_notify",
"subject" => "conversation_created",
"subject_params" => %{
"conversation_id" => conversation_id,
"conversation_participant_id" => conversation_participant_id,
"conversation_event_id" => event.id,
"conversation_event_title" => event.title,
"conversation_event_uuid" => event.uuid
},
"type" => "conversation"
}
)
assert [] = all_enqueued()
end
test "an author who is the event organizer" do
%User{} = user = insert(:user)
%Actor{id: actor_id} = actor = insert(:actor, user: user)
%Actor{} = organizer_actor = insert(:actor)
%Event{} = event = insert(:event, organizer_actor: organizer_actor)
%Comment{} = comment = insert(:comment, actor: organizer_actor)
%Conversation{id: conversation_id} =
conversation =
insert(:conversation, event: event, last_comment: comment, origin_comment: comment)
%ConversationParticipant{id: conversation_participant_actor_id} = %ConversationParticipant{id: conversation_participant_actor_id} =
insert(:conversation_participant, actor: actor, conversation: conversation) insert(:conversation_participant, actor: actor, conversation: conversation)
@@ -42,7 +120,7 @@ defmodule Mobilizon.Service.Activity.ConversationTest do
assert_enqueued( assert_enqueued(
worker: LegacyNotifierBuilder, worker: LegacyNotifierBuilder,
args: %{ args: %{
"author_id" => last_comment_actor_id, "author_id" => organizer_actor.id,
"participant" => %{"actor_id" => actor_id, "id" => conversation_participant_actor_id}, "participant" => %{"actor_id" => actor_id, "id" => conversation_participant_actor_id},
"object_id" => to_string(conversation_id), "object_id" => to_string(conversation_id),
"object_type" => "conversation", "object_type" => "conversation",
@@ -50,7 +128,10 @@ defmodule Mobilizon.Service.Activity.ConversationTest do
"subject" => "conversation_created", "subject" => "conversation_created",
"subject_params" => %{ "subject_params" => %{
"conversation_id" => conversation_id, "conversation_id" => conversation_id,
"conversation_participant_id" => conversation_participant_actor_id "conversation_participant_id" => conversation_participant_actor_id,
"conversation_event_id" => event.id,
"conversation_event_title" => event.title,
"conversation_event_uuid" => event.uuid
}, },
"type" => "conversation" "type" => "conversation"
} }
@@ -59,7 +140,7 @@ defmodule Mobilizon.Service.Activity.ConversationTest do
assert_enqueued( assert_enqueued(
worker: LegacyNotifierBuilder, worker: LegacyNotifierBuilder,
args: %{ args: %{
"author_id" => last_comment_actor_id, "author_id" => organizer_actor.id,
"participant" => %{ "participant" => %{
"actor_id" => conversation_other_participant_actor_id, "actor_id" => conversation_other_participant_actor_id,
"id" => conversation_participant_id "id" => conversation_participant_id
@@ -70,7 +151,81 @@ defmodule Mobilizon.Service.Activity.ConversationTest do
"subject" => "conversation_created", "subject" => "conversation_created",
"subject_params" => %{ "subject_params" => %{
"conversation_id" => conversation_id, "conversation_id" => conversation_id,
"conversation_participant_id" => conversation_participant_id "conversation_participant_id" => conversation_participant_id,
"conversation_event_id" => event.id,
"conversation_event_title" => event.title,
"conversation_event_uuid" => event.uuid
},
"type" => "conversation"
}
)
end
test "an author who is member of the event organizer group" do
%User{} = user = insert(:user)
%Actor{id: actor_id} = actor = insert(:actor, user: user)
%Actor{} = organizer_group = insert(:group)
%Event{} = event = insert(:event, attributed_to: organizer_group)
%Comment{} = comment = insert(:comment, actor: organizer_group)
%Conversation{id: conversation_id} =
conversation =
insert(:conversation, event: event, last_comment: comment, origin_comment: comment)
%ConversationParticipant{id: conversation_participant_actor_id} =
insert(:conversation_participant, actor: actor, conversation: conversation)
%ConversationParticipant{
id: conversation_participant_id,
actor: %Actor{id: conversation_other_participant_actor_id}
} = insert(:conversation_participant, conversation: conversation)
conversation = Conversations.get_conversation(conversation_id)
assert {:ok, _} =
ConversationActivity.insert_activity(conversation, subject: "conversation_created")
assert_enqueued(
worker: LegacyNotifierBuilder,
args: %{
"author_id" => organizer_group.id,
"participant" => %{"actor_id" => actor_id, "id" => conversation_participant_actor_id},
"object_id" => to_string(conversation_id),
"object_type" => "conversation",
"op" => "legacy_notify",
"subject" => "conversation_created",
"subject_params" => %{
"conversation_id" => conversation_id,
"conversation_participant_id" => conversation_participant_actor_id,
"conversation_event_id" => event.id,
"conversation_event_title" => event.title,
"conversation_event_uuid" => event.uuid
},
"type" => "conversation"
}
)
assert_enqueued(
worker: LegacyNotifierBuilder,
args: %{
"author_id" => organizer_group.id,
"participant" => %{
"actor_id" => conversation_other_participant_actor_id,
"id" => conversation_participant_id
},
"object_id" => to_string(conversation_id),
"object_type" => "conversation",
"op" => "legacy_notify",
"subject" => "conversation_created",
"subject_params" => %{
"conversation_id" => conversation_id,
"conversation_participant_id" => conversation_participant_id,
"conversation_event_id" => event.id,
"conversation_event_title" => event.title,
"conversation_event_uuid" => event.uuid
}, },
"type" => "conversation" "type" => "conversation"
} }