From 789d166b94bd578b2298c92e9f3b12560731b579 Mon Sep 17 00:00:00 2001 From: einhorn_b Date: Thu, 30 Nov 2023 18:38:38 +0100 Subject: [PATCH] fix backend tests --- .../ContributionMessageResolver.test.ts | 147 +++++++++++++----- .../UnconfirmedContributionAdmin.role.ts | 2 + ...nfirmedContributionAdminAddMessage.role.ts | 12 +- .../UnconfirmedContributionUser.role.ts | 2 + ...onfirmedContributionUserAddMessage.role.ts | 7 + backend/src/seeds/graphql/mutations.ts | 1 + 6 files changed, 133 insertions(+), 38 deletions(-) diff --git a/backend/src/graphql/resolver/ContributionMessageResolver.test.ts b/backend/src/graphql/resolver/ContributionMessageResolver.test.ts index a6e7d8867..552b3985c 100644 --- a/backend/src/graphql/resolver/ContributionMessageResolver.test.ts +++ b/backend/src/graphql/resolver/ContributionMessageResolver.test.ts @@ -24,6 +24,7 @@ import { } from '@/seeds/graphql/mutations' import { listContributionMessages, adminListContributionMessages } from '@/seeds/graphql/queries' import { bibiBloxberg } from '@/seeds/users/bibi-bloxberg' +import { bobBaumeister } from '@/seeds/users/bob-baumeister' import { peterLustig } from '@/seeds/users/peter-lustig' jest.mock('@/emails/sendEmailVariants', () => { @@ -78,6 +79,7 @@ describe('ContributionMessageResolver', () => { beforeAll(async () => { await userFactory(testEnv, bibiBloxberg) await userFactory(testEnv, peterLustig) + await userFactory(testEnv, bobBaumeister) await mutate({ mutation: login, variables: { email: 'bibi@bloxberg.de', password: 'Aa12345_' }, @@ -129,7 +131,7 @@ describe('ContributionMessageResolver', () => { ) }) - it('throws error when contribution.userId equals user.id', async () => { + it('treat the logged-in user as a normal user, not as a moderator or admin if contribution.userId equals user.id', async () => { jest.clearAllMocks() await mutate({ mutation: login, @@ -143,29 +145,30 @@ describe('ContributionMessageResolver', () => { creationDate: new Date().toString(), }, }) - await expect( - mutate({ - mutation: adminCreateContributionMessage, - variables: { - contributionId: result2.data.createContribution.id, - message: 'Test', + const mutationResult = await mutate({ + mutation: adminCreateContributionMessage, + variables: { + contributionId: result2.data.createContribution.id, + message: 'Test', + }, + }) + expect(logger.debug).toBeCalledTimes(4) + expect(logger.debug).toHaveBeenNthCalledWith( + 4, + 'use UnconfirmedContributionUserAddMessageRole', + ) + expect(mutationResult).toEqual( + expect.objectContaining({ + data: { + adminCreateContributionMessage: expect.objectContaining({ + id: expect.any(Number), + message: 'Test', + type: 'DIALOG', + userFirstName: 'Peter', + userLastName: 'Lustig', + }), }, }), - ).resolves.toEqual( - expect.objectContaining({ - errors: [ - new GraphQLError( - 'ContributionMessage was not sent successfully: Error: Admin can not answer on his own contribution', - ), - ], - }), - ) - }) - - it('logs the error "ContributionMessage was not sent successfully: Error: Admin can not answer on his own contribution"', () => { - expect(logger.error).toBeCalledWith( - 'ContributionMessage was not sent successfully: Error: Admin can not answer on his own contribution', - new Error('Admin can not answer on his own contribution'), ) }) }) @@ -332,35 +335,84 @@ describe('ContributionMessageResolver', () => { ) }) - it('throws error when other user tries to send createContributionMessage', async () => { + it('other user tries to send createContributionMessage but is also moderator or admin so it is allowed', async () => { jest.clearAllMocks() await mutate({ mutation: login, variables: { email: 'peter@lustig.de', password: 'Aa12345_' }, }) - await expect( - mutate({ - mutation: createContributionMessage, - variables: { - contributionId: result.data.createContribution.id, - message: 'Test', + + const mutationResult = await mutate({ + mutation: createContributionMessage, + variables: { + contributionId: result.data.createContribution.id, + message: 'Test', + }, + }) + + expect(logger.debug).toBeCalledTimes(4) + expect(logger.debug).toHaveBeenNthCalledWith( + 4, + 'use UnconfirmedContributionAdminAddMessageRole', + ) + + expect(mutationResult).toEqual( + expect.objectContaining({ + data: { + createContributionMessage: expect.objectContaining({ + id: expect.any(Number), + message: 'Test', + type: 'DIALOG', + userFirstName: 'Peter', + userLastName: 'Lustig', + }), }, }), - ).resolves.toEqual( + ) + }) + + it('throws error when other user tries to send createContributionMessage', async () => { + jest.clearAllMocks() + const user = await mutate({ + mutation: login, + variables: { email: 'bob@baumeister.de', password: 'Aa12345_' }, + }) + const mutationResult = await mutate({ + mutation: createContributionMessage, + variables: { + contributionId: result.data.createContribution.id, + message: 'Test', + }, + }) + + expect(logger.debug).toBeCalledTimes(4) + expect(logger.debug).toHaveBeenNthCalledWith( + 4, + 'use UnconfirmedContributionAdminAddMessageRole', + ) + + expect(mutationResult).toEqual( expect.objectContaining({ errors: [ new GraphQLError( - 'ContributionMessage was not sent successfully: Error: Can not send message to contribution of another user', + 'ContributionMessage was not sent successfully: Error: missing right ADMIN_CREATE_CONTRIBUTION_MESSAGE for user', ), ], }), ) }) - it('logs the error "ContributionMessage was not sent successfully: Error: Can not send message to contribution of another user"', () => { - expect(logger.error).toBeCalledWith( - 'ContributionMessage was not sent successfully: Error: Can not send message to contribution of another user', - new Error('Can not send message to contribution of another user'), + it('logs the error "ContributionMessage was not sent successfully: Error: missing right ADMIN_CREATE_CONTRIBUTION_MESSAGE for user"', () => { + expect(logger.debug).toBeCalledTimes(4) + expect(logger.error).toHaveBeenNthCalledWith( + 1, + 'missing right ADMIN_CREATE_CONTRIBUTION_MESSAGE for user', + expect.any(Number), + ) + expect(logger.error).toHaveBeenNthCalledWith( + 2, + 'ContributionMessage was not sent successfully: Error: missing right ADMIN_CREATE_CONTRIBUTION_MESSAGE for user', + new Error('missing right ADMIN_CREATE_CONTRIBUTION_MESSAGE for user'), ) }) }) @@ -450,13 +502,22 @@ describe('ContributionMessageResolver', () => { expect.objectContaining({ data: { listContributionMessages: { - count: 2, + count: 3, messages: expect.arrayContaining([ expect.objectContaining({ id: expect.any(Number), message: 'Admin Test', type: 'DIALOG', userFirstName: 'Peter', + userId: expect.any(Number), + userLastName: 'Lustig', + }), + expect.objectContaining({ + id: expect.any(Number), + message: 'Test', + type: 'DIALOG', + userFirstName: 'Peter', + userId: expect.any(Number), userLastName: 'Lustig', }), expect.objectContaining({ @@ -464,6 +525,7 @@ describe('ContributionMessageResolver', () => { message: 'User Test', type: 'DIALOG', userFirstName: 'Bibi', + userId: expect.any(Number), userLastName: 'Bloxberg', }), ]), @@ -535,13 +597,22 @@ describe('ContributionMessageResolver', () => { expect.objectContaining({ data: { adminListContributionMessages: { - count: 3, + count: 4, messages: expect.arrayContaining([ expect.objectContaining({ id: expect.any(Number), message: 'Admin Test', type: 'DIALOG', userFirstName: 'Peter', + userId: expect.any(Number), + userLastName: 'Lustig', + }), + expect.objectContaining({ + id: expect.any(Number), + message: 'Test', + type: 'DIALOG', + userFirstName: 'Peter', + userId: expect.any(Number), userLastName: 'Lustig', }), expect.objectContaining({ @@ -549,6 +620,7 @@ describe('ContributionMessageResolver', () => { message: 'User Test', type: 'DIALOG', userFirstName: 'Bibi', + userId: expect.any(Number), userLastName: 'Bloxberg', }), expect.objectContaining({ @@ -556,6 +628,7 @@ describe('ContributionMessageResolver', () => { message: 'Internal moderator communication', type: 'MODERATOR', userFirstName: 'Peter', + userId: expect.any(Number), userLastName: 'Lustig', }), ]), diff --git a/backend/src/interactions/updateUnconfirmedContribution/UnconfirmedContributionAdmin.role.ts b/backend/src/interactions/updateUnconfirmedContribution/UnconfirmedContributionAdmin.role.ts index b6c21e9bd..96f1cf767 100644 --- a/backend/src/interactions/updateUnconfirmedContribution/UnconfirmedContributionAdmin.role.ts +++ b/backend/src/interactions/updateUnconfirmedContribution/UnconfirmedContributionAdmin.role.ts @@ -7,6 +7,7 @@ import { ContributionMessageBuilder } from '@/data/ContributionMessage.builder' import { AdminUpdateContributionArgs } from '@/graphql/arg/AdminUpdateContributionArgs' import { ContributionStatus } from '@/graphql/enum/ContributionStatus' import { LogError } from '@/server/LogError' +import { backendLogger as logger } from '@/server/logger' import { AbstractUnconfirmedContributionRole } from './AbstractUnconfirmedContribution.role' @@ -25,6 +26,7 @@ export class UnconfirmedContributionAdminRole extends AbstractUnconfirmedContrib updateData.amount ?? contribution.amount, updateData.creationDate ? new Date(updateData.creationDate) : contribution.contributionDate, ) + logger.debug('use UnconfirmedContributionAdminRole') } /** diff --git a/backend/src/interactions/updateUnconfirmedContribution/UnconfirmedContributionAdminAddMessage.role.ts b/backend/src/interactions/updateUnconfirmedContribution/UnconfirmedContributionAdminAddMessage.role.ts index 2ab7bfb46..df25249d0 100644 --- a/backend/src/interactions/updateUnconfirmedContribution/UnconfirmedContributionAdminAddMessage.role.ts +++ b/backend/src/interactions/updateUnconfirmedContribution/UnconfirmedContributionAdminAddMessage.role.ts @@ -6,8 +6,13 @@ import { ContributionMessageArgs } from '@/graphql/arg/ContributionMessageArgs' import { ContributionMessageType } from '@/graphql/enum/ContributionMessageType' import { ContributionStatus } from '@/graphql/enum/ContributionStatus' import { LogError } from '@/server/LogError' +import { backendLogger as logger } from '@/server/logger' import { AbstractUnconfirmedContributionRole } from './AbstractUnconfirmedContribution.role' +import { Role } from '@/auth/Role' +import { RoleNames } from '@/graphql/enum/RoleNames' +import { RIGHTS } from '@/auth/RIGHTS' +import { Authorized } from 'type-graphql' /** * This role will be used for Moderators and Admins which want to comment a contribution @@ -16,6 +21,7 @@ import { AbstractUnconfirmedContributionRole } from './AbstractUnconfirmedContri export class UnconfirmedContributionAdminAddMessageRole extends AbstractUnconfirmedContributionRole { public constructor(contribution: Contribution, private updateData: ContributionMessageArgs) { super(contribution, contribution.amount, contribution.contributionDate) + logger.debug('use UnconfirmedContributionAdminAddMessageRole') } protected update(): void { @@ -38,7 +44,11 @@ export class UnconfirmedContributionAdminAddMessageRole extends AbstractUnconfir } } - protected checkAuthorization(user: User): AbstractUnconfirmedContributionRole { + protected checkAuthorization(user: User, role: Role): AbstractUnconfirmedContributionRole { + if (!role.hasRight(RIGHTS.ADMIN_CREATE_CONTRIBUTION_MESSAGE)) { + throw new LogError('missing right ADMIN_CREATE_CONTRIBUTION_MESSAGE for user', user.id) + } + // TODO: think if there are cases in which admin comment his own contribution if ( this.self.userId === user.id && diff --git a/backend/src/interactions/updateUnconfirmedContribution/UnconfirmedContributionUser.role.ts b/backend/src/interactions/updateUnconfirmedContribution/UnconfirmedContributionUser.role.ts index 94686b8ca..671756cf7 100644 --- a/backend/src/interactions/updateUnconfirmedContribution/UnconfirmedContributionUser.role.ts +++ b/backend/src/interactions/updateUnconfirmedContribution/UnconfirmedContributionUser.role.ts @@ -5,6 +5,7 @@ import { ContributionMessageBuilder } from '@/data/ContributionMessage.builder' import { ContributionArgs } from '@/graphql/arg/ContributionArgs' import { ContributionStatus } from '@/graphql/enum/ContributionStatus' import { LogError } from '@/server/LogError' +import { backendLogger as logger } from '@/server/logger' import { AbstractUnconfirmedContributionRole } from './AbstractUnconfirmedContribution.role' @@ -15,6 +16,7 @@ import { AbstractUnconfirmedContributionRole } from './AbstractUnconfirmedContri export class UnconfirmedContributionUserRole extends AbstractUnconfirmedContributionRole { public constructor(contribution: Contribution, private updateData: ContributionArgs) { super(contribution, updateData.amount, new Date(updateData.creationDate)) + logger.debug('use UnconfirmedContributionUserRole') } protected update(): void { diff --git a/backend/src/interactions/updateUnconfirmedContribution/UnconfirmedContributionUserAddMessage.role.ts b/backend/src/interactions/updateUnconfirmedContribution/UnconfirmedContributionUserAddMessage.role.ts index f7576fa80..e33dea71e 100644 --- a/backend/src/interactions/updateUnconfirmedContribution/UnconfirmedContributionUserAddMessage.role.ts +++ b/backend/src/interactions/updateUnconfirmedContribution/UnconfirmedContributionUserAddMessage.role.ts @@ -3,8 +3,10 @@ import { User } from '@entity/User' import { ContributionMessageBuilder } from '@/data/ContributionMessage.builder' import { ContributionMessageArgs } from '@/graphql/arg/ContributionMessageArgs' +import { ContributionMessageType } from '@/graphql/enum/ContributionMessageType' import { ContributionStatus } from '@/graphql/enum/ContributionStatus' import { LogError } from '@/server/LogError' +import { backendLogger as logger } from '@/server/logger' import { AbstractUnconfirmedContributionRole } from './AbstractUnconfirmedContribution.role' @@ -15,6 +17,7 @@ import { AbstractUnconfirmedContributionRole } from './AbstractUnconfirmedContri export class UnconfirmedContributionUserAddMessageRole extends AbstractUnconfirmedContributionRole { public constructor(contribution: Contribution, private updateData: ContributionMessageArgs) { super(contribution, contribution.amount, contribution.contributionDate) + logger.debug('use UnconfirmedContributionUserAddMessageRole') } protected update(): void { @@ -34,6 +37,7 @@ export class UnconfirmedContributionUserAddMessageRole extends AbstractUnconfirm throw new LogError('Can not update contribution of another user', this.self, user.id) } // only admins and moderators can update it when status is other than progress or pending + // but we are in the user add message role.. we are currently not admin or moderator if ( this.self.contributionStatus !== ContributionStatus.IN_PROGRESS && this.self.contributionStatus !== ContributionStatus.PENDING @@ -43,6 +47,9 @@ export class UnconfirmedContributionUserAddMessageRole extends AbstractUnconfirm this.self.contributionStatus, ) } + if (this.updateData.messageType !== ContributionMessageType.DIALOG) { + throw new LogError('unexpected contribution message type, only dialog is allowed for user') + } return this } diff --git a/backend/src/seeds/graphql/mutations.ts b/backend/src/seeds/graphql/mutations.ts index 305af4939..981bb0da6 100644 --- a/backend/src/seeds/graphql/mutations.ts +++ b/backend/src/seeds/graphql/mutations.ts @@ -262,6 +262,7 @@ export const createContribution = gql` id amount memo + userId } } `