feat: revokeUserInviteByAdmin mutation added and invitedUsers query updated

This commit is contained in:
Mir Arif Hasan
2024-01-09 18:11:43 +06:00
parent cd371fc9d4
commit b9c36faaa4
5 changed files with 99 additions and 7 deletions

View File

@@ -269,6 +269,25 @@ export class AdminResolver {
return invitedUser.right; return invitedUser.right;
} }
@Mutation(() => Boolean, { description: 'Revoke a user invite by ID' })
@UseGuards(GqlAuthGuard, GqlAdminGuard)
async revokeUserInviteByAdmin(
@GqlAdmin() adminUser: Admin,
@Args({
name: 'inviteeEmail',
description: 'Invite Email',
type: () => ID,
})
inviteeEmail: string,
): Promise<boolean> {
const invite = await this.adminService.revokeUserInvite(
inviteeEmail,
adminUser,
);
if (E.isLeft(invite)) throwErr(invite.left);
return invite.right;
}
@Mutation(() => Boolean, { @Mutation(() => Boolean, {
description: 'Delete an user account from infra', description: 'Delete an user account from infra',
}) })
@@ -471,4 +490,14 @@ export class AdminResolver {
userInvited(@GqlUser() admin: AuthUser) { userInvited(@GqlUser() admin: AuthUser) {
return this.pubsub.asyncIterator(`admin/${admin.uid}/invited`); return this.pubsub.asyncIterator(`admin/${admin.uid}/invited`);
} }
@Subscription(() => InvitedUser, {
description: 'Listen for User Revocation',
resolve: (value) => value,
})
@SkipThrottle()
@UseGuards(GqlAuthGuard, GqlAdminGuard)
userRevoked(@GqlUser() admin: AuthUser) {
return this.pubsub.asyncIterator(`admin/${admin.uid}/revoked`);
}
} }

View File

@@ -11,10 +11,10 @@ import {
INVALID_EMAIL, INVALID_EMAIL,
ONLY_ONE_ADMIN_ACCOUNT, ONLY_ONE_ADMIN_ACCOUNT,
TEAM_INVITE_ALREADY_MEMBER, TEAM_INVITE_ALREADY_MEMBER,
TEAM_INVITE_NO_INVITE_FOUND,
USER_ALREADY_INVITED, USER_ALREADY_INVITED,
USER_IS_ADMIN, USER_IS_ADMIN,
USER_NOT_FOUND, USER_NOT_FOUND,
USER_NOT_INVITED,
} from '../errors'; } from '../errors';
import { MailerService } from '../mailer/mailer.service'; import { MailerService } from '../mailer/mailer.service';
import { InvitedUser } from './invited-user.model'; import { InvitedUser } from './invited-user.model';
@@ -26,6 +26,7 @@ import { TeamInvitationService } from '../team-invitation/team-invitation.servic
import { TeamMemberRole } from '../team/team.model'; import { TeamMemberRole } from '../team/team.model';
import { ShortcodeService } from 'src/shortcode/shortcode.service'; import { ShortcodeService } from 'src/shortcode/shortcode.service';
import { ConfigService } from '@nestjs/config'; import { ConfigService } from '@nestjs/config';
import { Admin } from './admin.model';
@Injectable() @Injectable()
export class AdminService { export class AdminService {
@@ -110,18 +111,69 @@ export class AdminService {
return E.right(invitedUser); return E.right(invitedUser);
} }
/**
* Revoke the invitation of a user to join infra.
* @param inviteeEmail Invitee's email
* @param adminUser Admin object
* @returns an Either of array of `InvitedUser` object or error string
*/
async revokeUserInvite(inviteeEmail: string, adminUser: Admin) {
try {
const deletedInvitee = await this.prisma.invitedUsers.delete({
where: {
inviteeEmail,
},
});
const invitedUser = <InvitedUser>{
adminEmail: deletedInvitee.adminEmail,
adminUid: deletedInvitee.adminUid,
inviteeEmail: deletedInvitee.inviteeEmail,
invitedOn: deletedInvitee.invitedOn,
};
this.pubsub.publish(`admin/${adminUser.uid}/revoked`, invitedUser);
return E.right(true);
} catch (error) {
return E.left(USER_NOT_INVITED);
}
}
/** /**
* Fetch the list of invited users by the admin. * Fetch the list of invited users by the admin.
* @returns an Either of array of `InvitedUser` object or error * @returns an Either of array of `InvitedUser` object or error
*/ */
async fetchInvitedUsers() { async fetchInvitedUsers() {
const invitedUsers = await this.prisma.invitedUsers.findMany(); const dbInvitedUsers = await this.prisma.invitedUsers.findMany();
const users: InvitedUser[] = invitedUsers.map( const invitationAcceptedUsers = await this.prisma.user.findMany({
(user) => <InvitedUser>{ ...user }, where: {
); email: {
in: dbInvitedUsers.map((user) => user.inviteeEmail),
},
},
});
return users; let invitedUsers: InvitedUser[] = [];
dbInvitedUsers.forEach((dbInvitedUser) => {
const isUserAccepts = invitationAcceptedUsers.find(
(user) => user.email === dbInvitedUser.inviteeEmail,
);
const invitedUser: InvitedUser = {
adminEmail: dbInvitedUser.adminEmail,
adminUid: dbInvitedUser.adminUid,
inviteeEmail: dbInvitedUser.inviteeEmail,
invitedOn: dbInvitedUser.invitedOn,
isInvitationAccepted: isUserAccepts ? true : false,
};
invitedUsers.push(invitedUser);
});
return invitedUsers;
} }
/** /**

View File

@@ -21,4 +21,10 @@ export class InvitedUser {
description: 'Date when the user invitation was sent', description: 'Date when the user invitation was sent',
}) })
invitedOn: Date; invitedOn: Date;
@Field({
description: 'Boolean status if invitation was accepted or not',
defaultValue: false,
})
isInvitationAccepted: boolean;
} }

View File

@@ -65,6 +65,11 @@ export const USER_FB_DOCUMENT_DELETION_FAILED =
*/ */
export const USER_NOT_FOUND = 'user/not_found' as const; export const USER_NOT_FOUND = 'user/not_found' as const;
/**
* User is not invited by admin
*/
export const USER_NOT_INVITED = 'admin/user_not_invited' as const;
/** /**
* User is already invited by admin * User is already invited by admin
*/ */

View File

@@ -31,7 +31,7 @@ import { Shortcode } from 'src/shortcode/shortcode.model';
// A custom message type that defines the topic and the corresponding payload. // 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. // For every module that publishes a subscription add its type def and the possible subscription type.
export type TopicDef = { export type TopicDef = {
[topic: `admin/${string}/${'invited'}`]: InvitedUser; [topic: `admin/${string}/${'invited' | 'revoked'}`]: InvitedUser;
[topic: `user/${string}/${'updated' | 'deleted'}`]: User; [topic: `user/${string}/${'updated' | 'deleted'}`]: User;
[topic: `user_settings/${string}/${'created' | 'updated'}`]: UserSettings; [topic: `user_settings/${string}/${'created' | 'updated'}`]: UserSettings;
[ [