diff --git a/lib/graphql/resolvers/event.ex b/lib/graphql/resolvers/event.ex index 04ab9b8c5..cd08d53db 100644 --- a/lib/graphql/resolvers/event.ex +++ b/lib/graphql/resolvers/event.ex @@ -160,7 +160,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Event do %{context: %{current_actor: %Actor{} = actor}} = _resolution ) do # Check that moderator has right - if can_event_be_updated_by?(event, actor) do + if can_event_be_access_by?(event, actor) do roles = case roles do nil -> diff --git a/lib/graphql/resolvers/event/utils.ex b/lib/graphql/resolvers/event/utils.ex index c4d014ae3..4c283bde4 100644 --- a/lib/graphql/resolvers/event/utils.ex +++ b/lib/graphql/resolvers/event/utils.ex @@ -25,6 +25,29 @@ defmodule Mobilizon.GraphQL.Resolvers.Event.Utils do Event.can_be_managed_by?(event, actor_member_id) end + @spec can_event_be_access_by?(Event.t(), Actor.t()) :: + boolean + def can_event_be_access_by?( + %Event{attributed_to: %Actor{type: :Group, allow_see_participants: true}} = event, + %Actor{} = actor_member + ) do + Permission.can_access_group_object?(actor_member, event) + end + + def can_event_be_access_by?( + %Event{attributed_to: %Actor{type: :Group, allow_see_participants: false}} = event, + %Actor{} = actor_member + ) do + can_event_be_updated_by?(event, actor_member) + end + + def can_event_be_access_by?( + %Event{} = event, + %Actor{} = actor_member + ) do + can_event_be_updated_by?(event, actor_member) + end + @spec can_event_be_deleted_by?(Event.t(), Actor.t()) :: boolean def can_event_be_deleted_by?( diff --git a/lib/graphql/resolvers/participant.ex b/lib/graphql/resolvers/participant.ex index 2aa5ab7cf..9b35b3c8f 100644 --- a/lib/graphql/resolvers/participant.ex +++ b/lib/graphql/resolvers/participant.ex @@ -309,7 +309,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Participant do }) do case Events.get_event_with_preload(event_id) do {:ok, %Event{} = event} -> - if can_event_be_updated_by?(event, moderator_actor) do + if can_event_be_access_by?(event, moderator_actor) do case export_format(format, event, roles, locale) do {:ok, path} -> {:ok, %{path: path, format: format}} diff --git a/test/graphql/resolvers/participant_test.exs b/test/graphql/resolvers/participant_test.exs index 212c0dfa4..d1a4a1bd4 100644 --- a/test/graphql/resolvers/participant_test.exs +++ b/test/graphql/resolvers/participant_test.exs @@ -3,8 +3,8 @@ defmodule Mobilizon.GraphQL.Resolvers.ParticipantTest do use Mobilizon.Tests.Helpers use Oban.Testing, repo: Mobilizon.Storage.Repo - alias Mobilizon.Actors.Actor alias Mobilizon.{Actors, Config, Conversations, Events} + alias Mobilizon.Actors.Actor alias Mobilizon.Events.{Event, EventParticipantStats, Participant} alias Mobilizon.GraphQL.AbsintheHelpers alias Mobilizon.Service.Workers.LegacyNotifierBuilder @@ -29,7 +29,16 @@ defmodule Mobilizon.GraphQL.Resolvers.ParticipantTest do user = insert(:user) actor = insert(:actor, user: user, preferred_username: "test") - {:ok, conn: conn, actor: actor, user: user} + event = insert(:event, join_options: :restricted, organizer_actor: actor) + insert(:participant, event: event, actor: actor, role: :creator) + + insert(:participant, + event: event, + actor: insert(:actor, user: insert(:user), preferred_username: "test-part"), + role: :participant + ) + + {:ok, conn: conn, actor: actor, user: user, event: event} end describe "Participant Resolver" do @@ -1384,6 +1393,283 @@ defmodule Mobilizon.GraphQL.Resolvers.ParticipantTest do end end + describe "Participate list and permission" do + @event_participant """ + query EventParticipants($uuid: UUID!, $roles: String, $page: Int, $limit: Int) { + event(uuid: $uuid) { + id, + uuid, + title, + participants(page: $page, limit: $limit, roles: $roles) { + elements { + role, + actor { + preferredUsername + } + } + }, + organizerActor { + preferredUsername + } + attributedTo { + preferredUsername + } + } + } + """ + + test "No participate if not logging", %{conn: conn, actor: actor, event: event} do + res = + conn + |> AbsintheHelpers.graphql_query( + query: @event_participant, + variables: %{uuid: event.uuid} + ) + + assert hd(res["errors"])["message"] == + "Not authorized to access object paginated_participant_list" + end + + test "participates for owned event", %{conn: conn, actor: actor, user: user, event: event} do + res = + conn + |> auth_conn(user) + |> AbsintheHelpers.graphql_query( + query: @event_participant, + variables: %{uuid: event.uuid} + ) + + assert res["errors"] == nil + assert res["data"]["event"]["uuid"] == event.uuid + + assert res["data"]["event"]["organizerActor"] == %{ + "preferredUsername" => actor.preferred_username + } + + assert res["data"]["event"]["attributedTo"] == nil + + assert res["data"]["event"]["participants"]["elements"] == [ + %{ + "actor" => %{ + "preferredUsername" => "test-part" + }, + "role" => "PARTICIPANT" + }, + %{ + "actor" => %{ + "preferredUsername" => actor.preferred_username + }, + "role" => "CREATOR" + } + ] + end + + test "participates for group event where user is admin (not allowed)", %{ + conn: conn, + actor: actor, + user: user, + event: event + } do + group = + insert(:group, + allow_see_participants: false, + name: "group1", + preferred_username: "test-group" + ) + + insert(:member, parent: group, actor: actor, role: :administrator) + + assert {:ok, activity, entity} = + Mobilizon.GraphQL.API.Events.update_event(%{attributed_to_id: group.id}, event) + + assert entity.attributed_to.preferred_username == "test-group" + + res = + conn + |> auth_conn(user) + |> AbsintheHelpers.graphql_query( + query: @event_participant, + variables: %{uuid: event.uuid} + ) + + assert res["errors"] == nil + assert res["data"]["event"]["uuid"] == event.uuid + + assert res["data"]["event"]["organizerActor"] == %{ + "preferredUsername" => actor.preferred_username + } + + assert res["data"]["event"]["attributedTo"] == %{ + "preferredUsername" => "test-group" + } + + assert res["data"]["event"]["participants"]["elements"] == [ + %{ + "actor" => %{ + "preferredUsername" => "test-part" + }, + "role" => "PARTICIPANT" + }, + %{ + "actor" => %{ + "preferredUsername" => actor.preferred_username + }, + "role" => "CREATOR" + } + ] + end + + test "participates for group event where user is admin (but allowed)", %{ + conn: conn, + actor: actor, + user: user, + event: event + } do + group = + insert(:group, + allow_see_participants: true, + name: "group1", + preferred_username: "test-group" + ) + + insert(:member, parent: group, actor: actor, role: :administrator) + + assert {:ok, activity, entity} = + Mobilizon.GraphQL.API.Events.update_event(%{attributed_to_id: group.id}, event) + + assert entity.attributed_to.preferred_username == "test-group" + + res = + conn + |> auth_conn(user) + |> AbsintheHelpers.graphql_query( + query: @event_participant, + variables: %{uuid: event.uuid} + ) + + assert res["errors"] == nil + assert res["data"]["event"]["uuid"] == event.uuid + + assert res["data"]["event"]["organizerActor"] == %{ + "preferredUsername" => actor.preferred_username + } + + assert res["data"]["event"]["attributedTo"] == %{ + "preferredUsername" => "test-group" + } + + assert res["data"]["event"]["participants"]["elements"] == [ + %{ + "actor" => %{ + "preferredUsername" => "test-part" + }, + "role" => "PARTICIPANT" + }, + %{ + "actor" => %{ + "preferredUsername" => actor.preferred_username + }, + "role" => "CREATOR" + } + ] + end + + test "participates for group event where user is member (not allowed)", %{ + conn: conn, + actor: actor, + user: user, + event: event + } do + user_group = insert(:user) + actor_group = insert(:actor, user: user_group, preferred_username: "test") + + group = + insert(:group, + allow_see_participants: false, + name: "group1", + preferred_username: "test-group" + ) + + insert(:member, parent: group, actor: actor, role: :administrator) + insert(:member, parent: group, actor: actor_group, role: :member) + + assert {:ok, activity, entity} = + Mobilizon.GraphQL.API.Events.update_event(%{attributed_to_id: group.id}, event) + + assert entity.attributed_to.preferred_username == "test-group" + + res = + conn + |> auth_conn(user_group) + |> AbsintheHelpers.graphql_query( + query: @event_participant, + variables: %{uuid: event.uuid} + ) + + assert hd(res["errors"])["message"] == + "Provided profile doesn't have moderator permissions on this event" + end + + test "participates for group event where user is member (but allowed)", %{ + conn: conn, + actor: actor, + user: user, + event: event + } do + user_group = insert(:user) + actor_group = insert(:actor, user: user_group, preferred_username: "test") + + group = + insert(:group, + allow_see_participants: true, + name: "group1", + preferred_username: "test-group" + ) + + insert(:member, parent: group, actor: actor, role: :administrator) + insert(:member, parent: group, actor: actor_group, role: :member) + + assert {:ok, activity, entity} = + Mobilizon.GraphQL.API.Events.update_event(%{attributed_to_id: group.id}, event) + + assert entity.attributed_to.preferred_username == "test-group" + + res = + conn + |> auth_conn(user_group) + |> AbsintheHelpers.graphql_query( + query: @event_participant, + variables: %{uuid: event.uuid} + ) + + assert res["errors"] == nil + assert res["data"]["event"]["uuid"] == event.uuid + + assert res["data"]["event"]["organizerActor"] == %{ + "preferredUsername" => actor.preferred_username + } + + assert res["data"]["event"]["attributedTo"] == %{ + "preferredUsername" => "test-group" + } + + assert res["data"]["event"]["participants"]["elements"] == [ + %{ + "actor" => %{ + "preferredUsername" => "test-part" + }, + "role" => "PARTICIPANT" + }, + %{ + "actor" => %{ + "preferredUsername" => actor.preferred_username + }, + "role" => "CREATOR" + } + ] + end + end + describe "Send private messages to participants" do @send_event_private_message_mutation """ mutation SendEventPrivateMessageMutation(