diff --git a/backend/src/graphql/resolver/ContributionLinkResolver.test.ts b/backend/src/graphql/resolver/ContributionLinkResolver.test.ts index 9db6a7d99..fa855f4b0 100644 --- a/backend/src/graphql/resolver/ContributionLinkResolver.test.ts +++ b/backend/src/graphql/resolver/ContributionLinkResolver.test.ts @@ -423,13 +423,13 @@ describe('Contribution Links', () => { ]) }) - it('returns an error if memo is longer than 255 characters', async () => { + it('returns an error if memo is longer than 512 characters', async () => { jest.clearAllMocks() const { errors: errorObjects } = await mutate({ mutation: createContributionLink, variables: { ...variables, - memo: '1234567890123456789212345678931234567894123456789512345678961234567897123456789812345678991234567890123456789012345678921234567893123456789412345678951234567896123456789712345678981234567899123456789012345678901234567892123456789312345678941234567895123456', + memo: '123456789012345678921234567893123456789412345678951234567896123456789712345678981234567899123456789012345678901234567892123456789312345678941234567895123456789612345678971234567898123456789912345678901234567890123456789212345678931234567894123456789512345612345678901234567892123456789312345678941234567895123456789612345678971234567898123456789912345678901234567890123456789212345678931234567894123456789512345678961234567897123456789812345678991234567890123456789012345678921234567893123456789412345678951234567', }, }) expect(errorObjects).toMatchObject([ @@ -441,7 +441,7 @@ describe('Contribution Links', () => { { property: 'memo', constraints: { - maxLength: 'memo must be shorter than or equal to 255 characters', + maxLength: 'memo must be shorter than or equal to 512 characters', }, }, ], diff --git a/backend/src/graphql/resolver/ContributionResolver.test.ts b/backend/src/graphql/resolver/ContributionResolver.test.ts index 1bb3b08b7..14dfa614f 100644 --- a/backend/src/graphql/resolver/ContributionResolver.test.ts +++ b/backend/src/graphql/resolver/ContributionResolver.test.ts @@ -229,14 +229,14 @@ describe('ContributionResolver', () => { ]) }) - it('throws error when memo length greater than 255 chars', async () => { + it('throws error when memo length greater than 512 chars', async () => { jest.clearAllMocks() const date = new Date() const { errors: errorObjects } = await mutate({ mutation: createContribution, variables: { amount: 100.0, - memo: 'Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test', + memo: 'Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test', contributionDate: date.toString(), }, }) @@ -249,7 +249,7 @@ describe('ContributionResolver', () => { { property: 'memo', constraints: { - maxLength: 'memo must be shorter than or equal to 255 characters', + maxLength: 'memo must be shorter than or equal to 512 characters', }, }, ], @@ -398,7 +398,7 @@ describe('ContributionResolver', () => { }) }) - describe('Memo length greater than 255 chars', () => { + describe('Memo length greater than 512 chars', () => { it('throws error', async () => { jest.clearAllMocks() const date = new Date() @@ -407,7 +407,7 @@ describe('ContributionResolver', () => { variables: { contributionId: pendingContribution.data.createContribution.id, amount: 100.0, - memo: 'Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test', + memo: 'Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test', contributionDate: date.toString(), }, }) @@ -420,7 +420,7 @@ describe('ContributionResolver', () => { { property: 'memo', constraints: { - maxLength: 'memo must be shorter than or equal to 255 characters', + maxLength: 'memo must be shorter than or equal to 512 characters', }, }, ], diff --git a/backend/src/graphql/resolver/TransactionLinkResolver.test.ts b/backend/src/graphql/resolver/TransactionLinkResolver.test.ts index 7862f71f0..575a522b2 100644 --- a/backend/src/graphql/resolver/TransactionLinkResolver.test.ts +++ b/backend/src/graphql/resolver/TransactionLinkResolver.test.ts @@ -187,7 +187,7 @@ describe('TransactionLinkResolver', () => { variables: { identifier: 'peter@lustig.de', amount: 100, - memo: 'test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test t', + memo: 'test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test', }, }) expect(errorObjects).toMatchObject([ @@ -199,7 +199,7 @@ describe('TransactionLinkResolver', () => { { property: 'memo', constraints: { - maxLength: 'memo must be shorter than or equal to 255 characters', + maxLength: 'memo must be shorter than or equal to 512 characters', }, }, ], diff --git a/backend/src/graphql/resolver/TransactionResolver.test.ts b/backend/src/graphql/resolver/TransactionResolver.test.ts index 275ae77fd..ff786681b 100644 --- a/backend/src/graphql/resolver/TransactionResolver.test.ts +++ b/backend/src/graphql/resolver/TransactionResolver.test.ts @@ -269,7 +269,7 @@ describe('send coins', () => { recipientCommunityIdentifier: homeCom.communityUuid, recipientIdentifier: 'peter@lustig.de', amount: 100, - memo: 'test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test t', + memo: 'test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test', }, }) expect(errorObjects).toMatchObject([ @@ -281,7 +281,7 @@ describe('send coins', () => { { property: 'memo', constraints: { - maxLength: 'memo must be shorter than or equal to 255 characters', + maxLength: 'memo must be shorter than or equal to 512 characters', }, }, ], diff --git a/backend/src/graphql/resolver/const/const.ts b/backend/src/graphql/resolver/const/const.ts index 2d4532cf5..8497ca6d5 100644 --- a/backend/src/graphql/resolver/const/const.ts +++ b/backend/src/graphql/resolver/const/const.ts @@ -8,7 +8,7 @@ export const FULL_CREATION_AVAILABLE = [ ] export const CONTRIBUTIONLINK_NAME_MAX_CHARS = 100 export const CONTRIBUTIONLINK_NAME_MIN_CHARS = 5 -export const MEMO_MAX_CHARS = 255 +export const MEMO_MAX_CHARS = 512 export const MEMO_MIN_CHARS = 5 export const DEFAULT_PAGINATION_PAGE_SIZE = 25 export const FRONTEND_CONTRIBUTIONS_ITEM_ANCHOR_PREFIX = 'contributionListItem-' diff --git a/database/migration/migrations/0093-increase_memo_to_512.ts b/database/migration/migrations/0093-increase_memo_to_512.ts new file mode 100644 index 000000000..db953d328 --- /dev/null +++ b/database/migration/migrations/0093-increase_memo_to_512.ts @@ -0,0 +1,20 @@ +/* MIGRATION TO INCREASE memo TO 512 in all tables which have a memo field + * + * This migration increases the memo field in all tables which have a memo field to 512 + */ + +export async function upgrade(queryFn: (query: string, values?: any[]) => Promise>) { + await queryFn('ALTER TABLE `contributions` MODIFY COLUMN `memo` varchar(512) NOT NULL;') + await queryFn('ALTER TABLE `contribution_links` MODIFY COLUMN `memo` varchar(512) NOT NULL;') + await queryFn('ALTER TABLE `pending_transactions` MODIFY COLUMN `memo` varchar(512) NOT NULL;') + await queryFn('ALTER TABLE `transactions` MODIFY COLUMN `memo` varchar(512) NOT NULL;') + await queryFn('ALTER TABLE `transaction_links` MODIFY COLUMN `memo` varchar(512) NOT NULL;') +} + +export async function downgrade(queryFn: (query: string, values?: any[]) => Promise>) { + await queryFn('ALTER TABLE `contributions` MODIFY COLUMN `memo` varchar(255) NOT NULL;') + await queryFn('ALTER TABLE `contribution_links` MODIFY COLUMN `memo` varchar(255) NOT NULL;') + await queryFn('ALTER TABLE `pending_transactions` MODIFY COLUMN `memo` varchar(255) NOT NULL;') + await queryFn('ALTER TABLE `transactions` MODIFY COLUMN `memo` varchar(255) NOT NULL;') + await queryFn('ALTER TABLE `transaction_links` MODIFY COLUMN `memo` varchar(255) NOT NULL;') +} diff --git a/database/src/entity/Contribution.ts b/database/src/entity/Contribution.ts index 53ec9f36f..976385263 100644 --- a/database/src/entity/Contribution.ts +++ b/database/src/entity/Contribution.ts @@ -39,7 +39,7 @@ export class Contribution extends BaseEntity { @Column({ type: 'datetime', nullable: false, name: 'contribution_date' }) contributionDate: Date - @Column({ type: 'varchar', length: 255, nullable: false, collation: 'utf8mb4_unicode_ci' }) + @Column({ type: 'varchar', length: 512, nullable: false, collation: 'utf8mb4_unicode_ci' }) memo: string @Column({ diff --git a/database/src/entity/ContributionLink.ts b/database/src/entity/ContributionLink.ts index fd66c8946..f8f1e96c6 100644 --- a/database/src/entity/ContributionLink.ts +++ b/database/src/entity/ContributionLink.ts @@ -10,7 +10,7 @@ export class ContributionLink extends BaseEntity { @Column({ type: 'varchar', length: 100, nullable: false, collation: 'utf8mb4_unicode_ci' }) name: string - @Column({ type: 'varchar', length: 255, nullable: false, collation: 'utf8mb4_unicode_ci' }) + @Column({ type: 'varchar', length: 512, nullable: false, collation: 'utf8mb4_unicode_ci' }) memo: string @Column({ name: 'valid_from', type: 'datetime', nullable: false }) diff --git a/database/src/entity/PendingTransaction.ts b/database/src/entity/PendingTransaction.ts index 71d3b5f30..58ba5a891 100644 --- a/database/src/entity/PendingTransaction.ts +++ b/database/src/entity/PendingTransaction.ts @@ -71,7 +71,7 @@ export class PendingTransaction extends BaseEntity { }) decayStart: Date | null - @Column({ type: 'varchar', length: 255, nullable: false, collation: 'utf8mb4_unicode_ci' }) + @Column({ type: 'varchar', length: 512, nullable: false, collation: 'utf8mb4_unicode_ci' }) memo: string @Column({ name: 'creation_date', type: 'datetime', precision: 3, nullable: true, default: null }) diff --git a/database/src/entity/Transaction.ts b/database/src/entity/Transaction.ts index b7d83bdf1..7a09c3027 100644 --- a/database/src/entity/Transaction.ts +++ b/database/src/entity/Transaction.ts @@ -70,7 +70,7 @@ export class Transaction extends BaseEntity { }) decayStart: Date | null - @Column({ type: 'varchar', length: 255, nullable: false, collation: 'utf8mb4_unicode_ci' }) + @Column({ type: 'varchar', length: 512, nullable: false, collation: 'utf8mb4_unicode_ci' }) memo: string @Column({ name: 'creation_date', type: 'datetime', precision: 3, nullable: true, default: null }) diff --git a/database/src/entity/TransactionLink.ts b/database/src/entity/TransactionLink.ts index e1ccfa675..e21e1266b 100644 --- a/database/src/entity/TransactionLink.ts +++ b/database/src/entity/TransactionLink.ts @@ -29,7 +29,7 @@ export class TransactionLink extends BaseEntity { }) holdAvailableAmount: Decimal - @Column({ type: 'varchar', length: 255, nullable: false, collation: 'utf8mb4_unicode_ci' }) + @Column({ type: 'varchar', length: 512, nullable: false, collation: 'utf8mb4_unicode_ci' }) memo: string @Column({ type: 'varchar', length: 24, nullable: false, collation: 'utf8mb4_unicode_ci' }) diff --git a/database/src/queries/user.ts b/database/src/queries/user.ts index b968e9433..da57053d7 100644 --- a/database/src/queries/user.ts +++ b/database/src/queries/user.ts @@ -49,6 +49,10 @@ export const findUserByIdentifier = async ( const user = userContact.user user.emailContact = userContact return user + } else { + // should don't happen often, so we create only in the rare case a logger for it + getLogger(`${LOG4JS_QUERIES_CATEGORY_NAME}.user.findUserByIdentifier`).warn("Couldn't find user by email in user_contacts", identifier) + return null } } else if (aliasSchema.safeParse(identifier).success) { return await DbUser.findOne({ diff --git a/frontend/src/components/Contributions/ContributionForm.vue b/frontend/src/components/Contributions/ContributionForm.vue index f4ea3b7cc..22377cb01 100644 --- a/frontend/src/components/Contributions/ContributionForm.vue +++ b/frontend/src/components/Contributions/ContributionForm.vue @@ -161,7 +161,7 @@ const validationSchema = computed(() => { })), // date cannot be in the future memo: string() .min(5, ({ min }) => ({ key: 'form.validation.contributionMemo.min', values: { min } })) - .max(255, ({ max }) => ({ key: 'form.validation.contributionMemo.max', values: { max } })) + .max(512, ({ max }) => ({ key: 'form.validation.contributionMemo.max', values: { max } })) .required('form.validation.contributionMemo.required'), hours: number() .typeError({ key: 'form.validation.hours.typeError', values: { min: 0.01, max: maxHours } }) diff --git a/frontend/src/validationSchemas.js b/frontend/src/validationSchemas.js index fd995d63a..53cdc6f86 100644 --- a/frontend/src/validationSchemas.js +++ b/frontend/src/validationSchemas.js @@ -24,7 +24,7 @@ export const translateYupErrorString = (error, t) => { export const memo = string() .required('form.validation.memo.required') .min(5, ({ min }) => ({ key: 'form.validation.memo.min', values: { min } })) - .max(255, ({ max }) => ({ key: 'form.validation.memo.max', values: { max } })) + .max(512, ({ max }) => ({ key: 'form.validation.memo.max', values: { max } })) export const identifier = string() .required('form.validation.identifier.required')