From 5370218dc9cfa0d291dfb37183580bb6b1d465df Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Fri, 28 Nov 2025 18:58:08 +0100 Subject: [PATCH 01/20] move enums into db which are used for seeding --- .../src/graphql/enum/ContributionCycleType.ts | 24 +------------------ .../src/graphql/enum/ContributionStatus.ts | 9 +------ backend/src/graphql/enum/ContributionType.ts | 7 +----- database/src/enum/ContributionCycleType.ts | 22 +++++++++++++++++ database/src/enum/ContributionStatus.ts | 7 ++++++ database/src/enum/ContributionType.ts | 5 ++++ database/src/enum/TransactionTypeId.ts | 8 +++++++ database/src/enum/index.ts | 6 ++++- 8 files changed, 50 insertions(+), 38 deletions(-) create mode 100644 database/src/enum/ContributionCycleType.ts create mode 100644 database/src/enum/ContributionStatus.ts create mode 100644 database/src/enum/ContributionType.ts create mode 100644 database/src/enum/TransactionTypeId.ts diff --git a/backend/src/graphql/enum/ContributionCycleType.ts b/backend/src/graphql/enum/ContributionCycleType.ts index a3c55aa68..abcb6a477 100644 --- a/backend/src/graphql/enum/ContributionCycleType.ts +++ b/backend/src/graphql/enum/ContributionCycleType.ts @@ -1,27 +1,5 @@ import { registerEnumType } from 'type-graphql' - -// lowercase values are not implemented yet -export enum ContributionCycleType { - ONCE = 'ONCE', - HOUR = 'hour', - TWO_HOURS = 'two_hours', - FOUR_HOURS = 'four_hours', - EIGHT_HOURS = 'eight_hours', - HALF_DAY = 'half_day', - DAILY = 'DAILY', - TWO_DAYS = 'two_days', - THREE_DAYS = 'three_days', - FOUR_DAYS = 'four_days', - FIVE_DAYS = 'five_days', - SIX_DAYS = 'six_days', - WEEK = 'week', - TWO_WEEKS = 'two_weeks', - MONTH = 'month', - TWO_MONTH = 'two_month', - QUARTER = 'quarter', - HALF_YEAR = 'half_year', - YEAR = 'year', -} +import { ContributionCycleType } from 'database' registerEnumType(ContributionCycleType, { name: 'ContributionCycleType', // this one is mandatory diff --git a/backend/src/graphql/enum/ContributionStatus.ts b/backend/src/graphql/enum/ContributionStatus.ts index 67cdf5398..74b1cba47 100644 --- a/backend/src/graphql/enum/ContributionStatus.ts +++ b/backend/src/graphql/enum/ContributionStatus.ts @@ -1,12 +1,5 @@ import { registerEnumType } from 'type-graphql' - -export enum ContributionStatus { - PENDING = 'PENDING', - DELETED = 'DELETED', - IN_PROGRESS = 'IN_PROGRESS', - DENIED = 'DENIED', - CONFIRMED = 'CONFIRMED', -} +import { ContributionStatus } from 'database' registerEnumType(ContributionStatus, { name: 'ContributionStatus', diff --git a/backend/src/graphql/enum/ContributionType.ts b/backend/src/graphql/enum/ContributionType.ts index e8529edc4..3be0b7595 100644 --- a/backend/src/graphql/enum/ContributionType.ts +++ b/backend/src/graphql/enum/ContributionType.ts @@ -1,10 +1,5 @@ import { registerEnumType } from 'type-graphql' - -export enum ContributionType { - ADMIN = 'ADMIN', - USER = 'USER', - LINK = 'LINK', -} +import { ContributionType } from 'database' registerEnumType(ContributionType, { name: 'ContributionType', diff --git a/database/src/enum/ContributionCycleType.ts b/database/src/enum/ContributionCycleType.ts new file mode 100644 index 000000000..6974cb563 --- /dev/null +++ b/database/src/enum/ContributionCycleType.ts @@ -0,0 +1,22 @@ +// lowercase values are not implemented yet +export enum ContributionCycleType { + ONCE = 'ONCE', + HOUR = 'hour', + TWO_HOURS = 'two_hours', + FOUR_HOURS = 'four_hours', + EIGHT_HOURS = 'eight_hours', + HALF_DAY = 'half_day', + DAILY = 'DAILY', + TWO_DAYS = 'two_days', + THREE_DAYS = 'three_days', + FOUR_DAYS = 'four_days', + FIVE_DAYS = 'five_days', + SIX_DAYS = 'six_days', + WEEK = 'week', + TWO_WEEKS = 'two_weeks', + MONTH = 'month', + TWO_MONTH = 'two_month', + QUARTER = 'quarter', + HALF_YEAR = 'half_year', + YEAR = 'year', +} diff --git a/database/src/enum/ContributionStatus.ts b/database/src/enum/ContributionStatus.ts new file mode 100644 index 000000000..a4bbc55f3 --- /dev/null +++ b/database/src/enum/ContributionStatus.ts @@ -0,0 +1,7 @@ +export enum ContributionStatus { + PENDING = 'PENDING', + DELETED = 'DELETED', + IN_PROGRESS = 'IN_PROGRESS', + DENIED = 'DENIED', + CONFIRMED = 'CONFIRMED', +} diff --git a/database/src/enum/ContributionType.ts b/database/src/enum/ContributionType.ts new file mode 100644 index 000000000..3cc15c94c --- /dev/null +++ b/database/src/enum/ContributionType.ts @@ -0,0 +1,5 @@ +export enum ContributionType { + ADMIN = 'ADMIN', + USER = 'USER', + LINK = 'LINK', +} diff --git a/database/src/enum/TransactionTypeId.ts b/database/src/enum/TransactionTypeId.ts new file mode 100644 index 000000000..dc5fc25e0 --- /dev/null +++ b/database/src/enum/TransactionTypeId.ts @@ -0,0 +1,8 @@ +export enum TransactionTypeId { + CREATION = 1, + SEND = 2, + RECEIVE = 3, + // This is a virtual property, never occurring on the database + DECAY = 4, + LINK_SUMMARY = 5, +} diff --git a/database/src/enum/index.ts b/database/src/enum/index.ts index c1d445299..ed629db22 100644 --- a/database/src/enum/index.ts +++ b/database/src/enum/index.ts @@ -1 +1,5 @@ -export * from './CommunityHandshakeStateType' \ No newline at end of file +export * from './CommunityHandshakeStateType' +export * from './ContributionType' +export * from './ContributionStatus' +export * from './TransactionTypeId' +export * from './ContributionCycleType' \ No newline at end of file From 933171d2082a28aa08b3e5523464935d111aca11 Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Fri, 28 Nov 2025 18:59:46 +0100 Subject: [PATCH 02/20] move some code from core into shared --- core/src/graphql/enum/TransactionTypeId.ts | 10 +--------- core/src/util/utilities.ts | 3 --- shared/src/index.ts | 1 + shared/src/util/index.ts | 1 + shared/src/util/utilities.ts | 2 ++ 5 files changed, 5 insertions(+), 12 deletions(-) create mode 100644 shared/src/util/index.ts create mode 100644 shared/src/util/utilities.ts diff --git a/core/src/graphql/enum/TransactionTypeId.ts b/core/src/graphql/enum/TransactionTypeId.ts index a7e39eebc..740a93d5b 100644 --- a/core/src/graphql/enum/TransactionTypeId.ts +++ b/core/src/graphql/enum/TransactionTypeId.ts @@ -1,13 +1,5 @@ import { registerEnumType } from 'type-graphql' - -export enum TransactionTypeId { - CREATION = 1, - SEND = 2, - RECEIVE = 3, - // This is a virtual property, never occurring on the database - DECAY = 4, - LINK_SUMMARY = 5, -} +import { TransactionTypeId } from 'database' registerEnumType(TransactionTypeId, { name: 'TransactionTypeId', // this one is mandatory diff --git a/core/src/util/utilities.ts b/core/src/util/utilities.ts index be9e3d898..09fd2f343 100644 --- a/core/src/util/utilities.ts +++ b/core/src/util/utilities.ts @@ -14,9 +14,6 @@ export const decimalSeparatorByLanguage = (a: Decimal, language: string): string return result } -export const fullName = (firstName: string, lastName: string): string => - [firstName, lastName].filter(Boolean).join(' ') - // Function to reset an interface by chatGPT export function resetInterface>(obj: T): T { diff --git a/shared/src/index.ts b/shared/src/index.ts index 1e44e2c48..9eb6655c5 100644 --- a/shared/src/index.ts +++ b/shared/src/index.ts @@ -3,6 +3,7 @@ export * from './enum' export * from './const' export * from './helper' export * from './logic/decay' +export * from './util' export * from './jwt/JWT' export * from './jwt/payloadtypes/AuthenticationJwtPayloadType' export * from './jwt/payloadtypes/AuthenticationResponseJwtPayloadType' diff --git a/shared/src/util/index.ts b/shared/src/util/index.ts new file mode 100644 index 000000000..c2a905916 --- /dev/null +++ b/shared/src/util/index.ts @@ -0,0 +1 @@ +export * from './utilities' \ No newline at end of file diff --git a/shared/src/util/utilities.ts b/shared/src/util/utilities.ts new file mode 100644 index 000000000..7473f5ed0 --- /dev/null +++ b/shared/src/util/utilities.ts @@ -0,0 +1,2 @@ +export const fullName = (firstName: string, lastName: string): string => + [firstName, lastName].filter(Boolean).join(' ') From 2b9068560d75d84d8f1ff84577e9e0f1f17d9335 Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Fri, 28 Nov 2025 19:00:31 +0100 Subject: [PATCH 03/20] move main seed into database --- backend/turbo.json | 6 +----- database/package.json | 1 + database/turbo.json | 4 ++++ 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/backend/turbo.json b/backend/turbo.json index 399bfa6ba..9ba2f9dad 100644 --- a/backend/turbo.json +++ b/backend/turbo.json @@ -1,10 +1,6 @@ { "extends": ["//"], - "tasks": { - "seed": { - "dependsOn": ["database#up", "^build"], - "cache": false - }, + "tasks": { "locales": {}, "locales:fix": {}, "lint": { diff --git a/database/package.json b/database/package.json index b22f9d95f..906e8682e 100644 --- a/database/package.json +++ b/database/package.json @@ -25,6 +25,7 @@ "up": "cross-env TZ=UTC tsx migration/index.ts up", "down": "cross-env TZ=UTC tsx migration/index.ts down", "reset": "cross-env TZ=UTC tsx migration/index.ts reset", + "seed": "cross-env TZ=UTC NODE_ENV=development bun src/seeds/index.ts", "up:test": "cross-env TZ=UTC DB_DATABASE=gradido_test tsx migration/index.ts up", "up:backend_test": "cross-env TZ=UTC DB_DATABASE=gradido_test_backend tsx migration/index.ts up", "up:federation_test": "cross-env TZ=UTC DB_DATABASE=gradido_test_federation tsx migration/index.ts up", diff --git a/database/turbo.json b/database/turbo.json index a40c23229..7017e8542 100644 --- a/database/turbo.json +++ b/database/turbo.json @@ -1,6 +1,10 @@ { "extends": ["//"], "tasks": { + "seed": { + "dependsOn": ["database#up", "^build"], + "cache": false + }, "clear": { "cache": false }, From 25b344f6a6f8dd1ab791c4d33a21742662dab7ae Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Fri, 28 Nov 2025 19:00:52 +0100 Subject: [PATCH 04/20] fix bug with missing use table call --- database/migration/clear.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/database/migration/clear.ts b/database/migration/clear.ts index a78d35890..9c2f5b364 100644 --- a/database/migration/clear.ts +++ b/database/migration/clear.ts @@ -4,6 +4,8 @@ import { connectToDatabaseServer } from './prepare' import { MIGRATIONS_TABLE } from '../src/config/const' export async function truncateTables(connection: Connection) { + const databaseName = CONFIG.DB_DATABASE + await connection.query(`USE \`${databaseName}\``) const [tables] = await connection.query('SHOW TABLES') const tableNames = (tables as any[]).map((table) => Object.values(table)[0]) From c87fc511c92878f4ddc23196b7e58ebe453b3493 Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Fri, 28 Nov 2025 19:01:28 +0100 Subject: [PATCH 05/20] rewrite seed code with direct db usage --- .../ContributionLinkInterface.ts | 7 + database/src/seeds/contributionLink/index.ts | 18 ++ .../src/seeds/creation/CreationInterface.ts | 9 + database/src/seeds/creation/index.ts | 155 ++++++++++++++++++ .../src/seeds/factory/contributionLink.ts | 33 ++++ database/src/seeds/factory/creation.ts | 76 +++++++++ database/src/seeds/factory/transaction.ts | 55 +++++++ database/src/seeds/factory/transactionLink.ts | 59 +++++++ database/src/seeds/factory/user.ts | 8 +- database/src/seeds/index.ts | 106 ++++++++++++ .../TransactionLinkInterface.ts | 10 ++ database/src/seeds/transactionLink/index.ts | 55 +++++++ 12 files changed, 589 insertions(+), 2 deletions(-) create mode 100644 database/src/seeds/contributionLink/ContributionLinkInterface.ts create mode 100644 database/src/seeds/contributionLink/index.ts create mode 100644 database/src/seeds/creation/CreationInterface.ts create mode 100644 database/src/seeds/creation/index.ts create mode 100644 database/src/seeds/factory/contributionLink.ts create mode 100644 database/src/seeds/factory/creation.ts create mode 100644 database/src/seeds/factory/transaction.ts create mode 100644 database/src/seeds/factory/transactionLink.ts create mode 100644 database/src/seeds/index.ts create mode 100644 database/src/seeds/transactionLink/TransactionLinkInterface.ts create mode 100644 database/src/seeds/transactionLink/index.ts diff --git a/database/src/seeds/contributionLink/ContributionLinkInterface.ts b/database/src/seeds/contributionLink/ContributionLinkInterface.ts new file mode 100644 index 000000000..15ba4b72d --- /dev/null +++ b/database/src/seeds/contributionLink/ContributionLinkInterface.ts @@ -0,0 +1,7 @@ +export interface ContributionLinkInterface { + amount: number + name: string + memo: string + validFrom?: Date + validTo?: Date +} diff --git a/database/src/seeds/contributionLink/index.ts b/database/src/seeds/contributionLink/index.ts new file mode 100644 index 000000000..41d28eb60 --- /dev/null +++ b/database/src/seeds/contributionLink/index.ts @@ -0,0 +1,18 @@ +import { ContributionLinkInterface } from './ContributionLinkInterface' + +export const contributionLinks: ContributionLinkInterface[] = [ + { + name: 'Dokumenta 2017', + memo: 'Vielen Dank für deinen Besuch bei der Dokumenta 2017', + amount: 200, + validFrom: new Date(2017, 3, 8), + validTo: new Date(2017, 6, 16), + }, + { + name: 'Dokumenta 2022', + memo: 'Vielen Dank für deinen Besuch bei der Dokumenta 2022', + amount: 200, + validFrom: new Date(2022, 5, 18), + validTo: new Date(2022, 8, 25), + }, +] diff --git a/database/src/seeds/creation/CreationInterface.ts b/database/src/seeds/creation/CreationInterface.ts new file mode 100644 index 000000000..ee450bd93 --- /dev/null +++ b/database/src/seeds/creation/CreationInterface.ts @@ -0,0 +1,9 @@ +export interface CreationInterface { + email: string + amount: number + memo: string + contributionDate: string + confirmed?: boolean + // number of months to move the confirmed creation to the past + moveCreationDate?: number +} diff --git a/database/src/seeds/creation/index.ts b/database/src/seeds/creation/index.ts new file mode 100644 index 000000000..cdb123dcb --- /dev/null +++ b/database/src/seeds/creation/index.ts @@ -0,0 +1,155 @@ +import { nMonthsBefore } from '../factory/creation' + +import { CreationInterface } from './CreationInterface' + +const bobsSendings = [ + { + amount: 10, + memo: 'Herzlich Willkommen bei Gradido!', + }, + { + amount: 10, + memo: 'für deine Hilfe, Betty', + }, + { + amount: 23.37, + memo: 'für deine Hilfe, David', + }, + { + amount: 47, + memo: 'für deine Hilfe, Frau Holle', + }, + { + amount: 1.02, + memo: 'für deine Hilfe, Herr Müller', + }, + { + amount: 5.67, + memo: 'für deine Hilfe, Maier', + }, + { + amount: 72.93, + memo: 'für deine Hilfe, Elsbeth', + }, + { + amount: 5.6, + memo: 'für deine Hilfe, Daniel', + }, + { + amount: 8.87, + memo: 'für deine Hilfe, Yoda', + }, + { + amount: 7.56, + memo: 'für deine Hilfe, Sabine', + }, + { + amount: 7.89, + memo: 'für deine Hilfe, Karl', + }, + { + amount: 8.9, + memo: 'für deine Hilfe, Darth Vader', + }, + { + amount: 56.79, + memo: 'für deine Hilfe, Luci', + }, + { + amount: 3.45, + memo: 'für deine Hilfe, Hanne', + }, + { + amount: 8.74, + memo: 'für deine Hilfe, Luise', + }, + { + amount: 7.85, + memo: 'für deine Hilfe, Annegred', + }, + { + amount: 32.7, + memo: 'für deine Hilfe, Prinz von Zamunda', + }, + { + amount: 44.2, + memo: 'für deine Hilfe, Charly Brown', + }, + { + amount: 38.17, + memo: 'für deine Hilfe, Michael', + }, + { + amount: 5.72, + memo: 'für deine Hilfe, Kaja', + }, + { + amount: 3.99, + memo: 'für deine Hilfe, Maja', + }, + { + amount: 4.5, + memo: 'für deine Hilfe, Martha', + }, + { + amount: 8.3, + memo: 'für deine Hilfe, Ursula', + }, + { + amount: 2.9, + memo: 'für deine Hilfe, Urs', + }, + { + amount: 4.6, + memo: 'für deine Hilfe, Mecedes', + }, + { + amount: 74.1, + memo: 'für deine Hilfe, Heidi', + }, + { + amount: 4.5, + memo: 'für deine Hilfe, Peter', + }, + { + amount: 5.8, + memo: 'für deine Hilfe, Fräulein Rottenmeier', + }, +] +const bobsTransactions: CreationInterface[] = [] +bobsSendings.forEach((sending) => { + bobsTransactions.push({ + email: 'bob@baumeister.de', + amount: sending.amount, + memo: sending.memo, + contributionDate: nMonthsBefore(new Date()), + confirmed: true, + }) +}) + +export const creations: CreationInterface[] = [ + { + email: 'bibi@bloxberg.de', + amount: 1000, + memo: 'Herzlich Willkommen bei Gradido!', + contributionDate: nMonthsBefore(new Date()), + confirmed: true, + moveCreationDate: 12, + }, + { + email: 'bibi@bloxberg.de', + amount: 1000, + memo: '#Hexen', + contributionDate: nMonthsBefore(new Date()), + confirmed: true, + moveCreationDate: 12, + }, + ...bobsTransactions, + { + email: 'raeuber@hotzenplotz.de', + amount: 1000, + memo: 'Herzlich Willkommen bei Gradido!', + contributionDate: nMonthsBefore(new Date()), + confirmed: true, + }, +] diff --git a/database/src/seeds/factory/contributionLink.ts b/database/src/seeds/factory/contributionLink.ts new file mode 100644 index 000000000..031fa9c00 --- /dev/null +++ b/database/src/seeds/factory/contributionLink.ts @@ -0,0 +1,33 @@ +import Decimal from 'decimal.js-light' +import { ContributionLink } from '../../entity' + +import { ContributionLinkInterface } from '../contributionLink/ContributionLinkInterface' +import { transactionLinkCode } from './transactionLink' +import { ContributionCycleType } from '../../enum' + +export const contributionLinkFactory = async ( + contributionLink: ContributionLinkInterface, +): Promise => { + return createContributionLink(contributionLink) +} + +export async function createContributionLink(contributionLinkData: ContributionLinkInterface): Promise { + const contributionLink = new ContributionLink() + contributionLink.amount = new Decimal(contributionLinkData.amount) + contributionLink.name = contributionLinkData.name + contributionLink.memo = contributionLinkData.memo + contributionLink.createdAt = new Date() + contributionLink.code = transactionLinkCode(new Date()) + contributionLink.cycle = ContributionCycleType.ONCE + if (contributionLinkData.validFrom) { + contributionLink.validFrom = contributionLinkData.validFrom + } + if (contributionLinkData.validTo) { + contributionLink.validTo = contributionLinkData.validTo + } + contributionLink.maxAmountPerMonth = new Decimal(200) + contributionLink.maxPerCycle = 1 + + return contributionLink.save() +} + \ No newline at end of file diff --git a/database/src/seeds/factory/creation.ts b/database/src/seeds/factory/creation.ts new file mode 100644 index 000000000..ddf5224de --- /dev/null +++ b/database/src/seeds/factory/creation.ts @@ -0,0 +1,76 @@ +import { Contribution, User } from '../../entity' +import { Decimal } from 'decimal.js-light' +import { CreationInterface } from '../creation/CreationInterface' +import { ContributionType, ContributionStatus, TransactionTypeId } from '../../enum' +import { findUserByIdentifier } from '../../queries' +import { createTransaction } from './transaction' + +export function nMonthsBefore(date: Date, months = 1): string { + return new Date(date.getFullYear(), date.getMonth() - months, 1).toISOString() +} + +export async function creationFactory( + creation: CreationInterface, + user?: User | null, + moderatorUser?: User | null, +): Promise { + if (!user) { + user = await findUserByIdentifier(creation.email) + } + if (!user) { + throw new Error(`User ${creation.email} not found`) + } + let contribution = await createContribution(creation, user) + if (creation.confirmed) { + if (!moderatorUser) { + moderatorUser = await findUserByIdentifier('peter@lustig.de') + } + if (!moderatorUser) { + throw new Error('Moderator user not found') + } + contribution = await confirmTransaction(contribution, moderatorUser) + } + return contribution +} + +export async function createContribution(creation: CreationInterface, user: User, store: boolean = true): Promise { + const contribution = new Contribution() + contribution.user = user + contribution.userId = user.id + contribution.amount = new Decimal(creation.amount) + contribution.createdAt = new Date() + contribution.contributionDate = getContributionDate(creation) + contribution.memo = creation.memo + contribution.contributionType = ContributionType.USER + contribution.contributionStatus = ContributionStatus.PENDING + + return store ? contribution.save() : contribution +} + +export async function confirmTransaction(contribution: Contribution, moderatorUser: User, store: boolean = true): Promise { + const now = new Date() + const transaction = await createTransaction( + contribution.amount, + contribution.memo, + contribution.user, + moderatorUser, + TransactionTypeId.CREATION, + now, + contribution.contributionDate, + true, + ) + contribution.confirmedAt = now + contribution.confirmedBy = moderatorUser.id + contribution.transactionId = transaction.id + contribution.transaction = transaction + contribution.contributionStatus = ContributionStatus.CONFIRMED + + return store ? contribution.save() : contribution +} + +function getContributionDate(creation: CreationInterface): Date { + if (creation.moveCreationDate) { + return new Date(nMonthsBefore(new Date(creation.contributionDate), creation.moveCreationDate)) + } + return new Date(creation.contributionDate) +} \ No newline at end of file diff --git a/database/src/seeds/factory/transaction.ts b/database/src/seeds/factory/transaction.ts new file mode 100644 index 000000000..1782c4f18 --- /dev/null +++ b/database/src/seeds/factory/transaction.ts @@ -0,0 +1,55 @@ +import Decimal from 'decimal.js-light' +import { User, Transaction } from '../../entity' +import { TransactionTypeId } from '../../enum' +import { fullName } from 'shared' +import { getLastTransaction } from '../../queries' +import { calculateDecay, Decay } from 'shared' + +export async function createTransaction( + amount: Decimal, + memo: string, + user: User, + linkedUser: User, + type: TransactionTypeId, + balanceDate: Date, + creationDate?: Date, + store: boolean = true, +): Promise { + + const lastTransaction = await getLastTransaction(user.id) + // balance and decay calculation + let newBalance = new Decimal(0) + let decay: Decay | null = null + if (lastTransaction) { + decay = calculateDecay( + lastTransaction.balance, + lastTransaction.balanceDate, + balanceDate, + ) + newBalance = decay.balance + } + newBalance = newBalance.add(amount.toString()) + + const transaction = new Transaction() + transaction.typeId = type + transaction.memo = memo + transaction.userId = user.id + transaction.userGradidoID = user.gradidoID + transaction.userName = fullName(user.firstName, user.lastName) + transaction.userCommunityUuid = user.communityUuid + transaction.linkedUserId = linkedUser.id + transaction.linkedUserGradidoID = linkedUser.gradidoID + transaction.linkedUserName = fullName(linkedUser.firstName, linkedUser.lastName) + transaction.linkedUserCommunityUuid = linkedUser.communityUuid + transaction.previous = lastTransaction ? lastTransaction.id : null + transaction.amount = amount + if (creationDate) { + transaction.creationDate = creationDate + } + transaction.balance = newBalance + transaction.balanceDate = balanceDate + transaction.decay = decay ? decay.decay : new Decimal(0) + transaction.decayStart = decay ? decay.start : null + + return store ? transaction.save() : transaction +} \ No newline at end of file diff --git a/database/src/seeds/factory/transactionLink.ts b/database/src/seeds/factory/transactionLink.ts new file mode 100644 index 000000000..82155a908 --- /dev/null +++ b/database/src/seeds/factory/transactionLink.ts @@ -0,0 +1,59 @@ +import { TransactionLinkInterface } from '../transactionLink/TransactionLinkInterface' +import { TransactionLink } from '../../entity' +import { Decimal } from 'decimal.js-light' +import { findUserByIdentifier } from '../../queries' +import { compoundInterest } from 'shared' +import { randomBytes } from 'node:crypto' + +export async function transactionLinkFactory( + transactionLinkData: TransactionLinkInterface, + userId?: number, +): Promise { + if (!userId) { + const user = await findUserByIdentifier(transactionLinkData.email) + if (!user) { + throw new Error(`User ${transactionLinkData.email} not found`) + } + userId = user.id + } + return createTransactionLink(transactionLinkData, userId) +} + +export async function createTransactionLink(transactionLinkData: TransactionLinkInterface, userId: number, store: boolean = true): Promise { + const holdAvailableAmount = compoundInterest(new Decimal(transactionLinkData.amount.toString()), CODE_VALID_DAYS_DURATION * 24 * 60 * 60) + let createdAt = transactionLinkData.createdAt || new Date() + const validUntil = transactionLinkExpireDate(createdAt) + + const transactionLink = new TransactionLink() + transactionLink.userId = userId + transactionLink.amount = new Decimal(transactionLinkData.amount) + transactionLink.memo = transactionLinkData.memo + transactionLink.holdAvailableAmount = holdAvailableAmount + transactionLink.code = transactionLinkCode(createdAt) + transactionLink.createdAt = createdAt + transactionLink.validUntil = validUntil + + if (transactionLinkData.deletedAt) { + transactionLink.deletedAt = new Date(createdAt.getTime() + 1000) + } + + return store ? transactionLink.save() : transactionLink +} + +////// Transaction Link BUSINESS LOGIC ////// +// TODO: move business logic to shared +export const CODE_VALID_DAYS_DURATION = 14 + +export const transactionLinkExpireDate = (date: Date): Date => { + const validUntil = new Date(date) + return new Date(validUntil.setDate(date.getDate() + CODE_VALID_DAYS_DURATION)) +} + +export const transactionLinkCode = (date: Date): string => { + const time = date.getTime().toString(16) + return ( + randomBytes(12) + .toString('hex') + .substring(0, 24 - time.length) + time + ) +} \ No newline at end of file diff --git a/database/src/seeds/factory/user.ts b/database/src/seeds/factory/user.ts index 3772fe66d..f4614587c 100644 --- a/database/src/seeds/factory/user.ts +++ b/database/src/seeds/factory/user.ts @@ -4,8 +4,9 @@ import { v4 } from 'uuid' import { UserContactType, OptInType, PasswordEncryptionType } from 'shared' import { getHomeCommunity } from '../../queries/communities' import random from 'crypto-random-bigint' +import { Community } from '../../entity' -export const userFactory = async (user: UserInterface): Promise => { +export async function userFactory(user: UserInterface, homeCommunity?: Community | null): Promise { let dbUserContact = new UserContact() dbUserContact.email = user.email ?? '' @@ -30,7 +31,9 @@ export const userFactory = async (user: UserInterface): Promise => { dbUser.password = random(64) dbUser.passwordEncryptionType = PasswordEncryptionType.GRADIDO_ID } - const homeCommunity = await getHomeCommunity() + if (!homeCommunity) { + homeCommunity = await getHomeCommunity() + } if (homeCommunity) { dbUser.community = homeCommunity dbUser.communityUuid = homeCommunity.communityUuid! @@ -41,5 +44,6 @@ export const userFactory = async (user: UserInterface): Promise => { dbUserContact = await dbUserContact.save() dbUser.emailId = dbUserContact.id dbUser.emailContact = dbUserContact + return dbUser.save() } \ No newline at end of file diff --git a/database/src/seeds/index.ts b/database/src/seeds/index.ts new file mode 100644 index 000000000..c2a659e2f --- /dev/null +++ b/database/src/seeds/index.ts @@ -0,0 +1,106 @@ +import { AppDatabase } from '../AppDatabase' +import { clearDatabase } from '../../migration/clear' +import { createCommunity } from './community' +import { userFactory } from './factory/user' +import { users } from './users' +import { datatype, internet, name } from 'faker' +import { creationFactory } from './factory/creation' +import { creations } from './creation' +import { transactionLinkFactory } from './factory/transactionLink' +import { transactionLinks } from './transactionLink' +import { contributionLinkFactory } from './factory/contributionLink' +import { contributionLinks } from './contributionLink' +import { User } from '../entity' +import { TransactionLink } from '../entity' +import { ContributionLink } from '../entity' + +const RANDOM_USER_COUNT = 100 + +async function run() { + const now = new Date() + // clear database, use mysql2 directly, not AppDatabase + await clearDatabase() + + const db = AppDatabase.getInstance() + await db.init() + + // seed home community + const homeCommunity = await createCommunity(false) + console.info('##seed## seeding home community successful...') + + // seed standard users + // start creation of all users in parallel + // put into map for later direct access + const userCreationIndexedByEmail = new Map>() + for (const user of users) { + userCreationIndexedByEmail.set(user.email!, userFactory(user, homeCommunity)) + } + const defaultUsersPromise = Promise.all(userCreationIndexedByEmail.values()).then(() => { + // log message after all users are created + console.info('##seed## seeding all standard users successful...') + }) + + // seed 100 random users + // start creation of all random users in parallel + const randomUsersCreation: Promise[] = [] + for (let i = 0; i < RANDOM_USER_COUNT; i++) { + randomUsersCreation.push(userFactory({ + firstName: name.firstName(), + lastName: name.lastName(), + email: internet.email(), + language: datatype.boolean() ? 'en' : 'de', + }, homeCommunity)) + } + const randomUsersPromise = Promise.all(randomUsersCreation).then(() => { + // log message after all random users are created + console.info(`##seed## seeding ${RANDOM_USER_COUNT} random users successful...`) + }) + + // create Contribution Links + // start creation of all contribution links in parallel + const contributionLinksPromises: Promise[] = [] + for (const contributionLink of contributionLinks) { + contributionLinksPromises.push(contributionLinkFactory(contributionLink)) + } + const contributionLinksPromise = Promise.all(contributionLinksPromises).then(() => { + // log message after all contribution links are created + console.info('##seed## seeding all contributionLinks successful...') + }) + + // create Transaction Links + // start creation of all transaction links in parallel + const transactionLinksPromises: Promise[] = [] + for (const transactionLink of transactionLinks) { + const user = await userCreationIndexedByEmail.get(transactionLink.email)! + transactionLinksPromises.push(transactionLinkFactory(transactionLink, user.id)) + } + const transactionLinksPromise = Promise.all(transactionLinksPromises).then(() => { + // log message after all transaction links are created + console.info('##seed## seeding all transactionLinks successful...') + }) + + // create GDD serial, must be called one after another because seeding don't use semaphore + const moderatorUser = await userCreationIndexedByEmail.get('peter@lustig.de')! + for (const creation of creations) { + const user = await userCreationIndexedByEmail.get(creation.email)! + await creationFactory(creation, user, moderatorUser) + } + + // wait for all promises to be resolved + await Promise.all([ + defaultUsersPromise, + randomUsersPromise, + contributionLinksPromise, + transactionLinksPromise, + ]) + + await db.destroy() + const timeDiffSeconds = (new Date().getTime() - now.getTime()) / 1000 + console.info(`##seed## seeding successful... after ${timeDiffSeconds} seconds`) +} + +run().catch((err) => { + // biome-ignore lint/suspicious/noConsole: no logger present + console.error('error on seeding', err) +}) + diff --git a/database/src/seeds/transactionLink/TransactionLinkInterface.ts b/database/src/seeds/transactionLink/TransactionLinkInterface.ts new file mode 100644 index 000000000..eaacfdf92 --- /dev/null +++ b/database/src/seeds/transactionLink/TransactionLinkInterface.ts @@ -0,0 +1,10 @@ +export interface TransactionLinkInterface { + email: string + amount: number + memo: string + createdAt?: Date + // TODO: for testing + // redeemedAt?: Date + // redeemedBy?: number + deletedAt?: boolean +} diff --git a/database/src/seeds/transactionLink/index.ts b/database/src/seeds/transactionLink/index.ts new file mode 100644 index 000000000..17683b580 --- /dev/null +++ b/database/src/seeds/transactionLink/index.ts @@ -0,0 +1,55 @@ +import { TransactionLinkInterface } from './TransactionLinkInterface' + +export const transactionLinks: TransactionLinkInterface[] = [ + { + email: 'bibi@bloxberg.de', + amount: 19.99, + memo: 'Leider wollte niemand meine Gradidos haben :(', + }, + { + email: 'bibi@bloxberg.de', + amount: 19.99, + memo: `Kein Trick, keine Zauberrei, +bei Gradidio sei dabei!`, + }, + { + email: 'bibi@bloxberg.de', + amount: 19.99, + memo: `Kein Trick, keine Zauberrei, +bei Gradidio sei dabei!`, + }, + { + email: 'bibi@bloxberg.de', + amount: 19.99, + memo: `Kein Trick, keine Zauberrei, +bei Gradidio sei dabei!`, + }, + { + email: 'bibi@bloxberg.de', + amount: 19.99, + memo: `Kein Trick, keine Zauberrei, +bei Gradidio sei dabei!`, + // TODO: for testing + // memo: `Yeah, eingelöst!`, + // redeemedAt: new Date(2022, 2, 2), + // redeemedBy: not null, + }, + { + email: 'bibi@bloxberg.de', + amount: 19.99, + memo: `Kein Trick, keine Zauberrei, +bei Gradidio sei dabei!`, + }, + { + email: 'bibi@bloxberg.de', + amount: 19.99, + memo: `Kein Trick, keine Zauberrei, +bei Gradidio sei dabei!`, + }, + { + email: 'bibi@bloxberg.de', + amount: 19.99, + memo: 'Da habe ich mich wohl etwas übernommen.', + deletedAt: true, + }, +] From bea80dbae634fb63cbff1d28b141af1e0a5db358 Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Fri, 28 Nov 2025 19:13:22 +0100 Subject: [PATCH 06/20] update imports from moved enums --- .../graphql/arg/SearchContributionsFilterArgs.ts | 2 +- backend/src/graphql/model/Transaction.ts | 4 ++-- .../resolver/ContributionMessageResolver.test.ts | 3 +-- .../graphql/resolver/ContributionResolver.test.ts | 3 +-- .../src/graphql/resolver/ContributionResolver.ts | 9 ++++----- .../graphql/resolver/TransactionLinkResolver.ts | 13 ++++++------- .../src/graphql/resolver/TransactionResolver.ts | 6 ++---- .../graphql/validator/ContributionStatusArray.ts | 2 +- .../AbstractUnconfirmedContribution.role.ts | 3 +-- .../UnconfirmedContributionAdmin.role.ts | 3 +-- .../UnconfirmedContributionAdminAddMessage.role.ts | 3 +-- .../UnconfirmedContributionUser.role.ts | 3 +-- .../UnconfirmedContributionUserAddMessage.role.ts | 3 +-- backend/src/util/virtualTransactions.ts | 3 +-- core/src/graphql/logic/processXComSendCoins.ts | 14 ++++++++++---- 15 files changed, 34 insertions(+), 40 deletions(-) diff --git a/backend/src/graphql/arg/SearchContributionsFilterArgs.ts b/backend/src/graphql/arg/SearchContributionsFilterArgs.ts index ad8b7747e..727940dac 100644 --- a/backend/src/graphql/arg/SearchContributionsFilterArgs.ts +++ b/backend/src/graphql/arg/SearchContributionsFilterArgs.ts @@ -1,7 +1,7 @@ import { IsBoolean, IsPositive, IsString } from 'class-validator' import { ArgsType, Field, InputType, Int } from 'type-graphql' -import { ContributionStatus } from '@enum/ContributionStatus' +import { ContributionStatus } from 'database' import { isContributionStatusArray } from '@/graphql/validator/ContributionStatusArray' diff --git a/backend/src/graphql/model/Transaction.ts b/backend/src/graphql/model/Transaction.ts index 0560cef54..312c67b15 100644 --- a/backend/src/graphql/model/Transaction.ts +++ b/backend/src/graphql/model/Transaction.ts @@ -1,8 +1,8 @@ -import { Transaction as dbTransaction } from 'database' +import { Transaction as dbTransaction, TransactionTypeId } from 'database' import { Decimal } from 'decimal.js-light' import { Field, Int, ObjectType } from 'type-graphql' -import { Decay, TransactionTypeId } from 'core' +import { Decay } from 'core' import { User } from './User' diff --git a/backend/src/graphql/resolver/ContributionMessageResolver.test.ts b/backend/src/graphql/resolver/ContributionMessageResolver.test.ts index 483747b90..673ffae15 100644 --- a/backend/src/graphql/resolver/ContributionMessageResolver.test.ts +++ b/backend/src/graphql/resolver/ContributionMessageResolver.test.ts @@ -1,9 +1,8 @@ import { ApolloServerTestClient } from 'apollo-server-testing' -import { Contribution as DbContribution, Event as DbEvent } from 'database' +import { Contribution as DbContribution, Event as DbEvent, ContributionStatus } from 'database' import { GraphQLError } from 'graphql' import { DataSource } from 'typeorm' -import { ContributionStatus } from '@enum/ContributionStatus' import { cleanDB, resetToken, testEnvironment } from '@test/helpers' import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const' diff --git a/backend/src/graphql/resolver/ContributionResolver.test.ts b/backend/src/graphql/resolver/ContributionResolver.test.ts index 31d405942..98b273763 100644 --- a/backend/src/graphql/resolver/ContributionResolver.test.ts +++ b/backend/src/graphql/resolver/ContributionResolver.test.ts @@ -1,11 +1,10 @@ import { ApolloServerTestClient } from 'apollo-server-testing' -import { Contribution, Event as DbEvent, Transaction as DbTransaction, User } from 'database' +import { Contribution, Event as DbEvent, Transaction as DbTransaction, User, ContributionStatus } from 'database' import { Decimal } from 'decimal.js-light' import { GraphQLError } from 'graphql' import { DataSource, Equal } from 'typeorm' import { ContributionMessageType } from '@enum/ContributionMessageType' -import { ContributionStatus } from '@enum/ContributionStatus' import { Order } from '@enum/Order' import { cleanDB, diff --git a/backend/src/graphql/resolver/ContributionResolver.ts b/backend/src/graphql/resolver/ContributionResolver.ts index 180c22cfb..7c451b5bf 100644 --- a/backend/src/graphql/resolver/ContributionResolver.ts +++ b/backend/src/graphql/resolver/ContributionResolver.ts @@ -1,6 +1,9 @@ import { Contribution as DbContribution, + ContributionStatus, + ContributionType, Transaction as DbTransaction, + TransactionTypeId, User as DbUser, DltTransaction as DbDltTransaction, UserContact, @@ -15,20 +18,16 @@ import { AdminUpdateContributionArgs } from '@arg/AdminUpdateContributionArgs' import { ContributionArgs } from '@arg/ContributionArgs' import { Paginated } from '@arg/Paginated' import { SearchContributionsFilterArgs } from '@arg/SearchContributionsFilterArgs' -import { ContributionStatus } from '@enum/ContributionStatus' -import { ContributionType } from '@enum/ContributionType' import { AdminUpdateContribution } from '@model/AdminUpdateContribution' import { Contribution, ContributionListResult } from '@model/Contribution' import { OpenCreation } from '@model/OpenCreation' import { UnconfirmedContribution } from '@model/UnconfirmedContribution' import { RIGHTS } from '@/auth/RIGHTS' import { - fullName, sendContributionChangedByModeratorEmail, sendContributionConfirmedEmail, sendContributionDeletedEmail, sendContributionDeniedEmail, - TransactionTypeId } from 'core' import { EVENT_ADMIN_CONTRIBUTION_CONFIRM, @@ -44,7 +43,7 @@ import { UpdateUnconfirmedContributionContext } from '@/interactions/updateUncon import { LogError } from '@/server/LogError' import { Context, getClientTimezoneOffset, getUser } from '@/server/context' import { TRANSACTIONS_LOCK } from 'database' -import { calculateDecay, Decay } from 'shared' +import { calculateDecay, Decay, fullName } from 'shared' import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const' import { ContributionMessageType } from '@enum/ContributionMessageType' diff --git a/backend/src/graphql/resolver/TransactionLinkResolver.ts b/backend/src/graphql/resolver/TransactionLinkResolver.ts index 869104bae..b6b8f822f 100644 --- a/backend/src/graphql/resolver/TransactionLinkResolver.ts +++ b/backend/src/graphql/resolver/TransactionLinkResolver.ts @@ -3,23 +3,24 @@ import { randomBytes } from 'crypto' import { Paginated } from '@arg/Paginated' import { TransactionLinkArgs } from '@arg/TransactionLinkArgs' import { TransactionLinkFilters } from '@arg/TransactionLinkFilters' -import { ContributionCycleType } from '@enum/ContributionCycleType' -import { ContributionStatus } from '@enum/ContributionStatus' -import { ContributionType } from '@enum/ContributionType' import { Community } from '@model/Community' import { ContributionLink } from '@model/ContributionLink' import { RedeemJwtLink } from '@model/RedeemJwtLink' import { TransactionLink, TransactionLinkResult } from '@model/TransactionLink' import { User } from '@model/User' import { QueryLinkResult } from '@union/QueryLinkResult' -import { Decay, interpretEncryptedTransferArgs, TransactionTypeId } from 'core' +import { Decay, interpretEncryptedTransferArgs, EncryptedTransferArgs } from 'core' import { AppDatabase, Contribution as DbContribution, + ContributionCycleType, + ContributionStatus, + ContributionType, ContributionLink as DbContributionLink, FederatedCommunity as DbFederatedCommunity, DltTransaction as DbDltTransaction, Transaction as DbTransaction, TransactionLink as DbTransactionLink, + TransactionTypeId, User as DbUser, findModeratorCreatingContributionLink, findTransactionLinkByCode, @@ -38,7 +39,6 @@ import { import { LogError } from '@/server/LogError' import { Context, getClientTimezoneOffset, getUser } from '@/server/context' import { calculateBalance } from '@/util/validate' -import { fullName } from 'core' import { TRANSACTION_LINK_LOCK, TRANSACTIONS_LOCK } from 'database' import { calculateDecay, @@ -53,7 +53,6 @@ import { import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const' import { DisbursementClient as V1_0_DisbursementClient } from '@/federation/client/1_0/DisbursementClient' import { DisbursementClientFactory } from '@/federation/client/DisbursementClientFactory' -import { EncryptedTransferArgs } from 'core' import { getLastTransaction } from 'database' import { getLogger, Logger } from 'log4js' import { randombytes_random } from 'sodium-native' @@ -65,7 +64,7 @@ import { } from './util/communities' import { getUserCreation, validateContribution } from './util/creations' import { transactionLinkList } from './util/transactionLinkList' -import { SignedTransferPayloadType } from 'shared' +import { fullName, SignedTransferPayloadType } from 'shared' import { contributionTransaction, deferredTransferTransaction, redeemDeferredTransferTransaction } from '@/apis/dltConnector' import { CODE_VALID_DAYS_DURATION } from './const/const' diff --git a/backend/src/graphql/resolver/TransactionResolver.ts b/backend/src/graphql/resolver/TransactionResolver.ts index 923971743..c82eabf8b 100644 --- a/backend/src/graphql/resolver/TransactionResolver.ts +++ b/backend/src/graphql/resolver/TransactionResolver.ts @@ -18,11 +18,9 @@ import { Transaction } from '@model/Transaction' import { TransactionList } from '@model/TransactionList' import { User } from '@model/User' import { - fullName, processXComCompleteTransaction, sendTransactionLinkRedeemedEmail, sendTransactionReceivedEmail, - TransactionTypeId } from 'core' import { RIGHTS } from '@/auth/RIGHTS' import { CONFIG } from '@/config' @@ -33,10 +31,10 @@ import { Context, getUser } from '@/server/context' import { communityUser } from '@/util/communityUser' import { calculateBalance } from '@/util/validate' import { virtualDecayTransaction, virtualLinkTransaction } from '@/util/virtualTransactions' -import { TRANSACTIONS_LOCK } from 'database' +import { fullName } from 'shared' import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const' -import { getLastTransaction } from 'database' +import { getLastTransaction, TRANSACTIONS_LOCK, TransactionTypeId } from 'database' import { getLogger, Logger } from 'log4js' import { BalanceResolver } from './BalanceResolver' import { GdtResolver } from './GdtResolver' diff --git a/backend/src/graphql/validator/ContributionStatusArray.ts b/backend/src/graphql/validator/ContributionStatusArray.ts index dd7c93277..65f61ec9e 100644 --- a/backend/src/graphql/validator/ContributionStatusArray.ts +++ b/backend/src/graphql/validator/ContributionStatusArray.ts @@ -1,6 +1,6 @@ import { ValidationOptions, registerDecorator } from 'class-validator' -import { ContributionStatus } from '@enum/ContributionStatus' +import { ContributionStatus } from 'database' export function isContributionStatusArray(validationOptions?: ValidationOptions) { return function (object: Object, propertyName: string) { diff --git a/backend/src/interactions/updateUnconfirmedContribution/AbstractUnconfirmedContribution.role.ts b/backend/src/interactions/updateUnconfirmedContribution/AbstractUnconfirmedContribution.role.ts index dd85e3fb6..0f83821df 100644 --- a/backend/src/interactions/updateUnconfirmedContribution/AbstractUnconfirmedContribution.role.ts +++ b/backend/src/interactions/updateUnconfirmedContribution/AbstractUnconfirmedContribution.role.ts @@ -1,10 +1,9 @@ -import { Contribution, User } from 'database' +import { Contribution, ContributionStatus, User } from 'database' import { Decimal } from 'decimal.js-light' import { Role } from '@/auth/Role' import { ContributionLogic } from '@/data/Contribution.logic' import { ContributionMessageBuilder } from '@/data/ContributionMessage.builder' -import { ContributionStatus } from '@/graphql/enum/ContributionStatus' import { LogError } from '@/server/LogError' import { Context, getClientTimezoneOffset } from '@/server/context' import { Logger, getLogger } from 'log4js' diff --git a/backend/src/interactions/updateUnconfirmedContribution/UnconfirmedContributionAdmin.role.ts b/backend/src/interactions/updateUnconfirmedContribution/UnconfirmedContributionAdmin.role.ts index f160966d3..d95edf240 100644 --- a/backend/src/interactions/updateUnconfirmedContribution/UnconfirmedContributionAdmin.role.ts +++ b/backend/src/interactions/updateUnconfirmedContribution/UnconfirmedContributionAdmin.role.ts @@ -1,10 +1,9 @@ -import { Contribution, User } from 'database' +import { Contribution, ContributionStatus, User } from 'database' import { RIGHTS } from '@/auth/RIGHTS' import { Role } from '@/auth/Role' import { ContributionMessageBuilder } from '@/data/ContributionMessage.builder' import { AdminUpdateContributionArgs } from '@/graphql/arg/AdminUpdateContributionArgs' -import { ContributionStatus } from '@/graphql/enum/ContributionStatus' import { LogError } from '@/server/LogError' import { AbstractUnconfirmedContributionRole } from './AbstractUnconfirmedContribution.role' diff --git a/backend/src/interactions/updateUnconfirmedContribution/UnconfirmedContributionAdminAddMessage.role.ts b/backend/src/interactions/updateUnconfirmedContribution/UnconfirmedContributionAdminAddMessage.role.ts index dcc10091f..780b2e401 100644 --- a/backend/src/interactions/updateUnconfirmedContribution/UnconfirmedContributionAdminAddMessage.role.ts +++ b/backend/src/interactions/updateUnconfirmedContribution/UnconfirmedContributionAdminAddMessage.role.ts @@ -1,11 +1,10 @@ -import { Contribution, User } from 'database' +import { Contribution, ContributionStatus, User } from 'database' import { RIGHTS } from '@/auth/RIGHTS' import { Role } from '@/auth/Role' import { ContributionMessageBuilder } from '@/data/ContributionMessage.builder' import { ContributionMessageArgs } from '@/graphql/arg/ContributionMessageArgs' import { ContributionMessageType } from '@/graphql/enum/ContributionMessageType' -import { ContributionStatus } from '@/graphql/enum/ContributionStatus' import { LogError } from '@/server/LogError' import { AbstractUnconfirmedContributionRole } from './AbstractUnconfirmedContribution.role' diff --git a/backend/src/interactions/updateUnconfirmedContribution/UnconfirmedContributionUser.role.ts b/backend/src/interactions/updateUnconfirmedContribution/UnconfirmedContributionUser.role.ts index 6955cbfa7..e32e6f413 100644 --- a/backend/src/interactions/updateUnconfirmedContribution/UnconfirmedContributionUser.role.ts +++ b/backend/src/interactions/updateUnconfirmedContribution/UnconfirmedContributionUser.role.ts @@ -1,8 +1,7 @@ -import { Contribution, User } from 'database' +import { Contribution, ContributionStatus, User } from 'database' import { ContributionMessageBuilder } from '@/data/ContributionMessage.builder' import { ContributionArgs } from '@/graphql/arg/ContributionArgs' -import { ContributionStatus } from '@/graphql/enum/ContributionStatus' import { LogError } from '@/server/LogError' import { AbstractUnconfirmedContributionRole } from './AbstractUnconfirmedContribution.role' diff --git a/backend/src/interactions/updateUnconfirmedContribution/UnconfirmedContributionUserAddMessage.role.ts b/backend/src/interactions/updateUnconfirmedContribution/UnconfirmedContributionUserAddMessage.role.ts index 0440762f3..e88c1f2ce 100644 --- a/backend/src/interactions/updateUnconfirmedContribution/UnconfirmedContributionUserAddMessage.role.ts +++ b/backend/src/interactions/updateUnconfirmedContribution/UnconfirmedContributionUserAddMessage.role.ts @@ -1,9 +1,8 @@ -import { Contribution, User } from 'database' +import { Contribution, ContributionStatus, User } from 'database' import { ContributionMessageBuilder } from '@/data/ContributionMessage.builder' import { ContributionMessageArgs } from '@/graphql/arg/ContributionMessageArgs' import { ContributionMessageType } from '@/graphql/enum/ContributionMessageType' -import { ContributionStatus } from '@/graphql/enum/ContributionStatus' import { LogError } from '@/server/LogError' import { AbstractUnconfirmedContributionRole } from './AbstractUnconfirmedContribution.role' diff --git a/backend/src/util/virtualTransactions.ts b/backend/src/util/virtualTransactions.ts index a3bbbe042..c54e265cd 100644 --- a/backend/src/util/virtualTransactions.ts +++ b/backend/src/util/virtualTransactions.ts @@ -1,8 +1,7 @@ -import { Transaction as dbTransaction } from 'database' +import { Transaction as dbTransaction, TransactionTypeId } from 'database' import { Decimal } from 'decimal.js-light' import { RemoveOptions, SaveOptions } from 'typeorm' -import { TransactionTypeId } from 'core' import { Transaction } from '@model/Transaction' import { User } from '@model/User' diff --git a/core/src/graphql/logic/processXComSendCoins.ts b/core/src/graphql/logic/processXComSendCoins.ts index bdbf24928..51ddcda73 100644 --- a/core/src/graphql/logic/processXComSendCoins.ts +++ b/core/src/graphql/logic/processXComSendCoins.ts @@ -10,22 +10,28 @@ import { findUserByIdentifier, getCommunityByUuid, PendingTransactionLoggingView, - UserLoggingView + UserLoggingView, + TransactionTypeId, } from 'database' import { Decimal } from 'decimal.js-light' import { CONFIG as CONFIG_CORE } from '../../config' import { LOG4JS_BASE_CATEGORY_NAME } from '../../config/const' -import { encryptAndSign, PendingTransactionState, SendCoinsJwtPayloadType, SendCoinsResponseJwtPayloadType, verifyAndDecrypt } from 'shared' +import { + encryptAndSign, + fullName, + PendingTransactionState, + SendCoinsJwtPayloadType, + SendCoinsResponseJwtPayloadType, + verifyAndDecrypt +} from 'shared' import { SendCoinsClient as V1_0_SendCoinsClient } from '../../federation/client/1_0/SendCoinsClient' import { SendCoinsResult } from '../../federation/client/1_0/model/SendCoinsResult' import { SendCoinsClientFactory } from '../../federation/client/SendCoinsClientFactory' -import { TransactionTypeId } from '../../graphql/enum/TransactionTypeId' // import { LogError } from '@server/LogError' import { getLogger } from 'log4js' import { calculateSenderBalance } from '../../util/calculateSenderBalance' -import { fullName } from '../../util/utilities' import { randombytes_random } from 'sodium-native' import { SendCoinsResultLoggingView } from '../../federation/client/1_0/logging/SendCoinsResultLogging.view' From 80079bc2d436eae7634d72a2875e3284f95db660 Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Fri, 28 Nov 2025 19:15:31 +0100 Subject: [PATCH 07/20] remove logging copy step because new seeding don't use logging --- .github/workflows/test_e2e.yml | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/.github/workflows/test_e2e.yml b/.github/workflows/test_e2e.yml index a670e485d..5fa4970d7 100644 --- a/.github/workflows/test_e2e.yml +++ b/.github/workflows/test_e2e.yml @@ -32,11 +32,6 @@ jobs: - name: Boot up test system | seed backend run: bun turbo seed - - name: Moving logs after seeding - run: | - mkdir -p /home/runner/work/gradido/gradido/logs/backend/seed - mv /home/runner/work/gradido/gradido/logs/backend/*.log /home/runner/work/gradido/gradido/logs/backend/seed/ - - name: Boot up test system | docker-compose backend, frontend run: | cd backend @@ -144,11 +139,6 @@ jobs: cd ../backend cp .env.test_e2e .env - - name: Moving logs after seeding - run: | - mkdir -p /home/runner/work/gradido/gradido/logs/backend/seed - mv /home/runner/work/gradido/gradido/logs/backend/*.log /home/runner/work/gradido/gradido/logs/backend/seed/ - - name: Boot up test system | docker-compose backend, frontend run: | bun turbo backend#build frontend#build --env-mode=loose @@ -222,11 +212,6 @@ jobs: - name: Boot up test system | seed backend run: bun turbo seed - - name: Moving logs after seeding - run: | - mkdir -p /home/runner/work/gradido/gradido/logs/backend/seed - mv /home/runner/work/gradido/gradido/logs/backend/*.log /home/runner/work/gradido/gradido/logs/backend/seed/ - - name: Boot up test system | docker-compose backend, frontend run: | cd backend From 15cd2a6e7fc983fd833e18639cbda1fd75c0bf78 Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Sat, 29 Nov 2025 11:04:35 +0100 Subject: [PATCH 08/20] speed up seeding --- database/src/seeds/factory/creation.ts | 53 +++++++- database/src/seeds/factory/transaction.ts | 6 +- database/src/seeds/factory/transactionLink.ts | 20 ++- database/src/seeds/factory/user.ts | 80 +++++++++--- database/src/seeds/index.ts | 117 ++++++++---------- 5 files changed, 187 insertions(+), 89 deletions(-) diff --git a/database/src/seeds/factory/creation.ts b/database/src/seeds/factory/creation.ts index ddf5224de..618cbeebd 100644 --- a/database/src/seeds/factory/creation.ts +++ b/database/src/seeds/factory/creation.ts @@ -1,9 +1,10 @@ -import { Contribution, User } from '../../entity' +import { Contribution, Transaction, User } from '../../entity' import { Decimal } from 'decimal.js-light' import { CreationInterface } from '../creation/CreationInterface' import { ContributionType, ContributionStatus, TransactionTypeId } from '../../enum' import { findUserByIdentifier } from '../../queries' import { createTransaction } from './transaction' +import { AppDatabase } from '../../AppDatabase' export function nMonthsBefore(date: Date, months = 1): string { return new Date(date.getFullYear(), date.getMonth() - months, 1).toISOString() @@ -28,11 +29,42 @@ export async function creationFactory( if (!moderatorUser) { throw new Error('Moderator user not found') } - contribution = await confirmTransaction(contribution, moderatorUser) + await confirmTransaction(contribution, moderatorUser) } return contribution } +export async function creationFactoryBulk( + creations: CreationInterface[], + userCreationIndexedByEmail: Map, + moderatorUser: User, +): Promise { + const lastTransaction = await Transaction.findOne({ order: { id: 'DESC' }, select: ['id'], where: {} }) + let transactionId = lastTransaction ? lastTransaction.id + 1 : 1 + const dbContributions: Contribution[] = [] + const dbTransactions: Transaction[] = [] + + for (const creation of creations) { + const user = userCreationIndexedByEmail.get(creation.email) + if (!user) { + throw new Error(`User ${creation.email} not found`) + } + let contribution = await createContribution(creation, user, false) + if (creation.confirmed) { + const { contribution: _, transaction } = await confirmTransaction(contribution, moderatorUser, transactionId, false) + dbTransactions.push(transaction) + transactionId++ + } + dbContributions.push(contribution) + } + const dataSource = AppDatabase.getInstance().getDataSource() + await dataSource.transaction(async (transaction) => { + await dataSource.getRepository(Contribution).insert(dbContributions) + await dataSource.getRepository(Transaction).insert(dbTransactions) + }) + return dbContributions +} + export async function createContribution(creation: CreationInterface, user: User, store: boolean = true): Promise { const contribution = new Contribution() contribution.user = user @@ -47,7 +79,12 @@ export async function createContribution(creation: CreationInterface, user: User return store ? contribution.save() : contribution } -export async function confirmTransaction(contribution: Contribution, moderatorUser: User, store: boolean = true): Promise { +export async function confirmTransaction( + contribution: Contribution, + moderatorUser: User, + transactionId?: number, + store: boolean = true +): Promise<{ contribution: Contribution, transaction: Transaction }> { const now = new Date() const transaction = await createTransaction( contribution.amount, @@ -57,7 +94,8 @@ export async function confirmTransaction(contribution: Contribution, moderatorUs TransactionTypeId.CREATION, now, contribution.contributionDate, - true, + transactionId, + store, ) contribution.confirmedAt = now contribution.confirmedBy = moderatorUser.id @@ -65,7 +103,12 @@ export async function confirmTransaction(contribution: Contribution, moderatorUs contribution.transaction = transaction contribution.contributionStatus = ContributionStatus.CONFIRMED - return store ? contribution.save() : contribution + if (store) { + await contribution.save() + await transaction.save() + } + + return { contribution, transaction } } function getContributionDate(creation: CreationInterface): Date { diff --git a/database/src/seeds/factory/transaction.ts b/database/src/seeds/factory/transaction.ts index 1782c4f18..02a56723e 100644 --- a/database/src/seeds/factory/transaction.ts +++ b/database/src/seeds/factory/transaction.ts @@ -12,7 +12,8 @@ export async function createTransaction( linkedUser: User, type: TransactionTypeId, balanceDate: Date, - creationDate?: Date, + creationDate?: Date, + id?: number, store: boolean = true, ): Promise { @@ -31,6 +32,9 @@ export async function createTransaction( newBalance = newBalance.add(amount.toString()) const transaction = new Transaction() + if (id) { + transaction.id = id + } transaction.typeId = type transaction.memo = memo transaction.userId = user.id diff --git a/database/src/seeds/factory/transactionLink.ts b/database/src/seeds/factory/transactionLink.ts index 82155a908..956e33fb5 100644 --- a/database/src/seeds/factory/transactionLink.ts +++ b/database/src/seeds/factory/transactionLink.ts @@ -1,9 +1,10 @@ import { TransactionLinkInterface } from '../transactionLink/TransactionLinkInterface' -import { TransactionLink } from '../../entity' +import { TransactionLink, User } from '../../entity' import { Decimal } from 'decimal.js-light' import { findUserByIdentifier } from '../../queries' import { compoundInterest } from 'shared' import { randomBytes } from 'node:crypto' +import { AppDatabase } from '../../AppDatabase' export async function transactionLinkFactory( transactionLinkData: TransactionLinkInterface, @@ -19,6 +20,23 @@ export async function transactionLinkFactory( return createTransactionLink(transactionLinkData, userId) } +export async function transactionLinkFactoryBulk( + transactionLinks: TransactionLinkInterface[], + userCreationIndexedByEmail: Map +): Promise { + const dbTransactionLinks: TransactionLink[] = [] + for (const transactionLink of transactionLinks) { + const user = userCreationIndexedByEmail.get(transactionLink.email) + if (!user) { + throw new Error(`User ${transactionLink.email} not found`) + } + dbTransactionLinks.push(await createTransactionLink(transactionLink, user.id, false)) + } + const dataSource = AppDatabase.getInstance().getDataSource() + await dataSource.getRepository(TransactionLink).insert(dbTransactionLinks) + return dbTransactionLinks +} + export async function createTransactionLink(transactionLinkData: TransactionLinkInterface, userId: number, store: boolean = true): Promise { const holdAvailableAmount = compoundInterest(new Decimal(transactionLinkData.amount.toString()), CODE_VALID_DAYS_DURATION * 24 * 60 * 60) let createdAt = transactionLinkData.createdAt || new Date() diff --git a/database/src/seeds/factory/user.ts b/database/src/seeds/factory/user.ts index f4614587c..4a8a434d4 100644 --- a/database/src/seeds/factory/user.ts +++ b/database/src/seeds/factory/user.ts @@ -5,13 +5,55 @@ import { UserContactType, OptInType, PasswordEncryptionType } from 'shared' import { getHomeCommunity } from '../../queries/communities' import random from 'crypto-random-bigint' import { Community } from '../../entity' +import { AppDatabase } from '../..' export async function userFactory(user: UserInterface, homeCommunity?: Community | null): Promise { - let dbUserContact = new UserContact() - - dbUserContact.email = user.email ?? '' - dbUserContact.type = UserContactType.USER_CONTACT_EMAIL + // TODO: improve with cascade + let dbUser = await createUser(user, homeCommunity) + let dbUserContact = await createUserContact(user, dbUser.id) + dbUserContact = await dbUserContact.save() + dbUser.emailId = dbUserContact.id + dbUser.emailContact = dbUserContact + dbUser = await dbUser.save() + return dbUser +} + +// only use in non-parallel environment (seeding for example) +export async function userFactoryBulk(users: UserInterface[], homeCommunity?: Community | null): Promise { + const dbUsers: User[] = [] + const dbUserContacts: UserContact[] = [] + const lastUser = await User.findOne({ order: { id: 'DESC' }, select: ['id'], where: {} }) + const lastUserContact = await UserContact.findOne({ order: { id: 'DESC' }, select: ['id'], where: {} }) + let userId = lastUser ? lastUser.id + 1 : 1 + let emailId = lastUserContact ? lastUserContact.id + 1 : 1 + for(const user of users) { + const dbUser = await createUser(user, homeCommunity, false) + dbUser.id = userId + dbUser.emailId = emailId + + const dbUserContact = await createUserContact(user, userId, false) + dbUserContact.id = emailId + dbUserContact.userId = userId + dbUser.emailContact = dbUserContact + + dbUsers.push(dbUser) + dbUserContacts.push(dbUserContact) + + userId++ + emailId++ + } + const dataSource = AppDatabase.getInstance().getDataSource() + await dataSource.transaction(async transaction => { + await Promise.all([ + transaction.getRepository(User).insert(dbUsers), + transaction.getRepository(UserContact).insert(dbUserContacts) + ]) + }) + return dbUsers +} + +export async function createUser(user: UserInterface, homeCommunity?: Community | null, store: boolean = true): Promise { let dbUser = new User() dbUser.firstName = user.firstName ?? '' dbUser.lastName = user.lastName ?? '' @@ -25,9 +67,6 @@ export async function userFactory(user: UserInterface, homeCommunity?: Community dbUser.gradidoID = v4() if (user.emailChecked) { - dbUserContact.emailVerificationCode = random(64).toString() - dbUserContact.emailOptInTypeId = OptInType.EMAIL_OPT_IN_REGISTER - dbUserContact.emailChecked = true dbUser.password = random(64) dbUser.passwordEncryptionType = PasswordEncryptionType.GRADIDO_ID } @@ -38,12 +77,25 @@ export async function userFactory(user: UserInterface, homeCommunity?: Community dbUser.community = homeCommunity dbUser.communityUuid = homeCommunity.communityUuid! } - // TODO: improve with cascade - dbUser = await dbUser.save() - dbUserContact.userId = dbUser.id - dbUserContact = await dbUserContact.save() - dbUser.emailId = dbUserContact.id - dbUser.emailContact = dbUserContact - return dbUser.save() + return store ? dbUser.save() : dbUser +} + +export async function createUserContact(user: UserInterface, userId?: number, store: boolean = true): Promise { + let dbUserContact = new UserContact() + + dbUserContact.email = user.email ?? '' + dbUserContact.type = UserContactType.USER_CONTACT_EMAIL + + if (user.emailChecked) { + dbUserContact.emailVerificationCode = random(64).toString() + dbUserContact.emailOptInTypeId = OptInType.EMAIL_OPT_IN_REGISTER + dbUserContact.emailChecked = true + } + + if (userId) { + dbUserContact.userId = userId + } + + return store ? dbUserContact.save() : dbUserContact } \ No newline at end of file diff --git a/database/src/seeds/index.ts b/database/src/seeds/index.ts index c2a659e2f..5f085c5f8 100644 --- a/database/src/seeds/index.ts +++ b/database/src/seeds/index.ts @@ -1,102 +1,83 @@ import { AppDatabase } from '../AppDatabase' -import { clearDatabase } from '../../migration/clear' import { createCommunity } from './community' -import { userFactory } from './factory/user' +import { userFactoryBulk } from './factory/user' import { users } from './users' -import { datatype, internet, name } from 'faker' -import { creationFactory } from './factory/creation' +import { internet, name } from 'faker' +import { creationFactoryBulk } from './factory/creation' import { creations } from './creation' -import { transactionLinkFactory } from './factory/transactionLink' +import { transactionLinkFactoryBulk } from './factory/transactionLink' import { transactionLinks } from './transactionLink' import { contributionLinkFactory } from './factory/contributionLink' import { contributionLinks } from './contributionLink' import { User } from '../entity' -import { TransactionLink } from '../entity' -import { ContributionLink } from '../entity' +import { UserInterface } from './users/UserInterface' const RANDOM_USER_COUNT = 100 async function run() { - const now = new Date() - // clear database, use mysql2 directly, not AppDatabase - await clearDatabase() - + console.info('##seed## seeding started...') + const db = AppDatabase.getInstance() await db.init() + await clearDatabase() // seed home community - const homeCommunity = await createCommunity(false) - console.info('##seed## seeding home community successful...') + const homeCommunity = await createCommunity(false) + console.info(`##seed## seeding home community successful ...`) // seed standard users - // start creation of all users in parallel // put into map for later direct access - const userCreationIndexedByEmail = new Map>() - for (const user of users) { - userCreationIndexedByEmail.set(user.email!, userFactory(user, homeCommunity)) + const userCreationIndexedByEmail = new Map() + const defaultUsers = await userFactoryBulk(users, homeCommunity) + for (const dbUser of defaultUsers) { + userCreationIndexedByEmail.set(dbUser.emailContact.email, dbUser) } - const defaultUsersPromise = Promise.all(userCreationIndexedByEmail.values()).then(() => { - // log message after all users are created - console.info('##seed## seeding all standard users successful...') - }) + console.info(`##seed## seeding all standard users successful ...`) - // seed 100 random users - // start creation of all random users in parallel - const randomUsersCreation: Promise[] = [] + // seed 100 random users + const randomUsers = new Array(RANDOM_USER_COUNT) for (let i = 0; i < RANDOM_USER_COUNT; i++) { - randomUsersCreation.push(userFactory({ + randomUsers[i] = { firstName: name.firstName(), lastName: name.lastName(), email: internet.email(), - language: datatype.boolean() ? 'en' : 'de', - }, homeCommunity)) + language: Math.random() < 0.5 ? 'en' : 'de', + } } - const randomUsersPromise = Promise.all(randomUsersCreation).then(() => { - // log message after all random users are created - console.info(`##seed## seeding ${RANDOM_USER_COUNT} random users successful...`) - }) - - // create Contribution Links - // start creation of all contribution links in parallel - const contributionLinksPromises: Promise[] = [] - for (const contributionLink of contributionLinks) { - contributionLinksPromises.push(contributionLinkFactory(contributionLink)) - } - const contributionLinksPromise = Promise.all(contributionLinksPromises).then(() => { - // log message after all contribution links are created - console.info('##seed## seeding all contributionLinks successful...') - }) - - // create Transaction Links - // start creation of all transaction links in parallel - const transactionLinksPromises: Promise[] = [] - for (const transactionLink of transactionLinks) { - const user = await userCreationIndexedByEmail.get(transactionLink.email)! - transactionLinksPromises.push(transactionLinkFactory(transactionLink, user.id)) - } - const transactionLinksPromise = Promise.all(transactionLinksPromises).then(() => { - // log message after all transaction links are created - console.info('##seed## seeding all transactionLinks successful...') - }) + await userFactoryBulk(randomUsers, homeCommunity) + console.info(`##seed## seeding ${RANDOM_USER_COUNT} random users successful ...`) // create GDD serial, must be called one after another because seeding don't use semaphore - const moderatorUser = await userCreationIndexedByEmail.get('peter@lustig.de')! - for (const creation of creations) { - const user = await userCreationIndexedByEmail.get(creation.email)! - await creationFactory(creation, user, moderatorUser) - } + const moderatorUser = userCreationIndexedByEmail.get('peter@lustig.de')! + await creationFactoryBulk(creations, userCreationIndexedByEmail, moderatorUser) + console.info(`##seed## seeding all creations successful ...`) - // wait for all promises to be resolved - await Promise.all([ - defaultUsersPromise, - randomUsersPromise, - contributionLinksPromise, - transactionLinksPromise, - ]) + // create Contribution Links + for (const contributionLink of contributionLinks) { + await contributionLinkFactory(contributionLink) + } + console.info(`##seed## seeding all contributionLinks successful ...`) + + // create Transaction Links + await transactionLinkFactoryBulk(transactionLinks, userCreationIndexedByEmail) + console.info(`##seed## seeding all transactionLinks successful ...`) await db.destroy() - const timeDiffSeconds = (new Date().getTime() - now.getTime()) / 1000 - console.info(`##seed## seeding successful... after ${timeDiffSeconds} seconds`) + console.info(`##seed## seeding successful...`) +} + +async function clearDatabase() { + await AppDatabase.getInstance().getDataSource().transaction(async trx => { + await trx.query(`SET FOREIGN_KEY_CHECKS = 0`) + await trx.query(`TRUNCATE TABLE contributions`) + await trx.query(`TRUNCATE TABLE contribution_links`) + await trx.query(`TRUNCATE TABLE users`) + await trx.query(`TRUNCATE TABLE user_contacts`) + await trx.query(`TRUNCATE TABLE transactions`) + await trx.query(`TRUNCATE TABLE transaction_links`) + await trx.query(`TRUNCATE TABLE communities`) + await trx.query(`SET FOREIGN_KEY_CHECKS = 1`) + }) } run().catch((err) => { From 01b4f1ef661ec9d52b0d433d7f3771bb55390406 Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Sat, 29 Nov 2025 14:33:13 +0100 Subject: [PATCH 09/20] fix to make compatible to gradido-blockchain --- database/src/seeds/creation/index.ts | 1 - database/src/seeds/factory/creation.ts | 25 ++++++++++++++++++----- database/src/seeds/factory/user.ts | 13 ++++++++++-- database/src/seeds/index.ts | 14 +++++++++++-- database/src/seeds/users/bibi-bloxberg.ts | 2 ++ 5 files changed, 45 insertions(+), 10 deletions(-) diff --git a/database/src/seeds/creation/index.ts b/database/src/seeds/creation/index.ts index cdb123dcb..109591d46 100644 --- a/database/src/seeds/creation/index.ts +++ b/database/src/seeds/creation/index.ts @@ -142,7 +142,6 @@ export const creations: CreationInterface[] = [ memo: '#Hexen', contributionDate: nMonthsBefore(new Date()), confirmed: true, - moveCreationDate: 12, }, ...bobsTransactions, { diff --git a/database/src/seeds/factory/creation.ts b/database/src/seeds/factory/creation.ts index 618cbeebd..8870a717f 100644 --- a/database/src/seeds/factory/creation.ts +++ b/database/src/seeds/factory/creation.ts @@ -29,7 +29,7 @@ export async function creationFactory( if (!moderatorUser) { throw new Error('Moderator user not found') } - await confirmTransaction(contribution, moderatorUser) + await confirmTransaction(creation, contribution, moderatorUser) } return contribution } @@ -51,7 +51,13 @@ export async function creationFactoryBulk( } let contribution = await createContribution(creation, user, false) if (creation.confirmed) { - const { contribution: _, transaction } = await confirmTransaction(contribution, moderatorUser, transactionId, false) + const { contribution: _, transaction } = await confirmTransaction( + creation, + contribution, + moderatorUser, + transactionId, + false + ) dbTransactions.push(transaction) transactionId++ } @@ -80,24 +86,25 @@ export async function createContribution(creation: CreationInterface, user: User } export async function confirmTransaction( + creation: CreationInterface, contribution: Contribution, moderatorUser: User, transactionId?: number, store: boolean = true ): Promise<{ contribution: Contribution, transaction: Transaction }> { - const now = new Date() + const balanceDate = getBalanceDate(creation) const transaction = await createTransaction( contribution.amount, contribution.memo, contribution.user, moderatorUser, TransactionTypeId.CREATION, - now, + balanceDate, contribution.contributionDate, transactionId, store, ) - contribution.confirmedAt = now + contribution.confirmedAt = balanceDate contribution.confirmedBy = moderatorUser.id contribution.transactionId = transaction.id contribution.transaction = transaction @@ -116,4 +123,12 @@ function getContributionDate(creation: CreationInterface): Date { return new Date(nMonthsBefore(new Date(creation.contributionDate), creation.moveCreationDate)) } return new Date(creation.contributionDate) +} + +function getBalanceDate(creation: CreationInterface): Date { + const now = new Date() + if (creation.moveCreationDate) { + return new Date(nMonthsBefore(now, creation.moveCreationDate)) + } + return now } \ No newline at end of file diff --git a/database/src/seeds/factory/user.ts b/database/src/seeds/factory/user.ts index 4a8a434d4..fb1ab852e 100644 --- a/database/src/seeds/factory/user.ts +++ b/database/src/seeds/factory/user.ts @@ -27,6 +27,7 @@ export async function userFactoryBulk(users: UserInterface[], homeCommunity?: Co const lastUserContact = await UserContact.findOne({ order: { id: 'DESC' }, select: ['id'], where: {} }) let userId = lastUser ? lastUser.id + 1 : 1 let emailId = lastUserContact ? lastUserContact.id + 1 : 1 + // console.log(`start with userId: ${userId} and emailId: ${emailId}`) for(const user of users) { const dbUser = await createUser(user, homeCommunity, false) dbUser.id = userId @@ -45,9 +46,13 @@ export async function userFactoryBulk(users: UserInterface[], homeCommunity?: Co } const dataSource = AppDatabase.getInstance().getDataSource() await dataSource.transaction(async transaction => { + // typeorm change my data what I don't want + // because of manuel id assignment + const dbUsersCopy = dbUsers.map(user => ({ ...user })) + const dbUserContactsCopy = dbUserContacts.map(userContact => ({ ...userContact })) await Promise.all([ - transaction.getRepository(User).insert(dbUsers), - transaction.getRepository(UserContact).insert(dbUserContacts) + transaction.getRepository(User).insert(dbUsersCopy), + transaction.getRepository(UserContact).insert(dbUserContactsCopy) ]) }) return dbUsers @@ -87,6 +92,10 @@ export async function createUserContact(user: UserInterface, userId?: number, st dbUserContact.email = user.email ?? '' dbUserContact.type = UserContactType.USER_CONTACT_EMAIL + if (user.createdAt) { + dbUserContact.createdAt = user.createdAt + dbUserContact.updatedAt = user.createdAt + } if (user.emailChecked) { dbUserContact.emailVerificationCode = random(64).toString() dbUserContact.emailOptInTypeId = OptInType.EMAIL_OPT_IN_REGISTER diff --git a/database/src/seeds/index.ts b/database/src/seeds/index.ts index 5f085c5f8..67229133e 100644 --- a/database/src/seeds/index.ts +++ b/database/src/seeds/index.ts @@ -5,7 +5,7 @@ import { users } from './users' import { internet, name } from 'faker' import { creationFactoryBulk } from './factory/creation' import { creations } from './creation' -import { transactionLinkFactoryBulk } from './factory/transactionLink' +import { transactionLinkCode, transactionLinkFactoryBulk } from './factory/transactionLink' import { transactionLinks } from './transactionLink' import { contributionLinkFactory } from './factory/contributionLink' import { contributionLinks } from './contributionLink' @@ -59,7 +59,17 @@ async function run() { console.info(`##seed## seeding all contributionLinks successful ...`) // create Transaction Links - await transactionLinkFactoryBulk(transactionLinks, userCreationIndexedByEmail) + const movedTransactionLinks = transactionLinks.map(transactionLink => { + let createdAt = new Date(new Date().getTime() + 1000) + if (transactionLink.createdAt) { + createdAt = transactionLink.createdAt + } + return { + ...transactionLink, + createdAt: createdAt, + } + }) + await transactionLinkFactoryBulk(movedTransactionLinks, userCreationIndexedByEmail) console.info(`##seed## seeding all transactionLinks successful ...`) await db.destroy() diff --git a/database/src/seeds/users/bibi-bloxberg.ts b/database/src/seeds/users/bibi-bloxberg.ts index 9a40e922b..f78a3af1c 100644 --- a/database/src/seeds/users/bibi-bloxberg.ts +++ b/database/src/seeds/users/bibi-bloxberg.ts @@ -9,4 +9,6 @@ export const bibiBloxberg: UserInterface = { emailChecked: true, language: 'de', publisherId: 1234, + // move user createdAt before transaction link + createdAt: new Date(2021, 9, 17), } From 27b4d81370628ae24b0aa83d495be09230554c5b Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Sat, 29 Nov 2025 14:57:00 +0100 Subject: [PATCH 10/20] add roles to new seeding --- database/src/enum/RoleNames.ts | 8 ++++++++ database/src/enum/index.ts | 3 ++- database/src/seeds/factory/user.ts | 25 ++++++++++++++++++++++-- database/src/seeds/index.ts | 1 + database/src/seeds/users/peter-lustig.ts | 4 +++- 5 files changed, 37 insertions(+), 4 deletions(-) create mode 100644 database/src/enum/RoleNames.ts diff --git a/database/src/enum/RoleNames.ts b/database/src/enum/RoleNames.ts new file mode 100644 index 000000000..dda8eaa8a --- /dev/null +++ b/database/src/enum/RoleNames.ts @@ -0,0 +1,8 @@ +export enum RoleNames { + UNAUTHORIZED = 'UNAUTHORIZED', + USER = 'USER', + MODERATOR = 'MODERATOR', + MODERATOR_AI = 'MODERATOR_AI', + ADMIN = 'ADMIN', + DLT_CONNECTOR = 'DLT_CONNECTOR_ROLE', +} \ No newline at end of file diff --git a/database/src/enum/index.ts b/database/src/enum/index.ts index ed629db22..df243acf3 100644 --- a/database/src/enum/index.ts +++ b/database/src/enum/index.ts @@ -2,4 +2,5 @@ export * from './CommunityHandshakeStateType' export * from './ContributionType' export * from './ContributionStatus' export * from './TransactionTypeId' -export * from './ContributionCycleType' \ No newline at end of file +export * from './ContributionCycleType' +export * from './RoleNames' \ No newline at end of file diff --git a/database/src/seeds/factory/user.ts b/database/src/seeds/factory/user.ts index fb1ab852e..bebd07cf0 100644 --- a/database/src/seeds/factory/user.ts +++ b/database/src/seeds/factory/user.ts @@ -1,11 +1,12 @@ import { UserInterface } from '../users/UserInterface' -import { User, UserContact } from '../../entity' +import { User, UserContact, UserRole } from '../../entity' import { v4 } from 'uuid' import { UserContactType, OptInType, PasswordEncryptionType } from 'shared' import { getHomeCommunity } from '../../queries/communities' import random from 'crypto-random-bigint' import { Community } from '../../entity' import { AppDatabase } from '../..' +import { RoleNames } from '../../enum/RoleNames' export async function userFactory(user: UserInterface, homeCommunity?: Community | null): Promise { // TODO: improve with cascade @@ -15,6 +16,11 @@ export async function userFactory(user: UserInterface, homeCommunity?: Community dbUser.emailId = dbUserContact.id dbUser.emailContact = dbUserContact dbUser = await dbUser.save() + + const userRole = user.role as RoleNames + if (userRole && (userRole === RoleNames.ADMIN || userRole === RoleNames.MODERATOR)) { + await createUserRole(dbUser.id, userRole) + } return dbUser } @@ -23,6 +29,7 @@ export async function userFactory(user: UserInterface, homeCommunity?: Community export async function userFactoryBulk(users: UserInterface[], homeCommunity?: Community | null): Promise { const dbUsers: User[] = [] const dbUserContacts: UserContact[] = [] + const dbUserRoles: UserRole[] = [] const lastUser = await User.findOne({ order: { id: 'DESC' }, select: ['id'], where: {} }) const lastUserContact = await UserContact.findOne({ order: { id: 'DESC' }, select: ['id'], where: {} }) let userId = lastUser ? lastUser.id + 1 : 1 @@ -40,6 +47,11 @@ export async function userFactoryBulk(users: UserInterface[], homeCommunity?: Co dbUsers.push(dbUser) dbUserContacts.push(dbUserContact) + + const userRole = user.role as RoleNames + if (userRole && (userRole === RoleNames.ADMIN || userRole === RoleNames.MODERATOR)) { + dbUserRoles.push(await createUserRole(dbUser.id, userRole, false)) + } userId++ emailId++ @@ -50,9 +62,11 @@ export async function userFactoryBulk(users: UserInterface[], homeCommunity?: Co // because of manuel id assignment const dbUsersCopy = dbUsers.map(user => ({ ...user })) const dbUserContactsCopy = dbUserContacts.map(userContact => ({ ...userContact })) + const dbUserRolesCopy = dbUserRoles.map(userRole => ({ ...userRole })) await Promise.all([ transaction.getRepository(User).insert(dbUsersCopy), - transaction.getRepository(UserContact).insert(dbUserContactsCopy) + transaction.getRepository(UserContact).insert(dbUserContactsCopy), + transaction.getRepository(UserRole).insert(dbUserRolesCopy) ]) }) return dbUsers @@ -107,4 +121,11 @@ export async function createUserContact(user: UserInterface, userId?: number, st } return store ? dbUserContact.save() : dbUserContact +} + +export async function createUserRole(userId: number, role: RoleNames, store: boolean = true): Promise { + let dbUserRole = new UserRole() + dbUserRole.userId = userId + dbUserRole.role = role + return store ? dbUserRole.save() : dbUserRole } \ No newline at end of file diff --git a/database/src/seeds/index.ts b/database/src/seeds/index.ts index 67229133e..4da2c28e3 100644 --- a/database/src/seeds/index.ts +++ b/database/src/seeds/index.ts @@ -83,6 +83,7 @@ async function clearDatabase() { await trx.query(`TRUNCATE TABLE contribution_links`) await trx.query(`TRUNCATE TABLE users`) await trx.query(`TRUNCATE TABLE user_contacts`) + await trx.query(`TRUNCATE TABLE user_roles`) await trx.query(`TRUNCATE TABLE transactions`) await trx.query(`TRUNCATE TABLE transaction_links`) await trx.query(`TRUNCATE TABLE communities`) diff --git a/database/src/seeds/users/peter-lustig.ts b/database/src/seeds/users/peter-lustig.ts index 58b07fe99..e20bac5fe 100644 --- a/database/src/seeds/users/peter-lustig.ts +++ b/database/src/seeds/users/peter-lustig.ts @@ -1,4 +1,5 @@ import { UserInterface } from './UserInterface' +import { RoleNames } from '../../enum' export const peterLustig: UserInterface = { email: 'peter@lustig.de', @@ -7,5 +8,6 @@ export const peterLustig: UserInterface = { // description: 'Latzhose und Nickelbrille', createdAt: new Date('2020-11-25T10:48:43'), emailChecked: true, - language: 'de' + language: 'de', + role: RoleNames.ADMIN, } From f30cbb80e7a4905bc96039cabf334a6ec8fb12de Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Sat, 29 Nov 2025 14:57:42 +0100 Subject: [PATCH 11/20] fix issue with enum, typed graphql decorator didn't work when importing enum from database --- .../src/graphql/arg/SearchContributionsFilterArgs.ts | 2 +- backend/src/graphql/enum/ContributionCycleType.ts | 2 ++ backend/src/graphql/enum/ContributionStatus.ts | 2 ++ backend/src/graphql/enum/ContributionType.ts | 2 ++ backend/src/graphql/enum/PendingTransactionState.ts | 2 ++ backend/src/graphql/enum/RoleNames.ts | 10 ++-------- .../resolver/ContributionMessageResolver.test.ts | 3 ++- .../src/graphql/resolver/ContributionResolver.test.ts | 3 ++- backend/src/graphql/resolver/ContributionResolver.ts | 4 ++-- .../src/graphql/resolver/TransactionLinkResolver.ts | 6 +++--- .../src/graphql/validator/ContributionStatusArray.ts | 2 +- .../AbstractUnconfirmedContribution.role.ts | 3 ++- .../UnconfirmedContributionAdmin.role.ts | 3 ++- .../UnconfirmedContributionAdminAddMessage.role.ts | 3 ++- .../UnconfirmedContributionUser.role.ts | 3 ++- .../UnconfirmedContributionUserAddMessage.role.ts | 3 ++- 16 files changed, 31 insertions(+), 22 deletions(-) diff --git a/backend/src/graphql/arg/SearchContributionsFilterArgs.ts b/backend/src/graphql/arg/SearchContributionsFilterArgs.ts index 727940dac..ad8b7747e 100644 --- a/backend/src/graphql/arg/SearchContributionsFilterArgs.ts +++ b/backend/src/graphql/arg/SearchContributionsFilterArgs.ts @@ -1,7 +1,7 @@ import { IsBoolean, IsPositive, IsString } from 'class-validator' import { ArgsType, Field, InputType, Int } from 'type-graphql' -import { ContributionStatus } from 'database' +import { ContributionStatus } from '@enum/ContributionStatus' import { isContributionStatusArray } from '@/graphql/validator/ContributionStatusArray' diff --git a/backend/src/graphql/enum/ContributionCycleType.ts b/backend/src/graphql/enum/ContributionCycleType.ts index abcb6a477..050a6ac0d 100644 --- a/backend/src/graphql/enum/ContributionCycleType.ts +++ b/backend/src/graphql/enum/ContributionCycleType.ts @@ -1,6 +1,8 @@ import { registerEnumType } from 'type-graphql' import { ContributionCycleType } from 'database' +export { ContributionCycleType } + registerEnumType(ContributionCycleType, { name: 'ContributionCycleType', // this one is mandatory description: 'Name of the Type of the ContributionCycle', // this one is optional diff --git a/backend/src/graphql/enum/ContributionStatus.ts b/backend/src/graphql/enum/ContributionStatus.ts index 74b1cba47..69d2e1171 100644 --- a/backend/src/graphql/enum/ContributionStatus.ts +++ b/backend/src/graphql/enum/ContributionStatus.ts @@ -1,6 +1,8 @@ import { registerEnumType } from 'type-graphql' import { ContributionStatus } from 'database' +export { ContributionStatus } + registerEnumType(ContributionStatus, { name: 'ContributionStatus', description: 'Name of the Type of the Contribution Status', diff --git a/backend/src/graphql/enum/ContributionType.ts b/backend/src/graphql/enum/ContributionType.ts index 3be0b7595..28fae333a 100644 --- a/backend/src/graphql/enum/ContributionType.ts +++ b/backend/src/graphql/enum/ContributionType.ts @@ -1,6 +1,8 @@ import { registerEnumType } from 'type-graphql' import { ContributionType } from 'database' +export { ContributionType } + registerEnumType(ContributionType, { name: 'ContributionType', description: 'Name of the Type of the Contribution', diff --git a/backend/src/graphql/enum/PendingTransactionState.ts b/backend/src/graphql/enum/PendingTransactionState.ts index e59f3fd7d..cf1a17291 100644 --- a/backend/src/graphql/enum/PendingTransactionState.ts +++ b/backend/src/graphql/enum/PendingTransactionState.ts @@ -1,6 +1,8 @@ import { registerEnumType } from 'type-graphql' import { PendingTransactionState } from 'shared' +export { PendingTransactionState } + registerEnumType(PendingTransactionState, { name: 'PendingTransactionState', // this one is mandatory description: 'State of the PendingTransaction', // this one is optional diff --git a/backend/src/graphql/enum/RoleNames.ts b/backend/src/graphql/enum/RoleNames.ts index 8ba8e1441..872b4937f 100644 --- a/backend/src/graphql/enum/RoleNames.ts +++ b/backend/src/graphql/enum/RoleNames.ts @@ -1,13 +1,7 @@ import { registerEnumType } from 'type-graphql' +import { RoleNames } from 'database' -export enum RoleNames { - UNAUTHORIZED = 'UNAUTHORIZED', - USER = 'USER', - MODERATOR = 'MODERATOR', - MODERATOR_AI = 'MODERATOR_AI', - ADMIN = 'ADMIN', - DLT_CONNECTOR = 'DLT_CONNECTOR_ROLE', -} +export { RoleNames } registerEnumType(RoleNames, { name: 'RoleNames', // this one is mandatory diff --git a/backend/src/graphql/resolver/ContributionMessageResolver.test.ts b/backend/src/graphql/resolver/ContributionMessageResolver.test.ts index 673ffae15..483747b90 100644 --- a/backend/src/graphql/resolver/ContributionMessageResolver.test.ts +++ b/backend/src/graphql/resolver/ContributionMessageResolver.test.ts @@ -1,8 +1,9 @@ import { ApolloServerTestClient } from 'apollo-server-testing' -import { Contribution as DbContribution, Event as DbEvent, ContributionStatus } from 'database' +import { Contribution as DbContribution, Event as DbEvent } from 'database' import { GraphQLError } from 'graphql' import { DataSource } from 'typeorm' +import { ContributionStatus } from '@enum/ContributionStatus' import { cleanDB, resetToken, testEnvironment } from '@test/helpers' import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const' diff --git a/backend/src/graphql/resolver/ContributionResolver.test.ts b/backend/src/graphql/resolver/ContributionResolver.test.ts index 98b273763..31d405942 100644 --- a/backend/src/graphql/resolver/ContributionResolver.test.ts +++ b/backend/src/graphql/resolver/ContributionResolver.test.ts @@ -1,10 +1,11 @@ import { ApolloServerTestClient } from 'apollo-server-testing' -import { Contribution, Event as DbEvent, Transaction as DbTransaction, User, ContributionStatus } from 'database' +import { Contribution, Event as DbEvent, Transaction as DbTransaction, User } from 'database' import { Decimal } from 'decimal.js-light' import { GraphQLError } from 'graphql' import { DataSource, Equal } from 'typeorm' import { ContributionMessageType } from '@enum/ContributionMessageType' +import { ContributionStatus } from '@enum/ContributionStatus' import { Order } from '@enum/Order' import { cleanDB, diff --git a/backend/src/graphql/resolver/ContributionResolver.ts b/backend/src/graphql/resolver/ContributionResolver.ts index 7c451b5bf..8faf03480 100644 --- a/backend/src/graphql/resolver/ContributionResolver.ts +++ b/backend/src/graphql/resolver/ContributionResolver.ts @@ -1,7 +1,5 @@ import { Contribution as DbContribution, - ContributionStatus, - ContributionType, Transaction as DbTransaction, TransactionTypeId, User as DbUser, @@ -18,6 +16,7 @@ import { AdminUpdateContributionArgs } from '@arg/AdminUpdateContributionArgs' import { ContributionArgs } from '@arg/ContributionArgs' import { Paginated } from '@arg/Paginated' import { SearchContributionsFilterArgs } from '@arg/SearchContributionsFilterArgs' +import { ContributionStatus } from '@enum/ContributionStatus' import { AdminUpdateContribution } from '@model/AdminUpdateContribution' import { Contribution, ContributionListResult } from '@model/Contribution' import { OpenCreation } from '@model/OpenCreation' @@ -47,6 +46,7 @@ import { calculateDecay, Decay, fullName } from 'shared' import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const' import { ContributionMessageType } from '@enum/ContributionMessageType' +import { ContributionType } from '@enum/ContributionType' import { AppDatabase } from 'database' import { getLogger } from 'log4js' import { diff --git a/backend/src/graphql/resolver/TransactionLinkResolver.ts b/backend/src/graphql/resolver/TransactionLinkResolver.ts index b6b8f822f..eac60b9e3 100644 --- a/backend/src/graphql/resolver/TransactionLinkResolver.ts +++ b/backend/src/graphql/resolver/TransactionLinkResolver.ts @@ -3,6 +3,8 @@ import { randomBytes } from 'crypto' import { Paginated } from '@arg/Paginated' import { TransactionLinkArgs } from '@arg/TransactionLinkArgs' import { TransactionLinkFilters } from '@arg/TransactionLinkFilters' +import { ContributionType } from '@enum/ContributionType' +import { ContributionStatus } from '@enum/ContributionStatus' import { Community } from '@model/Community' import { ContributionLink } from '@model/ContributionLink' import { RedeemJwtLink } from '@model/RedeemJwtLink' @@ -12,9 +14,6 @@ import { QueryLinkResult } from '@union/QueryLinkResult' import { Decay, interpretEncryptedTransferArgs, EncryptedTransferArgs } from 'core' import { AppDatabase, Contribution as DbContribution, - ContributionCycleType, - ContributionStatus, - ContributionType, ContributionLink as DbContributionLink, FederatedCommunity as DbFederatedCommunity, DltTransaction as DbDltTransaction, @@ -26,6 +25,7 @@ import { findTransactionLinkByCode, getHomeCommunity } from 'database' +import { ContributionCycleType } from '@/graphql/enum/ContributionCycleType' import { Decimal } from 'decimal.js-light' import { Arg, Args, Authorized, Ctx, Int, Mutation, Query, Resolver } from 'type-graphql' diff --git a/backend/src/graphql/validator/ContributionStatusArray.ts b/backend/src/graphql/validator/ContributionStatusArray.ts index 65f61ec9e..dd7c93277 100644 --- a/backend/src/graphql/validator/ContributionStatusArray.ts +++ b/backend/src/graphql/validator/ContributionStatusArray.ts @@ -1,6 +1,6 @@ import { ValidationOptions, registerDecorator } from 'class-validator' -import { ContributionStatus } from 'database' +import { ContributionStatus } from '@enum/ContributionStatus' export function isContributionStatusArray(validationOptions?: ValidationOptions) { return function (object: Object, propertyName: string) { diff --git a/backend/src/interactions/updateUnconfirmedContribution/AbstractUnconfirmedContribution.role.ts b/backend/src/interactions/updateUnconfirmedContribution/AbstractUnconfirmedContribution.role.ts index 0f83821df..c3bed06ab 100644 --- a/backend/src/interactions/updateUnconfirmedContribution/AbstractUnconfirmedContribution.role.ts +++ b/backend/src/interactions/updateUnconfirmedContribution/AbstractUnconfirmedContribution.role.ts @@ -1,6 +1,7 @@ -import { Contribution, ContributionStatus, User } from 'database' +import { Contribution, User } from 'database' import { Decimal } from 'decimal.js-light' +import { ContributionStatus } from '@enum/ContributionStatus' import { Role } from '@/auth/Role' import { ContributionLogic } from '@/data/Contribution.logic' import { ContributionMessageBuilder } from '@/data/ContributionMessage.builder' diff --git a/backend/src/interactions/updateUnconfirmedContribution/UnconfirmedContributionAdmin.role.ts b/backend/src/interactions/updateUnconfirmedContribution/UnconfirmedContributionAdmin.role.ts index d95edf240..368abf461 100644 --- a/backend/src/interactions/updateUnconfirmedContribution/UnconfirmedContributionAdmin.role.ts +++ b/backend/src/interactions/updateUnconfirmedContribution/UnconfirmedContributionAdmin.role.ts @@ -1,5 +1,6 @@ -import { Contribution, ContributionStatus, User } from 'database' +import { Contribution, User } from 'database' +import { ContributionStatus } from '@enum/ContributionStatus' import { RIGHTS } from '@/auth/RIGHTS' import { Role } from '@/auth/Role' import { ContributionMessageBuilder } from '@/data/ContributionMessage.builder' diff --git a/backend/src/interactions/updateUnconfirmedContribution/UnconfirmedContributionAdminAddMessage.role.ts b/backend/src/interactions/updateUnconfirmedContribution/UnconfirmedContributionAdminAddMessage.role.ts index 780b2e401..887c2d7ad 100644 --- a/backend/src/interactions/updateUnconfirmedContribution/UnconfirmedContributionAdminAddMessage.role.ts +++ b/backend/src/interactions/updateUnconfirmedContribution/UnconfirmedContributionAdminAddMessage.role.ts @@ -1,5 +1,6 @@ -import { Contribution, ContributionStatus, User } from 'database' +import { Contribution, User } from 'database' +import { ContributionStatus } from '@enum/ContributionStatus' import { RIGHTS } from '@/auth/RIGHTS' import { Role } from '@/auth/Role' import { ContributionMessageBuilder } from '@/data/ContributionMessage.builder' diff --git a/backend/src/interactions/updateUnconfirmedContribution/UnconfirmedContributionUser.role.ts b/backend/src/interactions/updateUnconfirmedContribution/UnconfirmedContributionUser.role.ts index e32e6f413..8dee35b2c 100644 --- a/backend/src/interactions/updateUnconfirmedContribution/UnconfirmedContributionUser.role.ts +++ b/backend/src/interactions/updateUnconfirmedContribution/UnconfirmedContributionUser.role.ts @@ -1,5 +1,6 @@ -import { Contribution, ContributionStatus, User } from 'database' +import { Contribution, User } from 'database' +import { ContributionStatus } from '@enum/ContributionStatus' import { ContributionMessageBuilder } from '@/data/ContributionMessage.builder' import { ContributionArgs } from '@/graphql/arg/ContributionArgs' import { LogError } from '@/server/LogError' diff --git a/backend/src/interactions/updateUnconfirmedContribution/UnconfirmedContributionUserAddMessage.role.ts b/backend/src/interactions/updateUnconfirmedContribution/UnconfirmedContributionUserAddMessage.role.ts index e88c1f2ce..319639f12 100644 --- a/backend/src/interactions/updateUnconfirmedContribution/UnconfirmedContributionUserAddMessage.role.ts +++ b/backend/src/interactions/updateUnconfirmedContribution/UnconfirmedContributionUserAddMessage.role.ts @@ -1,5 +1,6 @@ -import { Contribution, ContributionStatus, User } from 'database' +import { Contribution, User } from 'database' +import { ContributionStatus } from '@enum/ContributionStatus' import { ContributionMessageBuilder } from '@/data/ContributionMessage.builder' import { ContributionMessageArgs } from '@/graphql/arg/ContributionMessageArgs' import { ContributionMessageType } from '@/graphql/enum/ContributionMessageType' From 654eec3f85095f0a76f7e46b82e791c7dbe0f7d8 Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Sun, 30 Nov 2025 12:30:33 +0100 Subject: [PATCH 12/20] use new seeding in database from backend --- .../resolver/ContributionResolver.test.ts | 8 -- .../src/graphql/resolver/UserResolver.test.ts | 8 +- backend/src/seeds/community/index.ts | 14 +-- .../ContributionLinkInterface.ts | 4 + backend/src/seeds/contributionLink/index.ts | 4 +- .../src/seeds/creation/CreationInterface.ts | 3 + backend/src/seeds/creation/index.ts | 5 + backend/src/seeds/factory/contributionLink.ts | 35 ++---- backend/src/seeds/factory/creation.ts | 61 ++--------- backend/src/seeds/factory/transactionLink.ts | 51 ++------- backend/src/seeds/factory/user.ts | 69 +----------- .../TransactionLinkInterface.ts | 3 + backend/src/seeds/transactionLink/index.ts | 3 + backend/src/seeds/users/UserInterface.ts | 3 + backend/src/seeds/users/bibi-bloxberg.ts | 3 + backend/src/seeds/users/bob-baumeister.ts | 3 + backend/src/seeds/users/garrick-ollivander.ts | 4 + backend/src/seeds/users/peter-lustig.ts | 3 + .../src/seeds/users/raeuber-hotzenplotz.ts | 4 + backend/src/seeds/users/stephen-hawking.ts | 3 + bun.lock | 8 +- database/@types/random-bigint/index.d.ts | 5 + database/package.json | 4 +- .../src/enum/GdtEntryType.ts | 0 database/src/index.ts | 1 + database/src/seeds/contributionLink/index.ts | 1 + database/src/seeds/creation/index.ts | 2 + .../src/seeds/factory/contributionLink.ts | 6 +- database/src/seeds/factory/index.ts | 6 + database/src/seeds/factory/user.ts | 7 +- database/src/seeds/index.ts | 103 +----------------- database/src/seeds/seed.ts | 98 +++++++++++++++++ database/src/seeds/transactionLink/index.ts | 1 + database/src/seeds/users/index.ts | 13 ++- 34 files changed, 223 insertions(+), 323 deletions(-) create mode 100644 database/@types/random-bigint/index.d.ts rename backend/src/seeds/graphql/enums.ts => database/src/enum/GdtEntryType.ts (100%) create mode 100644 database/src/seeds/factory/index.ts create mode 100644 database/src/seeds/seed.ts diff --git a/backend/src/graphql/resolver/ContributionResolver.test.ts b/backend/src/graphql/resolver/ContributionResolver.test.ts index 31d405942..399dc7e82 100644 --- a/backend/src/graphql/resolver/ContributionResolver.test.ts +++ b/backend/src/graphql/resolver/ContributionResolver.test.ts @@ -2139,14 +2139,6 @@ describe('ContributionResolver', () => { }) }) - it('stores the EMAIL_CONFIRMATION event in the database', async () => { - await expect(DbEvent.find()).resolves.toContainEqual( - expect.objectContaining({ - type: EventType.EMAIL_CONFIRMATION, - }), - ) - }) - describe('confirm same contribution again', () => { it('throws an error', async () => { jest.clearAllMocks() diff --git a/backend/src/graphql/resolver/UserResolver.test.ts b/backend/src/graphql/resolver/UserResolver.test.ts index 0fd06c0d1..b64b66370 100644 --- a/backend/src/graphql/resolver/UserResolver.test.ts +++ b/backend/src/graphql/resolver/UserResolver.test.ts @@ -67,7 +67,7 @@ import { printTimeDuration } from '@/util/time' import { objectValuesToArray } from 'core' import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const' -import { getLogger } from 'config-schema/test/testSetup' +import { clearLogs, getLogger, printLogs } from 'config-schema/test/testSetup' import { Location2Point } from './util/Location2Point' jest.mock('@/apis/humhub/HumHubClient') @@ -738,7 +738,7 @@ describe('UserResolver', () => { hasElopage: false, hideAmountGDD: false, hideAmountGDT: false, - humhubAllowed: true, + humhubAllowed: false, humhubPublishName: 'PUBLISH_NAME_ALIAS_OR_INITALS', klickTipp: { newsletterState: false, @@ -1610,7 +1610,7 @@ describe('UserResolver', () => { hasElopage: false, hideAmountGDD: false, hideAmountGDT: false, - humhubAllowed: true, + humhubAllowed: false, humhubPublishName: 'PUBLISH_NAME_ALIAS_OR_INITALS', klickTipp: { newsletterState: false, @@ -2256,7 +2256,7 @@ describe('UserResolver', () => { relations: ['user'], }) const activationLink = `${ - CONFIG.EMAIL_LINK_VERIFICATION + CONFIG.EMAIL_LINK_SETPASSWORD }${userContact.emailVerificationCode.toString()}` expect(sendAccountActivationEmail).toBeCalledWith({ firstName: 'Bibi', diff --git a/backend/src/seeds/community/index.ts b/backend/src/seeds/community/index.ts index d51eafc31..0d3b44d88 100644 --- a/backend/src/seeds/community/index.ts +++ b/backend/src/seeds/community/index.ts @@ -1,27 +1,19 @@ import { Community as DbCommunity } from 'database' -import { v4 as uuidv4 } from 'uuid' import { CONFIG } from '@/config' + export async function writeHomeCommunityEntry(): Promise { try { // check for existing homeCommunity entry let homeCom = await DbCommunity.findOne({ where: { foreign: false } }) - if (homeCom) { - // simply update the existing entry, but it MUST keep the ID and UUID because of possible relations - homeCom.publicKey = Buffer.from('public-key-data-seeding') // keyPair.publicKey - // homeCom.privateKey = keyPair.secretKey - homeCom.url = 'http://localhost/api/' - homeCom.name = CONFIG.COMMUNITY_NAME - homeCom.description = CONFIG.COMMUNITY_DESCRIPTION - await DbCommunity.save(homeCom) - } else { + if (!homeCom) { // insert a new homecommunity entry including a new ID and a new but ensured unique UUID homeCom = new DbCommunity() homeCom.foreign = false homeCom.publicKey = Buffer.from('public-key-data-seeding') // keyPair.publicKey // homeCom.privateKey = keyPair.secretKey - homeCom.communityUuid = uuidv4() // await newCommunityUuid() + homeCom.communityUuid = 'beac216d-73ae-427f-9678-0209af4936ce' // await newCommunityUuid() homeCom.url = 'http://localhost/api/' homeCom.name = CONFIG.COMMUNITY_NAME homeCom.description = CONFIG.COMMUNITY_DESCRIPTION diff --git a/backend/src/seeds/contributionLink/ContributionLinkInterface.ts b/backend/src/seeds/contributionLink/ContributionLinkInterface.ts index 15ba4b72d..ce0a60695 100644 --- a/backend/src/seeds/contributionLink/ContributionLinkInterface.ts +++ b/backend/src/seeds/contributionLink/ContributionLinkInterface.ts @@ -1,3 +1,6 @@ +export { ContributionLinkInterface } from 'database' + +/* export interface ContributionLinkInterface { amount: number name: string @@ -5,3 +8,4 @@ export interface ContributionLinkInterface { validFrom?: Date validTo?: Date } +*/ diff --git a/backend/src/seeds/contributionLink/index.ts b/backend/src/seeds/contributionLink/index.ts index 41d28eb60..5be34e171 100644 --- a/backend/src/seeds/contributionLink/index.ts +++ b/backend/src/seeds/contributionLink/index.ts @@ -1,5 +1,6 @@ -import { ContributionLinkInterface } from './ContributionLinkInterface' +export { contributionLinks } from 'database' +/* export const contributionLinks: ContributionLinkInterface[] = [ { name: 'Dokumenta 2017', @@ -16,3 +17,4 @@ export const contributionLinks: ContributionLinkInterface[] = [ validTo: new Date(2022, 8, 25), }, ] +*/ \ No newline at end of file diff --git a/backend/src/seeds/creation/CreationInterface.ts b/backend/src/seeds/creation/CreationInterface.ts index ee450bd93..a05276a3d 100644 --- a/backend/src/seeds/creation/CreationInterface.ts +++ b/backend/src/seeds/creation/CreationInterface.ts @@ -1,3 +1,5 @@ +export { CreationInterface } from 'database' +/* export interface CreationInterface { email: string amount: number @@ -7,3 +9,4 @@ export interface CreationInterface { // number of months to move the confirmed creation to the past moveCreationDate?: number } +*/ \ No newline at end of file diff --git a/backend/src/seeds/creation/index.ts b/backend/src/seeds/creation/index.ts index 1499f663b..f95bc6fa4 100644 --- a/backend/src/seeds/creation/index.ts +++ b/backend/src/seeds/creation/index.ts @@ -1,3 +1,7 @@ + +export { creations } from 'database' + +/* import { nMonthsBefore } from '@/seeds/factory/creation' import { CreationInterface } from './CreationInterface' @@ -153,3 +157,4 @@ export const creations: CreationInterface[] = [ confirmed: true, }, ] +*/ \ No newline at end of file diff --git a/backend/src/seeds/factory/contributionLink.ts b/backend/src/seeds/factory/contributionLink.ts index 4e8c945f3..e29d7a635 100644 --- a/backend/src/seeds/factory/contributionLink.ts +++ b/backend/src/seeds/factory/contributionLink.ts @@ -1,32 +1,15 @@ -import { ApolloServerTestClient } from 'apollo-server-testing' +import { + contributionLinkFactory as contributionLinkFactoryDb, + ContributionLinkInterface +} from 'database' import { ContributionLink } from '@model/ContributionLink' -import { ContributionLinkInterface } from '@/seeds/contributionLink/ContributionLinkInterface' -import { createContributionLink, login } from '@/seeds/graphql/mutations' +export { ContributionLinkInterface } -export const contributionLinkFactory = async ( - client: ApolloServerTestClient, +export async function contributionLinkFactory ( + _client: any, contributionLink: ContributionLinkInterface, -): Promise => { - const { mutate } = client - - // login as admin - await mutate({ - mutation: login, - variables: { email: 'peter@lustig.de', password: 'Aa12345_' }, - }) - const variables = { - amount: contributionLink.amount, - memo: contributionLink.memo, - name: contributionLink.name, - cycle: 'ONCE', - maxPerCycle: 1, - maxAmountPerMonth: 200, - validFrom: contributionLink.validFrom ? contributionLink.validFrom.toISOString() : undefined, - validTo: contributionLink.validTo ? contributionLink.validTo.toISOString() : undefined, - } - - const result = await mutate({ mutation: createContributionLink, variables }) - return result.data.createContributionLink +): Promise { + return new ContributionLink(await contributionLinkFactoryDb(contributionLink)) } diff --git a/backend/src/seeds/factory/creation.ts b/backend/src/seeds/factory/creation.ts index 9ce36bfa9..2d57dc782 100644 --- a/backend/src/seeds/factory/creation.ts +++ b/backend/src/seeds/factory/creation.ts @@ -1,58 +1,15 @@ -import { ApolloServerTestClient } from 'apollo-server-testing' -import { Contribution, Transaction } from 'database' +import { + Contribution, + creationFactory as creationFactoryDb, + CreationInterface, + nMonthsBefore +} from 'database' -import { findUserByEmail } from '@/graphql/resolver/UserResolver' -import { CreationInterface } from '@/seeds/creation/CreationInterface' -import { confirmContribution, createContribution, login } from '@/seeds/graphql/mutations' - -export const nMonthsBefore = (date: Date, months = 1): string => { - return new Date(date.getFullYear(), date.getMonth() - months, 1).toISOString() -} +export { CreationInterface, nMonthsBefore } export const creationFactory = async ( - client: ApolloServerTestClient, + _client: any, creation: CreationInterface, ): Promise => { - const { mutate } = client - await mutate({ - mutation: login, - variables: { email: creation.email, password: 'Aa12345_' }, - }) - const { - data: { createContribution: contribution }, - } = await mutate({ mutation: createContribution, variables: { ...creation } }) - - if (creation.confirmed) { - 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({ - where: { id: contribution.id }, - }) - - if (creation.moveCreationDate) { - const transaction = await Transaction.findOneOrFail({ - where: { userId: user.id, creationDate: new Date(creation.contributionDate) }, - order: { balanceDate: 'DESC' }, - }) - - if (transaction.decay.equals(0) && transaction.creationDate) { - confirmedContribution.contributionDate = new Date( - nMonthsBefore(transaction.creationDate, creation.moveCreationDate), - ) - transaction.creationDate = new Date( - nMonthsBefore(transaction.creationDate, creation.moveCreationDate), - ) - transaction.balanceDate = new Date( - nMonthsBefore(transaction.balanceDate, creation.moveCreationDate), - ) - await transaction.save() - await confirmedContribution.save() - } - } - return confirmedContribution - } else { - return contribution - } + return creationFactoryDb(creation) } diff --git a/backend/src/seeds/factory/transactionLink.ts b/backend/src/seeds/factory/transactionLink.ts index 80384025f..02911bd32 100644 --- a/backend/src/seeds/factory/transactionLink.ts +++ b/backend/src/seeds/factory/transactionLink.ts @@ -1,46 +1,13 @@ -import { ApolloServerTestClient } from 'apollo-server-testing' -import { TransactionLink } from 'database' +import { + transactionLinkFactory as transactionLinkFactoryDb, + TransactionLinkInterface +} from 'database' -import { transactionLinkExpireDate } from '@/graphql/resolver/TransactionLinkResolver' -import { createTransactionLink, login } from '@/seeds/graphql/mutations' -import { TransactionLinkInterface } from '@/seeds/transactionLink/TransactionLinkInterface' +export { TransactionLinkInterface } -export const transactionLinkFactory = async ( - client: ApolloServerTestClient, +export async function transactionLinkFactory ( + _client: any, transactionLink: TransactionLinkInterface, -): Promise => { - const { mutate } = client - - // login - await mutate({ - mutation: login, - variables: { email: transactionLink.email, password: 'Aa12345_' }, - }) - - const variables = { - amount: transactionLink.amount, - memo: transactionLink.memo, - } - - // get the transaction links's id - const { - data: { - createTransactionLink: { id }, - }, - } = await mutate({ mutation: createTransactionLink, variables }) - - if (transactionLink.createdAt || transactionLink.deletedAt) { - const dbTransactionLink = await TransactionLink.findOneOrFail({ where: { id } }) - - if (transactionLink.createdAt) { - dbTransactionLink.createdAt = transactionLink.createdAt - dbTransactionLink.validUntil = transactionLinkExpireDate(transactionLink.createdAt) - await dbTransactionLink.save() - } - - if (transactionLink.deletedAt) { - dbTransactionLink.deletedAt = new Date(dbTransactionLink.createdAt.getTime() + 1000) - await dbTransactionLink.save() - } - } +): Promise { + await transactionLinkFactoryDb(transactionLink) } diff --git a/backend/src/seeds/factory/user.ts b/backend/src/seeds/factory/user.ts index 36d9adfeb..f174df39a 100644 --- a/backend/src/seeds/factory/user.ts +++ b/backend/src/seeds/factory/user.ts @@ -1,77 +1,20 @@ -import { ApolloServerTestClient } from 'apollo-server-testing' -import { User } from 'database' +import { User, userFactory as userFactoryDb } from 'database' -import { RoleNames } from '@enum/RoleNames' - -import { setUserRole } from '@/graphql/resolver/util/modifyUserRole' import { writeHomeCommunityEntry } from '@/seeds/community' -import { createUser, setPassword } from '@/seeds/graphql/mutations' import { UserInterface } from '@/seeds/users/UserInterface' +import { encryptPassword } from '@/password/PasswordEncryptor' export const userFactory = async ( - client: ApolloServerTestClient, + _client: any, user: UserInterface, ): Promise => { - const { mutate } = client - const homeCom = await writeHomeCommunityEntry() - // console.log('call createUser with', JSON.stringify(user, null, 2)) - const response = await mutate({ mutation: createUser, variables: user }) - if (!response?.data?.createUser) { - // console.log(JSON.stringify(response, null, 2)) - throw new Error('createUser mutation returned unexpected response') - } - const { - data: { - createUser: { id }, - }, - } = response - // get user from database - let dbUser = await User.findOneOrFail({ where: { id }, relations: ['emailContact', 'userRoles'] }) - - const emailContact = dbUser.emailContact + const dbUser = await userFactoryDb(user, homeCom) if (user.emailChecked) { - await mutate({ - mutation: setPassword, - variables: { password: 'Aa12345_', code: emailContact.emailVerificationCode }, - }) - } - - // get last changes of user from database - dbUser = await User.findOneOrFail({ where: { id }, relations: { userRoles: true, emailContact: true } }) - - if (user.createdAt || user.deletedAt || user.role) { - if (user.createdAt) { - dbUser.createdAt = user.createdAt - // make sure emailContact is also updated for e2e test, prevent failing when time between seeding and test run is < 1 minute - dbUser.emailContact.createdAt = user.createdAt - dbUser.emailContact.updatedAt = user.createdAt - await dbUser.emailContact.save() - } - if (user.deletedAt) { - dbUser.deletedAt = user.deletedAt - } - const userRole = user.role as RoleNames - if (userRole && (userRole === RoleNames.ADMIN || userRole === RoleNames.MODERATOR)) { - await setUserRole(dbUser, user.role) - } + const passwortHash = await encryptPassword(dbUser, 'Aa12345_') + dbUser.password = passwortHash await dbUser.save() } - try { - if (homeCom.communityUuid) { - dbUser.communityUuid = homeCom.communityUuid - await User.save(dbUser) - } - } catch (_err) { - // no homeCommunity exists - } - - // get last changes of user from database - dbUser = await User.findOneOrFail({ - where: { id }, - withDeleted: true, - relations: ['emailContact', 'userRoles'], - }) return dbUser } diff --git a/backend/src/seeds/transactionLink/TransactionLinkInterface.ts b/backend/src/seeds/transactionLink/TransactionLinkInterface.ts index eaacfdf92..4b2e57fa3 100644 --- a/backend/src/seeds/transactionLink/TransactionLinkInterface.ts +++ b/backend/src/seeds/transactionLink/TransactionLinkInterface.ts @@ -1,3 +1,5 @@ +export { TransactionLinkInterface } from 'database' +/* export interface TransactionLinkInterface { email: string amount: number @@ -8,3 +10,4 @@ export interface TransactionLinkInterface { // redeemedBy?: number deletedAt?: boolean } +*/ \ No newline at end of file diff --git a/backend/src/seeds/transactionLink/index.ts b/backend/src/seeds/transactionLink/index.ts index 17683b580..c5d46b146 100644 --- a/backend/src/seeds/transactionLink/index.ts +++ b/backend/src/seeds/transactionLink/index.ts @@ -1,3 +1,5 @@ +export { transactionLinks } from 'database' +/* import { TransactionLinkInterface } from './TransactionLinkInterface' export const transactionLinks: TransactionLinkInterface[] = [ @@ -53,3 +55,4 @@ bei Gradidio sei dabei!`, deletedAt: true, }, ] +*/ \ No newline at end of file diff --git a/backend/src/seeds/users/UserInterface.ts b/backend/src/seeds/users/UserInterface.ts index 1fb1b128a..abbecb254 100644 --- a/backend/src/seeds/users/UserInterface.ts +++ b/backend/src/seeds/users/UserInterface.ts @@ -1,3 +1,5 @@ +export { UserInterface } from 'database' +/* export interface UserInterface { alias?: string email?: string @@ -11,3 +13,4 @@ export interface UserInterface { publisherId?: number role?: string } +*/ \ No newline at end of file diff --git a/backend/src/seeds/users/bibi-bloxberg.ts b/backend/src/seeds/users/bibi-bloxberg.ts index f78a3af1c..dda6b1525 100644 --- a/backend/src/seeds/users/bibi-bloxberg.ts +++ b/backend/src/seeds/users/bibi-bloxberg.ts @@ -1,3 +1,5 @@ +export { bibiBloxberg } from 'database' +/* import { UserInterface } from './UserInterface' export const bibiBloxberg: UserInterface = { @@ -12,3 +14,4 @@ export const bibiBloxberg: UserInterface = { // move user createdAt before transaction link createdAt: new Date(2021, 9, 17), } +*/ \ No newline at end of file diff --git a/backend/src/seeds/users/bob-baumeister.ts b/backend/src/seeds/users/bob-baumeister.ts index b7902f7bc..61df64759 100644 --- a/backend/src/seeds/users/bob-baumeister.ts +++ b/backend/src/seeds/users/bob-baumeister.ts @@ -1,3 +1,5 @@ +export { bobBaumeister } from 'database' +/* import { UserInterface } from './UserInterface' export const bobBaumeister: UserInterface = { @@ -9,3 +11,4 @@ export const bobBaumeister: UserInterface = { emailChecked: true, language: 'de', } +*/ \ No newline at end of file diff --git a/backend/src/seeds/users/garrick-ollivander.ts b/backend/src/seeds/users/garrick-ollivander.ts index 264a866bd..332f06157 100644 --- a/backend/src/seeds/users/garrick-ollivander.ts +++ b/backend/src/seeds/users/garrick-ollivander.ts @@ -1,3 +1,6 @@ + +export { garrickOllivander } from 'database' +/* import { UserInterface } from './UserInterface' export const garrickOllivander: UserInterface = { @@ -10,3 +13,4 @@ export const garrickOllivander: UserInterface = { emailChecked: false, language: 'en', } +*/ \ No newline at end of file diff --git a/backend/src/seeds/users/peter-lustig.ts b/backend/src/seeds/users/peter-lustig.ts index ff1fe065e..6c86ef800 100644 --- a/backend/src/seeds/users/peter-lustig.ts +++ b/backend/src/seeds/users/peter-lustig.ts @@ -1,3 +1,5 @@ +export { peterLustig } from 'database' +/* import { RoleNames } from '@enum/RoleNames' import { UserInterface } from './UserInterface' @@ -12,3 +14,4 @@ export const peterLustig: UserInterface = { language: 'de', role: RoleNames.ADMIN, } +*/ \ No newline at end of file diff --git a/backend/src/seeds/users/raeuber-hotzenplotz.ts b/backend/src/seeds/users/raeuber-hotzenplotz.ts index 62601efff..dc52f10b4 100644 --- a/backend/src/seeds/users/raeuber-hotzenplotz.ts +++ b/backend/src/seeds/users/raeuber-hotzenplotz.ts @@ -1,3 +1,6 @@ + +export { raeuberHotzenplotz } from 'database' +/* import { UserInterface } from './UserInterface' export const raeuberHotzenplotz: UserInterface = { @@ -8,3 +11,4 @@ export const raeuberHotzenplotz: UserInterface = { emailChecked: true, language: 'de', } +*/ \ No newline at end of file diff --git a/backend/src/seeds/users/stephen-hawking.ts b/backend/src/seeds/users/stephen-hawking.ts index a683b7579..a9a2085e6 100644 --- a/backend/src/seeds/users/stephen-hawking.ts +++ b/backend/src/seeds/users/stephen-hawking.ts @@ -1,3 +1,5 @@ +export { stephenHawking } from 'database' +/* import { UserInterface } from './UserInterface' export const stephenHawking: UserInterface = { @@ -10,3 +12,4 @@ export const stephenHawking: UserInterface = { deletedAt: new Date('2018-03-14T09:17:52'), language: 'en', } +*/ \ No newline at end of file diff --git a/bun.lock b/bun.lock index 6dd175b61..5485b2e8d 100644 --- a/bun.lock +++ b/bun.lock @@ -245,7 +245,7 @@ "@types/mysql": "^2.15.27", "@types/node": "^18.7.14", "await-semaphore": "^0.1.3", - "crypto-random-bigint": "^2.1.1", + "random-bigint": "^0.0.1", "ts-node": "^10.9.2", "typescript": "^4.9.5", }, @@ -1768,8 +1768,6 @@ "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="], - "crypto-random-bigint": ["crypto-random-bigint@2.1.1", "", { "dependencies": { "uint-rng": "^1.2.1" } }, "sha512-96+FDrenXybkpnLML/60S8NcG32KgJ5Y8yvNNCYPW02r+ssoXFR5XKenuIQcHLWumnGj8UPqUUHBzXNrDGkDmQ=="], - "css-functions-list": ["css-functions-list@3.2.3", "", {}, "sha512-IQOkD3hbR5KrN93MtcYuad6YPuTSUhntLHDuLEbFWE+ff2/XSZNdZG+LcbbIW5AXKg/WFIfYItIzVoHngHXZzA=="], "css-select": ["css-select@4.3.0", "", { "dependencies": { "boolbase": "^1.0.0", "css-what": "^6.0.1", "domhandler": "^4.3.1", "domutils": "^2.8.0", "nth-check": "^2.0.1" } }, "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ=="], @@ -3278,8 +3276,6 @@ "tiny-case": ["tiny-case@1.0.3", "", {}, "sha512-Eet/eeMhkO6TX8mnUteS9zgPbUMQa4I6Kkp5ORiBD5476/m+PIRiumP5tmh5ioJpH7k51Kehawy2UDfsnxxY8Q=="], - "tiny-webcrypto": ["tiny-webcrypto@1.0.3", "", {}, "sha512-LQQdNMAgz9BXNT2SKbYh3eCb+fLV0p7JB7MwUjzY6IOlQLGIadfnFqRpshERsS5Dl2OM/hs0+4I/XmSrF+RBbw=="], - "tinybench": ["tinybench@2.9.0", "", {}, "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg=="], "tinyexec": ["tinyexec@1.0.1", "", {}, "sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw=="], @@ -3392,8 +3388,6 @@ "uglify-js": ["uglify-js@3.19.3", "", { "bin": { "uglifyjs": "bin/uglifyjs" } }, "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ=="], - "uint-rng": ["uint-rng@1.2.1", "", { "dependencies": { "tiny-webcrypto": "^1.0.2" } }, "sha512-swhDg5H+3DX2sIvnYA7VMBMXV/t8mPxvh49CjCDkwFmj/3OZIDOQwJANBgM1MPSUBrUHNIlXmU7/GcL7m4907g=="], - "uint8array-extras": ["uint8array-extras@1.5.0", "", {}, "sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A=="], "unbox-primitive": ["unbox-primitive@1.1.0", "", { "dependencies": { "call-bound": "^1.0.3", "has-bigints": "^1.0.2", "has-symbols": "^1.1.0", "which-boxed-primitive": "^1.1.1" } }, "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw=="], diff --git a/database/@types/random-bigint/index.d.ts b/database/@types/random-bigint/index.d.ts new file mode 100644 index 000000000..9692fcbf7 --- /dev/null +++ b/database/@types/random-bigint/index.d.ts @@ -0,0 +1,5 @@ + +declare module 'random-bigint' { + function random(bits: number, cb?: (err: Error, num: BigInt) => void): BigInt + export = random +} diff --git a/database/package.json b/database/package.json index 906e8682e..ada327ba9 100644 --- a/database/package.json +++ b/database/package.json @@ -25,7 +25,7 @@ "up": "cross-env TZ=UTC tsx migration/index.ts up", "down": "cross-env TZ=UTC tsx migration/index.ts down", "reset": "cross-env TZ=UTC tsx migration/index.ts reset", - "seed": "cross-env TZ=UTC NODE_ENV=development bun src/seeds/index.ts", + "seed": "cross-env TZ=UTC NODE_ENV=development bun src/seeds/seed.ts", "up:test": "cross-env TZ=UTC DB_DATABASE=gradido_test tsx migration/index.ts up", "up:backend_test": "cross-env TZ=UTC DB_DATABASE=gradido_test_backend tsx migration/index.ts up", "up:federation_test": "cross-env TZ=UTC DB_DATABASE=gradido_test_federation tsx migration/index.ts up", @@ -39,7 +39,7 @@ "@types/mysql": "^2.15.27", "@types/node": "^18.7.14", "await-semaphore": "^0.1.3", - "crypto-random-bigint": "^2.1.1", + "random-bigint": "^0.0.1", "ts-node": "^10.9.2", "typescript": "^4.9.5" }, diff --git a/backend/src/seeds/graphql/enums.ts b/database/src/enum/GdtEntryType.ts similarity index 100% rename from backend/src/seeds/graphql/enums.ts rename to database/src/enum/GdtEntryType.ts diff --git a/database/src/index.ts b/database/src/index.ts index 45b60530c..2afe19cad 100644 --- a/database/src/index.ts +++ b/database/src/index.ts @@ -4,6 +4,7 @@ export { latestDbVersion } export * from './entity' export * from './logging' export * from './queries' +export * from './seeds' export * from './util' export * from './enum' export { AppDatabase } from './AppDatabase' diff --git a/database/src/seeds/contributionLink/index.ts b/database/src/seeds/contributionLink/index.ts index 41d28eb60..15c34d32b 100644 --- a/database/src/seeds/contributionLink/index.ts +++ b/database/src/seeds/contributionLink/index.ts @@ -1,4 +1,5 @@ import { ContributionLinkInterface } from './ContributionLinkInterface' +export type { ContributionLinkInterface } export const contributionLinks: ContributionLinkInterface[] = [ { diff --git a/database/src/seeds/creation/index.ts b/database/src/seeds/creation/index.ts index 109591d46..f20ec2bc5 100644 --- a/database/src/seeds/creation/index.ts +++ b/database/src/seeds/creation/index.ts @@ -2,6 +2,8 @@ import { nMonthsBefore } from '../factory/creation' import { CreationInterface } from './CreationInterface' +export type { CreationInterface } + const bobsSendings = [ { amount: 10, diff --git a/database/src/seeds/factory/contributionLink.ts b/database/src/seeds/factory/contributionLink.ts index 031fa9c00..c05888568 100644 --- a/database/src/seeds/factory/contributionLink.ts +++ b/database/src/seeds/factory/contributionLink.ts @@ -5,13 +5,11 @@ import { ContributionLinkInterface } from '../contributionLink/ContributionLinkI import { transactionLinkCode } from './transactionLink' import { ContributionCycleType } from '../../enum' -export const contributionLinkFactory = async ( - contributionLink: ContributionLinkInterface, -): Promise => { +export function contributionLinkFactory(contributionLink: ContributionLinkInterface): Promise { return createContributionLink(contributionLink) } -export async function createContributionLink(contributionLinkData: ContributionLinkInterface): Promise { +export function createContributionLink(contributionLinkData: ContributionLinkInterface): Promise { const contributionLink = new ContributionLink() contributionLink.amount = new Decimal(contributionLinkData.amount) contributionLink.name = contributionLinkData.name diff --git a/database/src/seeds/factory/index.ts b/database/src/seeds/factory/index.ts new file mode 100644 index 000000000..1165a6f27 --- /dev/null +++ b/database/src/seeds/factory/index.ts @@ -0,0 +1,6 @@ +export * from './contributionLink' +export * from './creation' +export * from './pendingTransaction' +export * from './transaction' +export * from './transactionLink' +export * from './user' diff --git a/database/src/seeds/factory/user.ts b/database/src/seeds/factory/user.ts index bebd07cf0..009c007df 100644 --- a/database/src/seeds/factory/user.ts +++ b/database/src/seeds/factory/user.ts @@ -3,7 +3,7 @@ import { User, UserContact, UserRole } from '../../entity' import { v4 } from 'uuid' import { UserContactType, OptInType, PasswordEncryptionType } from 'shared' import { getHomeCommunity } from '../../queries/communities' -import random from 'crypto-random-bigint' +import random from 'random-bigint' import { Community } from '../../entity' import { AppDatabase } from '../..' import { RoleNames } from '../../enum/RoleNames' @@ -12,14 +12,13 @@ export async function userFactory(user: UserInterface, homeCommunity?: Community // TODO: improve with cascade let dbUser = await createUser(user, homeCommunity) let dbUserContact = await createUserContact(user, dbUser.id) - dbUserContact = await dbUserContact.save() dbUser.emailId = dbUserContact.id dbUser.emailContact = dbUserContact dbUser = await dbUser.save() const userRole = user.role as RoleNames if (userRole && (userRole === RoleNames.ADMIN || userRole === RoleNames.MODERATOR)) { - await createUserRole(dbUser.id, userRole) + dbUser.userRoles = [await createUserRole(dbUser.id, userRole)] } return dbUser @@ -86,7 +85,7 @@ export async function createUser(user: UserInterface, homeCommunity?: Community dbUser.gradidoID = v4() if (user.emailChecked) { - dbUser.password = random(64) + // dbUser.password = dbUser.passwordEncryptionType = PasswordEncryptionType.GRADIDO_ID } if (!homeCommunity) { diff --git a/database/src/seeds/index.ts b/database/src/seeds/index.ts index 4da2c28e3..61c60ba28 100644 --- a/database/src/seeds/index.ts +++ b/database/src/seeds/index.ts @@ -1,98 +1,5 @@ -import { AppDatabase } from '../AppDatabase' -import { createCommunity } from './community' -import { userFactoryBulk } from './factory/user' -import { users } from './users' -import { internet, name } from 'faker' -import { creationFactoryBulk } from './factory/creation' -import { creations } from './creation' -import { transactionLinkCode, transactionLinkFactoryBulk } from './factory/transactionLink' -import { transactionLinks } from './transactionLink' -import { contributionLinkFactory } from './factory/contributionLink' -import { contributionLinks } from './contributionLink' -import { User } from '../entity' -import { UserInterface } from './users/UserInterface' - -const RANDOM_USER_COUNT = 100 - -async function run() { - console.info('##seed## seeding started...') - - const db = AppDatabase.getInstance() - await db.init() - await clearDatabase() - - // seed home community - const homeCommunity = await createCommunity(false) - console.info(`##seed## seeding home community successful ...`) - - // seed standard users - // put into map for later direct access - const userCreationIndexedByEmail = new Map() - const defaultUsers = await userFactoryBulk(users, homeCommunity) - for (const dbUser of defaultUsers) { - userCreationIndexedByEmail.set(dbUser.emailContact.email, dbUser) - } - console.info(`##seed## seeding all standard users successful ...`) - - // seed 100 random users - const randomUsers = new Array(RANDOM_USER_COUNT) - for (let i = 0; i < RANDOM_USER_COUNT; i++) { - randomUsers[i] = { - firstName: name.firstName(), - lastName: name.lastName(), - email: internet.email(), - language: Math.random() < 0.5 ? 'en' : 'de', - } - } - await userFactoryBulk(randomUsers, homeCommunity) - console.info(`##seed## seeding ${RANDOM_USER_COUNT} random users successful ...`) - - // create GDD serial, must be called one after another because seeding don't use semaphore - const moderatorUser = userCreationIndexedByEmail.get('peter@lustig.de')! - await creationFactoryBulk(creations, userCreationIndexedByEmail, moderatorUser) - console.info(`##seed## seeding all creations successful ...`) - - // create Contribution Links - for (const contributionLink of contributionLinks) { - await contributionLinkFactory(contributionLink) - } - console.info(`##seed## seeding all contributionLinks successful ...`) - - // create Transaction Links - const movedTransactionLinks = transactionLinks.map(transactionLink => { - let createdAt = new Date(new Date().getTime() + 1000) - if (transactionLink.createdAt) { - createdAt = transactionLink.createdAt - } - return { - ...transactionLink, - createdAt: createdAt, - } - }) - await transactionLinkFactoryBulk(movedTransactionLinks, userCreationIndexedByEmail) - console.info(`##seed## seeding all transactionLinks successful ...`) - - await db.destroy() - console.info(`##seed## seeding successful...`) -} - -async function clearDatabase() { - await AppDatabase.getInstance().getDataSource().transaction(async trx => { - await trx.query(`SET FOREIGN_KEY_CHECKS = 0`) - await trx.query(`TRUNCATE TABLE contributions`) - await trx.query(`TRUNCATE TABLE contribution_links`) - await trx.query(`TRUNCATE TABLE users`) - await trx.query(`TRUNCATE TABLE user_contacts`) - await trx.query(`TRUNCATE TABLE user_roles`) - await trx.query(`TRUNCATE TABLE transactions`) - await trx.query(`TRUNCATE TABLE transaction_links`) - await trx.query(`TRUNCATE TABLE communities`) - await trx.query(`SET FOREIGN_KEY_CHECKS = 1`) - }) -} - -run().catch((err) => { - // biome-ignore lint/suspicious/noConsole: no logger present - console.error('error on seeding', err) -}) - +export * from './contributionLink' +export * from './creation' +export * from './factory' +export * from './transactionLink' +export * from './users' diff --git a/database/src/seeds/seed.ts b/database/src/seeds/seed.ts new file mode 100644 index 000000000..e551d7a61 --- /dev/null +++ b/database/src/seeds/seed.ts @@ -0,0 +1,98 @@ +import { AppDatabase } from '../AppDatabase' +import { createCommunity } from './community' +import { userFactoryBulk } from './factory/user' +import { users } from './users' +import { internet, name } from 'faker' +import { creationFactoryBulk } from './factory/creation' +import { creations } from './creation' +import { transactionLinkFactoryBulk } from './factory/transactionLink' +import { transactionLinks } from './transactionLink' +import { contributionLinkFactory } from './factory/contributionLink' +import { contributionLinks } from './contributionLink' +import { User } from '../entity' +import { UserInterface } from './users/UserInterface' + +const RANDOM_USER_COUNT = 100 + +async function run() { + console.info('##seed## seeding started...') + + const db = AppDatabase.getInstance() + await db.init() + await clearDatabase() + + // seed home community + const homeCommunity = await createCommunity(false) + console.info(`##seed## seeding home community successful ...`) + + // seed standard users + // put into map for later direct access + const userCreationIndexedByEmail = new Map() + const defaultUsers = await userFactoryBulk(users, homeCommunity) + for (const dbUser of defaultUsers) { + userCreationIndexedByEmail.set(dbUser.emailContact.email, dbUser) + } + console.info(`##seed## seeding all standard users successful ...`) + + // seed 100 random users + const randomUsers = new Array(RANDOM_USER_COUNT) + for (let i = 0; i < RANDOM_USER_COUNT; i++) { + randomUsers[i] = { + firstName: name.firstName(), + lastName: name.lastName(), + email: internet.email(), + language: Math.random() < 0.5 ? 'en' : 'de', + } + } + await userFactoryBulk(randomUsers, homeCommunity) + console.info(`##seed## seeding ${RANDOM_USER_COUNT} random users successful ...`) + + // create GDD serial, must be called one after another because seeding don't use semaphore + const moderatorUser = userCreationIndexedByEmail.get('peter@lustig.de')! + await creationFactoryBulk(creations, userCreationIndexedByEmail, moderatorUser) + console.info(`##seed## seeding all creations successful ...`) + + // create Contribution Links + for (const contributionLink of contributionLinks) { + await contributionLinkFactory(contributionLink) + } + console.info(`##seed## seeding all contributionLinks successful ...`) + + // create Transaction Links + const movedTransactionLinks = transactionLinks.map(transactionLink => { + let createdAt = new Date(new Date().getTime() + 1000) + if (transactionLink.createdAt) { + createdAt = transactionLink.createdAt + } + return { + ...transactionLink, + createdAt: createdAt, + } + }) + await transactionLinkFactoryBulk(movedTransactionLinks, userCreationIndexedByEmail) + console.info(`##seed## seeding all transactionLinks successful ...`) + + await db.destroy() + console.info(`##seed## seeding successful...`) +} + +async function clearDatabase() { + await AppDatabase.getInstance().getDataSource().transaction(async trx => { + await trx.query(`SET FOREIGN_KEY_CHECKS = 0`) + await trx.query(`TRUNCATE TABLE contributions`) + await trx.query(`TRUNCATE TABLE contribution_links`) + await trx.query(`TRUNCATE TABLE users`) + await trx.query(`TRUNCATE TABLE user_contacts`) + await trx.query(`TRUNCATE TABLE user_roles`) + await trx.query(`TRUNCATE TABLE transactions`) + await trx.query(`TRUNCATE TABLE transaction_links`) + await trx.query(`TRUNCATE TABLE communities`) + await trx.query(`SET FOREIGN_KEY_CHECKS = 1`) + }) +} + +run().catch((err) => { + // biome-ignore lint/suspicious/noConsole: no logger present + console.error('error on seeding', err) +}) + diff --git a/database/src/seeds/transactionLink/index.ts b/database/src/seeds/transactionLink/index.ts index 17683b580..2d5364aa5 100644 --- a/database/src/seeds/transactionLink/index.ts +++ b/database/src/seeds/transactionLink/index.ts @@ -1,4 +1,5 @@ import { TransactionLinkInterface } from './TransactionLinkInterface' +export type { TransactionLinkInterface } export const transactionLinks: TransactionLinkInterface[] = [ { diff --git a/database/src/seeds/users/index.ts b/database/src/seeds/users/index.ts index beb6c6f25..8149ffd4c 100644 --- a/database/src/seeds/users/index.ts +++ b/database/src/seeds/users/index.ts @@ -4,8 +4,19 @@ import { garrickOllivander } from './garrick-ollivander' import { peterLustig } from './peter-lustig' import { raeuberHotzenplotz } from './raeuber-hotzenplotz' import { stephenHawking } from './stephen-hawking' +import { UserInterface } from './UserInterface' -export const users = [ +export { + type UserInterface, + bibiBloxberg, + bobBaumeister, + garrickOllivander, + peterLustig, + raeuberHotzenplotz, + stephenHawking +} + +export const users: UserInterface[] = [ peterLustig, bibiBloxberg, bobBaumeister, From 1b0d8324fb6c446097b9eb6a55fe66e10505e98f Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Sun, 30 Nov 2025 12:47:17 +0100 Subject: [PATCH 13/20] move seeding back into backend --- backend/src/seeds/factory/user.ts | 17 +++- backend/src/seeds/index.ts | 127 ++++++++++++++---------------- backend/turbo.json | 6 +- database/src/seeds/seed.ts | 98 ----------------------- database/turbo.json | 4 - 5 files changed, 82 insertions(+), 170 deletions(-) delete mode 100644 database/src/seeds/seed.ts diff --git a/backend/src/seeds/factory/user.ts b/backend/src/seeds/factory/user.ts index f174df39a..5308518cb 100644 --- a/backend/src/seeds/factory/user.ts +++ b/backend/src/seeds/factory/user.ts @@ -1,4 +1,4 @@ -import { User, userFactory as userFactoryDb } from 'database' +import { User, userFactory as userFactoryDb, userFactoryBulk as userFactoryBulkDb, Community } from 'database' import { writeHomeCommunityEntry } from '@/seeds/community' import { UserInterface } from '@/seeds/users/UserInterface' @@ -18,3 +18,18 @@ export const userFactory = async ( } return dbUser } + +export async function userFactoryBulk(users: UserInterface[], homeCommunity?: Community | null) { + if (!homeCommunity) { + homeCommunity = await writeHomeCommunityEntry() + } + const dbUsers = await userFactoryBulkDb(users, homeCommunity) + for (const dbUser of dbUsers) { + if (dbUser.emailContact.emailChecked) { + const passwortHash = await encryptPassword(dbUser, 'Aa12345_') + dbUser.password = passwortHash + await dbUser.save() + } + } + return dbUsers +} \ No newline at end of file diff --git a/backend/src/seeds/index.ts b/backend/src/seeds/index.ts index 3a1504262..4cc352ec7 100644 --- a/backend/src/seeds/index.ts +++ b/backend/src/seeds/index.ts @@ -1,10 +1,13 @@ -import { createTestClient } from 'apollo-server-testing' -import { entities } from 'database' -import { datatype, internet, name } from 'faker' +import { + AppDatabase, + User, + UserInterface, + creationFactoryBulk, + transactionLinkFactoryBulk +} from 'database' +import { internet, name } from 'faker' import { CONFIG } from '@/config' -import { CONFIG as CORE_CONFIG } from 'core' -import { createServer } from '@/server/createServer' import { initLogging } from '@/server/logger' import { getLogger } from 'log4js' @@ -12,95 +15,87 @@ import { writeHomeCommunityEntry } from './community' import { contributionLinks } from './contributionLink/index' import { creations } from './creation/index' import { contributionLinkFactory } from './factory/contributionLink' -import { creationFactory } from './factory/creation' -import { transactionLinkFactory } from './factory/transactionLink' -import { userFactory } from './factory/user' +import { userFactoryBulk } from './factory/user' import { transactionLinks } from './transactionLink/index' import { users } from './users/index' -CORE_CONFIG.EMAIL = false +const RANDOM_USER_COUNT = 100 const logger = getLogger('seed') -const context = { - token: '', - setHeaders: { - push: (value: { key: string; value: string }): void => { - context.token = value.value - }, - - forEach: (): void => { - // do nothing - }, - }, - clientTimezoneOffset: 0, -} - -export const cleanDB = async () => { - // this only works as long we do not have foreign key constraints - for (const entity of entities) { - if (entity.name !== 'Migration') { - await resetEntity(entity) - } - } -} - -const resetEntity = async (entity: any) => { - const items = await entity.find({ withDeleted: true }) - if (items.length > 0) { - const ids = items.map((e: any) => e.id) - await entity.delete(ids) - } -} - const run = async () => { initLogging() - const server = await createServer(getLogger('apollo'), context) - const seedClient = createTestClient(server.apollo) - const { con } = server - await cleanDB() - logger.info('##seed## clean database successful...') + const db = AppDatabase.getInstance() + await db.init() + await clearDatabase(db) + logger.info('clean database successful...') logger.info(`crypto worker enabled: ${CONFIG.USE_CRYPTO_WORKER}`) // seed home community - await writeHomeCommunityEntry() + const homeCommunity = await writeHomeCommunityEntry() // seed the standard users - for (const user of users) { - await userFactory(seedClient, user) + // put into map for later direct access + const userCreationIndexedByEmail = new Map() + const defaultUsers = await userFactoryBulk(users, homeCommunity) + for (const dbUser of defaultUsers) { + userCreationIndexedByEmail.set(dbUser.emailContact.email, dbUser) } - logger.info('##seed## seeding all standard users successful...') + logger.info('seeding all standard users successful...') // seed 100 random users - for (let i = 0; i < 100; i++) { - await userFactory(seedClient, { + const randomUsers = new Array(RANDOM_USER_COUNT) + for (let i = 0; i < RANDOM_USER_COUNT; i++) { + randomUsers[i] = { firstName: name.firstName(), lastName: name.lastName(), email: internet.email(), - language: datatype.boolean() ? 'en' : 'de', - }) - logger.info(`##seed## seed ${i}. random user`) + language: Math.random() < 0.5 ? 'en' : 'de', + } } - logger.info('##seed## seeding all random users successful...') + await userFactoryBulk(randomUsers, homeCommunity) + logger.info('seeding all random users successful...') // create GDD - for (const creation of creations) { - await creationFactory(seedClient, creation) - } - logger.info('##seed## seeding all creations successful...') + const moderatorUser = userCreationIndexedByEmail.get('peter@lustig.de')! + await creationFactoryBulk(creations, userCreationIndexedByEmail, moderatorUser) + logger.info('seeding all creations successful...') // create Transaction Links - for (const transactionLink of transactionLinks) { - await transactionLinkFactory(seedClient, transactionLink) - } - logger.info('##seed## seeding all transactionLinks successful...') + const movedTransactionLinks = transactionLinks.map(transactionLink => { + let createdAt = new Date(new Date().getTime() + 1000) + if (transactionLink.createdAt) { + createdAt = transactionLink.createdAt + } + return { + ...transactionLink, + createdAt: createdAt, + } + }) + await transactionLinkFactoryBulk(movedTransactionLinks, userCreationIndexedByEmail) + logger.info('seeding all transactionLinks successful...') // create Contribution Links for (const contributionLink of contributionLinks) { - await contributionLinkFactory(seedClient, contributionLink) + await contributionLinkFactory(null, contributionLink) } - logger.info('##seed## seeding all contributionLinks successful...') + logger.info('seeding all contributionLinks successful...') - await con.destroy() + await db.destroy() +} + +async function clearDatabase(db: AppDatabase) { + await db.getDataSource().transaction(async trx => { + await trx.query(`SET FOREIGN_KEY_CHECKS = 0`) + await trx.query(`TRUNCATE TABLE contributions`) + await trx.query(`TRUNCATE TABLE contribution_links`) + await trx.query(`TRUNCATE TABLE users`) + await trx.query(`TRUNCATE TABLE user_contacts`) + await trx.query(`TRUNCATE TABLE user_roles`) + await trx.query(`TRUNCATE TABLE transactions`) + await trx.query(`TRUNCATE TABLE transaction_links`) + await trx.query(`TRUNCATE TABLE communities`) + await trx.query(`SET FOREIGN_KEY_CHECKS = 1`) + }) } run().catch((err) => { diff --git a/backend/turbo.json b/backend/turbo.json index 9ba2f9dad..fb847307f 100644 --- a/backend/turbo.json +++ b/backend/turbo.json @@ -1,12 +1,16 @@ { "extends": ["//"], "tasks": { + "seed": { + "dependsOn": ["database#up", "^build"], + "cache": false + }, "locales": {}, "locales:fix": {}, "lint": { }, "lint:fix": { - }, + }, "test": { "dependsOn": ["database#up:backend_test", "^build"] }, diff --git a/database/src/seeds/seed.ts b/database/src/seeds/seed.ts deleted file mode 100644 index e551d7a61..000000000 --- a/database/src/seeds/seed.ts +++ /dev/null @@ -1,98 +0,0 @@ -import { AppDatabase } from '../AppDatabase' -import { createCommunity } from './community' -import { userFactoryBulk } from './factory/user' -import { users } from './users' -import { internet, name } from 'faker' -import { creationFactoryBulk } from './factory/creation' -import { creations } from './creation' -import { transactionLinkFactoryBulk } from './factory/transactionLink' -import { transactionLinks } from './transactionLink' -import { contributionLinkFactory } from './factory/contributionLink' -import { contributionLinks } from './contributionLink' -import { User } from '../entity' -import { UserInterface } from './users/UserInterface' - -const RANDOM_USER_COUNT = 100 - -async function run() { - console.info('##seed## seeding started...') - - const db = AppDatabase.getInstance() - await db.init() - await clearDatabase() - - // seed home community - const homeCommunity = await createCommunity(false) - console.info(`##seed## seeding home community successful ...`) - - // seed standard users - // put into map for later direct access - const userCreationIndexedByEmail = new Map() - const defaultUsers = await userFactoryBulk(users, homeCommunity) - for (const dbUser of defaultUsers) { - userCreationIndexedByEmail.set(dbUser.emailContact.email, dbUser) - } - console.info(`##seed## seeding all standard users successful ...`) - - // seed 100 random users - const randomUsers = new Array(RANDOM_USER_COUNT) - for (let i = 0; i < RANDOM_USER_COUNT; i++) { - randomUsers[i] = { - firstName: name.firstName(), - lastName: name.lastName(), - email: internet.email(), - language: Math.random() < 0.5 ? 'en' : 'de', - } - } - await userFactoryBulk(randomUsers, homeCommunity) - console.info(`##seed## seeding ${RANDOM_USER_COUNT} random users successful ...`) - - // create GDD serial, must be called one after another because seeding don't use semaphore - const moderatorUser = userCreationIndexedByEmail.get('peter@lustig.de')! - await creationFactoryBulk(creations, userCreationIndexedByEmail, moderatorUser) - console.info(`##seed## seeding all creations successful ...`) - - // create Contribution Links - for (const contributionLink of contributionLinks) { - await contributionLinkFactory(contributionLink) - } - console.info(`##seed## seeding all contributionLinks successful ...`) - - // create Transaction Links - const movedTransactionLinks = transactionLinks.map(transactionLink => { - let createdAt = new Date(new Date().getTime() + 1000) - if (transactionLink.createdAt) { - createdAt = transactionLink.createdAt - } - return { - ...transactionLink, - createdAt: createdAt, - } - }) - await transactionLinkFactoryBulk(movedTransactionLinks, userCreationIndexedByEmail) - console.info(`##seed## seeding all transactionLinks successful ...`) - - await db.destroy() - console.info(`##seed## seeding successful...`) -} - -async function clearDatabase() { - await AppDatabase.getInstance().getDataSource().transaction(async trx => { - await trx.query(`SET FOREIGN_KEY_CHECKS = 0`) - await trx.query(`TRUNCATE TABLE contributions`) - await trx.query(`TRUNCATE TABLE contribution_links`) - await trx.query(`TRUNCATE TABLE users`) - await trx.query(`TRUNCATE TABLE user_contacts`) - await trx.query(`TRUNCATE TABLE user_roles`) - await trx.query(`TRUNCATE TABLE transactions`) - await trx.query(`TRUNCATE TABLE transaction_links`) - await trx.query(`TRUNCATE TABLE communities`) - await trx.query(`SET FOREIGN_KEY_CHECKS = 1`) - }) -} - -run().catch((err) => { - // biome-ignore lint/suspicious/noConsole: no logger present - console.error('error on seeding', err) -}) - diff --git a/database/turbo.json b/database/turbo.json index 7017e8542..a40c23229 100644 --- a/database/turbo.json +++ b/database/turbo.json @@ -1,10 +1,6 @@ { "extends": ["//"], "tasks": { - "seed": { - "dependsOn": ["database#up", "^build"], - "cache": false - }, "clear": { "cache": false }, From e2f069c50eda3f89fd6d346282451f037a2e0cb1 Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Sun, 30 Nov 2025 13:05:00 +0100 Subject: [PATCH 14/20] queze a bit more speed out of e2e tests --- .github/workflows/test_e2e.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test_e2e.yml b/.github/workflows/test_e2e.yml index 5fa4970d7..5d7e1f8be 100644 --- a/.github/workflows/test_e2e.yml +++ b/.github/workflows/test_e2e.yml @@ -30,7 +30,7 @@ jobs: sudo cp ./nginx/e2e-test.conf /etc/nginx/sites-available/default - name: Boot up test system | seed backend - run: bun turbo seed + run: bun turbo seed --env-mode=loose - name: Boot up test system | docker-compose backend, frontend run: | @@ -130,7 +130,7 @@ jobs: sudo cp ./nginx/e2e-test.conf /etc/nginx/sites-available/default - name: Boot up test system | seed backend - run: bun turbo seed + run: bun turbo seed --env-mode=loose - name: copy test config run: | @@ -210,7 +210,7 @@ jobs: sudo cp ./nginx/e2e-test.conf /etc/nginx/sites-available/default - name: Boot up test system | seed backend - run: bun turbo seed + run: bun turbo seed --env-mode=loose - name: Boot up test system | docker-compose backend, frontend run: | From bcc86d382270fcd3956cfbe653475328d347b965 Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Sun, 30 Nov 2025 13:33:15 +0100 Subject: [PATCH 15/20] use sass-embedded on systems without grass --- admin/package.json | 2 +- bun.lock | 82 ++++++++++++++++++++++++++++++++++--------- frontend/package.json | 2 +- 3 files changed, 67 insertions(+), 19 deletions(-) diff --git a/admin/package.json b/admin/package.json index 463162667..848eb39bf 100644 --- a/admin/package.json +++ b/admin/package.json @@ -78,7 +78,7 @@ "mock-apollo-client": "^1.2.1", "postcss-html": "^1.8.0", "prettier": "^3.5.3", - "sass": "^1.77.8", + "sass-embedded": "^1.93.2", "stylelint": "^16.19.1", "stylelint-config-recommended-vue": "^1.6.0", "stylelint-config-standard-scss": "^14.0.0", diff --git a/bun.lock b/bun.lock index 5485b2e8d..d7ce9fd0c 100644 --- a/bun.lock +++ b/bun.lock @@ -76,7 +76,7 @@ "mock-apollo-client": "^1.2.1", "postcss-html": "^1.8.0", "prettier": "^3.5.3", - "sass": "^1.77.8", + "sass-embedded": "^1.93.2", "stylelint": "^16.19.1", "stylelint-config-recommended-vue": "^1.6.0", "stylelint-config-standard-scss": "^14.0.0", @@ -428,7 +428,7 @@ "mock-apollo-client": "^1.2.1", "postcss-html": "^1.8.0", "prettier": "^3.5.3", - "sass": "^1.83.4", + "sass-embedded": "^1.93.2", "stylelint": "^16.19.1", "stylelint-config-recommended-vue": "^1.6.0", "stylelint-config-standard-scss": "^14.0.0", @@ -634,6 +634,8 @@ "@borewit/text-codec": ["@borewit/text-codec@0.1.1", "", {}, "sha512-5L/uBxmjaCIX5h8Z+uu+kA9BQLkc/Wl06UGR5ajNRxu+/XjonB5i8JpgFMrPj3LXTCPA0pv8yxUvbUi+QthGGA=="], + "@bufbuild/protobuf": ["@bufbuild/protobuf@2.10.1", "", {}, "sha512-ckS3+vyJb5qGpEYv/s1OebUHDi/xSNtfgw1wqKZo7MR9F2z+qXr0q5XagafAG/9O0QPVIUfST0smluYSTpYFkg=="], + "@cacheable/memoize": ["@cacheable/memoize@2.0.3", "", { "dependencies": { "@cacheable/utils": "^2.0.3" } }, "sha512-hl9wfQgpiydhQEIv7fkjEzTGE+tcosCXLKFDO707wYJ/78FVOlowb36djex5GdbSyeHnG62pomYLMuV/OT8Pbw=="], "@cacheable/memory": ["@cacheable/memory@2.0.3", "", { "dependencies": { "@cacheable/memoize": "^2.0.3", "@cacheable/utils": "^2.0.3", "@keyv/bigmap": "^1.0.2", "hookified": "^1.12.1", "keyv": "^5.5.3" } }, "sha512-R3UKy/CKOyb1LZG/VRCTMcpiMDyLH7SH3JrraRdK6kf3GweWCOU3sgvE13W3TiDRbxnDKylzKJvhUAvWl9LQOA=="], @@ -1628,6 +1630,8 @@ "buffer": ["buffer@6.0.3", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" } }, "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA=="], + "buffer-builder": ["buffer-builder@0.2.0", "", {}, "sha512-7VPMEPuYznPSoR21NE1zvd2Xna6c/CloiZCfcMXR1Jny6PjX0N4Nsa38zcBFo/FMK+BlA+FLKbJCQ0i2yxp+Xg=="], + "buffer-crc32": ["buffer-crc32@0.2.13", "", {}, "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ=="], "buffer-from": ["buffer-from@1.1.2", "", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="], @@ -1712,6 +1716,8 @@ "colorette": ["colorette@2.0.20", "", {}, "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w=="], + "colorjs.io": ["colorjs.io@0.5.2", "", {}, "sha512-twmVoizEW7ylZSN32OgKdXRmo1qg+wT5/6C3xu5b9QsWzSFAhHLn2xd8ro0diCsKfCj1RdaTP/nrcW+vAoQPIw=="], + "combined-stream": ["combined-stream@1.0.8", "", { "dependencies": { "delayed-stream": "~1.0.0" } }, "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg=="], "commander": ["commander@7.2.0", "", {}, "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw=="], @@ -3070,6 +3076,44 @@ "sass": ["sass@1.93.2", "", { "dependencies": { "chokidar": "^4.0.0", "immutable": "^5.0.2", "source-map-js": ">=0.6.2 <2.0.0" }, "optionalDependencies": { "@parcel/watcher": "^2.4.1" }, "bin": { "sass": "sass.js" } }, "sha512-t+YPtOQHpGW1QWsh1CHQ5cPIr9lbbGZLZnbihP/D/qZj/yuV68m8qarcV17nvkOX81BCrvzAlq2klCQFZghyTg=="], + "sass-embedded": ["sass-embedded@1.93.3", "", { "dependencies": { "@bufbuild/protobuf": "^2.5.0", "buffer-builder": "^0.2.0", "colorjs.io": "^0.5.0", "immutable": "^5.0.2", "rxjs": "^7.4.0", "supports-color": "^8.1.1", "sync-child-process": "^1.0.2", "varint": "^6.0.0" }, "optionalDependencies": { "sass-embedded-all-unknown": "1.93.3", "sass-embedded-android-arm": "1.93.3", "sass-embedded-android-arm64": "1.93.3", "sass-embedded-android-riscv64": "1.93.3", "sass-embedded-android-x64": "1.93.3", "sass-embedded-darwin-arm64": "1.93.3", "sass-embedded-darwin-x64": "1.93.3", "sass-embedded-linux-arm": "1.93.3", "sass-embedded-linux-arm64": "1.93.3", "sass-embedded-linux-musl-arm": "1.93.3", "sass-embedded-linux-musl-arm64": "1.93.3", "sass-embedded-linux-musl-riscv64": "1.93.3", "sass-embedded-linux-musl-x64": "1.93.3", "sass-embedded-linux-riscv64": "1.93.3", "sass-embedded-linux-x64": "1.93.3", "sass-embedded-unknown-all": "1.93.3", "sass-embedded-win32-arm64": "1.93.3", "sass-embedded-win32-x64": "1.93.3" }, "bin": { "sass": "dist/bin/sass.js" } }, "sha512-+VUy01yfDqNmIVMd/LLKl2TTtY0ovZN0rTonh+FhKr65mFwIYgU9WzgIZKS7U9/SPCQvWTsTGx9jyt+qRm/XFw=="], + + "sass-embedded-all-unknown": ["sass-embedded-all-unknown@1.93.3", "", { "dependencies": { "sass": "1.93.3" }, "cpu": [ "!arm", "!x64", "!arm64", ] }, "sha512-3okGgnE41eg+CPLtAPletu6nQ4N0ij7AeW+Sl5Km4j29XcmqZQeFwYjHe1AlKTEgLi/UAONk1O8i8/lupeKMbw=="], + + "sass-embedded-android-arm": ["sass-embedded-android-arm@1.93.3", "", { "os": "android", "cpu": "arm" }, "sha512-8xOw9bywfOD6Wv24BgCmgjkk6tMrsOTTHcb28KDxeJtFtoxiUyMbxo0vChpPAfp2Hyg2tFFKS60s0s4JYk+Raw=="], + + "sass-embedded-android-arm64": ["sass-embedded-android-arm64@1.93.3", "", { "os": "android", "cpu": "arm64" }, "sha512-uqUl3Kt1IqdGVAcAdbmC+NwuUJy8tM+2ZnB7/zrt6WxWVShVCRdFnWR9LT8HJr7eJN7AU8kSXxaVX/gedanPsg=="], + + "sass-embedded-android-riscv64": ["sass-embedded-android-riscv64@1.93.3", "", { "os": "android", "cpu": "none" }, "sha512-2jNJDmo+3qLocjWqYbXiBDnfgwrUeZgZFHJIwAefU7Fn66Ot7rsXl+XPwlokaCbTpj7eMFIqsRAZ/uDueXNCJg=="], + + "sass-embedded-android-x64": ["sass-embedded-android-x64@1.93.3", "", { "os": "android", "cpu": "x64" }, "sha512-y0RoAU6ZenQFcjM9PjQd3cRqRTjqwSbtWLL/p68y2oFyh0QGN0+LQ826fc0ZvU/AbqCsAizkqjzOn6cRZJxTTQ=="], + + "sass-embedded-darwin-arm64": ["sass-embedded-darwin-arm64@1.93.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-7zb/hpdMOdKteK17BOyyypemglVURd1Hdz6QGsggy60aUFfptTLQftLRg8r/xh1RbQAUKWFbYTNaM47J9yPxYg=="], + + "sass-embedded-darwin-x64": ["sass-embedded-darwin-x64@1.93.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-Ek1Vp8ZDQEe327Lz0b7h3hjvWH3u9XjJiQzveq74RPpJQ2q6d9LfWpjiRRohM4qK6o4XOHw1X10OMWPXJtdtWg=="], + + "sass-embedded-linux-arm": ["sass-embedded-linux-arm@1.93.3", "", { "os": "linux", "cpu": "arm" }, "sha512-yeiv2y+dp8B4wNpd3+JsHYD0mvpXSfov7IGyQ1tMIR40qv+ROkRqYiqQvAOXf76Qwh4Y9OaYZtLpnsPjfeq6mA=="], + + "sass-embedded-linux-arm64": ["sass-embedded-linux-arm64@1.93.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-RBrHWgfd8Dd8w4fbmdRVXRrhh8oBAPyeWDTKAWw8ZEmuXfVl4ytjDuyxaVilh6rR1xTRTNpbaA/YWApBlLrrNw=="], + + "sass-embedded-linux-musl-arm": ["sass-embedded-linux-musl-arm@1.93.3", "", { "os": "linux", "cpu": "arm" }, "sha512-fU0fwAwbp7sBE3h5DVU5UPzvaLg7a4yONfFWkkcCp6ZrOiPuGRHXXYriWQ0TUnWy4wE+svsVuWhwWgvlb/tkKg=="], + + "sass-embedded-linux-musl-arm64": ["sass-embedded-linux-musl-arm64@1.93.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-PS829l+eUng+9W4PFclXGb4uA2+965NHV3/Sa5U7qTywjeeUUYTZg70dJHSqvhrBEfCc2XJABeW3adLJbyQYkw=="], + + "sass-embedded-linux-musl-riscv64": ["sass-embedded-linux-musl-riscv64@1.93.3", "", { "os": "linux", "cpu": "none" }, "sha512-cK1oBY+FWQquaIGEeQ5H74KTO8cWsSWwXb/WaildOO9U6wmUypTgUYKQ0o5o/29nZbWWlM1PHuwVYTSnT23Jjg=="], + + "sass-embedded-linux-musl-x64": ["sass-embedded-linux-musl-x64@1.93.3", "", { "os": "linux", "cpu": "x64" }, "sha512-A7wkrsHu2/I4Zpa0NMuPGkWDVV7QGGytxGyUq3opSXgAexHo/vBPlGoDXoRlSdex0cV+aTMRPjoGIfdmNlHwyg=="], + + "sass-embedded-linux-riscv64": ["sass-embedded-linux-riscv64@1.93.3", "", { "os": "linux", "cpu": "none" }, "sha512-vWkW1+HTF5qcaHa6hO80gx/QfB6GGjJUP0xLbnAoY4pwEnw5ulGv6RM8qYr8IDhWfVt/KH+lhJ2ZFxnJareisQ=="], + + "sass-embedded-linux-x64": ["sass-embedded-linux-x64@1.93.3", "", { "os": "linux", "cpu": "x64" }, "sha512-k6uFxs+e5jSuk1Y0niCwuq42F9ZC5UEP7P+RIOurIm8w/5QFa0+YqeW+BPWEW5M1FqVOsNZH3qGn4ahqvAEjPA=="], + + "sass-embedded-unknown-all": ["sass-embedded-unknown-all@1.93.3", "", { "dependencies": { "sass": "1.93.3" }, "os": [ "!linux", "!win32", "!darwin", "!android", ] }, "sha512-o5wj2rLpXH0C+GJKt/VpWp6AnMsCCbfFmnMAttcrsa+U3yrs/guhZ3x55KAqqUsE8F47e3frbsDL+1OuQM5DAA=="], + + "sass-embedded-win32-arm64": ["sass-embedded-win32-arm64@1.93.3", "", { "os": "win32", "cpu": "arm64" }, "sha512-0dOfT9moy9YmBolodwYYXtLwNr4jL4HQC9rBfv6mVrD7ud8ue2kDbn+GVzj1hEJxvEexVSmDCf7MHUTLcGs9xQ=="], + + "sass-embedded-win32-x64": ["sass-embedded-win32-x64@1.93.3", "", { "os": "win32", "cpu": "x64" }, "sha512-wHFVfxiS9hU/sNk7KReD+lJWRp3R0SLQEX4zfOnRP2zlvI2X4IQR5aZr9GNcuMP6TmNpX0nQPZTegS8+h9RrEg=="], + "saxes": ["saxes@6.0.0", "", { "dependencies": { "xmlchars": "^2.2.0" } }, "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA=="], "schema-utils": ["schema-utils@4.3.3", "", { "dependencies": { "@types/json-schema": "^7.0.9", "ajv": "^8.9.0", "ajv-formats": "^2.1.1", "ajv-keywords": "^5.1.0" } }, "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA=="], @@ -3232,7 +3276,7 @@ "superjson": ["superjson@2.2.2", "", { "dependencies": { "copy-anything": "^3.0.2" } }, "sha512-5JRxVqC8I8NuOUjzBbvVJAKNM8qoVuH0O77h4WInc/qC2q5IreqKxYwgkga3PfA22OayK2ikceb/B26dztPl+Q=="], - "supports-color": ["supports-color@5.5.0", "", { "dependencies": { "has-flag": "^3.0.0" } }, "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow=="], + "supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="], "supports-hyperlinks": ["supports-hyperlinks@3.2.0", "", { "dependencies": { "has-flag": "^4.0.0", "supports-color": "^7.0.0" } }, "sha512-zFObLMyZeEwzAoKCyu1B91U79K2t7ApXuQfo8OuxwXLDgcKxuwM+YvcbIhm6QWqz7mHUH1TVytR1PwVVjEuMig=="], @@ -3244,6 +3288,10 @@ "symbol-tree": ["symbol-tree@3.2.4", "", {}, "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw=="], + "sync-child-process": ["sync-child-process@1.0.2", "", { "dependencies": { "sync-message-port": "^1.0.0" } }, "sha512-8lD+t2KrrScJ/7KXCSyfhT3/hRq78rC0wBFqNJXv3mZyn6hW2ypM05JmlSvtqRbeq6jqA94oHbxAr2vYsJ8vDA=="], + + "sync-message-port": ["sync-message-port@1.1.3", "", {}, "sha512-GTt8rSKje5FilG+wEdfCkOcLL7LWqpMlr2c3LRuKt/YXxcJ52aGSbGBAdI4L3aaqfrBt6y711El53ItyH1NWzg=="], + "synckit": ["synckit@0.11.11", "", { "dependencies": { "@pkgr/core": "^0.2.9" } }, "sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw=="], "table": ["table@6.9.0", "", { "dependencies": { "ajv": "^8.0.1", "lodash.truncate": "^4.4.2", "slice-ansi": "^4.0.0", "string-width": "^4.2.3", "strip-ansi": "^6.0.1" } }, "sha512-9kY+CygyYM6j02t5YFHbNz2FN5QmYGv9zAjVp4lCDjlCw7amdckXlEt/bjMhUIfj4ThGRE4gCUH5+yGnNuPo5A=="], @@ -3444,6 +3492,8 @@ "validator": ["validator@13.15.15", "", {}, "sha512-BgWVbCI72aIQy937xbawcs+hrVaN/CZ2UwutgaJ36hGqRrLNM+f5LUT/YPRbo8IV/ASeFzXszezV+y2+rq3l8A=="], + "varint": ["varint@6.0.0", "", {}, "sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg=="], + "vary": ["vary@1.1.2", "", {}, "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg=="], "vee-validate": ["vee-validate@4.15.1", "", { "dependencies": { "@vue/devtools-api": "^7.5.2", "type-fest": "^4.8.3" }, "peerDependencies": { "vue": "^3.4.26" } }, "sha512-DkFsiTwEKau8VIxyZBGdO6tOudD+QoUBPuHj3e6QFqmbfCRj1ArmYWue9lEp6jLSWBIw4XPlDLjFIZNLdRAMSg=="], @@ -3874,8 +3924,6 @@ "clean-css/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], - "concurrently/supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="], - "css-select/domhandler": ["domhandler@4.3.1", "", { "dependencies": { "domelementtype": "^2.2.0" } }, "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ=="], "css-select/domutils": ["domutils@2.8.0", "", { "dependencies": { "dom-serializer": "^1.0.1", "domelementtype": "^2.2.0", "domhandler": "^4.2.0" } }, "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A=="], @@ -4028,8 +4076,6 @@ "jest-worker/jest-util": ["jest-util@29.7.0", "", { "dependencies": { "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", "graceful-fs": "^4.2.9", "picomatch": "^2.2.3" } }, "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA=="], - "jest-worker/supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="], - "js-beautify/glob": ["glob@10.4.5", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg=="], "jsdom/parse5": ["parse5@7.3.0", "", { "dependencies": { "entities": "^6.0.0" } }, "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw=="], @@ -4074,6 +4120,8 @@ "nodemon/semver": ["semver@5.7.2", "", { "bin": { "semver": "bin/semver" } }, "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g=="], + "nodemon/supports-color": ["supports-color@5.5.0", "", { "dependencies": { "has-flag": "^3.0.0" } }, "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow=="], + "noise-curve-ed/sodium-universal": ["sodium-universal@5.0.1", "", { "dependencies": { "sodium-native": "^5.0.1" }, "peerDependencies": { "sodium-javascript": "~0.8.0" }, "optionalPeers": ["sodium-javascript"] }, "sha512-rv+aH+tnKB5H0MAc2UadHShLMslpJsc4wjdnHRtiSIEYpOetCgu8MS4ExQRia+GL/MK3uuCyZPeEsi+J3h+Q+Q=="], "nypm/consola": ["consola@3.4.2", "", {}, "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA=="], @@ -4106,6 +4154,10 @@ "safe-push-apply/isarray": ["isarray@2.0.5", "", {}, "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw=="], + "sass-embedded-all-unknown/sass": ["sass@1.93.3", "", { "dependencies": { "chokidar": "^4.0.0", "immutable": "^5.0.2", "source-map-js": ">=0.6.2 <2.0.0" }, "optionalDependencies": { "@parcel/watcher": "^2.4.1" }, "bin": { "sass": "sass.js" } }, "sha512-elOcIZRTM76dvxNAjqYrucTSI0teAF/L2Lv0s6f6b7FOwcwIuA357bIE871580AjHJuSvLIRUosgV+lIWx6Rgg=="], + + "sass-embedded-unknown-all/sass": ["sass@1.93.3", "", { "dependencies": { "chokidar": "^4.0.0", "immutable": "^5.0.2", "source-map-js": ">=0.6.2 <2.0.0" }, "optionalDependencies": { "@parcel/watcher": "^2.4.1" }, "bin": { "sass": "sass.js" } }, "sha512-elOcIZRTM76dvxNAjqYrucTSI0teAF/L2Lv0s6f6b7FOwcwIuA357bIE871580AjHJuSvLIRUosgV+lIWx6Rgg=="], + "schema-utils/ajv": ["ajv@8.17.1", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g=="], "seek-bzip/commander": ["commander@6.2.1", "", {}, "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA=="], @@ -4152,8 +4204,6 @@ "subscriptions-transport-ws/ws": ["ws@7.5.10", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ=="], - "supports-color/has-flag": ["has-flag@3.0.0", "", {}, "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw=="], - "supports-hyperlinks/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], "table/ajv": ["ajv@8.17.1", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g=="], @@ -4280,8 +4330,6 @@ "@jest/create-cache-key-function/@jest/types/@types/yargs": ["@types/yargs@17.0.33", "", { "dependencies": { "@types/yargs-parser": "*" } }, "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA=="], - "@jest/reporters/jest-worker/supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="], - "@jest/transform/write-file-atomic/signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="], "@swc/cli/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], @@ -4382,10 +4430,6 @@ "jest-environment-jsdom/jsdom/xml-name-validator": ["xml-name-validator@3.0.0", "", {}, "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw=="], - "jest-haste-map/jest-worker/supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="], - - "jest-runner/jest-worker/supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="], - "jest-worker/jest-util/@jest/types": ["@jest/types@29.6.3", "", { "dependencies": { "@jest/schemas": "^29.6.3", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", "@types/yargs": "^17.0.8", "chalk": "^4.0.0" } }, "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw=="], "jest-worker/jest-util/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], @@ -4412,6 +4456,8 @@ "nodemon/chokidar/readdirp": ["readdirp@3.6.0", "", { "dependencies": { "picomatch": "^2.2.1" } }, "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA=="], + "nodemon/supports-color/has-flag": ["has-flag@3.0.0", "", {}, "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw=="], + "noise-curve-ed/sodium-universal/sodium-native": ["sodium-native@5.0.9", "", { "dependencies": { "require-addon": "^1.1.0", "which-runtime": "^1.2.1" } }, "sha512-6fpu3d6zdrRpLhuV3CDIBO5g90KkgaeR+c3xvDDz0ZnDkAlqbbPhFW7zhMJfsskfZ9SuC3SvBbqvxcECkXRyKw=="], "pkg-dir/find-up/locate-path": ["locate-path@5.0.0", "", { "dependencies": { "p-locate": "^4.1.0" } }, "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g=="], @@ -4444,8 +4490,6 @@ "terser-webpack-plugin/jest-worker/@types/node": ["@types/node@18.19.130", "", { "dependencies": { "undici-types": "~5.26.4" } }, "sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg=="], - "terser-webpack-plugin/jest-worker/supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="], - "test-exclude/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], "typeorm/glob/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], @@ -4508,6 +4552,8 @@ "vue-apollo/chalk/escape-string-regexp": ["escape-string-regexp@1.0.5", "", {}, "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="], + "vue-apollo/chalk/supports-color": ["supports-color@5.5.0", "", { "dependencies": { "has-flag": "^3.0.0" } }, "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow=="], + "vue/@vue/compiler-dom/@vue/compiler-core": ["@vue/compiler-core@3.5.13", "", { "dependencies": { "@babel/parser": "^7.25.3", "@vue/shared": "3.5.13", "entities": "^4.5.0", "estree-walker": "^2.0.2", "source-map-js": "^1.2.0" } }, "sha512-oOdAkwqUfW1WqpwSYJce06wvt6HljgY3fGeM9NcVA1HaYOij3mZG9Rkysn0OHuyUAGMbEbARIpsG+LPVlBJ5/Q=="], "vue/@vue/compiler-sfc/@vue/compiler-core": ["@vue/compiler-core@3.5.13", "", { "dependencies": { "@babel/parser": "^7.25.3", "@vue/shared": "3.5.13", "entities": "^4.5.0", "estree-walker": "^2.0.2", "source-map-js": "^1.2.0" } }, "sha512-oOdAkwqUfW1WqpwSYJce06wvt6HljgY3fGeM9NcVA1HaYOij3mZG9Rkysn0OHuyUAGMbEbARIpsG+LPVlBJ5/Q=="], @@ -4594,6 +4640,8 @@ "vue-apollo/chalk/ansi-styles/color-convert": ["color-convert@1.9.3", "", { "dependencies": { "color-name": "1.1.3" } }, "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg=="], + "vue-apollo/chalk/supports-color/has-flag": ["has-flag@3.0.0", "", {}, "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw=="], + "web-resource-inliner/htmlparser2/domutils/dom-serializer": ["dom-serializer@1.4.1", "", { "dependencies": { "domelementtype": "^2.0.1", "domhandler": "^4.2.0", "entities": "^2.0.0" } }, "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag=="], "web-resource-inliner/htmlparser2/domutils/domhandler": ["domhandler@4.3.1", "", { "dependencies": { "domelementtype": "^2.2.0" } }, "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ=="], diff --git a/frontend/package.json b/frontend/package.json index ade408c16..31311f66f 100755 --- a/frontend/package.json +++ b/frontend/package.json @@ -103,7 +103,7 @@ "mock-apollo-client": "^1.2.1", "postcss-html": "^1.8.0", "prettier": "^3.5.3", - "sass": "^1.83.4", + "sass-embedded": "^1.93.2", "stylelint": "^16.19.1", "stylelint-config-recommended-vue": "^1.6.0", "stylelint-config-standard-scss": "^14.0.0", From 646723055f708252c0d9032c33875c54148f5b3c Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Sun, 30 Nov 2025 13:41:18 +0100 Subject: [PATCH 16/20] try grass for scss parsing in ci worker --- .github/workflows/test_e2e.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/test_e2e.yml b/.github/workflows/test_e2e.yml index 5d7e1f8be..942054a36 100644 --- a/.github/workflows/test_e2e.yml +++ b/.github/workflows/test_e2e.yml @@ -32,6 +32,9 @@ jobs: - name: Boot up test system | seed backend run: bun turbo seed --env-mode=loose + - name: Install grass + run: cargo install grass + - name: Boot up test system | docker-compose backend, frontend run: | cd backend From eb8a687895cc658626fc12f5cdc242e9b76fdf01 Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Sun, 30 Nov 2025 13:44:14 +0100 Subject: [PATCH 17/20] revert changes which don't speed up ci --- .github/workflows/test_e2e.yml | 3 --- admin/package.json | 2 +- bun.lock | 34 +++++++++++++++++++--------------- frontend/package.json | 2 +- 4 files changed, 21 insertions(+), 20 deletions(-) diff --git a/.github/workflows/test_e2e.yml b/.github/workflows/test_e2e.yml index 942054a36..5d7e1f8be 100644 --- a/.github/workflows/test_e2e.yml +++ b/.github/workflows/test_e2e.yml @@ -32,9 +32,6 @@ jobs: - name: Boot up test system | seed backend run: bun turbo seed --env-mode=loose - - name: Install grass - run: cargo install grass - - name: Boot up test system | docker-compose backend, frontend run: | cd backend diff --git a/admin/package.json b/admin/package.json index 848eb39bf..463162667 100644 --- a/admin/package.json +++ b/admin/package.json @@ -78,7 +78,7 @@ "mock-apollo-client": "^1.2.1", "postcss-html": "^1.8.0", "prettier": "^3.5.3", - "sass-embedded": "^1.93.2", + "sass": "^1.77.8", "stylelint": "^16.19.1", "stylelint-config-recommended-vue": "^1.6.0", "stylelint-config-standard-scss": "^14.0.0", diff --git a/bun.lock b/bun.lock index d7ce9fd0c..fa8cc8486 100644 --- a/bun.lock +++ b/bun.lock @@ -76,7 +76,7 @@ "mock-apollo-client": "^1.2.1", "postcss-html": "^1.8.0", "prettier": "^3.5.3", - "sass-embedded": "^1.93.2", + "sass": "^1.77.8", "stylelint": "^16.19.1", "stylelint-config-recommended-vue": "^1.6.0", "stylelint-config-standard-scss": "^14.0.0", @@ -428,7 +428,7 @@ "mock-apollo-client": "^1.2.1", "postcss-html": "^1.8.0", "prettier": "^3.5.3", - "sass-embedded": "^1.93.2", + "sass": "^1.83.4", "stylelint": "^16.19.1", "stylelint-config-recommended-vue": "^1.6.0", "stylelint-config-standard-scss": "^14.0.0", @@ -3074,7 +3074,7 @@ "safety-catch": ["safety-catch@1.0.2", "", {}, "sha512-C1UYVZ4dtbBxEtvOcpjBaaD27nP8MlvyAQEp2fOTOEe6pfUpk1cDUxij6BR1jZup6rSyUTaBBplK7LanskrULA=="], - "sass": ["sass@1.93.2", "", { "dependencies": { "chokidar": "^4.0.0", "immutable": "^5.0.2", "source-map-js": ">=0.6.2 <2.0.0" }, "optionalDependencies": { "@parcel/watcher": "^2.4.1" }, "bin": { "sass": "sass.js" } }, "sha512-t+YPtOQHpGW1QWsh1CHQ5cPIr9lbbGZLZnbihP/D/qZj/yuV68m8qarcV17nvkOX81BCrvzAlq2klCQFZghyTg=="], + "sass": ["sass@1.93.3", "", { "dependencies": { "chokidar": "^4.0.0", "immutable": "^5.0.2", "source-map-js": ">=0.6.2 <2.0.0" }, "optionalDependencies": { "@parcel/watcher": "^2.4.1" }, "bin": { "sass": "sass.js" } }, "sha512-elOcIZRTM76dvxNAjqYrucTSI0teAF/L2Lv0s6f6b7FOwcwIuA357bIE871580AjHJuSvLIRUosgV+lIWx6Rgg=="], "sass-embedded": ["sass-embedded@1.93.3", "", { "dependencies": { "@bufbuild/protobuf": "^2.5.0", "buffer-builder": "^0.2.0", "colorjs.io": "^0.5.0", "immutable": "^5.0.2", "rxjs": "^7.4.0", "supports-color": "^8.1.1", "sync-child-process": "^1.0.2", "varint": "^6.0.0" }, "optionalDependencies": { "sass-embedded-all-unknown": "1.93.3", "sass-embedded-android-arm": "1.93.3", "sass-embedded-android-arm64": "1.93.3", "sass-embedded-android-riscv64": "1.93.3", "sass-embedded-android-x64": "1.93.3", "sass-embedded-darwin-arm64": "1.93.3", "sass-embedded-darwin-x64": "1.93.3", "sass-embedded-linux-arm": "1.93.3", "sass-embedded-linux-arm64": "1.93.3", "sass-embedded-linux-musl-arm": "1.93.3", "sass-embedded-linux-musl-arm64": "1.93.3", "sass-embedded-linux-musl-riscv64": "1.93.3", "sass-embedded-linux-musl-x64": "1.93.3", "sass-embedded-linux-riscv64": "1.93.3", "sass-embedded-linux-x64": "1.93.3", "sass-embedded-unknown-all": "1.93.3", "sass-embedded-win32-arm64": "1.93.3", "sass-embedded-win32-x64": "1.93.3" }, "bin": { "sass": "dist/bin/sass.js" } }, "sha512-+VUy01yfDqNmIVMd/LLKl2TTtY0ovZN0rTonh+FhKr65mFwIYgU9WzgIZKS7U9/SPCQvWTsTGx9jyt+qRm/XFw=="], @@ -3276,7 +3276,7 @@ "superjson": ["superjson@2.2.2", "", { "dependencies": { "copy-anything": "^3.0.2" } }, "sha512-5JRxVqC8I8NuOUjzBbvVJAKNM8qoVuH0O77h4WInc/qC2q5IreqKxYwgkga3PfA22OayK2ikceb/B26dztPl+Q=="], - "supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="], + "supports-color": ["supports-color@5.5.0", "", { "dependencies": { "has-flag": "^3.0.0" } }, "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow=="], "supports-hyperlinks": ["supports-hyperlinks@3.2.0", "", { "dependencies": { "has-flag": "^4.0.0", "supports-color": "^7.0.0" } }, "sha512-zFObLMyZeEwzAoKCyu1B91U79K2t7ApXuQfo8OuxwXLDgcKxuwM+YvcbIhm6QWqz7mHUH1TVytR1PwVVjEuMig=="], @@ -3924,6 +3924,8 @@ "clean-css/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], + "concurrently/supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="], + "css-select/domhandler": ["domhandler@4.3.1", "", { "dependencies": { "domelementtype": "^2.2.0" } }, "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ=="], "css-select/domutils": ["domutils@2.8.0", "", { "dependencies": { "dom-serializer": "^1.0.1", "domelementtype": "^2.2.0", "domhandler": "^4.2.0" } }, "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A=="], @@ -4076,6 +4078,8 @@ "jest-worker/jest-util": ["jest-util@29.7.0", "", { "dependencies": { "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", "graceful-fs": "^4.2.9", "picomatch": "^2.2.3" } }, "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA=="], + "jest-worker/supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="], + "js-beautify/glob": ["glob@10.4.5", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg=="], "jsdom/parse5": ["parse5@7.3.0", "", { "dependencies": { "entities": "^6.0.0" } }, "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw=="], @@ -4120,8 +4124,6 @@ "nodemon/semver": ["semver@5.7.2", "", { "bin": { "semver": "bin/semver" } }, "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g=="], - "nodemon/supports-color": ["supports-color@5.5.0", "", { "dependencies": { "has-flag": "^3.0.0" } }, "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow=="], - "noise-curve-ed/sodium-universal": ["sodium-universal@5.0.1", "", { "dependencies": { "sodium-native": "^5.0.1" }, "peerDependencies": { "sodium-javascript": "~0.8.0" }, "optionalPeers": ["sodium-javascript"] }, "sha512-rv+aH+tnKB5H0MAc2UadHShLMslpJsc4wjdnHRtiSIEYpOetCgu8MS4ExQRia+GL/MK3uuCyZPeEsi+J3h+Q+Q=="], "nypm/consola": ["consola@3.4.2", "", {}, "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA=="], @@ -4154,9 +4156,7 @@ "safe-push-apply/isarray": ["isarray@2.0.5", "", {}, "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw=="], - "sass-embedded-all-unknown/sass": ["sass@1.93.3", "", { "dependencies": { "chokidar": "^4.0.0", "immutable": "^5.0.2", "source-map-js": ">=0.6.2 <2.0.0" }, "optionalDependencies": { "@parcel/watcher": "^2.4.1" }, "bin": { "sass": "sass.js" } }, "sha512-elOcIZRTM76dvxNAjqYrucTSI0teAF/L2Lv0s6f6b7FOwcwIuA357bIE871580AjHJuSvLIRUosgV+lIWx6Rgg=="], - - "sass-embedded-unknown-all/sass": ["sass@1.93.3", "", { "dependencies": { "chokidar": "^4.0.0", "immutable": "^5.0.2", "source-map-js": ">=0.6.2 <2.0.0" }, "optionalDependencies": { "@parcel/watcher": "^2.4.1" }, "bin": { "sass": "sass.js" } }, "sha512-elOcIZRTM76dvxNAjqYrucTSI0teAF/L2Lv0s6f6b7FOwcwIuA357bIE871580AjHJuSvLIRUosgV+lIWx6Rgg=="], + "sass-embedded/supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="], "schema-utils/ajv": ["ajv@8.17.1", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g=="], @@ -4204,6 +4204,8 @@ "subscriptions-transport-ws/ws": ["ws@7.5.10", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ=="], + "supports-color/has-flag": ["has-flag@3.0.0", "", {}, "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw=="], + "supports-hyperlinks/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], "table/ajv": ["ajv@8.17.1", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g=="], @@ -4330,6 +4332,8 @@ "@jest/create-cache-key-function/@jest/types/@types/yargs": ["@types/yargs@17.0.33", "", { "dependencies": { "@types/yargs-parser": "*" } }, "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA=="], + "@jest/reporters/jest-worker/supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="], + "@jest/transform/write-file-atomic/signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="], "@swc/cli/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], @@ -4430,6 +4434,10 @@ "jest-environment-jsdom/jsdom/xml-name-validator": ["xml-name-validator@3.0.0", "", {}, "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw=="], + "jest-haste-map/jest-worker/supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="], + + "jest-runner/jest-worker/supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="], + "jest-worker/jest-util/@jest/types": ["@jest/types@29.6.3", "", { "dependencies": { "@jest/schemas": "^29.6.3", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", "@types/yargs": "^17.0.8", "chalk": "^4.0.0" } }, "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw=="], "jest-worker/jest-util/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], @@ -4456,8 +4464,6 @@ "nodemon/chokidar/readdirp": ["readdirp@3.6.0", "", { "dependencies": { "picomatch": "^2.2.1" } }, "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA=="], - "nodemon/supports-color/has-flag": ["has-flag@3.0.0", "", {}, "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw=="], - "noise-curve-ed/sodium-universal/sodium-native": ["sodium-native@5.0.9", "", { "dependencies": { "require-addon": "^1.1.0", "which-runtime": "^1.2.1" } }, "sha512-6fpu3d6zdrRpLhuV3CDIBO5g90KkgaeR+c3xvDDz0ZnDkAlqbbPhFW7zhMJfsskfZ9SuC3SvBbqvxcECkXRyKw=="], "pkg-dir/find-up/locate-path": ["locate-path@5.0.0", "", { "dependencies": { "p-locate": "^4.1.0" } }, "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g=="], @@ -4490,6 +4496,8 @@ "terser-webpack-plugin/jest-worker/@types/node": ["@types/node@18.19.130", "", { "dependencies": { "undici-types": "~5.26.4" } }, "sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg=="], + "terser-webpack-plugin/jest-worker/supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="], + "test-exclude/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], "typeorm/glob/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], @@ -4552,8 +4560,6 @@ "vue-apollo/chalk/escape-string-regexp": ["escape-string-regexp@1.0.5", "", {}, "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="], - "vue-apollo/chalk/supports-color": ["supports-color@5.5.0", "", { "dependencies": { "has-flag": "^3.0.0" } }, "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow=="], - "vue/@vue/compiler-dom/@vue/compiler-core": ["@vue/compiler-core@3.5.13", "", { "dependencies": { "@babel/parser": "^7.25.3", "@vue/shared": "3.5.13", "entities": "^4.5.0", "estree-walker": "^2.0.2", "source-map-js": "^1.2.0" } }, "sha512-oOdAkwqUfW1WqpwSYJce06wvt6HljgY3fGeM9NcVA1HaYOij3mZG9Rkysn0OHuyUAGMbEbARIpsG+LPVlBJ5/Q=="], "vue/@vue/compiler-sfc/@vue/compiler-core": ["@vue/compiler-core@3.5.13", "", { "dependencies": { "@babel/parser": "^7.25.3", "@vue/shared": "3.5.13", "entities": "^4.5.0", "estree-walker": "^2.0.2", "source-map-js": "^1.2.0" } }, "sha512-oOdAkwqUfW1WqpwSYJce06wvt6HljgY3fGeM9NcVA1HaYOij3mZG9Rkysn0OHuyUAGMbEbARIpsG+LPVlBJ5/Q=="], @@ -4640,8 +4646,6 @@ "vue-apollo/chalk/ansi-styles/color-convert": ["color-convert@1.9.3", "", { "dependencies": { "color-name": "1.1.3" } }, "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg=="], - "vue-apollo/chalk/supports-color/has-flag": ["has-flag@3.0.0", "", {}, "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw=="], - "web-resource-inliner/htmlparser2/domutils/dom-serializer": ["dom-serializer@1.4.1", "", { "dependencies": { "domelementtype": "^2.0.1", "domhandler": "^4.2.0", "entities": "^2.0.0" } }, "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag=="], "web-resource-inliner/htmlparser2/domutils/domhandler": ["domhandler@4.3.1", "", { "dependencies": { "domelementtype": "^2.2.0" } }, "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ=="], diff --git a/frontend/package.json b/frontend/package.json index 31311f66f..ade408c16 100755 --- a/frontend/package.json +++ b/frontend/package.json @@ -103,7 +103,7 @@ "mock-apollo-client": "^1.2.1", "postcss-html": "^1.8.0", "prettier": "^3.5.3", - "sass-embedded": "^1.93.2", + "sass": "^1.83.4", "stylelint": "^16.19.1", "stylelint-config-recommended-vue": "^1.6.0", "stylelint-config-standard-scss": "^14.0.0", From a805fda1a50e3614ffe919ebed4dcd58dd73faa6 Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Sun, 30 Nov 2025 14:09:53 +0100 Subject: [PATCH 18/20] bundle custom type defs in root --- .../@types => @types}/@hyperswarm__dht/index.d.ts | 0 {backend/@types => @types}/klicktipp-api/index.d.ts | 0 {backend/@types => @types}/random-bigint/index.d.ts | 0 {backend/@types => @types}/sodium-native/index.d.ts | 0 backend/tsconfig.json | 2 +- core/tsconfig.json | 8 ++++++-- database/@types/random-bigint/index.d.ts | 5 ----- database/tsconfig.json | 6 +++++- dht-node/tsconfig.json | 4 ++-- federation/tsconfig.json | 1 + 10 files changed, 15 insertions(+), 11 deletions(-) rename {dht-node/src/dht_node/@types => @types}/@hyperswarm__dht/index.d.ts (100%) rename {backend/@types => @types}/klicktipp-api/index.d.ts (100%) rename {backend/@types => @types}/random-bigint/index.d.ts (100%) rename {backend/@types => @types}/sodium-native/index.d.ts (100%) delete mode 100644 database/@types/random-bigint/index.d.ts diff --git a/dht-node/src/dht_node/@types/@hyperswarm__dht/index.d.ts b/@types/@hyperswarm__dht/index.d.ts similarity index 100% rename from dht-node/src/dht_node/@types/@hyperswarm__dht/index.d.ts rename to @types/@hyperswarm__dht/index.d.ts diff --git a/backend/@types/klicktipp-api/index.d.ts b/@types/klicktipp-api/index.d.ts similarity index 100% rename from backend/@types/klicktipp-api/index.d.ts rename to @types/klicktipp-api/index.d.ts diff --git a/backend/@types/random-bigint/index.d.ts b/@types/random-bigint/index.d.ts similarity index 100% rename from backend/@types/random-bigint/index.d.ts rename to @types/random-bigint/index.d.ts diff --git a/backend/@types/sodium-native/index.d.ts b/@types/sodium-native/index.d.ts similarity index 100% rename from backend/@types/sodium-native/index.d.ts rename to @types/sodium-native/index.d.ts diff --git a/backend/tsconfig.json b/backend/tsconfig.json index 454d4853c..4cd3fc557 100644 --- a/backend/tsconfig.json +++ b/backend/tsconfig.json @@ -61,7 +61,7 @@ }, // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ "typeRoots": [ /* List of folders to include type definitions from. */ - "@types", + "../@types", "node_modules/@types", "../node_modules/@types", ], diff --git a/core/tsconfig.json b/core/tsconfig.json index 155a31a7b..711c21cc9 100644 --- a/core/tsconfig.json +++ b/core/tsconfig.json @@ -49,8 +49,12 @@ // "paths": { }, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ // "rootDirs": [".", "../database"], /* List of root folders whose combined content represents the structure of the project at runtime. */ /* List of folders to include type definitions from. */ - "typeRoots": ["./node_modules/@types", "../node_modules/@types"], - // "types": ["bun-types"], /* Type declaration files to be included in compilation. */ + "typeRoots": [ + "./node_modules/@types", + "../node_modules/@types", + "../@types" + ], + // "types": ["bun-types", "../@types"], /* Type declaration files to be included in compilation. */ // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ diff --git a/database/@types/random-bigint/index.d.ts b/database/@types/random-bigint/index.d.ts deleted file mode 100644 index 9692fcbf7..000000000 --- a/database/@types/random-bigint/index.d.ts +++ /dev/null @@ -1,5 +0,0 @@ - -declare module 'random-bigint' { - function random(bits: number, cb?: (err: Error, num: BigInt) => void): BigInt - export = random -} diff --git a/database/tsconfig.json b/database/tsconfig.json index 862e9bf94..bf09027c5 100644 --- a/database/tsconfig.json +++ b/database/tsconfig.json @@ -50,7 +50,11 @@ //"@/*": ["src/*"], /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ //}, // "rootDirs": [".", "../database"], /* List of root folders whose combined content represents the structure of the project at runtime. */ - "typeRoots": ["node_modules/@types"], /* List of folders to include type definitions from. */ + "typeRoots": [ + "./node_modules/@types", + "../node_modules/@types", + "../@types" + ], // "types": ["node"], /* Type declaration files to be included in compilation. */ // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ diff --git a/dht-node/tsconfig.json b/dht-node/tsconfig.json index 9628b7c41..8d979c82b 100644 --- a/dht-node/tsconfig.json +++ b/dht-node/tsconfig.json @@ -52,9 +52,9 @@ }, // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ "typeRoots": [ /* List of folders to include type definitions from. */ - "src/dht_node/@types", "node_modules/@types", - "../node_modules/@types" + "../node_modules/@types", + "../@types" ], // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ diff --git a/federation/tsconfig.json b/federation/tsconfig.json index 4082df448..a687b17a5 100644 --- a/federation/tsconfig.json +++ b/federation/tsconfig.json @@ -64,6 +64,7 @@ "typeRoots": [ /* List of folders to include type definitions from. */ "node_modules/@types", "../node_modules/@types", + "../@types" ], // "types": [], /* Type declaration files to be included in compilation. */ // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ From 4eb8a87fdd5f2f37fec11199b875bebc1da8af7e Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Sun, 30 Nov 2025 14:36:59 +0100 Subject: [PATCH 19/20] revert not neccessary changes, to reduce review noise --- .github/workflows/test_e2e.yml | 21 ++++++++++++++++--- backend/src/graphql/model/Transaction.ts | 4 ++-- .../graphql/resolver/ContributionResolver.ts | 7 ++++--- .../resolver/TransactionLinkResolver.ts | 11 +++++----- .../graphql/resolver/TransactionResolver.ts | 6 ++++-- .../src/graphql/resolver/UserResolver.test.ts | 6 +++--- .../AbstractUnconfirmedContribution.role.ts | 2 +- .../UnconfirmedContributionAdmin.role.ts | 2 +- ...nfirmedContributionAdminAddMessage.role.ts | 2 +- .../UnconfirmedContributionUser.role.ts | 2 +- ...onfirmedContributionUserAddMessage.role.ts | 2 +- backend/src/seeds/community/index.ts | 14 ++++++++++--- backend/src/util/virtualTransactions.ts | 3 ++- core/src/graphql/enum/TransactionTypeId.ts | 1 + .../src/graphql/logic/processXComSendCoins.ts | 14 ++++--------- core/src/util/utilities.ts | 2 +- database/migration/clear.ts | 2 -- database/package.json | 1 - database/src/seeds/factory/user.ts | 1 + 19 files changed, 62 insertions(+), 41 deletions(-) diff --git a/.github/workflows/test_e2e.yml b/.github/workflows/test_e2e.yml index 5d7e1f8be..a670e485d 100644 --- a/.github/workflows/test_e2e.yml +++ b/.github/workflows/test_e2e.yml @@ -30,7 +30,12 @@ jobs: sudo cp ./nginx/e2e-test.conf /etc/nginx/sites-available/default - name: Boot up test system | seed backend - run: bun turbo seed --env-mode=loose + run: bun turbo seed + + - name: Moving logs after seeding + run: | + mkdir -p /home/runner/work/gradido/gradido/logs/backend/seed + mv /home/runner/work/gradido/gradido/logs/backend/*.log /home/runner/work/gradido/gradido/logs/backend/seed/ - name: Boot up test system | docker-compose backend, frontend run: | @@ -130,7 +135,7 @@ jobs: sudo cp ./nginx/e2e-test.conf /etc/nginx/sites-available/default - name: Boot up test system | seed backend - run: bun turbo seed --env-mode=loose + run: bun turbo seed - name: copy test config run: | @@ -139,6 +144,11 @@ jobs: cd ../backend cp .env.test_e2e .env + - name: Moving logs after seeding + run: | + mkdir -p /home/runner/work/gradido/gradido/logs/backend/seed + mv /home/runner/work/gradido/gradido/logs/backend/*.log /home/runner/work/gradido/gradido/logs/backend/seed/ + - name: Boot up test system | docker-compose backend, frontend run: | bun turbo backend#build frontend#build --env-mode=loose @@ -210,7 +220,12 @@ jobs: sudo cp ./nginx/e2e-test.conf /etc/nginx/sites-available/default - name: Boot up test system | seed backend - run: bun turbo seed --env-mode=loose + run: bun turbo seed + + - name: Moving logs after seeding + run: | + mkdir -p /home/runner/work/gradido/gradido/logs/backend/seed + mv /home/runner/work/gradido/gradido/logs/backend/*.log /home/runner/work/gradido/gradido/logs/backend/seed/ - name: Boot up test system | docker-compose backend, frontend run: | diff --git a/backend/src/graphql/model/Transaction.ts b/backend/src/graphql/model/Transaction.ts index 312c67b15..0560cef54 100644 --- a/backend/src/graphql/model/Transaction.ts +++ b/backend/src/graphql/model/Transaction.ts @@ -1,8 +1,8 @@ -import { Transaction as dbTransaction, TransactionTypeId } from 'database' +import { Transaction as dbTransaction } from 'database' import { Decimal } from 'decimal.js-light' import { Field, Int, ObjectType } from 'type-graphql' -import { Decay } from 'core' +import { Decay, TransactionTypeId } from 'core' import { User } from './User' diff --git a/backend/src/graphql/resolver/ContributionResolver.ts b/backend/src/graphql/resolver/ContributionResolver.ts index 8faf03480..180c22cfb 100644 --- a/backend/src/graphql/resolver/ContributionResolver.ts +++ b/backend/src/graphql/resolver/ContributionResolver.ts @@ -1,7 +1,6 @@ import { Contribution as DbContribution, Transaction as DbTransaction, - TransactionTypeId, User as DbUser, DltTransaction as DbDltTransaction, UserContact, @@ -17,16 +16,19 @@ import { ContributionArgs } from '@arg/ContributionArgs' import { Paginated } from '@arg/Paginated' import { SearchContributionsFilterArgs } from '@arg/SearchContributionsFilterArgs' import { ContributionStatus } from '@enum/ContributionStatus' +import { ContributionType } from '@enum/ContributionType' import { AdminUpdateContribution } from '@model/AdminUpdateContribution' import { Contribution, ContributionListResult } from '@model/Contribution' import { OpenCreation } from '@model/OpenCreation' import { UnconfirmedContribution } from '@model/UnconfirmedContribution' import { RIGHTS } from '@/auth/RIGHTS' import { + fullName, sendContributionChangedByModeratorEmail, sendContributionConfirmedEmail, sendContributionDeletedEmail, sendContributionDeniedEmail, + TransactionTypeId } from 'core' import { EVENT_ADMIN_CONTRIBUTION_CONFIRM, @@ -42,11 +44,10 @@ import { UpdateUnconfirmedContributionContext } from '@/interactions/updateUncon import { LogError } from '@/server/LogError' import { Context, getClientTimezoneOffset, getUser } from '@/server/context' import { TRANSACTIONS_LOCK } from 'database' -import { calculateDecay, Decay, fullName } from 'shared' +import { calculateDecay, Decay } from 'shared' import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const' import { ContributionMessageType } from '@enum/ContributionMessageType' -import { ContributionType } from '@enum/ContributionType' import { AppDatabase } from 'database' import { getLogger } from 'log4js' import { diff --git a/backend/src/graphql/resolver/TransactionLinkResolver.ts b/backend/src/graphql/resolver/TransactionLinkResolver.ts index eac60b9e3..869104bae 100644 --- a/backend/src/graphql/resolver/TransactionLinkResolver.ts +++ b/backend/src/graphql/resolver/TransactionLinkResolver.ts @@ -3,15 +3,16 @@ import { randomBytes } from 'crypto' import { Paginated } from '@arg/Paginated' import { TransactionLinkArgs } from '@arg/TransactionLinkArgs' import { TransactionLinkFilters } from '@arg/TransactionLinkFilters' -import { ContributionType } from '@enum/ContributionType' +import { ContributionCycleType } from '@enum/ContributionCycleType' import { ContributionStatus } from '@enum/ContributionStatus' +import { ContributionType } from '@enum/ContributionType' import { Community } from '@model/Community' import { ContributionLink } from '@model/ContributionLink' import { RedeemJwtLink } from '@model/RedeemJwtLink' import { TransactionLink, TransactionLinkResult } from '@model/TransactionLink' import { User } from '@model/User' import { QueryLinkResult } from '@union/QueryLinkResult' -import { Decay, interpretEncryptedTransferArgs, EncryptedTransferArgs } from 'core' +import { Decay, interpretEncryptedTransferArgs, TransactionTypeId } from 'core' import { AppDatabase, Contribution as DbContribution, ContributionLink as DbContributionLink, @@ -19,13 +20,11 @@ import { DltTransaction as DbDltTransaction, Transaction as DbTransaction, TransactionLink as DbTransactionLink, - TransactionTypeId, User as DbUser, findModeratorCreatingContributionLink, findTransactionLinkByCode, getHomeCommunity } from 'database' -import { ContributionCycleType } from '@/graphql/enum/ContributionCycleType' import { Decimal } from 'decimal.js-light' import { Arg, Args, Authorized, Ctx, Int, Mutation, Query, Resolver } from 'type-graphql' @@ -39,6 +38,7 @@ import { import { LogError } from '@/server/LogError' import { Context, getClientTimezoneOffset, getUser } from '@/server/context' import { calculateBalance } from '@/util/validate' +import { fullName } from 'core' import { TRANSACTION_LINK_LOCK, TRANSACTIONS_LOCK } from 'database' import { calculateDecay, @@ -53,6 +53,7 @@ import { import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const' import { DisbursementClient as V1_0_DisbursementClient } from '@/federation/client/1_0/DisbursementClient' import { DisbursementClientFactory } from '@/federation/client/DisbursementClientFactory' +import { EncryptedTransferArgs } from 'core' import { getLastTransaction } from 'database' import { getLogger, Logger } from 'log4js' import { randombytes_random } from 'sodium-native' @@ -64,7 +65,7 @@ import { } from './util/communities' import { getUserCreation, validateContribution } from './util/creations' import { transactionLinkList } from './util/transactionLinkList' -import { fullName, SignedTransferPayloadType } from 'shared' +import { SignedTransferPayloadType } from 'shared' import { contributionTransaction, deferredTransferTransaction, redeemDeferredTransferTransaction } from '@/apis/dltConnector' import { CODE_VALID_DAYS_DURATION } from './const/const' diff --git a/backend/src/graphql/resolver/TransactionResolver.ts b/backend/src/graphql/resolver/TransactionResolver.ts index c82eabf8b..923971743 100644 --- a/backend/src/graphql/resolver/TransactionResolver.ts +++ b/backend/src/graphql/resolver/TransactionResolver.ts @@ -18,9 +18,11 @@ import { Transaction } from '@model/Transaction' import { TransactionList } from '@model/TransactionList' import { User } from '@model/User' import { + fullName, processXComCompleteTransaction, sendTransactionLinkRedeemedEmail, sendTransactionReceivedEmail, + TransactionTypeId } from 'core' import { RIGHTS } from '@/auth/RIGHTS' import { CONFIG } from '@/config' @@ -31,10 +33,10 @@ import { Context, getUser } from '@/server/context' import { communityUser } from '@/util/communityUser' import { calculateBalance } from '@/util/validate' import { virtualDecayTransaction, virtualLinkTransaction } from '@/util/virtualTransactions' -import { fullName } from 'shared' +import { TRANSACTIONS_LOCK } from 'database' import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const' -import { getLastTransaction, TRANSACTIONS_LOCK, TransactionTypeId } from 'database' +import { getLastTransaction } from 'database' import { getLogger, Logger } from 'log4js' import { BalanceResolver } from './BalanceResolver' import { GdtResolver } from './GdtResolver' diff --git a/backend/src/graphql/resolver/UserResolver.test.ts b/backend/src/graphql/resolver/UserResolver.test.ts index b64b66370..e19eff8c5 100644 --- a/backend/src/graphql/resolver/UserResolver.test.ts +++ b/backend/src/graphql/resolver/UserResolver.test.ts @@ -67,7 +67,7 @@ import { printTimeDuration } from '@/util/time' import { objectValuesToArray } from 'core' import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const' -import { clearLogs, getLogger, printLogs } from 'config-schema/test/testSetup' +import { getLogger } from 'config-schema/test/testSetup' import { Location2Point } from './util/Location2Point' jest.mock('@/apis/humhub/HumHubClient') @@ -738,7 +738,7 @@ describe('UserResolver', () => { hasElopage: false, hideAmountGDD: false, hideAmountGDT: false, - humhubAllowed: false, + humhubAllowed: true, humhubPublishName: 'PUBLISH_NAME_ALIAS_OR_INITALS', klickTipp: { newsletterState: false, @@ -1610,7 +1610,7 @@ describe('UserResolver', () => { hasElopage: false, hideAmountGDD: false, hideAmountGDT: false, - humhubAllowed: false, + humhubAllowed: true, humhubPublishName: 'PUBLISH_NAME_ALIAS_OR_INITALS', klickTipp: { newsletterState: false, diff --git a/backend/src/interactions/updateUnconfirmedContribution/AbstractUnconfirmedContribution.role.ts b/backend/src/interactions/updateUnconfirmedContribution/AbstractUnconfirmedContribution.role.ts index c3bed06ab..dd85e3fb6 100644 --- a/backend/src/interactions/updateUnconfirmedContribution/AbstractUnconfirmedContribution.role.ts +++ b/backend/src/interactions/updateUnconfirmedContribution/AbstractUnconfirmedContribution.role.ts @@ -1,10 +1,10 @@ import { Contribution, User } from 'database' import { Decimal } from 'decimal.js-light' -import { ContributionStatus } from '@enum/ContributionStatus' import { Role } from '@/auth/Role' import { ContributionLogic } from '@/data/Contribution.logic' import { ContributionMessageBuilder } from '@/data/ContributionMessage.builder' +import { ContributionStatus } from '@/graphql/enum/ContributionStatus' import { LogError } from '@/server/LogError' import { Context, getClientTimezoneOffset } from '@/server/context' import { Logger, getLogger } from 'log4js' diff --git a/backend/src/interactions/updateUnconfirmedContribution/UnconfirmedContributionAdmin.role.ts b/backend/src/interactions/updateUnconfirmedContribution/UnconfirmedContributionAdmin.role.ts index 368abf461..f160966d3 100644 --- a/backend/src/interactions/updateUnconfirmedContribution/UnconfirmedContributionAdmin.role.ts +++ b/backend/src/interactions/updateUnconfirmedContribution/UnconfirmedContributionAdmin.role.ts @@ -1,10 +1,10 @@ import { Contribution, User } from 'database' -import { ContributionStatus } from '@enum/ContributionStatus' import { RIGHTS } from '@/auth/RIGHTS' import { Role } from '@/auth/Role' import { ContributionMessageBuilder } from '@/data/ContributionMessage.builder' import { AdminUpdateContributionArgs } from '@/graphql/arg/AdminUpdateContributionArgs' +import { ContributionStatus } from '@/graphql/enum/ContributionStatus' import { LogError } from '@/server/LogError' import { AbstractUnconfirmedContributionRole } from './AbstractUnconfirmedContribution.role' diff --git a/backend/src/interactions/updateUnconfirmedContribution/UnconfirmedContributionAdminAddMessage.role.ts b/backend/src/interactions/updateUnconfirmedContribution/UnconfirmedContributionAdminAddMessage.role.ts index 887c2d7ad..dcc10091f 100644 --- a/backend/src/interactions/updateUnconfirmedContribution/UnconfirmedContributionAdminAddMessage.role.ts +++ b/backend/src/interactions/updateUnconfirmedContribution/UnconfirmedContributionAdminAddMessage.role.ts @@ -1,11 +1,11 @@ import { Contribution, User } from 'database' -import { ContributionStatus } from '@enum/ContributionStatus' import { RIGHTS } from '@/auth/RIGHTS' import { Role } from '@/auth/Role' import { ContributionMessageBuilder } from '@/data/ContributionMessage.builder' import { ContributionMessageArgs } from '@/graphql/arg/ContributionMessageArgs' import { ContributionMessageType } from '@/graphql/enum/ContributionMessageType' +import { ContributionStatus } from '@/graphql/enum/ContributionStatus' import { LogError } from '@/server/LogError' import { AbstractUnconfirmedContributionRole } from './AbstractUnconfirmedContribution.role' diff --git a/backend/src/interactions/updateUnconfirmedContribution/UnconfirmedContributionUser.role.ts b/backend/src/interactions/updateUnconfirmedContribution/UnconfirmedContributionUser.role.ts index 8dee35b2c..6955cbfa7 100644 --- a/backend/src/interactions/updateUnconfirmedContribution/UnconfirmedContributionUser.role.ts +++ b/backend/src/interactions/updateUnconfirmedContribution/UnconfirmedContributionUser.role.ts @@ -1,8 +1,8 @@ import { Contribution, User } from 'database' -import { ContributionStatus } from '@enum/ContributionStatus' import { ContributionMessageBuilder } from '@/data/ContributionMessage.builder' import { ContributionArgs } from '@/graphql/arg/ContributionArgs' +import { ContributionStatus } from '@/graphql/enum/ContributionStatus' import { LogError } from '@/server/LogError' import { AbstractUnconfirmedContributionRole } from './AbstractUnconfirmedContribution.role' diff --git a/backend/src/interactions/updateUnconfirmedContribution/UnconfirmedContributionUserAddMessage.role.ts b/backend/src/interactions/updateUnconfirmedContribution/UnconfirmedContributionUserAddMessage.role.ts index 319639f12..0440762f3 100644 --- a/backend/src/interactions/updateUnconfirmedContribution/UnconfirmedContributionUserAddMessage.role.ts +++ b/backend/src/interactions/updateUnconfirmedContribution/UnconfirmedContributionUserAddMessage.role.ts @@ -1,9 +1,9 @@ import { Contribution, User } from 'database' -import { ContributionStatus } from '@enum/ContributionStatus' import { ContributionMessageBuilder } from '@/data/ContributionMessage.builder' import { ContributionMessageArgs } from '@/graphql/arg/ContributionMessageArgs' import { ContributionMessageType } from '@/graphql/enum/ContributionMessageType' +import { ContributionStatus } from '@/graphql/enum/ContributionStatus' import { LogError } from '@/server/LogError' import { AbstractUnconfirmedContributionRole } from './AbstractUnconfirmedContribution.role' diff --git a/backend/src/seeds/community/index.ts b/backend/src/seeds/community/index.ts index 0d3b44d88..d51eafc31 100644 --- a/backend/src/seeds/community/index.ts +++ b/backend/src/seeds/community/index.ts @@ -1,19 +1,27 @@ import { Community as DbCommunity } from 'database' +import { v4 as uuidv4 } from 'uuid' import { CONFIG } from '@/config' - export async function writeHomeCommunityEntry(): Promise { try { // check for existing homeCommunity entry let homeCom = await DbCommunity.findOne({ where: { foreign: false } }) - if (!homeCom) { + if (homeCom) { + // simply update the existing entry, but it MUST keep the ID and UUID because of possible relations + homeCom.publicKey = Buffer.from('public-key-data-seeding') // keyPair.publicKey + // homeCom.privateKey = keyPair.secretKey + homeCom.url = 'http://localhost/api/' + homeCom.name = CONFIG.COMMUNITY_NAME + homeCom.description = CONFIG.COMMUNITY_DESCRIPTION + await DbCommunity.save(homeCom) + } else { // insert a new homecommunity entry including a new ID and a new but ensured unique UUID homeCom = new DbCommunity() homeCom.foreign = false homeCom.publicKey = Buffer.from('public-key-data-seeding') // keyPair.publicKey // homeCom.privateKey = keyPair.secretKey - homeCom.communityUuid = 'beac216d-73ae-427f-9678-0209af4936ce' // await newCommunityUuid() + homeCom.communityUuid = uuidv4() // await newCommunityUuid() homeCom.url = 'http://localhost/api/' homeCom.name = CONFIG.COMMUNITY_NAME homeCom.description = CONFIG.COMMUNITY_DESCRIPTION diff --git a/backend/src/util/virtualTransactions.ts b/backend/src/util/virtualTransactions.ts index c54e265cd..a3bbbe042 100644 --- a/backend/src/util/virtualTransactions.ts +++ b/backend/src/util/virtualTransactions.ts @@ -1,7 +1,8 @@ -import { Transaction as dbTransaction, TransactionTypeId } from 'database' +import { Transaction as dbTransaction } from 'database' import { Decimal } from 'decimal.js-light' import { RemoveOptions, SaveOptions } from 'typeorm' +import { TransactionTypeId } from 'core' import { Transaction } from '@model/Transaction' import { User } from '@model/User' diff --git a/core/src/graphql/enum/TransactionTypeId.ts b/core/src/graphql/enum/TransactionTypeId.ts index 740a93d5b..c6c188c5f 100644 --- a/core/src/graphql/enum/TransactionTypeId.ts +++ b/core/src/graphql/enum/TransactionTypeId.ts @@ -1,5 +1,6 @@ import { registerEnumType } from 'type-graphql' import { TransactionTypeId } from 'database' +export { TransactionTypeId } registerEnumType(TransactionTypeId, { name: 'TransactionTypeId', // this one is mandatory diff --git a/core/src/graphql/logic/processXComSendCoins.ts b/core/src/graphql/logic/processXComSendCoins.ts index 51ddcda73..bdbf24928 100644 --- a/core/src/graphql/logic/processXComSendCoins.ts +++ b/core/src/graphql/logic/processXComSendCoins.ts @@ -10,28 +10,22 @@ import { findUserByIdentifier, getCommunityByUuid, PendingTransactionLoggingView, - UserLoggingView, - TransactionTypeId, + UserLoggingView } from 'database' import { Decimal } from 'decimal.js-light' import { CONFIG as CONFIG_CORE } from '../../config' import { LOG4JS_BASE_CATEGORY_NAME } from '../../config/const' -import { - encryptAndSign, - fullName, - PendingTransactionState, - SendCoinsJwtPayloadType, - SendCoinsResponseJwtPayloadType, - verifyAndDecrypt -} from 'shared' +import { encryptAndSign, PendingTransactionState, SendCoinsJwtPayloadType, SendCoinsResponseJwtPayloadType, verifyAndDecrypt } from 'shared' import { SendCoinsClient as V1_0_SendCoinsClient } from '../../federation/client/1_0/SendCoinsClient' import { SendCoinsResult } from '../../federation/client/1_0/model/SendCoinsResult' import { SendCoinsClientFactory } from '../../federation/client/SendCoinsClientFactory' +import { TransactionTypeId } from '../../graphql/enum/TransactionTypeId' // import { LogError } from '@server/LogError' import { getLogger } from 'log4js' import { calculateSenderBalance } from '../../util/calculateSenderBalance' +import { fullName } from '../../util/utilities' import { randombytes_random } from 'sodium-native' import { SendCoinsResultLoggingView } from '../../federation/client/1_0/logging/SendCoinsResultLogging.view' diff --git a/core/src/util/utilities.ts b/core/src/util/utilities.ts index 09fd2f343..cfec3d37a 100644 --- a/core/src/util/utilities.ts +++ b/core/src/util/utilities.ts @@ -2,6 +2,7 @@ import { promisify } from 'util' import { Decimal } from 'decimal.js-light' import { i18n } from '../locales/localization' +export { fullName } from 'shared' export const objectValuesToArray = (obj: Record): string[] => Object.keys(obj).map((key) => obj[key]) @@ -15,7 +16,6 @@ export const decimalSeparatorByLanguage = (a: Decimal, language: string): string } // Function to reset an interface by chatGPT - export function resetInterface>(obj: T): T { // Iterate over all properties of the object for (const key in obj) { diff --git a/database/migration/clear.ts b/database/migration/clear.ts index 9c2f5b364..a78d35890 100644 --- a/database/migration/clear.ts +++ b/database/migration/clear.ts @@ -4,8 +4,6 @@ import { connectToDatabaseServer } from './prepare' import { MIGRATIONS_TABLE } from '../src/config/const' export async function truncateTables(connection: Connection) { - const databaseName = CONFIG.DB_DATABASE - await connection.query(`USE \`${databaseName}\``) const [tables] = await connection.query('SHOW TABLES') const tableNames = (tables as any[]).map((table) => Object.values(table)[0]) diff --git a/database/package.json b/database/package.json index ada327ba9..03ba57869 100644 --- a/database/package.json +++ b/database/package.json @@ -25,7 +25,6 @@ "up": "cross-env TZ=UTC tsx migration/index.ts up", "down": "cross-env TZ=UTC tsx migration/index.ts down", "reset": "cross-env TZ=UTC tsx migration/index.ts reset", - "seed": "cross-env TZ=UTC NODE_ENV=development bun src/seeds/seed.ts", "up:test": "cross-env TZ=UTC DB_DATABASE=gradido_test tsx migration/index.ts up", "up:backend_test": "cross-env TZ=UTC DB_DATABASE=gradido_test_backend tsx migration/index.ts up", "up:federation_test": "cross-env TZ=UTC DB_DATABASE=gradido_test_federation tsx migration/index.ts up", diff --git a/database/src/seeds/factory/user.ts b/database/src/seeds/factory/user.ts index 009c007df..4d16c009e 100644 --- a/database/src/seeds/factory/user.ts +++ b/database/src/seeds/factory/user.ts @@ -82,6 +82,7 @@ export async function createUser(user: UserInterface, homeCommunity?: Community dbUser.createdAt = user.createdAt ?? new Date() dbUser.deletedAt = user.deletedAt ?? null dbUser.publisherId = user.publisherId ?? 0 + dbUser.humhubAllowed = true dbUser.gradidoID = v4() if (user.emailChecked) { From 4428cb7b0c9c2a525a834edaa0edf982838a5f8e Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Sun, 30 Nov 2025 14:58:00 +0100 Subject: [PATCH 20/20] remove changes --- backend/turbo.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/backend/turbo.json b/backend/turbo.json index fb847307f..399bfa6ba 100644 --- a/backend/turbo.json +++ b/backend/turbo.json @@ -1,16 +1,16 @@ { "extends": ["//"], - "tasks": { - "seed": { + "tasks": { + "seed": { "dependsOn": ["database#up", "^build"], "cache": false - }, + }, "locales": {}, "locales:fix": {}, "lint": { }, "lint:fix": { - }, + }, "test": { "dependsOn": ["database#up:backend_test", "^build"] },