From a58698e0fb2e4ac9ce1b5bbfd806af6aab2a52b8 Mon Sep 17 00:00:00 2001 From: mahula Date: Thu, 24 Nov 2022 20:58:59 +0100 Subject: [PATCH 01/73] add fake mail server to docker.compose files for development and testing --- docker-compose.override.yml | 11 +++++++++++ docker-compose.test.yml | 11 +++++++++++ 2 files changed, 22 insertions(+) diff --git a/docker-compose.override.yml b/docker-compose.override.yml index fe2f68a8d..c69c68b50 100644 --- a/docker-compose.override.yml +++ b/docker-compose.override.yml @@ -112,6 +112,17 @@ services: volumes: - /sessions + ######################################################## + # MAILSERVER TO FAKE SMTP ############################## + ######################################################## + mailserver: + image: maildev/maildev + ports: + - 1080:1080 + - 1025:1025 + networks: + - external-net + volumes: frontend_node_modules: admin_node_modules: diff --git a/docker-compose.test.yml b/docker-compose.test.yml index 790bd468d..84647ef03 100644 --- a/docker-compose.test.yml +++ b/docker-compose.test.yml @@ -81,6 +81,17 @@ services: nginx: image: gradido/nginx:test + ######################################################## + # MAILSERVER TO FAKE SMTP ############################## + ######################################################## + mailserver: + image: maildev/maildev + ports: + - 1080:1080 + - 1025:1025 + networks: + - external-net + networks: external-net: internal-net: From e60b455a7f2751042e62f8afacf3a9b48d0e9e21 Mon Sep 17 00:00:00 2001 From: mahula Date: Thu, 24 Nov 2022 21:14:14 +0100 Subject: [PATCH 02/73] configure backend to use the fake smtp server by default --- backend/src/config/index.ts | 12 +++++++----- backend/src/mailer/sendEMail.ts | 2 +- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/backend/src/config/index.ts b/backend/src/config/index.ts index 26227b90d..f65a0f28b 100644 --- a/backend/src/config/index.ts +++ b/backend/src/config/index.ts @@ -66,14 +66,16 @@ const loginServer = { } const email = { - EMAIL: process.env.EMAIL === 'true' || false, + // eslint-disable-next-line no-unneeded-ternary + EMAIL: process.env.EMAIL === 'false' ? false : true, EMAIL_TEST_MODUS: process.env.EMAIL_TEST_MODUS === 'true' || false, EMAIL_TEST_RECEIVER: process.env.EMAIL_TEST_RECEIVER || 'stage1@gradido.net', - EMAIL_USERNAME: process.env.EMAIL_USERNAME || 'gradido_email', + EMAIL_USERNAME: process.env.EMAIL_USERNAME || 'null', EMAIL_SENDER: process.env.EMAIL_SENDER || 'info@gradido.net', - EMAIL_PASSWORD: process.env.EMAIL_PASSWORD || 'xxx', - EMAIL_SMTP_URL: process.env.EMAIL_SMTP_URL || 'gmail.com', - EMAIL_SMTP_PORT: process.env.EMAIL_SMTP_PORT || '587', + EMAIL_PASSWORD: process.env.EMAIL_PASSWORD || 'null', + EMAIL_SMTP_URL: process.env.EMAIL_SMTP_URL || 'mailserver', + EMAIL_SMTP_PORT: process.env.EMAIL_SMTP_PORT || '1025', + EMAIL_TLS: process.env.EMAIL_TLS === 'true' || false, EMAIL_LINK_VERIFICATION: process.env.EMAIL_LINK_VERIFICATION || 'http://localhost/checkEmail/{optin}{code}', EMAIL_LINK_SETPASSWORD: diff --git a/backend/src/mailer/sendEMail.ts b/backend/src/mailer/sendEMail.ts index 00282f232..b167cee2c 100644 --- a/backend/src/mailer/sendEMail.ts +++ b/backend/src/mailer/sendEMail.ts @@ -29,7 +29,7 @@ export const sendEMail = async (emailDef: { host: CONFIG.EMAIL_SMTP_URL, port: Number(CONFIG.EMAIL_SMTP_PORT), secure: false, // true for 465, false for other ports - requireTLS: true, + requireTLS: CONFIG.EMAIL_TLS, auth: { user: CONFIG.EMAIL_USERNAME, pass: CONFIG.EMAIL_PASSWORD, From 04514f421bc36aecd2a0cdd07c50c5c85185f049 Mon Sep 17 00:00:00 2001 From: mahula Date: Fri, 25 Nov 2022 11:53:36 +0100 Subject: [PATCH 03/73] adapt mailer unit tests to config changes --- backend/src/mailer/sendEMail.test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/backend/src/mailer/sendEMail.test.ts b/backend/src/mailer/sendEMail.test.ts index e062b71d8..8fa8b0d7b 100644 --- a/backend/src/mailer/sendEMail.test.ts +++ b/backend/src/mailer/sendEMail.test.ts @@ -9,6 +9,7 @@ CONFIG.EMAIL_SMTP_URL = 'EMAIL_SMTP_URL' CONFIG.EMAIL_SMTP_PORT = '1234' CONFIG.EMAIL_USERNAME = 'user' CONFIG.EMAIL_PASSWORD = 'pwd' +CONFIG.EMAIL_TLS = true jest.mock('nodemailer', () => { return { From 47f86b3faa8798fd230409133a3da2a737a41984 Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Wed, 30 Nov 2022 13:33:28 +0100 Subject: [PATCH 04/73] consider node env for sending emails --- backend/src/config/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/config/index.ts b/backend/src/config/index.ts index f65a0f28b..8ffec33ef 100644 --- a/backend/src/config/index.ts +++ b/backend/src/config/index.ts @@ -67,7 +67,7 @@ const loginServer = { const email = { // eslint-disable-next-line no-unneeded-ternary - EMAIL: process.env.EMAIL === 'false' ? false : true, + EMAIL: process.env.EMAIL === 'false' ? false : process.env.NODE_ENV !== 'development', EMAIL_TEST_MODUS: process.env.EMAIL_TEST_MODUS === 'true' || false, EMAIL_TEST_RECEIVER: process.env.EMAIL_TEST_RECEIVER || 'stage1@gradido.net', EMAIL_USERNAME: process.env.EMAIL_USERNAME || 'null', From 06b5fa429558a1e8f4c5dbe5d597a8b7b166fa01 Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Mon, 12 Dec 2022 14:05:15 +0100 Subject: [PATCH 05/73] refactor(backend): seed contributions as user --- backend/src/seeds/factory/creation.ts | 49 +++++++-------------------- 1 file changed, 13 insertions(+), 36 deletions(-) diff --git a/backend/src/seeds/factory/creation.ts b/backend/src/seeds/factory/creation.ts index 36e481519..09bf981bb 100644 --- a/backend/src/seeds/factory/creation.ts +++ b/backend/src/seeds/factory/creation.ts @@ -1,8 +1,7 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/explicit-module-boundary-types */ -import { backendLogger as logger } from '@/server/logger' -import { login, adminCreateContribution, confirmContribution } from '@/seeds/graphql/mutations' +import { login, createContribution, confirmContribution } from '@/seeds/graphql/mutations' import { CreationInterface } from '@/seeds/creation/CreationInterface' import { ApolloServerTestClient } from 'apollo-server-testing' import { Transaction } from '@entity/Transaction' @@ -19,43 +18,27 @@ export const creationFactory = async ( creation: CreationInterface, ): Promise => { const { mutate } = client - logger.trace('creationFactory...') - await mutate({ mutation: login, variables: { email: 'peter@lustig.de', password: 'Aa12345_' } }) - logger.trace('creationFactory... after login') - // TODO it would be nice to have this mutation return the id - await mutate({ mutation: adminCreateContribution, variables: { ...creation } }) - logger.trace('creationFactory... after adminCreateContribution') + await mutate({ mutation: login, variables: { email: creation.email, password: 'Aa12345_' } }) - const user = await findUserByEmail(creation.email) // userContact.user + const { + data: { createContribution: contribution }, + } = await mutate({ mutation: createContribution, variables: { ...creation } }) - const pendingCreation = await Contribution.findOneOrFail({ - where: { userId: user.id, amount: creation.amount }, - order: { createdAt: 'DESC' }, - }) - logger.trace( - 'creationFactory... after Contribution.findOneOrFail pendingCreation=', - pendingCreation, - ) if (creation.confirmed) { - logger.trace('creationFactory... creation.confirmed=', creation.confirmed) - await mutate({ mutation: confirmContribution, variables: { id: pendingCreation.id } }) - logger.trace('creationFactory... after confirmContribution') - const confirmedCreation = await Contribution.findOneOrFail({ id: pendingCreation.id }) - logger.trace( - 'creationFactory... after Contribution.findOneOrFail confirmedCreation=', - confirmedCreation, - ) + const user = await findUserByEmail(creation.email) // userContact.user + + await mutate({ mutation: login, variables: { email: 'peter@lustig.de', password: 'Aa12345_' } }) + await mutate({ mutation: confirmContribution, variables: { id: contribution.id } }) + const confirmedContribution = await Contribution.findOneOrFail({ id: contribution.id }) if (creation.moveCreationDate) { - logger.trace('creationFactory... creation.moveCreationDate=', creation.moveCreationDate) const transaction = await Transaction.findOneOrFail({ where: { userId: user.id, creationDate: new Date(creation.creationDate) }, order: { balanceDate: 'DESC' }, }) - logger.trace('creationFactory... after Transaction.findOneOrFail transaction=', transaction) if (transaction.decay.equals(0) && transaction.creationDate) { - confirmedCreation.contributionDate = new Date( + confirmedContribution.contributionDate = new Date( nMonthsBefore(transaction.creationDate, creation.moveCreationDate), ) transaction.creationDate = new Date( @@ -64,17 +47,11 @@ export const creationFactory = async ( transaction.balanceDate = new Date( nMonthsBefore(transaction.balanceDate, creation.moveCreationDate), ) - logger.trace('creationFactory... before transaction.save transaction=', transaction) await transaction.save() - logger.trace( - 'creationFactory... before confirmedCreation.save confirmedCreation=', - confirmedCreation, - ) - await confirmedCreation.save() + await confirmedContribution.save() } } } else { - logger.trace('creationFactory... pendingCreation=', pendingCreation) - return pendingCreation + return contribution } } From 35c392bbae05b692512169852e04be89e521f38e Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Mon, 12 Dec 2022 14:38:56 +0100 Subject: [PATCH 06/73] adopt unit tests to changes in factory --- .../graphql/resolver/AdminResolver.test.ts | 30 ++++++++++++++----- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/backend/src/graphql/resolver/AdminResolver.test.ts b/backend/src/graphql/resolver/AdminResolver.test.ts index b83a9876f..02730f460 100644 --- a/backend/src/graphql/resolver/AdminResolver.test.ts +++ b/backend/src/graphql/resolver/AdminResolver.test.ts @@ -969,13 +969,21 @@ describe('AdminResolver', () => { const now = new Date() beforeAll(async () => { - creation = await creationFactory(testEnv, { - email: 'peter@lustig.de', - amount: 400, - memo: 'Herzlich Willkommen bei Gradido!', - creationDate: contributionDateFormatter( - new Date(now.getFullYear(), now.getMonth() - 1, 1), - ), + await mutate({ + mutation: adminCreateContribution, + variables: { + email: 'peter@lustig.de', + amount: 400, + memo: 'Herzlich Willkommen bei Gradido!', + creationDate: contributionDateFormatter( + new Date(now.getFullYear(), now.getMonth() - 1, 1), + ), + }, + }) + creation = await Contribution.findOneOrFail({ + where: { + memo: 'Herzlich Willkommen bei Gradido!', + }, }) }) @@ -1702,6 +1710,10 @@ describe('AdminResolver', () => { new Date(now.getFullYear(), now.getMonth() - 2, 1), ), }) + await query({ + query: login, + variables: { email: 'peter@lustig.de', password: 'Aa12345_' }, + }) }) it('returns true', async () => { @@ -1782,6 +1794,10 @@ describe('AdminResolver', () => { new Date(now.getFullYear(), now.getMonth() - 2, 1), ), }) + await query({ + query: login, + variables: { email: 'peter@lustig.de', password: 'Aa12345_' }, + }) }) // In the futrue this should not throw anymore From 881e38f22b168a0533d61f211b63dcc2c51a8260 Mon Sep 17 00:00:00 2001 From: mahula Date: Fri, 16 Dec 2022 13:05:57 +0100 Subject: [PATCH 07/73] set email disabled and tls enabled as defaults in backend config --- backend/src/config/index.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/backend/src/config/index.ts b/backend/src/config/index.ts index 6ae6e24f0..76a87976a 100644 --- a/backend/src/config/index.ts +++ b/backend/src/config/index.ts @@ -66,8 +66,7 @@ const loginServer = { } const email = { - // eslint-disable-next-line no-unneeded-ternary - EMAIL: process.env.EMAIL === 'false' ? false : process.env.NODE_ENV !== 'development', + EMAIL: process.env.EMAIL === 'true' || false, EMAIL_TEST_MODUS: process.env.EMAIL_TEST_MODUS === 'true' || false, EMAIL_TEST_RECEIVER: process.env.EMAIL_TEST_RECEIVER || 'stage1@gradido.net', EMAIL_USERNAME: process.env.EMAIL_USERNAME || 'null', @@ -75,7 +74,8 @@ const email = { EMAIL_PASSWORD: process.env.EMAIL_PASSWORD || 'null', EMAIL_SMTP_URL: process.env.EMAIL_SMTP_URL || 'mailserver', EMAIL_SMTP_PORT: process.env.EMAIL_SMTP_PORT || '1025', - EMAIL_TLS: process.env.EMAIL_TLS === 'true' || false, + // eslint-disable-next-line no-unneeded-ternary + EMAIL_TLS: process.env.EMAIL_TLS === 'false' ? false : true, EMAIL_LINK_VERIFICATION: process.env.EMAIL_LINK_VERIFICATION || 'http://localhost/checkEmail/{optin}{code}', EMAIL_LINK_SETPASSWORD: From 36204195656cc142a3d6ecbad921d5407d3e88cc Mon Sep 17 00:00:00 2001 From: mahula Date: Fri, 16 Dec 2022 13:53:19 +0100 Subject: [PATCH 08/73] adapt emailer config to config changes --- backend/src/emails/sendEmailTranslated.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/emails/sendEmailTranslated.ts b/backend/src/emails/sendEmailTranslated.ts index 69008c00e..5652b3424 100644 --- a/backend/src/emails/sendEmailTranslated.ts +++ b/backend/src/emails/sendEmailTranslated.ts @@ -41,7 +41,7 @@ export const sendEmailTranslated = async (params: { host: CONFIG.EMAIL_SMTP_URL, port: Number(CONFIG.EMAIL_SMTP_PORT), secure: false, // true for 465, false for other ports - requireTLS: true, + requireTLS: CONFIG.EMAIL_TLS, auth: { user: CONFIG.EMAIL_USERNAME, pass: CONFIG.EMAIL_PASSWORD, From d864732c0f5915862208eb59ee285919a41b292e Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Mon, 26 Dec 2022 16:32:22 +0100 Subject: [PATCH 09/73] fix config - [x] `ENV_NAME` present in config but never used - [x] `FEDERATION_DHT_SEED` has a trailing space - [x] `v14.2022-11-22` should be `v14.2022-12-22` - [x] Check if versions are all correctly configured in all configs --- backend/.env.dist | 2 +- backend/src/config/index.ts | 2 +- deployment/bare_metal/.env.dist | 5 ++--- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/backend/.env.dist b/backend/.env.dist index b238388f6..ba5b89fa9 100644 --- a/backend/.env.dist +++ b/backend/.env.dist @@ -66,5 +66,5 @@ EVENT_PROTOCOL_DISABLED=false # if you set the value of FEDERATION_DHT_TOPIC, the DHT hyperswarm will start to announce and listen # on an hash created from this topic # FEDERATION_DHT_TOPIC=GRADIDO_HUB -# FEDERATION_DHT_SEED=64ebcb0e3ad547848fef4197c6e2332f +# FEDERATION_DHT_SEED=64ebcb0e3ad547848fef4197c6e2332f # FEDERATION_COMMUNITY_URL=http://localhost:4000/api diff --git a/backend/src/config/index.ts b/backend/src/config/index.ts index 698b17e67..4779e5b21 100644 --- a/backend/src/config/index.ts +++ b/backend/src/config/index.ts @@ -17,7 +17,7 @@ const constants = { LOG_LEVEL: process.env.LOG_LEVEL || 'info', CONFIG_VERSION: { DEFAULT: 'DEFAULT', - EXPECTED: 'v14.2022-11-22', + EXPECTED: 'v14.2022-12-22', CURRENT: '', }, } diff --git a/deployment/bare_metal/.env.dist b/deployment/bare_metal/.env.dist index a5f6996d7..e816c9236 100644 --- a/deployment/bare_metal/.env.dist +++ b/deployment/bare_metal/.env.dist @@ -27,11 +27,10 @@ COMMUNITY_DESCRIPTION="Gradido Development Stage1 Test Community" COMMUNITY_SUPPORT_MAIL=support@supportmail.com # backend -BACKEND_CONFIG_VERSION=v13.2022-12-20 +BACKEND_CONFIG_VERSION=v14.2022-12-22 JWT_EXPIRES_IN=10m GDT_API_URL=https://gdt.gradido.net -ENV_NAME=stage1 TYPEORM_LOGGING_RELATIVE_PATH=../deployment/bare_metal/log/typeorm.backend.log @@ -64,7 +63,7 @@ EVENT_PROTOCOL_DISABLED=false # if you set the value of FEDERATION_DHT_TOPIC, the DHT hyperswarm will start to announce and listen # on an hash created from this topic # FEDERATION_DHT_TOPIC=GRADIDO_HUB -# FEDERATION_DHT_SEED=64ebcb0e3ad547848fef4197c6e2332f +# FEDERATION_DHT_SEED=64ebcb0e3ad547848fef4197c6e2332f # database DATABASE_CONFIG_VERSION=v1.2022-03-18 From f6f253a40a7aa3770d70cab3814021837a04de31 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Tue, 27 Dec 2022 02:55:48 +0100 Subject: [PATCH 10/73] include new scopes for lint pr: - federation - workflow - docker --- .github/workflows/lint_pr.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/lint_pr.yml b/.github/workflows/lint_pr.yml index 2f9229737..24e66bd20 100644 --- a/.github/workflows/lint_pr.yml +++ b/.github/workflows/lint_pr.yml @@ -29,6 +29,9 @@ jobs: admin database release + federation + workflow + docker other # Configure that a scope must always be provided. requireScope: true From 68bd762cd19cd4a6af0fd71d6d7576e3580d4f25 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Mon, 2 Jan 2023 14:42:27 +0100 Subject: [PATCH 11/73] fix logger middleware to not throw errors when variables cannot be parsed properly --- backend/src/server/plugins.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/src/server/plugins.ts b/backend/src/server/plugins.ts index 24df45baa..7ecbedf2a 100644 --- a/backend/src/server/plugins.ts +++ b/backend/src/server/plugins.ts @@ -23,8 +23,8 @@ const setHeadersPlugin = { const filterVariables = (variables: any) => { const vars = clonedeep(variables) - if (vars.password) vars.password = '***' - if (vars.passwordNew) vars.passwordNew = '***' + if (vars && vars.password) vars.password = '***' + if (vars && vars.passwordNew) vars.passwordNew = '***' return vars } From 53757893fde5fcf2cc419cc73fde9683f4b3e8c6 Mon Sep 17 00:00:00 2001 From: elweyn Date: Tue, 3 Jan 2023 10:06:00 +0100 Subject: [PATCH 12/73] Co-authored-by: ogerly Add hideAmountGDD & hideAmountGDT to users table. --- .../0059-add_hide_amount_to_users/User.ts | 118 ++++++++++++++++++ database/entity/User.ts | 2 +- 2 files changed, 119 insertions(+), 1 deletion(-) create mode 100644 database/entity/0059-add_hide_amount_to_users/User.ts diff --git a/database/entity/0059-add_hide_amount_to_users/User.ts b/database/entity/0059-add_hide_amount_to_users/User.ts new file mode 100644 index 000000000..ba9e5fc49 --- /dev/null +++ b/database/entity/0059-add_hide_amount_to_users/User.ts @@ -0,0 +1,118 @@ +import { + BaseEntity, + Entity, + PrimaryGeneratedColumn, + Column, + DeleteDateColumn, + OneToMany, + JoinColumn, + OneToOne, +} from 'typeorm' +import { Contribution } from '../Contribution' +import { ContributionMessage } from '../ContributionMessage' +import { UserContact } from '../UserContact' + +@Entity('users', { engine: 'InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci' }) +export class User extends BaseEntity { + @PrimaryGeneratedColumn('increment', { unsigned: true }) + id: number + + @Column({ + name: 'gradido_id', + length: 36, + nullable: false, + collation: 'utf8mb4_unicode_ci', + }) + gradidoID: string + + @Column({ + name: 'alias', + length: 20, + nullable: true, + default: null, + collation: 'utf8mb4_unicode_ci', + }) + alias: string + + @OneToOne(() => UserContact, (emailContact: UserContact) => emailContact.user) + @JoinColumn({ name: 'email_id' }) + emailContact: UserContact + + @Column({ name: 'email_id', type: 'int', unsigned: true, nullable: true, default: null }) + emailId: number | null + + @Column({ + name: 'first_name', + length: 255, + nullable: true, + default: null, + collation: 'utf8mb4_unicode_ci', + }) + firstName: string + + @Column({ + name: 'last_name', + length: 255, + nullable: true, + default: null, + collation: 'utf8mb4_unicode_ci', + }) + lastName: string + + @Column({ name: 'created_at', default: () => 'CURRENT_TIMESTAMP', nullable: false }) + createdAt: Date + + @DeleteDateColumn({ name: 'deleted_at', nullable: true }) + deletedAt: Date | null + + @Column({ type: 'bigint', default: 0, unsigned: true }) + password: BigInt + + @Column({ + name: 'password_encryption_type', + type: 'int', + unsigned: true, + nullable: false, + default: 0, + }) + passwordEncryptionType: number + + @Column({ length: 4, default: 'de', collation: 'utf8mb4_unicode_ci', nullable: false }) + language: string + + @Column({ type: 'bool', default: false }) + hideAmountGDD: boolean + + @Column({ type: 'bool', default: false }) + hideAmountGDT: boolean + + @Column({ name: 'is_admin', type: 'datetime', nullable: true, default: null }) + isAdmin: Date | null + + @Column({ name: 'referrer_id', type: 'int', unsigned: true, nullable: true, default: null }) + referrerId?: number | null + + @Column({ + name: 'contribution_link_id', + type: 'int', + unsigned: true, + nullable: true, + default: null, + }) + contributionLinkId?: number | null + + @Column({ name: 'publisher_id', default: 0 }) + publisherId: number + + @OneToMany(() => Contribution, (contribution) => contribution.user) + @JoinColumn({ name: 'user_id' }) + contributions?: Contribution[] + + @OneToMany(() => ContributionMessage, (message) => message.user) + @JoinColumn({ name: 'user_id' }) + messages?: ContributionMessage[] + + @OneToMany(() => UserContact, (userContact: UserContact) => userContact.user) + @JoinColumn({ name: 'user_id' }) + userContacts?: UserContact[] +} diff --git a/database/entity/User.ts b/database/entity/User.ts index 5cffc688e..fbb65204c 100644 --- a/database/entity/User.ts +++ b/database/entity/User.ts @@ -1 +1 @@ -export { User } from './0057-clear_old_password_junk/User' +export { User } from './0059-add_hide_amount_to_users/User' From 643de6144a36d2032323c323aec99f02249b9756 Mon Sep 17 00:00:00 2001 From: elweyn Date: Tue, 3 Jan 2023 10:09:58 +0100 Subject: [PATCH 13/73] Co-authored-by: ogerly Add new database version to backend. --- backend/src/config/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/config/index.ts b/backend/src/config/index.ts index 698b17e67..209f0cf81 100644 --- a/backend/src/config/index.ts +++ b/backend/src/config/index.ts @@ -10,7 +10,7 @@ Decimal.set({ }) const constants = { - DB_VERSION: '0058-add_communities_table', + DB_VERSION: '0059-add_hide_amount_to_users', DECAY_START_TIME: new Date('2021-05-13 17:46:31-0000'), // GMT+0 LOG4JS_CONFIG: 'log4js-config.json', // default log level on production should be info From 465dc469b0342e5bb0e06a81f6b335cb3a67ebd1 Mon Sep 17 00:00:00 2001 From: elweyn Date: Tue, 3 Jan 2023 10:13:01 +0100 Subject: [PATCH 14/73] Add hideAmount to updataUserInfos args & change updateUserInfo method. Co-authored-by: ogerly --- backend/src/graphql/arg/UpdateUserInfosArgs.ts | 6 ++++++ backend/src/graphql/resolver/UserResolver.ts | 14 +++++++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/backend/src/graphql/arg/UpdateUserInfosArgs.ts b/backend/src/graphql/arg/UpdateUserInfosArgs.ts index 81c07a329..8ac3f40a2 100644 --- a/backend/src/graphql/arg/UpdateUserInfosArgs.ts +++ b/backend/src/graphql/arg/UpdateUserInfosArgs.ts @@ -19,4 +19,10 @@ export default class UpdateUserInfosArgs { @Field({ nullable: true }) passwordNew?: string + + @Field({ nullable: false }) + hideAmountGDD: boolean + + @Field({ nullable: false }) + hideAmountGDT: boolean } diff --git a/backend/src/graphql/resolver/UserResolver.ts b/backend/src/graphql/resolver/UserResolver.ts index 4b4744b67..b58a8132a 100644 --- a/backend/src/graphql/resolver/UserResolver.ts +++ b/backend/src/graphql/resolver/UserResolver.ts @@ -567,7 +567,15 @@ export class UserResolver { @Mutation(() => Boolean) async updateUserInfos( @Args() - { firstName, lastName, language, password, passwordNew }: UpdateUserInfosArgs, + { + firstName, + lastName, + language, + password, + passwordNew, + hideAmountGDD, + hideAmountGDT, + }: UpdateUserInfosArgs, @Ctx() context: Context, ): Promise { logger.info(`updateUserInfos(${firstName}, ${lastName}, ${language}, ***, ***)...`) @@ -609,6 +617,10 @@ export class UserResolver { userEntity.password = encryptPassword(userEntity, passwordNew) } + // Save hideAmountGDD value + userEntity.hideAmountGDD = hideAmountGDD + userEntity.hideAmountGDT = hideAmountGDT + const queryRunner = getConnection().createQueryRunner() await queryRunner.connect() await queryRunner.startTransaction('REPEATABLE READ') From 3d8e28e16c80f9146d906f1ff6d674db17b2c60b Mon Sep 17 00:00:00 2001 From: elweyn Date: Tue, 3 Jan 2023 10:42:54 +0100 Subject: [PATCH 15/73] Add comment to update hideAmountGDT. --- backend/src/graphql/resolver/UserResolver.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/backend/src/graphql/resolver/UserResolver.ts b/backend/src/graphql/resolver/UserResolver.ts index b58a8132a..8ce964c71 100644 --- a/backend/src/graphql/resolver/UserResolver.ts +++ b/backend/src/graphql/resolver/UserResolver.ts @@ -619,6 +619,7 @@ export class UserResolver { // Save hideAmountGDD value userEntity.hideAmountGDD = hideAmountGDD + // Save hideAmountGDT value userEntity.hideAmountGDT = hideAmountGDT const queryRunner = getConnection().createQueryRunner() From 84afbf9a9e6b02e957e220d781e3165b3e61bf0f Mon Sep 17 00:00:00 2001 From: elweyn Date: Tue, 3 Jan 2023 11:21:25 +0100 Subject: [PATCH 16/73] Fix imported User path. --- database/entity/0057-clear_old_password_junk/UserContact.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/database/entity/0057-clear_old_password_junk/UserContact.ts b/database/entity/0057-clear_old_password_junk/UserContact.ts index c101fba4c..dd06d3bbc 100644 --- a/database/entity/0057-clear_old_password_junk/UserContact.ts +++ b/database/entity/0057-clear_old_password_junk/UserContact.ts @@ -6,7 +6,7 @@ import { DeleteDateColumn, OneToOne, } from 'typeorm' -import { User } from './User' +import { User } from '../User' @Entity('user_contacts', { engine: 'InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci' }) export class UserContact extends BaseEntity { From ce909108a9f756edae3f3c1e13d954ddaaceb66b Mon Sep 17 00:00:00 2001 From: elweyn Date: Tue, 3 Jan 2023 11:22:26 +0100 Subject: [PATCH 17/73] Add migration for the new fields. --- database/migrations/0059-add_hide_amount_to_users.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 database/migrations/0059-add_hide_amount_to_users.ts diff --git a/database/migrations/0059-add_hide_amount_to_users.ts b/database/migrations/0059-add_hide_amount_to_users.ts new file mode 100644 index 000000000..d06e00559 --- /dev/null +++ b/database/migrations/0059-add_hide_amount_to_users.ts @@ -0,0 +1,12 @@ +/* eslint-disable @typescript-eslint/explicit-module-boundary-types */ +/* eslint-disable @typescript-eslint/no-explicit-any */ + +export async function upgrade(queryFn: (query: string, values?: any[]) => Promise>) { + await queryFn('ALTER TABLE users ADD COLUMN hideAmountGDD bool DEFAULT false;') + await queryFn('ALTER TABLE users ADD COLUMN hideAmountGDT bool DEFAULT false;') +} + +export async function downgrade(queryFn: (query: string, values?: any[]) => Promise>) { + await queryFn('ALTER TABLE users DROP COLUMN hideAmountGDD;') + await queryFn('ALTER TABLE users DROP COLUMN hideAmountGDT;') +} From e936e2bf401e85912cc244acc5bb9b6708b56579 Mon Sep 17 00:00:00 2001 From: elweyn Date: Tue, 3 Jan 2023 11:28:20 +0100 Subject: [PATCH 18/73] Add new fields hideAmount... to the communityUser. --- backend/src/util/communityUser.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/backend/src/util/communityUser.ts b/backend/src/util/communityUser.ts index 98279db15..4d04be1b8 100644 --- a/backend/src/util/communityUser.ts +++ b/backend/src/util/communityUser.ts @@ -18,6 +18,8 @@ const communityDbUser: dbUser = { lastName: 'Akademie', deletedAt: null, password: BigInt(0), + hideAmountGDD: false, + hideAmountGDT: false, // emailHash: Buffer.from(''), createdAt: new Date(), // emailChecked: false, From 2010a1b059dfbe4725717a77472bb129ed44f166 Mon Sep 17 00:00:00 2001 From: elweyn Date: Tue, 3 Jan 2023 12:24:49 +0100 Subject: [PATCH 19/73] Add hideAmountGDD and hideAmountGDT to the login mutations and the verifyLogin queries --- backend/src/graphql/model/User.ts | 8 ++++++++ frontend/src/graphql/mutations.js | 6 ++++++ frontend/src/graphql/queries.js | 2 ++ frontend/src/store/store.js | 12 ++++++++++++ 4 files changed, 28 insertions(+) diff --git a/backend/src/graphql/model/User.ts b/backend/src/graphql/model/User.ts index cc52ff1f1..6e353f6a7 100644 --- a/backend/src/graphql/model/User.ts +++ b/backend/src/graphql/model/User.ts @@ -27,6 +27,8 @@ export class User { this.klickTipp = null this.hasElopage = null this.creation = creation + this.hideAmountGDD = user.hideAmountGDD + this.hideAmountGDT = user.hideAmountGDT } @Field(() => Number) @@ -72,6 +74,12 @@ export class User { @Field(() => String) language: string + @Field(() => Boolean) + hideAmountGDD: boolean + + @Field(() => Boolean) + hideAmountGDT: boolean + // This is not the users publisherId, but the one of the users who recommend him @Field(() => Number, { nullable: true }) publisherId: number | null diff --git a/frontend/src/graphql/mutations.js b/frontend/src/graphql/mutations.js index 3156c2861..8b0464244 100644 --- a/frontend/src/graphql/mutations.js +++ b/frontend/src/graphql/mutations.js @@ -31,6 +31,8 @@ export const updateUserInfos = gql` $password: String $passwordNew: String $locale: String + $hideAmountGDD: boolean! + $hideAmountGDT: boolean! ) { updateUserInfos( firstName: $firstName @@ -38,6 +40,8 @@ export const updateUserInfos = gql` password: $password passwordNew: $passwordNew language: $locale + hideAmountGDD: $hideAmountGDD + hideAmountGDT: $hideAmountGDT ) } ` @@ -151,6 +155,8 @@ export const login = gql` publisherId isAdmin creation + hideAmountGDD + hideAmountGDT } } ` diff --git a/frontend/src/graphql/queries.js b/frontend/src/graphql/queries.js index d261797c2..d4973146d 100644 --- a/frontend/src/graphql/queries.js +++ b/frontend/src/graphql/queries.js @@ -14,6 +14,8 @@ export const verifyLogin = gql` publisherId isAdmin creation + hideAmountGDD + hideAmountGDT } } ` diff --git a/frontend/src/store/store.js b/frontend/src/store/store.js index 8fdbc519e..dff96ee1d 100644 --- a/frontend/src/store/store.js +++ b/frontend/src/store/store.js @@ -50,6 +50,12 @@ export const mutations = { creation: (state, creation) => { state.creation = creation }, + hideAmountGDD: (state, hideAmountGDD) => { + state.hideAmountGDD = hideAmountGDD + }, + hideAmountGDT: (state, hideAmountGDT) => { + state.hideAmountGDT = hideAmountGDT + }, } export const actions = { @@ -64,6 +70,8 @@ export const actions = { commit('publisherId', data.publisherId) commit('isAdmin', data.isAdmin) commit('creation', data.creation) + commit('hideAmountGDD', data.hideAmountGDD) + commit('hideAmountGDT', data.hideAmountGDT) }, logout: ({ commit, state }) => { commit('token', null) @@ -76,6 +84,8 @@ export const actions = { commit('publisherId', null) commit('isAdmin', false) commit('creation', null) + commit('hideAmountGDD', null) + commit('hideAmountGDT', null) localStorage.clear() }, } @@ -102,6 +112,8 @@ try { hasElopage: false, publisherId: null, creation: null, + hideAmountGDD: null, + hideAmountGDT: null, }, getters: {}, // Syncronous mutation of the state From 9bbb401428101c1a9534861caa5906b44aa305f3 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Sun, 8 Jan 2023 13:53:16 +0100 Subject: [PATCH 20/73] fixed email text --- backend/src/emails/sendEmailVariants.test.ts | 10 ++++++---- backend/src/locales/en.json | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/backend/src/emails/sendEmailVariants.test.ts b/backend/src/emails/sendEmailVariants.test.ts index 6dbde1196..1015f2cb5 100644 --- a/backend/src/emails/sendEmailVariants.test.ts +++ b/backend/src/emails/sendEmailVariants.test.ts @@ -327,18 +327,20 @@ describe('sendEmailVariants', () => { to: 'Peter Lustig ', from: 'Gradido (do not answer) ', attachments: [], - subject: 'Gradido: Your common good contribution was confirmed', + subject: 'Gradido: Your contribution to the common good was confirmed', html: expect.any(String), - text: expect.stringContaining('GRADIDO: YOUR COMMON GOOD CONTRIBUTION WAS CONFIRMED'), + text: expect.stringContaining( + 'GRADIDO: YOUR CONTRIBUTION TO THE COMMON GOOD WAS CONFIRMED', + ), }), }) expect(result.originalMessage.html).toContain('') expect(result.originalMessage.html).toContain('') expect(result.originalMessage.html).toContain( - 'Gradido: Your common good contribution was confirmed', + 'Gradido: Your contribution to the common good was confirmed', ) expect(result.originalMessage.html).toContain( - '>Gradido: Your common good contribution was confirmed', + '>Gradido: Your contribution to the common good was confirmed', ) expect(result.originalMessage.html).toContain('Hello Peter Lustig') expect(result.originalMessage.html).toContain( diff --git a/backend/src/locales/en.json b/backend/src/locales/en.json index 6131bb501..ac1ad380f 100644 --- a/backend/src/locales/en.json +++ b/backend/src/locales/en.json @@ -21,7 +21,7 @@ }, "contributionConfirmed": { "commonGoodContributionConfirmed": "Your public good contribution “{contributionMemo}” has just been confirmed by {senderFirstName} {senderLastName} and credited to your Gradido account.", - "subject": "Gradido: Your common good contribution was confirmed" + "subject": "Gradido: Your contribution to the common good was confirmed" }, "contributionRejected": { "commonGoodContributionRejected": "Your public good contribution “{contributionMemo}” was rejected by {senderFirstName} {senderLastName}.", From 77a377f2f0744ea9c667f29bebffcebc24c82855 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Mon, 9 Jan 2023 10:09:44 +0100 Subject: [PATCH 21/73] added few more extension recommendations --- .vscode/extensions.json | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 9b0d3b79e..43770e9b0 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -3,6 +3,10 @@ "streetsidesoftware.code-spell-checker", "dbaeumer.vscode-eslint", "esbenp.prettier-vscode", - "hediet.vscode-drawio" + "hediet.vscode-drawio", + "streetsidesoftware.code-spell-checker-german", + "mtxr.sqltools", + "mtxr.sqltools-driver-mysql", + "jcbuisson.vue" ] } \ No newline at end of file From e79be0c07afb286ed3282c9f23eb70318b3f9bd7 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Mon, 9 Jan 2023 10:12:45 +0100 Subject: [PATCH 22/73] added default connection to sqltools vscode config --- .vscode/settings.json | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 3b6641073..9634ae8a9 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1,18 @@ { - "git.ignoreLimitWarning": true + "git.ignoreLimitWarning": true, + "sqltools.connections": [ + { + "mysqlOptions": { + "authProtocol": "default" + }, + "previewLimit": 50, + "server": "localhost", + "port": 3306, + "driver": "MariaDB", + "name": "localhost", + "database": "gradido_community", + "username": "root", + "password": "" + } + ], } \ No newline at end of file From 14923f30914b3ffb1763ddc8eae43531d9ecd399 Mon Sep 17 00:00:00 2001 From: ogerly Date: Mon, 9 Jan 2023 10:13:58 +0100 Subject: [PATCH 23/73] fix pagination gdt --- frontend/src/pages/Transactions.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/pages/Transactions.vue b/frontend/src/pages/Transactions.vue index 4be91b92b..40d883886 100644 --- a/frontend/src/pages/Transactions.vue +++ b/frontend/src/pages/Transactions.vue @@ -85,7 +85,7 @@ export default { } }, watch: { - gdt() { + currentPage() { if (this.gdt) { this.updateGdt() } From 914f50e09d0f9a048dc135ee5bec06e2852a6f53 Mon Sep 17 00:00:00 2001 From: ogerly Date: Mon, 9 Jan 2023 11:40:26 +0100 Subject: [PATCH 24/73] Navbar sheets are under the user icon --- frontend/src/components/Menu/Navbar.vue | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/frontend/src/components/Menu/Navbar.vue b/frontend/src/components/Menu/Navbar.vue index 7efb0d2ef..87e571c4f 100644 --- a/frontend/src/components/Menu/Navbar.vue +++ b/frontend/src/components/Menu/Navbar.vue @@ -12,14 +12,15 @@ - - + +
+
From 2e54641f20621cccc7b5b07188be0745db15bd40 Mon Sep 17 00:00:00 2001 From: ogerly Date: Mon, 9 Jan 2023 11:49:20 +0100 Subject: [PATCH 25/73] error corrected GdtBalance not null --- frontend/src/layouts/DashboardLayout.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/layouts/DashboardLayout.vue b/frontend/src/layouts/DashboardLayout.vue index e5bf394f2..13c942dbc 100755 --- a/frontend/src/layouts/DashboardLayout.vue +++ b/frontend/src/layouts/DashboardLayout.vue @@ -177,7 +177,7 @@ export default { } = result this.GdtBalance = transactionList.balance.balanceGDT === null - ? null + ? 0 : Number(transactionList.balance.balanceGDT) this.transactions = transactionList.transactions this.balance = Number(transactionList.balance.balance) From 9fbc9e78195241cc29968ff1d5394f780cec0364 Mon Sep 17 00:00:00 2001 From: ogerly Date: Mon, 9 Jan 2023 12:27:50 +0100 Subject: [PATCH 26/73] Creation menu is highlighted on all submenus --- frontend/src/components/Menu/Sidebar.vue | 2 +- frontend/src/pages/Community.vue | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/frontend/src/components/Menu/Sidebar.vue b/frontend/src/components/Menu/Sidebar.vue index a373e9a74..864d42906 100644 --- a/frontend/src/components/Menu/Sidebar.vue +++ b/frontend/src/components/Menu/Sidebar.vue @@ -19,7 +19,7 @@ {{ $t('gdt.gdt') }} - + {{ $t('creation') }} diff --git a/frontend/src/pages/Community.vue b/frontend/src/pages/Community.vue index 16af01ce3..177f7f592 100644 --- a/frontend/src/pages/Community.vue +++ b/frontend/src/pages/Community.vue @@ -315,6 +315,7 @@ export default { }) this.updateTransactions(0) this.tabIndex = 1 + this.$router.push({ path: '#my' }) }, } From c728d08b81900e3a064274d4bbb157ad4968a4f7 Mon Sep 17 00:00:00 2001 From: ogerly Date: Mon, 9 Jan 2023 12:47:51 +0100 Subject: [PATCH 27/73] remove padding on menu on creation navbar --- .../components/Template/ContentHeader/NavCommunity.vue | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/frontend/src/components/Template/ContentHeader/NavCommunity.vue b/frontend/src/components/Template/ContentHeader/NavCommunity.vue index 20361e82c..63f53722d 100644 --- a/frontend/src/components/Template/ContentHeader/NavCommunity.vue +++ b/frontend/src/components/Template/ContentHeader/NavCommunity.vue @@ -1,19 +1,19 @@ diff --git a/frontend/src/components/Template/ContentHeader/GdtAmount.vue b/frontend/src/components/Template/ContentHeader/GdtAmount.vue index 6a2312e07..9216ff232 100644 --- a/frontend/src/components/Template/ContentHeader/GdtAmount.vue +++ b/frontend/src/components/Template/ContentHeader/GdtAmount.vue @@ -34,7 +34,7 @@ @@ -42,6 +42,8 @@
diff --git a/frontend/src/graphql/mutations.js b/frontend/src/graphql/mutations.js index 8b0464244..95d7b0c39 100644 --- a/frontend/src/graphql/mutations.js +++ b/frontend/src/graphql/mutations.js @@ -31,8 +31,8 @@ export const updateUserInfos = gql` $password: String $passwordNew: String $locale: String - $hideAmountGDD: boolean! - $hideAmountGDT: boolean! + $hideAmountGDD: Boolean + $hideAmountGDT: Boolean ) { updateUserInfos( firstName: $firstName diff --git a/frontend/src/locales/de.json b/frontend/src/locales/de.json index 52da80cc6..e34d11297 100644 --- a/frontend/src/locales/de.json +++ b/frontend/src/locales/de.json @@ -269,6 +269,10 @@ "warningText": "Bist du noch da?" }, "settings": { + "showAmountGDD": "Dein GDD Betrag ist sichtbar.", + "hideAmountGDD": "Dein GDD Betrag ist versteckt.", + "showAmountGDT": "Dein GDT Betrag ist sichtbar.", + "hideAmountGDT": "Dein GDT Betrag ist versteckt.", "language": { "changeLanguage": "Sprache ändern", "de": "Deutsch", From 754140dcbc1eb5186fcb31e47625bff42e4c8bb3 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Tue, 10 Jan 2023 10:54:57 +0100 Subject: [PATCH 37/73] removed jest from dependencies - only present in dev dependencies now --- backend/package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/backend/package.json b/backend/package.json index 69a436563..1fb27f05f 100644 --- a/backend/package.json +++ b/backend/package.json @@ -31,7 +31,6 @@ "express": "^4.17.1", "graphql": "^15.5.1", "i18n": "^0.15.1", - "jest": "^27.2.4", "jsonwebtoken": "^8.5.1", "lodash.clonedeep": "^4.5.0", "log4js": "^6.4.6", From 427a0a6865e3f7978f7e0e03ac537c47214306f5 Mon Sep 17 00:00:00 2001 From: elweyn Date: Tue, 10 Jan 2023 10:55:41 +0100 Subject: [PATCH 38/73] Change test of returned login datas. --- backend/src/graphql/resolver/UserResolver.test.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/backend/src/graphql/resolver/UserResolver.test.ts b/backend/src/graphql/resolver/UserResolver.test.ts index b70dd1522..073bad04d 100644 --- a/backend/src/graphql/resolver/UserResolver.test.ts +++ b/backend/src/graphql/resolver/UserResolver.test.ts @@ -63,6 +63,7 @@ jest.mock('@/emails/sendEmailVariants', () => { }) /* + jest.mock('@/apis/KlicktippController', () => { return { __esModule: true, @@ -132,6 +133,8 @@ describe('UserResolver', () => { { id: expect.any(Number), gradidoID: expect.any(String), + hideAmountGDD: expect.any(Boolean), + hideAmountGDT: expect.any(Boolean), alias: null, emailContact: expect.any(UserContact), // 'peter@lustig.de', emailId: expect.any(Number), From d71a73ec3b48ade0370a259d1ea5b15680b576b9 Mon Sep 17 00:00:00 2001 From: elweyn Date: Tue, 10 Jan 2023 10:56:08 +0100 Subject: [PATCH 39/73] Add new mutation variables to the tests mutation in backend. --- backend/src/seeds/graphql/mutations.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/backend/src/seeds/graphql/mutations.ts b/backend/src/seeds/graphql/mutations.ts index e5dc90a0e..2b4ed6656 100644 --- a/backend/src/seeds/graphql/mutations.ts +++ b/backend/src/seeds/graphql/mutations.ts @@ -31,6 +31,8 @@ export const updateUserInfos = gql` $password: String $passwordNew: String $locale: String + $hideAmountGDD: Boolean + $hideAmountGDT: Boolean ) { updateUserInfos( firstName: $firstName @@ -38,6 +40,8 @@ export const updateUserInfos = gql` password: $password passwordNew: $passwordNew language: $locale + hideAmountGDD: $hideAmountGDD + hideAmountGDT: $hideAmountGDT ) } ` From 1e265b1078c10cfb2a7aeaebeaecbca4e6983780 Mon Sep 17 00:00:00 2001 From: mahula Date: Tue, 10 Jan 2023 11:07:16 +0100 Subject: [PATCH 40/73] set email username and password to empty string in backend config --- backend/src/config/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/src/config/index.ts b/backend/src/config/index.ts index 22a509080..6258eb36a 100644 --- a/backend/src/config/index.ts +++ b/backend/src/config/index.ts @@ -69,9 +69,9 @@ const email = { EMAIL: process.env.EMAIL === 'true' || false, EMAIL_TEST_MODUS: process.env.EMAIL_TEST_MODUS === 'true' || false, EMAIL_TEST_RECEIVER: process.env.EMAIL_TEST_RECEIVER || 'stage1@gradido.net', - EMAIL_USERNAME: process.env.EMAIL_USERNAME || 'null', + EMAIL_USERNAME: process.env.EMAIL_USERNAME || '', EMAIL_SENDER: process.env.EMAIL_SENDER || 'info@gradido.net', - EMAIL_PASSWORD: process.env.EMAIL_PASSWORD || 'null', + EMAIL_PASSWORD: process.env.EMAIL_PASSWORD || '', EMAIL_SMTP_URL: process.env.EMAIL_SMTP_URL || 'mailserver', EMAIL_SMTP_PORT: process.env.EMAIL_SMTP_PORT || '1025', // eslint-disable-next-line no-unneeded-ternary From dded791586c67c23f84deededa89b8f78ac7a36b Mon Sep 17 00:00:00 2001 From: elweyn Date: Tue, 10 Jan 2023 11:54:44 +0100 Subject: [PATCH 41/73] Fix linting and locales --- frontend/src/locales/de.json | 6 +++--- frontend/src/locales/en.json | 6 +++++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/frontend/src/locales/de.json b/frontend/src/locales/de.json index e34d11297..2eabd6ab5 100644 --- a/frontend/src/locales/de.json +++ b/frontend/src/locales/de.json @@ -269,9 +269,7 @@ "warningText": "Bist du noch da?" }, "settings": { - "showAmountGDD": "Dein GDD Betrag ist sichtbar.", "hideAmountGDD": "Dein GDD Betrag ist versteckt.", - "showAmountGDT": "Dein GDT Betrag ist sichtbar.", "hideAmountGDT": "Dein GDT Betrag ist versteckt.", "language": { "changeLanguage": "Sprache ändern", @@ -305,7 +303,9 @@ "text": "Speichere nun dein neues Passwort, mit dem du dich zukünftig in deinem Gradido-Konto anmelden kannst." }, "subtitle": "Wenn du dein Passwort vergessen hast, kannst du es hier zurücksetzen." - } + }, + "showAmountGDD": "Dein GDD Betrag ist sichtbar.", + "showAmountGDT": "Dein GDT Betrag ist sichtbar." }, "signin": "Anmelden", "signup": "Registrieren", diff --git a/frontend/src/locales/en.json b/frontend/src/locales/en.json index 7837743e0..f90eef660 100644 --- a/frontend/src/locales/en.json +++ b/frontend/src/locales/en.json @@ -269,6 +269,8 @@ "warningText": "Are you still there?" }, "settings": { + "hideAmountGDD": "Your GDD amount is hidden.", + "hideAmountGDT": "Your GDT amount is hidden.", "language": { "changeLanguage": "Change language", "de": "Deutsch", @@ -301,7 +303,9 @@ "text": "Now save your new password, which you can use to log in to your Gradido account in the future." }, "subtitle": "If you have forgotten your password, you can reset it here." - } + }, + "showAmountGDD": "Your GDD amount is visible.", + "showAmountGDT": "Your GDT amount is visible." }, "signin": "Sign in", "signup": "Sign up", From 34014affa09c5774b80cad3460d0767b566d62b7 Mon Sep 17 00:00:00 2001 From: ogerly Date: Tue, 10 Jan 2023 12:20:55 +0100 Subject: [PATCH 42/73] send gdd and send link gdd is running --- .../GddSend/TransactionConfirmationLink.vue | 2 +- .../GddSend/TransactionConfirmationSend.vue | 2 +- frontend/src/components/GddSend/TransactionForm.vue | 2 +- .../components/GddSend/TransactionResultLink.vue | 2 +- .../GddSend/TransactionResultSendSuccess.vue | 2 +- frontend/src/pages/Send.vue | 13 +++++++------ 6 files changed, 12 insertions(+), 11 deletions(-) diff --git a/frontend/src/components/GddSend/TransactionConfirmationLink.vue b/frontend/src/components/GddSend/TransactionConfirmationLink.vue index 0fcb94459..91fea3486 100644 --- a/frontend/src/components/GddSend/TransactionConfirmationLink.vue +++ b/frontend/src/components/GddSend/TransactionConfirmationLink.vue @@ -37,7 +37,7 @@ - {{ $t('back') }} + {{ $t('back') }} - {{ $t('back') }} + {{ $t('back') }}
- + {{ $t('form.close') }}
diff --git a/frontend/src/components/GddSend/TransactionResultSendSuccess.vue b/frontend/src/components/GddSend/TransactionResultSendSuccess.vue index 36ce3f4e6..b57196db4 100644 --- a/frontend/src/components/GddSend/TransactionResultSendSuccess.vue +++ b/frontend/src/components/GddSend/TransactionResultSendSuccess.vue @@ -6,7 +6,7 @@ {{ $t('form.send_transaction_success') }}
- {{ $t('form.close') }} + {{ $t('form.close') }}
diff --git a/frontend/src/pages/Send.vue b/frontend/src/pages/Send.vue index 7131a7247..370943ad6 100644 --- a/frontend/src/pages/Send.vue +++ b/frontend/src/pages/Send.vue @@ -15,7 +15,7 @@ :amount="transactionData.amount" :memo="transactionData.memo" @send-transaction="sendTransaction" - @on-reset="onReset" + @on-back="onBack" > @@ -169,8 +169,9 @@ export default { } this.loading = false }, - onReset() { + onBack() { this.currentTransactionStep = TRANSACTION_STEPS.transactionForm + this.$mount() }, updateTransactions(pagination) { this.$emit('update-transactions', pagination) From 456b48650b68aca4bdf376b0583d6f7af2c61e4d Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Tue, 10 Jan 2023 12:33:06 +0100 Subject: [PATCH 43/73] mock and instead of using vue router --- frontend/src/pages/Community.spec.js | 27 ++++++--------------------- 1 file changed, 6 insertions(+), 21 deletions(-) diff --git a/frontend/src/pages/Community.spec.js b/frontend/src/pages/Community.spec.js index 62ed46cbb..04cce68e6 100644 --- a/frontend/src/pages/Community.spec.js +++ b/frontend/src/pages/Community.spec.js @@ -4,32 +4,12 @@ import { toastErrorSpy, toastSuccessSpy } from '@test/testSetup' import { createContribution, updateContribution, deleteContribution } from '@/graphql/mutations' import { listContributions, listAllContributions, verifyLogin } from '@/graphql/queries' -import VueRouter from 'vue-router' -import routes from '../routes/routes' - const localVue = global.localVue -localVue.use(VueRouter) const mockStoreDispach = jest.fn() const apolloQueryMock = jest.fn() const apolloMutationMock = jest.fn() -const router = new VueRouter({ - base: '/', - routes, - linkActiveClass: 'active', - mode: 'history', - // scrollBehavior: (to, from, savedPosition) => { - // if (savedPosition) { - // return savedPosition - // } - // if (to.hash) { - // return { selector: to.hash } - // } - // return { x: 0, y: 0 } - // }, -}) - describe('Community', () => { let wrapper @@ -49,12 +29,17 @@ describe('Community', () => { $i18n: { locale: 'en', }, + $router: { + push: jest.fn(), + }, + $route: { + hash: 'my', + }, } const Wrapper = () => { return mount(Community, { localVue, - router, mocks, }) } From 74c575882ae79827c180f024110610aa6b431d23 Mon Sep 17 00:00:00 2001 From: elweyn Date: Tue, 10 Jan 2023 13:56:39 +0100 Subject: [PATCH 44/73] Tests on GddAmount --- .../Template/ContentHeader/GddAmount.spec.js | 96 ++++++++++++++++++- 1 file changed, 95 insertions(+), 1 deletion(-) diff --git a/frontend/src/components/Template/ContentHeader/GddAmount.spec.js b/frontend/src/components/Template/ContentHeader/GddAmount.spec.js index fc7d65cc4..a335b0efb 100644 --- a/frontend/src/components/Template/ContentHeader/GddAmount.spec.js +++ b/frontend/src/components/Template/ContentHeader/GddAmount.spec.js @@ -1,20 +1,31 @@ import { mount } from '@vue/test-utils' import GddAmount from './GddAmount' +import { updateUserInfos } from '@/graphql/mutations' +import flushPromises from 'flush-promises' + +import { toastErrorSpy, toastSuccessSpy } from '@test/testSetup' const localVue = global.localVue +const mockAPICall = jest.fn() +const storeCommitMock = jest.fn() + const state = { - language: 'en', + hideAmountGDD: false, } const mocks = { $store: { state, + commit: storeCommitMock, }, $i18n: { locale: 'en', }, $t: jest.fn((t) => t), + $apollo: { + mutate: mockAPICall, + }, } const propsData = { @@ -38,5 +49,88 @@ describe('GddAmount', () => { it('renders the component gdd-amount', () => { expect(wrapper.find('div.gdd-amount').exists()).toBe(true) }) + + describe('API throws exception', () => { + beforeEach(async () => { + mockAPICall.mockRejectedValue({ + message: 'Ouch', + }) + jest.clearAllMocks() + await wrapper.find('div.border-left svg').trigger('click') + await flushPromises() + }) + + it('toasts an error message', () => { + expect(toastErrorSpy).toBeCalledWith('Ouch') + }) + }) + + describe('API call successful', () => { + beforeEach(async () => { + mockAPICall.mockResolvedValue({ + data: { + updateUserInfos: { + validValues: 1, + }, + }, + }) + jest.clearAllMocks() + await wrapper.find('div.border-left svg').trigger('click') + await flushPromises() + }) + + it('calls the API', () => { + expect(mockAPICall).toBeCalledWith( + expect.objectContaining({ + mutation: updateUserInfos, + variables: { + hideAmountGDD: true, + }, + }), + ) + }) + + it('commits hideAmountGDD to store', () => { + expect(storeCommitMock).toBeCalledWith('hideAmountGDD', true) + }) + + it('toasts a success message', () => { + expect(toastSuccessSpy).toBeCalledWith('settings.showAmountGDD') + }) + }) + }) + + describe.skip('second call to API', () => { + beforeEach(async () => { + mockAPICall.mockResolvedValue({ + data: { + updateUserInfos: { + validValues: 1, + }, + }, + }) + jest.clearAllMocks() + await wrapper.find('div.border-left svg').trigger('click') + await flushPromises() + }) + + it('calls the API', () => { + expect(mockAPICall).toBeCalledWith( + expect.objectContaining({ + mutation: updateUserInfos, + variables: { + hideAmountGDD: true, + }, + }), + ) + }) + + it('commits hideAmountGDD to store', () => { + expect(storeCommitMock).toBeCalledWith('hideAmountGDD', false) + }) + + it('toasts a success message', () => { + expect(toastSuccessSpy).toBeCalledWith('settings.hideAmountGDD') + }) }) }) From 01f054c1818ac1ab624e4a221cf6e01a9432b1e9 Mon Sep 17 00:00:00 2001 From: elweyn Date: Tue, 10 Jan 2023 13:56:52 +0100 Subject: [PATCH 45/73] Tests on GdtAmount --- .../Template/ContentHeader/GdtAmount.spec.js | 96 ++++++++++++++++++- 1 file changed, 95 insertions(+), 1 deletion(-) diff --git a/frontend/src/components/Template/ContentHeader/GdtAmount.spec.js b/frontend/src/components/Template/ContentHeader/GdtAmount.spec.js index 30ce85817..739a00676 100644 --- a/frontend/src/components/Template/ContentHeader/GdtAmount.spec.js +++ b/frontend/src/components/Template/ContentHeader/GdtAmount.spec.js @@ -1,19 +1,30 @@ import { mount } from '@vue/test-utils' import GdtAmount from './GdtAmount' +import { updateUserInfos } from '@/graphql/mutations' +import flushPromises from 'flush-promises' + +import { toastErrorSpy, toastSuccessSpy } from '@test/testSetup' const localVue = global.localVue +const mockAPICall = jest.fn() +const storeCommitMock = jest.fn() + const state = { - language: 'en', + hideAmountGDT: false, } const mocks = { $store: { state, + commit: storeCommitMock, }, $i18n: { locale: 'en', }, + $apollo: { + mutate: mockAPICall, + }, $t: jest.fn((t) => t), $n: jest.fn((n) => n), } @@ -39,5 +50,88 @@ describe('GdtAmount', () => { it('renders the component gdt-amount', () => { expect(wrapper.find('div.gdt-amount').exists()).toBe(true) }) + + describe('API throws exception', () => { + beforeEach(async () => { + mockAPICall.mockRejectedValue({ + message: 'Ouch', + }) + jest.clearAllMocks() + await wrapper.find('div.border-left svg').trigger('click') + await flushPromises() + }) + + it('toasts an error message', () => { + expect(toastErrorSpy).toBeCalledWith('Ouch') + }) + }) + + describe('API call successful', () => { + beforeEach(async () => { + mockAPICall.mockResolvedValue({ + data: { + updateUserInfos: { + validValues: 1, + }, + }, + }) + jest.clearAllMocks() + await wrapper.find('div.border-left svg').trigger('click') + await flushPromises() + }) + + it('calls the API', () => { + expect(mockAPICall).toBeCalledWith( + expect.objectContaining({ + mutation: updateUserInfos, + variables: { + hideAmountGDT: true, + }, + }), + ) + }) + + it('commits hideAmountGDT to store', () => { + expect(storeCommitMock).toBeCalledWith('hideAmountGDT', true) + }) + + it('toasts a success message', () => { + expect(toastSuccessSpy).toBeCalledWith('settings.showAmountGDT') + }) + }) + }) + + describe.skip('second call to API', () => { + beforeEach(async () => { + mockAPICall.mockResolvedValue({ + data: { + updateUserInfos: { + validValues: 1, + }, + }, + }) + jest.clearAllMocks() + await wrapper.find('div.border-left svg').trigger('click') + await flushPromises() + }) + + it('calls the API', () => { + expect(mockAPICall).toBeCalledWith( + expect.objectContaining({ + mutation: updateUserInfos, + variables: { + hideAmountGDT: true, + }, + }), + ) + }) + + it('commits hideAmountGDT to store', () => { + expect(storeCommitMock).toBeCalledWith('hideAmountGDT', false) + }) + + it('toasts a success message', () => { + expect(toastSuccessSpy).toBeCalledWith('settings.hideAmountGDT') + }) }) }) From 775240d13c68a72e8b36248fa2537e0032cf79c4 Mon Sep 17 00:00:00 2001 From: ogerly Date: Tue, 10 Jan 2023 13:58:34 +0100 Subject: [PATCH 46/73] fix test --- frontend/src/components/GddSend/TransactionForm.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/components/GddSend/TransactionForm.spec.js b/frontend/src/components/GddSend/TransactionForm.spec.js index 213301fda..59537dc47 100644 --- a/frontend/src/components/GddSend/TransactionForm.spec.js +++ b/frontend/src/components/GddSend/TransactionForm.spec.js @@ -322,7 +322,7 @@ Die ganze Welt bezwingen.“`) [ { email: 'someone@watches.tv', - amount: '87.23', + amount: 87.23, memo: 'Long enough', selected: 'send', }, From 676283449c4f518ca13392470c2a215d547db65b Mon Sep 17 00:00:00 2001 From: elweyn Date: Tue, 10 Jan 2023 14:35:56 +0100 Subject: [PATCH 47/73] Fix 'second call to API' test of Gdt- and GddAmount --- .../src/components/Template/ContentHeader/GddAmount.spec.js | 5 +++-- .../src/components/Template/ContentHeader/GdtAmount.spec.js | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/frontend/src/components/Template/ContentHeader/GddAmount.spec.js b/frontend/src/components/Template/ContentHeader/GddAmount.spec.js index a335b0efb..26967507b 100644 --- a/frontend/src/components/Template/ContentHeader/GddAmount.spec.js +++ b/frontend/src/components/Template/ContentHeader/GddAmount.spec.js @@ -100,7 +100,7 @@ describe('GddAmount', () => { }) }) - describe.skip('second call to API', () => { + describe('second call to API', () => { beforeEach(async () => { mockAPICall.mockResolvedValue({ data: { @@ -110,6 +110,7 @@ describe('GddAmount', () => { }, }) jest.clearAllMocks() + wrapper.vm.$store.state.hideAmountGDD = true await wrapper.find('div.border-left svg').trigger('click') await flushPromises() }) @@ -119,7 +120,7 @@ describe('GddAmount', () => { expect.objectContaining({ mutation: updateUserInfos, variables: { - hideAmountGDD: true, + hideAmountGDD: false, }, }), ) diff --git a/frontend/src/components/Template/ContentHeader/GdtAmount.spec.js b/frontend/src/components/Template/ContentHeader/GdtAmount.spec.js index 739a00676..58744cbfe 100644 --- a/frontend/src/components/Template/ContentHeader/GdtAmount.spec.js +++ b/frontend/src/components/Template/ContentHeader/GdtAmount.spec.js @@ -101,7 +101,7 @@ describe('GdtAmount', () => { }) }) - describe.skip('second call to API', () => { + describe('second call to API', () => { beforeEach(async () => { mockAPICall.mockResolvedValue({ data: { @@ -111,6 +111,7 @@ describe('GdtAmount', () => { }, }) jest.clearAllMocks() + wrapper.vm.$store.state.hideAmountGDT = true await wrapper.find('div.border-left svg').trigger('click') await flushPromises() }) @@ -120,7 +121,7 @@ describe('GdtAmount', () => { expect.objectContaining({ mutation: updateUserInfos, variables: { - hideAmountGDT: true, + hideAmountGDT: false, }, }), ) From c0b3a93a59138c39a11abcdff6c6198a9461fdce Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Wed, 11 Jan 2023 12:35:22 +0100 Subject: [PATCH 48/73] calculate last transaction correctly --- backend/src/graphql/resolver/BalanceResolver.ts | 2 +- backend/src/graphql/resolver/TransactionResolver.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/src/graphql/resolver/BalanceResolver.ts b/backend/src/graphql/resolver/BalanceResolver.ts index a0016e8f2..26f9cd656 100644 --- a/backend/src/graphql/resolver/BalanceResolver.ts +++ b/backend/src/graphql/resolver/BalanceResolver.ts @@ -32,7 +32,7 @@ export class BalanceResolver { const lastTransaction = context.lastTransaction ? context.lastTransaction - : await dbTransaction.findOne({ userId: user.id }, { order: { balanceDate: 'DESC' } }) + : await dbTransaction.findOne({ userId: user.id }, { order: { id: 'DESC' } }) logger.debug(`lastTransaction=${lastTransaction}`) diff --git a/backend/src/graphql/resolver/TransactionResolver.ts b/backend/src/graphql/resolver/TransactionResolver.ts index 0ac5b382e..33914583e 100644 --- a/backend/src/graphql/resolver/TransactionResolver.ts +++ b/backend/src/graphql/resolver/TransactionResolver.ts @@ -211,7 +211,7 @@ export class TransactionResolver { // find current balance const lastTransaction = await dbTransaction.findOne( { userId: user.id }, - { order: { balanceDate: 'DESC' }, relations: ['contribution'] }, + { order: { id: 'DESC' }, relations: ['contribution'] }, ) logger.debug(`lastTransaction=${lastTransaction}`) From c585b2c234e1c577d1ce47d006e72e2b95f04bbb Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Wed, 11 Jan 2023 13:08:47 +0100 Subject: [PATCH 49/73] check for confirmed transaction within semaphore lock --- .../src/graphql/resolver/ContributionResolver.ts | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/backend/src/graphql/resolver/ContributionResolver.ts b/backend/src/graphql/resolver/ContributionResolver.ts index 2587aab61..4c78ae1e7 100644 --- a/backend/src/graphql/resolver/ContributionResolver.ts +++ b/backend/src/graphql/resolver/ContributionResolver.ts @@ -553,11 +553,15 @@ export class ContributionResolver { @Arg('id', () => Int) id: number, @Ctx() context: Context, ): Promise { + // acquire lock + const releaseLock = await TRANSACTIONS_LOCK.acquire() + const clientTimezoneOffset = getClientTimezoneOffset(context) - const contribution = await DbContribution.findOne(id) + + const contribution = await DbContribution.findOne({ id, confirmedAt: IsNull() }) if (!contribution) { - logger.error(`Contribution not found for given id: ${id}`) - throw new Error('Contribution not found to given id.') + logger.error(`Contribution not found to given id (${id}) or already confirmed`) + throw new Error('Contribution not found to given id or already confirmed.') } const moderatorUser = getUser(context) if (moderatorUser.id === contribution.userId) { @@ -580,9 +584,6 @@ export class ContributionResolver { clientTimezoneOffset, ) - // acquire lock - const releaseLock = await TRANSACTIONS_LOCK.acquire() - const receivedCallDate = new Date() const queryRunner = getConnection().createQueryRunner() await queryRunner.connect() From c9488c8b8168152f5e49778d930c9ea9aa96a060 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Wed, 11 Jan 2023 13:11:40 +0100 Subject: [PATCH 50/73] try to minimize changeset --- backend/src/graphql/resolver/ContributionResolver.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/backend/src/graphql/resolver/ContributionResolver.ts b/backend/src/graphql/resolver/ContributionResolver.ts index 4c78ae1e7..ef273a60b 100644 --- a/backend/src/graphql/resolver/ContributionResolver.ts +++ b/backend/src/graphql/resolver/ContributionResolver.ts @@ -557,9 +557,8 @@ export class ContributionResolver { const releaseLock = await TRANSACTIONS_LOCK.acquire() const clientTimezoneOffset = getClientTimezoneOffset(context) - const contribution = await DbContribution.findOne({ id, confirmedAt: IsNull() }) - if (!contribution) { + if (!contribution) {P logger.error(`Contribution not found to given id (${id}) or already confirmed`) throw new Error('Contribution not found to given id or already confirmed.') } From 8628a05a219661ac33627eef5d0b43533a7ca6e2 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Wed, 11 Jan 2023 13:14:50 +0100 Subject: [PATCH 51/73] properly use findOne where --- backend/src/graphql/resolver/ContributionResolver.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/src/graphql/resolver/ContributionResolver.ts b/backend/src/graphql/resolver/ContributionResolver.ts index ef273a60b..f83202e1c 100644 --- a/backend/src/graphql/resolver/ContributionResolver.ts +++ b/backend/src/graphql/resolver/ContributionResolver.ts @@ -557,8 +557,8 @@ export class ContributionResolver { const releaseLock = await TRANSACTIONS_LOCK.acquire() const clientTimezoneOffset = getClientTimezoneOffset(context) - const contribution = await DbContribution.findOne({ id, confirmedAt: IsNull() }) - if (!contribution) {P + const contribution = await DbContribution.findOne({ where: { id, confirmedAt: IsNull() } }) + if (!contribution) { logger.error(`Contribution not found to given id (${id}) or already confirmed`) throw new Error('Contribution not found to given id or already confirmed.') } From 23ce6f62c11905f8dcf2901d95eedd7960c0e950 Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Wed, 11 Jan 2023 13:26:29 +0100 Subject: [PATCH 52/73] fix(other): update browser list --- admin/yarn.lock | 6 +++--- backend/yarn.lock | 6 +++--- frontend/yarn.lock | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/admin/yarn.lock b/admin/yarn.lock index 7507f2559..5d8275b1a 100644 --- a/admin/yarn.lock +++ b/admin/yarn.lock @@ -4141,9 +4141,9 @@ caniuse-api@^3.0.0: lodash.uniq "^4.5.0" caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000844, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001271: - version "1.0.30001354" - resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001354.tgz" - integrity sha512-mImKeCkyGDAHNywYFA4bqnLAzTUvVkqPvhY4DV47X+Gl2c5Z8c3KNETnXp14GQt11LvxE8AwjzGxJ+rsikiOzg== + version "1.0.30001442" + resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001442.tgz" + integrity sha512-239m03Pqy0hwxYPYR5JwOIxRJfLTWtle9FV8zosfV5pHg+/51uD4nxcUlM8+mWWGfwKtt8lJNHnD3cWw9VZ6ow== capture-exit@^2.0.0: version "2.0.0" diff --git a/backend/yarn.lock b/backend/yarn.lock index 82bcd6b1f..264cbd409 100644 --- a/backend/yarn.lock +++ b/backend/yarn.lock @@ -1913,9 +1913,9 @@ camelcase@^6.2.0: integrity sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg== caniuse-lite@^1.0.30001264: - version "1.0.30001418" - resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001418.tgz" - integrity sha512-oIs7+JL3K9JRQ3jPZjlH6qyYDp+nBTCais7hjh0s+fuBwufc7uZ7hPYMXrDOJhV360KGMTcczMRObk0/iMqZRg== + version "1.0.30001442" + resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001442.tgz" + integrity sha512-239m03Pqy0hwxYPYR5JwOIxRJfLTWtle9FV8zosfV5pHg+/51uD4nxcUlM8+mWWGfwKtt8lJNHnD3cWw9VZ6ow== chacha20-universal@^1.0.4: version "1.0.4" diff --git a/frontend/yarn.lock b/frontend/yarn.lock index ff3a7ff1a..f374ac7bd 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -4578,9 +4578,9 @@ caniuse-api@^3.0.0: lodash.uniq "^4.5.0" caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001181, caniuse-lite@^1.0.30001280, caniuse-lite@^1.0.30001286: - version "1.0.30001439" - resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001439.tgz" - integrity sha512-1MgUzEkoMO6gKfXflStpYgZDlFM7M/ck/bgfVCACO5vnAf0fXoNVHdWtqGU+MYca+4bL9Z5bpOVmR33cWW9G2A== + version "1.0.30001442" + resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001442.tgz" + integrity sha512-239m03Pqy0hwxYPYR5JwOIxRJfLTWtle9FV8zosfV5pHg+/51uD4nxcUlM8+mWWGfwKtt8lJNHnD3cWw9VZ6ow== capture-exit@^2.0.0: version "2.0.0" From dc33427cd0529e9ee151cc1e01e3b3a57ddc6a0f Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Wed, 11 Jan 2023 15:15:26 +0100 Subject: [PATCH 53/73] add openCreation graphqlModel and resolver --- backend/src/auth/RIGHTS.ts | 1 + backend/src/auth/ROLES.ts | 1 + backend/src/graphql/model/OpenCreation.ts | 14 +++++++++++ .../graphql/resolver/ContributionResolver.ts | 23 ++++++++++++++++++- .../src/graphql/resolver/util/creations.ts | 10 +++++--- 5 files changed, 45 insertions(+), 4 deletions(-) create mode 100644 backend/src/graphql/model/OpenCreation.ts diff --git a/backend/src/auth/RIGHTS.ts b/backend/src/auth/RIGHTS.ts index 4f144f1e9..6515f9e3b 100644 --- a/backend/src/auth/RIGHTS.ts +++ b/backend/src/auth/RIGHTS.ts @@ -35,6 +35,7 @@ export enum RIGHTS { SEARCH_ADMIN_USERS = 'SEARCH_ADMIN_USERS', CREATE_CONTRIBUTION_MESSAGE = 'CREATE_CONTRIBUTION_MESSAGE', LIST_ALL_CONTRIBUTION_MESSAGES = 'LIST_ALL_CONTRIBUTION_MESSAGES', + OPEN_CREATIONS = 'OPEN_CREATIONS', // Admin SEARCH_USERS = 'SEARCH_USERS', SET_USER_ROLE = 'SET_USER_ROLE', diff --git a/backend/src/auth/ROLES.ts b/backend/src/auth/ROLES.ts index eabaf8e99..2f3b4e081 100644 --- a/backend/src/auth/ROLES.ts +++ b/backend/src/auth/ROLES.ts @@ -33,6 +33,7 @@ export const ROLE_USER = new Role('user', [ RIGHTS.COMMUNITY_STATISTICS, RIGHTS.CREATE_CONTRIBUTION_MESSAGE, RIGHTS.LIST_ALL_CONTRIBUTION_MESSAGES, + RIGHTS.OPEN_CREATIONS, ]) export const ROLE_ADMIN = new Role('admin', Object.values(RIGHTS)) // all rights diff --git a/backend/src/graphql/model/OpenCreation.ts b/backend/src/graphql/model/OpenCreation.ts new file mode 100644 index 000000000..9ef08fd4a --- /dev/null +++ b/backend/src/graphql/model/OpenCreation.ts @@ -0,0 +1,14 @@ +import { ObjectType, Field, Int } from 'type-graphql' +import Decimal from 'decimal.js-light' + +@ObjectType() +export class OpenCreation { + @Field(() => Int) + month: number + + @Field(() => Int) + year: number + + @Field(() => Decimal) + amount: Decimal +} diff --git a/backend/src/graphql/resolver/ContributionResolver.ts b/backend/src/graphql/resolver/ContributionResolver.ts index 2587aab61..db32a910e 100644 --- a/backend/src/graphql/resolver/ContributionResolver.ts +++ b/backend/src/graphql/resolver/ContributionResolver.ts @@ -11,8 +11,9 @@ import { Transaction as DbTransaction } from '@entity/Transaction' import { AdminCreateContributions } from '@model/AdminCreateContributions' import { AdminUpdateContribution } from '@model/AdminUpdateContribution' import { Contribution, ContributionListResult } from '@model/Contribution' -import { UnconfirmedContribution } from '@model/UnconfirmedContribution' import { Decay } from '@model/Decay' +import { OpenCreation } from '@model/OpenCreation' +import { UnconfirmedContribution } from '@model/UnconfirmedContribution' import { TransactionTypeId } from '@enum/TransactionTypeId' import { Order } from '@enum/Order' import { ContributionType } from '@enum/ContributionType' @@ -27,6 +28,7 @@ import { RIGHTS } from '@/auth/RIGHTS' import { Context, getUser, getClientTimezoneOffset } from '@/server/context' import { backendLogger as logger } from '@/server/logger' import { + getCreationDates, getUserCreation, getUserCreations, validateContribution, @@ -683,4 +685,23 @@ export class ContributionResolver { ) // return userTransactions.map((t) => new Transaction(t, new User(user), communityUser)) } + + @Authorized([RIGHTS.OPEN_CREATIONS]) + @Query(() => [OpenCreation]) + async openCreations( + @Arg('userId', () => Int, { nullable: true }) userId: number | null, + @Ctx() context: Context, + ): Promise { + const id = userId || getUser(context).id + const clientTimezoneOffset = getClientTimezoneOffset(context) + const creationDates = getCreationDates(clientTimezoneOffset) + const creations = await getUserCreation(id, clientTimezoneOffset) + return creationDates.map((date, index) => { + return { + month: date.getMonth(), + year: date.getFullYear(), + amount: creations[index], + } + }) + } } diff --git a/backend/src/graphql/resolver/util/creations.ts b/backend/src/graphql/resolver/util/creations.ts index 54286d2aa..00137eaa1 100644 --- a/backend/src/graphql/resolver/util/creations.ts +++ b/backend/src/graphql/resolver/util/creations.ts @@ -101,15 +101,19 @@ export const getUserCreation = async ( } const getCreationMonths = (timezoneOffset: number): number[] => { + return getCreationDates(timezoneOffset).map((date) => date.getMonth() + 1) +} + +export const getCreationDates = (timezoneOffset: number): Date[] => { const clientNow = new Date() clientNow.setTime(clientNow.getTime() - timezoneOffset * 60 * 1000) logger.info( `getCreationMonths -- offset: ${timezoneOffset} -- clientNow: ${clientNow.toISOString()}`, ) return [ - new Date(clientNow.getFullYear(), clientNow.getMonth() - 2, 1).getMonth() + 1, - new Date(clientNow.getFullYear(), clientNow.getMonth() - 1, 1).getMonth() + 1, - clientNow.getMonth() + 1, + new Date(clientNow.getFullYear(), clientNow.getMonth() - 2, 1), + new Date(clientNow.getFullYear(), clientNow.getMonth() - 1, 1), + clientNow, ] } From 340554b8150b24946ebd34b49813895c61514ba5 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Wed, 11 Jan 2023 15:39:33 +0100 Subject: [PATCH 54/73] skipped alot of test due to unknown timeout errors --- .../resolver/ContributionResolver.test.ts | 38 ++++++++++++------- .../graphql/resolver/ContributionResolver.ts | 2 +- 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/backend/src/graphql/resolver/ContributionResolver.test.ts b/backend/src/graphql/resolver/ContributionResolver.test.ts index 3dfd09bb5..77e6e266c 100644 --- a/backend/src/graphql/resolver/ContributionResolver.test.ts +++ b/backend/src/graphql/resolver/ContributionResolver.test.ts @@ -414,7 +414,7 @@ describe('ContributionResolver', () => { resetToken() }) - describe('wrong contribution id', () => { + describe.skip('wrong contribution id', () => { it('throws an error', async () => { jest.clearAllMocks() await expect( @@ -429,13 +429,17 @@ describe('ContributionResolver', () => { }), ).resolves.toEqual( expect.objectContaining({ - errors: [new GraphQLError('No contribution found to given id.')], + errors: [ + new GraphQLError('Contribution not found to given id or already confirmed.'), + ], }), ) }) it('logs the error found', () => { - expect(logger.error).toBeCalledWith('No contribution found to given id') + expect(logger.error).toBeCalledWith( + 'Contribution not found to given id (-1) or already confirmed.', + ) }) }) @@ -790,7 +794,7 @@ describe('ContributionResolver', () => { resetToken() }) - describe('wrong contribution id', () => { + describe.skip('wrong contribution id', () => { it('returns an error', async () => { await expect( mutate({ @@ -801,13 +805,17 @@ describe('ContributionResolver', () => { }), ).resolves.toEqual( expect.objectContaining({ - errors: [new GraphQLError('Contribution not found for given id.')], + errors: [ + new GraphQLError('Contribution not found to given id or already confirmed.'), + ], }), ) }) it('logs the error found', () => { - expect(logger.error).toBeCalledWith('Contribution not found for given id') + expect(logger.error).toBeCalledWith( + 'Contribution not found to given id (-1) or already confirmed.', + ) }) }) @@ -836,7 +844,7 @@ describe('ContributionResolver', () => { }) }) - describe('User deletes own contribution', () => { + describe.skip('User deletes own contribution', () => { it('deletes successfully', async () => { await expect( mutate({ @@ -1833,17 +1841,21 @@ describe('ContributionResolver', () => { }), ).resolves.toEqual( expect.objectContaining({ - errors: [new GraphQLError('Contribution not found to given id.')], + errors: [ + new GraphQLError('Contribution not found to given id or already confirmed.'), + ], }), ) }) it('logs the error thrown', () => { - expect(logger.error).toBeCalledWith('Contribution not found for given id: -1') + expect(logger.error).toBeCalledWith( + 'Contribution not found to given id (-1) or already confirmed.', + ) }) }) - describe('confirm own creation', () => { + describe.skip('confirm own creation', () => { beforeAll(async () => { const now = new Date() creation = await creationFactory(testEnv, { @@ -1876,7 +1888,7 @@ describe('ContributionResolver', () => { }) }) - describe('confirm creation for other user', () => { + describe.skip('confirm creation for other user', () => { beforeAll(async () => { const now = new Date() creation = await creationFactory(testEnv, { @@ -1908,7 +1920,7 @@ describe('ContributionResolver', () => { ) }) - it('stores the contribution confirm event in the database', async () => { + it.skip('stores the contribution confirm event in the database', async () => { await expect(EventProtocol.find()).resolves.toContainEqual( expect.objectContaining({ type: EventProtocolType.CONTRIBUTION_CONFIRM, @@ -1977,7 +1989,7 @@ describe('ContributionResolver', () => { }) }) - it('throws no error for the second confirmation', async () => { + it.skip('throws no error for the second confirmation', async () => { const r1 = mutate({ mutation: confirmContribution, variables: { diff --git a/backend/src/graphql/resolver/ContributionResolver.ts b/backend/src/graphql/resolver/ContributionResolver.ts index f83202e1c..5f78fff7d 100644 --- a/backend/src/graphql/resolver/ContributionResolver.ts +++ b/backend/src/graphql/resolver/ContributionResolver.ts @@ -559,7 +559,7 @@ export class ContributionResolver { const clientTimezoneOffset = getClientTimezoneOffset(context) const contribution = await DbContribution.findOne({ where: { id, confirmedAt: IsNull() } }) if (!contribution) { - logger.error(`Contribution not found to given id (${id}) or already confirmed`) + logger.error(`Contribution not found to given id (${id}) or already confirmed.`) throw new Error('Contribution not found to given id or already confirmed.') } const moderatorUser = getUser(context) From 2d4f7f9fd5bd7be5340f2fbb99c292bc00f2dcb8 Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Wed, 11 Jan 2023 20:15:02 +0100 Subject: [PATCH 55/73] get open creations via own apollo call --- frontend/src/graphql/queries.js | 10 ++++++++++ frontend/src/pages/Community.vue | 33 +++++++++++++++++++++++++++----- 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/frontend/src/graphql/queries.js b/frontend/src/graphql/queries.js index db6a68bf4..65fde8d1d 100644 --- a/frontend/src/graphql/queries.js +++ b/frontend/src/graphql/queries.js @@ -250,3 +250,13 @@ export const listContributionMessages = gql` } } ` + +export const openCreations = gql` + query { + openCreations { + year + month + amount + } + } +` diff --git a/frontend/src/pages/Community.vue b/frontend/src/pages/Community.vue index 16af01ce3..29173921f 100644 --- a/frontend/src/pages/Community.vue +++ b/frontend/src/pages/Community.vue @@ -52,7 +52,12 @@ import OpenCreationsAmount from '@/components/Contributions/OpenCreationsAmount. import ContributionForm from '@/components/Contributions/ContributionForm.vue' import ContributionList from '@/components/Contributions/ContributionList.vue' import { createContribution, updateContribution, deleteContribution } from '@/graphql/mutations' -import { listContributions, listAllContributions, verifyLogin } from '@/graphql/queries' +import { + listContributions, + listAllContributions, + verifyLogin, + openCreations, +} from '@/graphql/queries' export default { name: 'Community', @@ -82,6 +87,7 @@ export default { }, updateAmount: '', maximalDate: new Date(), + openCreations: [], } }, mounted() { @@ -90,6 +96,23 @@ export default { this.hashLink = this.$route.hash }) }, + apollo: { + OpenCreations: { + query() { + return openCreations + }, + fetchPolicy: 'network-only', + variables() { + return {} + }, + update({ openCreations }) { + this.openCreations = openCreations + }, + error({ message }) { + this.toastError(message) + }, + }, + }, watch: { $route(to, from) { this.tabIndex = this.tabLinkHashes.findIndex((hashLink) => hashLink === to.hash) @@ -123,14 +146,14 @@ export default { maxGddLastMonth() { // when existing contribution is edited, the amount is added back on top of the amount return this.form.id && !this.isThisMonth - ? parseInt(this.$store.state.creation[1]) + parseInt(this.updateAmount) - : parseInt(this.$store.state.creation[1]) + ? parseInt(this.openCreations[1].amount) + parseInt(this.updateAmount) + : parseInt(this.openCreations[1].amount) }, maxGddThisMonth() { // when existing contribution is edited, the amount is added back on top of the amount return this.form.id && this.isThisMonth - ? parseInt(this.$store.state.creation[2]) + parseInt(this.updateAmount) - : parseInt(this.$store.state.creation[2]) + ? parseInt(this.openCreations[2].amount) + parseInt(this.updateAmount) + : parseInt(this.openCreations[2].amount) }, }, methods: { From 6389697bd69f2df5f76d74a9feb1420ff9a6d9fa Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Wed, 11 Jan 2023 21:13:38 +0100 Subject: [PATCH 56/73] reset unit tests --- .../resolver/ContributionResolver.test.ts | 38 +++++++------------ .../graphql/resolver/ContributionResolver.ts | 10 +++-- 2 files changed, 20 insertions(+), 28 deletions(-) diff --git a/backend/src/graphql/resolver/ContributionResolver.test.ts b/backend/src/graphql/resolver/ContributionResolver.test.ts index 77e6e266c..3dfd09bb5 100644 --- a/backend/src/graphql/resolver/ContributionResolver.test.ts +++ b/backend/src/graphql/resolver/ContributionResolver.test.ts @@ -414,7 +414,7 @@ describe('ContributionResolver', () => { resetToken() }) - describe.skip('wrong contribution id', () => { + describe('wrong contribution id', () => { it('throws an error', async () => { jest.clearAllMocks() await expect( @@ -429,17 +429,13 @@ describe('ContributionResolver', () => { }), ).resolves.toEqual( expect.objectContaining({ - errors: [ - new GraphQLError('Contribution not found to given id or already confirmed.'), - ], + errors: [new GraphQLError('No contribution found to given id.')], }), ) }) it('logs the error found', () => { - expect(logger.error).toBeCalledWith( - 'Contribution not found to given id (-1) or already confirmed.', - ) + expect(logger.error).toBeCalledWith('No contribution found to given id') }) }) @@ -794,7 +790,7 @@ describe('ContributionResolver', () => { resetToken() }) - describe.skip('wrong contribution id', () => { + describe('wrong contribution id', () => { it('returns an error', async () => { await expect( mutate({ @@ -805,17 +801,13 @@ describe('ContributionResolver', () => { }), ).resolves.toEqual( expect.objectContaining({ - errors: [ - new GraphQLError('Contribution not found to given id or already confirmed.'), - ], + errors: [new GraphQLError('Contribution not found for given id.')], }), ) }) it('logs the error found', () => { - expect(logger.error).toBeCalledWith( - 'Contribution not found to given id (-1) or already confirmed.', - ) + expect(logger.error).toBeCalledWith('Contribution not found for given id') }) }) @@ -844,7 +836,7 @@ describe('ContributionResolver', () => { }) }) - describe.skip('User deletes own contribution', () => { + describe('User deletes own contribution', () => { it('deletes successfully', async () => { await expect( mutate({ @@ -1841,21 +1833,17 @@ describe('ContributionResolver', () => { }), ).resolves.toEqual( expect.objectContaining({ - errors: [ - new GraphQLError('Contribution not found to given id or already confirmed.'), - ], + errors: [new GraphQLError('Contribution not found to given id.')], }), ) }) it('logs the error thrown', () => { - expect(logger.error).toBeCalledWith( - 'Contribution not found to given id (-1) or already confirmed.', - ) + expect(logger.error).toBeCalledWith('Contribution not found for given id: -1') }) }) - describe.skip('confirm own creation', () => { + describe('confirm own creation', () => { beforeAll(async () => { const now = new Date() creation = await creationFactory(testEnv, { @@ -1888,7 +1876,7 @@ describe('ContributionResolver', () => { }) }) - describe.skip('confirm creation for other user', () => { + describe('confirm creation for other user', () => { beforeAll(async () => { const now = new Date() creation = await creationFactory(testEnv, { @@ -1920,7 +1908,7 @@ describe('ContributionResolver', () => { ) }) - it.skip('stores the contribution confirm event in the database', async () => { + it('stores the contribution confirm event in the database', async () => { await expect(EventProtocol.find()).resolves.toContainEqual( expect.objectContaining({ type: EventProtocolType.CONTRIBUTION_CONFIRM, @@ -1989,7 +1977,7 @@ describe('ContributionResolver', () => { }) }) - it.skip('throws no error for the second confirmation', async () => { + it('throws no error for the second confirmation', async () => { const r1 = mutate({ mutation: confirmContribution, variables: { diff --git a/backend/src/graphql/resolver/ContributionResolver.ts b/backend/src/graphql/resolver/ContributionResolver.ts index 5f78fff7d..12da50ed0 100644 --- a/backend/src/graphql/resolver/ContributionResolver.ts +++ b/backend/src/graphql/resolver/ContributionResolver.ts @@ -557,10 +557,14 @@ export class ContributionResolver { const releaseLock = await TRANSACTIONS_LOCK.acquire() const clientTimezoneOffset = getClientTimezoneOffset(context) - const contribution = await DbContribution.findOne({ where: { id, confirmedAt: IsNull() } }) + const contribution = await DbContribution.findOne(id) if (!contribution) { - logger.error(`Contribution not found to given id (${id}) or already confirmed.`) - throw new Error('Contribution not found to given id or already confirmed.') + logger.error(`Contribution not found for given id: ${id}`) + throw new Error('Contribution not found to given id.') + } + if (contribution.confirmedAt) { + logger.error(`Contribution already confirmd: ${id}`) + throw new Error('Contribution already confirmd.') } const moderatorUser = getUser(context) if (moderatorUser.id === contribution.userId) { From 29479bafec3843ba4ac4a88c762937763c53af62 Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Wed, 11 Jan 2023 21:29:11 +0100 Subject: [PATCH 57/73] release lock after each error --- backend/src/graphql/resolver/ContributionResolver.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/backend/src/graphql/resolver/ContributionResolver.ts b/backend/src/graphql/resolver/ContributionResolver.ts index 12da50ed0..45b3d2553 100644 --- a/backend/src/graphql/resolver/ContributionResolver.ts +++ b/backend/src/graphql/resolver/ContributionResolver.ts @@ -560,15 +560,18 @@ export class ContributionResolver { const contribution = await DbContribution.findOne(id) if (!contribution) { logger.error(`Contribution not found for given id: ${id}`) + releaseLock() throw new Error('Contribution not found to given id.') } if (contribution.confirmedAt) { logger.error(`Contribution already confirmd: ${id}`) + releaseLock() throw new Error('Contribution already confirmd.') } const moderatorUser = getUser(context) if (moderatorUser.id === contribution.userId) { logger.error('Moderator can not confirm own contribution') + releaseLock() throw new Error('Moderator can not confirm own contribution') } const user = await DbUser.findOneOrFail( @@ -577,6 +580,7 @@ export class ContributionResolver { ) if (user.deletedAt) { logger.error('This user was deleted. Cannot confirm a contribution.') + releaseLock() throw new Error('This user was deleted. Cannot confirm a contribution.') } const creations = await getUserCreation(contribution.userId, clientTimezoneOffset, false) From 8f9e77a9c1ee4862902d786fe5b3f5c2771e1e23 Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Wed, 11 Jan 2023 21:40:11 +0100 Subject: [PATCH 58/73] add test: confirming a confirmed contribution throws --- .../resolver/ContributionResolver.test.ts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/backend/src/graphql/resolver/ContributionResolver.test.ts b/backend/src/graphql/resolver/ContributionResolver.test.ts index 3dfd09bb5..9a7fb76f2 100644 --- a/backend/src/graphql/resolver/ContributionResolver.test.ts +++ b/backend/src/graphql/resolver/ContributionResolver.test.ts @@ -1947,6 +1947,23 @@ describe('ContributionResolver', () => { }), ) }) + + describe('confirm same contribution again', () => { + it('throws an error', async () => { + await expect( + mutate({ + mutation: confirmContribution, + variables: { + id: creation ? creation.id : -1, + }, + }), + ).resolves.toEqual( + expect.objectContaining({ + errors: [new GraphQLError('Contribution already confirmd.')], + }), + ) + }) + }) }) describe('confirm two creations one after the other quickly', () => { From edd2fb992eacad97a7792a1c843664fae7f2a58f Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Wed, 11 Jan 2023 22:10:34 +0100 Subject: [PATCH 59/73] remove verify login --- frontend/src/pages/Community.vue | 47 ++++++++++---------------------- 1 file changed, 14 insertions(+), 33 deletions(-) diff --git a/frontend/src/pages/Community.vue b/frontend/src/pages/Community.vue index 29173921f..9a18db9c0 100644 --- a/frontend/src/pages/Community.vue +++ b/frontend/src/pages/Community.vue @@ -52,12 +52,7 @@ import OpenCreationsAmount from '@/components/Contributions/OpenCreationsAmount. import ContributionForm from '@/components/Contributions/ContributionForm.vue' import ContributionList from '@/components/Contributions/ContributionList.vue' import { createContribution, updateContribution, deleteContribution } from '@/graphql/mutations' -import { - listContributions, - listAllContributions, - verifyLogin, - openCreations, -} from '@/graphql/queries' +import { listContributions, listAllContributions, openCreations } from '@/graphql/queries' export default { name: 'Community', @@ -145,15 +140,19 @@ export default { }, maxGddLastMonth() { // when existing contribution is edited, the amount is added back on top of the amount - return this.form.id && !this.isThisMonth - ? parseInt(this.openCreations[1].amount) + parseInt(this.updateAmount) - : parseInt(this.openCreations[1].amount) + if (this.openCreations && this.openCreations.length) + return this.form.id && !this.isThisMonth + ? parseInt(this.openCreations[1].amount) + parseInt(this.updateAmount) + : parseInt(this.openCreations[1].amount) + return 0 }, maxGddThisMonth() { // when existing contribution is edited, the amount is added back on top of the amount - return this.form.id && this.isThisMonth - ? parseInt(this.openCreations[2].amount) + parseInt(this.updateAmount) - : parseInt(this.openCreations[2].amount) + if (this.openCreations && this.openCreations.length) + return this.form.id && this.isThisMonth + ? parseInt(this.openCreations[2].amount) + parseInt(this.updateAmount) + : parseInt(this.openCreations[2].amount) + return 0 }, }, methods: { @@ -183,7 +182,7 @@ export default { currentPage: this.currentPage, pageSize: this.pageSize, }) - this.verifyLogin() + this.$apollo.queries.OpenCreations.refetch() }) .catch((err) => { this.toastError(err.message) @@ -211,7 +210,7 @@ export default { currentPage: this.currentPage, pageSize: this.pageSize, }) - this.verifyLogin() + this.$apollo.queries.OpenCreations.refetch() }) .catch((err) => { this.toastError(err.message) @@ -236,7 +235,7 @@ export default { currentPage: this.currentPage, pageSize: this.pageSize, }) - this.verifyLogin() + this.$apollo.queries.OpenCreations.refetch() }) .catch((err) => { this.toastError(err.message) @@ -291,22 +290,6 @@ export default { this.toastError(err.message) }) }, - verifyLogin() { - this.$apollo - .query({ - query: verifyLogin, - fetchPolicy: 'network-only', - }) - .then((result) => { - const { - data: { verifyLogin }, - } = result - this.$store.dispatch('login', verifyLogin) - }) - .catch(() => { - this.$emit('logout') - }) - }, updateContributionForm(item) { this.form.id = item.id this.form.date = item.contributionDate @@ -326,8 +309,6 @@ export default { }, created() { - // verifyLogin is important at this point so that creation is updated on reload if they are deleted in a session in the admin area. - this.verifyLogin() this.updateListContributions({ currentPage: this.currentPage, pageSize: this.pageSize, From a11b27e397f01d26856cb6ff870573e359325bf9 Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Wed, 11 Jan 2023 22:21:54 +0100 Subject: [PATCH 60/73] unit tests without verify login, test for apllo refetch instead --- frontend/src/pages/Community.spec.js | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/frontend/src/pages/Community.spec.js b/frontend/src/pages/Community.spec.js index 62ed46cbb..7297876df 100644 --- a/frontend/src/pages/Community.spec.js +++ b/frontend/src/pages/Community.spec.js @@ -2,7 +2,7 @@ import { mount } from '@vue/test-utils' import Community from './Community' import { toastErrorSpy, toastSuccessSpy } from '@test/testSetup' import { createContribution, updateContribution, deleteContribution } from '@/graphql/mutations' -import { listContributions, listAllContributions, verifyLogin } from '@/graphql/queries' +import { listContributions, listAllContributions } from '@/graphql/queries' import VueRouter from 'vue-router' import routes from '../routes/routes' @@ -13,6 +13,7 @@ localVue.use(VueRouter) const mockStoreDispach = jest.fn() const apolloQueryMock = jest.fn() const apolloMutationMock = jest.fn() +const apolloRefetchMock = jest.fn() const router = new VueRouter({ base: '/', @@ -39,6 +40,11 @@ describe('Community', () => { $apollo: { query: apolloQueryMock, mutate: apolloMutationMock, + queries: { + OpenCreations: { + refetch: apolloRefetchMock, + }, + }, }, $store: { dispatch: mockStoreDispach, @@ -207,10 +213,7 @@ describe('Community', () => { }) it('verifies the login (to get the new creations available)', () => { - expect(apolloQueryMock).toBeCalledWith({ - query: verifyLogin, - fetchPolicy: 'network-only', - }) + expect(apolloRefetchMock).toBeCalled() }) it('set all data to the default values)', () => { @@ -294,10 +297,7 @@ describe('Community', () => { }) it('verifies the login (to get the new creations available)', () => { - expect(apolloQueryMock).toBeCalledWith({ - query: verifyLogin, - fetchPolicy: 'network-only', - }) + expect(apolloRefetchMock).toBeCalled() }) it('set all data to the default values)', () => { @@ -376,10 +376,7 @@ describe('Community', () => { }) it('verifies the login (to get the new creations available)', () => { - expect(apolloQueryMock).toBeCalledWith({ - query: verifyLogin, - fetchPolicy: 'network-only', - }) + expect(apolloRefetchMock).toBeCalled() }) }) From 553710ba6a054959e196cf65f1d46f923e06255d Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Wed, 11 Jan 2023 22:26:43 +0100 Subject: [PATCH 61/73] remove creations from user frontend --- frontend/src/graphql/mutations.js | 1 - frontend/src/store/store.js | 6 ------ frontend/src/store/store.test.js | 32 ++++++------------------------- 3 files changed, 6 insertions(+), 33 deletions(-) diff --git a/frontend/src/graphql/mutations.js b/frontend/src/graphql/mutations.js index 95d7b0c39..111eb7ab5 100644 --- a/frontend/src/graphql/mutations.js +++ b/frontend/src/graphql/mutations.js @@ -154,7 +154,6 @@ export const login = gql` hasElopage publisherId isAdmin - creation hideAmountGDD hideAmountGDT } diff --git a/frontend/src/store/store.js b/frontend/src/store/store.js index 84fd82fd5..1cd874c06 100644 --- a/frontend/src/store/store.js +++ b/frontend/src/store/store.js @@ -47,9 +47,6 @@ export const mutations = { hasElopage: (state, hasElopage) => { state.hasElopage = hasElopage }, - creation: (state, creation) => { - state.creation = creation - }, hideAmountGDD: (state, hideAmountGDD) => { state.hideAmountGDD = !!hideAmountGDD }, @@ -69,7 +66,6 @@ export const actions = { commit('hasElopage', data.hasElopage) commit('publisherId', data.publisherId) commit('isAdmin', data.isAdmin) - commit('creation', data.creation) commit('hideAmountGDD', data.hideAmountGDD) commit('hideAmountGDT', data.hideAmountGDT) }, @@ -83,7 +79,6 @@ export const actions = { commit('hasElopage', false) commit('publisherId', null) commit('isAdmin', false) - commit('creation', null) commit('hideAmountGDD', false) commit('hideAmountGDT', true) localStorage.clear() @@ -111,7 +106,6 @@ try { newsletterState: null, hasElopage: false, publisherId: null, - creation: null, hideAmountGDD: null, hideAmountGDT: null, }, diff --git a/frontend/src/store/store.test.js b/frontend/src/store/store.test.js index 5f40d7fa2..33fedd562 100644 --- a/frontend/src/store/store.test.js +++ b/frontend/src/store/store.test.js @@ -30,7 +30,6 @@ const { publisherId, isAdmin, hasElopage, - creation, hideAmountGDD, hideAmountGDT, } = mutations @@ -143,14 +142,6 @@ describe('Vuex store', () => { }) }) - describe('creation', () => { - it('sets the state of creation', () => { - const state = { creation: null } - creation(state, true) - expect(state.creation).toEqual(true) - }) - }) - describe('hideAmountGDD', () => { it('sets the state of hideAmountGDD', () => { const state = { hideAmountGDD: false } @@ -183,14 +174,13 @@ describe('Vuex store', () => { hasElopage: false, publisherId: 1234, isAdmin: true, - creation: ['1000', '1000', '1000'], hideAmountGDD: false, hideAmountGDT: true, } it('calls eleven commits', () => { login({ commit, state }, commitedData) - expect(commit).toHaveBeenCalledTimes(11) + expect(commit).toHaveBeenCalledTimes(10) }) it('commits email', () => { @@ -233,19 +223,14 @@ describe('Vuex store', () => { expect(commit).toHaveBeenNthCalledWith(8, 'isAdmin', true) }) - it('commits creation', () => { - login({ commit, state }, commitedData) - expect(commit).toHaveBeenNthCalledWith(9, 'creation', ['1000', '1000', '1000']) - }) - it('commits hideAmountGDD', () => { login({ commit, state }, commitedData) - expect(commit).toHaveBeenNthCalledWith(10, 'hideAmountGDD', false) + expect(commit).toHaveBeenNthCalledWith(9, 'hideAmountGDD', false) }) it('commits hideAmountGDT', () => { login({ commit, state }, commitedData) - expect(commit).toHaveBeenNthCalledWith(11, 'hideAmountGDT', true) + expect(commit).toHaveBeenNthCalledWith(10, 'hideAmountGDT', true) }) }) @@ -255,7 +240,7 @@ describe('Vuex store', () => { it('calls eleven commits', () => { logout({ commit, state }) - expect(commit).toHaveBeenCalledTimes(11) + expect(commit).toHaveBeenCalledTimes(10) }) it('commits token', () => { @@ -298,19 +283,14 @@ describe('Vuex store', () => { expect(commit).toHaveBeenNthCalledWith(8, 'isAdmin', false) }) - it('commits creation', () => { - logout({ commit, state }) - expect(commit).toHaveBeenNthCalledWith(9, 'creation', null) - }) - it('commits hideAmountGDD', () => { logout({ commit, state }) - expect(commit).toHaveBeenNthCalledWith(10, 'hideAmountGDD', false) + expect(commit).toHaveBeenNthCalledWith(9, 'hideAmountGDD', false) }) it('commits hideAmountGDT', () => { logout({ commit, state }) - expect(commit).toHaveBeenNthCalledWith(11, 'hideAmountGDT', true) + expect(commit).toHaveBeenNthCalledWith(10, 'hideAmountGDT', true) }) // how to get this working? it.skip('calls localStorage.clear()', () => { From 3a63e2721dc2e28d4ddf1d893233d7ab46e3cbca Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Wed, 11 Jan 2023 22:32:50 +0100 Subject: [PATCH 62/73] remove creations from graphql user object --- backend/src/graphql/model/User.ts | 16 +--------------- backend/src/graphql/resolver/UserResolver.ts | 8 +++----- 2 files changed, 4 insertions(+), 20 deletions(-) diff --git a/backend/src/graphql/model/User.ts b/backend/src/graphql/model/User.ts index 6e353f6a7..b4fdcae4f 100644 --- a/backend/src/graphql/model/User.ts +++ b/backend/src/graphql/model/User.ts @@ -1,13 +1,11 @@ import { ObjectType, Field } from 'type-graphql' import { KlickTipp } from './KlickTipp' import { User as dbUser } from '@entity/User' -import Decimal from 'decimal.js-light' -import { FULL_CREATION_AVAILABLE } from '../resolver/const/const' import { UserContact } from './UserContact' @ObjectType() export class User { - constructor(user: dbUser, creation: Decimal[] = FULL_CREATION_AVAILABLE) { + constructor(user: dbUser) { this.id = user.id this.gradidoID = user.gradidoID this.alias = user.alias @@ -26,7 +24,6 @@ export class User { this.isAdmin = user.isAdmin this.klickTipp = null this.hasElopage = null - this.creation = creation this.hideAmountGDD = user.hideAmountGDD this.hideAmountGDT = user.hideAmountGDT } @@ -34,9 +31,6 @@ export class User { @Field(() => Number) id: number - // `public_key` binary(32) DEFAULT NULL, - // `privkey` binary(80) DEFAULT NULL, - @Field(() => String) gradidoID: string @@ -62,9 +56,6 @@ export class User { @Field(() => Date, { nullable: true }) deletedAt: Date | null - // `password` bigint(20) unsigned DEFAULT 0, - // `email_hash` binary(32) DEFAULT NULL, - @Field(() => Date) createdAt: Date @@ -84,8 +75,6 @@ export class User { @Field(() => Number, { nullable: true }) publisherId: number | null - // `passphrase` text COLLATE utf8mb4_unicode_ci DEFAULT NULL, - @Field(() => Date, { nullable: true }) isAdmin: Date | null @@ -94,7 +83,4 @@ export class User { @Field(() => Boolean, { nullable: true }) hasElopage: boolean | null - - @Field(() => [Decimal]) - creation: Decimal[] } diff --git a/backend/src/graphql/resolver/UserResolver.ts b/backend/src/graphql/resolver/UserResolver.ts index ed1bf3f47..c630c240a 100644 --- a/backend/src/graphql/resolver/UserResolver.ts +++ b/backend/src/graphql/resolver/UserResolver.ts @@ -58,7 +58,7 @@ import { EventSendConfirmationEmail, EventActivateAccount, } from '@/event/Event' -import { getUserCreation, getUserCreations } from './util/creations' +import { getUserCreations } from './util/creations' import { isValidPassword } from '@/password/EncryptorUtils' import { FULL_CREATION_AVAILABLE } from './const/const' import { encryptPassword, verifyPassword } from '@/password/PasswordEncryptor' @@ -114,9 +114,8 @@ export class UserResolver { async verifyLogin(@Ctx() context: Context): Promise { logger.info('verifyLogin...') // TODO refactor and do not have duplicate code with login(see below) - const clientTimezoneOffset = getClientTimezoneOffset(context) const userEntity = getUser(context) - const user = new User(userEntity, await getUserCreation(userEntity.id, clientTimezoneOffset)) + const user = new User(userEntity) // Elopage Status & Stored PublisherId user.hasElopage = await this.hasElopage(context) @@ -132,7 +131,6 @@ export class UserResolver { @Ctx() context: Context, ): Promise { logger.info(`login with ${email}, ***, ${publisherId} ...`) - const clientTimezoneOffset = getClientTimezoneOffset(context) email = email.trim().toLowerCase() const dbUser = await findUserByEmail(email) if (dbUser.deletedAt) { @@ -163,7 +161,7 @@ export class UserResolver { logger.addContext('user', dbUser.id) logger.debug('validation of login credentials successful...') - const user = new User(dbUser, await getUserCreation(dbUser.id, clientTimezoneOffset)) + const user = new User(dbUser) logger.debug(`user= ${JSON.stringify(user, null, 2)}`) i18n.setLocale(user.language) From b2f9c499dd19b9db5f738bb956acbdf9b14915d4 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Wed, 11 Jan 2023 22:47:55 +0100 Subject: [PATCH 63/73] use try finally to release lock --- .../graphql/resolver/ContributionResolver.ts | 196 +++++++++--------- 1 file changed, 98 insertions(+), 98 deletions(-) diff --git a/backend/src/graphql/resolver/ContributionResolver.ts b/backend/src/graphql/resolver/ContributionResolver.ts index 45b3d2553..3794546e2 100644 --- a/backend/src/graphql/resolver/ContributionResolver.ts +++ b/backend/src/graphql/resolver/ContributionResolver.ts @@ -556,113 +556,113 @@ export class ContributionResolver { // acquire lock const releaseLock = await TRANSACTIONS_LOCK.acquire() - const clientTimezoneOffset = getClientTimezoneOffset(context) - const contribution = await DbContribution.findOne(id) - if (!contribution) { - logger.error(`Contribution not found for given id: ${id}`) - releaseLock() - throw new Error('Contribution not found to given id.') - } - if (contribution.confirmedAt) { - logger.error(`Contribution already confirmd: ${id}`) - releaseLock() - throw new Error('Contribution already confirmd.') - } - const moderatorUser = getUser(context) - if (moderatorUser.id === contribution.userId) { - logger.error('Moderator can not confirm own contribution') - releaseLock() - throw new Error('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.') - releaseLock() - throw new Error('This user was deleted. Cannot confirm a contribution.') - } - const creations = await getUserCreation(contribution.userId, clientTimezoneOffset, false) - validateContribution( - creations, - contribution.amount, - contribution.contributionDate, - clientTimezoneOffset, - ) - - const receivedCallDate = new Date() - const queryRunner = getConnection().createQueryRunner() - await queryRunner.connect() - await queryRunner.startTransaction('REPEATABLE READ') // 'READ COMMITTED') try { - const lastTransaction = await queryRunner.manager - .createQueryBuilder() - .select('transaction') - .from(DbTransaction, 'transaction') - .where('transaction.userId = :id', { id: contribution.userId }) - .orderBy('transaction.id', 'DESC') - .getOne() - logger.info('lastTransaction ID', lastTransaction ? lastTransaction.id : 'undefined') - - let newBalance = new Decimal(0) - let decay: Decay | null = null - if (lastTransaction) { - decay = calculateDecay( - lastTransaction.balance, - lastTransaction.balanceDate, - receivedCallDate, - ) - newBalance = decay.balance + 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.') } - newBalance = newBalance.add(contribution.amount.toString()) + if (contribution.confirmedAt) { + logger.error(`Contribution already confirmd: ${id}`) + throw new Error('Contribution already confirmd.') + } + 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') + } + 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.') + } + const creations = await getUserCreation(contribution.userId, clientTimezoneOffset, false) + validateContribution( + creations, + contribution.amount, + contribution.contributionDate, + clientTimezoneOffset, + ) - const transaction = new DbTransaction() - transaction.typeId = TransactionTypeId.CREATION - transaction.memo = contribution.memo - transaction.userId = contribution.userId - transaction.previous = lastTransaction ? lastTransaction.id : null - transaction.amount = contribution.amount - transaction.creationDate = contribution.contributionDate - transaction.balance = newBalance - transaction.balanceDate = receivedCallDate - transaction.decay = decay ? decay.decay : new Decimal(0) - transaction.decayStart = decay ? decay.start : null - await queryRunner.manager.insert(DbTransaction, transaction) + const receivedCallDate = new Date() + const queryRunner = getConnection().createQueryRunner() + await queryRunner.connect() + await queryRunner.startTransaction('REPEATABLE READ') // 'READ COMMITTED') + try { + const lastTransaction = await queryRunner.manager + .createQueryBuilder() + .select('transaction') + .from(DbTransaction, 'transaction') + .where('transaction.userId = :id', { id: contribution.userId }) + .orderBy('transaction.id', 'DESC') + .getOne() + logger.info('lastTransaction ID', lastTransaction ? lastTransaction.id : 'undefined') - contribution.confirmedAt = receivedCallDate - contribution.confirmedBy = moderatorUser.id - contribution.transactionId = transaction.id - contribution.contributionStatus = ContributionStatus.CONFIRMED - await queryRunner.manager.update(DbContribution, { id: contribution.id }, contribution) + let newBalance = new Decimal(0) + let decay: Decay | null = null + if (lastTransaction) { + decay = calculateDecay( + lastTransaction.balance, + lastTransaction.balanceDate, + receivedCallDate, + ) + newBalance = decay.balance + } + newBalance = newBalance.add(contribution.amount.toString()) - await queryRunner.commitTransaction() - logger.info('creation commited successfuly.') - sendContributionConfirmedEmail({ - firstName: user.firstName, - lastName: user.lastName, - email: user.emailContact.email, - language: user.language, - senderFirstName: moderatorUser.firstName, - senderLastName: moderatorUser.lastName, - contributionMemo: contribution.memo, - contributionAmount: contribution.amount, - }) - } catch (e) { - await queryRunner.rollbackTransaction() - logger.error('Creation was not successful', e) - throw new Error('Creation was not successful.') + const transaction = new DbTransaction() + transaction.typeId = TransactionTypeId.CREATION + transaction.memo = contribution.memo + transaction.userId = contribution.userId + transaction.previous = lastTransaction ? lastTransaction.id : null + transaction.amount = contribution.amount + transaction.creationDate = contribution.contributionDate + transaction.balance = newBalance + transaction.balanceDate = receivedCallDate + transaction.decay = decay ? decay.decay : new Decimal(0) + transaction.decayStart = decay ? decay.start : null + await queryRunner.manager.insert(DbTransaction, transaction) + + contribution.confirmedAt = receivedCallDate + contribution.confirmedBy = moderatorUser.id + contribution.transactionId = transaction.id + contribution.contributionStatus = ContributionStatus.CONFIRMED + await queryRunner.manager.update(DbContribution, { id: contribution.id }, contribution) + + await queryRunner.commitTransaction() + logger.info('creation commited successfuly.') + sendContributionConfirmedEmail({ + firstName: user.firstName, + lastName: user.lastName, + email: user.emailContact.email, + language: user.language, + senderFirstName: moderatorUser.firstName, + senderLastName: moderatorUser.lastName, + contributionMemo: contribution.memo, + contributionAmount: contribution.amount, + }) + } catch (e) { + await queryRunner.rollbackTransaction() + logger.error('Creation was not successful', e) + throw new Error('Creation was not successful.') + } finally { + await queryRunner.release() + } + + const event = new Event() + const eventContributionConfirm = new EventContributionConfirm() + eventContributionConfirm.userId = user.id + eventContributionConfirm.amount = contribution.amount + eventContributionConfirm.contributionId = contribution.id + await eventProtocol.writeEvent(event.setEventContributionConfirm(eventContributionConfirm)) } finally { - await queryRunner.release() releaseLock() } - const event = new Event() - const eventContributionConfirm = new EventContributionConfirm() - eventContributionConfirm.userId = user.id - eventContributionConfirm.amount = contribution.amount - eventContributionConfirm.contributionId = contribution.id - await eventProtocol.writeEvent(event.setEventContributionConfirm(eventContributionConfirm)) return true } From 6497960696fcadee05664fff866f553142ceea55 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Wed, 11 Jan 2023 23:08:48 +0100 Subject: [PATCH 64/73] increase backend coverage requirement to 78% --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 3c486cb20..4cc28bf20 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -527,7 +527,7 @@ jobs: report_name: Coverage Backend type: lcov result_path: ./backend/coverage/lcov.info - min_coverage: 76 + min_coverage: 78 token: ${{ github.token }} ########################################################################## From b64db8158a7ee198ad793903d18d788230bf338b Mon Sep 17 00:00:00 2001 From: ogerly Date: Thu, 12 Jan 2023 10:22:17 +0100 Subject: [PATCH 65/73] go back in the form --- .../components/GddSend/TransactionForm.vue | 202 +++++++++--------- .../GddSend/TransactionResultSendError.vue | 2 +- .../src/components/Inputs/InputAmount.vue | 3 +- frontend/src/components/Inputs/InputEmail.vue | 1 + .../src/components/Inputs/InputTextarea.vue | 2 +- frontend/src/pages/Send.vue | 1 - 6 files changed, 107 insertions(+), 104 deletions(-) diff --git a/frontend/src/components/GddSend/TransactionForm.vue b/frontend/src/components/GddSend/TransactionForm.vue index 607a20afc..6128079a3 100644 --- a/frontend/src/components/GddSend/TransactionForm.vue +++ b/frontend/src/components/GddSend/TransactionForm.vue @@ -1,112 +1,114 @@