From ded649f342a61798b521ff68406a8549efeedff0 Mon Sep 17 00:00:00 2001 From: joseji Date: Thu, 15 Sep 2022 11:42:03 +0200 Subject: [PATCH 1/5] Events and logs completed in User Resolver --- .../src/graphql/resolver/UserResolver.test.ts | 67 +++++++++++++++++-- backend/src/graphql/resolver/UserResolver.ts | 6 +- 2 files changed, 64 insertions(+), 9 deletions(-) diff --git a/backend/src/graphql/resolver/UserResolver.test.ts b/backend/src/graphql/resolver/UserResolver.test.ts index 36bae56de..58d697d8e 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,14 @@ 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, + }), + ) + }) }) describe('email already exists', () => { @@ -383,6 +393,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 +419,10 @@ bei Gradidio sei dabei!`, }), ) }) + + it('logs the error found', () => { + expect(logger.error).toBeCalledWith('Could not login with emailVerificationCode') + }) }) }) @@ -433,6 +451,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 +497,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 +505,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.') + }) }) }) @@ -595,6 +620,14 @@ bei Gradidio sei dabei!`, }), ) }) + + it('stores the login event in the database', () => { + expect(EventProtocol.find()).resolves.toContainEqual( + expect.objectContaining({ + type: EventProtocolType.LOGIN, + }), + ) + }) }) }) }) @@ -649,13 +682,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 +803,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 +817,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 +840,10 @@ bei Gradidio sei dabei!`, }), ) }) + + it('logs the error found', () => { + expect(logger.error).toBeCalledWith(`Old password is invalid`) + }) }) describe('invalid new password', () => { @@ -821,6 +866,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 +889,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 +909,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 +924,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..2e2f5aeec 100644 --- a/backend/src/graphql/resolver/UserResolver.ts +++ b/backend/src/graphql/resolver/UserResolver.ts @@ -273,7 +273,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 +389,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 +548,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!', ) @@ -727,6 +728,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) }) From 390bb1db3de2c1621a2e44a502737056c352ce9a Mon Sep 17 00:00:00 2001 From: joseji Date: Fri, 16 Sep 2022 12:22:32 +0200 Subject: [PATCH 2/5] IDs also tested while event saving, added ActivateAccount event when setting password --- backend/src/graphql/resolver/UserResolver.test.ts | 12 ++++++++++++ backend/src/graphql/resolver/UserResolver.ts | 6 ++++++ 2 files changed, 18 insertions(+) diff --git a/backend/src/graphql/resolver/UserResolver.test.ts b/backend/src/graphql/resolver/UserResolver.test.ts index 58d697d8e..2c6406939 100644 --- a/backend/src/graphql/resolver/UserResolver.test.ts +++ b/backend/src/graphql/resolver/UserResolver.test.ts @@ -176,6 +176,7 @@ describe('UserResolver', () => { expect(EventProtocol.find()).resolves.toContainEqual( expect.objectContaining({ type: EventProtocolType.SEND_CONFIRMATION_EMAIL, + userId: expect.any(Number), // as it is randomly generated }), ) }) @@ -255,6 +256,7 @@ 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() @@ -281,6 +283,15 @@ describe('UserResolver', () => { }), ) }) + + it('stores the account activated event in the database', () => { + expect(EventProtocol.find()).resolves.toContainEqual( + expect.objectContaining({ + type: EventProtocolType.ACTIVATE_ACCOUNT, + userId: expect.any(Number), // as it is randomly generated + }), + ) + }) }) /* A transaction link requires GDD on account @@ -625,6 +636,7 @@ bei Gradidio sei dabei!`, expect(EventProtocol.find()).resolves.toContainEqual( expect.objectContaining({ type: EventProtocolType.LOGIN, + userId: expect.any(Number), // as it is randomly generated }), ) }) diff --git a/backend/src/graphql/resolver/UserResolver.ts b/backend/src/graphql/resolver/UserResolver.ts index 2e2f5aeec..fad0fadd3 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' @@ -611,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) => { @@ -619,6 +622,9 @@ 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() From cfdec3d1226a029e719d28d0db5c09cccf267bd2 Mon Sep 17 00:00:00 2001 From: joseji Date: Fri, 16 Sep 2022 13:45:20 +0200 Subject: [PATCH 3/5] Fixed wrong handling of dates in tests failing depending on the day you execute them --- backend/src/graphql/resolver/UserResolver.test.ts | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/backend/src/graphql/resolver/UserResolver.test.ts b/backend/src/graphql/resolver/UserResolver.test.ts index 2c6406939..367f82b4f 100644 --- a/backend/src/graphql/resolver/UserResolver.test.ts +++ b/backend/src/graphql/resolver/UserResolver.test.ts @@ -261,14 +261,21 @@ describe('UserResolver', () => { 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, From 5f94cfca88de2896624a8de48c4457adf8331556 Mon Sep 17 00:00:00 2001 From: jjimenezgarcia <99907380+jjimenezgarcia@users.noreply.github.com> Date: Mon, 19 Sep 2022 15:40:59 +0200 Subject: [PATCH 4/5] Update backend/src/graphql/resolver/UserResolver.test.ts Co-authored-by: Moriz Wahl --- backend/src/graphql/resolver/UserResolver.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/graphql/resolver/UserResolver.test.ts b/backend/src/graphql/resolver/UserResolver.test.ts index 367f82b4f..5be3c3e20 100644 --- a/backend/src/graphql/resolver/UserResolver.test.ts +++ b/backend/src/graphql/resolver/UserResolver.test.ts @@ -176,7 +176,7 @@ describe('UserResolver', () => { expect(EventProtocol.find()).resolves.toContainEqual( expect.objectContaining({ type: EventProtocolType.SEND_CONFIRMATION_EMAIL, - userId: expect.any(Number), // as it is randomly generated + userId: user.id, }), ) }) From 1203dada61f234a8afc8ca4878c06b7fccb44a5b Mon Sep 17 00:00:00 2001 From: joseji Date: Mon, 19 Sep 2022 19:18:06 +0200 Subject: [PATCH 5/5] ids are now checked in event creation --- backend/src/graphql/resolver/UserResolver.test.ts | 9 ++++++--- backend/src/graphql/resolver/UserResolver.ts | 2 ++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/backend/src/graphql/resolver/UserResolver.test.ts b/backend/src/graphql/resolver/UserResolver.test.ts index 5be3c3e20..13715e088 100644 --- a/backend/src/graphql/resolver/UserResolver.test.ts +++ b/backend/src/graphql/resolver/UserResolver.test.ts @@ -176,7 +176,7 @@ describe('UserResolver', () => { expect(EventProtocol.find()).resolves.toContainEqual( expect.objectContaining({ type: EventProtocolType.SEND_CONFIRMATION_EMAIL, - userId: user.id, + userId: user[0].id, }), ) }) @@ -295,7 +295,7 @@ describe('UserResolver', () => { expect(EventProtocol.find()).resolves.toContainEqual( expect.objectContaining({ type: EventProtocolType.ACTIVATE_ACCOUNT, - userId: expect.any(Number), // as it is randomly generated + userId: user[0].id, }), ) }) @@ -605,6 +605,8 @@ bei Gradidio sei dabei!`, }) describe('authenticated', () => { + let user: User[] + const variables = { email: 'bibi@bloxberg.de', password: 'Aa12345_', @@ -612,6 +614,7 @@ bei Gradidio sei dabei!`, beforeAll(async () => { await query({ query: login, variables }) + user = await User.find() }) afterAll(() => { @@ -643,7 +646,7 @@ bei Gradidio sei dabei!`, expect(EventProtocol.find()).resolves.toContainEqual( expect.objectContaining({ type: EventProtocolType.LOGIN, - userId: expect.any(Number), // as it is randomly generated + userId: user[0].id, }), ) }) diff --git a/backend/src/graphql/resolver/UserResolver.ts b/backend/src/graphql/resolver/UserResolver.ts index fad0fadd3..f2fd048fc 100644 --- a/backend/src/graphql/resolver/UserResolver.ts +++ b/backend/src/graphql/resolver/UserResolver.ts @@ -622,9 +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()