diff --git a/.env.example b/.env.example index 3fc9868..71a6505 100644 --- a/.env.example +++ b/.env.example @@ -62,6 +62,8 @@ MAILTRAP_DISABLE_TEMPLATE_UUID= MAILTRAP_ENABLE_TEMPLATE_UUID= +MAILTRAP_DELETE_USER_TEMPLATE_UUID= + WEBSITES_ENABLE_APP_SERVICE_STORAGE= PORT= diff --git a/libs/common/src/config/email.config.ts b/libs/common/src/config/email.config.ts index 88e012a..dba9e54 100644 --- a/libs/common/src/config/email.config.ts +++ b/libs/common/src/config/email.config.ts @@ -15,5 +15,7 @@ export default registerAs( process.env.MAILTRAP_INVITATION_TEMPLATE_UUID, MAILTRAP_DISABLE_TEMPLATE_UUID: process.env.MAILTRAP_DISABLE_TEMPLATE_UUID, MAILTRAP_ENABLE_TEMPLATE_UUID: process.env.MAILTRAP_ENABLE_TEMPLATE_UUID, + MAILTRAP_DELETE_USER_TEMPLATE_UUID: + process.env.MAILTRAP_DELETE_USER_TEMPLATE_UUID, }), ); diff --git a/libs/common/src/constants/controller-route.ts b/libs/common/src/constants/controller-route.ts index 2e627e9..67a0085 100644 --- a/libs/common/src/constants/controller-route.ts +++ b/libs/common/src/constants/controller-route.ts @@ -772,6 +772,12 @@ export class ControllerRoute { public static readonly DISABLE_USER_INVITATION_DESCRIPTION = 'This endpoint disables an invitation for a user to assign to role and spaces.'; + public static readonly DELETE_USER_INVITATION_SUMMARY = + 'Delete user invitation'; + + public static readonly DELETE_USER_INVITATION_DESCRIPTION = + 'This endpoint deletes an invitation for a user to assign to role and spaces.'; + public static readonly ACTIVATION_CODE_SUMMARY = 'Activate Invitation Code'; diff --git a/libs/common/src/util/email.service.ts b/libs/common/src/util/email.service.ts index cfdc509..acdcd55 100644 --- a/libs/common/src/util/email.service.ts +++ b/libs/common/src/util/email.service.ts @@ -83,13 +83,12 @@ export class EmailService { ); } } - async sendEmailWithDisableOrEnableTemplate( + async sendEmailWithTemplate( email: string, name: string, isEnable: boolean, + isDelete: boolean, ): Promise { - console.log(isEnable); - const isProduction = process.env.NODE_ENV === 'production'; const API_TOKEN = this.configService.get( 'email-config.MAILTRAP_API_TOKEN', @@ -97,12 +96,16 @@ export class EmailService { const API_URL = isProduction ? SEND_EMAIL_API_URL_PROD : SEND_EMAIL_API_URL_DEV; - const TEMPLATE_UUID = isEnable + + // Determine the template UUID based on the arguments + const templateUuid = isDelete ? this.configService.get( - 'email-config.MAILTRAP_ENABLE_TEMPLATE_UUID', + 'email-config.MAILTRAP_DELETE_USER_TEMPLATE_UUID', ) : this.configService.get( - 'email-config.MAILTRAP_DISABLE_TEMPLATE_UUID', + isEnable + ? 'email-config.MAILTRAP_ENABLE_TEMPLATE_UUID' + : 'email-config.MAILTRAP_DISABLE_TEMPLATE_UUID', ); const emailData = { @@ -111,12 +114,12 @@ export class EmailService { }, to: [ { - email: email, + email, }, ], - template_uuid: TEMPLATE_UUID, + template_uuid: templateUuid, template_variables: { - name: name, + name, }, }; diff --git a/src/invite-user/controllers/invite-user.controller.ts b/src/invite-user/controllers/invite-user.controller.ts index f090bc5..8f65993 100644 --- a/src/invite-user/controllers/invite-user.controller.ts +++ b/src/invite-user/controllers/invite-user.controller.ts @@ -2,6 +2,7 @@ import { InviteUserService } from '../services/invite-user.service'; import { Body, Controller, + Delete, Param, Post, Put, @@ -114,4 +115,17 @@ export class InviteUserController { invitedUserUuid, ); } + @ApiBearerAuth() + @UseGuards(JwtAuthGuard) + @Delete(':invitedUserUuid') + @ApiOperation({ + summary: ControllerRoute.INVITE_USER.ACTIONS.DELETE_USER_INVITATION_SUMMARY, + description: + ControllerRoute.INVITE_USER.ACTIONS.DELETE_USER_INVITATION_DESCRIPTION, + }) + async deleteUserInvitation( + @Param('invitedUserUuid') invitedUserUuid: string, + ): Promise { + return await this.inviteUserService.deleteUserInvitation(invitedUserUuid); + } } diff --git a/src/invite-user/services/invite-user.service.ts b/src/invite-user/services/invite-user.service.ts index e87ea6d..2b5521c 100644 --- a/src/invite-user/services/invite-user.service.ts +++ b/src/invite-user/services/invite-user.service.ts @@ -524,10 +524,11 @@ export class InviteUserService { HttpStatus.BAD_REQUEST, ); } - await this.emailService.sendEmailWithDisableOrEnableTemplate( + await this.emailService.sendEmailWithTemplate( userData.email, userData.firstName, disable, + false, ); await queryRunner.commitTransaction(); @@ -611,4 +612,69 @@ export class InviteUserService { await Promise.allSettled(associatePromises); } + + async deleteUserInvitation( + invitedUserUuid: string, + ): Promise { + const queryRunner = this.dataSource.createQueryRunner(); + await queryRunner.startTransaction(); + + try { + const userData = await this.inviteUserRepository.findOne({ + where: { uuid: invitedUserUuid }, + relations: ['roleType', 'spaces.space', 'project'], + }); + + if (!userData) { + throw new HttpException('User not found', HttpStatus.NOT_FOUND); + } + + if (userData.status === UserStatusEnum.INVITED) { + await this.inviteUserRepository.update( + { uuid: invitedUserUuid }, + { isActive: false }, + ); + } else if (userData.status === UserStatusEnum.ACTIVE) { + const user = await this.userRepository.findOne({ + where: { inviteUser: { uuid: invitedUserUuid } }, + relations: ['userSpaces.space', 'userSpaces.space.community'], + }); + + if (!user) { + throw new HttpException( + 'User account not found', + HttpStatus.NOT_FOUND, + ); + } + + await this.disassociateUserFromSpaces(user, userData.project.uuid); + await this.inviteUserRepository.update( + { uuid: invitedUserUuid }, + { isActive: false }, + ); + await this.userRepository.update( + { uuid: user.uuid }, + { isActive: false }, + ); + } + await this.emailService.sendEmailWithTemplate( + userData.email, + userData.firstName, + false, + true, + ); + await queryRunner.commitTransaction(); + + return new SuccessResponseDto({ + statusCode: HttpStatus.OK, + success: true, + message: 'User invitation deleted successfully', + }); + } catch (error) { + await queryRunner.rollbackTransaction(); + throw error; + } finally { + await queryRunner.release(); + } + } }