From 0d6fb2a427f1c294fe2c7cbca0f6f17180a2d6d5 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Thu, 16 Feb 2023 19:16:33 +0100 Subject: [PATCH 01/26] started event refactoring on database level --- .../entity/0061-event_refactoring/Event.ts | 82 +++++++++++++++++++ database/entity/Event.ts | 1 + database/entity/EventProtocol.ts | 1 - database/entity/index.ts | 8 +- database/migrations/0061-event_refactoring.ts | 33 ++++++++ 5 files changed, 120 insertions(+), 5 deletions(-) create mode 100644 database/entity/0061-event_refactoring/Event.ts create mode 100644 database/entity/Event.ts delete mode 100644 database/entity/EventProtocol.ts create mode 100644 database/migrations/0061-event_refactoring.ts diff --git a/database/entity/0061-event_refactoring/Event.ts b/database/entity/0061-event_refactoring/Event.ts new file mode 100644 index 000000000..62f517aba --- /dev/null +++ b/database/entity/0061-event_refactoring/Event.ts @@ -0,0 +1,82 @@ +import { Contribution } from '@entity/Contribution' +import { ContributionMessage } from '@entity/ContributionMessage' +import { User } from '@entity/User' +import Decimal from 'decimal.js-light' +import { BaseEntity, Entity, PrimaryGeneratedColumn, Column, Transaction } from 'typeorm' +import { DecimalTransformer } from '../../src/typeorm/DecimalTransformer' + +@Entity('event') +// TODO tablename event_protocol +export class Event extends BaseEntity { + @PrimaryGeneratedColumn('increment', { unsigned: true }) + id: number + + @Column({ length: 100, nullable: false, collation: 'utf8mb4_unicode_ci' }) + type: string + + // TODO proper field type + @Column({ name: 'created_at', type: 'datetime', default: () => 'CURRENT_TIMESTAMP' }) + createdAt: Date + + // TODO field name user_id + // @Column({ name: 'affected_user_id', unsigned: true, nullable: false }) + // affectedUserId: number + + @ManyToOne(() => User) + @JoinColumn({ name: 'affected_user_id', referencedColumnName: 'id' }) + affectedUser: User | null + + // TODO new column + // TODO potentially save actingRole aswell + // @Column({ name: 'acting_user_id', unsigned: true, nullable: false }) + // actingUserId: number + + @ManyToOne(() => User) + @JoinColumn({ name: 'acting_user_id', referencedColumnName: 'id' }) + actingUser: User | null + + // TODO rename column x_user_id + // @Column({ name: 'involved_user_id', type: 'int', unsigned: true, nullable: true }) + // involvedUserId: number | null + + @ManyToOne(() => User) + @JoinColumn({ name: 'involved_user_id', referencedColumnName: 'id' }) + involvedUser: User | null + + // TODO drop column xCommunityId + + // TODO rename column transaction_id + // @Column({ name: 'involved_transaction_id', type: 'int', unsigned: true, nullable: true }) + // involvedTransactionId: number | null + + @ManyToOne(() => Transaction) + @JoinColumn({ name: 'involved_transaction_id', referencedColumnName: 'id' }) + involvedTransaction: Transaction | null + + // TODO rename column contribution_id + // @Column({ name: 'involved_contribution_id', type: 'int', unsigned: true, nullable: true }) + // involvedContributionId: number | null + + @ManyToOne(() => Contribution) + @JoinColumn({ name: 'involved_contribution_id', referencedColumnName: 'id' }) + involvedContribution: Contribution | null + + // TODO move column + // TODO rename column message_id + // TEST do we need the Id field definition? + // @Column({ name: 'involved_contribution_message_id', type: 'int', unsigned: true, nullable: true }) + // involvedContributionMessageId: number | null + + @ManyToOne(() => ContributionMessage) + @JoinColumn({ name: 'involved_contribution_message_id', referencedColumnName: 'id' }) + involvedContributionMessage: ContributionMessage | null + + @Column({ + type: 'decimal', + precision: 40, + scale: 20, + nullable: true, + transformer: DecimalTransformer, + }) + amount: Decimal | null +} diff --git a/database/entity/Event.ts b/database/entity/Event.ts new file mode 100644 index 000000000..e53085f2f --- /dev/null +++ b/database/entity/Event.ts @@ -0,0 +1 @@ +export { Event } from './0061-event_refactoring/Event' diff --git a/database/entity/EventProtocol.ts b/database/entity/EventProtocol.ts deleted file mode 100644 index 6ebbd3d68..000000000 --- a/database/entity/EventProtocol.ts +++ /dev/null @@ -1 +0,0 @@ -export { EventProtocol } from './0050-add_messageId_to_event_protocol/EventProtocol' diff --git a/database/entity/index.ts b/database/entity/index.ts index a58afb816..2d9d04c3b 100644 --- a/database/entity/index.ts +++ b/database/entity/index.ts @@ -7,21 +7,21 @@ import { TransactionLink } from './TransactionLink' import { User } from './User' import { UserContact } from './UserContact' import { Contribution } from './Contribution' -import { EventProtocol } from './EventProtocol' +import { Event } from './Event' import { ContributionMessage } from './ContributionMessage' import { Community } from './Community' export const entities = [ + Community, Contribution, ContributionLink, + ContributionMessage, + Event, LoginElopageBuys, LoginEmailOptIn, Migration, Transaction, TransactionLink, User, - EventProtocol, - ContributionMessage, UserContact, - Community, ] diff --git a/database/migrations/0061-event_refactoring.ts b/database/migrations/0061-event_refactoring.ts new file mode 100644 index 000000000..a5ce50595 --- /dev/null +++ b/database/migrations/0061-event_refactoring.ts @@ -0,0 +1,33 @@ +/* MIGRATION TO REFACTOR THE EVENT_PROTOCOL TABLE + * + * This migration refactors the `event_protocol` table. + * It renames the table to `event`, introduces new fields and renames others. + */ + +/* 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 `communities` MODIFY COLUMN `last_announced_at` datetime(3) AFTER `end_point`;', + ) + await queryFn( + 'ALTER TABLE `communities` ADD COLUMN `foreign` tinyint(4) NOT NULL DEFAULT 1 AFTER `id`;', + ) + await queryFn( + 'ALTER TABLE `communities` ADD COLUMN `verified_at` datetime(3) AFTER `last_announced_at`;', + ) + await queryFn( + 'ALTER TABLE `communities` ADD COLUMN `last_error_at` datetime(3) AFTER `verified_at`;', + ) +} + +export async function downgrade(queryFn: (query: string, values?: any[]) => Promise>) { + // write downgrade logic as parameter of queryFn + await queryFn( + 'ALTER TABLE `communities` MODIFY COLUMN `last_announced_at` datetime(3) NOT NULL AFTER `end_point`;', + ) + await queryFn('ALTER TABLE `communities` DROP COLUMN `foreign`;') + await queryFn('ALTER TABLE `communities` DROP COLUMN `verified_at`;') + await queryFn('ALTER TABLE `communities` DROP COLUMN `last_error_at`;') +} From 80a059b94d3cfaf0d33796e36e4f6d4b5b21e1ac Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Fri, 17 Feb 2023 11:49:26 +0100 Subject: [PATCH 02/26] properly import entities --- database/entity/0061-event_refactoring/Event.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/database/entity/0061-event_refactoring/Event.ts b/database/entity/0061-event_refactoring/Event.ts index 62f517aba..ca2ab58da 100644 --- a/database/entity/0061-event_refactoring/Event.ts +++ b/database/entity/0061-event_refactoring/Event.ts @@ -1,6 +1,6 @@ -import { Contribution } from '@entity/Contribution' -import { ContributionMessage } from '@entity/ContributionMessage' -import { User } from '@entity/User' +import { Contribution } from '../Contribution' +import { ContributionMessage } from '../ContributionMessage' +import { User } from '../User' import Decimal from 'decimal.js-light' import { BaseEntity, Entity, PrimaryGeneratedColumn, Column, Transaction } from 'typeorm' import { DecimalTransformer } from '../../src/typeorm/DecimalTransformer' From 6d8b11aeb8f3f15ce627e8a5d8c6bcc193c614f7 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Fri, 17 Feb 2023 14:47:31 +0100 Subject: [PATCH 03/26] finished up Table definition and migration --- .../entity/0061-event_refactoring/Event.ts | 24 +++-------- database/migrations/0061-event_refactoring.ts | 43 ++++++++++++++----- 2 files changed, 39 insertions(+), 28 deletions(-) diff --git a/database/entity/0061-event_refactoring/Event.ts b/database/entity/0061-event_refactoring/Event.ts index ca2ab58da..80b4238bb 100644 --- a/database/entity/0061-event_refactoring/Event.ts +++ b/database/entity/0061-event_refactoring/Event.ts @@ -1,12 +1,12 @@ import { Contribution } from '../Contribution' import { ContributionMessage } from '../ContributionMessage' import { User } from '../User' +import { Transaction } from '../Transaction' import Decimal from 'decimal.js-light' -import { BaseEntity, Entity, PrimaryGeneratedColumn, Column, Transaction } from 'typeorm' +import { BaseEntity, Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, ManyToOne, JoinColumn } from 'typeorm' import { DecimalTransformer } from '../../src/typeorm/DecimalTransformer' -@Entity('event') -// TODO tablename event_protocol +@Entity('events') export class Event extends BaseEntity { @PrimaryGeneratedColumn('increment', { unsigned: true }) id: number @@ -14,28 +14,24 @@ export class Event extends BaseEntity { @Column({ length: 100, nullable: false, collation: 'utf8mb4_unicode_ci' }) type: string - // TODO proper field type - @Column({ name: 'created_at', type: 'datetime', default: () => 'CURRENT_TIMESTAMP' }) + @CreateDateColumn({ name: 'created_at', type: 'datetime', default: () => 'CURRENT_TIMESTAMP()' , nullable: false }) createdAt: Date - // TODO field name user_id // @Column({ name: 'affected_user_id', unsigned: true, nullable: false }) // affectedUserId: number @ManyToOne(() => User) @JoinColumn({ name: 'affected_user_id', referencedColumnName: 'id' }) - affectedUser: User | null + affectedUser: User - // TODO new column - // TODO potentially save actingRole aswell + // TODO potentially save actingRole as well // @Column({ name: 'acting_user_id', unsigned: true, nullable: false }) // actingUserId: number @ManyToOne(() => User) @JoinColumn({ name: 'acting_user_id', referencedColumnName: 'id' }) - actingUser: User | null + actingUser: User - // TODO rename column x_user_id // @Column({ name: 'involved_user_id', type: 'int', unsigned: true, nullable: true }) // involvedUserId: number | null @@ -43,9 +39,6 @@ export class Event extends BaseEntity { @JoinColumn({ name: 'involved_user_id', referencedColumnName: 'id' }) involvedUser: User | null - // TODO drop column xCommunityId - - // TODO rename column transaction_id // @Column({ name: 'involved_transaction_id', type: 'int', unsigned: true, nullable: true }) // involvedTransactionId: number | null @@ -53,7 +46,6 @@ export class Event extends BaseEntity { @JoinColumn({ name: 'involved_transaction_id', referencedColumnName: 'id' }) involvedTransaction: Transaction | null - // TODO rename column contribution_id // @Column({ name: 'involved_contribution_id', type: 'int', unsigned: true, nullable: true }) // involvedContributionId: number | null @@ -61,8 +53,6 @@ export class Event extends BaseEntity { @JoinColumn({ name: 'involved_contribution_id', referencedColumnName: 'id' }) involvedContribution: Contribution | null - // TODO move column - // TODO rename column message_id // TEST do we need the Id field definition? // @Column({ name: 'involved_contribution_message_id', type: 'int', unsigned: true, nullable: true }) // involvedContributionMessageId: number | null diff --git a/database/migrations/0061-event_refactoring.ts b/database/migrations/0061-event_refactoring.ts index a5ce50595..88874b15e 100644 --- a/database/migrations/0061-event_refactoring.ts +++ b/database/migrations/0061-event_refactoring.ts @@ -8,26 +8,47 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ export async function upgrade(queryFn: (query: string, values?: any[]) => Promise>) { + await queryFn('RENAME TABLE `event_protocol` TO `events`;') + await queryFn('ALTER TABLE `events` RENAME COLUMN `user_id` TO `affected_user_id`;') + await queryFn( - 'ALTER TABLE `communities` MODIFY COLUMN `last_announced_at` datetime(3) AFTER `end_point`;', + 'ALTER TABLE `events` ADD COLUMN `acting_user_id` int(10) unsigned DEFAULT NULL AFTER `affected_user_id`;', + ) + await queryFn('UPDATE `events` SET `acting_user_id` = `affected_user_id`;') + await queryFn( + 'ALTER TABLE `events` MODIFY COLUMN `acting_user_id` int(10) unsigned NOT NULL AFTER `affected_user_id`;', + ) + + await queryFn('ALTER TABLE `events` RENAME COLUMN `x_user_id` TO `involved_user_id`;') + await queryFn('ALTER TABLE `events` DROP COLUMN `x_community_id`;') + await queryFn('ALTER TABLE `events` RENAME COLUMN `transaction_id` TO `involved_transaction_id`;') + await queryFn( + 'ALTER TABLE `events` RENAME COLUMN `contribution_id` TO `involved_contribution_id`;', ) await queryFn( - 'ALTER TABLE `communities` ADD COLUMN `foreign` tinyint(4) NOT NULL DEFAULT 1 AFTER `id`;', + 'ALTER TABLE `events` MODIFY COLUMN `message_id` int(10) unsigned DEFAULT NULL AFTER `involved_contribution_id`;', ) await queryFn( - 'ALTER TABLE `communities` ADD COLUMN `verified_at` datetime(3) AFTER `last_announced_at`;', - ) - await queryFn( - 'ALTER TABLE `communities` ADD COLUMN `last_error_at` datetime(3) AFTER `verified_at`;', + 'ALTER TABLE `events` RENAME COLUMN `message_id` TO `involved_contribution_message_id`;', ) } export async function downgrade(queryFn: (query: string, values?: any[]) => Promise>) { - // write downgrade logic as parameter of queryFn await queryFn( - 'ALTER TABLE `communities` MODIFY COLUMN `last_announced_at` datetime(3) NOT NULL AFTER `end_point`;', + 'ALTER TABLE `events` RENAME COLUMN `involved_contribution_message_id` TO `message_id`;', ) - await queryFn('ALTER TABLE `communities` DROP COLUMN `foreign`;') - await queryFn('ALTER TABLE `communities` DROP COLUMN `verified_at`;') - await queryFn('ALTER TABLE `communities` DROP COLUMN `last_error_at`;') + await queryFn( + 'ALTER TABLE `events` MODIFY COLUMN `message_id` int(10) unsigned DEFAULT NULL AFTER `amount`;', + ) + await queryFn( + 'ALTER TABLE `events` RENAME COLUMN `involved_contribution_id` TO `contribution_id`;', + ) + await queryFn('ALTER TABLE `events` RENAME COLUMN `involved_transaction_id` TO `transaction_id`;') + await queryFn( + 'ALTER TABLE `events` ADD COLUMN `x_community_id` int(10) unsigned DEFAULT NULL AFTER `involved_user_id`;', + ) + await queryFn('ALTER TABLE `events` RENAME COLUMN `involved_user_id` TO `x_user_id`;') + await queryFn('ALTER TABLE `events` DROP COLUMN `acting_user_id`;') + await queryFn('ALTER TABLE `events` RENAME COLUMN `affected_user_id` TO `user_id`;') + await queryFn('RENAME TABLE `events` TO `event_protocol`;') } From 5aef000520129810dbf5b2e2964c6e970762ac11 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Fri, 17 Feb 2023 14:53:07 +0100 Subject: [PATCH 04/26] lint fixes --- database/entity/0061-event_refactoring/Event.ts | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/database/entity/0061-event_refactoring/Event.ts b/database/entity/0061-event_refactoring/Event.ts index 80b4238bb..5a62fcdc2 100644 --- a/database/entity/0061-event_refactoring/Event.ts +++ b/database/entity/0061-event_refactoring/Event.ts @@ -3,7 +3,15 @@ import { ContributionMessage } from '../ContributionMessage' import { User } from '../User' import { Transaction } from '../Transaction' import Decimal from 'decimal.js-light' -import { BaseEntity, Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, ManyToOne, JoinColumn } from 'typeorm' +import { + BaseEntity, + Entity, + PrimaryGeneratedColumn, + Column, + CreateDateColumn, + ManyToOne, + JoinColumn, +} from 'typeorm' import { DecimalTransformer } from '../../src/typeorm/DecimalTransformer' @Entity('events') @@ -14,7 +22,12 @@ export class Event extends BaseEntity { @Column({ length: 100, nullable: false, collation: 'utf8mb4_unicode_ci' }) type: string - @CreateDateColumn({ name: 'created_at', type: 'datetime', default: () => 'CURRENT_TIMESTAMP()' , nullable: false }) + @CreateDateColumn({ + name: 'created_at', + type: 'datetime', + default: () => 'CURRENT_TIMESTAMP()', + nullable: false, + }) createdAt: Date // @Column({ name: 'affected_user_id', unsigned: true, nullable: false }) From d8f2843a55c8079e6268981f03b0229af6c24025 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Sat, 18 Feb 2023 00:11:29 +0100 Subject: [PATCH 05/26] fix database version requirement of dht-node & federation --- dht-node/src/config/index.ts | 2 +- federation/src/config/index.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dht-node/src/config/index.ts b/dht-node/src/config/index.ts index 8210ddfcc..6ba9493ac 100644 --- a/dht-node/src/config/index.ts +++ b/dht-node/src/config/index.ts @@ -3,7 +3,7 @@ import dotenv from 'dotenv' dotenv.config() const constants = { - DB_VERSION: '0060-update_communities_table', + DB_VERSION: '0061-event_refactoring', LOG4JS_CONFIG: 'log4js-config.json', // default log level on production should be info LOG_LEVEL: process.env.LOG_LEVEL || 'info', diff --git a/federation/src/config/index.ts b/federation/src/config/index.ts index c8a841315..6b3bf6424 100644 --- a/federation/src/config/index.ts +++ b/federation/src/config/index.ts @@ -11,7 +11,7 @@ Decimal.set({ */ const constants = { - DB_VERSION: '0060-update_communities_table', + DB_VERSION: '0060-0061-event_refactoring', // 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 fde67c2c32b61e4cfaec449f641d331aa6410a3f Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Sat, 18 Feb 2023 00:12:36 +0100 Subject: [PATCH 06/26] todo event data refactoring --- database/migrations/0061-event_refactoring.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/database/migrations/0061-event_refactoring.ts b/database/migrations/0061-event_refactoring.ts index 88874b15e..2fdc7dcef 100644 --- a/database/migrations/0061-event_refactoring.ts +++ b/database/migrations/0061-event_refactoring.ts @@ -31,6 +31,8 @@ export async function upgrade(queryFn: (query: string, values?: any[]) => Promis await queryFn( 'ALTER TABLE `events` RENAME COLUMN `message_id` TO `involved_contribution_message_id`;', ) + + // TODO insert data based on event type } export async function downgrade(queryFn: (query: string, values?: any[]) => Promise>) { From 41569ad0f11b91ff8299dde0a255b0c3af2876b7 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Sat, 18 Feb 2023 01:08:06 +0100 Subject: [PATCH 07/26] refactor events - first step to get backend working --- backend/src/config/index.ts | 2 +- backend/src/event/Event.ts | 192 ++++++++++-------- .../resolver/ContributionResolver.test.ts | 22 +- .../graphql/resolver/ContributionResolver.ts | 31 ++- .../resolver/TransactionResolver.test.ts | 6 +- .../graphql/resolver/TransactionResolver.ts | 13 +- .../src/graphql/resolver/UserResolver.test.ts | 20 +- backend/src/graphql/resolver/UserResolver.ts | 35 +++- 8 files changed, 182 insertions(+), 139 deletions(-) diff --git a/backend/src/config/index.ts b/backend/src/config/index.ts index 27b51b47d..961d83219 100644 --- a/backend/src/config/index.ts +++ b/backend/src/config/index.ts @@ -10,7 +10,7 @@ Decimal.set({ }) const constants = { - DB_VERSION: '0060-update_communities_table', + DB_VERSION: '0061-event_refactoring', 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 diff --git a/backend/src/event/Event.ts b/backend/src/event/Event.ts index 8e65d85f2..5ba21fe19 100644 --- a/backend/src/event/Event.ts +++ b/backend/src/event/Event.ts @@ -1,212 +1,230 @@ -import { EventProtocol as DbEvent } from '@entity/EventProtocol' +import { Event as DbEvent } from '@entity/Event' +import { User as DbUser } from '@entity/User' +import { ContributionMessage as DbContributionMessage } from '@entity/ContributionMessage' +import { Contribution as DbContribution } from '@entity/Contribution' +import { Transaction as DbTransaction } from '@entity/Transaction' import Decimal from 'decimal.js-light' import { EventProtocolType } from './EventProtocolType' export const Event = ( type: EventProtocolType, - userId: number, - xUserId: number | null = null, - xCommunityId: number | null = null, - transactionId: number | null = null, - contributionId: number | null = null, + affectedUser: DbUser, + actingUser: DbUser, + involvedUser: DbUser | null = null, + involvedTransaction: DbTransaction | null = null, + involvedContribution: DbContribution | null = null, + involvedContributionMessage: DbContributionMessage | null = null, amount: Decimal | null = null, - messageId: number | null = null, ): DbEvent => { const event = new DbEvent() event.type = type - event.userId = userId - event.xUserId = xUserId - event.xCommunityId = xCommunityId - event.transactionId = transactionId - event.contributionId = contributionId + event.affectedUser = affectedUser + event.actingUser = actingUser + event.involvedUser = involvedUser + event.involvedTransaction = involvedTransaction + event.involvedContribution = involvedContribution + event.involvedContributionMessage = involvedContributionMessage event.amount = amount - event.messageId = messageId return event } export const EVENT_CONTRIBUTION_CREATE = async ( - userId: number, - contributionId: number, + user: DbUser, + contribution: DbContribution, amount: Decimal, ): Promise => Event( EventProtocolType.CONTRIBUTION_CREATE, - userId, + user, + user, null, null, + contribution, null, - contributionId, amount, ).save() export const EVENT_CONTRIBUTION_DELETE = async ( - userId: number, - contributionId: number, + user: DbUser, + contribution: DbContribution, amount: Decimal, ): Promise => Event( EventProtocolType.CONTRIBUTION_DELETE, - userId, + user, + user, null, null, + contribution, null, - contributionId, amount, ).save() export const EVENT_CONTRIBUTION_UPDATE = async ( - userId: number, - contributionId: number, + user: DbUser, + contribution: DbContribution, amount: Decimal, ): Promise => Event( EventProtocolType.CONTRIBUTION_UPDATE, - userId, + user, + user, null, null, + contribution, null, - contributionId, amount, ).save() +// TODO what was user_id? affected or moderator user? +// await EVENT_ADMIN_CONTRIBUTION_CREATE(moderator.id, contribution.id, amount) export const EVENT_ADMIN_CONTRIBUTION_CREATE = async ( - userId: number, - contributionId: number, + user: DbUser, + moderator: DbUser, + contribution: DbContribution, amount: Decimal, ): Promise => Event( EventProtocolType.ADMIN_CONTRIBUTION_CREATE, - userId, + user, + moderator, null, null, + contribution, null, - contributionId, amount, ).save() +// TODO await EVENT_ADMIN_CONTRIBUTION_UPDATE(emailContact.user.id, contributionToUpdate.id, amount) export const EVENT_ADMIN_CONTRIBUTION_UPDATE = async ( - userId: number, - contributionId: number, + user: DbUser, + moderator: DbUser, + contribution: DbContribution, amount: Decimal, ): Promise => Event( EventProtocolType.ADMIN_CONTRIBUTION_UPDATE, - userId, + user, + moderator, null, null, + contribution, null, - contributionId, amount, ).save() +// TODO await EVENT_ADMIN_CONTRIBUTION_DELETE(contribution.userId, contribution.id, contribution.amount) export const EVENT_ADMIN_CONTRIBUTION_DELETE = async ( - userId: number, - contributionId: number, + user: DbUser, + moderator: DbUser, + contribution: DbContribution, amount: Decimal, ): Promise => Event( EventProtocolType.ADMIN_CONTRIBUTION_DELETE, - userId, + user, + moderator, null, null, + contribution, null, - contributionId, amount, ).save() +// TODO await EVENT_CONTRIBUTION_CONFIRM(user.id, contribution.id, contribution.amount) export const EVENT_CONTRIBUTION_CONFIRM = async ( - userId: number, - contributionId: number, + user: DbUser, + moderator: DbUser, + contribution: DbContribution, amount: Decimal, ): Promise => Event( EventProtocolType.CONTRIBUTION_CONFIRM, - userId, + user, + moderator, null, null, + contribution, null, - contributionId, amount, ).save() +// TODO await EVENT_ADMIN_CONTRIBUTION_DENY( +// contributionToUpdate.userId, +// moderator.id, +// contributionToUpdate.id, +// contributionToUpdate.amount, +// ) +// x User = moderator export const EVENT_ADMIN_CONTRIBUTION_DENY = async ( - userId: number, - xUserId: number, - contributionId: number, + user: DbUser, + moderator: DbUser, + contribution: DbContribution, amount: Decimal, ): Promise => Event( EventProtocolType.ADMIN_CONTRIBUTION_DENY, - userId, - xUserId, + user, + moderator, null, null, - contributionId, + contribution, + null, amount, ).save() export const EVENT_TRANSACTION_SEND = async ( - userId: number, - xUserId: number, - transactionId: number, + user: DbUser, + involvedUser: DbUser, + transaction: DbTransaction, amount: Decimal, ): Promise => Event( EventProtocolType.TRANSACTION_SEND, - userId, - xUserId, + user, + user, + involvedUser, + transaction, null, - transactionId, null, amount, ).save() +// TODO acting user = involved user export const EVENT_TRANSACTION_RECEIVE = async ( - userId: number, - xUserId: number, - transactionId: number, + user: DbUser, + involvedUser: DbUser, + transaction: DbTransaction, amount: Decimal, ): Promise => Event( EventProtocolType.TRANSACTION_RECEIVE, - userId, - xUserId, + user, + involvedUser, + involvedUser, + transaction, null, - transactionId, null, amount, ).save() -export const EVENT_LOGIN = async (userId: number): Promise => - Event(EventProtocolType.LOGIN, userId, null, null, null, null, null, null).save() +export const EVENT_LOGIN = async (user: DbUser): Promise => + Event(EventProtocolType.LOGIN, user, user).save() -export const EVENT_SEND_ACCOUNT_MULTIREGISTRATION_EMAIL = async ( - userId: number, -): Promise => Event(EventProtocolType.SEND_ACCOUNT_MULTIREGISTRATION_EMAIL, userId).save() +export const EVENT_SEND_ACCOUNT_MULTIREGISTRATION_EMAIL = async (user: DbUser): Promise => + Event(EventProtocolType.SEND_ACCOUNT_MULTIREGISTRATION_EMAIL, user, { id: 0 } as DbUser).save() -export const EVENT_SEND_CONFIRMATION_EMAIL = async (userId: number): Promise => - Event(EventProtocolType.SEND_CONFIRMATION_EMAIL, userId).save() +export const EVENT_SEND_CONFIRMATION_EMAIL = async (user: DbUser): Promise => + Event(EventProtocolType.SEND_CONFIRMATION_EMAIL, user, user).save() -export const EVENT_ADMIN_SEND_CONFIRMATION_EMAIL = async (userId: number): Promise => - Event(EventProtocolType.ADMIN_SEND_CONFIRMATION_EMAIL, userId).save() +export const EVENT_ADMIN_SEND_CONFIRMATION_EMAIL = async ( + user: DbUser, + moderator: DbUser, +): Promise => + Event(EventProtocolType.ADMIN_SEND_CONFIRMATION_EMAIL, user, moderator).save() -/* export const EVENT_REDEEM_REGISTER = async ( - userId: number, - transactionId: number | null = null, - contributionId: number | null = null, -): Promise => - Event( - EventProtocolType.REDEEM_REGISTER, - userId, - null, - null, - transactionId, - contributionId, - ).save() -*/ +export const EVENT_REGISTER = async (user: DbUser): Promise => + Event(EventProtocolType.REGISTER, user, user).save() -export const EVENT_REGISTER = async (userId: number): Promise => - Event(EventProtocolType.REGISTER, userId).save() - -export const EVENT_ACTIVATE_ACCOUNT = async (userId: number): Promise => - Event(EventProtocolType.ACTIVATE_ACCOUNT, userId).save() +export const EVENT_ACTIVATE_ACCOUNT = async (user: DbUser): Promise => + Event(EventProtocolType.ACTIVATE_ACCOUNT, user, user).save() diff --git a/backend/src/graphql/resolver/ContributionResolver.test.ts b/backend/src/graphql/resolver/ContributionResolver.test.ts index b56180c45..8f2ae3981 100644 --- a/backend/src/graphql/resolver/ContributionResolver.test.ts +++ b/backend/src/graphql/resolver/ContributionResolver.test.ts @@ -38,7 +38,7 @@ import { userFactory } from '@/seeds/factory/user' import { creationFactory } from '@/seeds/factory/creation' import { creations } from '@/seeds/creation/index' import { peterLustig } from '@/seeds/users/peter-lustig' -import { EventProtocol } from '@entity/EventProtocol' +import { Event as DbEvent } from '@entity/Event' import { Contribution } from '@entity/Contribution' import { Transaction as DbTransaction } from '@entity/Transaction' import { User } from '@entity/User' @@ -284,7 +284,7 @@ describe('ContributionResolver', () => { }) it('stores the CONTRIBUTION_CREATE event in the database', async () => { - await expect(EventProtocol.find()).resolves.toContainEqual( + await expect(DbEvent.find()).resolves.toContainEqual( expect.objectContaining({ type: EventProtocolType.CONTRIBUTION_CREATE, amount: expect.decimalEqual(100), @@ -589,7 +589,7 @@ describe('ContributionResolver', () => { variables: { email: 'bibi@bloxberg.de', password: 'Aa12345_' }, }) - await expect(EventProtocol.find()).resolves.toContainEqual( + await expect(DbEvent.find()).resolves.toContainEqual( expect.objectContaining({ type: EventProtocolType.CONTRIBUTION_UPDATE, amount: expect.decimalEqual(10), @@ -819,7 +819,7 @@ describe('ContributionResolver', () => { }) it('stores the ADMIN_CONTRIBUTION_DENY event in the database', async () => { - await expect(EventProtocol.find()).resolves.toContainEqual( + await expect(DbEvent.find()).resolves.toContainEqual( expect.objectContaining({ type: EventProtocolType.ADMIN_CONTRIBUTION_DENY, userId: bibi.id, @@ -934,7 +934,7 @@ describe('ContributionResolver', () => { }) it('stores the CONTRIBUTION_DELETE event in the database', async () => { - await expect(EventProtocol.find()).resolves.toContainEqual( + await expect(DbEvent.find()).resolves.toContainEqual( expect.objectContaining({ type: EventProtocolType.CONTRIBUTION_DELETE, contributionId: contributionToDelete.data.createContribution.id, @@ -2082,7 +2082,7 @@ describe('ContributionResolver', () => { }) it('stores the ADMIN_CONTRIBUTION_CREATE event in the database', async () => { - await expect(EventProtocol.find()).resolves.toContainEqual( + await expect(DbEvent.find()).resolves.toContainEqual( expect.objectContaining({ type: EventProtocolType.ADMIN_CONTRIBUTION_CREATE, userId: admin.id, @@ -2353,7 +2353,7 @@ describe('ContributionResolver', () => { }) it('stores the ADMIN_CONTRIBUTION_UPDATE event in the database', async () => { - await expect(EventProtocol.find()).resolves.toContainEqual( + await expect(DbEvent.find()).resolves.toContainEqual( expect.objectContaining({ type: EventProtocolType.ADMIN_CONTRIBUTION_UPDATE, userId: admin.id, @@ -2394,7 +2394,7 @@ describe('ContributionResolver', () => { }) it('stores the ADMIN_CONTRIBUTION_UPDATE event in the database', async () => { - await expect(EventProtocol.find()).resolves.toContainEqual( + await expect(DbEvent.find()).resolves.toContainEqual( expect.objectContaining({ type: EventProtocolType.ADMIN_CONTRIBUTION_UPDATE, userId: admin.id, @@ -2573,7 +2573,7 @@ describe('ContributionResolver', () => { }) it('stores the ADMIN_CONTRIBUTION_DELETE event in the database', async () => { - await expect(EventProtocol.find()).resolves.toContainEqual( + await expect(DbEvent.find()).resolves.toContainEqual( expect.objectContaining({ type: EventProtocolType.ADMIN_CONTRIBUTION_DELETE, userId: admin.id, @@ -2717,7 +2717,7 @@ describe('ContributionResolver', () => { }) it('stores the CONTRIBUTION_CONFIRM event in the database', async () => { - await expect(EventProtocol.find()).resolves.toContainEqual( + await expect(DbEvent.find()).resolves.toContainEqual( expect.objectContaining({ type: EventProtocolType.CONTRIBUTION_CONFIRM, }), @@ -2749,7 +2749,7 @@ describe('ContributionResolver', () => { }) it('stores the SEND_CONFIRMATION_EMAIL event in the database', async () => { - await expect(EventProtocol.find()).resolves.toContainEqual( + await expect(DbEvent.find()).resolves.toContainEqual( expect.objectContaining({ type: EventProtocolType.SEND_CONFIRMATION_EMAIL, }), diff --git a/backend/src/graphql/resolver/ContributionResolver.ts b/backend/src/graphql/resolver/ContributionResolver.ts index c2f0d7d23..145966f47 100644 --- a/backend/src/graphql/resolver/ContributionResolver.ts +++ b/backend/src/graphql/resolver/ContributionResolver.ts @@ -91,7 +91,7 @@ export class ContributionResolver { logger.trace('contribution to save', contribution) await DbContribution.save(contribution) - await EVENT_CONTRIBUTION_CREATE(user.id, contribution.id, amount) + await EVENT_CONTRIBUTION_CREATE(user, contribution, amount) return new UnconfirmedContribution(contribution, user, creations) } @@ -119,7 +119,7 @@ export class ContributionResolver { contribution.deletedAt = new Date() await contribution.save() - await EVENT_CONTRIBUTION_DELETE(user.id, contribution.id, contribution.amount) + await EVENT_CONTRIBUTION_DELETE(user, contribution, contribution.amount) const res = await contribution.softRemove() return !!res @@ -267,7 +267,7 @@ export class ContributionResolver { contributionToUpdate.updatedAt = new Date() DbContribution.save(contributionToUpdate) - await EVENT_CONTRIBUTION_UPDATE(user.id, contributionId, amount) + await EVENT_CONTRIBUTION_UPDATE(user, contributionToUpdate, amount) return new UnconfirmedContribution(contributionToUpdate, user, creations) } @@ -324,7 +324,7 @@ export class ContributionResolver { await DbContribution.save(contribution) - await EVENT_ADMIN_CONTRIBUTION_CREATE(moderator.id, contribution.id, amount) + await EVENT_ADMIN_CONTRIBUTION_CREATE(emailContact.user, moderator, contribution, amount) return getUserCreation(emailContact.userId, clientTimezoneOffset) } @@ -419,7 +419,12 @@ export class ContributionResolver { result.creation = await getUserCreation(emailContact.user.id, clientTimezoneOffset) - await EVENT_ADMIN_CONTRIBUTION_UPDATE(emailContact.user.id, contributionToUpdate.id, amount) + await EVENT_ADMIN_CONTRIBUTION_UPDATE( + emailContact.user, + moderator, + contributionToUpdate, + amount, + ) return result } @@ -490,7 +495,13 @@ export class ContributionResolver { await contribution.save() const res = await contribution.softRemove() - await EVENT_ADMIN_CONTRIBUTION_DELETE(contribution.userId, contribution.id, contribution.amount) + // TODO allow to query the user with relation + await EVENT_ADMIN_CONTRIBUTION_DELETE( + { id: contribution.userId } as DbUser, + moderator, + contribution, + contribution.amount, + ) sendContributionDeletedEmail({ firstName: user.firstName, @@ -603,7 +614,7 @@ export class ContributionResolver { await queryRunner.release() } - await EVENT_CONTRIBUTION_CONFIRM(user.id, contribution.id, contribution.amount) + await EVENT_CONTRIBUTION_CONFIRM(user, moderatorUser, contribution, contribution.amount) } finally { releaseLock() } @@ -694,9 +705,9 @@ export class ContributionResolver { const res = await contributionToUpdate.save() await EVENT_ADMIN_CONTRIBUTION_DENY( - contributionToUpdate.userId, - moderator.id, - contributionToUpdate.id, + user, + moderator, + contributionToUpdate, contributionToUpdate.amount, ) diff --git a/backend/src/graphql/resolver/TransactionResolver.test.ts b/backend/src/graphql/resolver/TransactionResolver.test.ts index 6751aa6ad..fd4f839b6 100644 --- a/backend/src/graphql/resolver/TransactionResolver.test.ts +++ b/backend/src/graphql/resolver/TransactionResolver.test.ts @@ -14,7 +14,7 @@ import { bobBaumeister } from '@/seeds/users/bob-baumeister' import { garrickOllivander } from '@/seeds/users/garrick-ollivander' import { peterLustig } from '@/seeds/users/peter-lustig' import { stephenHawking } from '@/seeds/users/stephen-hawking' -import { EventProtocol } from '@entity/EventProtocol' +import { Event as DbEvent } from '@entity/Event' import { Transaction } from '@entity/Transaction' import { User } from '@entity/User' import { cleanDB, testEnvironment } from '@test/helpers' @@ -337,7 +337,7 @@ describe('send coins', () => { memo: 'unrepeatable memo', }) - expect(EventProtocol.find()).resolves.toContainEqual( + expect(DbEvent.find()).resolves.toContainEqual( expect.objectContaining({ type: EventProtocolType.TRANSACTION_SEND, userId: user[1].id, @@ -354,7 +354,7 @@ describe('send coins', () => { memo: 'unrepeatable memo', }) - expect(EventProtocol.find()).resolves.toContainEqual( + expect(DbEvent.find()).resolves.toContainEqual( expect.objectContaining({ type: EventProtocolType.TRANSACTION_RECEIVE, userId: user[0].id, diff --git a/backend/src/graphql/resolver/TransactionResolver.ts b/backend/src/graphql/resolver/TransactionResolver.ts index 9d5a1d38c..f0527ee61 100644 --- a/backend/src/graphql/resolver/TransactionResolver.ts +++ b/backend/src/graphql/resolver/TransactionResolver.ts @@ -138,16 +138,17 @@ export const executeTransaction = async ( logger.info(`commit Transaction successful...`) await EVENT_TRANSACTION_SEND( - transactionSend.userId, - transactionSend.linkedUserId, - transactionSend.id, + sender, + recipient, + transactionSend, + // TODO why mul -1? transactionSend.amount.mul(-1), ) await EVENT_TRANSACTION_RECEIVE( - transactionReceive.userId, - transactionReceive.linkedUserId, - transactionReceive.id, + recipient, + sender, + transactionReceive, transactionReceive.amount, ) } catch (e) { diff --git a/backend/src/graphql/resolver/UserResolver.test.ts b/backend/src/graphql/resolver/UserResolver.test.ts index 19eb04b34..a2dd08ea4 100644 --- a/backend/src/graphql/resolver/UserResolver.test.ts +++ b/backend/src/graphql/resolver/UserResolver.test.ts @@ -35,7 +35,7 @@ import { transactionLinkFactory } from '@/seeds/factory/transactionLink' import { ContributionLink } from '@model/ContributionLink' import { TransactionLink } from '@entity/TransactionLink' import { EventProtocolType } from '@/event/EventProtocolType' -import { EventProtocol } from '@entity/EventProtocol' +import { Event as DbEvent } from '@entity/Event' import { validate as validateUUID, version as versionUUID } from 'uuid' import { peterLustig } from '@/seeds/users/peter-lustig' import { UserContact } from '@entity/UserContact' @@ -182,7 +182,7 @@ describe('UserResolver', () => { { email: 'peter@lustig.de' }, { relations: ['user'] }, ) - expect(EventProtocol.find()).resolves.toContainEqual( + expect(DbEvent.find()).resolves.toContainEqual( expect.objectContaining({ type: EventProtocolType.REGISTER, userId: userConatct.user.id, @@ -211,7 +211,7 @@ describe('UserResolver', () => { }) it('stores the SEND_CONFIRMATION_EMAIL event in the database', () => { - expect(EventProtocol.find()).resolves.toContainEqual( + expect(DbEvent.find()).resolves.toContainEqual( expect.objectContaining({ type: EventProtocolType.SEND_CONFIRMATION_EMAIL, userId: user[0].id, @@ -256,7 +256,7 @@ describe('UserResolver', () => { { email: 'peter@lustig.de' }, { relations: ['user'] }, ) - expect(EventProtocol.find()).resolves.toContainEqual( + expect(DbEvent.find()).resolves.toContainEqual( expect.objectContaining({ type: EventProtocolType.SEND_ACCOUNT_MULTIREGISTRATION_EMAIL, userId: userConatct.user.id, @@ -356,7 +356,7 @@ describe('UserResolver', () => { }) it('stores the ACTIVATE_ACCOUNT event in the database', () => { - expect(EventProtocol.find()).resolves.toContainEqual( + expect(DbEvent.find()).resolves.toContainEqual( expect.objectContaining({ type: EventProtocolType.ACTIVATE_ACCOUNT, userId: user[0].id, @@ -365,7 +365,7 @@ describe('UserResolver', () => { }) it('stores the REDEEM_REGISTER event in the database', () => { - expect(EventProtocol.find()).resolves.toContainEqual( + expect(DbEvent.find()).resolves.toContainEqual( expect.objectContaining({ type: EventProtocolType.REDEEM_REGISTER, userId: result.data.createUser.id, @@ -449,7 +449,7 @@ describe('UserResolver', () => { }) it('stores the REDEEM_REGISTER event in the database', async () => { - await expect(EventProtocol.find()).resolves.toContainEqual( + await expect(DbEvent.find()).resolves.toContainEqual( expect.objectContaining({ type: EventProtocolType.REDEEM_REGISTER, userId: newUser.data.createUser.id, @@ -680,7 +680,7 @@ describe('UserResolver', () => { { email: 'bibi@bloxberg.de' }, { relations: ['user'] }, ) - expect(EventProtocol.find()).resolves.toContainEqual( + expect(DbEvent.find()).resolves.toContainEqual( expect.objectContaining({ type: EventProtocolType.LOGIN, userId: userConatct.user.id, @@ -928,7 +928,7 @@ describe('UserResolver', () => { }) it('stores the LOGIN event in the database', () => { - expect(EventProtocol.find()).resolves.toContainEqual( + expect(DbEvent.find()).resolves.toContainEqual( expect.objectContaining({ type: EventProtocolType.LOGIN, userId: user[0].id, @@ -1847,7 +1847,7 @@ describe('UserResolver', () => { { email: 'bibi@bloxberg.de' }, { relations: ['user'] }, ) - expect(EventProtocol.find()).resolves.toContainEqual( + expect(DbEvent.find()).resolves.toContainEqual( expect.objectContaining({ type: EventProtocolType.ADMIN_SEND_CONFIRMATION_EMAIL, userId: userConatct.user.id, diff --git a/backend/src/graphql/resolver/UserResolver.ts b/backend/src/graphql/resolver/UserResolver.ts index f9617b0df..435ca3c82 100644 --- a/backend/src/graphql/resolver/UserResolver.ts +++ b/backend/src/graphql/resolver/UserResolver.ts @@ -16,7 +16,9 @@ import { getConnection, getCustomRepository, IsNull, Not } from '@dbTools/typeor import { User as DbUser } from '@entity/User' import { UserContact as DbUserContact } from '@entity/UserContact' import { TransactionLink as DbTransactionLink } from '@entity/TransactionLink' +import { Transaction as DbTransaction } from '@entity/Transaction' import { ContributionLink as DbContributionLink } from '@entity/ContributionLink' +import { Contribution as DbContribution } from '@entity/Contribution' import { UserRepository } from '@repository/User' import { User } from '@model/User' @@ -178,7 +180,7 @@ export class UserResolver { value: encode(dbUser.gradidoID), }) - await EVENT_LOGIN(user.id) + await EVENT_LOGIN(dbUser) logger.info(`successful Login: ${JSON.stringify(user, null, 2)}`) return user } @@ -248,7 +250,7 @@ export class UserResolver { language: foundUser.language, // use language of the emails owner for sending }) - await EVENT_SEND_ACCOUNT_MULTIREGISTRATION_EMAIL(foundUser.id) + await EVENT_SEND_ACCOUNT_MULTIREGISTRATION_EMAIL(foundUser) logger.info( `sendAccountMultiRegistrationEmail by ${firstName} ${lastName} to ${foundUser.firstName} ${foundUser.lastName} <${email}>`, @@ -266,7 +268,11 @@ export class UserResolver { const gradidoID = await newGradidoID() - const eventRegisterRedeem = Event(EventProtocolType.REDEEM_REGISTER, 0) + const eventRegisterRedeem = Event( + EventProtocolType.REDEEM_REGISTER, + { id: 0 } as DbUser, + { id: 0 } as DbUser, + ) let dbUser = new DbUser() dbUser.gradidoID = gradidoID dbUser.firstName = firstName @@ -283,14 +289,16 @@ export class UserResolver { logger.info('redeemCode found contributionLink=' + contributionLink) if (contributionLink) { dbUser.contributionLinkId = contributionLink.id - eventRegisterRedeem.contributionId = contributionLink.id + // TODO this is so wrong + eventRegisterRedeem.involvedContribution = { id: contributionLink.id } as DbContribution } } else { const transactionLink = await DbTransactionLink.findOne({ code: redeemCode }) logger.info('redeemCode found transactionLink=' + transactionLink) if (transactionLink) { dbUser.referrerId = transactionLink.userId - eventRegisterRedeem.transactionId = transactionLink.id + // TODO this is so wrong + eventRegisterRedeem.involvedTransaction = { id: transactionLink.id } as DbTransaction } } } @@ -329,7 +337,7 @@ export class UserResolver { }) logger.info(`sendAccountActivationEmail of ${firstName}.${lastName} to ${email}`) - await EVENT_SEND_CONFIRMATION_EMAIL(dbUser.id) + await EVENT_SEND_CONFIRMATION_EMAIL(dbUser) if (!emailSent) { logger.debug(`Account confirmation link: ${activationLink}`) @@ -346,10 +354,11 @@ export class UserResolver { logger.info('createUser() successful...') if (redeemCode) { - eventRegisterRedeem.userId = dbUser.id + eventRegisterRedeem.affectedUser = dbUser + eventRegisterRedeem.actingUser = dbUser await eventRegisterRedeem.save() } else { - await EVENT_REGISTER(dbUser.id) + await EVENT_REGISTER(dbUser) } return new User(dbUser) @@ -465,7 +474,7 @@ export class UserResolver { await queryRunner.commitTransaction() logger.info('User and UserContact data written successfully...') - await EVENT_ACTIVATE_ACCOUNT(user.id) + await EVENT_ACTIVATE_ACCOUNT(user) } catch (e) { await queryRunner.rollbackTransaction() throw new LogError('Error on writing User and User Contact data', e) @@ -775,9 +784,13 @@ export class UserResolver { return null } + // TODO this is an admin function - needs refactor @Authorized([RIGHTS.SEND_ACTIVATION_EMAIL]) @Mutation(() => Boolean) - async sendActivationEmail(@Arg('email') email: string): Promise { + async sendActivationEmail( + @Arg('email') email: string, + @Ctx() context: Context, + ): Promise { email = email.trim().toLowerCase() // const user = await dbUser.findOne({ id: emailContact.userId }) const user = await findUserByEmail(email) @@ -802,7 +815,7 @@ export class UserResolver { if (!emailSent) { logger.info(`Account confirmation link: ${activationLink}`) } else { - await EVENT_ADMIN_SEND_CONFIRMATION_EMAIL(user.id) + await EVENT_ADMIN_SEND_CONFIRMATION_EMAIL(user, getUser(context)) } return true From 4e55acebeb0fec2e92a010b109a307e4b26fddd3 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Sat, 18 Feb 2023 01:24:48 +0100 Subject: [PATCH 08/26] have explicit reference id columns due to missing foreign keys --- .../entity/0061-event_refactoring/Event.ts | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/database/entity/0061-event_refactoring/Event.ts b/database/entity/0061-event_refactoring/Event.ts index 5a62fcdc2..219861834 100644 --- a/database/entity/0061-event_refactoring/Event.ts +++ b/database/entity/0061-event_refactoring/Event.ts @@ -30,45 +30,46 @@ export class Event extends BaseEntity { }) createdAt: Date - // @Column({ name: 'affected_user_id', unsigned: true, nullable: false }) - // affectedUserId: number + @Column({ name: 'affected_user_id', unsigned: true, nullable: false }) + affectedUserId: number @ManyToOne(() => User) @JoinColumn({ name: 'affected_user_id', referencedColumnName: 'id' }) affectedUser: User // TODO potentially save actingRole as well - // @Column({ name: 'acting_user_id', unsigned: true, nullable: false }) - // actingUserId: number + @Column({ name: 'acting_user_id', unsigned: true, nullable: false }) + actingUserId: number @ManyToOne(() => User) @JoinColumn({ name: 'acting_user_id', referencedColumnName: 'id' }) actingUser: User - // @Column({ name: 'involved_user_id', type: 'int', unsigned: true, nullable: true }) - // involvedUserId: number | null + @Column({ name: 'involved_user_id', type: 'int', unsigned: true, nullable: true }) + involvedUserId: number | null @ManyToOne(() => User) @JoinColumn({ name: 'involved_user_id', referencedColumnName: 'id' }) involvedUser: User | null - // @Column({ name: 'involved_transaction_id', type: 'int', unsigned: true, nullable: true }) - // involvedTransactionId: number | null + @Column({ name: 'involved_transaction_id', type: 'int', unsigned: true, nullable: true }) + involvedTransactionId: number | null @ManyToOne(() => Transaction) @JoinColumn({ name: 'involved_transaction_id', referencedColumnName: 'id' }) involvedTransaction: Transaction | null - // @Column({ name: 'involved_contribution_id', type: 'int', unsigned: true, nullable: true }) - // involvedContributionId: number | null + @Column({ name: 'involved_contribution_id', type: 'int', unsigned: true, nullable: true }) + involvedContributionId: number | null @ManyToOne(() => Contribution) @JoinColumn({ name: 'involved_contribution_id', referencedColumnName: 'id' }) involvedContribution: Contribution | null // TEST do we need the Id field definition? - // @Column({ name: 'involved_contribution_message_id', type: 'int', unsigned: true, nullable: true }) - // involvedContributionMessageId: number | null + // TODO we need proper foreign keys to have things working without the explicit column + @Column({ name: 'involved_contribution_message_id', type: 'int', unsigned: true, nullable: true }) + involvedContributionMessageId: number | null @ManyToOne(() => ContributionMessage) @JoinColumn({ name: 'involved_contribution_message_id', referencedColumnName: 'id' }) From e73c26a1cd045a28c55c9954e63e8346dcc4b983 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Sat, 18 Feb 2023 01:31:29 +0100 Subject: [PATCH 09/26] fix transactionResolver tests --- .../graphql/resolver/TransactionResolver.test.ts | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/backend/src/graphql/resolver/TransactionResolver.test.ts b/backend/src/graphql/resolver/TransactionResolver.test.ts index fd4f839b6..6ddbb8191 100644 --- a/backend/src/graphql/resolver/TransactionResolver.test.ts +++ b/backend/src/graphql/resolver/TransactionResolver.test.ts @@ -340,9 +340,10 @@ describe('send coins', () => { expect(DbEvent.find()).resolves.toContainEqual( expect.objectContaining({ type: EventProtocolType.TRANSACTION_SEND, - userId: user[1].id, - transactionId: transaction[0].id, - xUserId: user[0].id, + affectedUserId: user[1].id, + actingUserId: user[1].id, + involvedUserId: user[0].id, + involvedTransactionId: transaction[0].id, }), ) }) @@ -357,9 +358,10 @@ describe('send coins', () => { expect(DbEvent.find()).resolves.toContainEqual( expect.objectContaining({ type: EventProtocolType.TRANSACTION_RECEIVE, - userId: user[0].id, - transactionId: transaction[0].id, - xUserId: user[1].id, + affectedUserId: user[0].id, + actingUserId: user[1].id, + involvedUserId: user[1].id, + involvedTransactionId: transaction[0].id, }), ) }) From 08ad0fb1bbe457a6e97836cfa9ead0d9e746af27 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Sat, 18 Feb 2023 01:43:27 +0100 Subject: [PATCH 10/26] fix userResolver tests --- .../src/graphql/resolver/UserResolver.test.ts | 30 ++++++++++++------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/backend/src/graphql/resolver/UserResolver.test.ts b/backend/src/graphql/resolver/UserResolver.test.ts index a2dd08ea4..e627f4f0f 100644 --- a/backend/src/graphql/resolver/UserResolver.test.ts +++ b/backend/src/graphql/resolver/UserResolver.test.ts @@ -185,7 +185,8 @@ describe('UserResolver', () => { expect(DbEvent.find()).resolves.toContainEqual( expect.objectContaining({ type: EventProtocolType.REGISTER, - userId: userConatct.user.id, + affectedUserId: userConatct.user.id, + actingUserId: userConatct.user.id, }), ) }) @@ -214,7 +215,8 @@ describe('UserResolver', () => { expect(DbEvent.find()).resolves.toContainEqual( expect.objectContaining({ type: EventProtocolType.SEND_CONFIRMATION_EMAIL, - userId: user[0].id, + affectedUserId: user[0].id, + actingUserId: user[0].id, }), ) }) @@ -259,7 +261,8 @@ describe('UserResolver', () => { expect(DbEvent.find()).resolves.toContainEqual( expect.objectContaining({ type: EventProtocolType.SEND_ACCOUNT_MULTIREGISTRATION_EMAIL, - userId: userConatct.user.id, + affectedUserId: userConatct.user.id, + actingUserId: 0, }), ) }) @@ -359,7 +362,8 @@ describe('UserResolver', () => { expect(DbEvent.find()).resolves.toContainEqual( expect.objectContaining({ type: EventProtocolType.ACTIVATE_ACCOUNT, - userId: user[0].id, + affectedUserId: user[0].id, + actingUserId: user[0].id, }), ) }) @@ -368,8 +372,9 @@ describe('UserResolver', () => { expect(DbEvent.find()).resolves.toContainEqual( expect.objectContaining({ type: EventProtocolType.REDEEM_REGISTER, - userId: result.data.createUser.id, - contributionId: link.id, + affectedUserId: result.data.createUser.id, + actingUserId: result.data.createUser.id, + involvedContributionId: link.id, }), ) }) @@ -452,7 +457,9 @@ describe('UserResolver', () => { await expect(DbEvent.find()).resolves.toContainEqual( expect.objectContaining({ type: EventProtocolType.REDEEM_REGISTER, - userId: newUser.data.createUser.id, + affectedUserId: newUser.data.createUser.id, + actingUserId: newUser.data.createUser.id, + involvedTransactionId: transactionLink.id, }), ) }) @@ -683,7 +690,8 @@ describe('UserResolver', () => { expect(DbEvent.find()).resolves.toContainEqual( expect.objectContaining({ type: EventProtocolType.LOGIN, - userId: userConatct.user.id, + affectedUserId: userConatct.user.id, + actingUserId: userConatct.user.id, }), ) }) @@ -931,7 +939,8 @@ describe('UserResolver', () => { expect(DbEvent.find()).resolves.toContainEqual( expect.objectContaining({ type: EventProtocolType.LOGIN, - userId: user[0].id, + affectedUserId: user[0].id, + actingUserId: user[0].id, }), ) }) @@ -1850,7 +1859,8 @@ describe('UserResolver', () => { expect(DbEvent.find()).resolves.toContainEqual( expect.objectContaining({ type: EventProtocolType.ADMIN_SEND_CONFIRMATION_EMAIL, - userId: userConatct.user.id, + affectedUserId: userConatct.user.id, + actingUserId: admin.id, }), ) }) From 8744ff919e21bcdd4757453a71c6db9e23e2af03 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Sat, 18 Feb 2023 02:01:31 +0100 Subject: [PATCH 11/26] fix contributionResolver tests --- .../resolver/ContributionResolver.test.ts | 40 +++++++++++-------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/backend/src/graphql/resolver/ContributionResolver.test.ts b/backend/src/graphql/resolver/ContributionResolver.test.ts index 8f2ae3981..540285c53 100644 --- a/backend/src/graphql/resolver/ContributionResolver.test.ts +++ b/backend/src/graphql/resolver/ContributionResolver.test.ts @@ -287,9 +287,10 @@ describe('ContributionResolver', () => { await expect(DbEvent.find()).resolves.toContainEqual( expect.objectContaining({ type: EventProtocolType.CONTRIBUTION_CREATE, + affectedUserId: bibi.id, + actingUserId: bibi.id, + involvedContributionId: pendingContribution.data.createContribution.id, amount: expect.decimalEqual(100), - contributionId: pendingContribution.data.createContribution.id, - userId: bibi.id, }), ) }) @@ -592,9 +593,10 @@ describe('ContributionResolver', () => { await expect(DbEvent.find()).resolves.toContainEqual( expect.objectContaining({ type: EventProtocolType.CONTRIBUTION_UPDATE, + affectedUserId: bibi.id, + actingUserId: bibi.id, + involvedContributionId: pendingContribution.data.createContribution.id, amount: expect.decimalEqual(10), - contributionId: pendingContribution.data.createContribution.id, - userId: bibi.id, }), ) }) @@ -822,9 +824,9 @@ describe('ContributionResolver', () => { await expect(DbEvent.find()).resolves.toContainEqual( expect.objectContaining({ type: EventProtocolType.ADMIN_CONTRIBUTION_DENY, - userId: bibi.id, - xUserId: admin.id, - contributionId: contributionToDeny.data.createContribution.id, + affectedUserId: bibi.id, + actingUserId: admin.id, + involvedContributionId: contributionToDeny.data.createContribution.id, amount: expect.decimalEqual(100), }), ) @@ -937,9 +939,10 @@ describe('ContributionResolver', () => { await expect(DbEvent.find()).resolves.toContainEqual( expect.objectContaining({ type: EventProtocolType.CONTRIBUTION_DELETE, - contributionId: contributionToDelete.data.createContribution.id, + affectedUserId: bibi.id, + actingUserId: bibi.id, + involvedContributionId: contributionToDelete.data.createContribution.id, amount: expect.decimalEqual(100), - userId: bibi.id, }), ) }) @@ -2085,7 +2088,8 @@ describe('ContributionResolver', () => { await expect(DbEvent.find()).resolves.toContainEqual( expect.objectContaining({ type: EventProtocolType.ADMIN_CONTRIBUTION_CREATE, - userId: admin.id, + affectedUserId: bibi.id, + actingUserId: admin.id, amount: expect.decimalEqual(200), }), ) @@ -2329,7 +2333,7 @@ describe('ContributionResolver', () => { mutate({ mutation: adminUpdateContribution, variables: { - id: creation ? creation.id : -1, + id: creation?.id, email: 'peter@lustig.de', amount: new Decimal(300), memo: 'Danke Peter!', @@ -2356,7 +2360,8 @@ describe('ContributionResolver', () => { await expect(DbEvent.find()).resolves.toContainEqual( expect.objectContaining({ type: EventProtocolType.ADMIN_CONTRIBUTION_UPDATE, - userId: admin.id, + affectedUserId: creation?.userId, + actingUserId: admin.id, amount: 300, }), ) @@ -2370,7 +2375,7 @@ describe('ContributionResolver', () => { mutate({ mutation: adminUpdateContribution, variables: { - id: creation ? creation.id : -1, + id: creation?.id, email: 'peter@lustig.de', amount: new Decimal(200), memo: 'Das war leider zu Viel!', @@ -2397,7 +2402,8 @@ describe('ContributionResolver', () => { await expect(DbEvent.find()).resolves.toContainEqual( expect.objectContaining({ type: EventProtocolType.ADMIN_CONTRIBUTION_UPDATE, - userId: admin.id, + affectedUserId: creation?.userId, + actingUserId: admin.id, amount: expect.decimalEqual(200), }), ) @@ -2562,7 +2568,7 @@ describe('ContributionResolver', () => { mutate({ mutation: adminDeleteContribution, variables: { - id: creation ? creation.id : -1, + id: creation?.id, }, }), ).resolves.toEqual( @@ -2576,7 +2582,9 @@ describe('ContributionResolver', () => { await expect(DbEvent.find()).resolves.toContainEqual( expect.objectContaining({ type: EventProtocolType.ADMIN_CONTRIBUTION_DELETE, - userId: admin.id, + affectedUserId: creation?.userId, + actingUserId: admin.id, + involvedContributionId: creation?.id, amount: expect.decimalEqual(200), }), ) From 89435409aff1da7c498d52cfc07e579e38335fa1 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Sat, 18 Feb 2023 02:11:03 +0100 Subject: [PATCH 12/26] fix typo --- federation/src/config/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/federation/src/config/index.ts b/federation/src/config/index.ts index 6b3bf6424..52c73ef0a 100644 --- a/federation/src/config/index.ts +++ b/federation/src/config/index.ts @@ -11,7 +11,7 @@ Decimal.set({ */ const constants = { - DB_VERSION: '0060-0061-event_refactoring', + DB_VERSION: '0061-event_refactoring', // 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 277df940526684578b2ec0623921ac0f025e6808 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Fri, 3 Mar 2023 23:59:25 +0100 Subject: [PATCH 13/26] remove todo as there is an issue now --- database/entity/0061-event_refactoring/Event.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/database/entity/0061-event_refactoring/Event.ts b/database/entity/0061-event_refactoring/Event.ts index 219861834..0f2afab43 100644 --- a/database/entity/0061-event_refactoring/Event.ts +++ b/database/entity/0061-event_refactoring/Event.ts @@ -37,7 +37,6 @@ export class Event extends BaseEntity { @JoinColumn({ name: 'affected_user_id', referencedColumnName: 'id' }) affectedUser: User - // TODO potentially save actingRole as well @Column({ name: 'acting_user_id', unsigned: true, nullable: false }) actingUserId: number From 76cbcc239393f61a2c9b26129b007cc7b59b07a5 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Sat, 4 Mar 2023 00:02:48 +0100 Subject: [PATCH 14/26] remove todo for foreign keys since there is an issue now --- database/entity/0061-event_refactoring/Event.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/database/entity/0061-event_refactoring/Event.ts b/database/entity/0061-event_refactoring/Event.ts index 0f2afab43..601852ccd 100644 --- a/database/entity/0061-event_refactoring/Event.ts +++ b/database/entity/0061-event_refactoring/Event.ts @@ -65,8 +65,6 @@ export class Event extends BaseEntity { @JoinColumn({ name: 'involved_contribution_id', referencedColumnName: 'id' }) involvedContribution: Contribution | null - // TEST do we need the Id field definition? - // TODO we need proper foreign keys to have things working without the explicit column @Column({ name: 'involved_contribution_message_id', type: 'int', unsigned: true, nullable: true }) involvedContributionMessageId: number | null From 08c379b46f83bdd5dd4e83ed925939b7ae485972 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Sat, 4 Mar 2023 00:30:56 +0100 Subject: [PATCH 15/26] transform event data --- backend/src/event/Event.ts | 13 -------- database/migrations/0061-event_refactoring.ts | 33 ++++++++++++++++++- 2 files changed, 32 insertions(+), 14 deletions(-) diff --git a/backend/src/event/Event.ts b/backend/src/event/Event.ts index 5ba21fe19..7ed75fd45 100644 --- a/backend/src/event/Event.ts +++ b/backend/src/event/Event.ts @@ -76,8 +76,6 @@ export const EVENT_CONTRIBUTION_UPDATE = async ( amount, ).save() -// TODO what was user_id? affected or moderator user? -// await EVENT_ADMIN_CONTRIBUTION_CREATE(moderator.id, contribution.id, amount) export const EVENT_ADMIN_CONTRIBUTION_CREATE = async ( user: DbUser, moderator: DbUser, @@ -95,7 +93,6 @@ export const EVENT_ADMIN_CONTRIBUTION_CREATE = async ( amount, ).save() -// TODO await EVENT_ADMIN_CONTRIBUTION_UPDATE(emailContact.user.id, contributionToUpdate.id, amount) export const EVENT_ADMIN_CONTRIBUTION_UPDATE = async ( user: DbUser, moderator: DbUser, @@ -113,7 +110,6 @@ export const EVENT_ADMIN_CONTRIBUTION_UPDATE = async ( amount, ).save() -// TODO await EVENT_ADMIN_CONTRIBUTION_DELETE(contribution.userId, contribution.id, contribution.amount) export const EVENT_ADMIN_CONTRIBUTION_DELETE = async ( user: DbUser, moderator: DbUser, @@ -131,7 +127,6 @@ export const EVENT_ADMIN_CONTRIBUTION_DELETE = async ( amount, ).save() -// TODO await EVENT_CONTRIBUTION_CONFIRM(user.id, contribution.id, contribution.amount) export const EVENT_CONTRIBUTION_CONFIRM = async ( user: DbUser, moderator: DbUser, @@ -149,13 +144,6 @@ export const EVENT_CONTRIBUTION_CONFIRM = async ( amount, ).save() -// TODO await EVENT_ADMIN_CONTRIBUTION_DENY( -// contributionToUpdate.userId, -// moderator.id, -// contributionToUpdate.id, -// contributionToUpdate.amount, -// ) -// x User = moderator export const EVENT_ADMIN_CONTRIBUTION_DENY = async ( user: DbUser, moderator: DbUser, @@ -190,7 +178,6 @@ export const EVENT_TRANSACTION_SEND = async ( amount, ).save() -// TODO acting user = involved user export const EVENT_TRANSACTION_RECEIVE = async ( user: DbUser, involvedUser: DbUser, diff --git a/database/migrations/0061-event_refactoring.ts b/database/migrations/0061-event_refactoring.ts index 2fdc7dcef..54fc2f702 100644 --- a/database/migrations/0061-event_refactoring.ts +++ b/database/migrations/0061-event_refactoring.ts @@ -32,10 +32,41 @@ export async function upgrade(queryFn: (query: string, values?: any[]) => Promis 'ALTER TABLE `events` RENAME COLUMN `message_id` TO `involved_contribution_message_id`;', ) - // TODO insert data based on event type + // TODO this is untested + // TODO transform back? + await queryFn( + 'UPDATE `events` LEFT JOIN `contributions` ON events.involved_contribution_id = contributions.id SET affected_user_id=contributions.user_id WHERE type = "ADMIN_CONTRIBUTION_CREATE";', + ) + + // inconsistent data on this type + await queryFn( + 'UPDATE `events` LEFT JOIN `contributions` ON events.involved_contribution_id = contributions.id SET acting_user_id=0 WHERE type = "ADMIN_CONTRIBUTION_UPDATE";', + ) + + await queryFn( + 'UPDATE `events` LEFT JOIN `contributions` ON events.involved_contribution_id = contributions.id SET acting_user_id=contributions.deleted_by WHERE type = "ADMIN_CONTRIBUTION_DELETE";', + ) + + await queryFn( + 'UPDATE `events` LEFT JOIN `contributions` ON events.involved_contribution_id = contributions.id SET acting_user_id=contributions.confirmed_by WHERE type = "CONTRIBUTION_CONFIRM";', + ) + + await queryFn( + 'UPDATE `events` LEFT JOIN `contributions` ON events.involved_contribution_id = contributions.id SET involved_user_id=NULL, acting_user_id=contributions.denied_by WHERE type = "ADMIN_CONTRIBUTION_DENY";', + ) + + await queryFn( + 'UPDATE `events` SET acting_user_id=involved_user_id WHERE type = "TRANSACTION_RECEIVE";', + ) } export async function downgrade(queryFn: (query: string, values?: any[]) => Promise>) { + await queryFn( + 'UPDATE `events` involved_user_id=acting_user_id WHERE type = "ADMIN_CONTRIBUTION_DENY";', + ) + await queryFn( + 'UPDATE `events` affected_user_id=acting_user_id WHERE type = "ADMIN_CONTRIBUTION_CREATE";', + ) await queryFn( 'ALTER TABLE `events` RENAME COLUMN `involved_contribution_message_id` TO `message_id`;', ) From c0f40f9c73db7e6eb1784bf93bb9acadf1418a42 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Sat, 4 Mar 2023 00:31:33 +0100 Subject: [PATCH 16/26] added comment and removed todo --- database/migrations/0061-event_refactoring.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/database/migrations/0061-event_refactoring.ts b/database/migrations/0061-event_refactoring.ts index 54fc2f702..c72366322 100644 --- a/database/migrations/0061-event_refactoring.ts +++ b/database/migrations/0061-event_refactoring.ts @@ -33,7 +33,7 @@ export async function upgrade(queryFn: (query: string, values?: any[]) => Promis ) // TODO this is untested - // TODO transform back? + // Moderator id was saved in former user_id await queryFn( 'UPDATE `events` LEFT JOIN `contributions` ON events.involved_contribution_id = contributions.id SET affected_user_id=contributions.user_id WHERE type = "ADMIN_CONTRIBUTION_CREATE";', ) From 38f563e29444dc32c33e263569b657e560be8034 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Sat, 4 Mar 2023 00:32:21 +0100 Subject: [PATCH 17/26] refine comment --- database/migrations/0061-event_refactoring.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/database/migrations/0061-event_refactoring.ts b/database/migrations/0061-event_refactoring.ts index c72366322..01d8d1574 100644 --- a/database/migrations/0061-event_refactoring.ts +++ b/database/migrations/0061-event_refactoring.ts @@ -38,7 +38,7 @@ export async function upgrade(queryFn: (query: string, values?: any[]) => Promis 'UPDATE `events` LEFT JOIN `contributions` ON events.involved_contribution_id = contributions.id SET affected_user_id=contributions.user_id WHERE type = "ADMIN_CONTRIBUTION_CREATE";', ) - // inconsistent data on this type + // inconsistent data on this type, since not all data can be reconstructed await queryFn( 'UPDATE `events` LEFT JOIN `contributions` ON events.involved_contribution_id = contributions.id SET acting_user_id=0 WHERE type = "ADMIN_CONTRIBUTION_UPDATE";', ) From 5515088929c0ccb4b3fa08dbd9164a8d8ed755d4 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Sat, 4 Mar 2023 00:38:08 +0100 Subject: [PATCH 18/26] removed obsolete todo --- backend/src/graphql/resolver/ContributionResolver.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/backend/src/graphql/resolver/ContributionResolver.ts b/backend/src/graphql/resolver/ContributionResolver.ts index 3a5c02d2e..1b8d24d2b 100644 --- a/backend/src/graphql/resolver/ContributionResolver.ts +++ b/backend/src/graphql/resolver/ContributionResolver.ts @@ -441,7 +441,6 @@ export class ContributionResolver { await contribution.save() const res = await contribution.softRemove() - // TODO allow to query the user with relation await EVENT_ADMIN_CONTRIBUTION_DELETE( { id: contribution.userId } as DbUser, moderator, From 10392960bfd880da6d68fb335863382507a85ea1 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Sat, 4 Mar 2023 00:43:55 +0100 Subject: [PATCH 19/26] fixed typo --- database/migrations/0061-event_refactoring.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/database/migrations/0061-event_refactoring.ts b/database/migrations/0061-event_refactoring.ts index 01d8d1574..43da6defa 100644 --- a/database/migrations/0061-event_refactoring.ts +++ b/database/migrations/0061-event_refactoring.ts @@ -62,10 +62,10 @@ export async function upgrade(queryFn: (query: string, values?: any[]) => Promis export async function downgrade(queryFn: (query: string, values?: any[]) => Promise>) { await queryFn( - 'UPDATE `events` involved_user_id=acting_user_id WHERE type = "ADMIN_CONTRIBUTION_DENY";', + 'UPDATE `events` SET involved_user_id=acting_user_id WHERE type = "ADMIN_CONTRIBUTION_DENY";', ) await queryFn( - 'UPDATE `events` affected_user_id=acting_user_id WHERE type = "ADMIN_CONTRIBUTION_CREATE";', + 'UPDATE `events` SET affected_user_id=acting_user_id WHERE type = "ADMIN_CONTRIBUTION_CREATE";', ) await queryFn( 'ALTER TABLE `events` RENAME COLUMN `involved_contribution_message_id` TO `message_id`;', From 63dc1b61833c8c3b6e5554b944b4bf854219457f Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Mon, 6 Mar 2023 13:47:45 +0100 Subject: [PATCH 20/26] escape type query --- database/migrations/0061-event_refactoring.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/database/migrations/0061-event_refactoring.ts b/database/migrations/0061-event_refactoring.ts index 43da6defa..3f424ef17 100644 --- a/database/migrations/0061-event_refactoring.ts +++ b/database/migrations/0061-event_refactoring.ts @@ -35,37 +35,37 @@ export async function upgrade(queryFn: (query: string, values?: any[]) => Promis // TODO this is untested // Moderator id was saved in former user_id await queryFn( - 'UPDATE `events` LEFT JOIN `contributions` ON events.involved_contribution_id = contributions.id SET affected_user_id=contributions.user_id WHERE type = "ADMIN_CONTRIBUTION_CREATE";', + 'UPDATE `events` LEFT JOIN `contributions` ON events.involved_contribution_id = contributions.id SET affected_user_id=contributions.user_id WHERE `type` = "ADMIN_CONTRIBUTION_CREATE";', ) // inconsistent data on this type, since not all data can be reconstructed await queryFn( - 'UPDATE `events` LEFT JOIN `contributions` ON events.involved_contribution_id = contributions.id SET acting_user_id=0 WHERE type = "ADMIN_CONTRIBUTION_UPDATE";', + 'UPDATE `events` LEFT JOIN `contributions` ON events.involved_contribution_id = contributions.id SET acting_user_id=0 WHERE `type` = "ADMIN_CONTRIBUTION_UPDATE";', ) await queryFn( - 'UPDATE `events` LEFT JOIN `contributions` ON events.involved_contribution_id = contributions.id SET acting_user_id=contributions.deleted_by WHERE type = "ADMIN_CONTRIBUTION_DELETE";', + 'UPDATE `events` LEFT JOIN `contributions` ON events.involved_contribution_id = contributions.id SET acting_user_id=contributions.deleted_by WHERE `type` = "ADMIN_CONTRIBUTION_DELETE";', ) await queryFn( - 'UPDATE `events` LEFT JOIN `contributions` ON events.involved_contribution_id = contributions.id SET acting_user_id=contributions.confirmed_by WHERE type = "CONTRIBUTION_CONFIRM";', + 'UPDATE `events` LEFT JOIN `contributions` ON events.involved_contribution_id = contributions.id SET acting_user_id=contributions.confirmed_by WHERE `type` = "CONTRIBUTION_CONFIRM";', ) await queryFn( - 'UPDATE `events` LEFT JOIN `contributions` ON events.involved_contribution_id = contributions.id SET involved_user_id=NULL, acting_user_id=contributions.denied_by WHERE type = "ADMIN_CONTRIBUTION_DENY";', + 'UPDATE `events` LEFT JOIN `contributions` ON events.involved_contribution_id = contributions.id SET involved_user_id=NULL, acting_user_id=contributions.denied_by WHERE `type` = "ADMIN_CONTRIBUTION_DENY";', ) await queryFn( - 'UPDATE `events` SET acting_user_id=involved_user_id WHERE type = "TRANSACTION_RECEIVE";', + 'UPDATE `events` SET acting_user_id=involved_user_id WHERE `type` = "TRANSACTION_RECEIVE";', ) } export async function downgrade(queryFn: (query: string, values?: any[]) => Promise>) { await queryFn( - 'UPDATE `events` SET involved_user_id=acting_user_id WHERE type = "ADMIN_CONTRIBUTION_DENY";', + 'UPDATE `events` SET involved_user_id=acting_user_id WHERE `type` = "ADMIN_CONTRIBUTION_DENY";', ) await queryFn( - 'UPDATE `events` SET affected_user_id=acting_user_id WHERE type = "ADMIN_CONTRIBUTION_CREATE";', + 'UPDATE `events` SET affected_user_id=acting_user_id WHERE `type` = "ADMIN_CONTRIBUTION_CREATE";', ) await queryFn( 'ALTER TABLE `events` RENAME COLUMN `involved_contribution_message_id` TO `message_id`;', From 60d7ce451fb4fefac0a99e8ade2e44dfa15740bb Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Mon, 6 Mar 2023 13:54:37 +0100 Subject: [PATCH 21/26] removed todo since this is tested now --- database/migrations/0061-event_refactoring.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/database/migrations/0061-event_refactoring.ts b/database/migrations/0061-event_refactoring.ts index 3f424ef17..11e81f97f 100644 --- a/database/migrations/0061-event_refactoring.ts +++ b/database/migrations/0061-event_refactoring.ts @@ -32,7 +32,6 @@ export async function upgrade(queryFn: (query: string, values?: any[]) => Promis 'ALTER TABLE `events` RENAME COLUMN `message_id` TO `involved_contribution_message_id`;', ) - // TODO this is untested // Moderator id was saved in former user_id await queryFn( 'UPDATE `events` LEFT JOIN `contributions` ON events.involved_contribution_id = contributions.id SET affected_user_id=contributions.user_id WHERE `type` = "ADMIN_CONTRIBUTION_CREATE";', From cbc7a0557d1449886ff371d95d72783af9432d31 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Tue, 7 Mar 2023 12:16:17 +0100 Subject: [PATCH 22/26] modify column to datetime(3) --- database/entity/0061-event_refactoring/Event.ts | 2 +- database/migrations/0061-event_refactoring.ts | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/database/entity/0061-event_refactoring/Event.ts b/database/entity/0061-event_refactoring/Event.ts index 601852ccd..ab75c2d94 100644 --- a/database/entity/0061-event_refactoring/Event.ts +++ b/database/entity/0061-event_refactoring/Event.ts @@ -25,7 +25,7 @@ export class Event extends BaseEntity { @CreateDateColumn({ name: 'created_at', type: 'datetime', - default: () => 'CURRENT_TIMESTAMP()', + default: () => 'CURRENT_TIMESTAMP(3)', nullable: false, }) createdAt: Date diff --git a/database/migrations/0061-event_refactoring.ts b/database/migrations/0061-event_refactoring.ts index 11e81f97f..f05f99929 100644 --- a/database/migrations/0061-event_refactoring.ts +++ b/database/migrations/0061-event_refactoring.ts @@ -57,9 +57,16 @@ export async function upgrade(queryFn: (query: string, values?: any[]) => Promis await queryFn( 'UPDATE `events` SET acting_user_id=involved_user_id WHERE `type` = "TRANSACTION_RECEIVE";', ) + + await queryFn( + 'ALTER TABLE `events` MODIFY COLUMN `created_at` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3);', + ) } export async function downgrade(queryFn: (query: string, values?: any[]) => Promise>) { + await queryFn( + 'ALTER TABLE `events` MODIFY COLUMN `created_at` datetime() NOT NULL DEFAULT CURRENT_TIMESTAMP();', + ) await queryFn( 'UPDATE `events` SET involved_user_id=acting_user_id WHERE `type` = "ADMIN_CONTRIBUTION_DENY";', ) From ae792850c335113e1d1d4d36cbc473399935f39f Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Tue, 7 Mar 2023 12:28:13 +0100 Subject: [PATCH 23/26] fix down script --- database/migrations/0061-event_refactoring.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/database/migrations/0061-event_refactoring.ts b/database/migrations/0061-event_refactoring.ts index f05f99929..eec403acc 100644 --- a/database/migrations/0061-event_refactoring.ts +++ b/database/migrations/0061-event_refactoring.ts @@ -65,7 +65,7 @@ export async function upgrade(queryFn: (query: string, values?: any[]) => Promis export async function downgrade(queryFn: (query: string, values?: any[]) => Promise>) { await queryFn( - 'ALTER TABLE `events` MODIFY COLUMN `created_at` datetime() NOT NULL DEFAULT CURRENT_TIMESTAMP();', + 'ALTER TABLE `events` MODIFY COLUMN `created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP();', ) await queryFn( 'UPDATE `events` SET involved_user_id=acting_user_id WHERE `type` = "ADMIN_CONTRIBUTION_DENY";', From bfa8f33ea6787588b9bef41120304b3a91186914 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Tue, 14 Mar 2023 16:08:57 +0100 Subject: [PATCH 24/26] merge conflict --- backend/src/graphql/resolver/TransactionResolver.test.ts | 4 ++-- backend/src/graphql/resolver/UserResolver.test.ts | 9 ++++----- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/backend/src/graphql/resolver/TransactionResolver.test.ts b/backend/src/graphql/resolver/TransactionResolver.test.ts index 9c20dd47c..6c1b4be7f 100644 --- a/backend/src/graphql/resolver/TransactionResolver.test.ts +++ b/backend/src/graphql/resolver/TransactionResolver.test.ts @@ -341,7 +341,7 @@ describe('send coins', () => { memo: 'unrepeatable memo', }) - expect(DbEvent.find()).resolves.toContainEqual( + await expect(DbEvent.find()).resolves.toContainEqual( expect.objectContaining({ type: EventProtocolType.TRANSACTION_SEND, affectedUserId: user[1].id, @@ -359,7 +359,7 @@ describe('send coins', () => { memo: 'unrepeatable memo', }) - expect(DbEvent.find()).resolves.toContainEqual( + await expect(DbEvent.find()).resolves.toContainEqual( expect.objectContaining({ type: EventProtocolType.TRANSACTION_RECEIVE, affectedUserId: user[0].id, diff --git a/backend/src/graphql/resolver/UserResolver.test.ts b/backend/src/graphql/resolver/UserResolver.test.ts index d2ac15085..b91ed8709 100644 --- a/backend/src/graphql/resolver/UserResolver.test.ts +++ b/backend/src/graphql/resolver/UserResolver.test.ts @@ -216,7 +216,7 @@ describe('UserResolver', () => { }) }) - it('stores the SEND_CONFIRMATION_EMAIL event in the database', () => { + it('stores the SEND_CONFIRMATION_EMAIL event in the database', async () => { await expect(DbEvent.find()).resolves.toContainEqual( expect.objectContaining({ type: EventProtocolType.SEND_CONFIRMATION_EMAIL, @@ -363,7 +363,7 @@ describe('UserResolver', () => { ) }) - it('stores the ACTIVATE_ACCOUNT event in the database', () => { + it('stores the ACTIVATE_ACCOUNT event in the database', async () => { await expect(DbEvent.find()).resolves.toContainEqual( expect.objectContaining({ type: EventProtocolType.ACTIVATE_ACCOUNT, @@ -373,7 +373,7 @@ describe('UserResolver', () => { ) }) - it('stores the REDEEM_REGISTER event in the database', () => { + it('stores the REDEEM_REGISTER event in the database', async () => { await expect(DbEvent.find()).resolves.toContainEqual( expect.objectContaining({ type: EventProtocolType.REDEEM_REGISTER, @@ -940,7 +940,7 @@ describe('UserResolver', () => { ) }) - it('stores the LOGIN event in the database', () => { + it('stores the LOGIN event in the database', async () => { await expect(DbEvent.find()).resolves.toContainEqual( expect.objectContaining({ type: EventProtocolType.LOGIN, @@ -1861,7 +1861,6 @@ describe('UserResolver', () => { { email: 'bibi@bloxberg.de' }, { relations: ['user'] }, ) - await expect(DbEvent.find()).resolves.toContainEqual( expect.objectContaining({ type: EventProtocolType.ADMIN_SEND_CONFIRMATION_EMAIL, From e8114e40837aafa62266821ac8c39d5ecc4f7d70 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Tue, 14 Mar 2023 20:04:28 +0100 Subject: [PATCH 25/26] remove mul -1 for congruency --- backend/src/graphql/resolver/TransactionResolver.ts | 3 +-- database/migrations/0061-event_refactoring.ts | 5 +++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/backend/src/graphql/resolver/TransactionResolver.ts b/backend/src/graphql/resolver/TransactionResolver.ts index 3145a999e..c3f4b5d48 100644 --- a/backend/src/graphql/resolver/TransactionResolver.ts +++ b/backend/src/graphql/resolver/TransactionResolver.ts @@ -142,8 +142,7 @@ export const executeTransaction = async ( sender, recipient, transactionSend, - // TODO why mul -1? - transactionSend.amount.mul(-1), + transactionSend.amount, ) await EVENT_TRANSACTION_RECEIVE( diff --git a/database/migrations/0061-event_refactoring.ts b/database/migrations/0061-event_refactoring.ts index eec403acc..019d3272b 100644 --- a/database/migrations/0061-event_refactoring.ts +++ b/database/migrations/0061-event_refactoring.ts @@ -58,6 +58,8 @@ export async function upgrade(queryFn: (query: string, values?: any[]) => Promis 'UPDATE `events` SET acting_user_id=involved_user_id WHERE `type` = "TRANSACTION_RECEIVE";', ) + await queryFn('UPDATE `events` SET amount = amount * -1 WHERE `type` = "TRANSACTION_SEND";') + await queryFn( 'ALTER TABLE `events` MODIFY COLUMN `created_at` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3);', ) @@ -67,6 +69,9 @@ export async function downgrade(queryFn: (query: string, values?: any[]) => Prom await queryFn( 'ALTER TABLE `events` MODIFY COLUMN `created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP();', ) + + await queryFn('UPDATE `events` SET amount = amount * -1 WHERE `type` = "TRANSACTION_SEND";') + await queryFn( 'UPDATE `events` SET involved_user_id=acting_user_id WHERE `type` = "ADMIN_CONTRIBUTION_DENY";', ) From d790e9cfcf1c58ff4d246d93d4b76313e687c66f Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Tue, 14 Mar 2023 20:08:11 +0100 Subject: [PATCH 26/26] lint fix --- backend/src/graphql/resolver/TransactionResolver.ts | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/backend/src/graphql/resolver/TransactionResolver.ts b/backend/src/graphql/resolver/TransactionResolver.ts index c3f4b5d48..5b10c098f 100644 --- a/backend/src/graphql/resolver/TransactionResolver.ts +++ b/backend/src/graphql/resolver/TransactionResolver.ts @@ -138,12 +138,7 @@ export const executeTransaction = async ( await queryRunner.commitTransaction() logger.info(`commit Transaction successful...`) - await EVENT_TRANSACTION_SEND( - sender, - recipient, - transactionSend, - transactionSend.amount, - ) + await EVENT_TRANSACTION_SEND(sender, recipient, transactionSend, transactionSend.amount) await EVENT_TRANSACTION_RECEIVE( recipient,