diff --git a/lib/graphql/resolvers/invitation.ex b/lib/graphql/resolvers/invitation.ex index 1a473d3d6..ba293c154 100644 --- a/lib/graphql/resolvers/invitation.ex +++ b/lib/graphql/resolvers/invitation.ex @@ -5,6 +5,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Invitation do alias Mobilizon.Actors alias Mobilizon.Actors.Actor + alias Mobilizon.Invitation alias Mobilizon.Invitations import Mobilizon.Web.Gettext @@ -54,4 +55,33 @@ defmodule Mobilizon.GraphQL.Resolvers.Invitation do Invitations.delete_invitation_by_token(group_id, token) end end + + def accept_invitation_token( + _parent, + %{group_id: group_id, token: token, actor_id: actor_id_chosen}, + %{ + context: %{current_actor: %Actor{id: actor_id_connected}} + } + ) do + with true <- + String.to_integer(actor_id_chosen) == actor_id_connected || + {:error, "You can only accept invitations for your own account"}, + %Invitation{} = _invitation <- + Invitations.find_invitation(group_id, token) || + {:error, "Invalid invitation token for this group"}, + false <- + Mobilizon.Actors.member?(actor_id_connected, group_id), + {:ok, member} <- + Mobilizon.Actors.create_member(%{ + role: :member, + parent_id: group_id, + actor_id: actor_id_connected + }) do + {:ok, member} + else + {:error, _} = error -> error + true -> {:error, "You are already a member of this group"} + _ -> {:error, "Unexpected error"} + end + end end diff --git a/lib/graphql/schema/invitation.ex b/lib/graphql/schema/invitation.ex index bc8fbf74b..30e2d7b76 100644 --- a/lib/graphql/schema/invitation.ex +++ b/lib/graphql/schema/invitation.ex @@ -24,7 +24,7 @@ defmodule Mobilizon.GraphQL.Schema.InvitationType do @desc "Update an invitation for a group" field :update_invitation, type: :invitation do arg(:group_id, non_null(:id), description: "ID of the group") - arg(:token, :string, description: "Token") + arg(:token, non_null(:string), description: "Token") arg(:label, :string, description: "Label") middleware(Rajska.QueryAuthorization, permit: :user, scope: false) resolve(&Invitation.update_invitation/3) @@ -33,10 +33,19 @@ defmodule Mobilizon.GraphQL.Schema.InvitationType do @desc "Delete an invitation for a group" field :delete_invitation, type: :invitation do arg(:group_id, non_null(:id), description: "ID of the group") - arg(:token, :string, description: "Token") + arg(:token, non_null(:string), description: "Token") middleware(Rajska.QueryAuthorization, permit: :user, scope: false) resolve(&Invitation.delete_invitation/3) end + + @desc "Accept an invitation to join a group" + field :accept_invitation_token, type: :member do + arg(:actor_id, non_null(:id), description: "The ID of the actor that will join the group") + arg(:group_id, non_null(:id), description: "ID of the group") + arg(:token, :string, description: "Token") + middleware(Rajska.QueryAuthorization, permit: :user, scope: false) + resolve(&Invitation.accept_invitation_token/3) + end end object :invitation_queries do diff --git a/lib/mobilizon/invitations/invitations.ex b/lib/mobilizon/invitations/invitations.ex index 1b38ff6f3..e0b677034 100644 --- a/lib/mobilizon/invitations/invitations.ex +++ b/lib/mobilizon/invitations/invitations.ex @@ -39,4 +39,8 @@ defmodule Mobilizon.Invitations do |> where([i], i.group_id == ^group_id) |> Repo.all() end + + def find_invitation(group_id, token) do + Repo.get_by(Invitation, group_id: group_id, token: token) + end end