diff --git a/backend/src/graphql/resolver/ContributionResolver.test.ts b/backend/src/graphql/resolver/ContributionResolver.test.ts index 13522bea2..fe98c0f6f 100644 --- a/backend/src/graphql/resolver/ContributionResolver.test.ts +++ b/backend/src/graphql/resolver/ContributionResolver.test.ts @@ -48,6 +48,7 @@ import { UserInputError } from 'apollo-server-express' import { raeuberHotzenplotz } from '@/seeds/users/raeuber-hotzenplotz' import { UnconfirmedContribution } from '../model/UnconfirmedContribution' import { ContributionListResult } from '../model/Contribution' +import { ContributionStatus } from '../enum/ContributionStatus' // mock account activation email to avoid console spam jest.mock('@/emails/sendEmailVariants', () => { @@ -202,13 +203,11 @@ describe('ContributionResolver', () => { }, }) - expect(errorObjects).toMatchObject([ - new GraphQLError('memo text is too short (5 characters minimum)'), - ]) + expect(errorObjects).toMatchObject([new GraphQLError('Memo text is too short')]) }) it('logs the error found', () => { - expect(logger.error).toBeCalledWith(`memo text is too short: memo.length=4 < 5`) + expect(logger.error).toBeCalledWith('Memo text is too short', 4) }) it('throws error when memo length greater than 255 chars', async () => { @@ -222,13 +221,11 @@ describe('ContributionResolver', () => { creationDate: date.toString(), }, }) - expect(errorObjects).toMatchObject([ - new GraphQLError('memo text is too long (255 characters maximum)'), - ]) + expect(errorObjects).toMatchObject([new GraphQLError('Memo text is too long')]) }) it('logs the error found', () => { - expect(logger.error).toBeCalledWith(`memo text is too long: memo.length=259 > 255`) + expect(logger.error).toBeCalledWith('Memo text is too long', 259) }) it('throws error when creationDate not-valid', async () => { @@ -328,28 +325,6 @@ describe('ContributionResolver', () => { resetToken() }) - describe('wrong contribution id', () => { - it('throws an error', async () => { - jest.clearAllMocks() - const { errors: errorObjects }: { errors: [GraphQLError] } = await mutate({ - mutation: updateContribution, - variables: { - contributionId: -1, - amount: 100.0, - memo: 'Test env contribution', - creationDate: new Date().toString(), - }, - }) - expect(errorObjects).toMatchObject([ - new GraphQLError('No contribution found to given id.'), - ]) - }) - - it('logs the error found', () => { - expect(logger.error).toBeCalledWith('No contribution found to given id') - }) - }) - describe('Memo length smaller than 5 chars', () => { it('throws error', async () => { jest.clearAllMocks() @@ -363,13 +338,11 @@ describe('ContributionResolver', () => { creationDate: date.toString(), }, }) - expect(errorObjects).toMatchObject([ - new GraphQLError('memo text is too short (5 characters minimum)'), - ]) + expect(errorObjects).toMatchObject([new GraphQLError('Memo text is too short')]) }) it('logs the error found', () => { - expect(logger.error).toBeCalledWith('memo text is too short: memo.length=4 < 5') + expect(logger.error).toBeCalledWith('Memo text is too short', 4) }) }) @@ -386,13 +359,36 @@ describe('ContributionResolver', () => { creationDate: date.toString(), }, }) - expect(errorObjects).toMatchObject([ - new GraphQLError('memo text is too long (255 characters maximum)'), - ]) + expect(errorObjects).toMatchObject([new GraphQLError('Memo text is too long')]) }) it('logs the error found', () => { - expect(logger.error).toBeCalledWith('memo text is too long: memo.length=259 > 255') + expect(logger.error).toBeCalledWith('Memo text is too long', 259) + }) + }) + + describe('wrong contribution id', () => { + it('throws an error', async () => { + jest.clearAllMocks() + await expect( + mutate({ + mutation: updateContribution, + variables: { + contributionId: -1, + amount: 100.0, + memo: 'Test env contribution', + creationDate: new Date().toString(), + }, + }), + ).resolves.toEqual( + expect.objectContaining({ + errors: [new GraphQLError('Contribution not found')], + }), + ) + }) + + it('logs the error found', () => { + expect(logger.error).toBeCalledWith('Contribution not found', -1) }) }) @@ -416,13 +412,15 @@ describe('ContributionResolver', () => { }, }) expect(errorObjects).toMatchObject([ - new GraphQLError('user of the pending contribution and send user does not correspond'), + new GraphQLError('Can not update contribution of another user'), ]) }) it('logs the error found', () => { expect(logger.error).toBeCalledWith( - 'user of the pending contribution and send user does not correspond', + 'Can not update contribution of another user', + expect.any(Object), + expect.any(Number), ) }) }) @@ -448,15 +446,63 @@ describe('ContributionResolver', () => { }, }) expect(errorObjects).toMatchObject([ - new GraphQLError('An admin is not allowed to update a user contribution.'), + new GraphQLError('An admin is not allowed to update an user contribution'), ]) }) it('logs the error found', () => { expect(logger.error).toBeCalledWith( - 'An admin is not allowed to update a user contribution.', + 'An admin is not allowed to update an user contribution', ) }) + + describe('contribution has wrong status', () => { + beforeAll(async () => { + const contribution = await Contribution.findOneOrFail({ + id: pendingContribution.data.createContribution.id, + }) + contribution.contributionStatus = ContributionStatus.DELETED + contribution.save() + await mutate({ + mutation: login, + variables: { email: 'bibi@bloxberg.de', password: 'Aa12345_' }, + }) + }) + + afterAll(async () => { + const contribution = await Contribution.findOneOrFail({ + id: pendingContribution.data.createContribution.id, + }) + contribution.contributionStatus = ContributionStatus.PENDING + contribution.save() + }) + + it('throws an error', async () => { + jest.clearAllMocks() + await expect( + mutate({ + mutation: updateContribution, + variables: { + contributionId: pendingContribution.data.createContribution.id, + amount: 10.0, + memo: 'Test env contribution', + creationDate: new Date().toString(), + }, + }), + ).resolves.toEqual( + expect.objectContaining({ + errors: [new GraphQLError('Contribution can not be updated due to status')], + }), + ) + }) + + it('logs the error found', () => { + expect(logger.error).toBeCalledWith( + 'Contribution can not be updated due to status', + ContributionStatus.DELETED, + ) + }) + }) }) describe('update to much so that the limit is exceeded', () => { @@ -506,15 +552,12 @@ describe('ContributionResolver', () => { }, }) expect(errorObjects).toMatchObject([ - new GraphQLError('Currently the month of the contribution cannot change.'), + new GraphQLError('Month of contribution can not be changed'), ]) }) - it.skip('logs the error found', () => { - expect(logger.error).toBeCalledWith( - 'No information for available creations with the given creationDate=', - 'Invalid Date', - ) + it('logs the error found', () => { + expect(logger.error).toBeCalledWith('Month of contribution can not be changed') }) }) @@ -607,25 +650,25 @@ describe('ContributionResolver', () => { describe('wrong contribution id', () => { it('throws an error', async () => { + jest.clearAllMocks() const { errors: errorObjects }: { errors: GraphQLError[] } = await mutate({ mutation: denyContribution, variables: { id: -1, }, }) - expect(errorObjects).toMatchObject([ - new GraphQLError('Contribution not found for given id.'), - ]) + expect(errorObjects).toMatchObject([new GraphQLError('Contribution not found')]) }) it('logs the error found', () => { - expect(logger.error).toBeCalledWith('Contribution not found for given id: -1') + expect(logger.error).toBeCalledWith('Contribution not found', -1) }) }) describe('deny contribution that is already confirmed', () => { let contribution: any it('throws an error', async () => { + jest.clearAllMocks() await mutate({ mutation: login, variables: { email: 'raeuber@hotzenplotz.de', password: 'Aa12345_' }, @@ -658,15 +701,11 @@ describe('ContributionResolver', () => { id: contribution.data.createContribution.id, }, }) - expect(errorObjects).toMatchObject([ - new GraphQLError('Contribution not found for given id.'), - ]) + expect(errorObjects).toMatchObject([new GraphQLError('Contribution not found')]) }) it('logs the error found', () => { - expect(logger.error).toBeCalledWith( - `Contribution not found for given id: ${contribution.data.createContribution.id}`, - ) + expect(logger.error).toBeCalledWith('Contribution not found', expect.any(Number)) }) }) @@ -674,6 +713,7 @@ describe('ContributionResolver', () => { let contribution: any it('throws an error', async () => { + jest.clearAllMocks() await mutate({ mutation: login, variables: { email: 'raeuber@hotzenplotz.de', password: 'Aa12345_' }, @@ -706,15 +746,11 @@ describe('ContributionResolver', () => { id: contribution.data.createContribution.id, }, }) - expect(errorObjects).toMatchObject([ - new GraphQLError('Contribution not found for given id.'), - ]) + expect(errorObjects).toMatchObject([new GraphQLError('Contribution not found')]) }) it('logs the error found', () => { - expect(logger.error).toBeCalledWith( - `Contribution not found for given id: ${contribution.data.createContribution.id}`, - ) + expect(logger.error).toBeCalledWith(`Contribution not found`, expect.any(Number)) }) }) @@ -722,6 +758,7 @@ describe('ContributionResolver', () => { let contribution: any it('throws an error', async () => { + jest.clearAllMocks() await mutate({ mutation: login, variables: { email: 'raeuber@hotzenplotz.de', password: 'Aa12345_' }, @@ -754,15 +791,11 @@ describe('ContributionResolver', () => { id: contribution.data.createContribution.id, }, }) - expect(errorObjects).toMatchObject([ - new GraphQLError('Contribution not found for given id.'), - ]) + expect(errorObjects).toMatchObject([new GraphQLError('Contribution not found')]) }) it('logs the error found', () => { - expect(logger.error).toBeCalledWith( - `Contribution not found for given id: ${contribution.data.createContribution.id}`, - ) + expect(logger.error).toBeCalledWith(`Contribution not found`, expect.any(Number)) }) }) @@ -813,19 +846,18 @@ describe('ContributionResolver', () => { describe('wrong contribution id', () => { it('returns an error', async () => { + jest.clearAllMocks() const { errors: errorObjects }: { errors: [GraphQLError] } = await mutate({ mutation: deleteContribution, variables: { id: -1, }, }) - expect(errorObjects).toMatchObject([ - new GraphQLError('Contribution not found for given id.'), - ]) + expect(errorObjects).toMatchObject([new GraphQLError('Contribution not found')]) }) it('logs the error found', () => { - expect(logger.error).toBeCalledWith('Contribution not found for given id') + expect(logger.error).toBeCalledWith('Contribution not found', expect.any(Number)) }) }) @@ -842,6 +874,7 @@ describe('ContributionResolver', () => { }) it('returns an error', async () => { + jest.clearAllMocks() const { errors: errorObjects }: { errors: [GraphQLError] } = await mutate({ mutation: deleteContribution, variables: { @@ -854,7 +887,11 @@ describe('ContributionResolver', () => { }) it('logs the error found', () => { - expect(logger.error).toBeCalledWith('Can not delete contribution of another user') + expect(logger.error).toBeCalledWith( + 'Can not delete contribution of another user', + expect.any(Contribution), + expect.any(Number), + ) }) }) @@ -923,7 +960,10 @@ describe('ContributionResolver', () => { }) it('logs the error found', () => { - expect(logger.error).toBeCalledWith('A confirmed contribution can not be deleted') + expect(logger.error).toBeCalledWith( + 'A confirmed contribution can not be deleted', + expect.objectContaining({ contributionStatus: 'CONFIRMED' }), + ) }) }) }) @@ -1830,13 +1870,13 @@ describe('ContributionResolver', () => { mutate({ mutation: adminCreateContribution, variables }), ).resolves.toEqual( expect.objectContaining({ - errors: [new GraphQLError('Could not find user with email: some@fake.email')], + errors: [new GraphQLError('Could not find user')], }), ) }) it('logs the error thrown', () => { - expect(logger.error).toBeCalledWith('Could not find user with email: some@fake.email') + expect(logger.error).toBeCalledWith('Could not find user', 'some@fake.email') }) }) @@ -1856,7 +1896,7 @@ describe('ContributionResolver', () => { ).resolves.toEqual( expect.objectContaining({ errors: [ - new GraphQLError('This user was deleted. Cannot create a contribution.'), + new GraphQLError('Cannot create contribution since the user was deleted'), ], }), ) @@ -1864,7 +1904,12 @@ describe('ContributionResolver', () => { it('logs the error thrown', () => { expect(logger.error).toBeCalledWith( - 'This user was deleted. Cannot create a contribution.', + 'Cannot create contribution since the user was deleted', + expect.objectContaining({ + user: expect.objectContaining({ + deletedAt: new Date('2018-03-14T09:17:52.000Z'), + }), + }), ) }) }) @@ -1885,7 +1930,9 @@ describe('ContributionResolver', () => { ).resolves.toEqual( expect.objectContaining({ errors: [ - new GraphQLError('Contribution could not be saved, Email is not activated'), + new GraphQLError( + 'Cannot create contribution since the users email is not activated', + ), ], }), ) @@ -1893,7 +1940,8 @@ describe('ContributionResolver', () => { it('logs the error thrown', () => { expect(logger.error).toBeCalledWith( - 'Contribution could not be saved, Email is not activated', + 'Cannot create contribution since the users email is not activated', + expect.objectContaining({ emailChecked: false }), ) }) }) @@ -1911,13 +1959,13 @@ describe('ContributionResolver', () => { mutate({ mutation: adminCreateContribution, variables }), ).resolves.toEqual( expect.objectContaining({ - errors: [new GraphQLError(`invalid Date for creationDate=invalid-date`)], + errors: [new GraphQLError('CreationDate is invalid')], }), ) }) it('logs the error thrown', () => { - expect(logger.error).toBeCalledWith(`invalid Date for creationDate=invalid-date`) + expect(logger.error).toBeCalledWith('CreationDate is invalid', 'invalid-date') }) }) @@ -2021,6 +2069,7 @@ describe('ContributionResolver', () => { describe('second creation surpasses the available amount ', () => { it('returns an array of the open creations for the last three months', async () => { + jest.clearAllMocks() variables.amount = new Decimal(1000) await expect( mutate({ mutation: adminCreateContribution, variables }), @@ -2113,17 +2162,13 @@ describe('ContributionResolver', () => { }), ).resolves.toEqual( expect.objectContaining({ - errors: [ - new GraphQLError('Could not find UserContact with email: bob@baumeister.de'), - ], + errors: [new GraphQLError('Could not find User')], }), ) }) it('logs the error thrown', () => { - expect(logger.error).toBeCalledWith( - 'Could not find UserContact with email: bob@baumeister.de', - ) + expect(logger.error).toBeCalledWith('Could not find User', 'bob@baumeister.de') }) }) @@ -2143,13 +2188,13 @@ describe('ContributionResolver', () => { }), ).resolves.toEqual( expect.objectContaining({ - errors: [new GraphQLError('User was deleted (stephen@hawking.uk)')], + errors: [new GraphQLError('User was deleted')], }), ) }) it('logs the error thrown', () => { - expect(logger.error).toBeCalledWith('User was deleted (stephen@hawking.uk)') + expect(logger.error).toBeCalledWith('User was deleted', 'stephen@hawking.uk') }) }) @@ -2169,13 +2214,13 @@ describe('ContributionResolver', () => { }), ).resolves.toEqual( expect.objectContaining({ - errors: [new GraphQLError('No contribution found to given id.')], + errors: [new GraphQLError('Contribution not found')], }), ) }) it('logs the error thrown', () => { - expect(logger.error).toBeCalledWith('No contribution found to given id.') + expect(logger.error).toBeCalledWith('Contribution not found', -1) }) }) @@ -2199,7 +2244,7 @@ describe('ContributionResolver', () => { expect.objectContaining({ errors: [ new GraphQLError( - 'user of the pending contribution and send user does not correspond', + 'User of the pending contribution and send user does not correspond', ), ], }), @@ -2208,7 +2253,7 @@ describe('ContributionResolver', () => { it('logs the error thrown', () => { expect(logger.error).toBeCalledWith( - 'user of the pending contribution and send user does not correspond', + 'User of the pending contribution and send user does not correspond', ) }) }) @@ -2436,13 +2481,13 @@ describe('ContributionResolver', () => { }), ).resolves.toEqual( expect.objectContaining({ - errors: [new GraphQLError('Contribution not found for given id.')], + errors: [new GraphQLError('Contribution not found')], }), ) }) it('logs the error thrown', () => { - expect(logger.error).toBeCalledWith('Contribution not found for given id: -1') + expect(logger.error).toBeCalledWith('Contribution not found', -1) }) }) @@ -2563,13 +2608,13 @@ describe('ContributionResolver', () => { }), ).resolves.toEqual( expect.objectContaining({ - errors: [new GraphQLError('Contribution not found to given id.')], + errors: [new GraphQLError('Contribution not found')], }), ) }) it('logs the error thrown', () => { - expect(logger.error).toBeCalledWith('Contribution not found for given id: -1') + expect(logger.error).toBeCalledWith('Contribution not found', -1) }) }) @@ -2587,6 +2632,7 @@ describe('ContributionResolver', () => { }) it('thows an error', async () => { + jest.clearAllMocks() await expect( mutate({ mutation: confirmContribution, @@ -2680,6 +2726,7 @@ describe('ContributionResolver', () => { describe('confirm same contribution again', () => { it('throws an error', async () => { + jest.clearAllMocks() await expect( mutate({ mutation: confirmContribution, @@ -2689,11 +2736,18 @@ describe('ContributionResolver', () => { }), ).resolves.toEqual( expect.objectContaining({ - errors: [new GraphQLError('Contribution already confirmd.')], + errors: [new GraphQLError('Contribution already confirmed')], }), ) }) }) + + it('logs the error thrown', () => { + expect(logger.error).toBeCalledWith( + 'Contribution already confirmed', + expect.any(Number), + ) + }) }) describe('confirm two creations one after the other quickly', () => { diff --git a/backend/src/graphql/resolver/ContributionResolver.ts b/backend/src/graphql/resolver/ContributionResolver.ts index c46a49555..926742d8a 100644 --- a/backend/src/graphql/resolver/ContributionResolver.ts +++ b/backend/src/graphql/resolver/ContributionResolver.ts @@ -55,6 +55,7 @@ import { sendContributionDeniedEmail, } from '@/emails/sendEmailVariants' import { TRANSACTIONS_LOCK } from '@/util/TRANSACTIONS_LOCK' +import LogError from '@/server/LogError' import { getLastTransaction } from './util/getLastTransaction' @@ -67,14 +68,11 @@ export class ContributionResolver { @Ctx() context: Context, ): Promise { const clientTimezoneOffset = getClientTimezoneOffset(context) - if (memo.length > MEMO_MAX_CHARS) { - logger.error(`memo text is too long: memo.length=${memo.length} > ${MEMO_MAX_CHARS}`) - throw new Error(`memo text is too long (${MEMO_MAX_CHARS} characters maximum)`) - } - if (memo.length < MEMO_MIN_CHARS) { - logger.error(`memo text is too short: memo.length=${memo.length} < ${MEMO_MIN_CHARS}`) - throw new Error(`memo text is too short (${MEMO_MIN_CHARS} characters minimum)`) + throw new LogError('Memo text is too short', memo.length) + } + if (memo.length > MEMO_MAX_CHARS) { + throw new LogError('Memo text is too long', memo.length) } const event = new Event() @@ -116,16 +114,13 @@ export class ContributionResolver { const user = getUser(context) const contribution = await DbContribution.findOne(id) if (!contribution) { - logger.error('Contribution not found for given id') - throw new Error('Contribution not found for given id.') + throw new LogError('Contribution not found', id) } if (contribution.userId !== user.id) { - logger.error('Can not delete contribution of another user') - throw new Error('Can not delete contribution of another user') + throw new LogError('Can not delete contribution of another user', contribution, user.id) } if (contribution.confirmedAt) { - logger.error('A confirmed contribution can not be deleted') - throw new Error('A confirmed contribution can not be deleted') + throw new LogError('A confirmed contribution can not be deleted', contribution) } contribution.contributionStatus = ContributionStatus.DELETED @@ -219,14 +214,11 @@ export class ContributionResolver { @Ctx() context: Context, ): Promise { const clientTimezoneOffset = getClientTimezoneOffset(context) - if (memo.length > MEMO_MAX_CHARS) { - logger.error(`memo text is too long: memo.length=${memo.length} > ${MEMO_MAX_CHARS}`) - throw new Error(`memo text is too long (${MEMO_MAX_CHARS} characters maximum)`) - } - if (memo.length < MEMO_MIN_CHARS) { - logger.error(`memo text is too short: memo.length=${memo.length} < ${MEMO_MIN_CHARS}`) - throw new Error(`memo text is too short (${MEMO_MIN_CHARS} characters minimum)`) + throw new LogError('Memo text is too short', memo.length) + } + if (memo.length > MEMO_MAX_CHARS) { + throw new LogError('Memo text is too long', memo.length) } const user = getUser(context) @@ -235,22 +227,22 @@ export class ContributionResolver { where: { id: contributionId, confirmedAt: IsNull(), deniedAt: IsNull() }, }) if (!contributionToUpdate) { - logger.error('No contribution found to given id') - throw new Error('No contribution found to given id.') + throw new LogError('Contribution not found', contributionId) } if (contributionToUpdate.userId !== user.id) { - logger.error('user of the pending contribution and send user does not correspond') - throw new Error('user of the pending contribution and send user does not correspond') + throw new LogError( + 'Can not update contribution of another user', + contributionToUpdate, + user.id, + ) } if ( contributionToUpdate.contributionStatus !== ContributionStatus.IN_PROGRESS && contributionToUpdate.contributionStatus !== ContributionStatus.PENDING ) { - logger.error( - `Contribution can not be updated since the state is ${contributionToUpdate.contributionStatus}`, - ) - throw new Error( - `Contribution can not be updated since the state is ${contributionToUpdate.contributionStatus}`, + throw new LogError( + 'Contribution can not be updated due to status', + contributionToUpdate.contributionStatus, ) } const creationDateObj = new Date(creationDate) @@ -258,8 +250,7 @@ export class ContributionResolver { if (contributionToUpdate.contributionDate.getMonth() === creationDateObj.getMonth()) { creations = updateCreations(creations, contributionToUpdate, clientTimezoneOffset) } else { - logger.error('Currently the month of the contribution cannot change.') - throw new Error('Currently the month of the contribution cannot change.') + throw new LogError('Month of contribution can not be changed') } // all possible cases not to be true are thrown in this function @@ -310,29 +301,24 @@ export class ContributionResolver { ) const clientTimezoneOffset = getClientTimezoneOffset(context) if (!isValidDateString(creationDate)) { - logger.error(`invalid Date for creationDate=${creationDate}`) - throw new Error(`invalid Date for creationDate=${creationDate}`) + throw new LogError('CreationDate is invalid', creationDate) } const emailContact = await UserContact.findOne({ where: { email }, withDeleted: true, relations: ['user'], }) - if (!emailContact) { - logger.error(`Could not find user with email: ${email}`) - throw new Error(`Could not find user with email: ${email}`) + if (!emailContact || !emailContact.user) { + throw new LogError('Could not find user', email) } - if (emailContact.deletedAt) { - logger.error('This emailContact was deleted. Cannot create a contribution.') - throw new Error('This emailContact was deleted. Cannot create a contribution.') - } - if (emailContact.user.deletedAt) { - logger.error('This user was deleted. Cannot create a contribution.') - throw new Error('This user was deleted. Cannot create a contribution.') + if (emailContact.deletedAt || emailContact.user.deletedAt) { + throw new LogError('Cannot create contribution since the user was deleted', emailContact) } if (!emailContact.emailChecked) { - logger.error('Contribution could not be saved, Email is not activated') - throw new Error('Contribution could not be saved, Email is not activated') + throw new LogError( + 'Cannot create contribution since the users email is not activated', + emailContact, + ) } const event = new Event() @@ -405,18 +391,11 @@ export class ContributionResolver { withDeleted: true, relations: ['user'], }) - if (!emailContact) { - logger.error(`Could not find UserContact with email: ${email}`) - throw new Error(`Could not find UserContact with email: ${email}`) + if (!emailContact || !emailContact.user) { + throw new LogError('Could not find User', email) } - const user = emailContact.user - if (!user) { - logger.error(`Could not find User to emailContact: ${email}`) - throw new Error(`Could not find User to emailContact: ${email}`) - } - if (user.deletedAt) { - logger.error(`User was deleted (${email})`) - throw new Error(`User was deleted (${email})`) + if (emailContact.deletedAt || emailContact.user.deletedAt) { + throw new LogError('User was deleted', email) } const moderator = getUser(context) @@ -425,28 +404,25 @@ export class ContributionResolver { where: { id, confirmedAt: IsNull(), deniedAt: IsNull() }, }) if (!contributionToUpdate) { - logger.error('No contribution found to given id.') - throw new Error('No contribution found to given id.') + throw new LogError('Contribution not found', id) } - if (contributionToUpdate.userId !== user.id) { - logger.error('user of the pending contribution and send user does not correspond') - throw new Error('user of the pending contribution and send user does not correspond') + if (contributionToUpdate.userId !== emailContact.user.id) { + throw new LogError('User of the pending contribution and send user does not correspond') } if (contributionToUpdate.moderatorId === null) { - logger.error('An admin is not allowed to update a user contribution.') - throw new Error('An admin is not allowed to update a user contribution.') + throw new LogError('An admin is not allowed to update an user contribution') } const creationDateObj = new Date(creationDate) - let creations = await getUserCreation(user.id, clientTimezoneOffset) + let creations = await getUserCreation(emailContact.user.id, clientTimezoneOffset) + // TODO: remove this restriction if (contributionToUpdate.contributionDate.getMonth() === creationDateObj.getMonth()) { creations = updateCreations(creations, contributionToUpdate, clientTimezoneOffset) } else { - logger.error('Currently the month of the contribution cannot change.') - throw new Error('Currently the month of the contribution cannot change.') + throw new LogError('Month of contribution can not be changed') } // all possible cases not to be true are thrown in this function @@ -464,11 +440,11 @@ export class ContributionResolver { result.memo = contributionToUpdate.memo result.date = contributionToUpdate.contributionDate - result.creation = await getUserCreation(user.id, clientTimezoneOffset) + result.creation = await getUserCreation(emailContact.user.id, clientTimezoneOffset) const event = new Event() const eventAdminContributionUpdate = new EventAdminContributionUpdate() - eventAdminContributionUpdate.userId = user.id + eventAdminContributionUpdate.userId = emailContact.user.id eventAdminContributionUpdate.amount = amount eventAdminContributionUpdate.contributionId = contributionToUpdate.id await writeEvent(event.setEventAdminContributionUpdate(eventAdminContributionUpdate)) @@ -521,19 +497,17 @@ export class ContributionResolver { ): Promise { const contribution = await DbContribution.findOne(id) if (!contribution) { - logger.error(`Contribution not found for given id: ${id}`) - throw new Error('Contribution not found for given id.') + throw new LogError('Contribution not found', id) } if (contribution.confirmedAt) { - logger.error('A confirmed contribution can not be deleted') - throw new Error('A confirmed contribution can not be deleted') + throw new LogError('A confirmed contribution can not be deleted') } const moderator = getUser(context) if ( contribution.contributionType === ContributionType.USER && contribution.userId === moderator.id ) { - throw new Error('Own contribution can not be deleted as admin') + throw new LogError('Own contribution can not be deleted as admin') } const user = await DbUser.findOneOrFail( { id: contribution.userId }, @@ -575,29 +549,24 @@ export class ContributionResolver { const clientTimezoneOffset = getClientTimezoneOffset(context) const contribution = await DbContribution.findOne(id) if (!contribution) { - logger.error(`Contribution not found for given id: ${id}`) - throw new Error('Contribution not found to given id.') + throw new LogError('Contribution not found', id) } if (contribution.confirmedAt) { - logger.error(`Contribution already confirmd: ${id}`) - throw new Error('Contribution already confirmd.') + throw new LogError('Contribution already confirmed', id) } if (contribution.contributionStatus === 'DENIED') { - logger.error(`Contribution already denied: ${id}`) - throw new Error('Contribution already denied.') + throw new LogError('Contribution already denied', id) } const moderatorUser = getUser(context) if (moderatorUser.id === contribution.userId) { - logger.error('Moderator can not confirm own contribution') - throw new Error('Moderator can not confirm own contribution') + throw new LogError('Moderator can not confirm own contribution') } 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.') + throw new LogError('Can not confirm contribution since the user was deleted') } const creations = await getUserCreation(contribution.userId, clientTimezoneOffset, false) validateContribution( @@ -661,8 +630,7 @@ export class ContributionResolver { }) } catch (e) { await queryRunner.rollbackTransaction() - logger.error('Creation was not successful', e) - throw new Error('Creation was not successful.') + throw new LogError('Creation was not successful', e) } finally { await queryRunner.release() } @@ -737,17 +705,16 @@ export class ContributionResolver { deniedBy: IsNull(), }) if (!contributionToUpdate) { - logger.error(`Contribution not found for given id: ${id}`) - throw new Error(`Contribution not found for given id.`) + throw new LogError('Contribution not found', id) } if ( contributionToUpdate.contributionStatus !== ContributionStatus.IN_PROGRESS && contributionToUpdate.contributionStatus !== ContributionStatus.PENDING ) { - logger.error( - `Contribution state (${contributionToUpdate.contributionStatus}) is not allowed.`, + throw new LogError( + 'Status of the contribution is not allowed', + contributionToUpdate.contributionStatus, ) - throw new Error(`State of the contribution is not allowed.`) } const moderator = getUser(context) const user = await DbUser.findOne( @@ -755,10 +722,7 @@ export class ContributionResolver { { relations: ['emailContact'] }, ) if (!user) { - logger.error( - `Could not find User for the Contribution (userId: ${contributionToUpdate.userId}).`, - ) - throw new Error('Could not find User for the Contribution.') + throw new LogError('Could not find User of the Contribution', contributionToUpdate.userId) } contributionToUpdate.contributionStatus = ContributionStatus.DENIED