Merge pull request #1663 from gradido/show-valid-time-of-link-in-email

feat: Show Link Duration in Emails
This commit is contained in:
Moriz Wahl 2022-03-29 20:30:55 +02:00 committed by GitHub
commit eeb5af9249
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 63 additions and 12 deletions

View File

@ -1,4 +1,4 @@
CONFIG_VERSION=v2.2022-03-24
CONFIG_VERSION=v3.2022-03-29
# Server
PORT=4000
@ -42,6 +42,7 @@ EMAIL_SMTP_URL=gmail.com
EMAIL_SMTP_PORT=587
EMAIL_LINK_VERIFICATION=http://localhost/checkEmail/{optin}{code}
EMAIL_LINK_SETPASSWORD=http://localhost/reset/{code}
EMAIL_LINK_FORGOTPASSWORD=http://localhost/forgot-password
EMAIL_CODE_VALID_TIME=1440
EMAIL_CODE_REQUEST_TIME=10

View File

@ -14,7 +14,7 @@ const constants = {
DECAY_START_TIME: new Date('2021-05-13 17:46:31'), // GMT+0
CONFIG_VERSION: {
DEFAULT: 'DEFAULT',
EXPECTED: 'v2.2022-03-24',
EXPECTED: 'v3.2022-03-29',
CURRENT: '',
},
}
@ -70,6 +70,8 @@ const email = {
process.env.EMAIL_LINK_VERIFICATION || 'http://localhost/checkEmail/{optin}{code}',
EMAIL_LINK_SETPASSWORD:
process.env.EMAIL_LINK_SETPASSWORD || 'http://localhost/reset-password/{optin}',
EMAIL_LINK_FORGOTPASSWORD:
process.env.EMAIL_LINK_FORGOTPASSWORD || 'http://localhost/forgot-password',
// time in minutes a optin code is valid
EMAIL_CODE_VALID_TIME: process.env.EMAIL_CODE_VALID_TIME
? parseInt(process.env.EMAIL_CODE_VALID_TIME) || 1440

View File

@ -39,8 +39,9 @@ import Paginated from '@arg/Paginated'
import TransactionLinkFilters from '@arg/TransactionLinkFilters'
import { Order } from '@enum/Order'
import { communityUser } from '@/util/communityUser'
import { checkOptInCode, activationLink } from './UserResolver'
import { checkOptInCode, activationLink, printTimeDuration } from './UserResolver'
import { sendAccountActivationEmail } from '@/mailer/sendAccountActivationEmail'
import CONFIG from '@/config'
// const EMAIL_OPT_IN_REGISTER = 1
// const EMAIL_OPT_UNKNOWN = 3 // elopage?
@ -397,6 +398,7 @@ export class AdminResolver {
firstName: user.firstName,
lastName: user.lastName,
email,
duration: printTimeDuration(CONFIG.EMAIL_CODE_VALID_TIME),
})
/* uncomment this, when you need the activation link on the console

View File

@ -134,6 +134,7 @@ describe('UserResolver', () => {
firstName: 'Peter',
lastName: 'Lustig',
email: 'peter@lustig.de',
duration: expect.any(String),
})
})
})

View File

@ -17,7 +17,7 @@ import { UserSettingRepository } from '@repository/UserSettingRepository'
import { Setting } from '@enum/Setting'
import { OptInType } from '@enum/OptInType'
import { LoginEmailOptIn } from '@entity/LoginEmailOptIn'
import { sendResetPasswordEmail } from '@/mailer/sendResetPasswordEmail'
import { sendResetPasswordEmail as sendResetPasswordEmailMailer } from '@/mailer/sendResetPasswordEmail'
import { sendAccountActivationEmail } from '@/mailer/sendAccountActivationEmail'
import { klicktippSignIn } from '@/apis/KlicktippController'
import { RIGHTS } from '@/auth/RIGHTS'
@ -369,6 +369,7 @@ export class UserResolver {
firstName,
lastName,
email,
duration: printTimeDuration(CONFIG.EMAIL_CODE_VALID_TIME),
})
/* uncomment this, when you need the activation link on the console
@ -403,11 +404,12 @@ export class UserResolver {
optInCode = await checkOptInCode(optInCode, user.id, OptInType.EMAIL_OPT_IN_RESET_PASSWORD)
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const emailSent = await sendResetPasswordEmail({
const emailSent = await sendResetPasswordEmailMailer({
link: activationLink(optInCode),
firstName: user.firstName,
lastName: user.lastName,
email,
duration: printTimeDuration(CONFIG.EMAIL_CODE_VALID_TIME),
})
/* uncomment this, when you need the activation link on the console

View File

@ -15,6 +15,7 @@ describe('sendAccountActivationEmail', () => {
firstName: 'Peter',
lastName: 'Lustig',
email: 'peter@lustig.de',
duration: '23 hours and 30 minutes',
})
})
@ -23,7 +24,9 @@ describe('sendAccountActivationEmail', () => {
to: `Peter Lustig <peter@lustig.de>`,
subject: 'Gradido: E-Mail Überprüfung',
text:
expect.stringContaining('Hallo Peter Lustig') && expect.stringContaining('activationLink'),
expect.stringContaining('Hallo Peter Lustig') &&
expect.stringContaining('activationLink') &&
expect.stringContaining('23 Stunden und 30 Minuten'),
})
})
})

View File

@ -1,15 +1,17 @@
import { sendEMail } from './sendEMail'
import { accountActivation } from './text/accountActivation'
import CONFIG from '@/config'
export const sendAccountActivationEmail = (data: {
link: string
firstName: string
lastName: string
email: string
duration: string
}): Promise<boolean> => {
return sendEMail({
to: `${data.firstName} ${data.lastName} <${data.email}>`,
subject: accountActivation.de.subject,
text: accountActivation.de.text(data),
text: accountActivation.de.text({ ...data, resendLink: CONFIG.EMAIL_LINK_FORGOTPASSWORD }),
})
}

View File

@ -15,6 +15,7 @@ describe('sendResetPasswordEmail', () => {
firstName: 'Peter',
lastName: 'Lustig',
email: 'peter@lustig.de',
duration: '23 hours and 30 minutes',
})
})
@ -22,7 +23,10 @@ describe('sendResetPasswordEmail', () => {
expect(sendEMail).toBeCalledWith({
to: `Peter Lustig <peter@lustig.de>`,
subject: 'Gradido: Passwort zurücksetzen',
text: expect.stringContaining('Hallo Peter Lustig') && expect.stringContaining('resetLink'),
text:
expect.stringContaining('Hallo Peter Lustig') &&
expect.stringContaining('resetLink') &&
expect.stringContaining('23 Stunden und 30 Minuten'),
})
})
})

View File

@ -1,15 +1,17 @@
import { sendEMail } from './sendEMail'
import { resetPassword } from './text/resetPassword'
import CONFIG from '@/config'
export const sendResetPasswordEmail = (data: {
link: string
firstName: string
lastName: string
email: string
duration: string
}): Promise<boolean> => {
return sendEMail({
to: `${data.firstName} ${data.lastName} <${data.email}>`,
subject: resetPassword.de.subject,
text: resetPassword.de.text(data),
text: resetPassword.de.text({ ...data, resendLink: CONFIG.EMAIL_LINK_FORGOTPASSWORD }),
})
}

View File

@ -1,7 +1,14 @@
export const accountActivation = {
de: {
subject: 'Gradido: E-Mail Überprüfung',
text: (data: { link: string; firstName: string; lastName: string; email: string }): string =>
text: (data: {
link: string
firstName: string
lastName: string
email: string
duration: string
resendLink: string
}): string =>
`Hallo ${data.firstName} ${data.lastName},
Deine E-Mail-Adresse wurde soeben bei Gradido registriert.
@ -10,6 +17,15 @@ Klicke bitte auf diesen Link, um die Registrierung abzuschließen und dein Gradi
${data.link}
oder kopiere den obigen Link in dein Browserfenster.
Der Link hat eine Gültigkeit von ${data.duration
.replace('hours', 'Stunden')
.replace('minutes', 'Minuten')
.replace(
' and ',
' und ',
)}. Sollte die Gültigkeit des Links bereits abgelaufen sein, kannst du dir hier einen neuen Link schicken lassen, in dem du deine E-Mail-Adresse eingibst:
${data.resendLink}
Mit freundlichen Grüßen,
dein Gradido-Team`,
},

View File

@ -1,13 +1,29 @@
export const resetPassword = {
de: {
subject: 'Gradido: Passwort zurücksetzen',
text: (data: { link: string; firstName: string; lastName: string; email: string }): string =>
text: (data: {
link: string
firstName: string
lastName: string
email: string
duration: string
resendLink: string
}): string =>
`Hallo ${data.firstName} ${data.lastName},
Du oder jemand anderes hat für dieses Konto ein Zurücksetzen des Passworts angefordert.
Wenn du es warst, klicke bitte auf den Link: ${data.link}
oder kopiere den obigen Link in Dein Browserfenster.
Der Link hat eine Gültigkeit von ${data.duration
.replace('hours', 'Stunden')
.replace('minutes', 'Minuten')
.replace(
' and ',
' und ',
)}. Sollte die Gültigkeit des Links bereits abgelaufen sein, kannst du dir hier einen neuen Link schicken lassen, in dem du deine E-Mail-Adresse eingibst:
${data.resendLink}
Mit freundlichen Grüßen,
dein Gradido-Team`,
},

View File

@ -18,7 +18,7 @@ WEBHOOK_GITHUB_SECRET=secret
WEBHOOK_GITHUB_BRANCH=master
# backend
BACKEND_CONFIG_VERSION=v2.2022-03-24
BACKEND_CONFIG_VERSION=v3.2022-03-29
EMAIL=true
EMAIL_USERNAME=peter@lustig.de