From d794a4dea90f8f8ed11729fc48c91cc5ae056d60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Wed, 1 Jun 2022 15:44:51 +0200 Subject: [PATCH 01/13] Refactor the 'createUser' resolver --- backend/src/graphql/resolver/UserResolver.ts | 163 +++++++++++-------- 1 file changed, 97 insertions(+), 66 deletions(-) diff --git a/backend/src/graphql/resolver/UserResolver.ts b/backend/src/graphql/resolver/UserResolver.ts index 9b42d76b5..146abaaa8 100644 --- a/backend/src/graphql/resolver/UserResolver.ts +++ b/backend/src/graphql/resolver/UserResolver.ts @@ -17,6 +17,7 @@ import { OptInType } from '@enum/OptInType' import { LoginEmailOptIn } from '@entity/LoginEmailOptIn' import { sendResetPasswordEmail as sendResetPasswordEmailMailer } from '@/mailer/sendResetPasswordEmail' import { sendAccountActivationEmail } from '@/mailer/sendAccountActivationEmail' +import { sendAccountMultiRegistrationEmail } from '@/mailer/sendAccountMultiRegistrationEmail' import { klicktippSignIn } from '@/apis/KlicktippController' import { RIGHTS } from '@/auth/RIGHTS' import { hasElopageBuys } from '@/util/hasElopageBuys' @@ -324,88 +325,118 @@ export class UserResolver { // Validate email unique email = email.trim().toLowerCase() + const emailHash = getEmailHash(email) + const passphrase = PassphraseGenerate() // TODO we cannot use repository.count(), since it does not allow to specify if you want to include the soft deletes const userFound = await DbUser.findOne({ email }, { withDeleted: true }) logger.info(`DbUser.findOne(email=${email}) = ${userFound}`) - if (userFound) { - logger.error('User already exists with this email=' + email) - // TODO: this is unsecure, but the current implementation of the login server. This way it can be queried if the user with given EMail is existent. - throw new Error(`User already exists.`) - } - - const passphrase = PassphraseGenerate() - // const keyPair = KeyPairEd25519Create(passphrase) // return pub, priv Key - // const passwordHash = SecretKeyCryptographyCreateKey(email, password) // return short and long hash - // const encryptedPrivkey = SecretKeyCryptographyEncrypt(keyPair[1], passwordHash[1]) - const emailHash = getEmailHash(email) - const dbUser = new DbUser() - dbUser.email = email - dbUser.firstName = firstName - dbUser.lastName = lastName - dbUser.emailHash = emailHash - dbUser.language = language - dbUser.publisherId = publisherId - dbUser.passphrase = passphrase.join(' ') - logger.debug('new dbUser=' + dbUser) - if (redeemCode) { - const transactionLink = await dbTransactionLink.findOne({ code: redeemCode }) - logger.info('redeemCode found transactionLink=' + transactionLink) - if (transactionLink) { - dbUser.referrerId = transactionLink.userId - } - } - // TODO this field has no null allowed unlike the loginServer table - // dbUser.pubKey = Buffer.from(randomBytes(32)) // Buffer.alloc(32, 0) default to 0000... - // dbUser.pubkey = keyPair[0] - // loginUser.password = passwordHash[0].readBigUInt64LE() // using the shorthash - // loginUser.pubKey = keyPair[0] - // loginUser.privKey = encryptedPrivkey - - const queryRunner = getConnection().createQueryRunner() - await queryRunner.connect() - await queryRunner.startTransaction('READ UNCOMMITTED') - try { - await queryRunner.manager.save(dbUser).catch((error) => { - logger.error('Error while saving dbUser', error) - throw new Error('error saving user') - }) - - const emailOptIn = newEmailOptIn(dbUser.id) - await queryRunner.manager.save(emailOptIn).catch((error) => { - logger.error('Error while saving emailOptIn', error) - throw new Error('error saving email opt in') - }) - - const activationLink = CONFIG.EMAIL_LINK_VERIFICATION.replace( - /{optin}/g, - emailOptIn.verificationCode.toString(), - ).replace(/{code}/g, redeemCode ? '/' + redeemCode : '') + if (userFound) { + // Wolle: logger.error('User already exists with this email=' + email) + logger.info('User already exists with this email=' + email) + // TODO: this is unsecure, but the current implementation of the login server. This way it can be queried if the user with given EMail is existent. + // Wolle: throw new Error(`User already exists.`) + // send mail even CC to support + // respond with fake user_id? + dbUser.email = email + dbUser.firstName = firstName + dbUser.lastName = lastName + dbUser.emailHash = emailHash + dbUser.language = language + dbUser.publisherId = publisherId + dbUser.passphrase = passphrase.join(' ') + logger.debug('partly faked dbUser=' + dbUser) // eslint-disable-next-line @typescript-eslint/no-unused-vars - const emailSent = await sendAccountActivationEmail({ - link: activationLink, + const emailSent = await sendAccountMultiRegistrationEmail({ + link: CONFIG.EMAIL_LINK_FORGOTPASSWORD, firstName, lastName, email, - duration: printTimeDuration(CONFIG.EMAIL_CODE_VALID_TIME), }) - logger.info(`sendAccountActivationEmail of ${firstName}.${lastName} to ${email}`) + logger.info(`sendAccountMultiRegistrationEmail of ${firstName}.${lastName} to ${email}`) /* uncomment this, when you need the activation link on the console */ // In case EMails are disabled log the activation link for the user if (!emailSent) { - logger.debug(`Account confirmation link: ${activationLink}`) + logger.debug(`Email not send!`) } + logger.info('createUser() faked and send multi registration mail...') + } else { + // Wolle: const passphrase = PassphraseGenerate() + // const keyPair = KeyPairEd25519Create(passphrase) // return pub, priv Key + // const passwordHash = SecretKeyCryptographyCreateKey(email, password) // return short and long hash + // const encryptedPrivkey = SecretKeyCryptographyEncrypt(keyPair[1], passwordHash[1]) + // Wolle: const emailHash = getEmailHash(email) - await queryRunner.commitTransaction() - } catch (e) { - logger.error(`error during create user with ${e}`) - await queryRunner.rollbackTransaction() - throw e - } finally { - await queryRunner.release() + // Wolle: const dbUser = new DbUser() + // Wolle: what is about id? + dbUser.email = email + dbUser.firstName = firstName + dbUser.lastName = lastName + dbUser.emailHash = emailHash + dbUser.language = language + dbUser.publisherId = publisherId + dbUser.passphrase = passphrase.join(' ') + logger.debug('new dbUser=' + dbUser) + if (redeemCode) { + const transactionLink = await dbTransactionLink.findOne({ code: redeemCode }) + logger.info('redeemCode found transactionLink=' + transactionLink) + if (transactionLink) { + dbUser.referrerId = transactionLink.userId + } + } + // TODO this field has no null allowed unlike the loginServer table + // dbUser.pubKey = Buffer.from(randomBytes(32)) // Buffer.alloc(32, 0) default to 0000... + // dbUser.pubkey = keyPair[0] + // loginUser.password = passwordHash[0].readBigUInt64LE() // using the shorthash + // loginUser.pubKey = keyPair[0] + // loginUser.privKey = encryptedPrivkey + + const queryRunner = getConnection().createQueryRunner() + await queryRunner.connect() + await queryRunner.startTransaction('READ UNCOMMITTED') + try { + await queryRunner.manager.save(dbUser).catch((error) => { + logger.error('Error while saving dbUser', error) + throw new Error('error saving user') + }) + + const emailOptIn = newEmailOptIn(dbUser.id) + await queryRunner.manager.save(emailOptIn).catch((error) => { + logger.error('Error while saving emailOptIn', error) + throw new Error('error saving email opt in') + }) + + const activationLink = CONFIG.EMAIL_LINK_VERIFICATION.replace( + /{optin}/g, + emailOptIn.verificationCode.toString(), + ).replace(/{code}/g, redeemCode ? '/' + redeemCode : '') + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const emailSent = await sendAccountActivationEmail({ + link: activationLink, + firstName, + lastName, + email, + duration: printTimeDuration(CONFIG.EMAIL_CODE_VALID_TIME), + }) + logger.info(`sendAccountActivationEmail of ${firstName}.${lastName} to ${email}`) + /* uncomment this, when you need the activation link on the console */ + // In case EMails are disabled log the activation link for the user + if (!emailSent) { + logger.debug(`Account confirmation link: ${activationLink}`) + } + + await queryRunner.commitTransaction() + } catch (e) { + logger.error(`error during create user with ${e}`) + await queryRunner.rollbackTransaction() + throw e + } finally { + await queryRunner.release() + } + logger.info('createUser() successful...') } - logger.info('createUser() successful...') return new User(dbUser) } From 2785379c12eeebedacf7ebadb86ffae88d235385 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Wed, 1 Jun 2022 15:45:28 +0200 Subject: [PATCH 02/13] Refactor the 'createUser' resolver, forgotten files --- .../sendAccountMultiRegistrationEmail.ts | 19 ++++++++++++++ .../mailer/text/accountMultiRegistration.ts | 26 +++++++++++++++++++ 2 files changed, 45 insertions(+) create mode 100644 backend/src/mailer/sendAccountMultiRegistrationEmail.ts create mode 100644 backend/src/mailer/text/accountMultiRegistration.ts diff --git a/backend/src/mailer/sendAccountMultiRegistrationEmail.ts b/backend/src/mailer/sendAccountMultiRegistrationEmail.ts new file mode 100644 index 000000000..bfbdb391c --- /dev/null +++ b/backend/src/mailer/sendAccountMultiRegistrationEmail.ts @@ -0,0 +1,19 @@ +import { sendEMail } from './sendEMail' +import { accountMultiRegistration } from './text/accountMultiRegistration' +import CONFIG from '@/config' + +export const sendAccountMultiRegistrationEmail = (data: { + link: string + firstName: string + lastName: string + email: string +}): Promise => { + return sendEMail({ + to: `${data.firstName} ${data.lastName} <${data.email}>`, + subject: accountMultiRegistration.de.subject, + text: accountMultiRegistration.de.text({ + ...data, + resendLink: CONFIG.EMAIL_LINK_FORGOTPASSWORD, + }), + }) +} diff --git a/backend/src/mailer/text/accountMultiRegistration.ts b/backend/src/mailer/text/accountMultiRegistration.ts new file mode 100644 index 000000000..58cc53a5f --- /dev/null +++ b/backend/src/mailer/text/accountMultiRegistration.ts @@ -0,0 +1,26 @@ +export const accountMultiRegistration = { + de: { + subject: 'Gradido: Erneuter Registrierungsversuch mit deiner E-Mail', + text: (data: { + link: string // Wolle: support link? + firstName: string + lastName: string + email: string + resendLink: string + }): string => + `Hallo ${data.firstName} ${data.lastName}, + +Deine E-Mail-Adresse wurde soeben erneut benutzt, um bei Gradido ein Konto zu registrieren. +Es existiert jedoch zu deiner E-Mail-Adresse schon ein Konto. + +Klicke bitte auf den folgenden Link, falls zu dein Passwort vergessen haben solltest: +${data.resendLink} +oder kopiere den obigen Link in dein Browserfenster. + +Wenn du nicht derjenige bist, der sich versucht hat erneut zu registrieren, wende dich bitte an unseren support: +${data.link} + +Mit freundlichen Grüßen, +dein Gradido-Team`, + }, +} From c7923e3122ad75d6e51679d3b43007167a645a06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Thu, 2 Jun 2022 15:45:49 +0200 Subject: [PATCH 03/13] Refactor and write the tests of the 'createUser' resolver and the multi registration email --- backend/.env.dist | 2 ++ backend/.env.template | 3 ++ backend/src/config/index.ts | 2 ++ .../src/graphql/resolver/UserResolver.test.ts | 35 ++++++++++++++++--- backend/src/graphql/resolver/UserResolver.ts | 4 ++- .../sendAccountMultiRegistrationEmail.test.ts | 31 ++++++++++++++++ .../sendAccountMultiRegistrationEmail.ts | 3 +- backend/src/mailer/sendEMail.test.ts | 3 ++ backend/src/mailer/sendEMail.ts | 7 +++- .../mailer/text/accountMultiRegistration.ts | 4 +-- deployment/bare_metal/.env.dist | 2 ++ 11 files changed, 87 insertions(+), 9 deletions(-) create mode 100644 backend/src/mailer/sendAccountMultiRegistrationEmail.test.ts diff --git a/backend/.env.dist b/backend/.env.dist index 62b786456..df08c7a66 100644 --- a/backend/.env.dist +++ b/backend/.env.dist @@ -45,6 +45,8 @@ EMAIL_LINK_VERIFICATION=http://localhost/checkEmail/{optin}{code} EMAIL_LINK_SETPASSWORD=http://localhost/reset-password/{optin} EMAIL_LINK_FORGOTPASSWORD=http://localhost/forgot-password EMAIL_LINK_OVERVIEW=http://localhost/overview +EMAIL_LINK_SUPPORT=https://gradido.net/de/contact/ +EMAIL_EMAIL_SUPPORT=support@gradido.net EMAIL_CODE_VALID_TIME=1440 EMAIL_CODE_REQUEST_TIME=10 diff --git a/backend/.env.template b/backend/.env.template index 140ec67e9..091ddf08c 100644 --- a/backend/.env.template +++ b/backend/.env.template @@ -42,7 +42,10 @@ EMAIL_SMTP_URL=$EMAIL_SMTP_URL EMAIL_SMTP_PORT=587 EMAIL_LINK_VERIFICATION=$EMAIL_LINK_VERIFICATION EMAIL_LINK_SETPASSWORD=$EMAIL_LINK_SETPASSWORD +EMAIL_LINK_FORGOTPASSWORD=$EMAIL_LINK_FORGOTPASSWORD EMAIL_LINK_OVERVIEW=$EMAIL_LINK_OVERVIEW +EMAIL_LINK_SUPPORT=$EMAIL_LINK_SUPPORT +EMAIL_EMAIL_SUPPORT=$EMAIL_EMAIL_SUPPORT EMAIL_CODE_VALID_TIME=$EMAIL_CODE_VALID_TIME EMAIL_CODE_REQUEST_TIME=$EMAIL_CODE_REQUEST_TIME diff --git a/backend/src/config/index.ts b/backend/src/config/index.ts index 28318ed6b..7e28d3d08 100644 --- a/backend/src/config/index.ts +++ b/backend/src/config/index.ts @@ -77,6 +77,8 @@ const email = { EMAIL_LINK_FORGOTPASSWORD: process.env.EMAIL_LINK_FORGOTPASSWORD || 'http://localhost/forgot-password', EMAIL_LINK_OVERVIEW: process.env.EMAIL_LINK_OVERVIEW || 'http://localhost/overview', + EMAIL_LINK_SUPPORT: process.env.EMAIL_LINK_SUPPORT || 'https://gradido.net/de/contact/', + EMAIL_EMAIL_SUPPORT: process.env.EMAIL_EMAIL_SUPPORT || 'support@gradido.net', // 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 diff --git a/backend/src/graphql/resolver/UserResolver.test.ts b/backend/src/graphql/resolver/UserResolver.test.ts index 78b630834..a880cf3f9 100644 --- a/backend/src/graphql/resolver/UserResolver.test.ts +++ b/backend/src/graphql/resolver/UserResolver.test.ts @@ -11,6 +11,7 @@ import { LoginEmailOptIn } from '@entity/LoginEmailOptIn' import { User } from '@entity/User' import CONFIG from '@/config' import { sendAccountActivationEmail } from '@/mailer/sendAccountActivationEmail' +import { sendAccountMultiRegistrationEmail } from '@/mailer/sendAccountMultiRegistrationEmail' import { sendResetPasswordEmail } from '@/mailer/sendResetPasswordEmail' import { printTimeDuration, activationLink } from './UserResolver' @@ -25,6 +26,13 @@ jest.mock('@/mailer/sendAccountActivationEmail', () => { } }) +jest.mock('@/mailer/sendAccountMultiRegistrationEmail', () => { + return { + __esModule: true, + sendAccountMultiRegistrationEmail: jest.fn(), + } +}) + jest.mock('@/mailer/sendResetPasswordEmail', () => { return { __esModule: true, @@ -151,14 +159,33 @@ describe('UserResolver', () => { }) describe('email already exists', () => { - it('throws and logs an error', async () => { - const mutation = await mutate({ mutation: createUser, variables }) + let mutation: any + beforeAll(async () => { + mutation = await mutate({ mutation: createUser, variables }) + }) + + it('logs an info', async () => { + expect(logger.info).toBeCalledWith('User already exists with this email=peter@lustig.de') + }) + + it('sends an account multi registration email', () => { + expect(sendAccountMultiRegistrationEmail).toBeCalledWith({ + firstName: 'Peter', + lastName: 'Lustig', + email: 'peter@lustig.de', + }) + }) + + it('results with partly faked user with random "id"', async () => { expect(mutation).toEqual( expect.objectContaining({ - errors: [new GraphQLError('User already exists.')], + data: { + createUser: { + id: expect.any(Number), + }, + }, }), ) - expect(logger.error).toBeCalledWith('User already exists with this email=peter@lustig.de') }) }) diff --git a/backend/src/graphql/resolver/UserResolver.ts b/backend/src/graphql/resolver/UserResolver.ts index 146abaaa8..95c4316ff 100644 --- a/backend/src/graphql/resolver/UserResolver.ts +++ b/backend/src/graphql/resolver/UserResolver.ts @@ -338,6 +338,7 @@ export class UserResolver { // Wolle: throw new Error(`User already exists.`) // send mail even CC to support // respond with fake user_id? + dbUser.id = sodium.randombytes_random() % (2048 * 16) dbUser.email = email dbUser.firstName = firstName dbUser.lastName = lastName @@ -349,7 +350,6 @@ export class UserResolver { // eslint-disable-next-line @typescript-eslint/no-unused-vars const emailSent = await sendAccountMultiRegistrationEmail({ - link: CONFIG.EMAIL_LINK_FORGOTPASSWORD, firstName, lastName, email, @@ -361,6 +361,8 @@ export class UserResolver { logger.debug(`Email not send!`) } logger.info('createUser() faked and send multi registration mail...') + // Wolle: + // console.log('dbUser: ', dbUser) } else { // Wolle: const passphrase = PassphraseGenerate() // const keyPair = KeyPairEd25519Create(passphrase) // return pub, priv Key diff --git a/backend/src/mailer/sendAccountMultiRegistrationEmail.test.ts b/backend/src/mailer/sendAccountMultiRegistrationEmail.test.ts new file mode 100644 index 000000000..67749c966 --- /dev/null +++ b/backend/src/mailer/sendAccountMultiRegistrationEmail.test.ts @@ -0,0 +1,31 @@ +import { sendAccountMultiRegistrationEmail } from './sendAccountMultiRegistrationEmail' +import { sendEMail } from './sendEMail' + +jest.mock('./sendEMail', () => { + return { + __esModule: true, + sendEMail: jest.fn(), + } +}) + +describe('sendAccountMultiRegistrationEmail', () => { + beforeEach(async () => { + await sendAccountMultiRegistrationEmail({ + firstName: 'Peter', + lastName: 'Lustig', + email: 'peter@lustig.de', + }) + }) + + it('calls sendEMail', () => { + expect(sendEMail).toBeCalledWith({ + to: `Peter Lustig `, + cc: 'support@gradido.net', + subject: 'Gradido: Erneuter Registrierungsversuch mit deiner E-Mail', + text: + expect.stringContaining('Hallo Peter Lustig') && + expect.stringContaining('http://localhost/forgot-password') && + expect.stringContaining('https://gradido.net/de/contact/'), + }) + }) +}) diff --git a/backend/src/mailer/sendAccountMultiRegistrationEmail.ts b/backend/src/mailer/sendAccountMultiRegistrationEmail.ts index bfbdb391c..f1420a229 100644 --- a/backend/src/mailer/sendAccountMultiRegistrationEmail.ts +++ b/backend/src/mailer/sendAccountMultiRegistrationEmail.ts @@ -3,17 +3,18 @@ import { accountMultiRegistration } from './text/accountMultiRegistration' import CONFIG from '@/config' export const sendAccountMultiRegistrationEmail = (data: { - link: string firstName: string lastName: string email: string }): Promise => { return sendEMail({ to: `${data.firstName} ${data.lastName} <${data.email}>`, + cc: CONFIG.EMAIL_EMAIL_SUPPORT, subject: accountMultiRegistration.de.subject, text: accountMultiRegistration.de.text({ ...data, resendLink: CONFIG.EMAIL_LINK_FORGOTPASSWORD, + supportLink: CONFIG.EMAIL_LINK_SUPPORT, }), }) } diff --git a/backend/src/mailer/sendEMail.test.ts b/backend/src/mailer/sendEMail.test.ts index 8a13c027d..5746f1ead 100644 --- a/backend/src/mailer/sendEMail.test.ts +++ b/backend/src/mailer/sendEMail.test.ts @@ -31,6 +31,7 @@ describe('sendEMail', () => { beforeEach(async () => { result = await sendEMail({ to: 'receiver@mail.org', + cc: 'support@gradido.net', subject: 'Subject', text: 'Text text text', }) @@ -50,6 +51,7 @@ describe('sendEMail', () => { CONFIG.EMAIL = true result = await sendEMail({ to: 'receiver@mail.org', + cc: 'support@gradido.net', subject: 'Subject', text: 'Text text text', }) @@ -72,6 +74,7 @@ describe('sendEMail', () => { expect((createTransport as jest.Mock).mock.results[0].value.sendMail).toBeCalledWith({ from: `Gradido (nicht antworten) <${CONFIG.EMAIL_SENDER}>`, to: 'receiver@mail.org', + cc: 'support@gradido.net', subject: 'Subject', text: 'Text text text', }) diff --git a/backend/src/mailer/sendEMail.ts b/backend/src/mailer/sendEMail.ts index 640dd7f4c..746daa810 100644 --- a/backend/src/mailer/sendEMail.ts +++ b/backend/src/mailer/sendEMail.ts @@ -5,10 +5,15 @@ import CONFIG from '@/config' export const sendEMail = async (emailDef: { to: string + cc?: string subject: string text: string }): Promise => { - logger.info(`send Email: to=${emailDef.to}, subject=${emailDef.subject}, text=${emailDef.text}`) + logger.info( + `send Email: to=${emailDef.to}` + + (emailDef.cc ? `, cc=${emailDef.cc}` : '') + + `, subject=${emailDef.subject}, text=${emailDef.text}`, + ) if (!CONFIG.EMAIL) { logger.info(`Emails are disabled via config...`) diff --git a/backend/src/mailer/text/accountMultiRegistration.ts b/backend/src/mailer/text/accountMultiRegistration.ts index 58cc53a5f..809ae1419 100644 --- a/backend/src/mailer/text/accountMultiRegistration.ts +++ b/backend/src/mailer/text/accountMultiRegistration.ts @@ -2,11 +2,11 @@ export const accountMultiRegistration = { de: { subject: 'Gradido: Erneuter Registrierungsversuch mit deiner E-Mail', text: (data: { - link: string // Wolle: support link? firstName: string lastName: string email: string resendLink: string + supportLink: string }): string => `Hallo ${data.firstName} ${data.lastName}, @@ -18,7 +18,7 @@ ${data.resendLink} oder kopiere den obigen Link in dein Browserfenster. Wenn du nicht derjenige bist, der sich versucht hat erneut zu registrieren, wende dich bitte an unseren support: -${data.link} +${data.supportLink} Mit freundlichen Grüßen, dein Gradido-Team`, diff --git a/deployment/bare_metal/.env.dist b/deployment/bare_metal/.env.dist index a1751a859..b90ec9ea7 100644 --- a/deployment/bare_metal/.env.dist +++ b/deployment/bare_metal/.env.dist @@ -47,6 +47,8 @@ EMAIL_LINK_VERIFICATION=https://stage1.gradido.net/checkEmail/{optin}{code} EMAIL_LINK_SETPASSWORD=https://stage1.gradido.net/reset-password/{optin} EMAIL_LINK_FORGOTPASSWORD=https://stage1.gradido.net/forgot-password EMAIL_LINK_OVERVIEW=https://stage1.gradido.net/overview +EMAIL_LINK_SUPPORT=https://gradido.net/de/contact/ +EMAIL_EMAIL_SUPPORT=support@gradido.net EMAIL_CODE_VALID_TIME=1440 EMAIL_CODE_REQUEST_TIME=10 From b6fc752f80c4da47674a9dbd7c074d8a4251f86d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Thu, 2 Jun 2022 15:56:20 +0200 Subject: [PATCH 04/13] Remove cc from multi registration email --- backend/.env.dist | 1 - backend/.env.template | 1 - backend/src/config/index.ts | 1 - backend/src/mailer/sendAccountMultiRegistrationEmail.test.ts | 1 - backend/src/mailer/sendAccountMultiRegistrationEmail.ts | 1 - deployment/bare_metal/.env.dist | 1 - 6 files changed, 6 deletions(-) diff --git a/backend/.env.dist b/backend/.env.dist index df08c7a66..2bbc5c9d1 100644 --- a/backend/.env.dist +++ b/backend/.env.dist @@ -46,7 +46,6 @@ EMAIL_LINK_SETPASSWORD=http://localhost/reset-password/{optin} EMAIL_LINK_FORGOTPASSWORD=http://localhost/forgot-password EMAIL_LINK_OVERVIEW=http://localhost/overview EMAIL_LINK_SUPPORT=https://gradido.net/de/contact/ -EMAIL_EMAIL_SUPPORT=support@gradido.net EMAIL_CODE_VALID_TIME=1440 EMAIL_CODE_REQUEST_TIME=10 diff --git a/backend/.env.template b/backend/.env.template index 091ddf08c..07dd0edc2 100644 --- a/backend/.env.template +++ b/backend/.env.template @@ -45,7 +45,6 @@ EMAIL_LINK_SETPASSWORD=$EMAIL_LINK_SETPASSWORD EMAIL_LINK_FORGOTPASSWORD=$EMAIL_LINK_FORGOTPASSWORD EMAIL_LINK_OVERVIEW=$EMAIL_LINK_OVERVIEW EMAIL_LINK_SUPPORT=$EMAIL_LINK_SUPPORT -EMAIL_EMAIL_SUPPORT=$EMAIL_EMAIL_SUPPORT EMAIL_CODE_VALID_TIME=$EMAIL_CODE_VALID_TIME EMAIL_CODE_REQUEST_TIME=$EMAIL_CODE_REQUEST_TIME diff --git a/backend/src/config/index.ts b/backend/src/config/index.ts index 7e28d3d08..28fd0fb80 100644 --- a/backend/src/config/index.ts +++ b/backend/src/config/index.ts @@ -78,7 +78,6 @@ const email = { process.env.EMAIL_LINK_FORGOTPASSWORD || 'http://localhost/forgot-password', EMAIL_LINK_OVERVIEW: process.env.EMAIL_LINK_OVERVIEW || 'http://localhost/overview', EMAIL_LINK_SUPPORT: process.env.EMAIL_LINK_SUPPORT || 'https://gradido.net/de/contact/', - EMAIL_EMAIL_SUPPORT: process.env.EMAIL_EMAIL_SUPPORT || 'support@gradido.net', // 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 diff --git a/backend/src/mailer/sendAccountMultiRegistrationEmail.test.ts b/backend/src/mailer/sendAccountMultiRegistrationEmail.test.ts index 67749c966..ba71b8b37 100644 --- a/backend/src/mailer/sendAccountMultiRegistrationEmail.test.ts +++ b/backend/src/mailer/sendAccountMultiRegistrationEmail.test.ts @@ -20,7 +20,6 @@ describe('sendAccountMultiRegistrationEmail', () => { it('calls sendEMail', () => { expect(sendEMail).toBeCalledWith({ to: `Peter Lustig `, - cc: 'support@gradido.net', subject: 'Gradido: Erneuter Registrierungsversuch mit deiner E-Mail', text: expect.stringContaining('Hallo Peter Lustig') && diff --git a/backend/src/mailer/sendAccountMultiRegistrationEmail.ts b/backend/src/mailer/sendAccountMultiRegistrationEmail.ts index f1420a229..8999e9e2b 100644 --- a/backend/src/mailer/sendAccountMultiRegistrationEmail.ts +++ b/backend/src/mailer/sendAccountMultiRegistrationEmail.ts @@ -9,7 +9,6 @@ export const sendAccountMultiRegistrationEmail = (data: { }): Promise => { return sendEMail({ to: `${data.firstName} ${data.lastName} <${data.email}>`, - cc: CONFIG.EMAIL_EMAIL_SUPPORT, subject: accountMultiRegistration.de.subject, text: accountMultiRegistration.de.text({ ...data, diff --git a/deployment/bare_metal/.env.dist b/deployment/bare_metal/.env.dist index b90ec9ea7..ac31a8524 100644 --- a/deployment/bare_metal/.env.dist +++ b/deployment/bare_metal/.env.dist @@ -48,7 +48,6 @@ EMAIL_LINK_SETPASSWORD=https://stage1.gradido.net/reset-password/{optin} EMAIL_LINK_FORGOTPASSWORD=https://stage1.gradido.net/forgot-password EMAIL_LINK_OVERVIEW=https://stage1.gradido.net/overview EMAIL_LINK_SUPPORT=https://gradido.net/de/contact/ -EMAIL_EMAIL_SUPPORT=support@gradido.net EMAIL_CODE_VALID_TIME=1440 EMAIL_CODE_REQUEST_TIME=10 From 9b90f52cbaa87a1316116ac33e9204cb613caff3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Thu, 2 Jun 2022 16:00:09 +0200 Subject: [PATCH 05/13] Cleanup --- backend/src/graphql/resolver/UserResolver.ts | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/backend/src/graphql/resolver/UserResolver.ts b/backend/src/graphql/resolver/UserResolver.ts index 95c4316ff..df610384d 100644 --- a/backend/src/graphql/resolver/UserResolver.ts +++ b/backend/src/graphql/resolver/UserResolver.ts @@ -332,12 +332,8 @@ export class UserResolver { logger.info(`DbUser.findOne(email=${email}) = ${userFound}`) const dbUser = new DbUser() if (userFound) { - // Wolle: logger.error('User already exists with this email=' + email) logger.info('User already exists with this email=' + email) // TODO: this is unsecure, but the current implementation of the login server. This way it can be queried if the user with given EMail is existent. - // Wolle: throw new Error(`User already exists.`) - // send mail even CC to support - // respond with fake user_id? dbUser.id = sodium.randombytes_random() % (2048 * 16) dbUser.email = email dbUser.firstName = firstName @@ -361,17 +357,11 @@ export class UserResolver { logger.debug(`Email not send!`) } logger.info('createUser() faked and send multi registration mail...') - // Wolle: - // console.log('dbUser: ', dbUser) } else { - // Wolle: const passphrase = PassphraseGenerate() // const keyPair = KeyPairEd25519Create(passphrase) // return pub, priv Key // const passwordHash = SecretKeyCryptographyCreateKey(email, password) // return short and long hash // const encryptedPrivkey = SecretKeyCryptographyEncrypt(keyPair[1], passwordHash[1]) - // Wolle: const emailHash = getEmailHash(email) - // Wolle: const dbUser = new DbUser() - // Wolle: what is about id? dbUser.email = email dbUser.firstName = firstName dbUser.lastName = lastName From ffd11cb75573e126349e623c4079473d933085ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Thu, 2 Jun 2022 16:12:52 +0200 Subject: [PATCH 06/13] Remove error 'User already exists.' from Register.Vue --- frontend/src/locales/de.json | 3 +-- frontend/src/locales/en.json | 3 +-- frontend/src/pages/Register.spec.js | 18 ------------------ frontend/src/pages/Register.vue | 11 +---------- 4 files changed, 3 insertions(+), 32 deletions(-) diff --git a/frontend/src/locales/de.json b/frontend/src/locales/de.json index dd76dddf5..2316ec61b 100644 --- a/frontend/src/locales/de.json +++ b/frontend/src/locales/de.json @@ -54,8 +54,7 @@ "no-transactionlist": "Es gab leider einen Fehler. Es wurden keine Transaktionen vom Server übermittelt.", "no-user": "Kein Benutzer mit diesen Anmeldedaten.", "session-expired": "Die Sitzung wurde aus Sicherheitsgründen beendet.", - "unknown-error": "Unbekanter Fehler: ", - "user-already-exists": "Ein Benutzer mit diesen Daten existiert bereits." + "unknown-error": "Unbekanter Fehler: " }, "followUs": "folge uns:", "footer": { diff --git a/frontend/src/locales/en.json b/frontend/src/locales/en.json index e5ebbcb2c..0f1cb8d3a 100644 --- a/frontend/src/locales/en.json +++ b/frontend/src/locales/en.json @@ -54,8 +54,7 @@ "no-transactionlist": "Unfortunately, there was an error. No transactions have been sent from the server.", "no-user": "No user with this credentials.", "session-expired": "The session was closed for security reasons.", - "unknown-error": "Unknown error: ", - "user-already-exists": "A user with this data already exists." + "unknown-error": "Unknown error: " }, "followUs": "follow us:", "footer": { diff --git a/frontend/src/pages/Register.spec.js b/frontend/src/pages/Register.spec.js index a9415de87..91e945c6a 100644 --- a/frontend/src/pages/Register.spec.js +++ b/frontend/src/pages/Register.spec.js @@ -139,24 +139,6 @@ describe('Register', () => { await flushPromises() } - describe('server sends back error "User already exists."', () => { - beforeEach(async () => { - await createError('GraphQL error: User already exists.') - }) - - it('shows no error message on the page', () => { - // don't show any error on the page! against boots - expect(wrapper.vm.showPageMessage).toBe(false) - expect(wrapper.find('.test-message-headline').exists()).toBe(false) - expect(wrapper.find('.test-message-subtitle').exists()).toBe(false) - expect(wrapper.find('.test-message-button').exists()).toBe(false) - }) - - it('toasts the error message', () => { - expect(toastErrorSpy).toBeCalledWith('error.user-already-exists') - }) - }) - describe('server sends back error "Unknown error"', () => { beforeEach(async () => { await createError(' – Unknown error.') diff --git a/frontend/src/pages/Register.vue b/frontend/src/pages/Register.vue index f1bfad6d9..b2d9e6e71 100755 --- a/frontend/src/pages/Register.vue +++ b/frontend/src/pages/Register.vue @@ -142,16 +142,7 @@ export default { this.showPageMessage = true }) .catch((error) => { - let errorMessage - switch (error.message) { - case 'GraphQL error: User already exists.': - errorMessage = this.$t('error.user-already-exists') - break - default: - errorMessage = this.$t('error.unknown-error') + error.message - break - } - this.toastError(errorMessage) + this.toastError(this.$t('error.unknown-error') + error.message) }) }, }, From 37149b40fac753721de4f2b73faa769fc74b696a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Thu, 2 Jun 2022 16:15:11 +0200 Subject: [PATCH 07/13] Remove method 'commitStorePublisherId' from Register.Vue --- frontend/src/pages/Register.vue | 3 --- 1 file changed, 3 deletions(-) diff --git a/frontend/src/pages/Register.vue b/frontend/src/pages/Register.vue index b2d9e6e71..0ae316ae9 100755 --- a/frontend/src/pages/Register.vue +++ b/frontend/src/pages/Register.vue @@ -122,9 +122,6 @@ export default { getValidationState({ dirty, validated, valid = null }) { return dirty || validated ? valid : null }, - commitStorePublisherId(val) { - this.$store.commit('publisherId', val) - }, async onSubmit() { this.$apollo .mutate({ From c5f7673cf291a45e7bff7504b74ba69356c396a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Tue, 14 Jun 2022 10:35:34 +0200 Subject: [PATCH 08/13] Change following the review suggestions of Alex and Moriz --- backend/.env.dist | 1 - backend/.env.template | 1 - backend/src/config/index.ts | 1 - .../src/graphql/resolver/UserResolver.test.ts | 2 +- backend/src/graphql/resolver/UserResolver.ts | 28 +++++++++++-------- .../sendAccountMultiRegistrationEmail.test.ts | 3 +- .../sendAccountMultiRegistrationEmail.ts | 1 - .../mailer/text/accountMultiRegistration.ts | 5 ++-- deployment/bare_metal/.env.dist | 1 - 9 files changed, 22 insertions(+), 21 deletions(-) diff --git a/backend/.env.dist b/backend/.env.dist index 2bbc5c9d1..62b786456 100644 --- a/backend/.env.dist +++ b/backend/.env.dist @@ -45,7 +45,6 @@ EMAIL_LINK_VERIFICATION=http://localhost/checkEmail/{optin}{code} EMAIL_LINK_SETPASSWORD=http://localhost/reset-password/{optin} EMAIL_LINK_FORGOTPASSWORD=http://localhost/forgot-password EMAIL_LINK_OVERVIEW=http://localhost/overview -EMAIL_LINK_SUPPORT=https://gradido.net/de/contact/ EMAIL_CODE_VALID_TIME=1440 EMAIL_CODE_REQUEST_TIME=10 diff --git a/backend/.env.template b/backend/.env.template index 07dd0edc2..60e2676f8 100644 --- a/backend/.env.template +++ b/backend/.env.template @@ -44,7 +44,6 @@ EMAIL_LINK_VERIFICATION=$EMAIL_LINK_VERIFICATION EMAIL_LINK_SETPASSWORD=$EMAIL_LINK_SETPASSWORD EMAIL_LINK_FORGOTPASSWORD=$EMAIL_LINK_FORGOTPASSWORD EMAIL_LINK_OVERVIEW=$EMAIL_LINK_OVERVIEW -EMAIL_LINK_SUPPORT=$EMAIL_LINK_SUPPORT EMAIL_CODE_VALID_TIME=$EMAIL_CODE_VALID_TIME EMAIL_CODE_REQUEST_TIME=$EMAIL_CODE_REQUEST_TIME diff --git a/backend/src/config/index.ts b/backend/src/config/index.ts index 100206b48..5736e6d8a 100644 --- a/backend/src/config/index.ts +++ b/backend/src/config/index.ts @@ -77,7 +77,6 @@ const email = { EMAIL_LINK_FORGOTPASSWORD: process.env.EMAIL_LINK_FORGOTPASSWORD || 'http://localhost/forgot-password', EMAIL_LINK_OVERVIEW: process.env.EMAIL_LINK_OVERVIEW || 'http://localhost/overview', - EMAIL_LINK_SUPPORT: process.env.EMAIL_LINK_SUPPORT || 'https://gradido.net/de/contact/', // 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 diff --git a/backend/src/graphql/resolver/UserResolver.test.ts b/backend/src/graphql/resolver/UserResolver.test.ts index a880cf3f9..970011857 100644 --- a/backend/src/graphql/resolver/UserResolver.test.ts +++ b/backend/src/graphql/resolver/UserResolver.test.ts @@ -159,7 +159,7 @@ describe('UserResolver', () => { }) describe('email already exists', () => { - let mutation: any + let mutation: User beforeAll(async () => { mutation = await mutate({ mutation: createUser, variables }) }) diff --git a/backend/src/graphql/resolver/UserResolver.ts b/backend/src/graphql/resolver/UserResolver.ts index df610384d..a5962526c 100644 --- a/backend/src/graphql/resolver/UserResolver.ts +++ b/backend/src/graphql/resolver/UserResolver.ts @@ -7,6 +7,7 @@ import { getConnection } from '@dbTools/typeorm' import CONFIG from '@/config' import { User } from '@model/User' import { User as DbUser } from '@entity/User' +import { communityDbUser } from '@/util/communityUser' import { TransactionLink as dbTransactionLink } from '@entity/TransactionLink' import { encode } from '@/auth/JWT' import CreateUserArgs from '@arg/CreateUserArgs' @@ -330,19 +331,20 @@ export class UserResolver { // TODO we cannot use repository.count(), since it does not allow to specify if you want to include the soft deletes const userFound = await DbUser.findOne({ email }, { withDeleted: true }) logger.info(`DbUser.findOne(email=${email}) = ${userFound}`) - const dbUser = new DbUser() + if (userFound) { logger.info('User already exists with this email=' + email) // TODO: this is unsecure, but the current implementation of the login server. This way it can be queried if the user with given EMail is existent. - dbUser.id = sodium.randombytes_random() % (2048 * 16) - dbUser.email = email - dbUser.firstName = firstName - dbUser.lastName = lastName - dbUser.emailHash = emailHash - dbUser.language = language - dbUser.publisherId = publisherId - dbUser.passphrase = passphrase.join(' ') - logger.debug('partly faked dbUser=' + dbUser) + + const user = new User(communityDbUser) + user.id = sodium.randombytes_random() % (2048 * 16) + user.email = email + user.emailChecked = true + user.firstName = firstName + user.lastName = lastName + user.language = language + user.publisherId = publisherId + logger.debug('partly faked user=' + user) // eslint-disable-next-line @typescript-eslint/no-unused-vars const emailSent = await sendAccountMultiRegistrationEmail({ @@ -357,11 +359,14 @@ export class UserResolver { logger.debug(`Email not send!`) } logger.info('createUser() faked and send multi registration mail...') + + return user } else { // const keyPair = KeyPairEd25519Create(passphrase) // return pub, priv Key // const passwordHash = SecretKeyCryptographyCreateKey(email, password) // return short and long hash // const encryptedPrivkey = SecretKeyCryptographyEncrypt(keyPair[1], passwordHash[1]) + const dbUser = new DbUser() dbUser.email = email dbUser.firstName = firstName dbUser.lastName = lastName @@ -428,8 +433,9 @@ export class UserResolver { await queryRunner.release() } logger.info('createUser() successful...') + + return new User(dbUser) } - return new User(dbUser) } @Authorized([RIGHTS.SEND_RESET_PASSWORD_EMAIL]) diff --git a/backend/src/mailer/sendAccountMultiRegistrationEmail.test.ts b/backend/src/mailer/sendAccountMultiRegistrationEmail.test.ts index ba71b8b37..bb37a196e 100644 --- a/backend/src/mailer/sendAccountMultiRegistrationEmail.test.ts +++ b/backend/src/mailer/sendAccountMultiRegistrationEmail.test.ts @@ -1,3 +1,4 @@ +import CONFIG from '@/config' import { sendAccountMultiRegistrationEmail } from './sendAccountMultiRegistrationEmail' import { sendEMail } from './sendEMail' @@ -23,7 +24,7 @@ describe('sendAccountMultiRegistrationEmail', () => { subject: 'Gradido: Erneuter Registrierungsversuch mit deiner E-Mail', text: expect.stringContaining('Hallo Peter Lustig') && - expect.stringContaining('http://localhost/forgot-password') && + expect.stringContaining(CONFIG.EMAIL_LINK_FORGOTPASSWORD) && expect.stringContaining('https://gradido.net/de/contact/'), }) }) diff --git a/backend/src/mailer/sendAccountMultiRegistrationEmail.ts b/backend/src/mailer/sendAccountMultiRegistrationEmail.ts index 8999e9e2b..18928770b 100644 --- a/backend/src/mailer/sendAccountMultiRegistrationEmail.ts +++ b/backend/src/mailer/sendAccountMultiRegistrationEmail.ts @@ -13,7 +13,6 @@ export const sendAccountMultiRegistrationEmail = (data: { text: accountMultiRegistration.de.text({ ...data, resendLink: CONFIG.EMAIL_LINK_FORGOTPASSWORD, - supportLink: CONFIG.EMAIL_LINK_SUPPORT, }), }) } diff --git a/backend/src/mailer/text/accountMultiRegistration.ts b/backend/src/mailer/text/accountMultiRegistration.ts index 809ae1419..c5b55bac5 100644 --- a/backend/src/mailer/text/accountMultiRegistration.ts +++ b/backend/src/mailer/text/accountMultiRegistration.ts @@ -6,19 +6,18 @@ export const accountMultiRegistration = { lastName: string email: string resendLink: string - supportLink: string }): string => `Hallo ${data.firstName} ${data.lastName}, Deine E-Mail-Adresse wurde soeben erneut benutzt, um bei Gradido ein Konto zu registrieren. Es existiert jedoch zu deiner E-Mail-Adresse schon ein Konto. -Klicke bitte auf den folgenden Link, falls zu dein Passwort vergessen haben solltest: +Klicke bitte auf den folgenden Link, falls du dein Passwort vergessen haben solltest: ${data.resendLink} oder kopiere den obigen Link in dein Browserfenster. Wenn du nicht derjenige bist, der sich versucht hat erneut zu registrieren, wende dich bitte an unseren support: -${data.supportLink} +https://gradido.net/de/contact/ Mit freundlichen Grüßen, dein Gradido-Team`, diff --git a/deployment/bare_metal/.env.dist b/deployment/bare_metal/.env.dist index ac31a8524..a1751a859 100644 --- a/deployment/bare_metal/.env.dist +++ b/deployment/bare_metal/.env.dist @@ -47,7 +47,6 @@ EMAIL_LINK_VERIFICATION=https://stage1.gradido.net/checkEmail/{optin}{code} EMAIL_LINK_SETPASSWORD=https://stage1.gradido.net/reset-password/{optin} EMAIL_LINK_FORGOTPASSWORD=https://stage1.gradido.net/forgot-password EMAIL_LINK_OVERVIEW=https://stage1.gradido.net/overview -EMAIL_LINK_SUPPORT=https://gradido.net/de/contact/ EMAIL_CODE_VALID_TIME=1440 EMAIL_CODE_REQUEST_TIME=10 From 09d99a72f4d53e33723e168130093148fd776c34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Tue, 14 Jun 2022 10:41:57 +0200 Subject: [PATCH 09/13] Add todo comment --- backend/src/graphql/resolver/UserResolver.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/graphql/resolver/UserResolver.ts b/backend/src/graphql/resolver/UserResolver.ts index a5962526c..ba00799bb 100644 --- a/backend/src/graphql/resolver/UserResolver.ts +++ b/backend/src/graphql/resolver/UserResolver.ts @@ -337,7 +337,7 @@ export class UserResolver { // TODO: this is unsecure, but the current implementation of the login server. This way it can be queried if the user with given EMail is existent. const user = new User(communityDbUser) - user.id = sodium.randombytes_random() % (2048 * 16) + user.id = sodium.randombytes_random() % (2048 * 16) // TODO: for a better faking derive id from email so that it will be always the same id when the same email comes in? user.email = email user.emailChecked = true user.firstName = firstName From d12ab5a307439babb33dc4eb852c82338182d017 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Tue, 14 Jun 2022 10:46:50 +0200 Subject: [PATCH 10/13] Set backend coverage to '69' --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b7000100e..ee2df4150 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -528,7 +528,7 @@ jobs: report_name: Coverage Backend type: lcov result_path: ./backend/coverage/lcov.info - min_coverage: 68 + min_coverage: 69 token: ${{ github.token }} ########################################################################## From 2bdf98bc15c9bf62c2ae74b58a1bc043d268a7a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Wed, 15 Jun 2022 07:38:09 +0200 Subject: [PATCH 11/13] Update frontend/src/locales/de.json Co-authored-by: Alexander Friedland --- frontend/src/locales/de.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/locales/de.json b/frontend/src/locales/de.json index 2316ec61b..ed5021207 100644 --- a/frontend/src/locales/de.json +++ b/frontend/src/locales/de.json @@ -54,7 +54,7 @@ "no-transactionlist": "Es gab leider einen Fehler. Es wurden keine Transaktionen vom Server übermittelt.", "no-user": "Kein Benutzer mit diesen Anmeldedaten.", "session-expired": "Die Sitzung wurde aus Sicherheitsgründen beendet.", - "unknown-error": "Unbekanter Fehler: " + "unknown-error": "Unbekannter Fehler: " }, "followUs": "folge uns:", "footer": { From 91959aea287bc1391de67eda5f29faed01da7cee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Mon, 20 Jun 2022 16:08:35 +0200 Subject: [PATCH 12/13] Fulfill Moriz suggestions --- backend/.env.dist | 2 +- backend/src/config/index.ts | 2 +- backend/src/graphql/resolver/UserResolver.ts | 173 +++++++++---------- deployment/bare_metal/.env.dist | 2 +- 4 files changed, 89 insertions(+), 90 deletions(-) diff --git a/backend/.env.dist b/backend/.env.dist index 41eeeaf58..db01cf4cc 100644 --- a/backend/.env.dist +++ b/backend/.env.dist @@ -1,4 +1,4 @@ -CONFIG_VERSION=v7.2022-06-15 +CONFIG_VERSION=v8.2022-06-20 # Server PORT=4000 diff --git a/backend/src/config/index.ts b/backend/src/config/index.ts index 4e6dd8099..a9cae6770 100644 --- a/backend/src/config/index.ts +++ b/backend/src/config/index.ts @@ -17,7 +17,7 @@ const constants = { LOG_LEVEL: process.env.LOG_LEVEL || 'info', CONFIG_VERSION: { DEFAULT: 'DEFAULT', - EXPECTED: 'v7.2022-06-15', + EXPECTED: 'v8.2022-06-20', CURRENT: '', }, } diff --git a/backend/src/graphql/resolver/UserResolver.ts b/backend/src/graphql/resolver/UserResolver.ts index 1ce7d668f..0bde22ae6 100644 --- a/backend/src/graphql/resolver/UserResolver.ts +++ b/backend/src/graphql/resolver/UserResolver.ts @@ -338,7 +338,6 @@ export class UserResolver { const user = new User(communityDbUser) user.id = sodium.randombytes_random() % (2048 * 16) // TODO: for a better faking derive id from email so that it will be always the same id when the same email comes in? user.email = email - user.emailChecked = true user.firstName = firstName user.lastName = lastName user.language = language @@ -360,93 +359,93 @@ export class UserResolver { logger.info('createUser() faked and send multi registration mail...') return user - } else { - const passphrase = PassphraseGenerate() - // const keyPair = KeyPairEd25519Create(passphrase) // return pub, priv Key - // const passwordHash = SecretKeyCryptographyCreateKey(email, password) // return short and long hash - // const encryptedPrivkey = SecretKeyCryptographyEncrypt(keyPair[1], passwordHash[1]) - const emailHash = getEmailHash(email) - - const dbUser = new DbUser() - dbUser.email = email - dbUser.firstName = firstName - dbUser.lastName = lastName - dbUser.emailHash = emailHash - dbUser.language = language - dbUser.publisherId = publisherId - dbUser.passphrase = passphrase.join(' ') - logger.debug('new dbUser=' + dbUser) - if (redeemCode) { - if (redeemCode.match(/^CL-/)) { - const contributionLink = await dbContributionLink.findOne({ - code: redeemCode.replace('CL-', ''), - }) - logger.info('redeemCode found contributionLink=' + contributionLink) - if (contributionLink) { - dbUser.contributionLinkId = contributionLink.id - } - } else { - const transactionLink = await dbTransactionLink.findOne({ code: redeemCode }) - logger.info('redeemCode found transactionLink=' + transactionLink) - if (transactionLink) { - dbUser.referrerId = transactionLink.userId - } - } - } - // TODO this field has no null allowed unlike the loginServer table - // dbUser.pubKey = Buffer.from(randomBytes(32)) // Buffer.alloc(32, 0) default to 0000... - // dbUser.pubkey = keyPair[0] - // loginUser.password = passwordHash[0].readBigUInt64LE() // using the shorthash - // loginUser.pubKey = keyPair[0] - // loginUser.privKey = encryptedPrivkey - - const queryRunner = getConnection().createQueryRunner() - await queryRunner.connect() - await queryRunner.startTransaction('READ UNCOMMITTED') - try { - await queryRunner.manager.save(dbUser).catch((error) => { - logger.error('Error while saving dbUser', error) - throw new Error('error saving user') - }) - - const emailOptIn = newEmailOptIn(dbUser.id) - await queryRunner.manager.save(emailOptIn).catch((error) => { - logger.error('Error while saving emailOptIn', error) - throw new Error('error saving email opt in') - }) - - const activationLink = CONFIG.EMAIL_LINK_VERIFICATION.replace( - /{optin}/g, - emailOptIn.verificationCode.toString(), - ).replace(/{code}/g, redeemCode ? '/' + redeemCode : '') - - // eslint-disable-next-line @typescript-eslint/no-unused-vars - const emailSent = await sendAccountActivationEmail({ - link: activationLink, - firstName, - lastName, - email, - duration: printTimeDuration(CONFIG.EMAIL_CODE_VALID_TIME), - }) - logger.info(`sendAccountActivationEmail of ${firstName}.${lastName} to ${email}`) - /* uncomment this, when you need the activation link on the console */ - // In case EMails are disabled log the activation link for the user - if (!emailSent) { - logger.debug(`Account confirmation link: ${activationLink}`) - } - - await queryRunner.commitTransaction() - } catch (e) { - logger.error(`error during create user with ${e}`) - await queryRunner.rollbackTransaction() - throw e - } finally { - await queryRunner.release() - } - logger.info('createUser() successful...') - - return new User(dbUser) } + + const passphrase = PassphraseGenerate() + // const keyPair = KeyPairEd25519Create(passphrase) // return pub, priv Key + // const passwordHash = SecretKeyCryptographyCreateKey(email, password) // return short and long hash + // const encryptedPrivkey = SecretKeyCryptographyEncrypt(keyPair[1], passwordHash[1]) + const emailHash = getEmailHash(email) + + const dbUser = new DbUser() + dbUser.email = email + dbUser.firstName = firstName + dbUser.lastName = lastName + dbUser.emailHash = emailHash + dbUser.language = language + dbUser.publisherId = publisherId + dbUser.passphrase = passphrase.join(' ') + logger.debug('new dbUser=' + dbUser) + if (redeemCode) { + if (redeemCode.match(/^CL-/)) { + const contributionLink = await dbContributionLink.findOne({ + code: redeemCode.replace('CL-', ''), + }) + logger.info('redeemCode found contributionLink=' + contributionLink) + if (contributionLink) { + dbUser.contributionLinkId = contributionLink.id + } + } else { + const transactionLink = await dbTransactionLink.findOne({ code: redeemCode }) + logger.info('redeemCode found transactionLink=' + transactionLink) + if (transactionLink) { + dbUser.referrerId = transactionLink.userId + } + } + } + // TODO this field has no null allowed unlike the loginServer table + // dbUser.pubKey = Buffer.from(randomBytes(32)) // Buffer.alloc(32, 0) default to 0000... + // dbUser.pubkey = keyPair[0] + // loginUser.password = passwordHash[0].readBigUInt64LE() // using the shorthash + // loginUser.pubKey = keyPair[0] + // loginUser.privKey = encryptedPrivkey + + const queryRunner = getConnection().createQueryRunner() + await queryRunner.connect() + await queryRunner.startTransaction('READ UNCOMMITTED') + try { + await queryRunner.manager.save(dbUser).catch((error) => { + logger.error('Error while saving dbUser', error) + throw new Error('error saving user') + }) + + const emailOptIn = newEmailOptIn(dbUser.id) + await queryRunner.manager.save(emailOptIn).catch((error) => { + logger.error('Error while saving emailOptIn', error) + throw new Error('error saving email opt in') + }) + + const activationLink = CONFIG.EMAIL_LINK_VERIFICATION.replace( + /{optin}/g, + emailOptIn.verificationCode.toString(), + ).replace(/{code}/g, redeemCode ? '/' + redeemCode : '') + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const emailSent = await sendAccountActivationEmail({ + link: activationLink, + firstName, + lastName, + email, + duration: printTimeDuration(CONFIG.EMAIL_CODE_VALID_TIME), + }) + logger.info(`sendAccountActivationEmail of ${firstName}.${lastName} to ${email}`) + /* uncomment this, when you need the activation link on the console */ + // In case EMails are disabled log the activation link for the user + if (!emailSent) { + logger.debug(`Account confirmation link: ${activationLink}`) + } + + await queryRunner.commitTransaction() + } catch (e) { + logger.error(`error during create user with ${e}`) + await queryRunner.rollbackTransaction() + throw e + } finally { + await queryRunner.release() + } + logger.info('createUser() successful...') + + return new User(dbUser) } @Authorized([RIGHTS.SEND_RESET_PASSWORD_EMAIL]) diff --git a/deployment/bare_metal/.env.dist b/deployment/bare_metal/.env.dist index d9e159382..67c153661 100644 --- a/deployment/bare_metal/.env.dist +++ b/deployment/bare_metal/.env.dist @@ -26,7 +26,7 @@ COMMUNITY_REDEEM_CONTRIBUTION_URL=https://stage1.gradido.net/redeem/CL-{code} COMMUNITY_DESCRIPTION="Gradido Development Stage1 Test Community" # backend -BACKEND_CONFIG_VERSION=v7.2022-06-15 +BACKEND_CONFIG_VERSION=v8.2022-06-20 JWT_EXPIRES_IN=30m GDT_API_URL=https://gdt.gradido.net From 548a6c75826ca90f47ca5004af5c8d8f9563f77f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Mon, 20 Jun 2022 16:59:19 +0200 Subject: [PATCH 13/13] Decrement backend coverage minimum to 68 --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ee2df4150..b7000100e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -528,7 +528,7 @@ jobs: report_name: Coverage Backend type: lcov result_path: ./backend/coverage/lcov.info - min_coverage: 69 + min_coverage: 68 token: ${{ github.token }} ##########################################################################