From 6af6358f1bf790ec70e4c083b0d8b8cfaa31fb0d Mon Sep 17 00:00:00 2001 From: Marco Comi <9998393+kin0992@users.noreply.github.com> Date: Wed, 17 Jan 2024 11:17:45 +0100 Subject: [PATCH] [DEV-1299] Handle user update attribute event in CognitoFunctions (#563) --- .changeset/shaggy-windows-swim.md | 5 ++ .../__tests__/custom-message-handler.test.ts | 15 ++++ .../src/custom-message-handler.ts | 17 +++- .../confirmation-update-email-address.ts | 87 +++++++++++++++++++ 4 files changed, 121 insertions(+), 3 deletions(-) create mode 100644 .changeset/shaggy-windows-swim.md create mode 100644 apps/cognito-functions/src/templates/confirmation-update-email-address.ts diff --git a/.changeset/shaggy-windows-swim.md b/.changeset/shaggy-windows-swim.md new file mode 100644 index 000000000..e61e2167e --- /dev/null +++ b/.changeset/shaggy-windows-swim.md @@ -0,0 +1,5 @@ +--- +"cognito-functions": minor +--- + +Handle the event UpdateUserAttribute, triggered when the user updates the email address diff --git a/apps/cognito-functions/src/__tests__/custom-message-handler.test.ts b/apps/cognito-functions/src/__tests__/custom-message-handler.test.ts index 3ce95780b..0ec3d4700 100644 --- a/apps/cognito-functions/src/__tests__/custom-message-handler.test.ts +++ b/apps/cognito-functions/src/__tests__/custom-message-handler.test.ts @@ -2,6 +2,7 @@ import { CustomMessageTriggerEvent } from 'aws-lambda'; import { makeHandler } from '../custom-message-handler'; import { makeConfirmationEmail } from '../templates/confirmation-message'; import { makeConfirmationForgotPasswordEmail } from '../templates/confirmation-forgot-password'; +import { makeConfirmationUpdateEmailAddress } from '../templates/confirmation-update-email-address'; const makeEvent = (): CustomMessageTriggerEvent => ({ version: 'aVersion', @@ -109,4 +110,18 @@ describe('Handler', () => { expect(error).toStrictEqual(new Error('Operation not permitted')); } }); + + it('should reply with verification link on UpdateUserAttribute event', async () => { + const updateUserAttributeEvent: CustomMessageTriggerEvent = { + ...makeEvent(), + triggerSource: 'CustomMessage_UpdateUserAttribute', + }; + const { response } = await makeHandler(env)(updateUserAttributeEvent); + const { userAttributes, codeParameter } = updateUserAttributeEvent.request; + const expected = makeConfirmationUpdateEmailAddress( + `https://${env.domain}/auth/email-confirmation?username=${userAttributes['sub']}&code=${codeParameter}`, + env.domain + ); + expect(response.emailMessage).toStrictEqual(expected); + }); }); diff --git a/apps/cognito-functions/src/custom-message-handler.ts b/apps/cognito-functions/src/custom-message-handler.ts index eb0d89934..d0ae2c184 100644 --- a/apps/cognito-functions/src/custom-message-handler.ts +++ b/apps/cognito-functions/src/custom-message-handler.ts @@ -2,6 +2,7 @@ import * as t from 'io-ts'; import { CustomMessageTriggerEvent } from 'aws-lambda'; import { makeConfirmationEmail } from './templates/confirmation-message'; import { makeConfirmationForgotPasswordEmail } from './templates/confirmation-forgot-password'; +import { makeConfirmationUpdateEmailAddress } from './templates/confirmation-update-email-address'; export const CustomMessageEnv = t.type({ domain: t.string, @@ -13,10 +14,11 @@ export const makeHandler = const username = event.request.userAttributes['sub']; const cognitoUserStatus = event.request.userAttributes['cognito:user_status']; + const eventTrigger = event.triggerSource; if ( - event.triggerSource === 'CustomMessage_SignUp' || - event.triggerSource === 'CustomMessage_ResendCode' + eventTrigger === 'CustomMessage_SignUp' || + eventTrigger === 'CustomMessage_ResendCode' ) { if (cognitoUserStatus === 'CONFIRMED') { // eslint-disable-next-line functional/no-expression-statements @@ -32,7 +34,7 @@ export const makeHandler = const emailSubject = 'Verifica la tua e-mail per PagoPA DevPortal'; const response = { ...event.response, emailMessage, emailSubject }; return { ...event, response }; - } else if (event.triggerSource === 'CustomMessage_ForgotPassword') { + } else if (eventTrigger === 'CustomMessage_ForgotPassword') { const { codeParameter } = event.request; const href = `https://${env.domain}/auth/change-password?username=${username}&code=${codeParameter}`; const emailMessage = makeConfirmationForgotPasswordEmail( @@ -42,6 +44,15 @@ export const makeHandler = const emailSubject = 'Password dimenticata'; const response = { ...event.response, emailMessage, emailSubject }; return { ...event, response }; + } else if (eventTrigger === 'CustomMessage_UpdateUserAttribute') { + // eslint-disable-next-line functional/no-expression-statements + console.log(`User ${username} has requested to update the email address`); + const { codeParameter } = event.request; + const href = `https://${env.domain}/auth/email-confirmation?username=${username}&code=${codeParameter}`; + const emailMessage = makeConfirmationUpdateEmailAddress(href, env.domain); + const emailSubject = 'Verifica nuovo indirizzo email'; + const response = { ...event.response, emailMessage, emailSubject }; + return { ...event, response }; } else { return event; } diff --git a/apps/cognito-functions/src/templates/confirmation-update-email-address.ts b/apps/cognito-functions/src/templates/confirmation-update-email-address.ts new file mode 100644 index 000000000..434b1e121 --- /dev/null +++ b/apps/cognito-functions/src/templates/confirmation-update-email-address.ts @@ -0,0 +1,87 @@ +import { parseMjmlToHtml } from './mjmlParser'; + +const TRANSLATIONS = { + previewText: 'Confermarci la validità di questa e-mail', + title: 'L’ultimo passo per attivare la tua utenza su PagoPA DevPortal', + text: 'Ciao,


Grazie per aver creato un account sul nostro DevPortal!

Non ti resta che confermarci la validità di questa e-mail.', + emailVerification: 'Verifica e-mail', + companyLegalDetails: + 'PagoPA S.p.A. - Società per azioni con socio unico capitale sociale di euro 1,000,000 i.v.Sede legale in Roma, Piazza Colonna 370, CAP 00187Sede operativa in Roma, Via Sardegna 38, CAP 00187N. di iscrizione a Registro Imprese di Roma, CF e P.IVA 15376371009', + wrongRecipient: + 'Ricevi questa e-mail perché hai creato un account su PagoPA DevPortal.
Non sei tu? Ignora o cancella questa e-mail.', + buttonFallbackText: 'Il bottone non funziona? Puoi usare il seguente link:', +}; + +export const makeConfirmationUpdateEmailAddress = ( + confirmationLink: string, + domain: string +) => parseMjmlToHtml(updateEmailAddressMessage(confirmationLink, domain)); + +const updateEmailAddressMessage = ( + confirmationLink: string, + domain: string +): string => ` + + + ${TRANSLATIONS.previewText} + + + .section { + box-sizing: border-box; + padding: 20px; + } + @media (min-width:480px) { + .section { + padding: 32px 40px 32px 40px; + } + } + @media (min-width:960px) { + .section { + padding: 78px 106px 60px 106px; + } + } + @media (min-width:760px) { + .container > table > tbody > tr > td { + padding: 22px 90px 0 0; + } + } + .box-shadow { + border: 1px solid #fefefe; + box-shadow: 0px 0px 45px 0px #0000001A; + } + .link a:link, .link a:visited, .link a:focus, .link a:hover, .link a:active { + text-decoration: none; + color: #0073E6; + } + + + + + + + + + + + + + + + ${TRANSLATIONS.title} + + + ${TRANSLATIONS.text} + + ${TRANSLATIONS.emailVerification} + + ${TRANSLATIONS.buttonFallbackText}
${confirmationLink}
+ + + + ${TRANSLATIONS.wrongRecipient} + ${TRANSLATIONS.companyLegalDetails} +
+
+
+
+`;