diff --git a/app/Controllers/Http/Api/v1/MeController.ts b/app/Controllers/Http/Api/v1/MeController.ts index a2fec0f..a762b35 100644 --- a/app/Controllers/Http/Api/v1/MeController.ts +++ b/app/Controllers/Http/Api/v1/MeController.ts @@ -57,7 +57,6 @@ export default class MeController extends BaseController { * Send confirmation code to new email * PATCH /me/email */ - // eslint-disable-next-line class-methods-use-this public async changeEmail(ctx: HttpContextContract) { const payload = await ctx.request.validate({ schema: schema.create({ @@ -77,7 +76,6 @@ export default class MeController extends BaseController { * Confirm code and update user email * POST /me/email/change/confirm */ - // eslint-disable-next-line class-methods-use-this public async changeEmailConfirm(ctx: HttpContextContract) { const confirmChangeEmailSchema = schema.create({ email: schema.string({}, [rules.email()]), diff --git a/app/Services/MeService.ts b/app/Services/MeService.ts index 8e61f34..a83e8c6 100644 --- a/app/Services/MeService.ts +++ b/app/Services/MeService.ts @@ -98,6 +98,12 @@ export default class MeService { }; } + /** + * Create new confirmation code and send to email + * + * @param email New email + * @returns IResonse + */ public static async changeUserEmail(email: string): Promise { const isConfirmationCodeExist = await Redis.get(`code.change.email:${email}`); @@ -119,16 +125,34 @@ export default class MeService { /** * Create new confirmation code and send to email */ - const EXPIRE_SECONDS = 60; + const EXPIRE_SECONDS = 120; const confirmationCode = Math.floor(1000 + Math.random() * 9000).toString(); - await Mail.send(message => { - message - .from('learn-management-system@sandbox7727dde9c8aa4686a308dbb9c0045acb.mailgun.org') - .to(email) - .subject('Confirmation code.') - .htmlView('emails/change_email_confirm', { confirmationCode }); - }); + /** + * Try send an confirmation code on update email + */ + try { + await Mail.send(message => { + message.to(email).subject('Confirmation code.').htmlView('emails/change_email_confirm', { confirmationCode }); + }); + } catch (error) { + Logger.error(`Email send error: ${error}`); + return { + success: false, + status: StatusCodeEnum.SERVICE_UNAVAILABLE, + message: 'Unable to send confirmation code to this address.', + data: { + error, + }, + error: { + code: 'E_SERVICE_UNAVAILABLE', + }, + }; + } + + /** + * Create confirmation code value in redis store + */ await Redis.set(`code.change.email:${email}`, confirmationCode, 'EX', EXPIRE_SECONDS); return { @@ -141,6 +165,15 @@ export default class MeService { }; } + /** + * Compare confirmation code with payload + * and update user email + * + * @param ctx Http context + * @param email New email + * @param code Confirmation code + * @returns IResponse + */ public static async changeUserEmailConfirm( ctx: HttpContextContract, email: string, @@ -164,6 +197,9 @@ export default class MeService { }; } + /** + * Return error if confirmation code is invalid + */ if (Number.parseInt(confirmationCode, 10) !== code) { return { success: false,