fix(announcements): make sure only valid announcements are shown to the user
Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
parent
dcbb8eae01
commit
c9a1c35aa7
|
@ -20,6 +20,7 @@ defmodule Mobilizon.GraphQL.Schema.ConversationType do
|
||||||
)
|
)
|
||||||
|
|
||||||
field(:last_comment, :comment, description: "The last comment of the conversation")
|
field(:last_comment, :comment, description: "The last comment of the conversation")
|
||||||
|
field(:origin_comment, :comment, description: "The first comment of the conversation")
|
||||||
|
|
||||||
field :comments, :paginated_comment_list do
|
field :comments, :paginated_comment_list do
|
||||||
arg(:page, :integer, default_value: 1)
|
arg(:page, :integer, default_value: 1)
|
||||||
|
|
|
@ -47,6 +47,12 @@ defmodule Mobilizon.GraphQL.Schema.Discussions.CommentType do
|
||||||
|
|
||||||
field(:threadLanguages, non_null(list_of(:string)), description: "The thread languages")
|
field(:threadLanguages, non_null(list_of(:string)), description: "The thread languages")
|
||||||
field(:actor, :person, resolve: dataloader(Actors), description: "The comment's author")
|
field(:actor, :person, resolve: dataloader(Actors), description: "The comment's author")
|
||||||
|
|
||||||
|
field(:attributed_to, :actor,
|
||||||
|
resolve: dataloader(Actors),
|
||||||
|
description: "The comment's attributed to actor"
|
||||||
|
)
|
||||||
|
|
||||||
field(:inserted_at, :datetime, description: "When was the comment inserted in database")
|
field(:inserted_at, :datetime, description: "When was the comment inserted in database")
|
||||||
field(:updated_at, :datetime, description: "When was the comment updated")
|
field(:updated_at, :datetime, description: "When was the comment updated")
|
||||||
field(:deleted_at, :datetime, description: "When was the comment deleted")
|
field(:deleted_at, :datetime, description: "When was the comment deleted")
|
||||||
|
|
|
@ -137,7 +137,7 @@ defmodule Mobilizon.Conversations do
|
||||||
subquery
|
subquery
|
||||||
|> subquery()
|
|> subquery()
|
||||||
|> order_by([cp], desc: cp.unread, desc: cp.updated_at)
|
|> order_by([cp], desc: cp.unread, desc: cp.updated_at)
|
||||||
|> preload([:actor, conversation: [:last_comment, :participants]])
|
|> preload([:actor, conversation: [:last_comment, :origin_comment, :participants, :event]])
|
||||||
|> Page.build_page(page, limit)
|
|> Page.build_page(page, limit)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -151,7 +151,7 @@ defmodule Mobilizon.Conversations do
|
||||||
ConversationParticipant
|
ConversationParticipant
|
||||||
|> join(:inner, [cp], a in Actor, on: cp.actor_id == a.id)
|
|> join(:inner, [cp], a in Actor, on: cp.actor_id == a.id)
|
||||||
|> where([_cp, a], a.user_id == ^user_id)
|
|> where([_cp, a], a.user_id == ^user_id)
|
||||||
|> preload([:actor, conversation: [:last_comment, :participants]])
|
|> preload([:actor, conversation: [:last_comment, :origin_comment, :participants, :event]])
|
||||||
|> Page.build_page(page, limit)
|
|> Page.build_page(page, limit)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,9 @@ export const COMMENT_FIELDS_FRAGMENT = gql`
|
||||||
actor {
|
actor {
|
||||||
...ActorFragment
|
...ActorFragment
|
||||||
}
|
}
|
||||||
|
attributedTo {
|
||||||
|
...ActorFragment
|
||||||
|
}
|
||||||
totalReplies
|
totalReplies
|
||||||
insertedAt
|
insertedAt
|
||||||
updatedAt
|
updatedAt
|
||||||
|
|
|
@ -12,6 +12,9 @@ export const CONVERSATION_QUERY_FRAGMENT = gql`
|
||||||
lastComment {
|
lastComment {
|
||||||
...CommentFields
|
...CommentFields
|
||||||
}
|
}
|
||||||
|
originComment {
|
||||||
|
...CommentFields
|
||||||
|
}
|
||||||
participants {
|
participants {
|
||||||
...ActorFragment
|
...ActorFragment
|
||||||
}
|
}
|
||||||
|
@ -19,6 +22,12 @@ export const CONVERSATION_QUERY_FRAGMENT = gql`
|
||||||
id
|
id
|
||||||
uuid
|
uuid
|
||||||
title
|
title
|
||||||
|
organizerActor {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
attributedTo {
|
||||||
|
id
|
||||||
|
}
|
||||||
picture {
|
picture {
|
||||||
id
|
id
|
||||||
url
|
url
|
||||||
|
|
|
@ -8,6 +8,7 @@ export interface IConversation {
|
||||||
id?: string;
|
id?: string;
|
||||||
actor?: IActor;
|
actor?: IActor;
|
||||||
lastComment?: IComment;
|
lastComment?: IComment;
|
||||||
|
originComment?: IComment;
|
||||||
comments: Paginate<IComment>;
|
comments: Paginate<IComment>;
|
||||||
participants: IActor[];
|
participants: IActor[];
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
|
|
|
@ -14,7 +14,11 @@
|
||||||
]"
|
]"
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
v-if="conversation.event && !isCurrentActorAuthor"
|
v-if="
|
||||||
|
conversation.event &&
|
||||||
|
!isCurrentActorAuthor &&
|
||||||
|
isOriginCommentAuthorEventOrganizer
|
||||||
|
"
|
||||||
class="bg-mbz-yellow p-6 mb-3 rounded flex gap-2 items-center"
|
class="bg-mbz-yellow p-6 mb-3 rounded flex gap-2 items-center"
|
||||||
>
|
>
|
||||||
<Calendar :size="36" />
|
<Calendar :size="36" />
|
||||||
|
@ -132,7 +136,11 @@
|
||||||
>
|
>
|
||||||
</form>
|
</form>
|
||||||
<div
|
<div
|
||||||
v-else-if="conversation.event"
|
v-else-if="
|
||||||
|
conversation.event &&
|
||||||
|
!isCurrentActorAuthor &&
|
||||||
|
isOriginCommentAuthorEventOrganizer
|
||||||
|
"
|
||||||
class="bg-mbz-yellow p-6 rounded flex gap-2 items-center mt-3"
|
class="bg-mbz-yellow p-6 rounded flex gap-2 items-center mt-3"
|
||||||
>
|
>
|
||||||
<Calendar :size="36" />
|
<Calendar :size="36" />
|
||||||
|
@ -292,6 +300,16 @@ const isCurrentActorAuthor = computed(
|
||||||
currentActor.value.id !== conversation.value?.actor?.id
|
currentActor.value.id !== conversation.value?.actor?.id
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const isOriginCommentAuthorEventOrganizer = computed(
|
||||||
|
() =>
|
||||||
|
conversation.value?.originComment?.actor &&
|
||||||
|
conversation.value?.event &&
|
||||||
|
[
|
||||||
|
conversation.value?.event?.organizerActor?.id,
|
||||||
|
conversation.value?.event?.attributedTo?.id,
|
||||||
|
].includes(conversation.value?.originComment?.actor.id)
|
||||||
|
);
|
||||||
|
|
||||||
useHead({
|
useHead({
|
||||||
title: () => title.value,
|
title: () => title.value,
|
||||||
});
|
});
|
||||||
|
|
|
@ -6,6 +6,7 @@ defmodule Mobilizon.Federation.ActivityPub.Transmogrifier.CreateTest do
|
||||||
alias Mobilizon.Actors.Actor
|
alias Mobilizon.Actors.Actor
|
||||||
alias Mobilizon.Conversations.Conversation
|
alias Mobilizon.Conversations.Conversation
|
||||||
alias Mobilizon.Discussions.Comment
|
alias Mobilizon.Discussions.Comment
|
||||||
|
alias Mobilizon.Events.Event
|
||||||
alias Mobilizon.Federation.ActivityPub.Transmogrifier
|
alias Mobilizon.Federation.ActivityPub.Transmogrifier
|
||||||
alias Mobilizon.Service.HTTP.ActivityPub.Mock
|
alias Mobilizon.Service.HTTP.ActivityPub.Mock
|
||||||
|
|
||||||
|
@ -103,5 +104,57 @@ defmodule Mobilizon.Federation.ActivityPub.Transmogrifier.CreateTest do
|
||||||
{:ok, admin} = Mobilizon.Actors.get_actor_by_url("https://framapiaf.org/users/admin")
|
{:ok, admin} = Mobilizon.Actors.get_actor_by_url("https://framapiaf.org/users/admin")
|
||||||
assert participant_ids == MapSet.new([actor.id, admin.id])
|
assert participant_ids == MapSet.new([actor.id, admin.id])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "it creates conversations for received comments if we're concerned even with reply to an event" do
|
||||||
|
actor_data = File.read!("test/fixtures/mastodon-actor.json") |> Jason.decode!()
|
||||||
|
|
||||||
|
Mock
|
||||||
|
|> expect(:call, 1, fn
|
||||||
|
%{method: :get, url: "https://framapiaf.org/users/admin"}, _opts ->
|
||||||
|
{:ok,
|
||||||
|
%Tesla.Env{
|
||||||
|
status: 200,
|
||||||
|
body:
|
||||||
|
actor_data
|
||||||
|
|> Map.put("id", "https://framapiaf.org/users/admin")
|
||||||
|
|> Map.put("preferredUsername", "admin")
|
||||||
|
}}
|
||||||
|
end)
|
||||||
|
|
||||||
|
actor = insert(:actor)
|
||||||
|
data = File.read!("test/fixtures/mastodon-post-activity-private.json") |> Jason.decode!()
|
||||||
|
data = Map.put(data, "to", [actor.url])
|
||||||
|
|
||||||
|
%Event{id: event_id, organizer_actor_id: organizer_actor_id} = event = insert(:event)
|
||||||
|
|
||||||
|
%Comment{url: reply_to_url, id: first_reply_comment_id} =
|
||||||
|
insert(:comment, visibility: :private, event: event)
|
||||||
|
|
||||||
|
object =
|
||||||
|
data["object"]
|
||||||
|
|> Map.put("to", [actor.url])
|
||||||
|
|> Map.put("inReplyTo", reply_to_url)
|
||||||
|
|> Map.put("tag", [
|
||||||
|
data["object"]["tag"]
|
||||||
|
|> hd()
|
||||||
|
|> Map.put("href", actor.url)
|
||||||
|
|> Map.put("name", Actor.preferred_username_and_domain(actor))
|
||||||
|
])
|
||||||
|
|
||||||
|
data = Map.put(data, "object", object)
|
||||||
|
|
||||||
|
{:ok, _activity,
|
||||||
|
%Conversation{
|
||||||
|
origin_comment: %Comment{visibility: :private, id: origin_comment_id},
|
||||||
|
last_comment: %Comment{visibility: :private, id: _last_comment_id},
|
||||||
|
participants: participants,
|
||||||
|
event: %Event{id: ^event_id}
|
||||||
|
}} = Transmogrifier.handle_incoming(data)
|
||||||
|
|
||||||
|
assert origin_comment_id == first_reply_comment_id
|
||||||
|
participant_ids = participants |> Enum.map(& &1.id) |> MapSet.new()
|
||||||
|
{:ok, admin} = Mobilizon.Actors.get_actor_by_url("https://framapiaf.org/users/admin")
|
||||||
|
assert participant_ids == MapSet.new([actor.id, organizer_actor_id, admin.id])
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue