From 634a7a7b8b8decb22a4392b03255f2193accf75b Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Mon, 13 Nov 2023 17:49:27 +0100 Subject: [PATCH] move EmailBuilder out to separat branch --- backend/src/emails/Email.builder.ts | 235 ------------------ ...lder.test.ts => sendEmailVariants.test.ts} | 186 ++++++++------ .../resolver/ContributionResolver.test.ts | 30 ++- .../graphql/resolver/ContributionResolver.ts | 51 ++-- .../graphql/resolver/TransactionResolver.ts | 36 +-- backend/src/graphql/resolver/UserResolver.ts | 67 ++--- database/entity/Contribution.ts | 2 +- 7 files changed, 224 insertions(+), 383 deletions(-) delete mode 100644 backend/src/emails/Email.builder.ts rename backend/src/emails/{Email.builder.test.ts => sendEmailVariants.test.ts} (81%) diff --git a/backend/src/emails/Email.builder.ts b/backend/src/emails/Email.builder.ts deleted file mode 100644 index 0129e2ed8..000000000 --- a/backend/src/emails/Email.builder.ts +++ /dev/null @@ -1,235 +0,0 @@ -import { Contribution } from '@entity/Contribution' -import { User } from '@entity/User' - -import { CONFIG } from '@/config' -import { LogError } from '@/server/LogError' -import { TimeDuration } from '@/util/time' -import { decimalSeparatorByLanguage, resetInterface } from '@/util/utilities' - -import { sendEmailTranslated } from './sendEmailTranslated' -import { Decimal } from 'decimal.js-light' - -export interface EmailLocals { - firstName: string - lastName: string - locale: string - supportEmail: string - communityURL: string - senderFirstName?: string - senderLastName?: string - senderEmail?: string - contributionMemo?: string - contributionAmount?: string - overviewURL?: string - activationLink?: string - timeDurationObject?: TimeDuration - resendLink?: string - resetLink?: string - transactionMemo?: string - transactionAmount?: string - contributionMemoUpdated?: string - [key: string]: string | TimeDuration | undefined -} - -export enum EmailType { - NONE = 'none', - ACCOUNT_ACTIVATION = 'accountActivation', - ACCOUNT_MULTI_REGISTRATION = 'accountMultiRegistration', - ADDED_CONTRIBUTION_MESSAGE = 'addedContributionMessage', - CONTRIBUTION_CONFIRMED = 'contributionConfirmed', - CONTRIBUTION_DELETED = 'contributionDeleted', - CONTRIBUTION_DENIED = 'contributionDenied', - CONTRIBUTION_CHANGED_BY_MODERATOR = 'contributionChangedByModerator', - RESET_PASSWORD = 'resetPassword', - TRANSACTION_LINK_REDEEMED = 'transactionLinkRedeemed', - TRANSACTION_RECEIVED = 'transactionReceived', -} - -// eslint-disable-next-line @typescript-eslint/no-extraneous-class -export class EmailBuilder { - private receiver: { to: string } - private type: EmailType - private locals: EmailLocals - - // https://refactoring.guru/design-patterns/builder/typescript/example - /** - * A fresh builder instance should contain a blank product object, which is - * used in further assembly. - */ - constructor() { - this.reset() - } - - public reset(): void { - this.receiver.to = '' - this.type = EmailType.NONE - this.locals = resetInterface(this.locals) - } - - protected setLocalsFromConfig(): void { - this.locals.overviewURL = CONFIG.EMAIL_LINK_OVERVIEW - this.locals.supportEmail = CONFIG.COMMUNITY_SUPPORT_MAIL - this.locals.communityURL = CONFIG.COMMUNITY_URL - switch (this.type) { - case EmailType.ACCOUNT_ACTIVATION: - case EmailType.ACCOUNT_MULTI_REGISTRATION: - case EmailType.RESET_PASSWORD: - this.locals.resendLink = CONFIG.EMAIL_LINK_FORGOTPASSWORD - } - } - - protected checkIfFieldsSet(names: string[]): void { - for (const name of names) { - // eslint-disable-next-line security/detect-object-injection - if (!this.locals[name]) { - throw new LogError(`missing field with ${name}`) - } - } - } - - /** - * check if non default fields a set for type - */ - protected checkRequiredFields(): void { - switch (this.type) { - case EmailType.NONE: - throw new LogError('please call setType before to set email type') - case EmailType.ACCOUNT_ACTIVATION: - this.checkIfFieldsSet(['activationLink', 'timeDurationObject', 'resendLink']) - break - case EmailType.ACCOUNT_MULTI_REGISTRATION: - this.checkIfFieldsSet(['resendLink']) - break - // CONTRIBUTION_CONFIRMED has same required fields as ADDED_CONTRIBUTION_MESSAGE plus contributionAmount - case EmailType.CONTRIBUTION_CONFIRMED: - this.checkIfFieldsSet(['contributionAmount']) - // eslint-disable-next-line no-fallthrough - case EmailType.ADDED_CONTRIBUTION_MESSAGE: - case EmailType.CONTRIBUTION_DELETED: - case EmailType.CONTRIBUTION_DENIED: - this.checkIfFieldsSet(['senderFirstName', 'senderLastName', 'contributionMemo']) - break - case EmailType.CONTRIBUTION_CHANGED_BY_MODERATOR: - this.checkIfFieldsSet([ - 'contributionMemoUpdated', - 'senderFirstName', - 'senderLastName', - 'contributionMemo', - ]) - break - case EmailType.RESET_PASSWORD: - this.checkIfFieldsSet(['resetLink', 'timeDurationObject', 'resendLink']) - break - // TRANSACTION_LINK_REDEEMED has same required fields as TRANSACTION_RECEIVED plus transactionMemo - case EmailType.TRANSACTION_LINK_REDEEMED: - this.checkIfFieldsSet(['transactionMemo']) - // eslint-disable-next-line no-fallthrough - case EmailType.TRANSACTION_RECEIVED: - this.checkIfFieldsSet([ - 'senderFirstName', - 'senderLastName', - 'senderEmail', - 'transactionAmount', - ]) - break - } - } - - /** - * Concrete Builders are supposed to provide their own methods for - * retrieving results. That's because various types of builders may create - * entirely different products that don't follow the same interface. - * Therefore, such methods cannot be declared in the base Builder interface - * (at least in a statically typed programming language). - * - * Usually, after returning the end result to the client, a builder instance - * is expected to be ready to start producing another product. That's why - * it's a usual practice to call the reset method at the end of the - * `getProduct` method body. However, this behavior is not mandatory, and - * you can make your builders wait for an explicit reset call from the - * client code before disposing of the previous result. - */ - public sendEmail(): Promise | boolean | null> { - this.setLocalsFromConfig() - // will throw if a field is missing - this.checkRequiredFields() - const result = sendEmailTranslated({ - receiver: this.receiver, - template: this.type.toString(), - locals: this.locals, - }) - this.reset() - return result - } - - public setRecipient(recipient: User): this { - this.receiver.to = `${recipient.firstName} ${recipient.lastName} <${recipient.emailContact.email}>` - this.locals.firstName = recipient.firstName - this.locals.lastName = recipient.lastName - this.locals.locale = recipient.language - return this - } - - public setSender(sender: User): this { - this.locals.senderEmail = sender.emailContact.email - this.locals.senderFirstName = sender.firstName - this.locals.senderLastName = sender.lastName - return this - } - - public setType(type: EmailType): this { - this.type = type - return this - } - - public setResetLink(resetLink: string): this { - this.locals.resentLink = resetLink - return this - } - - public setContribution(contribution: Contribution): this { - this.locals.contributionMemo = contribution.memo - if (!this.locals.locale || this.locals.locale === '') { - throw new LogError('missing locale please call setRecipient before') - } - this.locals.contributionAmount = decimalSeparatorByLanguage( - contribution.amount, - this.locals.locale, - ) - return this - } - - public setUpdatedContributionMemo(updatedMemo: string): this { - this.locals.contributionMemoUpdated = updatedMemo - return this - } - - public setTransaction(amount: Decimal, memo: string): this { - this.setTransactionMemo(memo) - this.setTransactionAmount(amount) - return this - } - - public setTransactionAmount(amount: Decimal): this { - if (!this.locals.locale || this.locals.locale === '') { - throw new LogError('missing locale please call setRecipient before') - } - this.locals.transactionAmount = decimalSeparatorByLanguage(amount, this.locals.locale) - return this - } - - public setTransactionMemo(memo: string): this { - this.locals.transactionMemo = memo - return this - } - - public setActivationLink(activationLink: string): this { - this.locals.activationLink = activationLink - return this - } - - public setTimeDurationObject(timeDurationObject: TimeDuration): this { - this.locals.timeDurationObject = timeDurationObject - return this - } -} diff --git a/backend/src/emails/Email.builder.test.ts b/backend/src/emails/sendEmailVariants.test.ts similarity index 81% rename from backend/src/emails/Email.builder.test.ts rename to backend/src/emails/sendEmailVariants.test.ts index b30e4835b..3340a361d 100644 --- a/backend/src/emails/Email.builder.test.ts +++ b/backend/src/emails/sendEmailVariants.test.ts @@ -2,17 +2,43 @@ /* eslint-disable @typescript-eslint/no-unsafe-return */ /* eslint-disable @typescript-eslint/no-unsafe-call */ /* eslint-disable @typescript-eslint/no-unsafe-assignment */ +import { Connection } from '@dbTools/typeorm' +import { ApolloServerTestClient } from 'apollo-server-testing' import { Decimal } from 'decimal.js-light' +import { testEnvironment } from '@test/helpers' import { logger, i18n as localization } from '@test/testSetup' import { CONFIG } from '@/config' import { sendEmailTranslated } from './sendEmailTranslated' -import { User } from '@entity/User' -import { UserContact } from '@entity/UserContact' -import { Contribution } from '@entity/Contribution' -import { EmailBuilder, EmailType } from './Email.builder' +import { + sendAddedContributionMessageEmail, + sendAccountActivationEmail, + sendAccountMultiRegistrationEmail, + sendContributionConfirmedEmail, + sendContributionDeniedEmail, + sendContributionDeletedEmail, + sendResetPasswordEmail, + sendTransactionLinkRedeemedEmail, + sendTransactionReceivedEmail, +} from './sendEmailVariants' + +let con: Connection +let testEnv: { + mutate: ApolloServerTestClient['mutate'] + query: ApolloServerTestClient['query'] + con: Connection +} + +beforeAll(async () => { + testEnv = await testEnvironment(logger, localization) + con = testEnv.con +}) + +afterAll(async () => { + await con.close() +}) jest.mock('./sendEmailTranslated', () => { const originalModule = jest.requireActual('./sendEmailTranslated') @@ -25,34 +51,18 @@ jest.mock('./sendEmailTranslated', () => { describe('sendEmailVariants', () => { // eslint-disable-next-line @typescript-eslint/no-explicit-any let result: any - const recipientUser = User.create() - recipientUser.firstName = 'Peter' - recipientUser.lastName = 'Lustig' - recipientUser.language = 'en' - const recipientUserContact = UserContact.create() - recipientUserContact.email = 'peter@lustig.de' - recipientUser.emailContact = recipientUserContact - - const senderUser = User.create() - senderUser.firstName = 'Bibi' - senderUser.lastName = 'Bloxberg' - const senderUserContact = UserContact.create() - senderUserContact.email = 'bibi@bloxberg.de' - - const contribution = Contribution.create() - contribution.memo = 'My contribution.' - contribution.amount = new Decimal(23.54) - - const emailBuilder = new EmailBuilder() describe('sendAddedContributionMessageEmail', () => { beforeAll(async () => { - result = await emailBuilder - .setSender(senderUser) - .setRecipient(recipientUser) - .setContribution(contribution) - .setType(EmailType.ADDED_CONTRIBUTION_MESSAGE) - .sendEmail() + result = await sendAddedContributionMessageEmail({ + firstName: 'Peter', + lastName: 'Lustig', + email: 'peter@lustig.de', + language: 'en', + senderFirstName: 'Bibi', + senderLastName: 'Bloxberg', + contributionMemo: 'My contribution.', + }) }) describe('calls "sendEmailTranslated"', () => { @@ -104,13 +114,14 @@ describe('sendEmailVariants', () => { describe('sendAccountActivationEmail', () => { beforeAll(async () => { - result = await emailBuilder - .setRecipient(recipientUser) - .setSender(senderUser) - .setActivationLink('http://localhost/checkEmail/6627633878930542284') - .setTimeDurationObject({ hours: 23, minutes: 30 }) - .setType(EmailType.ACCOUNT_ACTIVATION) - .sendEmail() + result = await sendAccountActivationEmail({ + firstName: 'Peter', + lastName: 'Lustig', + email: 'peter@lustig.de', + language: 'en', + activationLink: 'http://localhost/checkEmail/6627633878930542284', + timeDurationObject: { hours: 23, minutes: 30 }, + }) }) describe('calls "sendEmailTranslated"', () => { @@ -161,10 +172,12 @@ describe('sendEmailVariants', () => { describe('sendAccountMultiRegistrationEmail', () => { beforeAll(async () => { - result = await emailBuilder - .setRecipient(recipientUser) - .setType(EmailType.ACCOUNT_MULTI_REGISTRATION) - .sendEmail() + result = await sendAccountMultiRegistrationEmail({ + firstName: 'Peter', + lastName: 'Lustig', + email: 'peter@lustig.de', + language: 'en', + }) }) describe('calls "sendEmailTranslated"', () => { @@ -213,12 +226,16 @@ describe('sendEmailVariants', () => { describe('sendContributionConfirmedEmail', () => { beforeAll(async () => { - result = await emailBuilder - .setRecipient(recipientUser) - .setSender(senderUser) - .setContribution(contribution) - .setType(EmailType.CONTRIBUTION_CONFIRMED) - .sendEmail() + result = await sendContributionConfirmedEmail({ + firstName: 'Peter', + lastName: 'Lustig', + email: 'peter@lustig.de', + language: 'en', + senderFirstName: 'Bibi', + senderLastName: 'Bloxberg', + contributionMemo: 'My contribution.', + contributionAmount: new Decimal(23.54), + }) }) describe('calls "sendEmailTranslated"', () => { @@ -271,12 +288,15 @@ describe('sendEmailVariants', () => { describe('sendContributionDeniedEmail', () => { beforeAll(async () => { - result = await emailBuilder - .setRecipient(recipientUser) - .setSender(senderUser) - .setContribution(contribution) - .setType(EmailType.CONTRIBUTION_DENIED) - .sendEmail() + result = await sendContributionDeniedEmail({ + firstName: 'Peter', + lastName: 'Lustig', + email: 'peter@lustig.de', + language: 'en', + senderFirstName: 'Bibi', + senderLastName: 'Bloxberg', + contributionMemo: 'My contribution.', + }) }) describe('calls "sendEmailTranslated"', () => { @@ -328,12 +348,15 @@ describe('sendEmailVariants', () => { describe('sendContributionDeletedEmail', () => { beforeAll(async () => { - result = await emailBuilder - .setRecipient(recipientUser) - .setSender(senderUser) - .setContribution(contribution) - .setType(EmailType.CONTRIBUTION_DELETED) - .sendEmail() + result = await sendContributionDeletedEmail({ + firstName: 'Peter', + lastName: 'Lustig', + email: 'peter@lustig.de', + language: 'en', + senderFirstName: 'Bibi', + senderLastName: 'Bloxberg', + contributionMemo: 'My contribution.', + }) }) describe('calls "sendEmailTranslated"', () => { @@ -385,12 +408,14 @@ describe('sendEmailVariants', () => { describe('sendResetPasswordEmail', () => { beforeAll(async () => { - result = await emailBuilder - .setRecipient(recipientUser) - .setResetLink('http://localhost/reset-password/3762660021544901417') - .setTimeDurationObject({ hours: 23, minutes: 30 }) - .setType(EmailType.RESET_PASSWORD) - .sendEmail() + result = await sendResetPasswordEmail({ + firstName: 'Peter', + lastName: 'Lustig', + email: 'peter@lustig.de', + language: 'en', + resetLink: 'http://localhost/reset-password/3762660021544901417', + timeDurationObject: { hours: 23, minutes: 30 }, + }) }) describe('calls "sendEmailTranslated"', () => { @@ -441,12 +466,17 @@ describe('sendEmailVariants', () => { describe('sendTransactionLinkRedeemedEmail', () => { beforeAll(async () => { - result = await emailBuilder - .setRecipient(recipientUser) - .setSender(senderUser) - .setTransaction(new Decimal(17.65), 'You deserve it! 🙏🏼') - .setType(EmailType.TRANSACTION_LINK_REDEEMED) - .sendEmail() + result = await sendTransactionLinkRedeemedEmail({ + firstName: 'Peter', + lastName: 'Lustig', + email: 'peter@lustig.de', + language: 'en', + senderFirstName: 'Bibi', + senderLastName: 'Bloxberg', + senderEmail: 'bibi@bloxberg.de', + transactionMemo: 'You deserve it! 🙏🏼', + transactionAmount: new Decimal(17.65), + }) }) describe('calls "sendEmailTranslated"', () => { @@ -500,12 +530,16 @@ describe('sendEmailVariants', () => { describe('sendTransactionReceivedEmail', () => { beforeAll(async () => { - result = await emailBuilder - .setRecipient(recipientUser) - .setSender(senderUser) - .setTransactionAmount(new Decimal(37.4)) - .setType(EmailType.TRANSACTION_RECEIVED) - .sendEmail() + result = await sendTransactionReceivedEmail({ + firstName: 'Peter', + lastName: 'Lustig', + email: 'peter@lustig.de', + language: 'en', + senderFirstName: 'Bibi', + senderLastName: 'Bloxberg', + senderEmail: 'bibi@bloxberg.de', + transactionAmount: new Decimal(37.4), + }) }) describe('calls "sendEmailTranslated"', () => { diff --git a/backend/src/graphql/resolver/ContributionResolver.test.ts b/backend/src/graphql/resolver/ContributionResolver.test.ts index 8b2bf141e..e6cb485a3 100644 --- a/backend/src/graphql/resolver/ContributionResolver.test.ts +++ b/backend/src/graphql/resolver/ContributionResolver.test.ts @@ -497,6 +497,28 @@ describe('ContributionResolver', () => { }) }) + it('throws an error', async () => { + jest.clearAllMocks() + const { errors: errorObjects } = await mutate({ + mutation: adminUpdateContribution, + variables: { + id: pendingContribution.data.createContribution.id, + amount: 10.0, + memo: 'Test env contribution', + creationDate: new Date().toString(), + }, + }) + expect(errorObjects).toEqual([ + new GraphQLError('An admin is not allowed to update an user contribution'), + ]) + }) + + it('logs the error "An admin is not allowed to update an user contribution"', () => { + expect(logger.error).toBeCalledWith( + 'An admin is not allowed to update an user contribution', + ) + }) + describe('contribution has wrong status', () => { beforeAll(async () => { const contribution = await Contribution.findOneOrFail({ @@ -2802,7 +2824,7 @@ describe('ContributionResolver', () => { } = await query({ query: adminListContributions, }) - + // console.log('17 contributions: %s', JSON.stringify(contributionListObject, null, 2)) expect(contributionListObject.contributionList).toHaveLength(18) expect(contributionListObject).toMatchObject({ contributionCount: 18, @@ -2885,7 +2907,7 @@ describe('ContributionResolver', () => { id: expect.any(Number), lastName: 'Lustig', memo: 'Das war leider zu Viel!', - messagesCount: 1, + messagesCount: 0, status: 'DELETED', }), expect.objectContaining({ @@ -3070,7 +3092,7 @@ describe('ContributionResolver', () => { id: expect.any(Number), lastName: 'Lustig', memo: 'Das war leider zu Viel!', - messagesCount: 1, + messagesCount: 0, status: 'DELETED', }), ]), @@ -3115,7 +3137,7 @@ describe('ContributionResolver', () => { id: expect.any(Number), lastName: 'Lustig', memo: 'Das war leider zu Viel!', - messagesCount: 1, + messagesCount: 0, status: 'DELETED', }), ]), diff --git a/backend/src/graphql/resolver/ContributionResolver.ts b/backend/src/graphql/resolver/ContributionResolver.ts index 775260c84..dc6d10364 100644 --- a/backend/src/graphql/resolver/ContributionResolver.ts +++ b/backend/src/graphql/resolver/ContributionResolver.ts @@ -22,7 +22,6 @@ import { OpenCreation } from '@model/OpenCreation' import { UnconfirmedContribution } from '@model/UnconfirmedContribution' import { RIGHTS } from '@/auth/RIGHTS' -import { EmailBuilder, EmailType } from '@/emails/Email.builder' import { EVENT_CONTRIBUTION_CREATE, EVENT_CONTRIBUTION_DELETE, @@ -46,6 +45,7 @@ import { getUserCreation, validateContribution, getOpenCreations } from './util/ import { findContributions } from './util/findContributions' import { getLastTransaction } from './util/getLastTransaction' import { sendTransactionsToDltConnector } from './util/sendTransactionsToDltConnector' +import { sendContributionConfirmedEmail, sendContributionDeletedEmail, sendContributionDeniedEmail } from '@/emails/sendEmailVariants' @Resolver() export class ContributionResolver { @@ -332,13 +332,15 @@ export class ContributionResolver { contribution, contribution.amount, ) - const emailBuilder = new EmailBuilder() - void emailBuilder - .setRecipient(user) - .setSender(moderator) - .setContribution(contribution) - .setType(EmailType.CONTRIBUTION_DELETED) - .sendEmail() + void sendContributionDeletedEmail({ + firstName: user.firstName, + lastName: user.lastName, + email: user.emailContact.email, + language: user.language, + senderFirstName: moderator.firstName, + senderLastName: moderator.lastName, + contributionMemo: contribution.memo, + }) return !!res } @@ -431,13 +433,16 @@ export class ContributionResolver { void sendTransactionsToDltConnector() logger.info('creation commited successfuly.') - const emailBuilder = new EmailBuilder() - void emailBuilder - .setRecipient(user) - .setSender(moderatorUser) - .setContribution(contribution) - .setType(EmailType.CONTRIBUTION_CONFIRMED) - .sendEmail() + void sendContributionConfirmedEmail({ + firstName: user.firstName, + lastName: user.lastName, + email: user.emailContact.email, + language: user.language, + senderFirstName: moderatorUser.firstName, + senderLastName: moderatorUser.lastName, + contributionMemo: contribution.memo, + contributionAmount: contribution.amount, + }) } catch (e) { await queryRunner.rollbackTransaction() throw new LogError('Creation was not successful', e) @@ -511,13 +516,15 @@ export class ContributionResolver { contributionToUpdate.amount, ) - const emailBuilder = new EmailBuilder() - void emailBuilder - .setRecipient(user) - .setSender(moderator) - .setContribution(contributionToUpdate) - .setType(EmailType.CONTRIBUTION_DENIED) - .sendEmail() + void sendContributionDeniedEmail({ + firstName: user.firstName, + lastName: user.lastName, + email: user.emailContact.email, + language: user.language, + senderFirstName: moderator.firstName, + senderLastName: moderator.lastName, + contributionMemo: contributionToUpdate.memo, + }) return !!res } diff --git a/backend/src/graphql/resolver/TransactionResolver.ts b/backend/src/graphql/resolver/TransactionResolver.ts index ba259e601..8d35708a6 100644 --- a/backend/src/graphql/resolver/TransactionResolver.ts +++ b/backend/src/graphql/resolver/TransactionResolver.ts @@ -22,7 +22,6 @@ import { User } from '@model/User' import { RIGHTS } from '@/auth/RIGHTS' import { CONFIG } from '@/config' -import { EmailBuilder, EmailType } from '@/emails/Email.builder' import { sendTransactionLinkRedeemedEmail, sendTransactionReceivedEmail, @@ -181,21 +180,28 @@ export const executeTransaction = async ( } finally { await queryRunner.release() } - const emailBuilder = new EmailBuilder() - void emailBuilder - .setRecipient(recipient) - .setSender(sender) - .setTransactionAmount(amount) - .setType(EmailType.TRANSACTION_RECEIVED) - .sendEmail() - + void sendTransactionReceivedEmail({ + firstName: recipient.firstName, + lastName: recipient.lastName, + email: recipient.emailContact.email, + language: recipient.language, + senderFirstName: sender.firstName, + senderLastName: sender.lastName, + senderEmail: sender.emailContact.email, + transactionAmount: amount, + }) if (transactionLink) { - void emailBuilder - .setRecipient(sender) - .setSender(recipient) - .setTransaction(amount, memo) - .setType(EmailType.TRANSACTION_LINK_REDEEMED) - .sendEmail() + void sendTransactionLinkRedeemedEmail({ + firstName: sender.firstName, + lastName: sender.lastName, + email: sender.emailContact.email, + language: sender.language, + senderFirstName: recipient.firstName, + senderLastName: recipient.lastName, + senderEmail: recipient.emailContact.email, + transactionAmount: amount, + transactionMemo: memo, + }) } logger.info(`finished executeTransaction successfully`) } finally { diff --git a/backend/src/graphql/resolver/UserResolver.ts b/backend/src/graphql/resolver/UserResolver.ts index 4a7a1fa2f..1f21abbb9 100644 --- a/backend/src/graphql/resolver/UserResolver.ts +++ b/backend/src/graphql/resolver/UserResolver.ts @@ -31,8 +31,11 @@ import { subscribe } from '@/apis/KlicktippController' import { encode } from '@/auth/JWT' import { RIGHTS } from '@/auth/RIGHTS' import { CONFIG } from '@/config' -import { EmailBuilder, EmailType } from '@/emails/Email.builder' -import { sendResetPasswordEmail } from '@/emails/sendEmailVariants' +import { + sendAccountActivationEmail, + sendAccountMultiRegistrationEmail, + sendResetPasswordEmail, +} from '@/emails/sendEmailVariants' import { Event, EventType, @@ -245,12 +248,12 @@ export class UserResolver { } logger.debug('partly faked user', user) - const emailBuilder = new EmailBuilder() - void emailBuilder - .setRecipient(foundUser) // this is the real name of the email owner, but just "firstName" and "lastName" would be the name of the new registrant which shall not be passed to the outside - .setType(EmailType.ACCOUNT_MULTI_REGISTRATION) - .sendEmail() - + void sendAccountMultiRegistrationEmail({ + firstName: foundUser.firstName, // this is the real name of the email owner, but just "firstName" would be the name of the new registrant which shall not be passed to the outside + lastName: foundUser.lastName, // this is the real name of the email owner, but just "lastName" would be the name of the new registrant which shall not be passed to the outside + email, + language: foundUser.language, // use language of the emails owner for sending + }) await EVENT_EMAIL_ACCOUNT_MULTIREGISTRATION(foundUser) logger.info( @@ -329,14 +332,14 @@ export class UserResolver { emailContact.emailVerificationCode.toString(), ).replace(/{code}/g, redeemCode ? '/' + redeemCode : '') - const emailBuilder = new EmailBuilder() - void emailBuilder - .setRecipient(dbUser) - .setActivationLink(activationLink) - .setTimeDurationObject(getTimeDurationObject(CONFIG.EMAIL_CODE_VALID_TIME)) - .setType(EmailType.ACCOUNT_ACTIVATION) - .sendEmail() - + void sendAccountActivationEmail({ + firstName, + lastName, + email, + language, + activationLink, + timeDurationObject: getTimeDurationObject(CONFIG.EMAIL_CODE_VALID_TIME), + }) logger.info(`sendAccountActivationEmail of ${firstName}.${lastName} to ${email}`) await EVENT_EMAIL_CONFIRMATION(dbUser) @@ -391,13 +394,15 @@ export class UserResolver { }) logger.info('optInCode for', email, user.emailContact) - const emailBuilder = new EmailBuilder() - void emailBuilder - .setRecipient(user) - .setResetLink(activationLink(user.emailContact.emailVerificationCode)) - .setTimeDurationObject(getTimeDurationObject(CONFIG.EMAIL_CODE_VALID_TIME)) - .setType(EmailType.RESET_PASSWORD) - .sendEmail() + + void sendResetPasswordEmail({ + firstName: user.firstName, + lastName: user.lastName, + email, + language: user.language, + resetLink: activationLink(user.emailContact.emailVerificationCode), + timeDurationObject: getTimeDurationObject(CONFIG.EMAIL_CODE_VALID_TIME), + }) logger.info(`forgotPassword(${email}) successful...`) await EVENT_EMAIL_FORGOT_PASSWORD(user) @@ -793,13 +798,15 @@ export class UserResolver { user.emailContact.emailResendCount++ await user.emailContact.save() - const emailBuilder = new EmailBuilder() - void emailBuilder - .setRecipient(user) - .setActivationLink(activationLink(user.emailContact.emailVerificationCode)) - .setTimeDurationObject(getTimeDurationObject(CONFIG.EMAIL_CODE_VALID_TIME)) - .setType(EmailType.ACCOUNT_ACTIVATION) - .sendEmail() + // eslint-disable-next-line @typescript-eslint/no-unused-vars + void sendAccountActivationEmail({ + firstName: user.firstName, + lastName: user.lastName, + email, + language: user.language, + activationLink: activationLink(user.emailContact.emailVerificationCode), + timeDurationObject: getTimeDurationObject(CONFIG.EMAIL_CODE_VALID_TIME), + }) await EVENT_EMAIL_ADMIN_CONFIRMATION(user, getUser(context)) diff --git a/database/entity/Contribution.ts b/database/entity/Contribution.ts index ef43b88df..29914255b 100644 --- a/database/entity/Contribution.ts +++ b/database/entity/Contribution.ts @@ -1 +1 @@ -export { Contribution } from './0074-add_updated_by_contribution/Contribution' +export { Contribution } from './0075-add_updated_by_contribution/Contribution'