From 89a6305c4571f3c9b99c0ceafac828bf7c02ddc0 Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Mon, 26 Jun 2023 13:12:42 +0200 Subject: [PATCH 01/17] feat(database): update typeorm --- backend/src/graphql/resolver/UserResolver.ts | 36 +-- backend/src/webhook/elopage.ts | 2 +- database/package.json | 2 +- database/yarn.lock | 258 ++++++++----------- 4 files changed, 130 insertions(+), 168 deletions(-) diff --git a/backend/src/graphql/resolver/UserResolver.ts b/backend/src/graphql/resolver/UserResolver.ts index 9df6b861b..19f59e1a3 100644 --- a/backend/src/graphql/resolver/UserResolver.ts +++ b/backend/src/graphql/resolver/UserResolver.ts @@ -270,7 +270,7 @@ export class UserResolver { if (redeemCode) { if (redeemCode.match(/^CL-/)) { const contributionLink = await DbContributionLink.findOne({ - code: redeemCode.replace('CL-', ''), + where: { code: redeemCode.replace('CL-', '') }, }) logger.info('redeemCode found contributionLink', contributionLink) if (contributionLink) { @@ -278,7 +278,7 @@ export class UserResolver { eventRegisterRedeem.involvedContributionLink = contributionLink } } else { - const transactionLink = await DbTransactionLink.findOne({ code: redeemCode }) + const transactionLink = await DbTransactionLink.findOne({ where: { code: redeemCode } }) logger.info('redeemCode found transactionLink', transactionLink) if (transactionLink) { dbUser.referrerId = transactionLink.userId @@ -403,10 +403,10 @@ export class UserResolver { } // load code - const userContact = await DbUserContact.findOneOrFail( - { emailVerificationCode: code }, - { relations: ['user'] }, - ).catch(() => { + const userContact = await DbUserContact.findOne({ + where: { emailVerificationCode: code }, + relations: ['user'], + }).catch(() => { throw new LogError('Could not login with emailVerificationCode') }) logger.debug('userContact loaded...') @@ -474,7 +474,7 @@ export class UserResolver { @Query(() => Boolean) async queryOptIn(@Arg('optIn') optIn: string): Promise { logger.info(`queryOptIn(${optIn})...`) - const userContact = await DbUserContact.findOneOrFail({ emailVerificationCode: optIn }) + const userContact = await DbUserContact.findOneOrFail({ where: { emailVerificationCode: optIn } }) logger.debug('found optInCode', userContact) // Code is only valid for `CONFIG.EMAIL_CODE_VALID_TIME` minutes if (!isEmailVerificationCodeValid(userContact.updatedAt || userContact.createdAt)) { @@ -705,7 +705,7 @@ export class UserResolver { @Ctx() context: Context, ): Promise { - const user = await DbUser.findOne({ id: userId }) + const user = await DbUser.findOne({ where: { id: userId } }) // user exists ? if (!user) { throw new LogError('Could not find user with given ID', userId) @@ -734,7 +734,7 @@ export class UserResolver { } await user.save() await EVENT_ADMIN_USER_ROLE_SET(user, moderator) - const newUser = await DbUser.findOne({ id: userId }) + const newUser = await DbUser.findOne({ where: { id: userId } }) return newUser ? newUser.isAdmin : null } @@ -757,7 +757,7 @@ export class UserResolver { // soft-delete user await user.softRemove() await EVENT_ADMIN_USER_DELETE(user, moderator) - const newUser = await DbUser.findOne({ id: userId }, { withDeleted: true }) + const newUser = await DbUser.findOne({ where: { id: userId }, withDeleted: true }) return newUser ? newUser.deletedAt : null } @@ -767,7 +767,7 @@ export class UserResolver { @Arg('userId', () => Int) userId: number, @Ctx() context: Context, ): Promise { - const user = await DbUser.findOne({ id: userId }, { withDeleted: true }) + const user = await DbUser.findOne({ where: { id: userId }, withDeleted: true }) if (!user) { throw new LogError('Could not find user with given ID', userId) } @@ -819,10 +819,11 @@ export class UserResolver { } export async function findUserByEmail(email: string): Promise { - const dbUserContact = await DbUserContact.findOneOrFail( - { email }, - { withDeleted: true, relations: ['user'] }, - ).catch(() => { + const dbUserContact = await DbUserContact.findOneOrFail({ + where: { email }, + withDeleted: true, + relations: ['user'] + }).catch(() => { throw new LogError('No user with this credentials', email) }) const dbUser = dbUserContact.user @@ -831,7 +832,10 @@ export async function findUserByEmail(email: string): Promise { } async function checkEmailExists(email: string): Promise { - const userContact = await DbUserContact.findOne({ email }, { withDeleted: true }) + const userContact = await DbUserContact.findOne({ + where: { email }, + withDeleted: true, + }) if (userContact) { return true } diff --git a/backend/src/webhook/elopage.ts b/backend/src/webhook/elopage.ts index 07e7d4ecf..940b80dd1 100644 --- a/backend/src/webhook/elopage.ts +++ b/backend/src/webhook/elopage.ts @@ -135,7 +135,7 @@ export const elopageWebhook = async (req: any, res: any): Promise => { // Do we already have such a user? // if ((await dbUser.count({ email })) !== 0) { - if ((await dbUserContact.count({ email })) !== 0) { + if ((await dbUserContact.count({ where: { email } })) !== 0) { // eslint-disable-next-line no-console console.log(`Did not create User - already exists with email: ${email}`) return diff --git a/database/package.json b/database/package.json index abc69d21d..c45783a7b 100644 --- a/database/package.json +++ b/database/package.json @@ -46,7 +46,7 @@ "mysql2": "^2.3.0", "reflect-metadata": "^0.1.13", "ts-mysql-migrate": "^1.0.2", - "typeorm": "^0.2.38", + "typeorm": "^0.3.16", "uuid": "^8.3.2" }, "engines": { diff --git a/database/yarn.lock b/database/yarn.lock index 8fab393c9..ac35e1eaa 100644 --- a/database/yarn.lock +++ b/database/yarn.lock @@ -2,6 +2,13 @@ # yarn lockfile v1 +"@babel/runtime@^7.21.0": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.22.5.tgz#8564dd588182ce0047d55d7a75e93921107b57ec" + integrity sha512-ecjvYlnAaZ/KVneE/OdKYBYfgXV3Ptu6zQWmgEF7vwKhQnvVS6bjMD2XYgj+SNvQ1GfK/pjgokfPkC/2CO8CuA== + dependencies: + regenerator-runtime "^0.13.11" + "@cspotcode/source-map-consumer@0.8.0": version "0.8.0" resolved "https://registry.yarnpkg.com/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz#33bf4b7b39c178821606f669bbc447a6a629786b" @@ -106,10 +113,10 @@ picocolors "^1.0.0" tslib "^2.5.0" -"@sqltools/formatter@^1.2.2": - version "1.2.3" - resolved "https://registry.yarnpkg.com/@sqltools/formatter/-/formatter-1.2.3.tgz#1185726610acc37317ddab11c3c7f9066966bd20" - integrity sha512-O3uyB/JbkAEMZaP3YqyHH7TMnex7tWyCbCI4EfJdOCoN6HIhqdJBWTM6aCCiWQ/5f5wxjgU735QAIpJbjDvmzg== +"@sqltools/formatter@^1.2.5": + version "1.2.5" + resolved "https://registry.yarnpkg.com/@sqltools/formatter/-/formatter-1.2.5.tgz#3abc203c79b8c3e90fd6c156a0c62d5403520e12" + integrity sha512-Uy0+khmZqUrUGm5dmMqVlnvufZRSK0FbYzVgp0UMstm+F5+W2/jnEEQyc9vo1ZR/E5ZI/B1WjjoTqBqwJL6Krw== "@tsconfig/node10@^1.0.7": version "1.0.8" @@ -173,11 +180,6 @@ resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-8.3.4.tgz#bd86a43617df0594787d38b735f55c805becf1bc" integrity sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw== -"@types/zen-observable@0.8.3": - version "0.8.3" - resolved "https://registry.yarnpkg.com/@types/zen-observable/-/zen-observable-0.8.3.tgz#781d360c282436494b32fe7d9f7f8e64b3118aa3" - integrity sha512-fbF6oTd4sGGy0xjHPKAt+eS2CrxJ3+6gQ3FGcBoIJR2TLAyCkCyI8JqZNy+FeON0AhVgNJoUumVoZQjBFUqHkw== - "@typescript-eslint/eslint-plugin@^5.57.1": version "5.59.9" resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.9.tgz#2604cfaf2b306e120044f901e20c8ed926debf15" @@ -292,11 +294,6 @@ ajv@^6.10.0, ajv@^6.12.4: json-schema-traverse "^0.4.1" uri-js "^4.2.2" -ansi-regex@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" - integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= - ansi-regex@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" @@ -307,11 +304,6 @@ ansi-regex@^5.0.1: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== -ansi-styles@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" - integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4= - ansi-styles@^4.0.0, ansi-styles@^4.1.0: version "4.3.0" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" @@ -324,10 +316,10 @@ any-promise@^1.0.0: resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" integrity sha1-q8av7tzqUugJzcA3au0845Y10X8= -app-root-path@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/app-root-path/-/app-root-path-3.0.0.tgz#210b6f43873227e18a4b810a032283311555d5ad" - integrity sha512-qMcx+Gy2UZynHjOHOIXPNvpf+9cjvk3cWrBBK7zg4gH9+clobJRb9NGzcT7mQTcV/6Gm/1WelUtqxVXnNlrwcw== +app-root-path@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/app-root-path/-/app-root-path-3.1.0.tgz#5971a2fc12ba170369a7a1ef018c71e6e47c2e86" + integrity sha512-biN3PwB2gUtjaYy/isrU3aNWI5w+fAfvHkSvCKeQGxhmYpwKFUxudR3Yya+KqVRHBmEDYh+/lTozYCFbmzX4nA== arg@^4.1.0: version "4.1.3" @@ -423,6 +415,13 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" +brace-expansion@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" + integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== + dependencies: + balanced-match "^1.0.0" + braces@^3.0.1: version "3.0.2" resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" @@ -465,18 +464,7 @@ callsites@^3.0.0: resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== -chalk@^1.1.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" - integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= - dependencies: - ansi-styles "^2.2.1" - escape-string-regexp "^1.0.2" - has-ansi "^2.0.0" - strip-ansi "^3.0.0" - supports-color "^2.0.0" - -chalk@^4.0.0, chalk@^4.1.0: +chalk@^4.0.0, chalk@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== @@ -505,6 +493,15 @@ cliui@^7.0.2: strip-ansi "^6.0.0" wrap-ansi "^7.0.0" +cliui@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" + integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.1" + wrap-ansi "^7.0.0" + color-convert@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" @@ -553,6 +550,13 @@ crypto@^1.0.1: resolved "https://registry.yarnpkg.com/crypto/-/crypto-1.0.1.tgz#2af1b7cad8175d24c8a1b0778255794a21803037" integrity sha512-VxBKmeNcqQdiUQUW2Tzq0t377b54N2bMtXO/qiLa+6eRRmmC4qT3D4OnTGoT/U6O9aklQ/jTwbOtRMTTY8G0Ig== +date-fns@^2.29.3: + version "2.30.0" + resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.30.0.tgz#f367e644839ff57894ec6ac480de40cae4b0f4d0" + integrity sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw== + dependencies: + "@babel/runtime" "^7.21.0" + debug@^3.2.7: version "3.2.7" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" @@ -560,7 +564,7 @@ debug@^3.2.7: dependencies: ms "^2.1.1" -debug@^4.1.1, debug@^4.3.1: +debug@^4.1.1: version "4.3.2" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b" integrity sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw== @@ -658,10 +662,10 @@ dotenv@^10.0.0: resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-10.0.0.tgz#3d4227b8fb95f81096cdd2b66653fb2c7085ba81" integrity sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q== -dotenv@^8.2.0: - version "8.6.0" - resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.6.0.tgz#061af664d19f7f4d8fc6e4ff9b584ce237adcb8b" - integrity sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g== +dotenv@^16.0.3: + version "16.3.1" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.3.1.tgz#369034de7d7e5b120972693352a3bf112172cc3e" + integrity sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ== emoji-regex@^8.0.0: version "8.0.0" @@ -746,7 +750,7 @@ escalade@^3.1.1: resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== -escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: +escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= @@ -1054,11 +1058,6 @@ fastq@^1.6.0: dependencies: reusify "^1.0.4" -figlet@^1.1.1: - version "1.5.2" - resolved "https://registry.yarnpkg.com/figlet/-/figlet-1.5.2.tgz#dda34ff233c9a48e36fcff6741aeb5bafe49b634" - integrity sha512-WOn21V8AhyE1QqVfPIVxe3tupJacq1xGkPTB4iagT6o+P2cAgEOOwIxMftr4+ZCTI6d551ij9j61DFr0nsP2uQ== - file-entry-cache@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" @@ -1203,17 +1202,16 @@ glob@^7.1.3: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^7.1.6: - version "7.2.0" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" - integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== +glob@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/glob/-/glob-8.1.0.tgz#d388f656593ef708ee3e34640fdfb99a9fd1c33e" + integrity sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ== dependencies: fs.realpath "^1.0.0" inflight "^1.0.4" inherits "2" - minimatch "^3.0.4" + minimatch "^5.0.1" once "^1.3.0" - path-is-absolute "^1.0.0" globals@^13.19.0: version "13.20.0" @@ -1274,13 +1272,6 @@ graphemer@^1.4.0: resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== -has-ansi@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" - integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE= - dependencies: - ansi-regex "^2.0.0" - has-bigints@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.1.tgz#64fe6acb020673e3b78db035a5af69aa9d07b113" @@ -1594,7 +1585,7 @@ isexe@^2.0.0: resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= -js-yaml@^4.0.0, js-yaml@^4.1.0: +js-yaml@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== @@ -1705,6 +1696,13 @@ minimatch@^3.0.5, minimatch@^3.1.2: dependencies: brace-expansion "^1.1.7" +minimatch@^5.0.1: + version "5.1.6" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" + integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== + dependencies: + brace-expansion "^2.0.1" + minimist@^1.2.0: version "1.2.5" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" @@ -1715,10 +1713,10 @@ minimist@^1.2.6: resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== -mkdirp@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" - integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== +mkdirp@^2.1.3: + version "2.1.6" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-2.1.6.tgz#964fbcb12b2d8c5d6fbc62a963ac95a273e2cc19" + integrity sha512-+hEnITedc8LAtIP9u3HJDFIdcLV2vXP33sqLLIzkv1Db1zO/1OxbvYf0Y1OC/S/Qo5dxHXepofhmxL02PsKe+A== ms@2.1.2: version "2.1.2" @@ -1897,11 +1895,6 @@ parent-module@^1.0.0: dependencies: callsites "^3.0.0" -parent-require@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/parent-require/-/parent-require-1.0.0.tgz#746a167638083a860b0eef6732cb27ed46c32977" - integrity sha1-dGoWdjgIOoYLDu9nMssn7UbDKXc= - parse5-htmlparser2-tree-adapter@^6.0.0: version "6.0.1" resolved "https://registry.yarnpkg.com/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz#2cdf9ad823321140370d4dbf5d3e92c7c8ddc6e6" @@ -2014,6 +2007,11 @@ reflect-metadata@^0.1.13: resolved "https://registry.yarnpkg.com/reflect-metadata/-/reflect-metadata-0.1.13.tgz#67ae3ca57c972a2aa1642b10fe363fe32d49dc08" integrity sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg== +regenerator-runtime@^0.13.11: + version "0.13.11" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9" + integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg== + regexp-tree@~0.1.1: version "0.1.27" resolved "https://registry.yarnpkg.com/regexp-tree/-/regexp-tree-0.1.27.tgz#2198f0ef54518ffa743fe74d983b56ffd631b6cd" @@ -2114,11 +2112,6 @@ safe-regex@^2.1.1: resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== -sax@>=0.6.0: - version "1.2.4" - resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" - integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== - semver@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" @@ -2199,6 +2192,15 @@ string-width@^4.1.0, string-width@^4.2.0: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.0" +string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + string.prototype.trim@^1.2.7: version "1.2.7" resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz#a68352740859f6893f14ce3ef1bb3037f7a90533" @@ -2233,13 +2235,6 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" -strip-ansi@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" - integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= - dependencies: - ansi-regex "^2.0.0" - strip-ansi@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" @@ -2274,11 +2269,6 @@ strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== -supports-color@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" - integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= - supports-color@^7.1.0: version "7.2.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" @@ -2376,11 +2366,6 @@ tslib@^1.8.1: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tslib@^2.1.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01" - integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw== - tslib@^2.5.0: version "2.5.3" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.3.tgz#24944ba2d990940e6e982c4bea147aba80209913" @@ -2414,28 +2399,26 @@ typed-array-length@^1.0.4: for-each "^0.3.3" is-typed-array "^1.1.9" -typeorm@^0.2.38: - version "0.2.38" - resolved "https://registry.yarnpkg.com/typeorm/-/typeorm-0.2.38.tgz#2af08079919f6ab04cd17017f9faa2c8d5cd566f" - integrity sha512-M6Y3KQcAREQcphOVJciywf4mv6+A0I/SeR+lWNjKsjnQ+a3XcMwGYMGL0Jonsx3H0Cqlf/3yYqVki1jIXSK/xg== +typeorm@^0.3.16: + version "0.3.17" + resolved "https://registry.yarnpkg.com/typeorm/-/typeorm-0.3.17.tgz#a73c121a52e4fbe419b596b244777be4e4b57949" + integrity sha512-UDjUEwIQalO9tWw9O2A4GU+sT3oyoUXheHJy4ft+RFdnRdQctdQ34L9SqE2p7LdwzafHx1maxT+bqXON+Qnmig== dependencies: - "@sqltools/formatter" "^1.2.2" - app-root-path "^3.0.0" + "@sqltools/formatter" "^1.2.5" + app-root-path "^3.1.0" buffer "^6.0.3" - chalk "^4.1.0" + chalk "^4.1.2" cli-highlight "^2.1.11" - debug "^4.3.1" - dotenv "^8.2.0" - glob "^7.1.6" - js-yaml "^4.0.0" - mkdirp "^1.0.4" + date-fns "^2.29.3" + debug "^4.3.4" + dotenv "^16.0.3" + glob "^8.1.0" + mkdirp "^2.1.3" reflect-metadata "^0.1.13" sha.js "^2.4.11" - tslib "^2.1.0" - xml2js "^0.4.23" - yargonaut "^1.1.4" - yargs "^17.0.1" - zen-observable-ts "^1.0.0" + tslib "^2.5.0" + uuid "^9.0.0" + yargs "^17.6.2" typescript@^4.3.5: version "4.3.5" @@ -2474,6 +2457,11 @@ uuid@^8.3.2: resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== +uuid@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.0.tgz#592f550650024a38ceb0c562f2f6aa435761efb5" + integrity sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg== + which-boxed-primitive@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" @@ -2523,19 +2511,6 @@ wrappy@1: resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= -xml2js@^0.4.23: - version "0.4.23" - resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.23.tgz#a0c69516752421eb2ac758ee4d4ccf58843eac66" - integrity sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug== - dependencies: - sax ">=0.6.0" - xmlbuilder "~11.0.0" - -xmlbuilder@~11.0.0: - version "11.0.1" - resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3" - integrity sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA== - y18n@^5.0.5: version "5.0.8" resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" @@ -2551,20 +2526,16 @@ yallist@^4.0.0: resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== -yargonaut@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/yargonaut/-/yargonaut-1.1.4.tgz#c64f56432c7465271221f53f5cc517890c3d6e0c" - integrity sha512-rHgFmbgXAAzl+1nngqOcwEljqHGG9uUZoPjsdZEs1w5JW9RXYzrSvH/u70C1JE5qFi0qjsdhnUX/dJRpWqitSA== - dependencies: - chalk "^1.1.1" - figlet "^1.1.1" - parent-require "^1.0.0" - yargs-parser@^20.2.2: version "20.2.9" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== +yargs-parser@^21.1.1: + version "21.1.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" + integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== + yargs@^16.0.0: version "16.2.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" @@ -2578,18 +2549,18 @@ yargs@^16.0.0: y18n "^5.0.5" yargs-parser "^20.2.2" -yargs@^17.0.1: - version "17.2.1" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.2.1.tgz#e2c95b9796a0e1f7f3bf4427863b42e0418191ea" - integrity sha512-XfR8du6ua4K6uLGm5S6fA+FIJom/MdJcFNVY8geLlp2v8GYbOXD4EB1tPNZsRn4vBzKGMgb5DRZMeWuFc2GO8Q== +yargs@^17.6.2: + version "17.7.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" + integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== dependencies: - cliui "^7.0.2" + cliui "^8.0.1" escalade "^3.1.1" get-caller-file "^2.0.5" require-directory "^2.1.1" - string-width "^4.2.0" + string-width "^4.2.3" y18n "^5.0.5" - yargs-parser "^20.2.2" + yargs-parser "^21.1.1" yn@3.1.1: version "3.1.1" @@ -2600,16 +2571,3 @@ yocto-queue@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== - -zen-observable-ts@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/zen-observable-ts/-/zen-observable-ts-1.1.0.tgz#2d1aa9d79b87058e9b75698b92791c1838551f83" - integrity sha512-1h4zlLSqI2cRLPJUHJFL8bCWHhkpuXkF+dbGkRaWjgDIG26DmzyshUMrdV/rL3UnR+mhaX4fRq8LPouq0MYYIA== - dependencies: - "@types/zen-observable" "0.8.3" - zen-observable "0.8.15" - -zen-observable@0.8.15: - version "0.8.15" - resolved "https://registry.yarnpkg.com/zen-observable/-/zen-observable-0.8.15.tgz#96415c512d8e3ffd920afd3889604e30b9eaac15" - integrity sha512-PQ2PC7R9rslx84ndNBZB/Dkv8V8fZEpk83RLgXtYd0fwUgEjseMn1Dgajh2x6S8QbZAFa9p2qVCEuYZNgve0dQ== From ba98797009719de6744ee901d6d1adf3317d251d Mon Sep 17 00:00:00 2001 From: mahula Date: Mon, 26 Jun 2023 13:55:45 +0200 Subject: [PATCH 02/17] add deleted user and not registered user scenarios to e2e password reset feature --- .../User.Authentication.ResetPassword.feature | 29 +++++++++++++++---- .../support/step_definitions/email_steps.ts | 15 ++++++++++ 2 files changed, 38 insertions(+), 6 deletions(-) diff --git a/e2e-tests/cypress/e2e/User.Authentication.ResetPassword.feature b/e2e-tests/cypress/e2e/User.Authentication.ResetPassword.feature index 50a29d320..ab9213cb9 100644 --- a/e2e-tests/cypress/e2e/User.Authentication.ResetPassword.feature +++ b/e2e-tests/cypress/e2e/User.Authentication.ResetPassword.feature @@ -2,13 +2,27 @@ Feature: User Authentication - reset password As a user I want to reset my password from the sign in page - # TODO for these pre-conditions utilize seeding or API check, if user exists in test system - # Background: - # Given the following "users" are in the database: - # | email | password | name | - # | raeuber@hotzenplotz.de | Aa12345_ | Räuber Hotzenplotz | - + Scenario: Reset password as not registered user + Given the user navigates to page "/login" + And the user navigates to the forgot password page + When the user enters the e-mail address "not@registered.com" + And the user submits the e-mail form + Then the user receives no password reset e-mail + + Scenario: Reset password as deleted user + # Given the following "users" are in the database: + # | email | password | name | + # | stephen@hawking.uk | Aa12345_ | Stephen Hawking | + Given the user navigates to page "/login" + And the user navigates to the forgot password page + When the user enters the e-mail address "stephen@hawking.uk" + And the user submits the e-mail form + Then the user receives no password reset e-mail + Scenario: Reset password from signin page successfully + # Given the following "users" are in the database: + # | email | password | name | + # | raeuber@hotzenplotz.de | Aa12345_ | Räuber Hotzenplotz | Given the user navigates to page "/login" And the user navigates to the forgot password page When the user enters the e-mail address "raeuber@hotzenplotz.de" @@ -23,3 +37,6 @@ Feature: User Authentication - reset password And the user cannot login But the user submits the credentials "raeuber@hotzenplotz.de" "12345Aa_" And the user is logged in with username "Räuber Hotzenplotz" + + + diff --git a/e2e-tests/cypress/support/step_definitions/email_steps.ts b/e2e-tests/cypress/support/step_definitions/email_steps.ts index d31e2474e..fdf273def 100644 --- a/e2e-tests/cypress/support/step_definitions/email_steps.ts +++ b/e2e-tests/cypress/support/step_definitions/email_steps.ts @@ -51,6 +51,21 @@ Then('the user receives an e-mail containing the {string} link', (linkName: stri ) }) +Then('the user receives no password reset e-mail', () { + cy.origin( + Cypress.env('mailserverURL'), + { args: { userEMailSite } }, + ({ userEMailSite }) => { + cy.visit('/') + cy.get(userEMailSite.emailInbox).should('be.visible') + + cy.get(userEMailSite.emailList) + .find('.email-item') + .should('have.length', 0) + } + ) +}) + When('the user opens the {string} link in the browser', (linkName: string) => { cy.task('getEmailLink').then((emailLink) => { cy.visit(emailLink) From e35104faa86c771bc5bdb0cd5426ccba108c7550 Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Mon, 26 Jun 2023 13:59:42 +0200 Subject: [PATCH 03/17] get backend running with new typeorm version --- backend/.eslintrc.js | 2 +- .../src/graphql/resolver/BalanceResolver.ts | 4 +- .../resolver/ContributionLinkResolver.ts | 4 +- .../resolver/ContributionMessageResolver.ts | 4 +- .../resolver/ContributionResolver.test.ts | 58 +++++++++++++++++++ .../graphql/resolver/ContributionResolver.ts | 42 ++++++++------ .../resolver/TransactionLinkResolver.ts | 37 +++++++----- backend/src/graphql/resolver/UserResolver.ts | 20 ++++--- .../resolver/util/findContributions.ts | 33 +++++++++-- .../resolver/util/findUserByIdentifier.ts | 10 ++-- .../resolver/util/getLastTransaction.ts | 14 ++--- .../resolver/util/transactionLinkList.ts | 4 +- backend/src/seeds/graphql/queries.ts | 2 + backend/src/server/context.ts | 2 +- backend/src/typeorm/DBVersion.ts | 2 +- backend/src/util/hasElopageBuys.ts | 2 +- 16 files changed, 167 insertions(+), 73 deletions(-) diff --git a/backend/.eslintrc.js b/backend/.eslintrc.js index e853c8bf6..0df8aca46 100644 --- a/backend/.eslintrc.js +++ b/backend/.eslintrc.js @@ -40,7 +40,7 @@ module.exports = { ], // import 'import/export': 'error', - 'import/no-deprecated': 'error', + // 'import/no-deprecated': 'error', 'import/no-empty-named-blocks': 'error', 'import/no-extraneous-dependencies': 'error', 'import/no-mutable-exports': 'error', diff --git a/backend/src/graphql/resolver/BalanceResolver.ts b/backend/src/graphql/resolver/BalanceResolver.ts index c8fdacdcf..9cd133181 100644 --- a/backend/src/graphql/resolver/BalanceResolver.ts +++ b/backend/src/graphql/resolver/BalanceResolver.ts @@ -1,5 +1,5 @@ /* eslint-disable @typescript-eslint/restrict-template-expressions */ -import { getCustomRepository } from '@dbTools/typeorm' +import { getCustomRepository, IsNull } from '@dbTools/typeorm' import { Transaction as dbTransaction } from '@entity/Transaction' import { TransactionLink as dbTransactionLink } from '@entity/TransactionLink' import { Decimal } from 'decimal.js-light' @@ -57,7 +57,7 @@ export class BalanceResolver { const linkCount = await dbTransactionLink.count({ where: { userId: user.id, - redeemedAt: null, + redeemedAt: IsNull(), // validUntil: MoreThan(new Date()), }, }) diff --git a/backend/src/graphql/resolver/ContributionLinkResolver.ts b/backend/src/graphql/resolver/ContributionLinkResolver.ts index 1dcf6a3cb..808bd584e 100644 --- a/backend/src/graphql/resolver/ContributionLinkResolver.ts +++ b/backend/src/graphql/resolver/ContributionLinkResolver.ts @@ -103,7 +103,7 @@ export class ContributionLinkResolver { @Arg('id', () => Int) id: number, @Ctx() context: Context, ): Promise { - const dbContributionLink = await DbContributionLink.findOne(id) + const dbContributionLink = await DbContributionLink.findOne({ where: { id } }) if (!dbContributionLink) { throw new LogError('Contribution Link not found', id) } @@ -130,7 +130,7 @@ export class ContributionLinkResolver { @Arg('id', () => Int) id: number, @Ctx() context: Context, ): Promise { - const dbContributionLink = await DbContributionLink.findOne(id) + const dbContributionLink = await DbContributionLink.findOne({ where: { id } }) if (!dbContributionLink) { throw new LogError('Contribution Link not found', id) } diff --git a/backend/src/graphql/resolver/ContributionMessageResolver.ts b/backend/src/graphql/resolver/ContributionMessageResolver.ts index b7fd37787..cc21f6e91 100644 --- a/backend/src/graphql/resolver/ContributionMessageResolver.ts +++ b/backend/src/graphql/resolver/ContributionMessageResolver.ts @@ -36,7 +36,7 @@ export class ContributionMessageResolver { await queryRunner.startTransaction('REPEATABLE READ') const contributionMessage = DbContributionMessage.create() try { - const contribution = await DbContribution.findOne({ id: contributionId }) + const contribution = await DbContribution.findOne({ where: { id: contributionId } }) if (!contribution) { throw new LogError('Contribution not found', contributionId) } @@ -124,7 +124,7 @@ export class ContributionMessageResolver { if (contribution.userId === moderator.id) { throw new LogError('Admin can not answer on his own contribution', contributionId) } - if (!contribution.user.emailContact) { + if (!contribution.user.emailContact && contribution.user.emailId) { contribution.user.emailContact = await DbUserContact.findOneOrFail({ where: { id: contribution.user.emailId }, }) diff --git a/backend/src/graphql/resolver/ContributionResolver.test.ts b/backend/src/graphql/resolver/ContributionResolver.test.ts index d4c84b4f3..81e913dde 100644 --- a/backend/src/graphql/resolver/ContributionResolver.test.ts +++ b/backend/src/graphql/resolver/ContributionResolver.test.ts @@ -2890,6 +2890,64 @@ describe('ContributionResolver', () => { ]), }) }) + + describe('with query', () => { + it('returns the creations of queried user', async () => { + const result = await query({ + query: adminListContributions, + variables: { + currentPage: 1, + pageSize: 2, + order: Order.DESC, + query: 'peter', + }, + }) + const { + data: { adminListContributions: contributionListObject }, + } = await query({ + query: adminListContributions, + variables: { + currentPage: 1, + pageSize: 2, + order: Order.DESC, + query: 'peter', + }, + }) + expect(contributionListObject.contributionList).toHaveLength(3) + expect(contributionListObject).toMatchObject({ + contributionCount: 3, + contributionList: expect.arrayContaining([ + expect.objectContaining({ + amount: expect.decimalEqual(400), + firstName: 'Peter', + id: expect.any(Number), + lastName: 'Lustig', + memo: 'Herzlich Willkommen bei Gradido!', + messagesCount: 0, + state: 'PENDING', + }), + expect.objectContaining({ + amount: expect.decimalEqual(100), + firstName: 'Peter', + id: expect.any(Number), + lastName: 'Lustig', + memo: 'Test env contribution', + messagesCount: 0, + state: 'PENDING', + }), + expect.objectContaining({ + amount: expect.decimalEqual(200), + firstName: 'Peter', + id: expect.any(Number), + lastName: 'Lustig', + memo: 'Das war leider zu Viel!', + messagesCount: 0, + state: 'DELETED', + }), + ]), + }) + }) + }) }) }) }) diff --git a/backend/src/graphql/resolver/ContributionResolver.ts b/backend/src/graphql/resolver/ContributionResolver.ts index fa1590523..9727d6015 100644 --- a/backend/src/graphql/resolver/ContributionResolver.ts +++ b/backend/src/graphql/resolver/ContributionResolver.ts @@ -101,7 +101,7 @@ export class ContributionResolver { @Ctx() context: Context, ): Promise { const user = getUser(context) - const contribution = await DbContribution.findOne(id) + const contribution = await DbContribution.findOne({ where: { id } }) if (!contribution) { throw new LogError('Contribution not found', id) } @@ -372,6 +372,8 @@ export class ContributionResolver { statusFilter?: ContributionStatus[] | null, @Arg('userId', () => Int, { nullable: true }) userId?: number | null, + @Arg('query', () => String, { nullable: true }) + query?: string | null, ): Promise { const [dbContributions, count] = await findContributions({ order, @@ -381,6 +383,7 @@ export class ContributionResolver { userId, relations: ['user', 'messages'], statusFilter, + query, }) return new ContributionListResult( @@ -395,7 +398,7 @@ export class ContributionResolver { @Arg('id', () => Int) id: number, @Ctx() context: Context, ): Promise { - const contribution = await DbContribution.findOne(id) + const contribution = await DbContribution.findOne({ where: { id } }) if (!contribution) { throw new LogError('Contribution not found', id) } @@ -409,10 +412,10 @@ export class ContributionResolver { ) { throw new LogError('Own contribution can not be deleted as admin') } - const user = await DbUser.findOneOrFail( - { id: contribution.userId }, - { relations: ['emailContact'] }, - ) + const user = await DbUser.findOneOrFail({ + where: { id: contribution.userId }, + relations: ['emailContact'], + }) contribution.contributionStatus = ContributionStatus.DELETED contribution.deletedBy = moderator.id await contribution.save() @@ -447,7 +450,7 @@ export class ContributionResolver { const releaseLock = await TRANSACTIONS_LOCK.acquire() try { const clientTimezoneOffset = getClientTimezoneOffset(context) - const contribution = await DbContribution.findOne(id) + const contribution = await DbContribution.findOne({ where: { id } }) if (!contribution) { throw new LogError('Contribution not found', id) } @@ -461,10 +464,11 @@ export class ContributionResolver { if (moderatorUser.id === contribution.userId) { throw new LogError('Moderator can not confirm own contribution') } - const user = await DbUser.findOneOrFail( - { id: contribution.userId }, - { withDeleted: true, relations: ['emailContact'] }, - ) + const user = await DbUser.findOneOrFail({ + where: { id: contribution.userId }, + withDeleted: true, + relations: ['emailContact'], + }) if (user.deletedAt) { throw new LogError('Can not confirm contribution since the user was deleted') } @@ -565,9 +569,11 @@ export class ContributionResolver { @Ctx() context: Context, ): Promise { const contributionToUpdate = await DbContribution.findOne({ - id, - confirmedAt: IsNull(), - deniedBy: IsNull(), + where: { + id, + confirmedAt: IsNull(), + deniedBy: IsNull(), + }, }) if (!contributionToUpdate) { throw new LogError('Contribution not found', id) @@ -582,10 +588,10 @@ export class ContributionResolver { ) } const moderator = getUser(context) - const user = await DbUser.findOne( - { id: contributionToUpdate.userId }, - { relations: ['emailContact'] }, - ) + const user = await DbUser.findOne({ + where: { id: contributionToUpdate.userId }, + relations: ['emailContact'], + }) if (!user) { throw new LogError('Could not find User of the Contribution', contributionToUpdate.userId) } diff --git a/backend/src/graphql/resolver/TransactionLinkResolver.ts b/backend/src/graphql/resolver/TransactionLinkResolver.ts index d6649814a..0ff606fa5 100644 --- a/backend/src/graphql/resolver/TransactionLinkResolver.ts +++ b/backend/src/graphql/resolver/TransactionLinkResolver.ts @@ -108,7 +108,7 @@ export class TransactionLinkResolver { ): Promise { const user = getUser(context) - const transactionLink = await DbTransactionLink.findOne({ id }) + const transactionLink = await DbTransactionLink.findOne({ where: { id } }) if (!transactionLink) { throw new LogError('Transaction link not found', id) } @@ -138,17 +138,22 @@ export class TransactionLinkResolver { @Query(() => QueryLinkResult) async queryTransactionLink(@Arg('code') code: string): Promise { if (code.match(/^CL-/)) { - const contributionLink = await DbContributionLink.findOneOrFail( - { code: code.replace('CL-', '') }, - { withDeleted: true }, - ) + const contributionLink = await DbContributionLink.findOneOrFail({ + where: { code: code.replace('CL-', '') }, + withDeleted: true, + }) return new ContributionLink(contributionLink) } else { - const transactionLink = await DbTransactionLink.findOneOrFail({ code }, { withDeleted: true }) - const user = await DbUser.findOneOrFail({ id: transactionLink.userId }) + const transactionLink = await DbTransactionLink.findOneOrFail({ + where: { code }, + withDeleted: true, + }) + const user = await DbUser.findOneOrFail({ where: { id: transactionLink.userId } }) let redeemedBy: User | null = null if (transactionLink?.redeemedBy) { - redeemedBy = new User(await DbUser.findOneOrFail({ id: transactionLink.redeemedBy })) + redeemedBy = new User( + await DbUser.findOneOrFail({ where: { id: transactionLink.redeemedBy } }), + ) } return new TransactionLink(transactionLink, new User(user), redeemedBy) } @@ -191,7 +196,7 @@ export class TransactionLinkResolver { throw new LogError('Contribution link is no longer valid', contributionLink.validTo) } } - let alreadyRedeemed: DbContribution | undefined + let alreadyRedeemed: DbContribution | null switch (contributionLink.cycle) { case ContributionCycleType.ONCE: { alreadyRedeemed = await queryRunner.manager @@ -302,15 +307,17 @@ export class TransactionLinkResolver { return true } else { const now = new Date() - const transactionLink = await DbTransactionLink.findOne({ code }) + const transactionLink = await DbTransactionLink.findOne({ where: { code } }) if (!transactionLink) { throw new LogError('Transaction link not found', code) } - const linkedUser = await DbUser.findOne( - { id: transactionLink.userId }, - { relations: ['emailContact'] }, - ) + const linkedUser = await DbUser.findOne({ + where: { + id: transactionLink.userId, + }, + relations: ['emailContact'], + }) if (!linkedUser) { throw new LogError('Linked user not found for given link', transactionLink.userId) @@ -378,7 +385,7 @@ export class TransactionLinkResolver { @Arg('userId', () => Int) userId: number, ): Promise { - const user = await DbUser.findOne({ id: userId }) + const user = await DbUser.findOne({ where: { id: userId } }) if (!user) { throw new LogError('Could not find requested User', userId) } diff --git a/backend/src/graphql/resolver/UserResolver.ts b/backend/src/graphql/resolver/UserResolver.ts index 19f59e1a3..840bb43c9 100644 --- a/backend/src/graphql/resolver/UserResolver.ts +++ b/backend/src/graphql/resolver/UserResolver.ts @@ -2,7 +2,7 @@ /* eslint-disable @typescript-eslint/no-unsafe-assignment */ /* eslint-disable @typescript-eslint/no-unsafe-member-access */ /* eslint-disable @typescript-eslint/restrict-template-expressions */ -import { getConnection, getCustomRepository, IsNull, Not } from '@dbTools/typeorm' +import { getConnection, getCustomRepository, IsNull, Not, Equal } from '@dbTools/typeorm' import { ContributionLink as DbContributionLink } from '@entity/ContributionLink' import { TransactionLink as DbTransactionLink } from '@entity/TransactionLink' import { User as DbUser } from '@entity/User' @@ -278,7 +278,7 @@ export class UserResolver { eventRegisterRedeem.involvedContributionLink = contributionLink } } else { - const transactionLink = await DbTransactionLink.findOne({ where: { code: redeemCode } }) + const transactionLink = await DbTransactionLink.findOne({ where: { code: redeemCode } }) logger.info('redeemCode found transactionLink', transactionLink) if (transactionLink) { dbUser.referrerId = transactionLink.userId @@ -403,8 +403,8 @@ export class UserResolver { } // load code - const userContact = await DbUserContact.findOne({ - where: { emailVerificationCode: code }, + const userContact = await DbUserContact.findOneOrFail({ + where: { emailVerificationCode: Equal(BigInt(code)) }, relations: ['user'], }).catch(() => { throw new LogError('Could not login with emailVerificationCode') @@ -474,7 +474,9 @@ export class UserResolver { @Query(() => Boolean) async queryOptIn(@Arg('optIn') optIn: string): Promise { logger.info(`queryOptIn(${optIn})...`) - const userContact = await DbUserContact.findOneOrFail({ where: { emailVerificationCode: optIn } }) + const userContact = await DbUserContact.findOneOrFail({ + where: { emailVerificationCode: Equal(BigInt(optIn)) }, + }) logger.debug('found optInCode', userContact) // Code is only valid for `CONFIG.EMAIL_CODE_VALID_TIME` minutes if (!isEmailVerificationCodeValid(userContact.updatedAt || userContact.createdAt)) { @@ -734,7 +736,7 @@ export class UserResolver { } await user.save() await EVENT_ADMIN_USER_ROLE_SET(user, moderator) - const newUser = await DbUser.findOne({ where: { id: userId } }) + const newUser = await DbUser.findOne({ where: { id: userId } }) return newUser ? newUser.isAdmin : null } @@ -744,7 +746,7 @@ export class UserResolver { @Arg('userId', () => Int) userId: number, @Ctx() context: Context, ): Promise { - const user = await DbUser.findOne({ id: userId }) + const user = await DbUser.findOne({ where: { id: userId } }) // user exists ? if (!user) { throw new LogError('Could not find user with given ID', userId) @@ -757,7 +759,7 @@ export class UserResolver { // soft-delete user await user.softRemove() await EVENT_ADMIN_USER_DELETE(user, moderator) - const newUser = await DbUser.findOne({ where: { id: userId }, withDeleted: true }) + const newUser = await DbUser.findOne({ where: { id: userId }, withDeleted: true }) return newUser ? newUser.deletedAt : null } @@ -822,7 +824,7 @@ export async function findUserByEmail(email: string): Promise { const dbUserContact = await DbUserContact.findOneOrFail({ where: { email }, withDeleted: true, - relations: ['user'] + relations: ['user'], }).catch(() => { throw new LogError('No user with this credentials', email) }) diff --git a/backend/src/graphql/resolver/util/findContributions.ts b/backend/src/graphql/resolver/util/findContributions.ts index 28984d5b1..66038538a 100644 --- a/backend/src/graphql/resolver/util/findContributions.ts +++ b/backend/src/graphql/resolver/util/findContributions.ts @@ -1,4 +1,4 @@ -import { In } from '@dbTools/typeorm' +import { In, Like, FindOperator } from '@dbTools/typeorm' import { Contribution as DbContribution } from '@entity/Contribution' import { ContributionStatus } from '@enum/ContributionStatus' @@ -12,27 +12,48 @@ interface FindContributionsOptions { relations?: string[] userId?: number | null statusFilter?: ContributionStatus[] | null + query?: string | null } export const findContributions = async ( options: FindContributionsOptions, ): Promise<[DbContribution[], number]> => { - const { order, currentPage, pageSize, withDeleted, relations, userId, statusFilter } = { + const { order, currentPage, pageSize, withDeleted, relations, userId, statusFilter, query } = { withDeleted: false, relations: [], + query: '', ...options, } + const where: { + userId?: number | undefined + contributionStatus?: FindOperator | undefined + user?: Record>[] | undefined + } = { + ...(statusFilter?.length && { contributionStatus: In(statusFilter) }), + ...(userId && { userId }), + } + + if (query) { + where.user = [ + { firstName: Like(`%${query}%`) }, + { lastName: Like(`%${query}%`) }, + // emailContact: { email: Like(`%${query}%`) }, + ] + } + return DbContribution.findAndCount({ - where: { - ...(statusFilter?.length && { contributionStatus: In(statusFilter) }), - ...(userId && { userId }), + relations: { + user: { + emailContact: true, + }, + messages: true, }, withDeleted, + where, order: { createdAt: order, id: order, }, - relations, skip: (currentPage - 1) * pageSize, take: pageSize, }) diff --git a/backend/src/graphql/resolver/util/findUserByIdentifier.ts b/backend/src/graphql/resolver/util/findUserByIdentifier.ts index bd9a25071..96c9eb458 100644 --- a/backend/src/graphql/resolver/util/findUserByIdentifier.ts +++ b/backend/src/graphql/resolver/util/findUserByIdentifier.ts @@ -7,20 +7,20 @@ import { LogError } from '@/server/LogError' import { VALID_ALIAS_REGEX } from './validateAlias' export const findUserByIdentifier = async (identifier: string): Promise => { - let user: DbUser | undefined + let user: DbUser | null if (validate(identifier) && version(identifier) === 4) { user = await DbUser.findOne({ where: { gradidoID: identifier }, relations: ['emailContact'] }) if (!user) { throw new LogError('No user found to given identifier', identifier) } } else if (/^.{2,}@.{2,}\..{2,}$/.exec(identifier)) { - const userContact = await DbUserContact.findOne( - { + const userContact = await DbUserContact.findOne({ + where: { email: identifier, emailChecked: true, }, - { relations: ['user'] }, - ) + relations: ['user'], + }) if (!userContact) { throw new LogError('No user with this credentials', identifier) } diff --git a/backend/src/graphql/resolver/util/getLastTransaction.ts b/backend/src/graphql/resolver/util/getLastTransaction.ts index 5b3e862c2..0d7747088 100644 --- a/backend/src/graphql/resolver/util/getLastTransaction.ts +++ b/backend/src/graphql/resolver/util/getLastTransaction.ts @@ -3,12 +3,10 @@ import { Transaction as DbTransaction } from '@entity/Transaction' export const getLastTransaction = async ( userId: number, relations?: string[], -): Promise => { - return DbTransaction.findOne( - { userId }, - { - order: { balanceDate: 'DESC', id: 'DESC' }, - relations, - }, - ) +): Promise => { + return DbTransaction.findOne({ + where: { userId }, + order: { balanceDate: 'DESC', id: 'DESC' }, + relations, + }) } diff --git a/backend/src/graphql/resolver/util/transactionLinkList.ts b/backend/src/graphql/resolver/util/transactionLinkList.ts index ee79216c8..653f86804 100644 --- a/backend/src/graphql/resolver/util/transactionLinkList.ts +++ b/backend/src/graphql/resolver/util/transactionLinkList.ts @@ -1,4 +1,4 @@ -import { MoreThan } from '@dbTools/typeorm' +import { MoreThan, IsNull } from '@dbTools/typeorm' import { TransactionLink as DbTransactionLink } from '@entity/TransactionLink' import { User as DbUser } from '@entity/User' @@ -22,7 +22,7 @@ export async function transactionLinkList( const [transactionLinks, count] = await DbTransactionLink.findAndCount({ where: { userId: user.id, - ...(!withRedeemed && { redeemedBy: null }), + ...(!withRedeemed && { redeemedBy: IsNull() }), ...(!withExpired && { validUntil: MoreThan(new Date()) }), }, withDeleted, diff --git a/backend/src/seeds/graphql/queries.ts b/backend/src/seeds/graphql/queries.ts index a964cdb3a..6353fe1cd 100644 --- a/backend/src/seeds/graphql/queries.ts +++ b/backend/src/seeds/graphql/queries.ts @@ -235,6 +235,7 @@ export const adminListContributions = gql` $order: Order = DESC $statusFilter: [ContributionStatus!] $userId: Int + $query: String ) { adminListContributions( currentPage: $currentPage @@ -242,6 +243,7 @@ export const adminListContributions = gql` order: $order statusFilter: $statusFilter userId: $userId + query: $query ) { contributionCount contributionList { diff --git a/backend/src/server/context.ts b/backend/src/server/context.ts index c7e59365b..45f0a6c1f 100644 --- a/backend/src/server/context.ts +++ b/backend/src/server/context.ts @@ -15,7 +15,7 @@ export interface Context { clientTimezoneOffset?: number gradidoID?: string // hack to use less DB calls for Balance Resolver - lastTransaction?: dbTransaction + lastTransaction?: dbTransaction | null transactionCount?: number linkCount?: number sumHoldAvailableAmount?: Decimal diff --git a/backend/src/typeorm/DBVersion.ts b/backend/src/typeorm/DBVersion.ts index f465069d3..acde7c1f0 100644 --- a/backend/src/typeorm/DBVersion.ts +++ b/backend/src/typeorm/DBVersion.ts @@ -4,7 +4,7 @@ import { backendLogger as logger } from '@/server/logger' const getDBVersion = async (): Promise => { try { - const dbVersion = await Migration.findOne({ order: { version: 'DESC' } }) + const [dbVersion] = await Migration.find({ order: { version: 'DESC' }, take: 1 }) return dbVersion ? dbVersion.fileName : null } catch (error) { logger.error(error) diff --git a/backend/src/util/hasElopageBuys.ts b/backend/src/util/hasElopageBuys.ts index 4e23e717c..1465e76e2 100644 --- a/backend/src/util/hasElopageBuys.ts +++ b/backend/src/util/hasElopageBuys.ts @@ -1,6 +1,6 @@ import { LoginElopageBuys } from '@entity/LoginElopageBuys' export async function hasElopageBuys(email: string): Promise { - const elopageBuyCount = await LoginElopageBuys.count({ payerEmail: email }) + const elopageBuyCount = await LoginElopageBuys.count({ where: { payerEmail: email } }) return elopageBuyCount > 0 } From ec4b8294b23ba65face20245028fd8f780de649c Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Mon, 26 Jun 2023 14:04:32 +0200 Subject: [PATCH 04/17] dht node running on ne typeorm version --- dht-node/src/dht_node/index.test.ts | 8 ++++---- dht-node/src/dht_node/index.ts | 2 +- dht-node/src/typeorm/DBVersion.ts | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/dht-node/src/dht_node/index.test.ts b/dht-node/src/dht_node/index.test.ts index ec172c4f8..c6e972c52 100644 --- a/dht-node/src/dht_node/index.test.ts +++ b/dht-node/src/dht_node/index.test.ts @@ -340,7 +340,7 @@ describe('federation', () => { }, ] await socketEventMocks.data(Buffer.from(JSON.stringify(jsonArray))) - result = await DbFederatedCommunity.find({ foreign: true }) + result = await DbFederatedCommunity.find({ where: { foreign: true } }) }) afterAll(async () => { @@ -601,7 +601,7 @@ describe('federation', () => { { api: 'toolong api', url: 'some valid url' }, ] await socketEventMocks.data(Buffer.from(JSON.stringify(jsonArray))) - result = await DbFederatedCommunity.find({ foreign: true }) + result = await DbFederatedCommunity.find({ where: { foreign: true } }) }) afterAll(async () => { @@ -655,7 +655,7 @@ describe('federation', () => { }, ] await socketEventMocks.data(Buffer.from(JSON.stringify(jsonArray))) - result = await DbFederatedCommunity.find({ foreign: true }) + result = await DbFederatedCommunity.find({ where: { foreign: true } }) }) afterAll(async () => { @@ -791,7 +791,7 @@ describe('federation', () => { ]), ), ) - result = await DbFederatedCommunity.find({ foreign: true }) + result = await DbFederatedCommunity.find({ where: { foreign: true } }) }) afterAll(async () => { diff --git a/dht-node/src/dht_node/index.ts b/dht-node/src/dht_node/index.ts index a767c323e..f24522c3b 100644 --- a/dht-node/src/dht_node/index.ts +++ b/dht-node/src/dht_node/index.ts @@ -217,7 +217,7 @@ async function writeFederatedHomeCommunityEntries(pubKey: string): Promise { try { // check for existing homeCommunity entry - let homeCom = await DbCommunity.findOne({ foreign: false }) + 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 = keyPair.publicKey diff --git a/dht-node/src/typeorm/DBVersion.ts b/dht-node/src/typeorm/DBVersion.ts index 5bd23c1d5..850c6ed80 100644 --- a/dht-node/src/typeorm/DBVersion.ts +++ b/dht-node/src/typeorm/DBVersion.ts @@ -3,7 +3,7 @@ import { logger } from '@/server/logger' const getDBVersion = async (): Promise => { try { - const dbVersion = await Migration.findOne({ order: { version: 'DESC' } }) + const [dbVersion] = await Migration.find({ order: { version: 'DESC' }, take: 1 }) return dbVersion ? dbVersion.fileName : null } catch (error) { logger.error(error) From d5af6c3b21827226f2fc2d24a09b09c30527fc74 Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Mon, 26 Jun 2023 14:08:12 +0200 Subject: [PATCH 05/17] federation running with new typeorm version --- .../src/graphql/api/1_0/resolver/PublicKeyResolver.ts | 6 ++++-- federation/src/typeorm/DBVersion.ts | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/federation/src/graphql/api/1_0/resolver/PublicKeyResolver.ts b/federation/src/graphql/api/1_0/resolver/PublicKeyResolver.ts index 0145324fc..e741e95c3 100644 --- a/federation/src/graphql/api/1_0/resolver/PublicKeyResolver.ts +++ b/federation/src/graphql/api/1_0/resolver/PublicKeyResolver.ts @@ -11,8 +11,10 @@ export class PublicKeyResolver { async getPublicKey(): Promise { logger.debug(`getPublicKey() via apiVersion=1_0 ...`) const homeCom = await DbFederatedCommunity.findOneOrFail({ - foreign: false, - apiVersion: '1_0', + where: { + foreign: false, + apiVersion: '1_0', + }, }) logger.info(`getPublicKey()-1_0... return publicKey=${homeCom.publicKey}`) return new GetPublicKeyResult(homeCom.publicKey.toString()) diff --git a/federation/src/typeorm/DBVersion.ts b/federation/src/typeorm/DBVersion.ts index bdb909c1d..267dfd57e 100644 --- a/federation/src/typeorm/DBVersion.ts +++ b/federation/src/typeorm/DBVersion.ts @@ -3,7 +3,7 @@ import { federationLogger as logger } from '@/server/logger' const getDBVersion = async (): Promise => { try { - const dbVersion = await Migration.findOne({ order: { version: 'DESC' } }) + const [dbVersion] = await Migration.find({ order: { version: 'DESC' }, take: 1 }) return dbVersion ? dbVersion.fileName : null } catch (error) { logger.error(error) From 27006be4ae2d7057590b3d8124d5f4896436563b Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Mon, 26 Jun 2023 14:21:35 +0200 Subject: [PATCH 06/17] undo changed comming from user query for find contributions --- .../resolver/ContributionResolver.test.ts | 58 ------------------- .../graphql/resolver/ContributionResolver.ts | 3 - .../resolver/util/findContributions.ts | 33 ++--------- 3 files changed, 6 insertions(+), 88 deletions(-) diff --git a/backend/src/graphql/resolver/ContributionResolver.test.ts b/backend/src/graphql/resolver/ContributionResolver.test.ts index 81e913dde..d4c84b4f3 100644 --- a/backend/src/graphql/resolver/ContributionResolver.test.ts +++ b/backend/src/graphql/resolver/ContributionResolver.test.ts @@ -2890,64 +2890,6 @@ describe('ContributionResolver', () => { ]), }) }) - - describe('with query', () => { - it('returns the creations of queried user', async () => { - const result = await query({ - query: adminListContributions, - variables: { - currentPage: 1, - pageSize: 2, - order: Order.DESC, - query: 'peter', - }, - }) - const { - data: { adminListContributions: contributionListObject }, - } = await query({ - query: adminListContributions, - variables: { - currentPage: 1, - pageSize: 2, - order: Order.DESC, - query: 'peter', - }, - }) - expect(contributionListObject.contributionList).toHaveLength(3) - expect(contributionListObject).toMatchObject({ - contributionCount: 3, - contributionList: expect.arrayContaining([ - expect.objectContaining({ - amount: expect.decimalEqual(400), - firstName: 'Peter', - id: expect.any(Number), - lastName: 'Lustig', - memo: 'Herzlich Willkommen bei Gradido!', - messagesCount: 0, - state: 'PENDING', - }), - expect.objectContaining({ - amount: expect.decimalEqual(100), - firstName: 'Peter', - id: expect.any(Number), - lastName: 'Lustig', - memo: 'Test env contribution', - messagesCount: 0, - state: 'PENDING', - }), - expect.objectContaining({ - amount: expect.decimalEqual(200), - firstName: 'Peter', - id: expect.any(Number), - lastName: 'Lustig', - memo: 'Das war leider zu Viel!', - messagesCount: 0, - state: 'DELETED', - }), - ]), - }) - }) - }) }) }) }) diff --git a/backend/src/graphql/resolver/ContributionResolver.ts b/backend/src/graphql/resolver/ContributionResolver.ts index 9727d6015..2e36eba3f 100644 --- a/backend/src/graphql/resolver/ContributionResolver.ts +++ b/backend/src/graphql/resolver/ContributionResolver.ts @@ -372,8 +372,6 @@ export class ContributionResolver { statusFilter?: ContributionStatus[] | null, @Arg('userId', () => Int, { nullable: true }) userId?: number | null, - @Arg('query', () => String, { nullable: true }) - query?: string | null, ): Promise { const [dbContributions, count] = await findContributions({ order, @@ -383,7 +381,6 @@ export class ContributionResolver { userId, relations: ['user', 'messages'], statusFilter, - query, }) return new ContributionListResult( diff --git a/backend/src/graphql/resolver/util/findContributions.ts b/backend/src/graphql/resolver/util/findContributions.ts index 66038538a..28984d5b1 100644 --- a/backend/src/graphql/resolver/util/findContributions.ts +++ b/backend/src/graphql/resolver/util/findContributions.ts @@ -1,4 +1,4 @@ -import { In, Like, FindOperator } from '@dbTools/typeorm' +import { In } from '@dbTools/typeorm' import { Contribution as DbContribution } from '@entity/Contribution' import { ContributionStatus } from '@enum/ContributionStatus' @@ -12,48 +12,27 @@ interface FindContributionsOptions { relations?: string[] userId?: number | null statusFilter?: ContributionStatus[] | null - query?: string | null } export const findContributions = async ( options: FindContributionsOptions, ): Promise<[DbContribution[], number]> => { - const { order, currentPage, pageSize, withDeleted, relations, userId, statusFilter, query } = { + const { order, currentPage, pageSize, withDeleted, relations, userId, statusFilter } = { withDeleted: false, relations: [], - query: '', ...options, } - const where: { - userId?: number | undefined - contributionStatus?: FindOperator | undefined - user?: Record>[] | undefined - } = { - ...(statusFilter?.length && { contributionStatus: In(statusFilter) }), - ...(userId && { userId }), - } - - if (query) { - where.user = [ - { firstName: Like(`%${query}%`) }, - { lastName: Like(`%${query}%`) }, - // emailContact: { email: Like(`%${query}%`) }, - ] - } - return DbContribution.findAndCount({ - relations: { - user: { - emailContact: true, - }, - messages: true, + where: { + ...(statusFilter?.length && { contributionStatus: In(statusFilter) }), + ...(userId && { userId }), }, withDeleted, - where, order: { createdAt: order, id: order, }, + relations, skip: (currentPage - 1) * pageSize, take: pageSize, }) From 95e7888d90e8703ce0e7c8880097d5a301d966c4 Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Mon, 26 Jun 2023 15:57:43 +0200 Subject: [PATCH 07/17] try to get unit tests and seeds running again --- .../resolver/ContributionResolver.test.ts | 8 +- .../resolver/TransactionResolver.test.ts | 12 +- .../src/graphql/resolver/UserResolver.test.ts | 163 +++++++++--------- backend/src/graphql/resolver/UserResolver.ts | 12 +- backend/src/seeds/factory/creation.ts | 9 +- backend/src/seeds/factory/transactionLink.ts | 2 +- backend/src/seeds/factory/user.ts | 4 +- backend/src/seeds/index.ts | 12 +- backend/test/helpers.ts | 15 +- .../UserContact.ts | 2 +- 10 files changed, 131 insertions(+), 108 deletions(-) diff --git a/backend/src/graphql/resolver/ContributionResolver.test.ts b/backend/src/graphql/resolver/ContributionResolver.test.ts index d4c84b4f3..42fe79ff0 100644 --- a/backend/src/graphql/resolver/ContributionResolver.test.ts +++ b/backend/src/graphql/resolver/ContributionResolver.test.ts @@ -1,7 +1,7 @@ /* eslint-disable @typescript-eslint/no-unsafe-assignment */ /* eslint-disable @typescript-eslint/no-unsafe-member-access */ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { Connection } from '@dbTools/typeorm' +import { Connection, Equal } from '@dbTools/typeorm' import { Contribution } from '@entity/Contribution' import { Event as DbEvent } from '@entity/Event' import { Transaction as DbTransaction } from '@entity/Transaction' @@ -457,7 +457,7 @@ describe('ContributionResolver', () => { describe('contribution has wrong status', () => { beforeAll(async () => { const contribution = await Contribution.findOneOrFail({ - id: pendingContribution.data.createContribution.id, + where: { id: pendingContribution.data.createContribution.id }, }) contribution.contributionStatus = ContributionStatus.DELETED await contribution.save() @@ -469,7 +469,7 @@ describe('ContributionResolver', () => { afterAll(async () => { const contribution = await Contribution.findOneOrFail({ - id: pendingContribution.data.createContribution.id, + where: { id: pendingContribution.data.createContribution.id }, }) contribution.contributionStatus = ContributionStatus.PENDING await contribution.save() @@ -1828,7 +1828,7 @@ describe('ContributionResolver', () => { creation = await Contribution.findOneOrFail({ where: { memo: 'Herzlich Willkommen bei Gradido!', - amount: 400, + amount: Equal(new Decimal('400')), }, }) }) diff --git a/backend/src/graphql/resolver/TransactionResolver.test.ts b/backend/src/graphql/resolver/TransactionResolver.test.ts index 96d434a29..60445e239 100644 --- a/backend/src/graphql/resolver/TransactionResolver.test.ts +++ b/backend/src/graphql/resolver/TransactionResolver.test.ts @@ -346,8 +346,10 @@ describe('send coins', () => { it('stores the TRANSACTION_SEND event in the database', async () => { // Find the exact transaction (sent one is the one with user[1] as user) const transaction = await Transaction.find({ - userId: user[1].id, - memo: 'unrepeatable memo', + where: { + userId: user[1].id, + memo: 'unrepeatable memo', + }, }) await expect(DbEvent.find()).resolves.toContainEqual( @@ -364,8 +366,10 @@ describe('send coins', () => { it('stores the TRANSACTION_RECEIVE event in the database', async () => { // Find the exact transaction (received one is the one with user[0] as user) const transaction = await Transaction.find({ - userId: user[0].id, - memo: 'unrepeatable memo', + where: { + userId: user[0].id, + memo: 'unrepeatable memo', + }, }) await expect(DbEvent.find()).resolves.toContainEqual( diff --git a/backend/src/graphql/resolver/UserResolver.test.ts b/backend/src/graphql/resolver/UserResolver.test.ts index 0384b64c5..bebaa912c 100644 --- a/backend/src/graphql/resolver/UserResolver.test.ts +++ b/backend/src/graphql/resolver/UserResolver.test.ts @@ -195,10 +195,12 @@ describe('UserResolver', () => { }) it('stores the USER_REGISTER event in the database', async () => { - const userConatct = await UserContact.findOneOrFail( - { email: 'peter@lustig.de' }, - { relations: ['user'] }, - ) + const userConatct = await UserContact.findOneOrFail({ + where: { + email: 'peter@lustig.de', + }, + relations: ['user'], + }) await expect(DbEvent.find()).resolves.toContainEqual( expect.objectContaining({ type: EventType.USER_REGISTER, @@ -271,10 +273,10 @@ describe('UserResolver', () => { }) it('stores the EMAIL_ACCOUNT_MULTIREGISTRATION event in the database', async () => { - const userConatct = await UserContact.findOneOrFail( - { email: 'peter@lustig.de' }, - { relations: ['user'] }, - ) + const userConatct = await UserContact.findOneOrFail({ + where: { email: 'peter@lustig.de' }, + relations: ['user'], + }) await expect(DbEvent.find()).resolves.toContainEqual( expect.objectContaining({ type: EventType.EMAIL_ACCOUNT_MULTIREGISTRATION, @@ -292,7 +294,7 @@ describe('UserResolver', () => { variables: { ...variables, email: 'bibi@bloxberg.de', language: 'it' }, }) await expect( - UserContact.findOne({ email: 'bibi@bloxberg.de' }, { relations: ['user'] }), + UserContact.findOne({ where: { email: 'bibi@bloxberg.de' }, relations: ['user'] }), ).resolves.toEqual( expect.objectContaining({ email: 'bibi@bloxberg.de', @@ -334,7 +336,7 @@ describe('UserResolver', () => { }) // make Peter Lustig Admin - const peter = await User.findOneOrFail({ id: user[0].id }) + const peter = await User.findOneOrFail({ where: { id: user[0].id } }) peter.isAdmin = new Date() await peter.save() @@ -365,7 +367,7 @@ describe('UserResolver', () => { it('sets the contribution link id', async () => { await expect( - UserContact.findOne({ email: 'ein@besucher.de' }, { relations: ['user'] }), + UserContact.findOne({ where: { email: 'ein@besucher.de' }, relations: ['user'] }), ).resolves.toEqual( expect.objectContaining({ user: expect.objectContaining({ @@ -445,7 +447,7 @@ describe('UserResolver', () => { memo: `testing transaction link`, }) - transactionLink = await TransactionLink.findOneOrFail() + transactionLink = await TransactionLink.findOneOrFail({}) resetToken() @@ -462,7 +464,7 @@ describe('UserResolver', () => { it('sets the referrer id to bob baumeister id', async () => { await expect( - UserContact.findOne({ email: 'which@ever.de' }, { relations: ['user'] }), + UserContact.findOne({ where: { email: 'which@ever.de' }, relations: ['user'] }), ).resolves.toEqual( expect.objectContaining({ user: expect.objectContaining({ referrerId: bob.data.login.id }), @@ -529,16 +531,18 @@ describe('UserResolver', () => { beforeAll(async () => { await mutate({ mutation: createUser, variables: createUserVariables }) - const emailContact = await UserContact.findOneOrFail({ email: createUserVariables.email }) + const emailContact = await UserContact.findOneOrFail({ + where: { email: createUserVariables.email }, + }) emailVerificationCode = emailContact.emailVerificationCode.toString() result = await mutate({ mutation: setPassword, variables: { code: emailVerificationCode, password: 'Aa12345_' }, }) - newUser = await User.findOneOrFail( - { id: emailContact.userId }, - { relations: ['emailContact'] }, - ) + newUser = await User.findOneOrFail({ + where: { id: emailContact.userId }, + relations: ['emailContact'], + }) }) afterAll(async () => { @@ -571,7 +575,9 @@ describe('UserResolver', () => { describe('no valid password', () => { beforeAll(async () => { await mutate({ mutation: createUser, variables: createUserVariables }) - const emailContact = await UserContact.findOneOrFail({ email: createUserVariables.email }) + const emailContact = await UserContact.findOneOrFail({ + where: { email: createUserVariables.email }, + }) emailVerificationCode = emailContact.emailVerificationCode.toString() }) @@ -697,10 +703,10 @@ describe('UserResolver', () => { }) it('stores the USER_LOGIN event in the database', async () => { - const userConatct = await UserContact.findOneOrFail( - { email: 'bibi@bloxberg.de' }, - { relations: ['user'] }, - ) + const userConatct = await UserContact.findOneOrFail({ + where: { email: 'bibi@bloxberg.de' }, + relations: ['user'], + }) await expect(DbEvent.find()).resolves.toContainEqual( expect.objectContaining({ type: EventType.USER_LOGIN, @@ -879,10 +885,10 @@ describe('UserResolver', () => { }) it('stores the USER_LOGOUT event in the database', async () => { - const userConatct = await UserContact.findOneOrFail( - { email: 'bibi@bloxberg.de' }, - { relations: ['user'] }, - ) + const userConatct = await UserContact.findOneOrFail({ + where: { email: 'bibi@bloxberg.de' }, + relations: ['user'], + }) await expect(DbEvent.find()).resolves.toContainEqual( expect.objectContaining({ type: EventType.USER_LOGOUT, @@ -1047,10 +1053,10 @@ describe('UserResolver', () => { }) it('stores the EMAIL_FORGOT_PASSWORD event in the database', async () => { - const userConatct = await UserContact.findOneOrFail( - { email: 'bibi@bloxberg.de' }, - { relations: ['user'] }, - ) + const userConatct = await UserContact.findOneOrFail({ + where: { email: 'bibi@bloxberg.de' }, + relations: ['user'], + }) await expect(DbEvent.find()).resolves.toContainEqual( expect.objectContaining({ type: EventType.EMAIL_FORGOT_PASSWORD, @@ -1083,7 +1089,7 @@ describe('UserResolver', () => { beforeAll(async () => { await userFactory(testEnv, bibiBloxberg) - emailContact = await UserContact.findOneOrFail({ email: bibiBloxberg.email }) + emailContact = await UserContact.findOneOrFail({ where: { email: bibiBloxberg.email } }) }) afterAll(async () => { @@ -1175,7 +1181,7 @@ describe('UserResolver', () => { locale: 'en', }, }) - await expect(User.findOne()).resolves.toEqual( + await expect(User.findOne({})).resolves.toEqual( expect.objectContaining({ firstName: 'Benjamin', lastName: 'Blümchen', @@ -1185,10 +1191,10 @@ describe('UserResolver', () => { }) it('stores the USER_INFO_UPDATE event in the database', async () => { - const userConatct = await UserContact.findOneOrFail( - { email: 'bibi@bloxberg.de' }, - { relations: ['user'] }, - ) + const userConatct = await UserContact.findOneOrFail({ + where: { email: 'bibi@bloxberg.de' }, + relations: ['user'], + }) await expect(DbEvent.find()).resolves.toContainEqual( expect.objectContaining({ type: EventType.USER_INFO_UPDATE, @@ -1212,7 +1218,7 @@ describe('UserResolver', () => { alias: 'bibi_Bloxberg', }, }) - await expect(User.findOne()).resolves.toEqual( + await expect(User.findOne({})).resolves.toEqual( expect.objectContaining({ alias: 'bibi_Bloxberg', }), @@ -1433,10 +1439,10 @@ describe('UserResolver', () => { let bibi: User beforeAll(async () => { - const usercontact = await UserContact.findOneOrFail( - { email: 'bibi@bloxberg.de' }, - { relations: ['user'] }, - ) + const usercontact = await UserContact.findOneOrFail({ + where: { email: 'bibi@bloxberg.de' }, + relations: ['user'], + }) bibi = usercontact.user bibi.passwordEncryptionType = PasswordEncryptionType.EMAIL bibi.password = SecretKeyCryptographyCreateKey( @@ -1450,10 +1456,10 @@ describe('UserResolver', () => { it('changes to gradidoID on login', async () => { await mutate({ mutation: login, variables }) - const usercontact = await UserContact.findOneOrFail( - { email: 'bibi@bloxberg.de' }, - { relations: ['user'] }, - ) + const usercontact = await UserContact.findOneOrFail({ + where: { email: 'bibi@bloxberg.de' }, + relations: ['user'], + }) bibi = usercontact.user expect(bibi).toEqual( @@ -1590,14 +1596,14 @@ describe('UserResolver', () => { }) it('stores the ADMIN_USER_ROLE_SET event in the database', async () => { - const userConatct = await UserContact.findOneOrFail( - { email: 'bibi@bloxberg.de' }, - { relations: ['user'] }, - ) - const adminConatct = await UserContact.findOneOrFail( - { email: 'peter@lustig.de' }, - { relations: ['user'] }, - ) + const userConatct = await UserContact.findOneOrFail({ + where: { email: 'bibi@bloxberg.de' }, + relations: ['user'], + }) + const adminConatct = await UserContact.findOneOrFail({ + where: { email: 'peter@lustig.de' }, + relations: ['user'], + }) await expect(DbEvent.find()).resolves.toContainEqual( expect.objectContaining({ type: EventType.ADMIN_USER_ROLE_SET, @@ -1792,14 +1798,15 @@ describe('UserResolver', () => { }) it('stores the ADMIN_USER_DELETE event in the database', async () => { - const userConatct = await UserContact.findOneOrFail( - { email: 'bibi@bloxberg.de' }, - { relations: ['user'], withDeleted: true }, - ) - const adminConatct = await UserContact.findOneOrFail( - { email: 'peter@lustig.de' }, - { relations: ['user'] }, - ) + const userConatct = await UserContact.findOneOrFail({ + where: { email: 'bibi@bloxberg.de' }, + relations: ['user'], + withDeleted: true, + }) + const adminConatct = await UserContact.findOneOrFail({ + where: { email: 'peter@lustig.de' }, + relations: ['user'], + }) await expect(DbEvent.find()).resolves.toContainEqual( expect.objectContaining({ type: EventType.ADMIN_USER_DELETE, @@ -1943,10 +1950,10 @@ describe('UserResolver', () => { }) it('sends an account activation email', async () => { - const userConatct = await UserContact.findOneOrFail( - { email: 'bibi@bloxberg.de' }, - { relations: ['user'] }, - ) + const userConatct = await UserContact.findOneOrFail({ + where: { email: 'bibi@bloxberg.de' }, + relations: ['user'], + }) const activationLink = CONFIG.EMAIL_LINK_VERIFICATION.replace( /{optin}/g, userConatct.emailVerificationCode.toString(), @@ -1965,10 +1972,10 @@ describe('UserResolver', () => { }) it('stores the EMAIL_ADMIN_CONFIRMATION event in the database', async () => { - const userConatct = await UserContact.findOneOrFail( - { email: 'bibi@bloxberg.de' }, - { relations: ['user'] }, - ) + const userConatct = await UserContact.findOneOrFail({ + where: { email: 'bibi@bloxberg.de' }, + relations: ['user'], + }) await expect(DbEvent.find()).resolves.toContainEqual( expect.objectContaining({ type: EventType.EMAIL_ADMIN_CONFIRMATION, @@ -2086,14 +2093,14 @@ describe('UserResolver', () => { }) it('stores the ADMIN_USER_UNDELETE event in the database', async () => { - const userConatct = await UserContact.findOneOrFail( - { email: 'bibi@bloxberg.de' }, - { relations: ['user'] }, - ) - const adminConatct = await UserContact.findOneOrFail( - { email: 'peter@lustig.de' }, - { relations: ['user'] }, - ) + const userConatct = await UserContact.findOneOrFail({ + where: { email: 'bibi@bloxberg.de' }, + relations: ['user'], + }) + const adminConatct = await UserContact.findOneOrFail({ + where: { email: 'peter@lustig.de' }, + relations: ['user'], + }) await expect(DbEvent.find()).resolves.toContainEqual( expect.objectContaining({ type: EventType.ADMIN_USER_UNDELETE, diff --git a/backend/src/graphql/resolver/UserResolver.ts b/backend/src/graphql/resolver/UserResolver.ts index 840bb43c9..214da858d 100644 --- a/backend/src/graphql/resolver/UserResolver.ts +++ b/backend/src/graphql/resolver/UserResolver.ts @@ -2,7 +2,7 @@ /* eslint-disable @typescript-eslint/no-unsafe-assignment */ /* eslint-disable @typescript-eslint/no-unsafe-member-access */ /* eslint-disable @typescript-eslint/restrict-template-expressions */ -import { getConnection, getCustomRepository, IsNull, Not, Equal } from '@dbTools/typeorm' +import { getConnection, getCustomRepository, IsNull, Not } from '@dbTools/typeorm' import { ContributionLink as DbContributionLink } from '@entity/ContributionLink' import { TransactionLink as DbTransactionLink } from '@entity/TransactionLink' import { User as DbUser } from '@entity/User' @@ -82,13 +82,13 @@ const newEmailContact = (email: string, userId: number): DbUserContact => { emailContact.type = UserContactType.USER_CONTACT_EMAIL emailContact.emailChecked = false emailContact.emailOptInTypeId = OptInType.EMAIL_OPT_IN_REGISTER - emailContact.emailVerificationCode = random(64) + emailContact.emailVerificationCode = random(64).toString() logger.debug('newEmailContact...successful', emailContact) return emailContact } // eslint-disable-next-line @typescript-eslint/ban-types -export const activationLink = (verificationCode: BigInt): string => { +export const activationLink = (verificationCode: string): string => { logger.debug(`activationLink(${verificationCode})...`) return CONFIG.EMAIL_LINK_SETPASSWORD.replace(/{optin}/g, verificationCode.toString()) } @@ -365,7 +365,7 @@ export class UserResolver { user.emailContact.updatedAt = new Date() user.emailContact.emailResendCount++ - user.emailContact.emailVerificationCode = random(64) + user.emailContact.emailVerificationCode = random(64).toString() user.emailContact.emailOptInTypeId = OptInType.EMAIL_OPT_IN_RESET_PASSWORD await user.emailContact.save().catch(() => { throw new LogError('Unable to save email verification code', user.emailContact) @@ -404,7 +404,7 @@ export class UserResolver { // load code const userContact = await DbUserContact.findOneOrFail({ - where: { emailVerificationCode: Equal(BigInt(code)) }, + where: { emailVerificationCode: code }, relations: ['user'], }).catch(() => { throw new LogError('Could not login with emailVerificationCode') @@ -475,7 +475,7 @@ export class UserResolver { async queryOptIn(@Arg('optIn') optIn: string): Promise { logger.info(`queryOptIn(${optIn})...`) const userContact = await DbUserContact.findOneOrFail({ - where: { emailVerificationCode: Equal(BigInt(optIn)) }, + where: { emailVerificationCode: optIn }, }) logger.debug('found optInCode', userContact) // Code is only valid for `CONFIG.EMAIL_CODE_VALID_TIME` minutes diff --git a/backend/src/seeds/factory/creation.ts b/backend/src/seeds/factory/creation.ts index 5b4c56c57..5ad1b2e4e 100644 --- a/backend/src/seeds/factory/creation.ts +++ b/backend/src/seeds/factory/creation.ts @@ -19,7 +19,10 @@ export const creationFactory = async ( creation: CreationInterface, ): Promise => { const { mutate } = client - await mutate({ mutation: login, variables: { email: creation.email, password: 'Aa12345_' } }) + await mutate({ + mutation: login, + variables: { email: creation.email, password: 'Aa12345_' }, + }) const { data: { createContribution: contribution }, @@ -30,7 +33,9 @@ export const creationFactory = async ( await mutate({ mutation: login, variables: { email: 'peter@lustig.de', password: 'Aa12345_' } }) await mutate({ mutation: confirmContribution, variables: { id: contribution.id } }) - const confirmedContribution = await Contribution.findOneOrFail({ id: contribution.id }) + const confirmedContribution = await Contribution.findOneOrFail({ + where: { id: contribution.id }, + }) if (creation.moveCreationDate) { const transaction = await Transaction.findOneOrFail({ diff --git a/backend/src/seeds/factory/transactionLink.ts b/backend/src/seeds/factory/transactionLink.ts index cab478c4b..b44fe349c 100644 --- a/backend/src/seeds/factory/transactionLink.ts +++ b/backend/src/seeds/factory/transactionLink.ts @@ -32,7 +32,7 @@ export const transactionLinkFactory = async ( } = await mutate({ mutation: createTransactionLink, variables }) if (transactionLink.createdAt || transactionLink.deletedAt) { - const dbTransactionLink = await TransactionLink.findOneOrFail({ id }) + const dbTransactionLink = await TransactionLink.findOneOrFail({ where: { id } }) if (transactionLink.createdAt) { dbTransactionLink.createdAt = transactionLink.createdAt diff --git a/backend/src/seeds/factory/user.ts b/backend/src/seeds/factory/user.ts index 13a274911..d40154e12 100644 --- a/backend/src/seeds/factory/user.ts +++ b/backend/src/seeds/factory/user.ts @@ -19,7 +19,7 @@ export const userFactory = async ( } = await mutate({ mutation: createUser, variables: user }) // console.log('creatUser:', { id }, { user }) // get user from database - let dbUser = await User.findOneOrFail({ id }, { relations: ['emailContact'] }) + let dbUser = await User.findOneOrFail({ where: { id }, relations: ['emailContact'] }) // console.log('dbUser:', dbUser) const emailContact = dbUser.emailContact @@ -33,7 +33,7 @@ export const userFactory = async ( } // get last changes of user from database - dbUser = await User.findOneOrFail({ id }) + dbUser = await User.findOneOrFail({ where: { id } }) if (user.createdAt || user.deletedAt || user.isAdmin) { if (user.createdAt) dbUser.createdAt = user.createdAt diff --git a/backend/src/seeds/index.ts b/backend/src/seeds/index.ts index 77fa51990..bc7950f26 100644 --- a/backend/src/seeds/index.ts +++ b/backend/src/seeds/index.ts @@ -1,3 +1,9 @@ +/* eslint-disable @typescript-eslint/no-unsafe-assignment */ +/* eslint-disable @typescript-eslint/no-explicit-any */ +/* eslint-disable @typescript-eslint/no-unsafe-member-access */ +/* eslint-disable @typescript-eslint/no-unsafe-call */ +/* eslint-disable @typescript-eslint/no-unsafe-return */ + import { entities } from '@entity/index' import { createTestClient } from 'apollo-server-testing' import { name, internet, datatype } from 'faker' @@ -36,12 +42,10 @@ export const cleanDB = async () => { } } -const [entityTypes] = entities - -const resetEntity = async (entity: typeof entityTypes) => { +const resetEntity = async (entity: any) => { const items = await entity.find({ withDeleted: true }) if (items.length > 0) { - const ids = items.map((i) => i.id) + const ids = items.map((e: any) => e.id) await entity.delete(ids) } } diff --git a/backend/test/helpers.ts b/backend/test/helpers.ts index 7f55b3c70..ec9c14795 100644 --- a/backend/test/helpers.ts +++ b/backend/test/helpers.ts @@ -1,4 +1,10 @@ /* eslint-disable @typescript-eslint/unbound-method */ +/* eslint-disable @typescript-eslint/no-unsafe-assignment */ +/* eslint-disable @typescript-eslint/no-unsafe-member-access */ +/* eslint-disable @typescript-eslint/no-explicit-any */ +/* eslint-disable @typescript-eslint/no-unsafe-call */ +/* eslint-disable @typescript-eslint/no-unsafe-return */ + import { entities } from '@entity/index' import { createTestClient } from 'apollo-server-testing' @@ -7,7 +13,6 @@ import { createServer } from '@/server/createServer' import { i18n, logger } from './testSetup' export const headerPushMock = jest.fn((t) => { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access context.token = t.value }) @@ -21,7 +26,7 @@ const context = { } export const cleanDB = async () => { - // this only works as lond we do not have foreign key constraints + // this only works as long we do not have foreign key constraints for (const entity of entities) { await resetEntity(entity) } @@ -36,12 +41,10 @@ export const testEnvironment = async (testLogger = logger, testI18n = i18n) => { return { mutate, query, con } } -const [entityTypes] = entities - -export const resetEntity = async (entity: typeof entityTypes) => { +export const resetEntity = async (entity: anny) => { const items = await entity.find({ withDeleted: true }) if (items.length > 0) { - const ids = items.map((i) => i.id) + const ids = items.map((e: any) => e.id) await entity.delete(ids) } } diff --git a/database/entity/0057-clear_old_password_junk/UserContact.ts b/database/entity/0057-clear_old_password_junk/UserContact.ts index dd06d3bbc..6064a3ea3 100644 --- a/database/entity/0057-clear_old_password_junk/UserContact.ts +++ b/database/entity/0057-clear_old_password_junk/UserContact.ts @@ -32,7 +32,7 @@ export class UserContact extends BaseEntity { email: string @Column({ name: 'email_verification_code', type: 'bigint', unsigned: true, unique: true }) - emailVerificationCode: BigInt + emailVerificationCode: string @Column({ name: 'email_opt_in_type_id' }) emailOptInTypeId: number From 642d2202bf80c5386aeef381eb4e5e675dde8dbd Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Mon, 26 Jun 2023 17:34:32 +0200 Subject: [PATCH 08/17] try to get repository working again --- .../src/graphql/resolver/BalanceResolver.ts | 3 +- .../resolver/TransactionLinkResolver.ts | 8 ++ .../graphql/resolver/TransactionResolver.ts | 3 +- backend/src/seeds/factory/transactionLink.ts | 5 +- backend/src/seeds/index.ts | 1 + backend/src/server/createServer.ts | 1 + .../src/typeorm/repository/TransactionLink.ts | 73 ++++++++++--------- backend/src/util/validate.ts | 5 +- backend/test/helpers.ts | 2 +- 9 files changed, 57 insertions(+), 44 deletions(-) diff --git a/backend/src/graphql/resolver/BalanceResolver.ts b/backend/src/graphql/resolver/BalanceResolver.ts index 9cd133181..9a11093b8 100644 --- a/backend/src/graphql/resolver/BalanceResolver.ts +++ b/backend/src/graphql/resolver/BalanceResolver.ts @@ -6,7 +6,7 @@ import { Decimal } from 'decimal.js-light' import { Resolver, Query, Ctx, Authorized } from 'type-graphql' import { Balance } from '@model/Balance' -import { TransactionLinkRepository } from '@repository/TransactionLink' +import { transactionLinkRepository } from '@repository/TransactionLink' import { RIGHTS } from '@/auth/RIGHTS' import { Context, getUser } from '@/server/context' @@ -77,7 +77,6 @@ export class BalanceResolver { ) // The final balance is reduced by the link amount withheld - const transactionLinkRepository = getCustomRepository(TransactionLinkRepository) const { sumHoldAvailableAmount } = context.sumHoldAvailableAmount ? { sumHoldAvailableAmount: context.sumHoldAvailableAmount } : await transactionLinkRepository.summary(user.id, now) diff --git a/backend/src/graphql/resolver/TransactionLinkResolver.ts b/backend/src/graphql/resolver/TransactionLinkResolver.ts index 0ff606fa5..b198a2335 100644 --- a/backend/src/graphql/resolver/TransactionLinkResolver.ts +++ b/backend/src/graphql/resolver/TransactionLinkResolver.ts @@ -76,14 +76,22 @@ export class TransactionLinkResolver { throw new LogError('Amount must be a positive number', amount) } + console.log('Hallo') + const holdAvailableAmount = amount.minus(calculateDecay(amount, createdDate, validUntil).decay) + console.log(holdAvailableAmount) + // validate amount const sendBalance = await calculateBalance(user.id, holdAvailableAmount.mul(-1), createdDate) + console.log('sendBalance', sendBalance) + if (!sendBalance) { throw new LogError('User has not enough GDD', user.id) } + console.log(sendBalance) + const transactionLink = DbTransactionLink.create() transactionLink.userId = user.id transactionLink.amount = amount diff --git a/backend/src/graphql/resolver/TransactionResolver.ts b/backend/src/graphql/resolver/TransactionResolver.ts index 40e9ec2dd..8a1097b99 100644 --- a/backend/src/graphql/resolver/TransactionResolver.ts +++ b/backend/src/graphql/resolver/TransactionResolver.ts @@ -16,7 +16,7 @@ import { TransactionTypeId } from '@enum/TransactionTypeId' import { Transaction } from '@model/Transaction' import { TransactionList } from '@model/TransactionList' import { User } from '@model/User' -import { TransactionLinkRepository } from '@repository/TransactionLink' +import { transactionLinkRepository } from '@repository/TransactionLink' import { RIGHTS } from '@/auth/RIGHTS' import { @@ -245,7 +245,6 @@ export class TransactionResolver { const self = new User(user) const transactions: Transaction[] = [] - const transactionLinkRepository = getCustomRepository(TransactionLinkRepository) const { sumHoldAvailableAmount, sumAmount, lastDate, firstDate, transactionLinkcount } = await transactionLinkRepository.summary(user.id, now) context.linkCount = transactionLinkcount diff --git a/backend/src/seeds/factory/transactionLink.ts b/backend/src/seeds/factory/transactionLink.ts index b44fe349c..8bbdb64c4 100644 --- a/backend/src/seeds/factory/transactionLink.ts +++ b/backend/src/seeds/factory/transactionLink.ts @@ -24,12 +24,15 @@ export const transactionLinkFactory = async ( memo: transactionLink.memo, } + const result = await mutate({ mutation: createTransactionLink, variables }) + console.log(result) + // get the transaction links's id const { data: { createTransactionLink: { id }, }, - } = await mutate({ mutation: createTransactionLink, variables }) + } = result if (transactionLink.createdAt || transactionLink.deletedAt) { const dbTransactionLink = await TransactionLink.findOneOrFail({ where: { id } }) diff --git a/backend/src/seeds/index.ts b/backend/src/seeds/index.ts index bc7950f26..2560aa883 100644 --- a/backend/src/seeds/index.ts +++ b/backend/src/seeds/index.ts @@ -52,6 +52,7 @@ const resetEntity = async (entity: any) => { const run = async () => { const server = await createServer(context) + console.log(server) const seedClient = createTestClient(server.apollo) const { con } = server await cleanDB() diff --git a/backend/src/server/createServer.ts b/backend/src/server/createServer.ts index c162d9f6f..36a5bd5e0 100644 --- a/backend/src/server/createServer.ts +++ b/backend/src/server/createServer.ts @@ -37,6 +37,7 @@ export const createServer = async ( logger.debug('createServer...') // open mysql connection + console.log('Connection.getInstance') const con = await Connection.getInstance() if (!con?.isConnected) { logger.fatal(`Couldn't open connection to database!`) diff --git a/backend/src/typeorm/repository/TransactionLink.ts b/backend/src/typeorm/repository/TransactionLink.ts index 8a66aa7cf..45586c538 100644 --- a/backend/src/typeorm/repository/TransactionLink.ts +++ b/backend/src/typeorm/repository/TransactionLink.ts @@ -1,41 +1,42 @@ /* eslint-disable @typescript-eslint/no-unsafe-assignment */ /* eslint-disable @typescript-eslint/no-unsafe-argument */ -import { Repository, EntityRepository } from '@dbTools/typeorm' +import { getConnection } from '@dbTools/typeorm' import { TransactionLink as dbTransactionLink } from '@entity/TransactionLink' import { Decimal } from 'decimal.js-light' -@EntityRepository(dbTransactionLink) -export class TransactionLinkRepository extends Repository { - async summary( - userId: number, - date: Date, - ): Promise<{ - sumHoldAvailableAmount: Decimal - sumAmount: Decimal - lastDate: Date | null - firstDate: Date | null - transactionLinkcount: number - }> { - const { sumHoldAvailableAmount, sumAmount, lastDate, firstDate, count } = - await this.createQueryBuilder('transactionLinks') - .select('SUM(transactionLinks.holdAvailableAmount)', 'sumHoldAvailableAmount') - .addSelect('SUM(transactionLinks.amount)', 'sumAmount') - .addSelect('MAX(transactionLinks.validUntil)', 'lastDate') - .addSelect('MIN(transactionLinks.createdAt)', 'firstDate') - .addSelect('COUNT(*)', 'count') - .where('transactionLinks.userId = :userId', { userId }) - .andWhere('transactionLinks.redeemedAt is NULL') - .andWhere('transactionLinks.validUntil > :date', { date }) - .orderBy('transactionLinks.createdAt', 'DESC') - .getRawOne() - return { - sumHoldAvailableAmount: sumHoldAvailableAmount - ? new Decimal(sumHoldAvailableAmount) - : new Decimal(0), - sumAmount: sumAmount ? new Decimal(sumAmount) : new Decimal(0), - lastDate: lastDate || null, - firstDate: firstDate || null, - transactionLinkcount: count || 0, - } - } -} +export const transactionLinkRepository = getConnection() + .getRepository(dbTransactionLink) + .extend({ + async summary( + userId: number, + date: Date, + ): Promise<{ + sumHoldAvailableAmount: Decimal + sumAmount: Decimal + lastDate: Date | null + firstDate: Date | null + transactionLinkcount: number + }> { + const { sumHoldAvailableAmount, sumAmount, lastDate, firstDate, count } = + await this.createQueryBuilder('transactionLinks') + .select('SUM(transactionLinks.holdAvailableAmount)', 'sumHoldAvailableAmount') + .addSelect('SUM(transactionLinks.amount)', 'sumAmount') + .addSelect('MAX(transactionLinks.validUntil)', 'lastDate') + .addSelect('MIN(transactionLinks.createdAt)', 'firstDate') + .addSelect('COUNT(*)', 'count') + .where('transactionLinks.userId = :userId', { userId }) + .andWhere('transactionLinks.redeemedAt is NULL') + .andWhere('transactionLinks.validUntil > :date', { date }) + .orderBy('transactionLinks.createdAt', 'DESC') + .getRawOne() + return { + sumHoldAvailableAmount: sumHoldAvailableAmount + ? new Decimal(sumHoldAvailableAmount) + : new Decimal(0), + sumAmount: sumAmount ? new Decimal(sumAmount) : new Decimal(0), + lastDate: lastDate || null, + firstDate: firstDate || null, + transactionLinkcount: count || 0, + } + }, + }) diff --git a/backend/src/util/validate.ts b/backend/src/util/validate.ts index 22a6ee5db..8c84b06b2 100644 --- a/backend/src/util/validate.ts +++ b/backend/src/util/validate.ts @@ -3,7 +3,7 @@ import { TransactionLink as dbTransactionLink } from '@entity/TransactionLink' import { Decimal } from 'decimal.js-light' import { Decay } from '@model/Decay' -import { TransactionLinkRepository } from '@repository/TransactionLink' +import { transactionLinkRepository } from '@repository/TransactionLink' import { getLastTransaction } from '@/graphql/resolver/util/getLastTransaction' @@ -26,10 +26,11 @@ async function calculateBalance( const lastTransaction = await getLastTransaction(userId) if (!lastTransaction) return null + console.log(lastTransaction) + const decay = calculateDecay(lastTransaction.balance, lastTransaction.balanceDate, time) const balance = decay.balance.add(amount.toString()) - const transactionLinkRepository = getCustomRepository(TransactionLinkRepository) const { sumHoldAvailableAmount } = await transactionLinkRepository.summary(userId, time) // If we want to redeem a link we need to make sure that the link amount is not considered as blocked diff --git a/backend/test/helpers.ts b/backend/test/helpers.ts index ec9c14795..8a541e3e4 100644 --- a/backend/test/helpers.ts +++ b/backend/test/helpers.ts @@ -41,7 +41,7 @@ export const testEnvironment = async (testLogger = logger, testI18n = i18n) => { return { mutate, query, con } } -export const resetEntity = async (entity: anny) => { +export const resetEntity = async (entity: any) => { const items = await entity.find({ withDeleted: true }) if (items.length > 0) { const ids = items.map((e: any) => e.id) From 8553bf59fda699587bbb583be8a189dc35d43e77 Mon Sep 17 00:00:00 2001 From: mahula Date: Tue, 27 Jun 2023 09:59:09 +0200 Subject: [PATCH 09/17] check visibility of email list in e2e email test step --- e2e-tests/cypress/support/step_definitions/email_steps.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/e2e-tests/cypress/support/step_definitions/email_steps.ts b/e2e-tests/cypress/support/step_definitions/email_steps.ts index fdf273def..27c389ab8 100644 --- a/e2e-tests/cypress/support/step_definitions/email_steps.ts +++ b/e2e-tests/cypress/support/step_definitions/email_steps.ts @@ -51,13 +51,13 @@ Then('the user receives an e-mail containing the {string} link', (linkName: stri ) }) -Then('the user receives no password reset e-mail', () { +Then('the user receives no password reset e-mail', () => { cy.origin( Cypress.env('mailserverURL'), { args: { userEMailSite } }, ({ userEMailSite }) => { cy.visit('/') - cy.get(userEMailSite.emailInbox).should('be.visible') + cy.get(userEMailSite.emailList).should('be.visible') cy.get(userEMailSite.emailList) .find('.email-item') From eb99a3243318a9a28f91a1f18c37278f892ada1f Mon Sep 17 00:00:00 2001 From: mahula Date: Tue, 27 Jun 2023 09:59:09 +0200 Subject: [PATCH 10/17] check visibility of email list in e2e email test step --- e2e-tests/cypress/support/step_definitions/email_steps.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/e2e-tests/cypress/support/step_definitions/email_steps.ts b/e2e-tests/cypress/support/step_definitions/email_steps.ts index 27c389ab8..830e86fe5 100644 --- a/e2e-tests/cypress/support/step_definitions/email_steps.ts +++ b/e2e-tests/cypress/support/step_definitions/email_steps.ts @@ -57,7 +57,8 @@ Then('the user receives no password reset e-mail', () => { { args: { userEMailSite } }, ({ userEMailSite }) => { cy.visit('/') - cy.get(userEMailSite.emailList).should('be.visible') + cy.wait(300) + cy.get(userEMailSite.emailInbox).should('be.visible') cy.get(userEMailSite.emailList) .find('.email-item') From 44dedacce5d8caaaa38d8fb589102be4867e56bf Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Wed, 28 Jun 2023 12:16:38 +0200 Subject: [PATCH 11/17] transaction link summary as function, seeds are working again --- .../src/graphql/resolver/BalanceResolver.ts | 6 +-- .../resolver/TransactionLinkResolver.ts | 7 --- .../graphql/resolver/TransactionResolver.ts | 6 +-- .../resolver/util/transactionLinkSummary.ts | 49 +++++++++++++++++++ backend/src/seeds/factory/transactionLink.ts | 5 +- backend/src/seeds/index.ts | 1 - backend/src/server/createServer.ts | 1 - .../src/typeorm/repository/TransactionLink.ts | 42 ---------------- backend/src/util/validate.ts | 7 +-- 9 files changed, 58 insertions(+), 66 deletions(-) create mode 100644 backend/src/graphql/resolver/util/transactionLinkSummary.ts delete mode 100644 backend/src/typeorm/repository/TransactionLink.ts diff --git a/backend/src/graphql/resolver/BalanceResolver.ts b/backend/src/graphql/resolver/BalanceResolver.ts index 9a11093b8..87de0e0f7 100644 --- a/backend/src/graphql/resolver/BalanceResolver.ts +++ b/backend/src/graphql/resolver/BalanceResolver.ts @@ -1,12 +1,11 @@ /* eslint-disable @typescript-eslint/restrict-template-expressions */ -import { getCustomRepository, IsNull } from '@dbTools/typeorm' +import { IsNull } from '@dbTools/typeorm' import { Transaction as dbTransaction } from '@entity/Transaction' import { TransactionLink as dbTransactionLink } from '@entity/TransactionLink' import { Decimal } from 'decimal.js-light' import { Resolver, Query, Ctx, Authorized } from 'type-graphql' import { Balance } from '@model/Balance' -import { transactionLinkRepository } from '@repository/TransactionLink' import { RIGHTS } from '@/auth/RIGHTS' import { Context, getUser } from '@/server/context' @@ -15,6 +14,7 @@ import { calculateDecay } from '@/util/decay' import { GdtResolver } from './GdtResolver' import { getLastTransaction } from './util/getLastTransaction' +import { transactionLinkSummary } from './util/transactionLinkSummary' @Resolver() export class BalanceResolver { @@ -79,7 +79,7 @@ export class BalanceResolver { // The final balance is reduced by the link amount withheld const { sumHoldAvailableAmount } = context.sumHoldAvailableAmount ? { sumHoldAvailableAmount: context.sumHoldAvailableAmount } - : await transactionLinkRepository.summary(user.id, now) + : await transactionLinkSummary(user.id, now) logger.debug(`context.sumHoldAvailableAmount=${context.sumHoldAvailableAmount}`) logger.debug(`sumHoldAvailableAmount=${sumHoldAvailableAmount}`) diff --git a/backend/src/graphql/resolver/TransactionLinkResolver.ts b/backend/src/graphql/resolver/TransactionLinkResolver.ts index b198a2335..c987dc0a0 100644 --- a/backend/src/graphql/resolver/TransactionLinkResolver.ts +++ b/backend/src/graphql/resolver/TransactionLinkResolver.ts @@ -76,22 +76,15 @@ export class TransactionLinkResolver { throw new LogError('Amount must be a positive number', amount) } - console.log('Hallo') - const holdAvailableAmount = amount.minus(calculateDecay(amount, createdDate, validUntil).decay) - console.log(holdAvailableAmount) - // validate amount const sendBalance = await calculateBalance(user.id, holdAvailableAmount.mul(-1), createdDate) - console.log('sendBalance', sendBalance) if (!sendBalance) { throw new LogError('User has not enough GDD', user.id) } - console.log(sendBalance) - const transactionLink = DbTransactionLink.create() transactionLink.userId = user.id transactionLink.amount = amount diff --git a/backend/src/graphql/resolver/TransactionResolver.ts b/backend/src/graphql/resolver/TransactionResolver.ts index 8a1097b99..5f42fb36e 100644 --- a/backend/src/graphql/resolver/TransactionResolver.ts +++ b/backend/src/graphql/resolver/TransactionResolver.ts @@ -2,7 +2,7 @@ /* eslint-disable new-cap */ /* eslint-disable @typescript-eslint/no-non-null-assertion */ -import { getCustomRepository, getConnection, In } from '@dbTools/typeorm' +import { getConnection, In } from '@dbTools/typeorm' import { Transaction as dbTransaction } from '@entity/Transaction' import { TransactionLink as dbTransactionLink } from '@entity/TransactionLink' import { User as dbUser } from '@entity/User' @@ -16,7 +16,6 @@ import { TransactionTypeId } from '@enum/TransactionTypeId' import { Transaction } from '@model/Transaction' import { TransactionList } from '@model/TransactionList' import { User } from '@model/User' -import { transactionLinkRepository } from '@repository/TransactionLink' import { RIGHTS } from '@/auth/RIGHTS' import { @@ -38,6 +37,7 @@ import { MEMO_MAX_CHARS, MEMO_MIN_CHARS } from './const/const' import { findUserByIdentifier } from './util/findUserByIdentifier' import { getLastTransaction } from './util/getLastTransaction' import { getTransactionList } from './util/getTransactionList' +import { transactionLinkSummary } from './util/transactionLinkSummary' export const executeTransaction = async ( amount: Decimal, @@ -246,7 +246,7 @@ export class TransactionResolver { const transactions: Transaction[] = [] const { sumHoldAvailableAmount, sumAmount, lastDate, firstDate, transactionLinkcount } = - await transactionLinkRepository.summary(user.id, now) + await transactionLinkSummary(user.id, now) context.linkCount = transactionLinkcount logger.debug(`transactionLinkcount=${transactionLinkcount}`) context.sumHoldAvailableAmount = sumHoldAvailableAmount diff --git a/backend/src/graphql/resolver/util/transactionLinkSummary.ts b/backend/src/graphql/resolver/util/transactionLinkSummary.ts new file mode 100644 index 000000000..8f5f41f15 --- /dev/null +++ b/backend/src/graphql/resolver/util/transactionLinkSummary.ts @@ -0,0 +1,49 @@ +/* eslint-disable @typescript-eslint/no-unsafe-assignment */ +/* eslint-disable @typescript-eslint/no-unsafe-argument */ +import { getConnection } from '@dbTools/typeorm' +import { TransactionLink as DbTransactionLink } from '@entity/TransactionLink' +import { Decimal } from 'decimal.js-light' + +import { LogError } from '@/server/LogError' + +export const transactionLinkSummary = async ( + userId: number, + date: Date, +): Promise<{ + sumHoldAvailableAmount: Decimal + sumAmount: Decimal + lastDate: Date | null + firstDate: Date | null + transactionLinkcount: number +}> => { + const queryRunner = getConnection().createQueryRunner() + try { + await queryRunner.connect() + const { sumHoldAvailableAmount, sumAmount, lastDate, firstDate, count } = + await queryRunner.manager + .createQueryBuilder(DbTransactionLink, 'transactionLink') + .select('SUM(transactionLink.holdAvailableAmount)', 'sumHoldAvailableAmount') + .addSelect('SUM(transactionLink.amount)', 'sumAmount') + .addSelect('MAX(transactionLink.validUntil)', 'lastDate') + .addSelect('MIN(transactionLink.createdAt)', 'firstDate') + .addSelect('COUNT(*)', 'count') + .where('transactionLink.userId = :userId', { userId }) + .andWhere('transactionLink.redeemedAt is NULL') + .andWhere('transactionLink.validUntil > :date', { date }) + .orderBy('transactionLink.createdAt', 'DESC') + .getRawOne() + return { + sumHoldAvailableAmount: sumHoldAvailableAmount + ? new Decimal(sumHoldAvailableAmount) + : new Decimal(0), + sumAmount: sumAmount ? new Decimal(sumAmount) : new Decimal(0), + lastDate: lastDate || null, + firstDate: firstDate || null, + transactionLinkcount: count || 0, + } + } catch (err) { + throw new LogError('Unable to get transaction link summary', err) + } finally { + await queryRunner.release() + } +} diff --git a/backend/src/seeds/factory/transactionLink.ts b/backend/src/seeds/factory/transactionLink.ts index 8bbdb64c4..b44fe349c 100644 --- a/backend/src/seeds/factory/transactionLink.ts +++ b/backend/src/seeds/factory/transactionLink.ts @@ -24,15 +24,12 @@ export const transactionLinkFactory = async ( memo: transactionLink.memo, } - const result = await mutate({ mutation: createTransactionLink, variables }) - console.log(result) - // get the transaction links's id const { data: { createTransactionLink: { id }, }, - } = result + } = await mutate({ mutation: createTransactionLink, variables }) if (transactionLink.createdAt || transactionLink.deletedAt) { const dbTransactionLink = await TransactionLink.findOneOrFail({ where: { id } }) diff --git a/backend/src/seeds/index.ts b/backend/src/seeds/index.ts index 2560aa883..bc7950f26 100644 --- a/backend/src/seeds/index.ts +++ b/backend/src/seeds/index.ts @@ -52,7 +52,6 @@ const resetEntity = async (entity: any) => { const run = async () => { const server = await createServer(context) - console.log(server) const seedClient = createTestClient(server.apollo) const { con } = server await cleanDB() diff --git a/backend/src/server/createServer.ts b/backend/src/server/createServer.ts index 36a5bd5e0..c162d9f6f 100644 --- a/backend/src/server/createServer.ts +++ b/backend/src/server/createServer.ts @@ -37,7 +37,6 @@ export const createServer = async ( logger.debug('createServer...') // open mysql connection - console.log('Connection.getInstance') const con = await Connection.getInstance() if (!con?.isConnected) { logger.fatal(`Couldn't open connection to database!`) diff --git a/backend/src/typeorm/repository/TransactionLink.ts b/backend/src/typeorm/repository/TransactionLink.ts deleted file mode 100644 index 45586c538..000000000 --- a/backend/src/typeorm/repository/TransactionLink.ts +++ /dev/null @@ -1,42 +0,0 @@ -/* eslint-disable @typescript-eslint/no-unsafe-assignment */ -/* eslint-disable @typescript-eslint/no-unsafe-argument */ -import { getConnection } from '@dbTools/typeorm' -import { TransactionLink as dbTransactionLink } from '@entity/TransactionLink' -import { Decimal } from 'decimal.js-light' - -export const transactionLinkRepository = getConnection() - .getRepository(dbTransactionLink) - .extend({ - async summary( - userId: number, - date: Date, - ): Promise<{ - sumHoldAvailableAmount: Decimal - sumAmount: Decimal - lastDate: Date | null - firstDate: Date | null - transactionLinkcount: number - }> { - const { sumHoldAvailableAmount, sumAmount, lastDate, firstDate, count } = - await this.createQueryBuilder('transactionLinks') - .select('SUM(transactionLinks.holdAvailableAmount)', 'sumHoldAvailableAmount') - .addSelect('SUM(transactionLinks.amount)', 'sumAmount') - .addSelect('MAX(transactionLinks.validUntil)', 'lastDate') - .addSelect('MIN(transactionLinks.createdAt)', 'firstDate') - .addSelect('COUNT(*)', 'count') - .where('transactionLinks.userId = :userId', { userId }) - .andWhere('transactionLinks.redeemedAt is NULL') - .andWhere('transactionLinks.validUntil > :date', { date }) - .orderBy('transactionLinks.createdAt', 'DESC') - .getRawOne() - return { - sumHoldAvailableAmount: sumHoldAvailableAmount - ? new Decimal(sumHoldAvailableAmount) - : new Decimal(0), - sumAmount: sumAmount ? new Decimal(sumAmount) : new Decimal(0), - lastDate: lastDate || null, - firstDate: firstDate || null, - transactionLinkcount: count || 0, - } - }, - }) diff --git a/backend/src/util/validate.ts b/backend/src/util/validate.ts index 8c84b06b2..4780c94e8 100644 --- a/backend/src/util/validate.ts +++ b/backend/src/util/validate.ts @@ -1,11 +1,10 @@ -import { getCustomRepository } from '@dbTools/typeorm' import { TransactionLink as dbTransactionLink } from '@entity/TransactionLink' import { Decimal } from 'decimal.js-light' import { Decay } from '@model/Decay' -import { transactionLinkRepository } from '@repository/TransactionLink' import { getLastTransaction } from '@/graphql/resolver/util/getLastTransaction' +import { transactionLinkSummary } from '@/graphql/resolver/util/transactionLinkSummary' import { calculateDecay } from './decay' @@ -26,12 +25,10 @@ async function calculateBalance( const lastTransaction = await getLastTransaction(userId) if (!lastTransaction) return null - console.log(lastTransaction) - const decay = calculateDecay(lastTransaction.balance, lastTransaction.balanceDate, time) const balance = decay.balance.add(amount.toString()) - const { sumHoldAvailableAmount } = await transactionLinkRepository.summary(userId, time) + const { sumHoldAvailableAmount } = await transactionLinkSummary(userId, time) // If we want to redeem a link we need to make sure that the link amount is not considered as blocked // else we cannot redeem links which are more or equal to half of what an account actually owns From c44807dd506f0c3aa7240ddd59e1fe7cbcab475f Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Wed, 28 Jun 2023 13:04:41 +0200 Subject: [PATCH 12/17] get most tests working again --- .../resolver/ContributionLinkResolver.test.ts | 2 +- .../resolver/KlicktippResolver.test.ts | 16 +++--- .../resolver/TransactionLinkResolver.test.ts | 40 ++++++------- .../src/graphql/resolver/UserResolver.test.ts | 14 +++-- backend/src/graphql/resolver/UserResolver.ts | 11 ++-- .../src/graphql/resolver/util/findUsers.ts | 57 +++++++++++++++++++ .../resolver/util/validateAlias.test.ts | 2 +- 7 files changed, 99 insertions(+), 43 deletions(-) create mode 100644 backend/src/graphql/resolver/util/findUsers.ts diff --git a/backend/src/graphql/resolver/ContributionLinkResolver.test.ts b/backend/src/graphql/resolver/ContributionLinkResolver.test.ts index 801e4560b..9605378e2 100644 --- a/backend/src/graphql/resolver/ContributionLinkResolver.test.ts +++ b/backend/src/graphql/resolver/ContributionLinkResolver.test.ts @@ -542,7 +542,7 @@ describe('Contribution Links', () => { }) it('updated the DB record', async () => { - await expect(DbContributionLink.findOne(linkId)).resolves.toEqual( + await expect(DbContributionLink.findOne({ where: { id: linkId } })).resolves.toEqual( expect.objectContaining({ id: linkId, name: 'Dokumenta 2023', diff --git a/backend/src/graphql/resolver/KlicktippResolver.test.ts b/backend/src/graphql/resolver/KlicktippResolver.test.ts index 6a2250bc9..2c819f070 100644 --- a/backend/src/graphql/resolver/KlicktippResolver.test.ts +++ b/backend/src/graphql/resolver/KlicktippResolver.test.ts @@ -72,10 +72,10 @@ describe('KlicktippResolver', () => { }) it('stores the NEWSLETTER_SUBSCRIBE event in the database', async () => { - const userConatct = await UserContact.findOneOrFail( - { email: 'bibi@bloxberg.de' }, - { relations: ['user'] }, - ) + const userConatct = await UserContact.findOneOrFail({ + where: { email: 'bibi@bloxberg.de' }, + relations: ['user'], + }) await expect(DbEvent.find()).resolves.toContainEqual( expect.objectContaining({ type: EventType.NEWSLETTER_SUBSCRIBE, @@ -121,10 +121,10 @@ describe('KlicktippResolver', () => { }) it('stores the NEWSLETTER_UNSUBSCRIBE event in the database', async () => { - const userConatct = await UserContact.findOneOrFail( - { email: 'bibi@bloxberg.de' }, - { relations: ['user'] }, - ) + const userConatct = await UserContact.findOneOrFail({ + where: { email: 'bibi@bloxberg.de' }, + relations: ['user'], + }) await expect(DbEvent.find()).resolves.toContainEqual( expect.objectContaining({ type: EventType.NEWSLETTER_UNSUBSCRIBE, diff --git a/backend/src/graphql/resolver/TransactionLinkResolver.test.ts b/backend/src/graphql/resolver/TransactionLinkResolver.test.ts index 3c6ba31ab..ac76bdecf 100644 --- a/backend/src/graphql/resolver/TransactionLinkResolver.test.ts +++ b/backend/src/graphql/resolver/TransactionLinkResolver.test.ts @@ -456,10 +456,10 @@ describe('TransactionLinkResolver', () => { }) it('stores the CONTRIBUTION_LINK_REDEEM event in the database', async () => { - const userConatct = await UserContact.findOneOrFail( - { email: 'bibi@bloxberg.de' }, - { relations: ['user'] }, - ) + const userConatct = await UserContact.findOneOrFail({ + where: { email: 'bibi@bloxberg.de' }, + relations: ['user'], + }) await expect(DbEvent.find()).resolves.toContainEqual( expect.objectContaining({ type: EventType.CONTRIBUTION_LINK_REDEEM, @@ -611,10 +611,10 @@ describe('TransactionLinkResolver', () => { }) it('stores the TRANSACTION_LINK_CREATE event in the database', async () => { - const userConatct = await UserContact.findOneOrFail( - { email: 'bibi@bloxberg.de' }, - { relations: ['user'] }, - ) + const userConatct = await UserContact.findOneOrFail({ + where: { email: 'bibi@bloxberg.de' }, + relations: ['user'], + }) await expect(DbEvent.find()).resolves.toContainEqual( expect.objectContaining({ type: EventType.TRANSACTION_LINK_CREATE, @@ -664,10 +664,10 @@ describe('TransactionLinkResolver', () => { }) it('stores the TRANSACTION_LINK_DELETE event in the database', async () => { - const userConatct = await UserContact.findOneOrFail( - { email: 'bibi@bloxberg.de' }, - { relations: ['user'] }, - ) + const userConatct = await UserContact.findOneOrFail({ + where: { email: 'bibi@bloxberg.de' }, + relations: ['user'], + }) await expect(DbEvent.find()).resolves.toContainEqual( expect.objectContaining({ type: EventType.TRANSACTION_LINK_DELETE, @@ -719,14 +719,14 @@ describe('TransactionLinkResolver', () => { }) it('stores the TRANSACTION_LINK_REDEEM event in the database', async () => { - const creator = await UserContact.findOneOrFail( - { email: 'bibi@bloxberg.de' }, - { relations: ['user'] }, - ) - const redeemer = await UserContact.findOneOrFail( - { email: 'peter@lustig.de' }, - { relations: ['user'] }, - ) + const creator = await UserContact.findOneOrFail({ + where: { email: 'bibi@bloxberg.de' }, + relations: ['user'], + }) + const redeemer = await UserContact.findOneOrFail({ + where: { email: 'peter@lustig.de' }, + relations: ['user'], + }) await expect(DbEvent.find()).resolves.toContainEqual( expect.objectContaining({ type: EventType.TRANSACTION_LINK_REDEEM, diff --git a/backend/src/graphql/resolver/UserResolver.test.ts b/backend/src/graphql/resolver/UserResolver.test.ts index bebaa912c..0bd15d7dc 100644 --- a/backend/src/graphql/resolver/UserResolver.test.ts +++ b/backend/src/graphql/resolver/UserResolver.test.ts @@ -447,7 +447,7 @@ describe('UserResolver', () => { memo: `testing transaction link`, }) - transactionLink = await TransactionLink.findOneOrFail({}) + transactionLink = await TransactionLink.findOneOrFail({ where: { userId: bob.id } }) resetToken() @@ -1106,7 +1106,9 @@ describe('UserResolver', () => { errors: [ // keep Whitspace in error message! new GraphQLError(`Could not find any entity of type "UserContact" matching: { - "emailVerificationCode": "not-valid" + "where": { + "emailVerificationCode": "not-valid" + } }`), ], }), @@ -1181,13 +1183,13 @@ describe('UserResolver', () => { locale: 'en', }, }) - await expect(User.findOne({})).resolves.toEqual( + await expect(User.find()).resolves.toEqual([ expect.objectContaining({ firstName: 'Benjamin', lastName: 'Blümchen', language: 'en', }), - ) + ]) }) it('stores the USER_INFO_UPDATE event in the database', async () => { @@ -1218,11 +1220,11 @@ describe('UserResolver', () => { alias: 'bibi_Bloxberg', }, }) - await expect(User.findOne({})).resolves.toEqual( + await expect(User.find()).resolves.toEqual([ expect.objectContaining({ alias: 'bibi_Bloxberg', }), - ) + ]) }) }) }) diff --git a/backend/src/graphql/resolver/UserResolver.ts b/backend/src/graphql/resolver/UserResolver.ts index 214da858d..c3595071e 100644 --- a/backend/src/graphql/resolver/UserResolver.ts +++ b/backend/src/graphql/resolver/UserResolver.ts @@ -2,7 +2,7 @@ /* eslint-disable @typescript-eslint/no-unsafe-assignment */ /* eslint-disable @typescript-eslint/no-unsafe-member-access */ /* eslint-disable @typescript-eslint/restrict-template-expressions */ -import { getConnection, getCustomRepository, IsNull, Not } from '@dbTools/typeorm' +import { getConnection, IsNull, Not } from '@dbTools/typeorm' import { ContributionLink as DbContributionLink } from '@entity/ContributionLink' import { TransactionLink as DbTransactionLink } from '@entity/TransactionLink' import { User as DbUser } from '@entity/User' @@ -23,7 +23,6 @@ import { UserContactType } from '@enum/UserContactType' import { SearchAdminUsersResult } from '@model/AdminUser' import { User } from '@model/User' import { UserAdmin, SearchUsersResult } from '@model/UserAdmin' -import { UserRepository } from '@repository/User' import { subscribe } from '@/apis/KlicktippController' import { encode } from '@/auth/JWT' @@ -65,6 +64,7 @@ import { randombytes_random } from 'sodium-native' import { FULL_CREATION_AVAILABLE } from './const/const' import { getUserCreations } from './util/creations' import { findUserByIdentifier } from './util/findUserByIdentifier' +import { findUsers } from './util/findUsers' import { getKlicktippState } from './util/getKlicktippState' import { validateAlias } from './util/validateAlias' @@ -603,9 +603,7 @@ export class UserResolver { @Args() { currentPage = 1, pageSize = 25, order = Order.DESC }: Paginated, ): Promise { - const userRepository = getCustomRepository(UserRepository) - - const [users, count] = await userRepository.findAndCount({ + const [users, count] = await DbUser.findAndCount({ where: { isAdmin: Not(IsNull()), }, @@ -638,7 +636,6 @@ export class UserResolver { @Ctx() context: Context, ): Promise { const clientTimezoneOffset = getClientTimezoneOffset(context) - const userRepository = getCustomRepository(UserRepository) const userFields = [ 'id', 'firstName', @@ -648,7 +645,7 @@ export class UserResolver { 'deletedAt', 'isAdmin', ] - const [users, count] = await userRepository.findBySearchCriteriaPagedFiltered( + const [users, count] = await findUsers( userFields.map((fieldName) => { return 'user.' + fieldName }), diff --git a/backend/src/graphql/resolver/util/findUsers.ts b/backend/src/graphql/resolver/util/findUsers.ts new file mode 100644 index 000000000..d01afb904 --- /dev/null +++ b/backend/src/graphql/resolver/util/findUsers.ts @@ -0,0 +1,57 @@ +import { getConnection, Brackets, IsNull, Not } from '@dbTools/typeorm' +import { User as DbUser } from '@entity/User' + +import { SearchUsersFilters } from '@arg/SearchUsersFilters' +import { Order } from '@enum/Order' + +import { LogError } from '@/server/LogError' + +export const findUsers = async ( + select: string[], + searchCriteria: string, + filters: SearchUsersFilters | null, + currentPage: number, + pageSize: number, + order = Order.ASC, +): Promise<[DbUser[], number]> => { + const queryRunner = getConnection().createQueryRunner() + try { + await queryRunner.connect() + const query = queryRunner.manager + .createQueryBuilder(DbUser, 'user') + .select(select) + .withDeleted() + .leftJoinAndSelect('user.emailContact', 'emailContact') + .where( + new Brackets((qb) => { + qb.where( + 'user.firstName like :name or user.lastName like :lastName or emailContact.email like :email', + { + name: `%${searchCriteria}%`, + lastName: `%${searchCriteria}%`, + email: `%${searchCriteria}%`, + }, + ) + }), + ) + if (filters) { + if (filters.byActivated !== null) { + query.andWhere('emailContact.emailChecked = :value', { value: filters.byActivated }) + } + + if (filters.byDeleted !== null) { + query.andWhere({ deletedAt: filters.byDeleted ? Not(IsNull()) : IsNull() }) + } + } + + return await query + .orderBy({ 'user.id': order }) + .take(pageSize) + .skip((currentPage - 1) * pageSize) + .getManyAndCount() + } catch (err) { + throw new LogError('Unable to search users', err) + } finally { + await queryRunner.release() + } +} diff --git a/backend/src/graphql/resolver/util/validateAlias.test.ts b/backend/src/graphql/resolver/util/validateAlias.test.ts index 0cb790edb..5003f8975 100644 --- a/backend/src/graphql/resolver/util/validateAlias.test.ts +++ b/backend/src/graphql/resolver/util/validateAlias.test.ts @@ -95,7 +95,7 @@ describe('validate alias', () => { describe('test against existing alias in database', () => { beforeAll(async () => { const bibi = await userFactory(testEnv, bibiBloxberg) - const user = await User.findOne({ id: bibi.id }) + const user = await User.findOne({ where: { id: bibi.id } }) if (user) { user.alias = 'b-b' await user.save() From d81d0cbd536496ea92e57b8674ab3241619facc9 Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Wed, 28 Jun 2023 13:08:41 +0200 Subject: [PATCH 13/17] undo query changes --- backend/src/seeds/graphql/queries.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/backend/src/seeds/graphql/queries.ts b/backend/src/seeds/graphql/queries.ts index 6353fe1cd..a964cdb3a 100644 --- a/backend/src/seeds/graphql/queries.ts +++ b/backend/src/seeds/graphql/queries.ts @@ -235,7 +235,6 @@ export const adminListContributions = gql` $order: Order = DESC $statusFilter: [ContributionStatus!] $userId: Int - $query: String ) { adminListContributions( currentPage: $currentPage @@ -243,7 +242,6 @@ export const adminListContributions = gql` order: $order statusFilter: $statusFilter userId: $userId - query: $query ) { contributionCount contributionList { From abe1d1b71f755ae50a8127eaffb210215f5dd1b6 Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Wed, 28 Jun 2023 13:56:08 +0200 Subject: [PATCH 14/17] remove unused file --- backend/src/typeorm/repository/User.ts | 56 -------------------------- 1 file changed, 56 deletions(-) delete mode 100644 backend/src/typeorm/repository/User.ts diff --git a/backend/src/typeorm/repository/User.ts b/backend/src/typeorm/repository/User.ts deleted file mode 100644 index f54859f41..000000000 --- a/backend/src/typeorm/repository/User.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { Brackets, EntityRepository, IsNull, Not, Repository } from '@dbTools/typeorm' -import { User as DbUser } from '@entity/User' - -import { SearchUsersFilters } from '@arg/SearchUsersFilters' -import { Order } from '@enum/Order' - -@EntityRepository(DbUser) -export class UserRepository extends Repository { - async findBySearchCriteriaPagedFiltered( - select: string[], - searchCriteria: string, - filters: SearchUsersFilters | null, - currentPage: number, - pageSize: number, - order = Order.ASC, - ): Promise<[DbUser[], number]> { - const query = this.createQueryBuilder('user') - .select(select) - .withDeleted() - .leftJoinAndSelect('user.emailContact', 'emailContact') - .where( - new Brackets((qb) => { - qb.where( - 'user.firstName like :name or user.lastName like :lastName or emailContact.email like :email', - { - name: `%${searchCriteria}%`, - lastName: `%${searchCriteria}%`, - email: `%${searchCriteria}%`, - }, - ) - }), - ) - /* - filterCriteria.forEach((filter) => { - query.andWhere(filter) - }) - */ - if (filters) { - if (filters.byActivated !== null) { - query.andWhere('emailContact.emailChecked = :value', { value: filters.byActivated }) - // filterCriteria.push({ 'emailContact.emailChecked': filters.byActivated }) - } - - if (filters.byDeleted !== null) { - // filterCriteria.push({ deletedAt: filters.byDeleted ? Not(IsNull()) : IsNull() }) - query.andWhere({ deletedAt: filters.byDeleted ? Not(IsNull()) : IsNull() }) - } - } - - return query - .orderBy({ 'user.id': order }) - .take(pageSize) - .skip((currentPage - 1) * pageSize) - .getManyAndCount() - } -} From 1b335f00ec34f30dc90f3ac3d3b68b5b5aeaf490 Mon Sep 17 00:00:00 2001 From: mahula Date: Wed, 28 Jun 2023 20:36:33 +0200 Subject: [PATCH 15/17] set cypress test retries to 0 --- e2e-tests/cypress.config.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/e2e-tests/cypress.config.ts b/e2e-tests/cypress.config.ts index 1424ab99f..a9dbc9b7f 100644 --- a/e2e-tests/cypress.config.ts +++ b/e2e-tests/cypress.config.ts @@ -49,10 +49,7 @@ export default defineConfig({ viewportHeight: 720, viewportWidth: 1280, video: false, - retries: { - runMode: 2, - openMode: 0, - }, + retries: 0, env: { backendURL: 'http://localhost:4000', mailserverURL: 'http://localhost:1080', From b4d54cfc6456265dae63f961ff3327c4bcd36d1b Mon Sep 17 00:00:00 2001 From: mahula Date: Thu, 29 Jun 2023 10:11:50 +0200 Subject: [PATCH 16/17] refactor e2e email step definition --- .../cypress/support/step_definitions/email_steps.ts | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/e2e-tests/cypress/support/step_definitions/email_steps.ts b/e2e-tests/cypress/support/step_definitions/email_steps.ts index 207e5781f..80581ad01 100644 --- a/e2e-tests/cypress/support/step_definitions/email_steps.ts +++ b/e2e-tests/cypress/support/step_definitions/email_steps.ts @@ -49,7 +49,7 @@ Then('the user receives an e-mail containing the {string} link', (linkName: stri .invoke('text') .then((text) => { const emailLink = text.match(linkPattern)[0] - cy.task('setEmailLink', emailLink) + cy.task('setEmailLink', emailLink ) }) }, ) @@ -64,9 +64,12 @@ Then('the user receives no password reset e-mail', () => { cy.wait(300) cy.get(userEMailSite.emailInbox).should('be.visible') - cy.get(userEMailSite.emailList) - .find('.email-item') - .should('have.length', 0) + cy.get(userEMailSite.emailList).then(($emailList) => { + const emailItems = $emailList.find('.email-item') + if (emailItems.length > 0) { + expect(emailItems.filter(`:contains("asswor")`).length).to.equal(0) + } + }) } ) }) From 00c15a9c18fe7fdb63310241905e0c030efddbd3 Mon Sep 17 00:00:00 2001 From: mahula Date: Thu, 29 Jun 2023 11:45:59 +0200 Subject: [PATCH 17/17] fix linting --- .../support/step_definitions/email_steps.ts | 28 ++++++++----------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/e2e-tests/cypress/support/step_definitions/email_steps.ts b/e2e-tests/cypress/support/step_definitions/email_steps.ts index 80581ad01..414490cda 100644 --- a/e2e-tests/cypress/support/step_definitions/email_steps.ts +++ b/e2e-tests/cypress/support/step_definitions/email_steps.ts @@ -49,29 +49,25 @@ Then('the user receives an e-mail containing the {string} link', (linkName: stri .invoke('text') .then((text) => { const emailLink = text.match(linkPattern)[0] - cy.task('setEmailLink', emailLink ) + cy.task('setEmailLink', emailLink) }) }, ) }) Then('the user receives no password reset e-mail', () => { - cy.origin( - Cypress.env('mailserverURL'), - { args: { userEMailSite } }, - ({ userEMailSite }) => { - cy.visit('/') - cy.wait(300) - cy.get(userEMailSite.emailInbox).should('be.visible') + cy.origin(Cypress.env('mailserverURL'), { args: { userEMailSite } }, ({ userEMailSite }) => { + cy.visit('/') + cy.wait(300) + cy.get(userEMailSite.emailInbox).should('be.visible') - cy.get(userEMailSite.emailList).then(($emailList) => { - const emailItems = $emailList.find('.email-item') - if (emailItems.length > 0) { - expect(emailItems.filter(`:contains("asswor")`).length).to.equal(0) - } - }) - } - ) + cy.get(userEMailSite.emailList).then(($emailList) => { + const emailItems = $emailList.find('.email-item') + if (emailItems.length > 0) { + expect(emailItems.filter(`:contains("asswor")`).length).to.equal(0) + } + }) + }) }) When(