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}
+
+
+
+
+`;