diff --git a/packages/hoppscotch-backend/src/admin/admin.resolver.ts b/packages/hoppscotch-backend/src/admin/admin.resolver.ts index deeb90dbe..0894fdd4d 100644 --- a/packages/hoppscotch-backend/src/admin/admin.resolver.ts +++ b/packages/hoppscotch-backend/src/admin/admin.resolver.ts @@ -269,6 +269,27 @@ export class AdminResolver { return invitedUser.right; } + @Mutation(() => Boolean, { + description: 'Revoke a user invite by invitee email', + }) + @UseGuards(GqlAuthGuard, GqlAdminGuard) + async revokeUserInvitationByAdmin( + @GqlAdmin() adminUser: Admin, + @Args({ + name: 'inviteeEmail', + description: 'Invite Email', + type: () => ID, + }) + inviteeEmail: string, + ): Promise { + const invite = await this.adminService.revokeUserInvite( + inviteeEmail, + adminUser.uid, + ); + if (E.isLeft(invite)) throwErr(invite.left); + return invite.right; + } + @Mutation(() => Boolean, { description: 'Delete an user account from infra', }) @@ -471,4 +492,14 @@ export class AdminResolver { userInvited(@GqlUser() admin: AuthUser) { return this.pubsub.asyncIterator(`admin/${admin.uid}/invited`); } + + @Subscription(() => InvitedUser, { + description: 'Listen for User Invite Revocation', + resolve: (value) => value, + }) + @SkipThrottle() + @UseGuards(GqlAuthGuard, GqlAdminGuard) + userRevoked(@GqlUser() admin: AuthUser) { + return this.pubsub.asyncIterator(`admin/${admin.uid}/invitation_revoked`); + } } diff --git a/packages/hoppscotch-backend/src/admin/admin.service.ts b/packages/hoppscotch-backend/src/admin/admin.service.ts index 077d46ab3..649bd9c48 100644 --- a/packages/hoppscotch-backend/src/admin/admin.service.ts +++ b/packages/hoppscotch-backend/src/admin/admin.service.ts @@ -13,6 +13,7 @@ import { TEAM_INVITE_ALREADY_MEMBER, TEAM_INVITE_NO_INVITE_FOUND, USER_ALREADY_INVITED, + USER_INVITATION_NOT_FOUND, USER_IS_ADMIN, USER_NOT_FOUND, } from '../errors'; @@ -110,6 +111,35 @@ export class AdminService { return E.right(invitedUser); } + /** + * Revoke infra level user invitation + * @param inviteeEmail Invitee's email + * @param adminUid Admin Uid + * @returns an Either of array of `InvitedUser` object or error string + */ + async revokeUserInvite(inviteeEmail: string, adminUid: string) { + try { + const deletedInvitee = await this.prisma.invitedUsers.delete({ + where: { + inviteeEmail, + }, + }); + + const invitedUser = { + adminEmail: deletedInvitee.adminEmail, + adminUid: deletedInvitee.adminUid, + inviteeEmail: deletedInvitee.inviteeEmail, + invitedOn: deletedInvitee.invitedOn, + }; + + this.pubsub.publish(`admin/${adminUid}/invitation_revoked`, invitedUser); + + return E.right(true); + } catch (error) { + return E.left(USER_INVITATION_NOT_FOUND); + } + } + /** * Fetch the list of invited users by the admin. * @returns an Either of array of `InvitedUser` object or error diff --git a/packages/hoppscotch-backend/src/errors.ts b/packages/hoppscotch-backend/src/errors.ts index 3297be8f8..174a782c8 100644 --- a/packages/hoppscotch-backend/src/errors.ts +++ b/packages/hoppscotch-backend/src/errors.ts @@ -99,6 +99,12 @@ export const USER_IS_OWNER = 'user/is_owner' as const; */ export const USER_IS_ADMIN = 'user/is_admin' as const; +/** + * User invite deletion failure error due to invitation not found + * (AdminService) + */ +export const USER_INVITATION_NOT_FOUND = 'user/invitation_not_found' as const; + /** * Teams not found * (TeamsService) diff --git a/packages/hoppscotch-backend/src/pubsub/topicsDefs.ts b/packages/hoppscotch-backend/src/pubsub/topicsDefs.ts index 49506c67e..f0054cceb 100644 --- a/packages/hoppscotch-backend/src/pubsub/topicsDefs.ts +++ b/packages/hoppscotch-backend/src/pubsub/topicsDefs.ts @@ -31,7 +31,7 @@ import { Shortcode } from 'src/shortcode/shortcode.model'; // A custom message type that defines the topic and the corresponding payload. // For every module that publishes a subscription add its type def and the possible subscription type. export type TopicDef = { - [topic: `admin/${string}/${'invited'}`]: InvitedUser; + [topic: `admin/${string}/${'invited' | 'invitation_revoked'}`]: InvitedUser; [topic: `user/${string}/${'updated' | 'deleted'}`]: User; [topic: `user_settings/${string}/${'created' | 'updated'}`]: UserSettings; [