diff --git a/lib/graphql/schema/actors/group.ex b/lib/graphql/schema/actors/group.ex index eed6b889b..39265eadd 100644 --- a/lib/graphql/schema/actors/group.ex +++ b/lib/graphql/schema/actors/group.ex @@ -61,6 +61,11 @@ defmodule Mobilizon.GraphQL.Schema.Actors.GroupType do description: "The type of the event's address" ) + field(:allow_see_participants, :boolean, + description: "Option to allow group's member to see event's participants", + default_value: false + ) + # These one should have a privacy setting field(:followers_count, :integer, description: "Number of followers for this actor", @@ -320,6 +325,12 @@ defmodule Mobilizon.GraphQL.Schema.Actors.GroupType do ) arg(:physical_address, :address_input, description: "The physical address for the group") + + arg(:allow_see_participants, :boolean, + description: "Option to allow group's member to see event's participants", + default_value: false + ) + middleware(Rajska.QueryAuthorization, permit: :user, scope: false) resolve(&Group.create_group/3) end @@ -352,6 +363,11 @@ defmodule Mobilizon.GraphQL.Schema.Actors.GroupType do ) arg(:physical_address, :address_input, description: "The physical address for the group") + + arg(:allow_see_participants, :boolean, + description: "Option to allow group's member to see event's participants" + ) + middleware(Rajska.QueryAuthorization, permit: :user, scope: false) resolve(&Group.update_group/3) end diff --git a/lib/mobilizon/actors/actor.ex b/lib/mobilizon/actors/actor.ex index d62f41288..4a0a1cf46 100644 --- a/lib/mobilizon/actors/actor.ex +++ b/lib/mobilizon/actors/actor.ex @@ -63,7 +63,8 @@ defmodule Mobilizon.Actors.Actor do owner_shares: [Share.t()], memberships: [t], last_refreshed_at: DateTime.t(), - physical_address: Address.t() + physical_address: Address.t(), + allow_see_participants: boolean } @required_attrs [:preferred_username, :keys, :suspended, :url] @@ -85,6 +86,7 @@ defmodule Mobilizon.Actors.Actor do :last_refreshed_at, :user_id, :physical_address_id, + :allow_see_participants, :visibility ] @attrs @required_attrs ++ @optional_attrs @@ -97,12 +99,13 @@ defmodule Mobilizon.Actors.Actor do :user_id, :visibility, :openness, - :physical_address_id + :physical_address_id, + :allow_see_participants ] @update_attrs @update_required_attrs ++ @update_optional_attrs @registration_required_attrs [:preferred_username, :keys, :suspended, :url, :type] - @registration_optional_attrs [:domain, :name, :summary, :user_id] + @registration_optional_attrs [:domain, :name, :summary, :user_id, :allow_see_participants] @registration_attrs @registration_required_attrs ++ @registration_optional_attrs @remote_actor_creation_required_attrs [ @@ -129,7 +132,8 @@ defmodule Mobilizon.Actors.Actor do :manually_approves_followers, :visibility, :openness, - :physical_address_id + :physical_address_id, + :allow_see_participants ] @remote_actor_creation_attrs @remote_actor_creation_required_attrs ++ @remote_actor_creation_optional_attrs @@ -149,7 +153,8 @@ defmodule Mobilizon.Actors.Actor do :summary, :visibility, :openness, - :manually_approves_followers + :manually_approves_followers, + :allow_see_participants ] @group_creation_attrs @group_creation_required_attrs ++ @group_creation_optional_attrs @@ -179,6 +184,7 @@ defmodule Mobilizon.Actors.Actor do field(:visibility, ActorVisibility, default: :private) field(:suspended, :boolean, default: false) field(:last_refreshed_at, :utc_datetime) + field(:allow_see_participants, :boolean, default: false) embeds_one(:avatar, File, on_replace: :update) embeds_one(:banner, File, on_replace: :update) diff --git a/priv/repo/migrations/20201105145719_repair_groups_with_missing_ur_ls.exs b/priv/repo/migrations/20201105145719_repair_groups_with_missing_ur_ls.exs index bfb6e9f1c..1570cbdb8 100644 --- a/priv/repo/migrations/20201105145719_repair_groups_with_missing_ur_ls.exs +++ b/priv/repo/migrations/20201105145719_repair_groups_with_missing_ur_ls.exs @@ -7,6 +7,12 @@ defmodule Mobilizon.Storage.Repo.Migrations.RepairGroupsWithMissingURLs do def up do Actor |> where([a], a.type == :Group and is_nil(a.domain)) + |> select( + [a], + {a.id, a.url, a.outbox_url, a.inbox_url, a.following_url, a.followers_url, + a.shared_inbox_url, a.members_url, a.resources_url, a.posts_url, a.events_url, a.todos_url, + a.discussions_url, a.type, a.name, a.domain} + ) |> Repo.all() |> Enum.each(&fix_group/1) end diff --git a/priv/repo/migrations/20251111093015_add_allow_to_group.exs b/priv/repo/migrations/20251111093015_add_allow_to_group.exs new file mode 100644 index 000000000..a8006c6b0 --- /dev/null +++ b/priv/repo/migrations/20251111093015_add_allow_to_group.exs @@ -0,0 +1,9 @@ +defmodule Mobilizon.Storage.Repo.Migrations.AddAllowToGroup do + use Ecto.Migration + + def change do + alter table("actors") do + add(:allow_see_participants, :boolean, default: false, null: false) + end + end +end diff --git a/schema.graphql b/schema.graphql index 99a0b0324..27a3f7b50 100644 --- a/schema.graphql +++ b/schema.graphql @@ -1478,6 +1478,9 @@ type RootMutationType { "The physical address for the group" physicalAddress: AddressInput + + "Option to allow group's member to see event's participants" + allowSeeParticipants: Boolean ): Group "Update a group" diff --git a/test/graphql/resolvers/group_test.exs b/test/graphql/resolvers/group_test.exs index d10d7471d..9f174ca1d 100644 --- a/test/graphql/resolvers/group_test.exs +++ b/test/graphql/resolvers/group_test.exs @@ -25,6 +25,7 @@ defmodule Mobilizon.Web.Resolvers.GroupTest do $summary: String $avatar: MediaInput $banner: MediaInput + $allowSeeParticipants: Boolean ) { createGroup( preferredUsername: $preferredUsername @@ -32,6 +33,7 @@ defmodule Mobilizon.Web.Resolvers.GroupTest do summary: $summary banner: $banner avatar: $avatar + allowSeeParticipants: $allowSeeParticipants ) { preferredUsername type @@ -39,6 +41,7 @@ defmodule Mobilizon.Web.Resolvers.GroupTest do uuid url } + allowSeeParticipants } } """ @@ -59,6 +62,7 @@ defmodule Mobilizon.Web.Resolvers.GroupTest do @new_group_params.preferredUsername assert res["data"]["createGroup"]["type"] == "GROUP" + assert res["data"]["createGroup"]["allowSeeParticipants"] == false res = conn @@ -72,6 +76,44 @@ defmodule Mobilizon.Web.Resolvers.GroupTest do "A profile or group with that name already exists" end + test "creates a group with allowSeeParticipants to false", + %{conn: conn, user: user} do + res = + conn + |> auth_conn(user) + |> AbsintheHelpers.graphql_query( + query: @create_group_mutation, + variables: Map.put(@new_group_params, :allowSeeParticipants, false) + ) + + assert res["errors"] == nil + + assert res["data"]["createGroup"]["preferredUsername"] == + @new_group_params.preferredUsername + + assert res["data"]["createGroup"]["type"] == "GROUP" + assert res["data"]["createGroup"]["allowSeeParticipants"] == false + end + + test "creates a group with allowSeeParticipants to true", + %{conn: conn, user: user} do + res = + conn + |> auth_conn(user) + |> AbsintheHelpers.graphql_query( + query: @create_group_mutation, + variables: Map.put(@new_group_params, :allowSeeParticipants, true) + ) + + assert res["errors"] == nil + + assert res["data"]["createGroup"]["preferredUsername"] == + @new_group_params.preferredUsername + + assert res["data"]["createGroup"]["type"] == "GROUP" + assert res["data"]["createGroup"]["allowSeeParticipants"] == true + end + test "doesn't creates a group if the username doesn't match the requirements", %{conn: conn, user: user} do res =