diff --git a/backend/src/graphql/resolver/AdminResolver.test.ts b/backend/src/graphql/resolver/AdminResolver.test.ts index f0ce064b4..75c672bd5 100644 --- a/backend/src/graphql/resolver/AdminResolver.test.ts +++ b/backend/src/graphql/resolver/AdminResolver.test.ts @@ -40,6 +40,7 @@ import Decimal from 'decimal.js-light' import { Contribution } from '@entity/Contribution' import { Transaction as DbTransaction } from '@entity/Transaction' import { ContributionLink as DbContributionLink } from '@entity/ContributionLink' +import { sendContributionConfirmedEmail } from '@/mailer/sendContributionConfirmedEmail' // mock account activation email to avoid console spam jest.mock('@/mailer/sendAccountActivationEmail', () => { @@ -49,6 +50,14 @@ jest.mock('@/mailer/sendAccountActivationEmail', () => { } }) +// mock account activation email to avoid console spam +jest.mock('@/mailer/sendContributionConfirmedEmail', () => { + return { + __esModule: true, + sendContributionConfirmedEmail: jest.fn(), + } +}) + let mutate: any, query: any, con: any let testEnv: any @@ -1450,6 +1459,20 @@ describe('AdminResolver', () => { expect(transaction[0].linkedUserId).toEqual(null) expect(transaction[0].typeId).toEqual(1) }) + + it('calls sendContributionConfirmedEmail', async () => { + expect(sendContributionConfirmedEmail).toBeCalledWith( + expect.objectContaining({ + contributionMemo: 'Herzlich Willkommen bei Gradido liebe Bibi!', + overviewURL: 'http://localhost/overview', + recipientEmail: 'bibi@bloxberg.de', + recipientFirstName: 'Bibi', + recipientLastName: 'Bloxberg', + senderFirstName: 'Peter', + senderLastName: 'Lustig', + }), + ) + }) }) describe('confirm two creations one after the other quickly', () => { diff --git a/backend/src/graphql/resolver/AdminResolver.ts b/backend/src/graphql/resolver/AdminResolver.ts index ac3936e4f..d71ffc72c 100644 --- a/backend/src/graphql/resolver/AdminResolver.ts +++ b/backend/src/graphql/resolver/AdminResolver.ts @@ -66,6 +66,8 @@ import { ContributionMessage as DbContributionMessage } from '@entity/Contributi import ContributionMessageArgs from '@arg/ContributionMessageArgs' import { ContributionMessageType } from '@enum/MessageType' import { ContributionMessage } from '@model/ContributionMessage' +import { sendContributionConfirmedEmail } from '@/mailer/sendContributionConfirmedEmail' +import { sendAddedContributionMessageEmail } from '@/mailer/sendAddedContributionMessageEmail' // const EMAIL_OPT_IN_REGISTER = 1 // const EMAIL_OPT_UNKNOWN = 3 // elopage? @@ -470,6 +472,16 @@ export class AdminResolver { await queryRunner.commitTransaction() logger.info('creation commited successfuly.') + sendContributionConfirmedEmail({ + senderFirstName: moderatorUser.firstName, + senderLastName: moderatorUser.lastName, + recipientFirstName: user.firstName, + recipientLastName: user.lastName, + recipientEmail: user.email, + contributionMemo: contribution.memo, + contributionAmount: contribution.amount, + overviewURL: CONFIG.EMAIL_LINK_OVERVIEW, + }) } catch (e) { await queryRunner.rollbackTransaction() logger.error(`Creation was not successful: ${e}`) @@ -713,7 +725,10 @@ export class AdminResolver { await queryRunner.startTransaction('READ UNCOMMITTED') const contributionMessage = DbContributionMessage.create() try { - const contribution = await Contribution.findOne({ id: contributionId }) + const contribution = await Contribution.findOne({ + where: { id: contributionId }, + relations: ['user'], + }) if (!contribution) { throw new Error('Contribution not found') } @@ -737,6 +752,18 @@ export class AdminResolver { await queryRunner.manager.update(Contribution, { id: contributionId }, contribution) } await queryRunner.commitTransaction() + + await sendAddedContributionMessageEmail({ + senderFirstName: user.firstName, + senderLastName: user.lastName, + recipientFirstName: contribution.user.firstName, + recipientLastName: contribution.user.lastName, + recipientEmail: contribution.user.email, + senderEmail: user.email, + contributionMemo: contribution.memo, + message, + overviewURL: CONFIG.EMAIL_LINK_OVERVIEW, + }) } catch (e) { await queryRunner.rollbackTransaction() logger.error(`ContributionMessage was not successful: ${e}`) diff --git a/backend/src/graphql/resolver/ContributionMessageResolver.test.ts b/backend/src/graphql/resolver/ContributionMessageResolver.test.ts index c0e330750..40e9e2ace 100644 --- a/backend/src/graphql/resolver/ContributionMessageResolver.test.ts +++ b/backend/src/graphql/resolver/ContributionMessageResolver.test.ts @@ -12,6 +12,14 @@ import { listContributionMessages, login } from '@/seeds/graphql/queries' import { userFactory } from '@/seeds/factory/user' import { bibiBloxberg } from '@/seeds/users/bibi-bloxberg' import { peterLustig } from '@/seeds/users/peter-lustig' +import { sendAddedContributionMessageEmail } from '@/mailer/sendAddedContributionMessageEmail' + +jest.mock('@/mailer/sendAddedContributionMessageEmail', () => { + return { + __esModule: true, + sendAddedContributionMessageEmail: jest.fn(), + } +}) let mutate: any, query: any, con: any let testEnv: any @@ -151,6 +159,20 @@ describe('ContributionMessageResolver', () => { }), ) }) + + it('calls sendAddedContributionMessageEmail', async () => { + expect(sendAddedContributionMessageEmail).toBeCalledWith({ + senderFirstName: 'Peter', + senderLastName: 'Lustig', + recipientFirstName: 'Bibi', + recipientLastName: 'Bloxberg', + recipientEmail: 'bibi@bloxberg.de', + senderEmail: 'peter@lustig.de', + contributionMemo: 'Test env contribution', + message: 'Admin Test', + overviewURL: 'http://localhost/overview', + }) + }) }) }) }) diff --git a/backend/src/graphql/resolver/TransactionResolver.ts b/backend/src/graphql/resolver/TransactionResolver.ts index bc062a1f4..1d8748f58 100644 --- a/backend/src/graphql/resolver/TransactionResolver.ts +++ b/backend/src/graphql/resolver/TransactionResolver.ts @@ -8,7 +8,10 @@ import { Context, getUser } from '@/server/context' import { Resolver, Query, Args, Authorized, Ctx, Mutation } from 'type-graphql' import { getCustomRepository, getConnection } from '@dbTools/typeorm' -import { sendTransactionReceivedEmail } from '@/mailer/sendTransactionReceivedEmail' +import { + sendTransactionLinkRedeemedEmail, + sendTransactionReceivedEmail, +} from '@/mailer/sendTransactionReceivedEmail' import { Transaction } from '@model/Transaction' import { TransactionList } from '@model/TransactionList' @@ -154,6 +157,19 @@ export const executeTransaction = async ( memo, overviewURL: CONFIG.EMAIL_LINK_OVERVIEW, }) + if (transactionLink) { + await sendTransactionLinkRedeemedEmail({ + senderFirstName: recipient.firstName, + senderLastName: recipient.lastName, + recipientFirstName: sender.firstName, + recipientLastName: sender.lastName, + email: sender.email, + senderEmail: recipient.email, + amount, + memo, + overviewURL: CONFIG.EMAIL_LINK_OVERVIEW, + }) + } logger.info(`finished executeTransaction successfully`) return true } diff --git a/backend/src/graphql/resolver/UserResolver.test.ts b/backend/src/graphql/resolver/UserResolver.test.ts index 36bae56de..13715e088 100644 --- a/backend/src/graphql/resolver/UserResolver.test.ts +++ b/backend/src/graphql/resolver/UserResolver.test.ts @@ -19,6 +19,8 @@ import { contributionLinkFactory } from '@/seeds/factory/contributionLink' import { ContributionLink } from '@model/ContributionLink' // import { TransactionLink } from '@entity/TransactionLink' +import { EventProtocolType } from '@/event/EventProtocolType' +import { EventProtocol } from '@entity/EventProtocol' import { logger } from '@test/testSetup' import { validate as validateUUID, version as versionUUID } from 'uuid' import { peterLustig } from '@/seeds/users/peter-lustig' @@ -169,6 +171,15 @@ describe('UserResolver', () => { duration: expect.any(String), }) }) + + it('stores the send confirmation event in the database', () => { + expect(EventProtocol.find()).resolves.toContainEqual( + expect.objectContaining({ + type: EventProtocolType.SEND_CONFIRMATION_EMAIL, + userId: user[0].id, + }), + ) + }) }) describe('email already exists', () => { @@ -245,18 +256,26 @@ describe('UserResolver', () => { mutation: setPassword, variables: { code: emailOptIn, password: 'Aa12345_' }, }) + // make Peter Lustig Admin const peter = await User.findOneOrFail({ id: user[0].id }) peter.isAdmin = new Date() await peter.save() + + // date statement + const actualDate = new Date() + const futureDate = new Date() // Create a future day from the executed day + futureDate.setDate(futureDate.getDate() + 1) + // factory logs in as Peter Lustig link = await contributionLinkFactory(testEnv, { name: 'Dokumenta 2022', memo: 'Vielen Dank für deinen Besuch bei der Dokumenta 2022', amount: 200, - validFrom: new Date(2022, 5, 18), - validTo: new Date(2022, 8, 25), + validFrom: actualDate, + validTo: futureDate, }) + resetToken() await mutate({ mutation: createUser, @@ -271,6 +290,15 @@ describe('UserResolver', () => { }), ) }) + + it('stores the account activated event in the database', () => { + expect(EventProtocol.find()).resolves.toContainEqual( + expect.objectContaining({ + type: EventProtocolType.ACTIVATE_ACCOUNT, + userId: user[0].id, + }), + ) + }) }) /* A transaction link requires GDD on account @@ -383,6 +411,10 @@ bei Gradidio sei dabei!`, }), ) }) + + it('logs the error thrown', () => { + expect(logger.error).toBeCalledWith('Password entered is lexically invalid') + }) }) describe('no valid optin code', () => { @@ -405,6 +437,10 @@ bei Gradidio sei dabei!`, }), ) }) + + it('logs the error found', () => { + expect(logger.error).toBeCalledWith('Could not login with emailVerificationCode') + }) }) }) @@ -433,6 +469,10 @@ bei Gradidio sei dabei!`, }), ) }) + + it('logs the error found', () => { + expect(logger.error).toBeCalledWith('User with email=bibi@bloxberg.de does not exist') + }) }) describe('user is in database and correct login data', () => { @@ -475,6 +515,7 @@ bei Gradidio sei dabei!`, describe('user is in database and wrong password', () => { beforeAll(async () => { await userFactory(testEnv, bibiBloxberg) + result = await query({ query: login, variables: { ...variables, password: 'wrong' } }) }) afterAll(async () => { @@ -482,14 +523,16 @@ bei Gradidio sei dabei!`, }) it('returns an error', () => { - expect( - query({ query: login, variables: { ...variables, password: 'wrong' } }), - ).resolves.toEqual( + expect(result).toEqual( expect.objectContaining({ errors: [new GraphQLError('No user with this credentials')], }), ) }) + + it('logs the error thrown', () => { + expect(logger.error).toBeCalledWith('The User has no valid credentials.') + }) }) }) @@ -562,6 +605,8 @@ bei Gradidio sei dabei!`, }) describe('authenticated', () => { + let user: User[] + const variables = { email: 'bibi@bloxberg.de', password: 'Aa12345_', @@ -569,6 +614,7 @@ bei Gradidio sei dabei!`, beforeAll(async () => { await query({ query: login, variables }) + user = await User.find() }) afterAll(() => { @@ -595,6 +641,15 @@ bei Gradidio sei dabei!`, }), ) }) + + it('stores the login event in the database', () => { + expect(EventProtocol.find()).resolves.toContainEqual( + expect.objectContaining({ + type: EventProtocolType.LOGIN, + userId: user[0].id, + }), + ) + }) }) }) }) @@ -649,13 +704,17 @@ bei Gradidio sei dabei!`, }) describe('request reset password again', () => { - it('thows an error', async () => { + it('throws an error', async () => { await expect(mutate({ mutation: forgotPassword, variables })).resolves.toEqual( expect.objectContaining({ errors: [new GraphQLError('email already sent less than 10 minutes minutes ago')], }), ) }) + + it('logs the error found', () => { + expect(logger.error).toBeCalledWith(`email already sent less than 10 minutes minutes ago`) + }) }) }) }) @@ -766,7 +825,7 @@ bei Gradidio sei dabei!`, }) describe('language is not valid', () => { - it('thows an error', async () => { + it('throws an error', async () => { await expect( mutate({ mutation: updateUserInfos, @@ -780,6 +839,10 @@ bei Gradidio sei dabei!`, }), ) }) + + it('logs the error found', () => { + expect(logger.error).toBeCalledWith(`"not-valid" isn't a valid language`) + }) }) describe('password', () => { @@ -799,6 +862,10 @@ bei Gradidio sei dabei!`, }), ) }) + + it('logs the error found', () => { + expect(logger.error).toBeCalledWith(`Old password is invalid`) + }) }) describe('invalid new password', () => { @@ -821,6 +888,10 @@ bei Gradidio sei dabei!`, }), ) }) + + it('logs the error found', () => { + expect(logger.error).toBeCalledWith('newPassword does not fullfil the rules') + }) }) describe('correct old and new password', () => { @@ -840,7 +911,7 @@ bei Gradidio sei dabei!`, ) }) - it('can login wtih new password', async () => { + it('can login with new password', async () => { await expect( query({ query: login, @@ -860,7 +931,7 @@ bei Gradidio sei dabei!`, ) }) - it('cannot login wtih old password', async () => { + it('cannot login with old password', async () => { await expect( query({ query: login, @@ -875,6 +946,10 @@ bei Gradidio sei dabei!`, }), ) }) + + it('logs the error thrown', () => { + expect(logger.error).toBeCalledWith('The User has no valid credentials.') + }) }) }) }) diff --git a/backend/src/graphql/resolver/UserResolver.ts b/backend/src/graphql/resolver/UserResolver.ts index 3b7013323..f2fd048fc 100644 --- a/backend/src/graphql/resolver/UserResolver.ts +++ b/backend/src/graphql/resolver/UserResolver.ts @@ -30,6 +30,7 @@ import { EventRedeemRegister, EventRegister, EventSendConfirmationEmail, + EventActivateAccount, } from '@/event/Event' import { getUserCreation } from './util/creations' import { UserRepository } from '@/typeorm/repository/User' @@ -273,7 +274,7 @@ export class UserResolver { logger.info(`login with ${email}, ***, ${publisherId} ...`) email = email.trim().toLowerCase() const dbUser = await DbUser.findOneOrFail({ email }, { withDeleted: true }).catch(() => { - logger.error(`User with email=${email} does not exists`) + logger.error(`User with email=${email} does not exist`) throw new Error('No user with this credentials') }) if (dbUser.deletedAt) { @@ -389,7 +390,7 @@ export class UserResolver { /* 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(`Email not send!`) + logger.debug(`Email not sent!`) } logger.info('createUser() faked and send multi registration mail...') @@ -548,6 +549,7 @@ export class UserResolver { logger.info(`setPassword(${code}, ***)...`) // Validate Password if (!isPassword(password)) { + logger.error('Password entered is lexically invalid') throw new Error( 'Please enter a valid password with at least 8 characters, upper and lower case letters, at least one number and one special character!', ) @@ -610,6 +612,8 @@ export class UserResolver { await queryRunner.connect() await queryRunner.startTransaction('READ UNCOMMITTED') + const event = new Event() + try { // Save user await queryRunner.manager.save(user).catch((error) => { @@ -618,6 +622,11 @@ export class UserResolver { }) await queryRunner.commitTransaction() + + const eventActivateAccount = new EventActivateAccount() + eventActivateAccount.userId = user.id + eventProtocol.writeEvent(event.setEventActivateAccount(eventActivateAccount)) + logger.info('User data written successfully...') } catch (e) { await queryRunner.rollbackTransaction() @@ -727,6 +736,7 @@ export class UserResolver { try { await queryRunner.manager.save(userEntity).catch((error) => { + logger.error('error saving user: ' + error) throw new Error('error saving user: ' + error) }) diff --git a/backend/src/mailer/sendAddedContributionMessageEmail.test.ts b/backend/src/mailer/sendAddedContributionMessageEmail.test.ts new file mode 100644 index 000000000..1151a0abc --- /dev/null +++ b/backend/src/mailer/sendAddedContributionMessageEmail.test.ts @@ -0,0 +1,40 @@ +import { sendAddedContributionMessageEmail } from './sendAddedContributionMessageEmail' +import { sendEMail } from './sendEMail' + +jest.mock('./sendEMail', () => { + return { + __esModule: true, + sendEMail: jest.fn(), + } +}) + +describe('sendAddedContributionMessageEmail', () => { + beforeEach(async () => { + await sendAddedContributionMessageEmail({ + senderFirstName: 'Peter', + senderLastName: 'Lustig', + recipientFirstName: 'Bibi', + recipientLastName: 'Bloxberg', + recipientEmail: 'bibi@bloxberg.de', + senderEmail: 'peter@lustig.de', + contributionMemo: 'Vielen herzlichen Dank für den neuen Hexenbesen!', + message: 'Was für ein Besen ist es geworden?', + overviewURL: 'http://localhost/overview', + }) + }) + + it('calls sendEMail', () => { + expect(sendEMail).toBeCalledWith({ + to: `Bibi Bloxberg `, + subject: 'Gradido Frage zur Schöpfung', + text: + expect.stringContaining('Hallo Bibi Bloxberg') && + expect.stringContaining('Peter Lustig') && + expect.stringContaining( + 'Du hast soeben zu deinem eingereichten Gradido Schöpfungsantrag "Vielen herzlichen Dank für den neuen Hexenbesen!" eine Rückfrage von Peter Lustig erhalten.', + ) && + expect.stringContaining('Was für ein Besen ist es geworden?') && + expect.stringContaining('http://localhost/overview'), + }) + }) +}) diff --git a/backend/src/mailer/sendAddedContributionMessageEmail.ts b/backend/src/mailer/sendAddedContributionMessageEmail.ts new file mode 100644 index 000000000..14d5f6d31 --- /dev/null +++ b/backend/src/mailer/sendAddedContributionMessageEmail.ts @@ -0,0 +1,26 @@ +import { backendLogger as logger } from '@/server/logger' +import { sendEMail } from './sendEMail' +import { contributionMessageReceived } from './text/contributionMessageReceived' + +export const sendAddedContributionMessageEmail = (data: { + senderFirstName: string + senderLastName: string + recipientFirstName: string + recipientLastName: string + recipientEmail: string + senderEmail: string + contributionMemo: string + message: string + overviewURL: string +}): Promise => { + logger.info( + `sendEmail(): to=${data.recipientFirstName} ${data.recipientLastName} <${data.recipientEmail}>, + subject=${contributionMessageReceived.de.subject}, + text=${contributionMessageReceived.de.text(data)}`, + ) + return sendEMail({ + to: `${data.recipientFirstName} ${data.recipientLastName} <${data.recipientEmail}>`, + subject: contributionMessageReceived.de.subject, + text: contributionMessageReceived.de.text(data), + }) +} diff --git a/backend/src/mailer/sendContributionConfirmedEmail.test.ts b/backend/src/mailer/sendContributionConfirmedEmail.test.ts new file mode 100644 index 000000000..1935144fd --- /dev/null +++ b/backend/src/mailer/sendContributionConfirmedEmail.test.ts @@ -0,0 +1,39 @@ +import Decimal from 'decimal.js-light' +import { sendContributionConfirmedEmail } from './sendContributionConfirmedEmail' +import { sendEMail } from './sendEMail' + +jest.mock('./sendEMail', () => { + return { + __esModule: true, + sendEMail: jest.fn(), + } +}) + +describe('sendContributionConfirmedEmail', () => { + beforeEach(async () => { + await sendContributionConfirmedEmail({ + senderFirstName: 'Peter', + senderLastName: 'Lustig', + recipientFirstName: 'Bibi', + recipientLastName: 'Bloxberg', + recipientEmail: 'bibi@bloxberg.de', + contributionMemo: 'Vielen herzlichen Dank für den neuen Hexenbesen!', + contributionAmount: new Decimal(200.0), + overviewURL: 'http://localhost/overview', + }) + }) + + it('calls sendEMail', () => { + expect(sendEMail).toBeCalledWith({ + to: 'Bibi Bloxberg ', + subject: 'Schöpfung wurde bestätigt', + text: + expect.stringContaining('Hallo Bibi Bloxberg') && + expect.stringContaining( + 'Dein Gradido Schöpfungsantrag "Vielen herzlichen Dank für den neuen Hexenbesen!" wurde soeben bestätigt.', + ) && + expect.stringContaining('Betrag: 200,00 GDD') && + expect.stringContaining('Link zu deinem Konto: http://localhost/overview'), + }) + }) +}) diff --git a/backend/src/mailer/sendContributionConfirmedEmail.ts b/backend/src/mailer/sendContributionConfirmedEmail.ts new file mode 100644 index 000000000..439d240eb --- /dev/null +++ b/backend/src/mailer/sendContributionConfirmedEmail.ts @@ -0,0 +1,26 @@ +import { backendLogger as logger } from '@/server/logger' +import Decimal from 'decimal.js-light' +import { sendEMail } from './sendEMail' +import { contributionConfirmed } from './text/contributionConfirmed' + +export const sendContributionConfirmedEmail = (data: { + senderFirstName: string + senderLastName: string + recipientFirstName: string + recipientLastName: string + recipientEmail: string + contributionMemo: string + contributionAmount: Decimal + overviewURL: string +}): Promise => { + logger.info( + `sendEmail(): to=${data.recipientFirstName} ${data.recipientLastName} <${data.recipientEmail}>, + subject=${contributionConfirmed.de.subject}, + text=${contributionConfirmed.de.text(data)}`, + ) + return sendEMail({ + to: `${data.recipientFirstName} ${data.recipientLastName} <${data.recipientEmail}>`, + subject: contributionConfirmed.de.subject, + text: contributionConfirmed.de.text(data), + }) +} diff --git a/backend/src/mailer/sendTransactionReceivedEmail.ts b/backend/src/mailer/sendTransactionReceivedEmail.ts index 692f92f9a..55f63e37e 100644 --- a/backend/src/mailer/sendTransactionReceivedEmail.ts +++ b/backend/src/mailer/sendTransactionReceivedEmail.ts @@ -1,7 +1,7 @@ import { backendLogger as logger } from '@/server/logger' import Decimal from 'decimal.js-light' import { sendEMail } from './sendEMail' -import { transactionReceived } from './text/transactionReceived' +import { transactionLinkRedeemed, transactionReceived } from './text/transactionReceived' export const sendTransactionReceivedEmail = (data: { senderFirstName: string @@ -26,3 +26,27 @@ export const sendTransactionReceivedEmail = (data: { text: transactionReceived.de.text(data), }) } + +export const sendTransactionLinkRedeemedEmail = (data: { + email: string + senderFirstName: string + senderLastName: string + recipientFirstName: string + recipientLastName: string + senderEmail: string + amount: Decimal + memo: string + overviewURL: string +}): Promise => { + logger.info( + `sendEmail(): to=${data.recipientFirstName} ${data.recipientLastName}, + <${data.email}>, + subject=${transactionLinkRedeemed.de.subject}, + text=${transactionLinkRedeemed.de.text(data)}`, + ) + return sendEMail({ + to: `${data.recipientFirstName} ${data.recipientLastName} <${data.email}>`, + subject: transactionLinkRedeemed.de.subject, + text: transactionLinkRedeemed.de.text(data), + }) +} diff --git a/backend/src/mailer/text/contributionConfirmed.ts b/backend/src/mailer/text/contributionConfirmed.ts new file mode 100644 index 000000000..2d9fce6a8 --- /dev/null +++ b/backend/src/mailer/text/contributionConfirmed.ts @@ -0,0 +1,30 @@ +import Decimal from 'decimal.js-light' + +export const contributionConfirmed = { + de: { + subject: 'Schöpfung wurde bestätigt', + text: (data: { + senderFirstName: string + senderLastName: string + recipientFirstName: string + recipientLastName: string + contributionMemo: string + contributionAmount: Decimal + overviewURL: string + }): string => + `Hallo ${data.recipientFirstName} ${data.recipientLastName}, + +Dein Gradido Schöpfungsantrag "${data.contributionMemo}" wurde soeben von ${data.senderFirstName} ${ + data.senderLastName + } bestätigt. +Betrag: ${data.contributionAmount.toFixed(2).replace('.', ',')} GDD + +Bitte antworte nicht auf diese E-Mail! + +Mit freundlichen Grüßen, +dein Gradido-Team + + +Link zu deinem Konto: ${data.overviewURL}`, + }, +} diff --git a/backend/src/mailer/text/contributionMessageReceived.ts b/backend/src/mailer/text/contributionMessageReceived.ts new file mode 100644 index 000000000..4affb71a8 --- /dev/null +++ b/backend/src/mailer/text/contributionMessageReceived.ts @@ -0,0 +1,30 @@ +export const contributionMessageReceived = { + de: { + subject: 'Gradido Frage zur Schöpfung', + text: (data: { + senderFirstName: string + senderLastName: string + recipientFirstName: string + recipientLastName: string + recipientEmail: string + senderEmail: string + contributionMemo: string + message: string + overviewURL: string + }): string => + `Hallo ${data.recipientFirstName} ${data.recipientLastName}, + +Du hast soeben zu deinem eingereichten Gradido Schöpfungsantrag "${data.contributionMemo}" eine Rückfrage von ${data.senderFirstName} ${data.senderLastName} erhalten. +Die Rückfrage lautet: + +${data.message} + +Bitte antworte nicht auf diese E-Mail! + +Mit freundlichen Grüßen, +dein Gradido-Team + + +Link zu deinem Konto: ${data.overviewURL}`, + }, +} diff --git a/backend/src/mailer/text/transactionReceived.ts b/backend/src/mailer/text/transactionReceived.ts index 07d03ad45..2764d1b60 100644 --- a/backend/src/mailer/text/transactionReceived.ts +++ b/backend/src/mailer/text/transactionReceived.ts @@ -29,6 +29,37 @@ Mit freundlichen Grüßen, dein Gradido-Team +Link zu deinem Konto: ${data.overviewURL}`, + }, +} + +export const transactionLinkRedeemed = { + de: { + subject: 'Gradido link eingelösst', + text: (data: { + email: string + senderFirstName: string + senderLastName: string + recipientFirstName: string + recipientLastName: string + senderEmail: string + amount: Decimal + memo: string + overviewURL: string + }): string => + `Hallo ${data.recipientFirstName} ${data.recipientLastName} + +${data.senderFirstName} ${data.senderLastName} (${ + data.senderEmail + }) hat soeben deinen Link eingelösst. +Betrag: ${data.amount.toFixed(2).replace('.', ',')} GDD, +Memo: ${data.memo} + +Bitte antworte nicht auf diese E-Mail! + +Mit freundlichen Grüßen, +dein Gradido-Team + Link zu deinem Konto: ${data.overviewURL}`, }, } diff --git a/deployment/bare_metal/.env.dist b/deployment/bare_metal/.env.dist index 1255104c9..ebb6717e7 100644 --- a/deployment/bare_metal/.env.dist +++ b/deployment/bare_metal/.env.dist @@ -61,7 +61,7 @@ EVENT_PROTOCOL_DISABLED=false DATABASE_CONFIG_VERSION=v1.2022-03-18 # frontend -FRONTEND_CONFIG_VERSION=v2.2022-04-07 +FRONTEND_CONFIG_VERSION=v3.2022-09-16 GRAPHQL_URI=https://stage1.gradido.net/graphql ADMIN_AUTH_URL=https://stage1.gradido.net/admin/authenticate?token={token} @@ -77,6 +77,8 @@ META_KEYWORDS_DE="Grundeinkommen, Währung, Dankbarkeit, Schenk-Ökonomie, Natü META_KEYWORDS_EN="Basic Income, Currency, Gratitude, Gift Economy, Natural Economy of Life, Economy, Ecology, Potential Development, Giving and Thanking, Cycle of Life, Monetary System" META_AUTHOR="Bernd Hückstädt - Gradido-Akademie" +SUPPORT_MAIL=support@supportmail.com + # admin ADMIN_CONFIG_VERSION=v1.2022-03-18 diff --git a/deployment/bare_metal/install.sh b/deployment/bare_metal/install.sh index 0fcf6d847..9366cbc75 100755 --- a/deployment/bare_metal/install.sh +++ b/deployment/bare_metal/install.sh @@ -75,7 +75,7 @@ pm2 startup sudo apt-get install -y certbot sudo apt-get install -y python3-certbot-nginx sudo certbot -> Enter email address (used for urgent renewal and security notices) > support@gradido.net +> Enter email address (used for urgent renewal and security notices) > e.g. support@supportmail.com > Please read the Terms of Service at > Y > Would you be willing, once your first certificate is successfully issued, to > N > No names were found in your configuration files. Please enter in your domain > stage1.gradido.net diff --git a/frontend/.env.dist b/frontend/.env.dist index 65d9ae305..4127f339a 100644 --- a/frontend/.env.dist +++ b/frontend/.env.dist @@ -1,4 +1,4 @@ -CONFIG_VERSION=v2.2022-04-07 +CONFIG_VERSION=v3.2022-09-16 # Environment DEFAULT_PUBLISHER_ID=2896 @@ -21,4 +21,7 @@ META_DESCRIPTION_DE="Dankbarkeit ist die Währung der neuen Zeit. Immer mehr Men META_DESCRIPTION_EN="Gratitude is the currency of the new age. More and more people are unleashing their potential and shaping a good future for all." META_KEYWORDS_DE="Grundeinkommen, Währung, Dankbarkeit, Schenk-Ökonomie, Natürliche Ökonomie des Lebens, Ökonomie, Ökologie, Potenzialentfaltung, Schenken und Danken, Kreislauf des Lebens, Geldsystem" META_KEYWORDS_EN="Basic Income, Currency, Gratitude, Gift Economy, Natural Economy of Life, Economy, Ecology, Potential Development, Giving and Thanking, Cycle of Life, Monetary System" -META_AUTHOR="Bernd Hückstädt - Gradido-Akademie" \ No newline at end of file +META_AUTHOR="Bernd Hückstädt - Gradido-Akademie" + +# Support Mail +SUPPORT_MAIL=support@supportmail.com \ No newline at end of file diff --git a/frontend/.env.template b/frontend/.env.template index 6d6b83fc7..0b9d34b38 100644 --- a/frontend/.env.template +++ b/frontend/.env.template @@ -21,4 +21,7 @@ META_DESCRIPTION_DE=$META_DESCRIPTION_DE META_DESCRIPTION_EN=$META_DESCRIPTION_EN META_KEYWORDS_DE=$META_KEYWORDS_DE META_KEYWORDS_EN=$META_KEYWORDS_EN -META_AUTHOR=$META_AUTHOR \ No newline at end of file +META_AUTHOR=$META_AUTHOR + +# Support Mail +SUPPORT_MAIL=$SUPPORT_MAIL \ No newline at end of file diff --git a/frontend/src/config/index.js b/frontend/src/config/index.js index 917a25d70..5ab5f2392 100644 --- a/frontend/src/config/index.js +++ b/frontend/src/config/index.js @@ -8,7 +8,7 @@ const constants = { DECAY_START_TIME: new Date('2021-05-13 17:46:31-0000'), // GMT+0 CONFIG_VERSION: { DEFAULT: 'DEFAULT', - EXPECTED: 'v2.2022-04-07', + EXPECTED: 'v3.2022-09-16', CURRENT: '', }, } @@ -60,6 +60,10 @@ const meta = { META_AUTHOR: process.env.META_AUTHOR || 'Bernd Hückstädt - Gradido-Akademie', } +const supportmail = { + SUPPORT_MAIL: process.env.SUPPORT_MAIL || 'support@supportmail.com', +} + // Check config version constants.CONFIG_VERSION.CURRENT = process.env.CONFIG_VERSION || constants.CONFIG_VERSION.DEFAULT if ( @@ -79,6 +83,7 @@ const CONFIG = { ...endpoints, ...community, ...meta, + ...supportmail, } module.exports = CONFIG diff --git a/frontend/src/pages/InfoStatistic.vue b/frontend/src/pages/InfoStatistic.vue index 309404f48..1e09f83ed 100644 --- a/frontend/src/pages/InfoStatistic.vue +++ b/frontend/src/pages/InfoStatistic.vue @@ -83,7 +83,7 @@ export default { countAdminUser: null, itemsContributionLinks: [], itemsAdminUser: [], - supportMail: 'support@supportemail.de', + supportMail: CONFIG.SUPPORT_MAIL, membersCount: '1203', totalUsers: null, totalGradidoCreated: null,