mirror of
https://github.com/SyncrowIOT/backend.git
synced 2025-07-10 15:17:41 +00:00
add OTP email sending functionality and integrate with user authentication flow
This commit is contained in:
@ -19,5 +19,7 @@ export default registerAs(
|
|||||||
process.env.MAILTRAP_DELETE_USER_TEMPLATE_UUID,
|
process.env.MAILTRAP_DELETE_USER_TEMPLATE_UUID,
|
||||||
MAILTRAP_EDIT_USER_TEMPLATE_UUID:
|
MAILTRAP_EDIT_USER_TEMPLATE_UUID:
|
||||||
process.env.MAILTRAP_EDIT_USER_TEMPLATE_UUID,
|
process.env.MAILTRAP_EDIT_USER_TEMPLATE_UUID,
|
||||||
|
MAILTRAP_SEND_OTP_TEMPLATE_UUID:
|
||||||
|
process.env.MAILTRAP_SEND_OTP_TEMPLATE_UUID,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
@ -181,6 +181,49 @@ export class EmailService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
async sendOtpEmailWithTemplate(
|
||||||
|
email: string,
|
||||||
|
emailEditData: any,
|
||||||
|
): Promise<void> {
|
||||||
|
const isProduction = process.env.NODE_ENV === 'production';
|
||||||
|
const API_TOKEN = this.configService.get<string>(
|
||||||
|
'email-config.MAILTRAP_API_TOKEN',
|
||||||
|
);
|
||||||
|
const API_URL = isProduction
|
||||||
|
? SEND_EMAIL_API_URL_PROD
|
||||||
|
: SEND_EMAIL_API_URL_DEV;
|
||||||
|
const TEMPLATE_UUID = this.configService.get<string>(
|
||||||
|
'email-config.MAILTRAP_SEND_OTP_TEMPLATE_UUID',
|
||||||
|
);
|
||||||
|
|
||||||
|
const emailData = {
|
||||||
|
from: {
|
||||||
|
email: this.smtpConfig.sender,
|
||||||
|
},
|
||||||
|
to: [
|
||||||
|
{
|
||||||
|
email: email,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
template_uuid: TEMPLATE_UUID,
|
||||||
|
template_variables: emailEditData,
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
await axios.post(API_URL, emailData, {
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${API_TOKEN}`,
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
throw new HttpException(
|
||||||
|
error.response?.data?.message ||
|
||||||
|
'Error sending email using Mailtrap template',
|
||||||
|
error.response?.status || HttpStatus.INTERNAL_SERVER_ERROR,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
generateUserChangesEmailBody(
|
generateUserChangesEmailBody(
|
||||||
addedSpaceNames: string[],
|
addedSpaceNames: string[],
|
||||||
removedSpaceNames: string[],
|
removedSpaceNames: string[],
|
||||||
|
@ -181,25 +181,25 @@ export class UserAuthService {
|
|||||||
otpCode: string;
|
otpCode: string;
|
||||||
cooldown: number;
|
cooldown: number;
|
||||||
}> {
|
}> {
|
||||||
|
try {
|
||||||
const otpLimiter = new Date();
|
const otpLimiter = new Date();
|
||||||
otpLimiter.setDate(
|
otpLimiter.setDate(
|
||||||
otpLimiter.getDate() - this.configService.get<number>('OTP_LIMITER'),
|
otpLimiter.getDate() - this.configService.get<number>('OTP_LIMITER'),
|
||||||
);
|
);
|
||||||
const userExists = await this.userRepository.exists({
|
const user = await this.userRepository.findOne({
|
||||||
where: {
|
where: {
|
||||||
region: data.regionUuid
|
region: data.regionUuid ? { uuid: data.regionUuid } : undefined,
|
||||||
? {
|
|
||||||
uuid: data.regionUuid,
|
|
||||||
}
|
|
||||||
: undefined,
|
|
||||||
email: data.email,
|
email: data.email,
|
||||||
isUserVerified: data.type === OtpType.PASSWORD ? true : undefined,
|
isUserVerified: data.type === OtpType.PASSWORD ? true : undefined,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
if (!userExists) {
|
if (!user) {
|
||||||
throw new BadRequestException('User not found');
|
throw new BadRequestException('User not found');
|
||||||
}
|
}
|
||||||
await this.otpRepository.softDelete({ email: data.email, type: data.type });
|
await this.otpRepository.softDelete({
|
||||||
|
email: data.email,
|
||||||
|
type: data.type,
|
||||||
|
});
|
||||||
await this.otpRepository.delete({
|
await this.otpRepository.delete({
|
||||||
email: data.email,
|
email: data.email,
|
||||||
type: data.type,
|
type: data.type,
|
||||||
@ -250,10 +250,29 @@ export class UserAuthService {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
cooldown = 30 * Math.pow(2, countOfOtpToReturn - 1);
|
cooldown = 30 * Math.pow(2, countOfOtpToReturn - 1);
|
||||||
const subject = 'OTP send successfully';
|
|
||||||
const message = `Your OTP code is ${otpCode}`;
|
const [otp1, otp2, otp3, otp4, otp5, otp6] = otpCode.split('');
|
||||||
this.emailService.sendEmail(data.email, subject, message);
|
|
||||||
|
await this.emailService.sendOtpEmailWithTemplate(data.email, {
|
||||||
|
name: user.firstName,
|
||||||
|
otp1,
|
||||||
|
otp2,
|
||||||
|
otp3,
|
||||||
|
otp4,
|
||||||
|
otp5,
|
||||||
|
otp6,
|
||||||
|
});
|
||||||
|
|
||||||
return { otpCode, cooldown };
|
return { otpCode, cooldown };
|
||||||
|
} catch (error) {
|
||||||
|
if (error instanceof BadRequestException) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
console.error('OTP generation error:', error);
|
||||||
|
throw new BadRequestException(
|
||||||
|
'An unexpected error occurred while generating the OTP.',
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async verifyOTP(
|
async verifyOTP(
|
||||||
|
Reference in New Issue
Block a user