From 1626f28f2063d680c0c29d0d7da5d3634f34376a Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Fri, 10 Dec 2021 00:39:57 +0100 Subject: [PATCH 01/13] an incorrect login should always result in an error not in a request to reset the password --- frontend/src/views/Pages/Login.vue | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/frontend/src/views/Pages/Login.vue b/frontend/src/views/Pages/Login.vue index d5d3e25a4..0d51cc4c6 100755 --- a/frontend/src/views/Pages/Login.vue +++ b/frontend/src/views/Pages/Login.vue @@ -104,13 +104,8 @@ export default { this.$router.push('/overview') loader.hide() }) - .catch((error) => { - if (error.message.includes('No user with this credentials')) { - this.$toasted.global.error(this.$t('error.no-account')) - } else { - // : this.$t('error.no-email-verify') - this.$router.push('/reset/login') - } + .catch(() => { + this.$toasted.global.error(this.$t('error.no-account')) loader.hide() }) }, From 83a2269a42c413e68efd8d4c63e88464f526c389 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Fri, 10 Dec 2021 14:51:10 +0100 Subject: [PATCH 02/13] Update frontend/src/views/Pages/Login.vue Co-authored-by: Hannes Heine --- frontend/src/views/Pages/Login.vue | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/frontend/src/views/Pages/Login.vue b/frontend/src/views/Pages/Login.vue index 0d51cc4c6..8364f15ab 100755 --- a/frontend/src/views/Pages/Login.vue +++ b/frontend/src/views/Pages/Login.vue @@ -104,8 +104,11 @@ export default { this.$router.push('/overview') loader.hide() }) - .catch(() => { + .catch((error) => { this.$toasted.global.error(this.$t('error.no-account')) + if (error.message.uncludes('User email not validated')) { + this.$router.push('/reset/login') + } loader.hide() }) }, From 508bb774def07ba8381d942b8e60523cadd7eb79 Mon Sep 17 00:00:00 2001 From: Hannes Heine Date: Sat, 11 Dec 2021 06:17:45 +0100 Subject: [PATCH 03/13] Update Login.vue Correct own typo --- frontend/src/views/Pages/Login.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/views/Pages/Login.vue b/frontend/src/views/Pages/Login.vue index 8364f15ab..3f434268a 100755 --- a/frontend/src/views/Pages/Login.vue +++ b/frontend/src/views/Pages/Login.vue @@ -106,7 +106,7 @@ export default { }) .catch((error) => { this.$toasted.global.error(this.$t('error.no-account')) - if (error.message.uncludes('User email not validated')) { + if (error.message.includes('User email not validated')) { this.$router.push('/reset/login') } loader.hide() From 7b8426593eead482a43046ec50dd00f0e2b78267 Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Mon, 13 Dec 2021 10:38:05 +0100 Subject: [PATCH 04/13] Test redirect when no password is present --- frontend/src/views/Pages/Login.spec.js | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/frontend/src/views/Pages/Login.spec.js b/frontend/src/views/Pages/Login.spec.js index 34175d8b3..9e8be9342 100644 --- a/frontend/src/views/Pages/Login.spec.js +++ b/frontend/src/views/Pages/Login.spec.js @@ -251,6 +251,25 @@ describe('Login', () => { it('toasts an error message', () => { expect(toastErrorMock).toBeCalledWith('error.no-account') }) + + describe('login fails with "User email not validated"', () => { + beforeEach(async () => { + apolloQueryMock.mockRejectedValue({ + message: 'User email not validated', + }) + wrapper = Wrapper() + jest.clearAllMocks() + await wrapper.find('input[placeholder="Email"]').setValue('user@example.org') + await wrapper.find('input[placeholder="form.password"]').setValue('1234') + await flushPromises() + await wrapper.find('form').trigger('submit') + await flushPromises() + }) + + it('redirects to /reset/login', () => { + expect(mockRouterPush).toBeCalledWith('/reset/login') + }) + }) }) }) }) From 7341515dad84839c62ac9694d33ebcec32139e54 Mon Sep 17 00:00:00 2001 From: elweyn Date: Mon, 13 Dec 2021 12:02:21 +0100 Subject: [PATCH 05/13] Send to /thx/login not /reset/login so the user get's a message to check to validate his account. --- frontend/src/views/Pages/Login.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/views/Pages/Login.vue b/frontend/src/views/Pages/Login.vue index 3f434268a..d7f09ea4c 100755 --- a/frontend/src/views/Pages/Login.vue +++ b/frontend/src/views/Pages/Login.vue @@ -107,7 +107,7 @@ export default { .catch((error) => { this.$toasted.global.error(this.$t('error.no-account')) if (error.message.includes('User email not validated')) { - this.$router.push('/reset/login') + this.$router.push('/thx/login') } loader.hide() }) From f787a7470f92f648bd60f948c2b75d0c87e3c0f8 Mon Sep 17 00:00:00 2001 From: elweyn Date: Mon, 13 Dec 2021 12:33:36 +0100 Subject: [PATCH 06/13] Moved reverse of the getPendingCreations to the AdminResolver instead to do it in the CreationConfirm page. --- admin/src/pages/CreationConfirm.vue | 2 +- backend/src/graphql/resolver/AdminResolver.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/admin/src/pages/CreationConfirm.vue b/admin/src/pages/CreationConfirm.vue index 0f180ffbc..08a8f44b0 100644 --- a/admin/src/pages/CreationConfirm.vue +++ b/admin/src/pages/CreationConfirm.vue @@ -80,7 +80,7 @@ export default { }) .then((result) => { this.$store.commit('resetOpenCreations') - this.confirmResult = result.data.getPendingCreations.reverse() + this.confirmResult = result.data.getPendingCreations this.$store.commit('setOpenCreations', result.data.getPendingCreations.length) }) .catch((error) => { diff --git a/backend/src/graphql/resolver/AdminResolver.ts b/backend/src/graphql/resolver/AdminResolver.ts index 127e5f26c..97439a980 100644 --- a/backend/src/graphql/resolver/AdminResolver.ts +++ b/backend/src/graphql/resolver/AdminResolver.ts @@ -132,7 +132,7 @@ export class AdminResolver { return newPendingCreation }), ) - return pendingCreationsPromise + return pendingCreationsPromise.reverse() } @Mutation(() => Boolean) From 4c9ebea6b639614fa0ff4609b9a88c9394781e40 Mon Sep 17 00:00:00 2001 From: elweyn Date: Mon, 13 Dec 2021 13:16:27 +0100 Subject: [PATCH 07/13] Change the amount argument to float for creation of pending creation --- admin/src/graphql/createPendingCreation.js | 2 +- backend/src/graphql/arg/CreatePendingCreationArgs.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/admin/src/graphql/createPendingCreation.js b/admin/src/graphql/createPendingCreation.js index 72c3249de..183fa5b15 100644 --- a/admin/src/graphql/createPendingCreation.js +++ b/admin/src/graphql/createPendingCreation.js @@ -3,7 +3,7 @@ import gql from 'graphql-tag' export const createPendingCreation = gql` mutation ( $email: String! - $amount: Int! + $amount: Float! $memo: String! $creationDate: String! $moderator: Int! diff --git a/backend/src/graphql/arg/CreatePendingCreationArgs.ts b/backend/src/graphql/arg/CreatePendingCreationArgs.ts index d2c17abf1..dfd4a4e85 100644 --- a/backend/src/graphql/arg/CreatePendingCreationArgs.ts +++ b/backend/src/graphql/arg/CreatePendingCreationArgs.ts @@ -1,11 +1,11 @@ -import { ArgsType, Field, Int } from 'type-graphql' +import { ArgsType, Field, Float, Int } from 'type-graphql' @ArgsType() export default class CreatePendingCreationArgs { @Field(() => String) email: string - @Field(() => Int) + @Field(() => Float) amount: number @Field(() => String) From 67a9f2d0e0eddc5b2d4ab9cdd4a5673ca32a4f48 Mon Sep 17 00:00:00 2001 From: elweyn Date: Mon, 13 Dec 2021 13:17:04 +0100 Subject: [PATCH 08/13] Change the amount argument type to float for updatePendingCreation. --- admin/src/graphql/updatePendingCreation.js | 2 +- backend/src/graphql/arg/UpdatePendingCreationArgs.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/admin/src/graphql/updatePendingCreation.js b/admin/src/graphql/updatePendingCreation.js index b137d961c..77668f15b 100644 --- a/admin/src/graphql/updatePendingCreation.js +++ b/admin/src/graphql/updatePendingCreation.js @@ -4,7 +4,7 @@ export const updatePendingCreation = gql` mutation ( $id: Int! $email: String! - $amount: Int! + $amount: Float! $memo: String! $creationDate: String! $moderator: Int! diff --git a/backend/src/graphql/arg/UpdatePendingCreationArgs.ts b/backend/src/graphql/arg/UpdatePendingCreationArgs.ts index bde7133aa..8cd9ccc4c 100644 --- a/backend/src/graphql/arg/UpdatePendingCreationArgs.ts +++ b/backend/src/graphql/arg/UpdatePendingCreationArgs.ts @@ -1,4 +1,4 @@ -import { ArgsType, Field, Int } from 'type-graphql' +import { ArgsType, Field, Float, Int } from 'type-graphql' @ArgsType() export default class CreatePendingCreationArgs { @@ -8,7 +8,7 @@ export default class CreatePendingCreationArgs { @Field(() => String) email: string - @Field(() => Int) + @Field(() => Float) amount: number @Field(() => String) From 51333155c93cedb4d3344662d245be05f0293327 Mon Sep 17 00:00:00 2001 From: elweyn Date: Mon, 13 Dec 2021 13:19:00 +0100 Subject: [PATCH 09/13] Needs to have another logic to remove item from list if remove or if confirmed was successful. --- admin/src/components/UserTable.vue | 2 +- admin/src/pages/CreationConfirm.vue | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/admin/src/components/UserTable.vue b/admin/src/components/UserTable.vue index 4a8ca8e84..9a0e876b2 100644 --- a/admin/src/components/UserTable.vue +++ b/admin/src/components/UserTable.vue @@ -237,7 +237,7 @@ export default { }, }) .then(() => { - this.$emit('remove-confirm-result', item, 'remove') + this.$emit('remove-confirm-result', item, 'confirmed') }) .catch((error) => { this.$toasted.error(error.message) diff --git a/admin/src/pages/CreationConfirm.vue b/admin/src/pages/CreationConfirm.vue index 08a8f44b0..62e850537 100644 --- a/admin/src/pages/CreationConfirm.vue +++ b/admin/src/pages/CreationConfirm.vue @@ -51,9 +51,9 @@ export default { }, methods: { removeConfirmResult(e, event) { + let index = 0 + const findArr = this.confirmResult.find((arr) => arr.id === e.id) if (event === 'remove') { - let index = 0 - const findArr = this.confirmResult.find((arr) => arr.id === e.id) this.$apollo .mutate({ mutation: deletePendingCreation, @@ -70,6 +70,10 @@ export default { .catch((error) => { this.$toasted.error(error.message) }) + } else { + this.confirmResult.splice(index, 1) + this.$store.commit('openCreationsMinus', 1) + this.$toasted.success('Pending Creation has been deleted') } }, getPendingCreations() { From 3d1df54c69032a08d04678b71380cc5865006499 Mon Sep 17 00:00:00 2001 From: elweyn Date: Mon, 13 Dec 2021 16:19:39 +0100 Subject: [PATCH 10/13] Adding test for successful confirm. --- admin/src/pages/CreationConfirm.spec.js | 66 ++++++++++++++++++++++++- 1 file changed, 64 insertions(+), 2 deletions(-) diff --git a/admin/src/pages/CreationConfirm.spec.js b/admin/src/pages/CreationConfirm.spec.js index 90db3a93f..ed3d33543 100644 --- a/admin/src/pages/CreationConfirm.spec.js +++ b/admin/src/pages/CreationConfirm.spec.js @@ -81,7 +81,7 @@ describe('CreationConfirm', () => { }) }) - describe('confirm creation delete with success', () => { + describe('delete creation delete with success', () => { beforeEach(async () => { apolloQueryMock.mockResolvedValue({ data: { @@ -130,7 +130,7 @@ describe('CreationConfirm', () => { }) }) - describe('confirm creation delete with error', () => { + describe('delete creation delete with error', () => { beforeEach(async () => { apolloMutateMock.mockRejectedValue({ message: 'Ouchhh!' }) await wrapper @@ -143,6 +143,68 @@ describe('CreationConfirm', () => { }) }) + describe('confirm creation delete with success', () => { + beforeEach(async () => { + apolloQueryMock.mockResolvedValue({ + data: { + getPendingCreations: [ + { + id: 1, + firstName: 'Bibi', + lastName: 'Bloxberg', + email: 'bibi@bloxberg.de', + amount: 500, + memo: 'Danke für alles', + date: new Date(), + moderator: 0, + }, + { + id: 2, + firstName: 'Räuber', + lastName: 'Hotzenplotz', + email: 'raeuber@hotzenplotz.de', + amount: 1000000, + memo: 'Gut Ergatert', + date: new Date(), + moderator: 0, + }, + ], + }, + }) + await wrapper + .findComponent({ name: 'UserTable' }) + .vm.$emit('remove-confirm-result', { id: 1 }, 'confirmed') + }) + + it('calls the deletePendingCreation mutation', () => { + expect(apolloMutateMock).not.toBeCalledWith({ + mutation: deletePendingCreation, + variables: { id: 1 }, + }) + }) + + it('commits openCreationsMinus to store', () => { + expect(storeCommitMock).toBeCalledWith('openCreationsMinus', 1) + }) + + it('toasts a success message', () => { + expect(toastedSuccessMock).toBeCalledWith('Pending Creation has been deleted') + }) + }) + + describe('delete creation delete with error', () => { + beforeEach(async () => { + apolloMutateMock.mockRejectedValue({ message: 'Ouchhh!' }) + await wrapper + .findComponent({ name: 'UserTable' }) + .vm.$emit('remove-confirm-result', { id: 1 }, 'confirm') + }) + + it('toasts an error message', () => { + expect(toastedErrorMock).not.toBeCalledWith('Ouchhh!') + }) + }) + describe('server response is error', () => { beforeEach(() => { jest.clearAllMocks() From f1b28a640e5d27e2e51903165cec5a5fc10ad98b Mon Sep 17 00:00:00 2001 From: elweyn Date: Tue, 14 Dec 2021 08:09:47 +0100 Subject: [PATCH 11/13] In case where their is no password set now we need to send the user to a page to change his password. --- frontend/src/views/Pages/Login.vue | 2 ++ 1 file changed, 2 insertions(+) diff --git a/frontend/src/views/Pages/Login.vue b/frontend/src/views/Pages/Login.vue index d7f09ea4c..4d2b75d2a 100755 --- a/frontend/src/views/Pages/Login.vue +++ b/frontend/src/views/Pages/Login.vue @@ -108,6 +108,8 @@ export default { this.$toasted.global.error(this.$t('error.no-account')) if (error.message.includes('User email not validated')) { this.$router.push('/thx/login') + } else if (error.message.includes('User has no password set yet')) { + this.$router.push('/reset/login') } loader.hide() }) From 238352bf24728343732f2296b786be173a7b357e Mon Sep 17 00:00:00 2001 From: elweyn Date: Fri, 17 Dec 2021 09:05:24 +0100 Subject: [PATCH 12/13] Change the removeConfirmResult so we switch over the event possibilities instead of an if else logic. --- admin/src/pages/CreationConfirm.spec.js | 3 +- admin/src/pages/CreationConfirm.vue | 47 ++++++++++++++----------- 2 files changed, 27 insertions(+), 23 deletions(-) diff --git a/admin/src/pages/CreationConfirm.spec.js b/admin/src/pages/CreationConfirm.spec.js index ed3d33543..fb59d1598 100644 --- a/admin/src/pages/CreationConfirm.spec.js +++ b/admin/src/pages/CreationConfirm.spec.js @@ -194,14 +194,13 @@ describe('CreationConfirm', () => { describe('delete creation delete with error', () => { beforeEach(async () => { - apolloMutateMock.mockRejectedValue({ message: 'Ouchhh!' }) await wrapper .findComponent({ name: 'UserTable' }) .vm.$emit('remove-confirm-result', { id: 1 }, 'confirm') }) it('toasts an error message', () => { - expect(toastedErrorMock).not.toBeCalledWith('Ouchhh!') + expect(toastedErrorMock).toBeCalledWith('Case confirm is not supported') }) }) diff --git a/admin/src/pages/CreationConfirm.vue b/admin/src/pages/CreationConfirm.vue index 62e850537..578c9b23f 100644 --- a/admin/src/pages/CreationConfirm.vue +++ b/admin/src/pages/CreationConfirm.vue @@ -53,27 +53,32 @@ export default { removeConfirmResult(e, event) { let index = 0 const findArr = this.confirmResult.find((arr) => arr.id === e.id) - if (event === 'remove') { - this.$apollo - .mutate({ - mutation: deletePendingCreation, - variables: { - id: findArr.id, - }, - }) - .then((result) => { - index = this.confirmResult.indexOf(findArr) - this.confirmResult.splice(index, 1) - this.$store.commit('openCreationsMinus', 1) - this.$toasted.success('Pending Creation has been deleted') - }) - .catch((error) => { - this.$toasted.error(error.message) - }) - } else { - this.confirmResult.splice(index, 1) - this.$store.commit('openCreationsMinus', 1) - this.$toasted.success('Pending Creation has been deleted') + switch (event) { + case 'remove': + this.$apollo + .mutate({ + mutation: deletePendingCreation, + variables: { + id: findArr.id, + }, + }) + .then((result) => { + index = this.confirmResult.indexOf(findArr) + this.confirmResult.splice(index, 1) + this.$store.commit('openCreationsMinus', 1) + this.$toasted.success('Pending Creation has been deleted') + }) + .catch((error) => { + this.$toasted.error(error.message) + }) + break + case 'confirmed': + this.confirmResult.splice(index, 1) + this.$store.commit('openCreationsMinus', 1) + this.$toasted.success('Pending Creation has been deleted') + break + default: + this.$toasted.error('Case ' + event + ' is not supported') } }, getPendingCreations() { From 56802e967fe894f52566c313b86941778b73813e Mon Sep 17 00:00:00 2001 From: elweyn Date: Tue, 21 Dec 2021 15:32:13 +0100 Subject: [PATCH 13/13] Change the Test of login.vue so we check the redirections. --- frontend/src/views/Pages/Login.spec.js | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/frontend/src/views/Pages/Login.spec.js b/frontend/src/views/Pages/Login.spec.js index 9e8be9342..f9fde0e1e 100644 --- a/frontend/src/views/Pages/Login.spec.js +++ b/frontend/src/views/Pages/Login.spec.js @@ -266,6 +266,25 @@ describe('Login', () => { await flushPromises() }) + it('redirects to /thx/login', () => { + expect(mockRouterPush).toBeCalledWith('/thx/login') + }) + }) + + describe('login fails with "User has no password set yet"', () => { + beforeEach(async () => { + apolloQueryMock.mockRejectedValue({ + message: 'User has no password set yet', + }) + wrapper = Wrapper() + jest.clearAllMocks() + await wrapper.find('input[placeholder="Email"]').setValue('user@example.org') + await wrapper.find('input[placeholder="form.password"]').setValue('1234') + await flushPromises() + await wrapper.find('form').trigger('submit') + await flushPromises() + }) + it('redirects to /reset/login', () => { expect(mockRouterPush).toBeCalledWith('/reset/login') })