mirror of
https://github.com/IT4Change/gradido.git
synced 2026-02-06 09:56:05 +00:00
move EmailBuilder out to separat branch
This commit is contained in:
parent
7a4604f173
commit
634a7a7b8b
@ -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<Record<string, unknown> | 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
|
||||
}
|
||||
}
|
||||
@ -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"', () => {
|
||||
@ -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',
|
||||
}),
|
||||
]),
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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))
|
||||
|
||||
|
||||
@ -1 +1 @@
|
||||
export { Contribution } from './0074-add_updated_by_contribution/Contribution'
|
||||
export { Contribution } from './0075-add_updated_by_contribution/Contribution'
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user