diff --git a/packages/hoppscotch-app/helpers/backend/gql/mutations/AcceptTeamInvitation.graphql b/packages/hoppscotch-app/helpers/backend/gql/mutations/AcceptTeamInvitation.graphql new file mode 100644 index 000000000..41d125554 --- /dev/null +++ b/packages/hoppscotch-app/helpers/backend/gql/mutations/AcceptTeamInvitation.graphql @@ -0,0 +1,12 @@ +mutation AcceptTeamInvitation($inviteID: ID!) { + acceptTeamInvitation(inviteID: $inviteID) { + membershipID + role + user { + uid + displayName + photoURL + email + } + } +} \ No newline at end of file diff --git a/packages/hoppscotch-app/helpers/backend/gql/mutations/CreateTeamInvitation.graphql b/packages/hoppscotch-app/helpers/backend/gql/mutations/CreateTeamInvitation.graphql new file mode 100644 index 000000000..98fcb580d --- /dev/null +++ b/packages/hoppscotch-app/helpers/backend/gql/mutations/CreateTeamInvitation.graphql @@ -0,0 +1,9 @@ +mutation CreateTeamInvitation($inviteeEmail: String!, $inviteeRole: TeamMemberRole!, $teamID: ID!) { + createTeamInvitation(inviteeRole: $inviteeRole, inviteeEmail: $inviteeEmail, teamID: $teamID) { + id + teamID + creatorUid + inviteeEmail + inviteeRole + } +} \ No newline at end of file diff --git a/packages/hoppscotch-app/helpers/backend/gql/mutations/RevokeTeamInvitation.graphql b/packages/hoppscotch-app/helpers/backend/gql/mutations/RevokeTeamInvitation.graphql new file mode 100644 index 000000000..a8652db46 --- /dev/null +++ b/packages/hoppscotch-app/helpers/backend/gql/mutations/RevokeTeamInvitation.graphql @@ -0,0 +1,3 @@ +mutation RevokeTeamInvitation($inviteID: ID!) { + revokeTeamInvitation(inviteID: $inviteID) +} \ No newline at end of file diff --git a/packages/hoppscotch-app/helpers/backend/mutations/TeamInvitation.ts b/packages/hoppscotch-app/helpers/backend/mutations/TeamInvitation.ts new file mode 100644 index 000000000..78bf0b073 --- /dev/null +++ b/packages/hoppscotch-app/helpers/backend/mutations/TeamInvitation.ts @@ -0,0 +1,55 @@ +import { runMutation } from "../GQLClient"; +import { AcceptTeamInvitationDocument, AcceptTeamInvitationMutation, AcceptTeamInvitationMutationVariables, CreateTeamInvitationDocument, CreateTeamInvitationMutation, CreateTeamInvitationMutationVariables, RevokeTeamInvitationDocument, RevokeTeamInvitationMutation, RevokeTeamInvitationMutationVariables, TeamMemberRole } from "../graphql"; +import { Email } from "../types/Email"; +import { pipe } from "fp-ts/function"; +import * as TE from "fp-ts/TaskEither"; + +type CreateTeamInvitationErrors + = "invalid/email" | "team/invalid_id" | "team/member_not_found" | "team_invite/already_member" | "team_invite/member_has_invite" + +type RevokeTeamInvitationErrors + = "team/not_required_role" | "team_invite/no_invite_found" + +type AcceptTeamInvitationErrors + = "team_invite/no_invite_found" | "team_invitee/not_invitee" | "team_invite/already_member" | "team_invite/email_do_not_match" + +export const createTeamInvitation = (inviteeEmail: Email, inviteeRole: TeamMemberRole, teamID: string) => + pipe( + runMutation< + CreateTeamInvitationMutation, + CreateTeamInvitationMutationVariables, + CreateTeamInvitationErrors + >( + CreateTeamInvitationDocument, + { + inviteeEmail, + inviteeRole, + teamID + } + ), + TE.map((x) => x.createTeamInvitation) + ) + +export const revokeTeamInvitation = (inviteID: string) => + runMutation< + RevokeTeamInvitationMutation, + RevokeTeamInvitationMutationVariables, + RevokeTeamInvitationErrors + >( + RevokeTeamInvitationDocument, + { + inviteID + } + ) + +export const acceptTeamInvitation = (inviteID: string) => + runMutation< + AcceptTeamInvitationMutation, + AcceptTeamInvitationMutationVariables, + AcceptTeamInvitationErrors + >( + AcceptTeamInvitationDocument, + { + inviteID + } + ) \ No newline at end of file diff --git a/packages/hoppscotch-app/helpers/backend/types/Email.ts b/packages/hoppscotch-app/helpers/backend/types/Email.ts new file mode 100644 index 000000000..7028308db --- /dev/null +++ b/packages/hoppscotch-app/helpers/backend/types/Email.ts @@ -0,0 +1,15 @@ +import * as t from "io-ts" + +const emailRegex = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/ + +interface EmailBrand { + readonly Email: unique symbol +} + +export const EmailCodec = t.brand( + t.string, + (x): x is t.Branded => emailRegex.test(x), + "Email" +) + +export type Email = t.TypeOf \ No newline at end of file