From e3e5fdd12b4566287bd9e28b8761c73b8ef22abd Mon Sep 17 00:00:00 2001 From: ogerly Date: Fri, 16 Sep 2022 08:22:24 +0200 Subject: [PATCH 01/10] remove modal box if redeem a redeemlink --- .../LinkInformations/RedeemValid.vue | 2 +- frontend/src/pages/TransactionLink.spec.js | 56 +++++++++---------- frontend/src/pages/TransactionLink.vue | 7 +-- 3 files changed, 30 insertions(+), 35 deletions(-) diff --git a/frontend/src/components/LinkInformations/RedeemValid.vue b/frontend/src/components/LinkInformations/RedeemValid.vue index 353fefaf8..c468a396a 100644 --- a/frontend/src/components/LinkInformations/RedeemValid.vue +++ b/frontend/src/components/LinkInformations/RedeemValid.vue @@ -3,7 +3,7 @@
- + {{ $t('gdd_per_link.redeem') }}
diff --git a/frontend/src/pages/TransactionLink.spec.js b/frontend/src/pages/TransactionLink.spec.js index b1bbd8950..fd58d6e1c 100644 --- a/frontend/src/pages/TransactionLink.spec.js +++ b/frontend/src/pages/TransactionLink.spec.js @@ -282,18 +282,18 @@ describe('TransactionLink', () => { }) describe('redeem link with success', () => { - let spy + // let spy beforeEach(async () => { - spy = jest.spyOn(wrapper.vm.$bvModal, 'msgBoxConfirm') + // spy = jest.spyOn(wrapper.vm.$bvModal, 'msgBoxConfirm') apolloMutateMock.mockResolvedValue() - spy.mockImplementation(() => Promise.resolve(true)) + // spy.mockImplementation(() => Promise.resolve(true)) await wrapper.findComponent({ name: 'RedeemValid' }).find('button').trigger('click') }) - it('opens the modal', () => { - expect(spy).toBeCalledWith('gdd_per_link.redeem-text') - }) + // it('opens the modal', () => { + // expect(spy).toBeCalledWith('gdd_per_link.redeem-text') + // }) it('calls the API', () => { expect(apolloMutateMock).toBeCalledWith( @@ -316,37 +316,37 @@ describe('TransactionLink', () => { }) }) - describe('cancel redeem link', () => { - let spy + // describe('cancel redeem link', () => { + // let spy - beforeEach(async () => { - spy = jest.spyOn(wrapper.vm.$bvModal, 'msgBoxConfirm') - apolloMutateMock.mockResolvedValue() - spy.mockImplementation(() => Promise.resolve(false)) - await wrapper.findComponent({ name: 'RedeemValid' }).find('button').trigger('click') - }) + // beforeEach(async () => { + // spy = jest.spyOn(wrapper.vm.$bvModal, 'msgBoxConfirm') + // apolloMutateMock.mockResolvedValue() + // spy.mockImplementation(() => Promise.resolve(false)) + // await wrapper.findComponent({ name: 'RedeemValid' }).find('button').trigger('click') + // }) - it('does not call the API', () => { - expect(apolloMutateMock).not.toBeCalled() - }) + // it('does not call the API', () => { + // expect(apolloMutateMock).not.toBeCalled() + // }) - it('does not toasts a success message', () => { - expect(mocks.$t).not.toBeCalledWith('gdd_per_link.redeemed', { n: '22' }) - expect(toastSuccessSpy).not.toBeCalled() - }) + // it('does not toasts a success message', () => { + // expect(mocks.$t).not.toBeCalledWith('gdd_per_link.redeemed', { n: '22' }) + // expect(toastSuccessSpy).not.toBeCalled() + // }) - it('does not push the route', () => { - expect(routerPushMock).not.toBeCalled() - }) - }) + // it('does not push the route', () => { + // expect(routerPushMock).not.toBeCalled() + // }) + // }) describe('redeem link with error', () => { - let spy + // let spy beforeEach(async () => { - spy = jest.spyOn(wrapper.vm.$bvModal, 'msgBoxConfirm') + // spy = jest.spyOn(wrapper.vm.$bvModal, 'msgBoxConfirm') apolloMutateMock.mockRejectedValue({ message: 'Oh Noo!' }) - spy.mockImplementation(() => Promise.resolve(true)) + // spy.mockImplementation(() => Promise.resolve(true)) await wrapper.findComponent({ name: 'RedeemValid' }).find('button').trigger('click') }) diff --git a/frontend/src/pages/TransactionLink.vue b/frontend/src/pages/TransactionLink.vue index 57236b55c..bd1909d7d 100644 --- a/frontend/src/pages/TransactionLink.vue +++ b/frontend/src/pages/TransactionLink.vue @@ -14,7 +14,7 @@ @@ -98,11 +98,6 @@ export default { this.$router.push('/overview') }) }, - redeemLink(amount) { - this.$bvModal.msgBoxConfirm(this.$t('gdd_per_link.redeem-text')).then((value) => { - if (value) this.mutationLink(amount) - }) - }, }, computed: { isContributionLink() { From caf487d2062667ac77794d0ea8624362b7737924 Mon Sep 17 00:00:00 2001 From: ogerly Date: Fri, 16 Sep 2022 08:24:31 +0200 Subject: [PATCH 02/10] remove text from modal for redeem link --- frontend/src/locales/de.json | 1 - frontend/src/locales/en.json | 1 - frontend/src/locales/es.json | 1 - frontend/src/locales/fr.json | 1 - frontend/src/locales/nl.json | 1 - frontend/src/pages/TransactionLink.spec.js | 34 ---------------------- 6 files changed, 39 deletions(-) diff --git a/frontend/src/locales/de.json b/frontend/src/locales/de.json index e6b12b0fa..1ed8af19f 100644 --- a/frontend/src/locales/de.json +++ b/frontend/src/locales/de.json @@ -178,7 +178,6 @@ "no-redeem": "Du darfst deinen eigenen Link nicht einlösen!", "not-copied": "Dein Gerät lässt das Kopieren leider nicht zu! Bitte kopiere den Link von Hand!", "redeem": "Einlösen", - "redeem-text": "Willst du den Betrag jetzt einlösen?", "redeemed": "Erfolgreich eingelöst! Deinem Konto wurden {n} GDD gutgeschrieben.", "redeemed-at": "Der Link wurde bereits am {date} eingelöst.", "redeemed-title": "eingelöst", diff --git a/frontend/src/locales/en.json b/frontend/src/locales/en.json index 07125eceb..113fa1cb9 100644 --- a/frontend/src/locales/en.json +++ b/frontend/src/locales/en.json @@ -178,7 +178,6 @@ "no-redeem": "You not allowed to redeem your own link!", "not-copied": "Unfortunately, your device does not allow copying! Please copy the link by hand!", "redeem": "Redeem", - "redeem-text": "Do you want to redeem the amount now?", "redeemed": "Successfully redeemed! Your account has been credited with {n} GDD.", "redeemed-at": "The link was already redeemed on {date}.", "redeemed-title": "redeemed", diff --git a/frontend/src/locales/es.json b/frontend/src/locales/es.json index 987bb71ef..b2a229f1c 100644 --- a/frontend/src/locales/es.json +++ b/frontend/src/locales/es.json @@ -180,7 +180,6 @@ "no-redeem": "No puedes canjear tu propio enlace!", "not-copied": "¡Desafortunadamente, su dispositivo no permite copiar! Copie el enlace manualmente!", "redeem": "Canjear", - "redeem-text": "¿Quieres canjear el importe ahora?", "redeemed": "¡Canjeado con éxito! Tu cuenta ha sido acreditada con {n} GDD.", "redeemed-at": "El enlace ya se canjeó el {date}.", "redeemed-title": "canjeado", diff --git a/frontend/src/locales/fr.json b/frontend/src/locales/fr.json index 61037af1a..e7ac18a18 100644 --- a/frontend/src/locales/fr.json +++ b/frontend/src/locales/fr.json @@ -180,7 +180,6 @@ "no-redeem": "Vous n´êtes pas autorisé à percevoir votre propre lien!", "not-copied": "Malheureusement votre appareil ne permet pas de copier! Veuillez copier le lien manuellement svp!", "redeem": "Encaisser", - "redeem-text": "Voulez-vous percevoir le montant maintenant?", "redeemed": "Encaissé avec succès! Votre compte est crédité de {n} GDD.", "redeemed-at": "Le lien a déjà été perçu le {date}.", "redeemed-title": "encaisser", diff --git a/frontend/src/locales/nl.json b/frontend/src/locales/nl.json index 99b972514..34f484fd7 100644 --- a/frontend/src/locales/nl.json +++ b/frontend/src/locales/nl.json @@ -180,7 +180,6 @@ "no-redeem": "Je mag je eigen link niet inwisselen!", "not-copied": "Jouw apparaat laat het kopiëren helaas niet toe! Kopieer de link alsjeblieft met de hand!", "redeem": "Inwisselen", - "redeem-text": "Wil je het bedrag nu inwisselen?", "redeemed": "Succesvol ingewisseld! Op jouw rekening werden {n} GDD bijgeschreven.", "redeemed-at": "De link werd al op {date} ingewisseld.", "redeemed-title": "ingewisseld", diff --git a/frontend/src/pages/TransactionLink.spec.js b/frontend/src/pages/TransactionLink.spec.js index fd58d6e1c..831502acd 100644 --- a/frontend/src/pages/TransactionLink.spec.js +++ b/frontend/src/pages/TransactionLink.spec.js @@ -282,19 +282,12 @@ describe('TransactionLink', () => { }) describe('redeem link with success', () => { - // let spy beforeEach(async () => { - // spy = jest.spyOn(wrapper.vm.$bvModal, 'msgBoxConfirm') apolloMutateMock.mockResolvedValue() - // spy.mockImplementation(() => Promise.resolve(true)) await wrapper.findComponent({ name: 'RedeemValid' }).find('button').trigger('click') }) - // it('opens the modal', () => { - // expect(spy).toBeCalledWith('gdd_per_link.redeem-text') - // }) - it('calls the API', () => { expect(apolloMutateMock).toBeCalledWith( expect.objectContaining({ @@ -316,37 +309,10 @@ describe('TransactionLink', () => { }) }) - // describe('cancel redeem link', () => { - // let spy - - // beforeEach(async () => { - // spy = jest.spyOn(wrapper.vm.$bvModal, 'msgBoxConfirm') - // apolloMutateMock.mockResolvedValue() - // spy.mockImplementation(() => Promise.resolve(false)) - // await wrapper.findComponent({ name: 'RedeemValid' }).find('button').trigger('click') - // }) - - // it('does not call the API', () => { - // expect(apolloMutateMock).not.toBeCalled() - // }) - - // it('does not toasts a success message', () => { - // expect(mocks.$t).not.toBeCalledWith('gdd_per_link.redeemed', { n: '22' }) - // expect(toastSuccessSpy).not.toBeCalled() - // }) - - // it('does not push the route', () => { - // expect(routerPushMock).not.toBeCalled() - // }) - // }) - describe('redeem link with error', () => { - // let spy beforeEach(async () => { - // spy = jest.spyOn(wrapper.vm.$bvModal, 'msgBoxConfirm') apolloMutateMock.mockRejectedValue({ message: 'Oh Noo!' }) - // spy.mockImplementation(() => Promise.resolve(true)) await wrapper.findComponent({ name: 'RedeemValid' }).find('button').trigger('click') }) From 222d8c2f579a936221c362a8f05921fc9c7fe359 Mon Sep 17 00:00:00 2001 From: ogerly Date: Fri, 16 Sep 2022 08:25:55 +0200 Subject: [PATCH 03/10] fix lint --- frontend/src/pages/TransactionLink.spec.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/frontend/src/pages/TransactionLink.spec.js b/frontend/src/pages/TransactionLink.spec.js index 831502acd..d5a75aa4a 100644 --- a/frontend/src/pages/TransactionLink.spec.js +++ b/frontend/src/pages/TransactionLink.spec.js @@ -282,7 +282,6 @@ describe('TransactionLink', () => { }) describe('redeem link with success', () => { - beforeEach(async () => { apolloMutateMock.mockResolvedValue() await wrapper.findComponent({ name: 'RedeemValid' }).find('button').trigger('click') @@ -310,7 +309,6 @@ describe('TransactionLink', () => { }) describe('redeem link with error', () => { - beforeEach(async () => { apolloMutateMock.mockRejectedValue({ message: 'Oh Noo!' }) await wrapper.findComponent({ name: 'RedeemValid' }).find('button').trigger('click') From b8442e172565baa6120a6fdee55458e61b6484fb Mon Sep 17 00:00:00 2001 From: joseji Date: Fri, 16 Sep 2022 13:42:45 +0200 Subject: [PATCH 04/10] added redeem register event test, transaction link execution failing --- .../src/graphql/resolver/UserResolver.test.ts | 45 ++++++++++++++++++- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/backend/src/graphql/resolver/UserResolver.test.ts b/backend/src/graphql/resolver/UserResolver.test.ts index 2c6406939..1103f8bf2 100644 --- a/backend/src/graphql/resolver/UserResolver.test.ts +++ b/backend/src/graphql/resolver/UserResolver.test.ts @@ -24,6 +24,8 @@ 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' +import { TransactionLink } from '@entity/TransactionLink' +import { transactionLinkFactory } from '@/seeds/factory/transactionLink' // import { klicktippSignIn } from '@/apis/KlicktippController' @@ -261,13 +263,19 @@ 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({ @@ -292,6 +300,39 @@ describe('UserResolver', () => { }), ) }) + + it('stores the redeem register event in the database', () => { + expect(EventProtocol.find()).resolves.toContainEqual( + expect.objectContaining({ + type: EventProtocolType.REDEEM_REGISTER, + userId: expect.any(Number), // as it is randomly generated + }), + ) + }) + }) + + describe('transaction link', () => { + beforeAll(async () => { + await transactionLinkFactory(testEnv, { + email: 'peter@lustig.de', + amount: 19.99, + memo: `Kein Trick, keine Zauberrei, + bei Gradidio sei dabei!`, + }) + + const transactionLink = await TransactionLink.findOneOrFail() + resetToken() + await mutate({ + mutation: createUser, + variables: { ...variables, email: 'neuer@user.de', redeemCode: transactionLink.code }, + }) + }) + + it('sets the referrer id to Peter Lustigs id', () => { + expect(User.findOne({ email: 'neuer@user.de' })).resolves.toEqual( + expect.objectContaining({ referrerId: user[0].id }), + ) + }) }) /* A transaction link requires GDD on account From a9cc4e9339d2539f9654fd6ef45f6698030ebb4c Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Mon, 19 Sep 2022 18:10:11 +0200 Subject: [PATCH 05/10] remove value column --- .../BusinessEventProtocol.md | 48 +++++++++---------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/docu/Concepts/TechnicalRequirements/BusinessEventProtocol.md b/docu/Concepts/TechnicalRequirements/BusinessEventProtocol.md index f8cf2cd03..58fe01fa0 100644 --- a/docu/Concepts/TechnicalRequirements/BusinessEventProtocol.md +++ b/docu/Concepts/TechnicalRequirements/BusinessEventProtocol.md @@ -6,30 +6,30 @@ With the business event protocol the gradido application will capture and persis The different event types will be defined as Enum. The following list is a first draft and will grow with further event types in the future. -| EventType | Value | Description | -| ----------------------------------- | ----- | ------------------------------------------------------------------------------------------------------ | -| BasicEvent | 0 | the basic event is the root of all further extending event types | -| VisitGradidoEvent | 10 | if a user visits a gradido page without login or register | -| RegisterEvent | 20 | the user presses the register button | -| RedeemRegisterEvent | 21 | the user presses the register button initiated by the redeem link | -| InActiveAccountEvent | 22 | the systems create an inactive account during the register process | -| SendConfirmEmailEvent | 23 | the system send a confirmation email to the user during the register process | -| ConfirmEmailEvent | 24 | the user confirms his email during the register process | -| RegisterEmailKlickTippEvent | 25 | the system registers the confirmed email at klicktipp | -| LoginEvent | 30 | the user presses the login button | -| RedeemLoginEvent | 31 | the user presses the login button initiated by the redeem link | -| ActivateAccountEvent | 32 | the system activates the users account during the first login process | -| PasswordChangeEvent | 33 | the user changes his password | -| TransactionSendEvent | 40 | the user creates a transaction and sends it online | -| TransactionSendRedeemEvent | 41 | the user creates a transaction and sends it per redeem link | -| TransactionRepeateRedeemEvent | 42 | the user recreates a redeem link of a still open transaction | -| TransactionCreationEvent | 50 | the user receives a creation transaction for his confirmed contribution | -| TransactionReceiveEvent | 51 | the user receives a transaction from an other user and posts the amount on his account | -| TransactionReceiveRedeemEvent | 52 | the user activates the redeem link and receives the transaction and posts the amount on his account | -| ContributionCreateEvent | 60 | the user enters his contribution and asks for confirmation | -| ContributionConfirmEvent | 61 | the user confirms a contribution of an other user (for future multi confirmation from several users) | -| ContributionLinkDefineEvent | 70 | the admin user defines a contributionLink, which could be send per Link/QR-Code on an other medium | -| ContributionLinkActivateRedeemEvent | 71 | the user activates a received contributionLink to create a contribution entry for the contributionLink | +| EventType | Description | +| ----------------------------------- | ------------------------------------------------------------------------------------------------------ | +| BasicEvent | the basic event is the root of all further extending event types | +| VisitGradidoEvent | if a user visits a gradido page without login or register | +| RegisterEvent | the user presses the register button | +| RedeemRegisterEvent | the user presses the register button initiated by the redeem link | +| InActiveAccountEvent | the systems create an inactive account during the register process | +| SendConfirmEmailEvent | the system send a confirmation email to the user during the register process | +| ConfirmEmailEvent | the user confirms his email during the register process | +| RegisterEmailKlickTippEvent | the system registers the confirmed email at klicktipp | +| LoginEvent | the user presses the login button | +| RedeemLoginEvent | the user presses the login button initiated by the redeem link | +| ActivateAccountEvent | the system activates the users account during the first login process | +| PasswordChangeEvent | the user changes his password | +| TransactionSendEvent | the user creates a transaction and sends it online | +| TransactionSendRedeemEvent | the user creates a transaction and sends it per redeem link | +| TransactionRepeateRedeemEvent | the user recreates a redeem link of a still open transaction | +| TransactionCreationEvent | the user receives a creation transaction for his confirmed contribution | +| TransactionReceiveEvent | the user receives a transaction from an other user and posts the amount on his account | +| TransactionReceiveRedeemEvent | the user activates the redeem link and receives the transaction and posts the amount on his account | +| ContributionCreateEvent | the user enters his contribution and asks for confirmation | +| ContributionConfirmEvent | the user confirms a contribution of an other user (for future multi confirmation from several users) | +| ContributionLinkDefineEvent | the admin user defines a contributionLink, which could be send per Link/QR-Code on an other medium | +| ContributionLinkActivateRedeemEvent | the user activates a received contributionLink to create a contribution entry for the contributionLink | ## EventProtocol - Entity From 70963203a001d868f0ac6366f34ae581ff5e5605 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Claus-Peter=20H=C3=BCbner?= Date: Tue, 20 Sep 2022 00:39:45 +0200 Subject: [PATCH 06/10] rework Event definitions --- .../BusinessEventProtocol.md | 121 +++++++++++------- 1 file changed, 72 insertions(+), 49 deletions(-) diff --git a/docu/Concepts/TechnicalRequirements/BusinessEventProtocol.md b/docu/Concepts/TechnicalRequirements/BusinessEventProtocol.md index 58fe01fa0..ecdf8df34 100644 --- a/docu/Concepts/TechnicalRequirements/BusinessEventProtocol.md +++ b/docu/Concepts/TechnicalRequirements/BusinessEventProtocol.md @@ -6,30 +6,41 @@ With the business event protocol the gradido application will capture and persis The different event types will be defined as Enum. The following list is a first draft and will grow with further event types in the future. -| EventType | Description | -| ----------------------------------- | ------------------------------------------------------------------------------------------------------ | -| BasicEvent | the basic event is the root of all further extending event types | -| VisitGradidoEvent | if a user visits a gradido page without login or register | -| RegisterEvent | the user presses the register button | -| RedeemRegisterEvent | the user presses the register button initiated by the redeem link | -| InActiveAccountEvent | the systems create an inactive account during the register process | -| SendConfirmEmailEvent | the system send a confirmation email to the user during the register process | -| ConfirmEmailEvent | the user confirms his email during the register process | -| RegisterEmailKlickTippEvent | the system registers the confirmed email at klicktipp | -| LoginEvent | the user presses the login button | -| RedeemLoginEvent | the user presses the login button initiated by the redeem link | -| ActivateAccountEvent | the system activates the users account during the first login process | -| PasswordChangeEvent | the user changes his password | -| TransactionSendEvent | the user creates a transaction and sends it online | -| TransactionSendRedeemEvent | the user creates a transaction and sends it per redeem link | -| TransactionRepeateRedeemEvent | the user recreates a redeem link of a still open transaction | -| TransactionCreationEvent | the user receives a creation transaction for his confirmed contribution | -| TransactionReceiveEvent | the user receives a transaction from an other user and posts the amount on his account | -| TransactionReceiveRedeemEvent | the user activates the redeem link and receives the transaction and posts the amount on his account | -| ContributionCreateEvent | the user enters his contribution and asks for confirmation | -| ContributionConfirmEvent | the user confirms a contribution of an other user (for future multi confirmation from several users) | -| ContributionLinkDefineEvent | the admin user defines a contributionLink, which could be send per Link/QR-Code on an other medium | -| ContributionLinkActivateRedeemEvent | the user activates a received contributionLink to create a contribution entry for the contributionLink | +| EventType | Description | +| -------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | +| BasicEvent | the basic event is the root of all further extending event types | +| VisitGradidoEvent | if a user visits a gradido page without login or register; possible as soon as a request-response-loop for the first page will be invoked | +| RegisterEvent | the user presses the register button | +| LoginEvent | the user presses the login button | +| VerifyRedeemEvent | the user presses a redeem link independent from transaction or contribution redeem | +| RedeemRegisterEvent | the user presses the register-button initiated by the redeem link | +| RedeemLoginEvent | the user presses the login-button initiated by the redeem link | +| ActivateAccountEvent | the system activates the users account after a successful confirmEmail-Event or during a reactivation of a deactivated account | +| InActiveAccountEvent | the systems creates an inactive account during the register process or an active account will be reset to inactive | +| SetPasswordEvent | the system sets a new password after ConfirmEmailEvent or SendForgotPasswordEvent | +| RegisterEmailKlickTippEvent | the system registers the confirmed email at klicktipp | +| PasswordChangeEvent | the user changes his password in his Profile | +| TransactionSendEvent | the user creates a transaction and sends it online; paired with TransactionReceiveEvent | +| TransactionLinkCreateEvent | the user creates a transaction link | +| TransactionReceiveEvent | the user receives a transaction from an other user and posts the amount on his account; paired with TransactionSendEvent | +| TransactionLinkRedeemEvent | the user activates the redeem link and receives the transaction and posts the amount on his account | +| ContributionCreateEvent | the user enters his contribution and asks for confirmation | +| ContributionConfirmEvent | the admin user confirms a contribution of an other user (for future multi confirmation from several users) | +| ContributionDenyEvent | the admin user denies a contribution of an other user | +| ContributionLinkDefineEvent | the admin user defines a contributionLink, which could be send per Link/QR-Code on an other medium | +| ContributionLinkRedeemEvent | the user activates a received contributionLink to create a contribution entry for the contributionLink | +| UserCreateContributionMessageEvent | the user captures a new message for a contribution | +| AdminCreateContributionMessageEvent | the admin user captures a new message for a contribution | +| LogoutEvent | the user invokes a logout | +| SendConfirmEmailEvent | the system sends a confirmation email to the user during the registration process | +| SendAccountMultiRegistrationEmailEvent | the system sends a info email to the user, that an other user tries to register with his existing email address | +| SendForgotPasswordEmailEvent | the system sends the forgot password email including a special link to start the forgot password process | +| SendTransactionSendEmailEvent | the system sends an email to inform the user about his transaction was sent to an other user | +| SendTransactionReceiveEmailEvent | the system sends an email to inform the user about a received transaction from an other user | +| SendAddedContributionEmailEvent | the system sends an email to inform the user about the creation of his captured contribution | +| SendContributionConfirmEmailEvent | the system sends an email to inform the user about the confirmation of his contribution | +| SendTransactionLinkRedeemEmailEvent | the system sends an email to the user, who created the transactionlink, that the link was redeemed | +| | | ## EventProtocol - Entity @@ -49,32 +60,44 @@ The business events will be stored in database in the new table `EventProtocol`. ## Event Types -The following table lists for each event type the mandatory attributes, which have to be initialized at event occurence and to be written in the database event protocol table: +The following table lists for each event type the mapping between old and new key, the mandatory attributes, which have to be initialized at event occurence and to be written in the database event protocol table: -| EventType | id | type | createdAt | userID | XuserID | XCommunityID | transactionID | contribID | amount | -| :---------------------------------- | :-: | :--: | :-------: | :----: | :-----: | :----------: | :-----------: | :-------: | :----: | -| BasicEvent | x | x | x | | | | | | | -| VisitGradidoEvent | x | x | x | | | | | | | -| RegisterEvent | x | x | x | x | | | | | | -| RedeemRegisterEvent | x | x | x | x | | | (x) | (x) | | -| InActiveAccountEvent | x | x | x | x | | | | | | -| SendConfirmEmailEvent | x | x | x | x | | | | | | -| ConfirmEmailEvent | x | x | x | x | | | | | | -| RegisterEmailKlickTippEvent | x | x | x | x | | | | | | -| LoginEvent | x | x | x | x | | | | | | -| RedeemLoginEvent | x | x | x | x | | | (x) | (x) | | -| ActivateAccountEvent | x | x | x | x | | | | | | -| PasswordChangeEvent | x | x | x | x | | | | | | -| TransactionSendEvent | x | x | x | x | x | x | x | | x | -| TransactionSendRedeemEvent | x | x | x | x | x | x | x | | x | -| TransactionRepeateRedeemEvent | x | x | x | x | x | x | x | | x | -| TransactionCreationEvent | x | x | x | x | | | x | | x | -| TransactionReceiveEvent | x | x | x | x | x | x | x | | x | -| TransactionReceiveRedeemEvent | x | x | x | x | x | x | x | | x | -| ContributionCreateEvent | x | x | x | x | | | | x | x | -| ContributionConfirmEvent | x | x | x | x | x | x | | x | x | -| ContributionLinkDefineEvent | x | x | x | x | | | | | x | -| ContributionLinkActivateRedeemEvent | x | x | x | x | | | | x | x | +| EventType - old key | EventType - new key | id | type | createdAt | userID | XuserID | XCommunityID | transactionID | contribID | amount | +| :-------------------------------- | :------------------------------------- | :-: | :--: | :-------: | :----: | :-----: | :----------: | :-----------: | :-------: | :----: | +| BASIC | BasicEvent | x | x | x | | | | | | | +| VISIT_GRADIDO | VisitGradidoEvent | x | x | x | | | | | | | +| REGISTER | RegisterEvent | x | x | x | x | | | | | | +| LOGIN | LoginEvent | x | x | x | x | | | | | | +| | VerifyRedeemEvent | | | | | | | | | | +| REDEEM_REGISTER | RedeemRegisterEvent | x | x | x | x | | | (x) | (x) | | +| REDEEM_LOGIN | RedeemLoginEvent | x | x | x | x | | | (x) | (x) | | +| ACTIVATE_ACCOUNT | ActivateAccountEvent | x | x | x | x | | | | | | +| INACTIVE_ACCOUNT | InActiveAccountEvent | x | x | x | x | | | | | | +| CONFIRM_EMAIL | SetPasswordEvent | x | x | x | x | | | | | | +| REGISTER_EMAIL_KLICKTIPP | RegisterEmailKlickTippEvent | x | x | x | x | | | | | | +| PASSWORD_CHANGE | PasswordChangeEvent | x | x | x | x | | | | | | +| TRANSACTION_SEND | TransactionSendEvent | x | x | x | x | x | x | x | | x | +| TRANSACTION_CREATION | TransactionLinkCreateEvent | x | x | x | x | | | x | | x | +| TRANSACTION_RECEIVE | TransactionReceiveEvent | x | x | x | x | x | x | x | | x | +| TRANSACTION_SEND_REDEEM | TransactionLinkRedeemEvent | x | x | x | x | x | x | x | | x | +| CONTRIBUTION_CREATE | ContributionCreateEvent | x | x | x | x | | | | x | x | +| CONTRIBUTION_CONFIRM | ContributionConfirmEvent | x | x | x | x | x | x | | x | x | +| | ContributionDenyEvent | x | x | x | x | x | x | | x | x | +| CONTRIBUTION_LINK_DEFINE | ContributionLinkDefineEvent | x | x | x | x | | | | | x | +| CONTRIBUTION_LINK_ACTIVATE_REDEEM | ContributionLinkRedeemEvent | x | x | x | x | | | | x | x | +| | UserCreateContributionMessageEvent | x | x | x | x | | | | x | x | +| | AdminCreateContributionMessageEvent | x | x | x | x | | | | x | x | +| | LogoutEvent | x | x | x | x | | | | x | x | +| SEND_CONFIRMATION_EMAIL | SendConfirmEmailEvent | x | x | x | x | | | | | | +| | SendAccountMultiRegistrationEmailEvent | x | x | x | x | | | | | | +| | SendForgotPasswordEmailEvent | x | x | x | x | | | | | | +| | SendTransactionSendEmailEvent | x | x | x | x | x | x | x | | x | +| | SendTransactionReceiveEmailEvent | x | x | x | x | x | x | x | | x | +| | SendAddedContributionEmailEvent | x | x | x | x | | | | x | x | +| | SendContributionConfirmEmailEvent | x | x | x | x | | | | x | x | +| | SendTransactionLinkRedeemEmailEvent | x | x | x | x | x | x | x | | x | +| TRANSACTION_REPEATE_REDEEM | - | | | | | | | | | | +| TRANSACTION_RECEIVE_REDEEM | - | | | | | | | | | | ## Event creation From 6202ca64ad809f888cae855723f421b3f121a70a Mon Sep 17 00:00:00 2001 From: joseji Date: Wed, 21 Sep 2022 19:50:27 +0200 Subject: [PATCH 07/10] test for register through transaction link done --- .../src/graphql/resolver/UserResolver.test.ts | 180 +++++++++++++----- 1 file changed, 128 insertions(+), 52 deletions(-) diff --git a/backend/src/graphql/resolver/UserResolver.test.ts b/backend/src/graphql/resolver/UserResolver.test.ts index 1103f8bf2..08256a11a 100644 --- a/backend/src/graphql/resolver/UserResolver.test.ts +++ b/backend/src/graphql/resolver/UserResolver.test.ts @@ -4,7 +4,15 @@ import { testEnvironment, headerPushMock, resetToken, cleanDB, resetEntity } from '@test/helpers' import { userFactory } from '@/seeds/factory/user' import { bibiBloxberg } from '@/seeds/users/bibi-bloxberg' -import { createUser, setPassword, forgotPassword, updateUserInfos } from '@/seeds/graphql/mutations' +import { + createUser, + setPassword, + forgotPassword, + updateUserInfos, + createTransactionLink, + createContribution, + confirmContribution, +} from '@/seeds/graphql/mutations' import { login, logout, verifyLogin, queryOptIn, searchAdminUsers } from '@/seeds/graphql/queries' import { GraphQLError } from 'graphql' import { LoginEmailOptIn } from '@entity/LoginEmailOptIn' @@ -15,17 +23,18 @@ import { sendAccountMultiRegistrationEmail } from '@/mailer/sendAccountMultiRegi import { sendResetPasswordEmail } from '@/mailer/sendResetPasswordEmail' import { printTimeDuration, activationLink } from './UserResolver' import { contributionLinkFactory } from '@/seeds/factory/contributionLink' -// import { transactionLinkFactory } from '@/seeds/factory/transactionLink' +import { transactionLinkFactory } from '@/seeds/factory/transactionLink' import { ContributionLink } from '@model/ContributionLink' -// import { TransactionLink } from '@entity/TransactionLink' +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' -import { TransactionLink } from '@entity/TransactionLink' -import { transactionLinkFactory } from '@/seeds/factory/transactionLink' +import { creationFactory } from '@/seeds/factory/creation' +import { creations } from '@/seeds/creation' +import { bobBaumeister } from '@/seeds/users/bob-baumeister' // import { klicktippSignIn } from '@/apis/KlicktippController' @@ -250,40 +259,47 @@ describe('UserResolver', () => { }) describe('redeem codes', () => { - describe('contribution link', () => { - let link: ContributionLink - beforeAll(async () => { - // activate account of admin Peter Lustig - await mutate({ - mutation: setPassword, - variables: { code: emailOptIn, password: 'Aa12345_' }, - }) - - // make Peter Lustig Admin - 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: actualDate, - validTo: futureDate, - }) - resetToken() - await mutate({ - mutation: createUser, - variables: { ...variables, email: 'ein@besucher.de', redeemCode: 'CL-' + link.code }, - }) + let result: any + let link: ContributionLink + beforeAll(async () => { + // activate account of admin Peter Lustig + await mutate({ + mutation: setPassword, + variables: { code: emailOptIn, password: 'Aa12345_' }, }) + // make Peter Lustig Admin + 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: 100, + validFrom: actualDate, + validTo: futureDate, + }) + + resetToken() + + result = await mutate({ + mutation: createUser, + variables: { ...variables, email: 'ein@besucher.de', redeemCode: 'CL-' + link.code }, + }) + }) + + afterAll(async () => { + await cleanDB() + }) + + describe('contribution link', () => { it('sets the contribution link id', async () => { await expect(User.findOne({ email: 'ein@besucher.de' })).resolves.toEqual( expect.objectContaining({ @@ -296,7 +312,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, }), ) }) @@ -305,32 +321,92 @@ describe('UserResolver', () => { expect(EventProtocol.find()).resolves.toContainEqual( expect.objectContaining({ type: EventProtocolType.REDEEM_REGISTER, - userId: expect.any(Number), // as it is randomly generated + userId: result.data.createUser.id, + contributionId: link.id, }), ) }) }) describe('transaction link', () => { + let contribution: any + let bob: any + let peter: any + let transactionLink: TransactionLink + let newUser: any + + const bobData = { + email: 'bob@baumeister.de', + password: 'Aa12345_', + publisherId: 1234, + } + + const peterData = { + email: 'peter@lustig.de', + password: 'Aa12345_', + publisherId: 1234, + } + beforeAll(async () => { - await transactionLinkFactory(testEnv, { - email: 'peter@lustig.de', - amount: 19.99, - memo: `Kein Trick, keine Zauberrei, - bei Gradidio sei dabei!`, + await userFactory(testEnv, bobBaumeister) + await query({ query: login, variables: bobData }) + + // create contribution as user bob + contribution = await mutate({ + mutation: createContribution, + variables: { amount: 1000, memo: 'testing', creationDate: new Date().toISOString() }, }) - const transactionLink = await TransactionLink.findOneOrFail() - resetToken() - await mutate({ - mutation: createUser, - variables: { ...variables, email: 'neuer@user.de', redeemCode: transactionLink.code }, + // login as admin + await query({ query: login, variables: peterData }) + + // confirm the contribution + contribution = await mutate({ + mutation: confirmContribution, + variables: { id: contribution.data.createContribution.id }, }) + + // login as user bob + bob = await query({ query: login, variables: bobData }) + + // create transaction link + await transactionLinkFactory(testEnv, { + email: 'bob@baumeister.de', + amount: 19.99, + memo: `testing transaction link`, + }) + + transactionLink = await TransactionLink.findOneOrFail() + + resetToken() + + // create new user using transaction link of bob + newUser = await mutate({ + mutation: createUser, + variables: { + ...variables, + email: 'which@ever.de', + redeemCode: transactionLink.code, + }, + }) + + console.log(await User.find()) + console.log(await EventProtocol.find()) }) - it('sets the referrer id to Peter Lustigs id', () => { - expect(User.findOne({ email: 'neuer@user.de' })).resolves.toEqual( - expect.objectContaining({ referrerId: user[0].id }), + it('sets the referrer id to bob baumeister id', () => { + expect(User.findOne({ email: 'which@ever.de' })).resolves.toEqual( + expect.objectContaining({ referrerId: bob.data.login.id }), + ) + }) + + // THIS ONE FAILS WITHOUT CONSOLE LOGS + it('stores the redeem register event in the database', () => { + expect(EventProtocol.find()).resolves.toContainEqual( + expect.objectContaining({ + type: EventProtocolType.REDEEM_REGISTER, + userId: newUser.data.createUser.id, + }), ) }) }) From c822580c1a2789cea653503a688e722c412c8028 Mon Sep 17 00:00:00 2001 From: joseji Date: Wed, 21 Sep 2022 19:53:57 +0200 Subject: [PATCH 08/10] removed unused variable --- backend/src/graphql/resolver/UserResolver.test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/backend/src/graphql/resolver/UserResolver.test.ts b/backend/src/graphql/resolver/UserResolver.test.ts index 08256a11a..6f3fd2d1d 100644 --- a/backend/src/graphql/resolver/UserResolver.test.ts +++ b/backend/src/graphql/resolver/UserResolver.test.ts @@ -331,7 +331,6 @@ describe('UserResolver', () => { describe('transaction link', () => { let contribution: any let bob: any - let peter: any let transactionLink: TransactionLink let newUser: any From f710fd9b4560ebff9bedaf38f1641f2b3d9b5fad Mon Sep 17 00:00:00 2001 From: joseji Date: Thu, 22 Sep 2022 11:19:32 +0200 Subject: [PATCH 09/10] fixed await for events redeem register --- backend/src/graphql/resolver/UserResolver.test.ts | 12 ++++-------- backend/src/graphql/resolver/UserResolver.ts | 4 ++-- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/backend/src/graphql/resolver/UserResolver.test.ts b/backend/src/graphql/resolver/UserResolver.test.ts index 840e1ea4a..fd4fc6d09 100644 --- a/backend/src/graphql/resolver/UserResolver.test.ts +++ b/backend/src/graphql/resolver/UserResolver.test.ts @@ -389,20 +389,16 @@ describe('UserResolver', () => { redeemCode: transactionLink.code, }, }) - - console.log(await User.find()) - console.log(await EventProtocol.find()) }) - it('sets the referrer id to bob baumeister id', () => { - expect(User.findOne({ email: 'which@ever.de' })).resolves.toEqual( + it('sets the referrer id to bob baumeister id', async () => { + await expect(User.findOne({ email: 'which@ever.de' })).resolves.toEqual( expect.objectContaining({ referrerId: bob.data.login.id }), ) }) - // THIS ONE FAILS WITHOUT CONSOLE LOGS - it('stores the redeem register event in the database', () => { - expect(EventProtocol.find()).resolves.toContainEqual( + it('stores the redeem register event in the database', async () => { + await expect(EventProtocol.find()).resolves.toContainEqual( expect.objectContaining({ type: EventProtocolType.REDEEM_REGISTER, userId: newUser.data.createUser.id, diff --git a/backend/src/graphql/resolver/UserResolver.ts b/backend/src/graphql/resolver/UserResolver.ts index f2fd048fc..18cd8134b 100644 --- a/backend/src/graphql/resolver/UserResolver.ts +++ b/backend/src/graphql/resolver/UserResolver.ts @@ -494,10 +494,10 @@ export class UserResolver { if (redeemCode) { eventRedeemRegister.userId = dbUser.id - eventProtocol.writeEvent(event.setEventRedeemRegister(eventRedeemRegister)) + await eventProtocol.writeEvent(event.setEventRedeemRegister(eventRedeemRegister)) } else { eventRegister.userId = dbUser.id - eventProtocol.writeEvent(event.setEventRegister(eventRegister)) + await eventProtocol.writeEvent(event.setEventRegister(eventRegister)) } return new User(dbUser) From db21cf2e8d9e524d52a5c42f78b0b0ece09ed605 Mon Sep 17 00:00:00 2001 From: joseji Date: Thu, 22 Sep 2022 11:49:56 +0200 Subject: [PATCH 10/10] removed unused imports --- backend/src/graphql/resolver/UserResolver.test.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/backend/src/graphql/resolver/UserResolver.test.ts b/backend/src/graphql/resolver/UserResolver.test.ts index fd4fc6d09..7ba74aff8 100644 --- a/backend/src/graphql/resolver/UserResolver.test.ts +++ b/backend/src/graphql/resolver/UserResolver.test.ts @@ -9,7 +9,6 @@ import { setPassword, forgotPassword, updateUserInfos, - createTransactionLink, createContribution, confirmContribution, } from '@/seeds/graphql/mutations' @@ -32,8 +31,6 @@ 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' -import { creationFactory } from '@/seeds/factory/creation' -import { creations } from '@/seeds/creation' import { bobBaumeister } from '@/seeds/users/bob-baumeister' // import { klicktippSignIn } from '@/apis/KlicktippController'