diff --git a/backend/src/graphql/model/User.ts b/backend/src/graphql/model/User.ts index 8d56c6775..cc52ff1f1 100644 --- a/backend/src/graphql/model/User.ts +++ b/backend/src/graphql/model/User.ts @@ -45,7 +45,7 @@ export class User { emailId: number | null // TODO privacy issue here - @Field(() => String) + @Field(() => String, { nullable: true }) email: string @Field(() => UserContact) diff --git a/backend/src/graphql/resolver/AdminResolver.test.ts b/backend/src/graphql/resolver/AdminResolver.test.ts index 27e3c6385..2f72155de 100644 --- a/backend/src/graphql/resolver/AdminResolver.test.ts +++ b/backend/src/graphql/resolver/AdminResolver.test.ts @@ -1498,7 +1498,7 @@ describe('AdminResolver', () => { }) // In the futrue this should not throw anymore - it('throws an error for the second confirmation', async () => { + it('and throws an error for the second confirmation', async () => { const r1 = mutate({ mutation: confirmContribution, variables: { @@ -1518,6 +1518,7 @@ describe('AdminResolver', () => { ) await expect(r2).resolves.toEqual( expect.objectContaining({ + // data: { confirmContribution: true }, errors: [new GraphQLError('Creation was not successful.')], }), ) diff --git a/backend/src/graphql/resolver/AdminResolver.ts b/backend/src/graphql/resolver/AdminResolver.ts index 7bdc4d59b..aaf3ed91f 100644 --- a/backend/src/graphql/resolver/AdminResolver.ts +++ b/backend/src/graphql/resolver/AdminResolver.ts @@ -426,7 +426,10 @@ export class AdminResolver { logger.error('Moderator can not confirm own contribution') throw new Error('Moderator can not confirm own contribution') } - const user = await dbUser.findOneOrFail({ id: contribution.userId }, { withDeleted: true }) + const user = await dbUser.findOneOrFail( + { id: contribution.userId }, + { withDeleted: true, relations: ['emailContact'] }, + ) if (user.deletedAt) { logger.error('This user was deleted. Cannot confirm a contribution.') throw new Error('This user was deleted. Cannot confirm a contribution.') @@ -438,7 +441,7 @@ export class AdminResolver { const queryRunner = getConnection().createQueryRunner() await queryRunner.connect() - await queryRunner.startTransaction('READ UNCOMMITTED') + await queryRunner.startTransaction('REPEATABLE READ') // 'READ COMMITTED') try { const lastTransaction = await queryRunner.manager .createQueryBuilder() @@ -487,7 +490,7 @@ export class AdminResolver { senderLastName: moderatorUser.lastName, recipientFirstName: user.firstName, recipientLastName: user.lastName, - recipientEmail: user.email, + recipientEmail: user.emailContact.email, contributionMemo: contribution.memo, contributionAmount: contribution.amount, overviewURL: CONFIG.EMAIL_LINK_OVERVIEW, @@ -733,6 +736,9 @@ export class AdminResolver { @Ctx() context: Context, ): Promise { const user = getUser(context) + if (!user.emailContact) { + user.emailContact = await UserContact.findOneOrFail({ where: { id: user.emailId } }) + } const queryRunner = getConnection().createQueryRunner() await queryRunner.connect() await queryRunner.startTransaction('READ UNCOMMITTED') @@ -748,6 +754,11 @@ export class AdminResolver { if (contribution.userId === user.id) { throw new Error('Admin can not answer on own contribution') } + if (!contribution.user.emailContact) { + contribution.user.emailContact = await UserContact.findOneOrFail({ + where: { id: contribution.user.emailId }, + }) + } contributionMessage.contributionId = contributionId contributionMessage.createdAt = new Date() contributionMessage.message = message @@ -764,19 +775,19 @@ export class AdminResolver { contribution.contributionStatus = ContributionStatus.IN_PROGRESS 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, + recipientEmail: contribution.user.emailContact.email, + senderEmail: user.emailContact.email, contributionMemo: contribution.memo, message, overviewURL: CONFIG.EMAIL_LINK_OVERVIEW, }) + await queryRunner.commitTransaction() } catch (e) { await queryRunner.rollbackTransaction() logger.error(`ContributionMessage was not successful: ${e}`) diff --git a/backend/src/graphql/resolver/ContributionMessageResolver.ts b/backend/src/graphql/resolver/ContributionMessageResolver.ts index fb92806d0..bd2bdeec8 100644 --- a/backend/src/graphql/resolver/ContributionMessageResolver.ts +++ b/backend/src/graphql/resolver/ContributionMessageResolver.ts @@ -23,7 +23,7 @@ export class ContributionMessageResolver { const user = getUser(context) const queryRunner = getConnection().createQueryRunner() await queryRunner.connect() - await queryRunner.startTransaction('READ UNCOMMITTED') + await queryRunner.startTransaction('READ COMMITTED') const contributionMessage = DbContributionMessage.create() try { const contribution = await Contribution.findOne({ id: contributionId }) diff --git a/backend/src/graphql/resolver/TransactionResolver.ts b/backend/src/graphql/resolver/TransactionResolver.ts index 4b46804f1..dff5eccf1 100644 --- a/backend/src/graphql/resolver/TransactionResolver.ts +++ b/backend/src/graphql/resolver/TransactionResolver.ts @@ -38,7 +38,6 @@ import Decimal from 'decimal.js-light' import { BalanceResolver } from './BalanceResolver' import { MEMO_MAX_CHARS, MEMO_MIN_CHARS } from './const/const' -import { UserContact } from '@entity/UserContact' import { findUserByEmail } from './UserResolver' export const executeTransaction = async ( @@ -165,8 +164,8 @@ export const executeTransaction = async ( senderLastName: recipient.lastName, recipientFirstName: sender.firstName, recipientLastName: sender.lastName, - email: sender.email, - senderEmail: recipient.email, + email: sender.emailContact.email, + senderEmail: recipient.emailContact.email, amount, memo, overviewURL: CONFIG.EMAIL_LINK_OVERVIEW,