From a240d76d15e4b86b3ac4a214b4214ef75e854352 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Fri, 10 Mar 2023 00:21:03 +0100 Subject: [PATCH 01/28] remove unused interfaces --- database/src/interface/TransactionContext.ts | 12 -------- database/src/interface/UserContext.ts | 26 ---------------- database/src/interface/UserInterface.ts | 32 -------------------- 3 files changed, 70 deletions(-) delete mode 100644 database/src/interface/TransactionContext.ts delete mode 100644 database/src/interface/UserContext.ts delete mode 100644 database/src/interface/UserInterface.ts diff --git a/database/src/interface/TransactionContext.ts b/database/src/interface/TransactionContext.ts deleted file mode 100644 index 8eeb579a0..000000000 --- a/database/src/interface/TransactionContext.ts +++ /dev/null @@ -1,12 +0,0 @@ -import Decimal from 'decimal.js-light' - -export interface TransactionContext { - typeId: number - userId: number - balance: Decimal - balanceDate: Date - amount: Decimal - memo: string - creationDate?: Date - sendReceiverUserId?: number -} diff --git a/database/src/interface/UserContext.ts b/database/src/interface/UserContext.ts deleted file mode 100644 index f3ccaecf4..000000000 --- a/database/src/interface/UserContext.ts +++ /dev/null @@ -1,26 +0,0 @@ -export interface UserContext { - pubKey?: Buffer - email?: string - firstName?: string - lastName?: string - deletedAt?: Date - password?: BigInt - privKey?: Buffer - emailHash?: Buffer - createdAt?: Date - emailChecked?: boolean - language?: string - publisherId?: number - passphrase?: string -} - -export interface ServerUserContext { - username?: string - password?: string - email?: string - role?: string - activated?: number - lastLogin?: Date - created?: Date - modified?: Date -} diff --git a/database/src/interface/UserInterface.ts b/database/src/interface/UserInterface.ts deleted file mode 100644 index ca328c092..000000000 --- a/database/src/interface/UserInterface.ts +++ /dev/null @@ -1,32 +0,0 @@ -import Decimal from 'decimal.js-light' - -export interface UserInterface { - // from user - email?: string - firstName?: string - lastName?: string - password?: BigInt - pubKey?: Buffer - privKey?: Buffer - emailHash?: Buffer - createdAt?: Date - emailChecked?: boolean - language?: string - deletedAt?: Date - publisherId?: number - passphrase?: string - // from server user - serverUserPassword?: string - role?: string - activated?: number - lastLogin?: Date - modified?: Date - // flag for admin - isAdmin?: boolean - // flag for balance (creation of 1000 GDD) - addBalance?: boolean - // balance - recordDate?: Date - creationDate?: Date - amount?: Decimal -} From 66c09d0615ece9104dd553cfa7e8004f68ef2779 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Fri, 10 Mar 2023 00:21:16 +0100 Subject: [PATCH 02/28] remove typeorm connection --- database/src/typeorm/connection.ts | 27 --------------------------- 1 file changed, 27 deletions(-) delete mode 100644 database/src/typeorm/connection.ts diff --git a/database/src/typeorm/connection.ts b/database/src/typeorm/connection.ts deleted file mode 100644 index e3434c3aa..000000000 --- a/database/src/typeorm/connection.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { createConnection, Connection } from 'typeorm' -import CONFIG from '../config' -import { entities } from '../../entity/index' - -const connection = async (): Promise => { - let con = null - try { - con = await createConnection({ - name: 'default', - type: 'mysql', - host: CONFIG.DB_HOST, - port: CONFIG.DB_PORT, - username: CONFIG.DB_USER, - password: CONFIG.DB_PASSWORD, - database: CONFIG.DB_DATABASE, - entities, - synchronize: false, - }) - } catch (error) { - // eslint-disable-next-line no-console - console.log(error) - } - - return con -} - -export default connection From 7d548968012e9a7ad6f0e855804c6042c07667f8 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Fri, 10 Mar 2023 00:21:27 +0100 Subject: [PATCH 03/28] refactor all main scripts --- database/src/helpers.ts | 34 ---------------------------------- database/src/index.ts | 33 +++++++++++++++++++++------------ database/src/prepare.ts | 16 +++++++--------- 3 files changed, 28 insertions(+), 55 deletions(-) delete mode 100644 database/src/helpers.ts diff --git a/database/src/helpers.ts b/database/src/helpers.ts deleted file mode 100644 index 710094548..000000000 --- a/database/src/helpers.ts +++ /dev/null @@ -1,34 +0,0 @@ -import CONFIG from './config' -import { createPool, PoolConfig } from 'mysql' -import { Migration } from 'ts-mysql-migrate' -import path from 'path' - -const poolConfig: PoolConfig = { - host: CONFIG.DB_HOST, - port: CONFIG.DB_PORT, - user: CONFIG.DB_USER, - password: CONFIG.DB_PASSWORD, - database: CONFIG.DB_DATABASE, -} - -// Pool? -const pool = createPool(poolConfig) - -// Create & Initialize Migrations -const migration = new Migration({ - conn: pool, - tableName: CONFIG.MIGRATIONS_TABLE, - silent: true, - dir: path.join(__dirname, '..', 'migrations'), -}) - -const initialize = async (): Promise => { - await migration.initialize() -} - -const resetDB = async (closePool = false): Promise => { - await migration.reset() // use for resetting database - if (closePool) pool.end() -} - -export { resetDB, pool, migration, initialize } diff --git a/database/src/index.ts b/database/src/index.ts index a9504063e..2d83bc52b 100644 --- a/database/src/index.ts +++ b/database/src/index.ts @@ -1,18 +1,28 @@ import 'reflect-metadata' -import prepare from './prepare' -import connection from './typeorm/connection' -import { resetDB, pool, migration } from './helpers' +import { createDatabase } from './prepare' +import CONFIG from './config' + +import { createPool, Pool } from 'mysql' +import { Migration } from 'ts-mysql-migrate' +import path from 'path' const run = async (command: string) => { // Database actions not supported by our migration library - await prepare() - - // Database connection for TypeORM - const con = await connection() - if (!con || !con.isConnected) { - throw new Error(`Couldn't open connection to database`) - } + await createDatabase() + const pool = createPool({ + host: CONFIG.DB_HOST, + port: CONFIG.DB_PORT, + user: CONFIG.DB_USER, + password: CONFIG.DB_PASSWORD, + database: CONFIG.DB_DATABASE, + }) + const migration = new Migration({ + conn: pool, + tableName: CONFIG.MIGRATIONS_TABLE, + silent: true, + dir: path.join(__dirname, '..', 'migrations'), + }) await migration.initialize() // Execute command @@ -25,14 +35,13 @@ const run = async (command: string) => { break case 'reset': // TODO protect from production - await resetDB() // use for resetting database + await migration.reset() break default: throw new Error(`Unsupported command ${command}`) } // Terminate connections gracefully - await con.close() pool.end() } diff --git a/database/src/prepare.ts b/database/src/prepare.ts index 440289aea..de47f7336 100644 --- a/database/src/prepare.ts +++ b/database/src/prepare.ts @@ -1,15 +1,8 @@ -/* PREPARE SCRIPT - * - * This file ensures operations our migration library - * can not take care of are done. - * This applies to all Database Operations like - * creating, deleting, renaming Databases. - */ +import { createConnection } from 'mysql2/promise' -import { createConnection, RowDataPacket } from 'mysql2/promise' import CONFIG from './config' -export default async (): Promise => { +const createDatabase = async (): Promise => { const con = await createConnection({ host: CONFIG.DB_HOST, port: CONFIG.DB_PORT, @@ -25,6 +18,8 @@ export default async (): Promise => { DEFAULT CHARACTER SET utf8mb4 DEFAULT COLLATE utf8mb4_unicode_ci;`) + /* LEGACY CODE + import { RowDataPacket } from 'mysql2/promise' // Check if old migration table is present, delete if needed const [rows] = await con.query(`SHOW TABLES FROM \`${CONFIG.DB_DATABASE}\` LIKE 'migrations';`) if ((rows).length > 0) { @@ -37,6 +32,9 @@ export default async (): Promise => { console.log('Found and dropped old migrations table') } } + */ await con.end() } + +export { createDatabase } From 6a7dac0cc643ef953664d19172c80affd90f3099 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Fri, 10 Mar 2023 00:21:37 +0100 Subject: [PATCH 04/28] cleaned test helpers --- backend/test/helpers.ts | 2 -- dht-node/test/helpers.ts | 2 -- 2 files changed, 4 deletions(-) diff --git a/backend/test/helpers.ts b/backend/test/helpers.ts index 1935b01a0..50bd3eb3f 100644 --- a/backend/test/helpers.ts +++ b/backend/test/helpers.ts @@ -3,7 +3,6 @@ import { createTestClient } from 'apollo-server-testing' import createServer from '../src/server/createServer' -import { initialize } from '@dbTools/helpers' import { entities } from '@entity/index' import { i18n, logger } from './testSetup' @@ -33,7 +32,6 @@ export const testEnvironment = async (testLogger: any = logger, testI18n: any = const testClient = createTestClient(server.apollo) const mutate = testClient.mutate const query = testClient.query - await initialize() return { mutate, query, con } } diff --git a/dht-node/test/helpers.ts b/dht-node/test/helpers.ts index f298bed1c..aa7f94964 100644 --- a/dht-node/test/helpers.ts +++ b/dht-node/test/helpers.ts @@ -4,7 +4,6 @@ import CONFIG from '@/config' import connection from '@/typeorm/connection' import { checkDBVersion } from '@/typeorm/DBVersion' -import { initialize } from '@dbTools/helpers' import { entities } from '@entity/index' import { logger } from './testSetup' @@ -42,7 +41,6 @@ export const testEnvironment = async () => { logger.fatal('Fatal: Database Version incorrect') throw new Error('Fatal: Database Version incorrect') } - await initialize() return { con } } From 331a4e12051dbe3be3c8c3303745129c8849751e Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Fri, 10 Mar 2023 00:24:00 +0100 Subject: [PATCH 05/28] lint fix --- database/src/index.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/database/src/index.ts b/database/src/index.ts index 2d83bc52b..48056ab55 100644 --- a/database/src/index.ts +++ b/database/src/index.ts @@ -2,7 +2,7 @@ import 'reflect-metadata' import { createDatabase } from './prepare' import CONFIG from './config' -import { createPool, Pool } from 'mysql' +import { createPool } from 'mysql' import { Migration } from 'ts-mysql-migrate' import path from 'path' @@ -10,6 +10,7 @@ const run = async (command: string) => { // Database actions not supported by our migration library await createDatabase() + // Initialize Migrations const pool = createPool({ host: CONFIG.DB_HOST, port: CONFIG.DB_PORT, From 6549fdea0b80038bb0c43a29ecd927005dd4cfcf Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Fri, 10 Mar 2023 19:19:57 +0100 Subject: [PATCH 06/28] more rules --- backend/.eslintrc.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/.eslintrc.js b/backend/.eslintrc.js index d8d232b25..fe05b6f1b 100644 --- a/backend/.eslintrc.js +++ b/backend/.eslintrc.js @@ -57,7 +57,7 @@ module.exports = { 'import/no-absolute-path': 'error', 'import/no-cycle': 'error', 'import/no-dynamic-require': 'error', - 'import/no-internal-modules': 'off', + 'import/no-internal-modules': 'off', // TODO 'import/no-relative-packages': 'error', 'import/no-relative-parent-imports': ['error', { ignore: ['@/*'] }], 'import/no-self-import': 'error', From 95ac9a8cc693cc4398ca451fa38e74bbb54d9812 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Fri, 10 Mar 2023 18:40:39 +0100 Subject: [PATCH 07/28] eslint-plugin-n + fixes --- backend/.eslintrc.js | 41 ++++++++++++++++++- backend/jest.config.js | 2 + backend/package.json | 4 ++ backend/src/config/index.ts | 1 + backend/src/index.ts | 7 +--- backend/src/middleware/klicktippMiddleware.ts | 1 + backend/src/server/plugins.ts | 1 + backend/yarn.lock | 31 +++++++++++++- 8 files changed, 81 insertions(+), 7 deletions(-) diff --git a/backend/.eslintrc.js b/backend/.eslintrc.js index fe05b6f1b..f3c5f0b45 100644 --- a/backend/.eslintrc.js +++ b/backend/.eslintrc.js @@ -5,7 +5,7 @@ module.exports = { node: true, }, parser: '@typescript-eslint/parser', - plugins: ['prettier', '@typescript-eslint', 'type-graphql', 'jest', 'import'], + plugins: ['prettier', '@typescript-eslint', 'type-graphql', 'jest', 'import', 'n'], extends: [ 'standard', 'eslint:recommended', @@ -78,6 +78,45 @@ module.exports = { 'import/no-unassigned-import': 'error', 'import/order': 'error', 'import/prefer-default-export': 'off', // TODO + // n + 'n/handle-callback-err': 'error', + 'n/no-callback-literal': 'error', + 'n/no-exports-assign': 'error', + 'n/no-extraneous-import': 'error', + 'n/no-extraneous-require': 'error', + 'n/no-hide-core-modules': 'error', + 'n/no-missing-import': 'off', // not compatible with typescript + 'n/no-missing-require': 'error', + 'n/no-new-require': 'error', + 'n/no-path-concat': 'error', + 'n/no-process-exit': 'error', + 'n/no-unpublished-bin': 'error', + 'n/no-unpublished-import': 'off', // TODO need to exclude seeds + 'n/no-unpublished-require': 'error', + 'n/no-unsupported-features': ['error', { ignores: ['modules'] }], + 'n/no-unsupported-features/es-builtins': 'error', + 'n/no-unsupported-features/es-syntax': 'error', + 'n/no-unsupported-features/node-builtins': 'error', + 'n/process-exit-as-throw': 'error', + 'n/shebang': 'error', + 'n/callback-return': 'error', + 'n/exports-style': 'error', + 'n/file-extension-in-import': ['error', 'never'], + 'n/global-require': 'error', + 'n/no-mixed-requires': 'error', + 'n/no-process-env': 'error', + 'n/no-restricted-import': 'error', + 'n/no-restricted-require': 'error', + 'n/no-sync': 'error', + 'n/prefer-global/buffer': 'error', + 'n/prefer-global/console': 'error', + 'n/prefer-global/process': 'error', + 'n/prefer-global/text-decoder': 'error', + 'n/prefer-global/text-encoder': 'error', + 'n/prefer-global/url': 'error', + 'n/prefer-global/url-search-params': 'error', + 'n/prefer-promises/dns': 'error', + 'n/prefer-promises/fs': 'error', }, overrides: [ // only for ts files diff --git a/backend/jest.config.js b/backend/jest.config.js index a6ae81d5f..f5dc0c069 100644 --- a/backend/jest.config.js +++ b/backend/jest.config.js @@ -17,10 +17,12 @@ module.exports = { '@repository/(.*)': '/src/typeorm/repository/$1', '@test/(.*)': '/test/$1', '@entity/(.*)': + // eslint-disable-next-line n/no-process-env process.env.NODE_ENV === 'development' ? '/../database/entity/$1' : '/../database/build/entity/$1', '@dbTools/(.*)': + // eslint-disable-next-line n/no-process-env process.env.NODE_ENV === 'development' ? '/../database/src/$1' : '/../database/build/src/$1', diff --git a/backend/package.json b/backend/package.json index d48db9b51..256c1d5cd 100644 --- a/backend/package.json +++ b/backend/package.json @@ -65,6 +65,7 @@ "eslint-import-resolver-typescript": "^3.5.3", "eslint-plugin-import": "^2.27.5", "eslint-plugin-jest": "^27.2.1", + "eslint-plugin-n": "^15.6.1", "eslint-plugin-node": "^11.1.0", "eslint-plugin-prettier": "^3.4.0", "eslint-plugin-promise": "^5.1.0", @@ -83,5 +84,8 @@ "ignore": [ "**/*.test.ts" ] + }, + "engines": { + "node": ">=19" } } diff --git a/backend/src/config/index.ts b/backend/src/config/index.ts index d4e5f56a8..942357c0b 100644 --- a/backend/src/config/index.ts +++ b/backend/src/config/index.ts @@ -1,5 +1,6 @@ // ATTENTION: DO NOT PUT ANY SECRETS IN HERE (or the .env) +/* eslint-disable n/no-process-env */ import dotenv from 'dotenv' import { Decimal } from 'decimal.js-light' diff --git a/backend/src/index.ts b/backend/src/index.ts index cd6d002cc..2917ac9b3 100644 --- a/backend/src/index.ts +++ b/backend/src/index.ts @@ -1,10 +1,7 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ - import createServer from './server/createServer' - -// config -import CONFIG from './config' import { startValidateCommunities } from './federation/validateCommunities' +import CONFIG from '@/config' async function main() { const { app } = await createServer() @@ -23,5 +20,5 @@ async function main() { main().catch((e) => { // eslint-disable-next-line no-console console.error(e) - process.exit(1) + throw e }) diff --git a/backend/src/middleware/klicktippMiddleware.ts b/backend/src/middleware/klicktippMiddleware.ts index 0469b4ccc..8ad0a6111 100644 --- a/backend/src/middleware/klicktippMiddleware.ts +++ b/backend/src/middleware/klicktippMiddleware.ts @@ -26,6 +26,7 @@ export const klicktippNewsletterStateMiddleware: MiddlewareFn = async ( { root, args, context, info }, next, ) => { + // eslint-disable-next-line n/callback-return const result = await next() let klickTipp = new KlickTipp({ status: 'Unsubscribed' }) if (CONFIG.KLICKTIPP) { diff --git a/backend/src/server/plugins.ts b/backend/src/server/plugins.ts index bc2495b71..d113cb4b7 100644 --- a/backend/src/server/plugins.ts +++ b/backend/src/server/plugins.ts @@ -61,6 +61,7 @@ ${JSON.stringify(requestContext.response.errors, null, 2)}`) } const plugins = + // eslint-disable-next-line n/no-process-env process.env.NODE_ENV === 'development' ? [setHeadersPlugin] : [setHeadersPlugin, logPlugin] export default plugins diff --git a/backend/yarn.lock b/backend/yarn.lock index 2a611bd3f..3db6ab6ff 100644 --- a/backend/yarn.lock +++ b/backend/yarn.lock @@ -1998,6 +1998,13 @@ buffer@^6.0.3: base64-js "^1.3.1" ieee754 "^1.2.1" +builtins@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/builtins/-/builtins-5.0.1.tgz#87f6db9ab0458be728564fa81d876d8d74552fa9" + integrity sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ== + dependencies: + semver "^7.0.0" + busboy@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/busboy/-/busboy-0.3.1.tgz#170899274c5bf38aae27d5c62b71268cd585fd1b" @@ -2937,6 +2944,14 @@ eslint-plugin-es@^3.0.0: eslint-utils "^2.0.0" regexpp "^3.0.0" +eslint-plugin-es@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-es/-/eslint-plugin-es-4.1.0.tgz#f0822f0c18a535a97c3e714e89f88586a7641ec9" + integrity sha512-GILhQTnjYE2WorX5Jyi5i4dz5ALWxBIdQECVQavL6s7cI76IZTDWleTHkxz/QT3kvcs2QlGHvKLYsSlPOlPXnQ== + dependencies: + eslint-utils "^2.0.0" + regexpp "^3.0.0" + eslint-plugin-import@^2.27.5: version "2.27.5" resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.27.5.tgz#876a6d03f52608a3e5bb439c2550588e51dd6c65" @@ -2965,6 +2980,20 @@ eslint-plugin-jest@^27.2.1: dependencies: "@typescript-eslint/utils" "^5.10.0" +eslint-plugin-n@^15.6.1: + version "15.6.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-n/-/eslint-plugin-n-15.6.1.tgz#f7e77f24abb92a550115cf11e29695da122c398c" + integrity sha512-R9xw9OtCRxxaxaszTQmQAlPgM+RdGjaL1akWuY/Fv9fRAi8Wj4CUKc6iYVG8QNRjRuo8/BqVYIpfqberJUEacA== + dependencies: + builtins "^5.0.1" + eslint-plugin-es "^4.1.0" + eslint-utils "^3.0.0" + ignore "^5.1.1" + is-core-module "^2.11.0" + minimatch "^3.1.2" + resolve "^1.22.1" + semver "^7.3.8" + eslint-plugin-node@^11.1.0: version "11.1.0" resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz#c95544416ee4ada26740a30474eefc5402dc671d" @@ -6293,7 +6322,7 @@ semver@^6.0.0, semver@^6.1.0, semver@^6.2.0, semver@^6.3.0: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== -semver@^7.3.7: +semver@^7.0.0, semver@^7.3.7, semver@^7.3.8: version "7.3.8" resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.8.tgz#07a78feafb3f7b32347d725e33de7e2a2df67798" integrity sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A== From d6e4fceef969f367d876a749ed997c0f3dd61a36 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Sun, 12 Mar 2023 02:28:27 +0100 Subject: [PATCH 08/28] merge error --- backend/.eslintrc.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/.eslintrc.js b/backend/.eslintrc.js index f3c5f0b45..b33a3e480 100644 --- a/backend/.eslintrc.js +++ b/backend/.eslintrc.js @@ -57,7 +57,7 @@ module.exports = { 'import/no-absolute-path': 'error', 'import/no-cycle': 'error', 'import/no-dynamic-require': 'error', - 'import/no-internal-modules': 'off', // TODO + 'import/no-internal-modules': 'off', 'import/no-relative-packages': 'error', 'import/no-relative-parent-imports': ['error', { ignore: ['@/*'] }], 'import/no-self-import': 'error', From d01b78c74956dd2e38a0894c8d1dd9afcbdd2d95 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Sun, 12 Mar 2023 02:36:16 +0100 Subject: [PATCH 09/28] reduce minimum node version to 14 --- backend/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/package.json b/backend/package.json index 256c1d5cd..afa4f367f 100644 --- a/backend/package.json +++ b/backend/package.json @@ -86,6 +86,6 @@ ] }, "engines": { - "node": ">=19" + "node": ">=14" } } From 0936602cb6133f6e9ba4ec96f8fd9a59d378984b Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Tue, 14 Mar 2023 12:17:10 +0100 Subject: [PATCH 10/28] feat(frontend): send coins via gradidoID --- frontend/src/components/GddSend/TransactionForm.vue | 13 ++++++++++++- frontend/src/components/TransactionRows/Name.vue | 5 +++-- frontend/src/graphql/mutations.js | 1 + frontend/src/graphql/queries.js | 1 + 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/frontend/src/components/GddSend/TransactionForm.vue b/frontend/src/components/GddSend/TransactionForm.vue index b560e0767..51e5c5ece 100644 --- a/frontend/src/components/GddSend/TransactionForm.vue +++ b/frontend/src/components/GddSend/TransactionForm.vue @@ -50,7 +50,7 @@ -
+
+
+ + {{ $t('form.recipient') }} + + + {{ gradidoID }} + +
-
+
{{ itemText }} @@ -36,7 +36,8 @@ export default { methods: { tunnelEmail() { this.$emit('set-tunneled-email', this.linkedUser.email) - if (this.$router.history.current.fullPath !== '/send') this.$router.push({ path: '/send' }) + if (this.$router.history.current.fullPath !== '/send') + this.$router.push({ path: '/send', query: { gradidoID: this.linkedUser.gradidoID } }) }, }, computed: { diff --git a/frontend/src/graphql/mutations.js b/frontend/src/graphql/mutations.js index 55858b09b..0f173d3b9 100644 --- a/frontend/src/graphql/mutations.js +++ b/frontend/src/graphql/mutations.js @@ -144,6 +144,7 @@ export const createContributionMessage = gql` export const login = gql` mutation($email: String!, $password: String!, $publisherId: Int) { login(email: $email, password: $password, publisherId: $publisherId) { + gradidoID email firstName lastName diff --git a/frontend/src/graphql/queries.js b/frontend/src/graphql/queries.js index 7193eded0..45f360610 100644 --- a/frontend/src/graphql/queries.js +++ b/frontend/src/graphql/queries.js @@ -38,6 +38,7 @@ export const transactionsQuery = gql` linkedUser { firstName lastName + gradidoID email } decay { From 8db5c055e5ae39777ef164349c35b4a03b32a58c Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Tue, 14 Mar 2023 13:08:51 +0100 Subject: [PATCH 11/28] simple user query and test --- backend/src/auth/RIGHTS.ts | 1 + backend/src/auth/ROLES.ts | 1 + .../src/graphql/resolver/UserResolver.test.ts | 104 +++++++++++++++++- backend/src/graphql/resolver/UserResolver.ts | 15 +++ backend/src/seeds/graphql/queries.ts | 9 ++ 5 files changed, 129 insertions(+), 1 deletion(-) diff --git a/backend/src/auth/RIGHTS.ts b/backend/src/auth/RIGHTS.ts index 22be48e40..3f39f1424 100644 --- a/backend/src/auth/RIGHTS.ts +++ b/backend/src/auth/RIGHTS.ts @@ -36,6 +36,7 @@ export enum RIGHTS { CREATE_CONTRIBUTION_MESSAGE = 'CREATE_CONTRIBUTION_MESSAGE', LIST_ALL_CONTRIBUTION_MESSAGES = 'LIST_ALL_CONTRIBUTION_MESSAGES', OPEN_CREATIONS = 'OPEN_CREATIONS', + USER = 'USER', // Admin SEARCH_USERS = 'SEARCH_USERS', SET_USER_ROLE = 'SET_USER_ROLE', diff --git a/backend/src/auth/ROLES.ts b/backend/src/auth/ROLES.ts index 2f3b4e081..df1ee0271 100644 --- a/backend/src/auth/ROLES.ts +++ b/backend/src/auth/ROLES.ts @@ -34,6 +34,7 @@ export const ROLE_USER = new Role('user', [ RIGHTS.CREATE_CONTRIBUTION_MESSAGE, RIGHTS.LIST_ALL_CONTRIBUTION_MESSAGES, RIGHTS.OPEN_CREATIONS, + RIGHTS.USER, ]) export const ROLE_ADMIN = new Role('admin', Object.values(RIGHTS)) // all rights diff --git a/backend/src/graphql/resolver/UserResolver.test.ts b/backend/src/graphql/resolver/UserResolver.test.ts index a57346583..c75678439 100644 --- a/backend/src/graphql/resolver/UserResolver.test.ts +++ b/backend/src/graphql/resolver/UserResolver.test.ts @@ -26,7 +26,13 @@ import { unDeleteUser, sendActivationEmail, } from '@/seeds/graphql/mutations' -import { verifyLogin, queryOptIn, searchAdminUsers, searchUsers } from '@/seeds/graphql/queries' +import { + verifyLogin, + queryOptIn, + searchAdminUsers, + searchUsers, + user as userQuery, +} from '@/seeds/graphql/queries' import { GraphQLError } from 'graphql' import { User } from '@entity/User' import CONFIG from '@/config' @@ -2189,6 +2195,102 @@ describe('UserResolver', () => { }) }) }) + + describe('user', () => { + beforeEach(() => { + jest.clearAllMocks() + }) + + describe('unauthenticated', () => { + it('throws and logs "401 Unauthorized" error', async () => { + await expect( + query({ + query: userQuery, + variables: { + identifier: 'identifier', + }, + }), + ).resolves.toEqual( + expect.objectContaining({ + errors: [new GraphQLError('401 Unauthorized')], + }), + ) + expect(logger.error).toBeCalledWith('401 Unauthorized') + }) + }) + + describe('authenticated', () => { + beforeAll(async () => { + user = await userFactory(testEnv, bibiBloxberg) + await mutate({ + mutation: login, + variables: { email: 'bibi@bloxberg.de', password: 'Aa12345_' }, + }) + }) + + describe('identifier is no gradido ID', () => { + it('throws and logs "No valid gradido ID" error', async () => { + await expect( + query({ + query: userQuery, + variables: { + identifier: 'identifier', + }, + }), + ).resolves.toEqual( + expect.objectContaining({ + errors: [new GraphQLError('No valid gradido ID')], + }), + ) + expect(logger.error).toBeCalledWith('No valid gradido ID', 'identifier') + }) + }) + + describe('identifier is not found', () => { + it('throws and logs "No user found to given identifier" error', async () => { + await expect( + query({ + query: userQuery, + variables: { + identifier: '00000000-0000-0000-0000-000000000000', + }, + }), + ).resolves.toEqual( + expect.objectContaining({ + errors: [new GraphQLError('No user found to given identifier')], + }), + ) + expect(logger.error).toBeCalledWith( + 'No user found to given identifier', + '00000000-0000-0000-0000-000000000000', + ) + }) + }) + + describe('identifier is found', () => { + it('returns user', async () => { + await expect( + query({ + query: userQuery, + variables: { + identifier: user.gradidoID, + }, + }), + ).resolves.toEqual( + expect.objectContaining({ + data: { + user: { + firstName: 'Bibi', + lastName: 'Bloxberg', + }, + }, + errors: undefined, + }), + ) + }) + }) + }) + }) }) describe('printTimeDuration', () => { diff --git a/backend/src/graphql/resolver/UserResolver.ts b/backend/src/graphql/resolver/UserResolver.ts index 078a29a8e..c07946f0b 100644 --- a/backend/src/graphql/resolver/UserResolver.ts +++ b/backend/src/graphql/resolver/UserResolver.ts @@ -811,6 +811,21 @@ export class UserResolver { return true } + + @Authorized([RIGHTS.USER]) + @Query(() => User, { nullable: true }) + async user(@Arg('identifier') identifier: string): Promise { + const isGradidoID = + /^[0-9a-f]{8,8}-[0-9a-f]{4,4}-[0-9a-f]{4,4}-[0-9a-f]{4,4}-[0-9a-f]{12,12}$/.exec(identifier) + if (!isGradidoID) { + throw new LogError('No valid gradido ID', identifier) + } + const user = await DbUser.findOne({ where: { gradidoID: identifier } }) + if (!user) { + throw new LogError('No user found to given identifier', identifier) + } + return new User(user) + } } export async function findUserByEmail(email: string): Promise { diff --git a/backend/src/seeds/graphql/queries.ts b/backend/src/seeds/graphql/queries.ts index 299a0103d..7c893586a 100644 --- a/backend/src/seeds/graphql/queries.ts +++ b/backend/src/seeds/graphql/queries.ts @@ -322,3 +322,12 @@ export const listContributionMessages = gql` } } ` + +export const user = gql` + query ($identifier: String!) { + user(identifier: $identifier) { + firstName + lastName + } + } +` From 7232780baed4d76bfcf02012386b6c0b1bea4fe9 Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Tue, 14 Mar 2023 19:25:06 +0100 Subject: [PATCH 12/28] send form with gradido id via url query --- .../components/GddSend/TransactionForm.vue | 25 ++++++++++++++++++- .../src/components/TransactionRows/Name.vue | 4 +-- frontend/src/graphql/queries.js | 9 +++++++ 3 files changed, 35 insertions(+), 3 deletions(-) diff --git a/frontend/src/components/GddSend/TransactionForm.vue b/frontend/src/components/GddSend/TransactionForm.vue index 51e5c5ece..8620337d6 100644 --- a/frontend/src/components/GddSend/TransactionForm.vue +++ b/frontend/src/components/GddSend/TransactionForm.vue @@ -65,7 +65,7 @@ {{ $t('form.recipient') }} - {{ gradidoID }} + {{ userName }}
@@ -129,6 +129,7 @@ import { SEND_TYPES } from '@/pages/Send' import InputEmail from '@/components/Inputs/InputEmail' import InputAmount from '@/components/Inputs/InputAmount' import InputTextarea from '@/components/Inputs/InputTextarea' +import { user as userQuery } from '@/graphql/queries' export default { name: 'TransactionForm', @@ -153,6 +154,7 @@ export default { memo: this.memo, }, radioSelected: this.selected, + userName: '', } }, methods: { @@ -173,11 +175,32 @@ export default { this.form.amount = '' this.form.memo = '' this.$refs.formValidator.validate() + if (this.$route.query && !this.$route.query === {}) this.$router.replace({ query: undefined }) }, setNewRecipientEmail() { this.form.email = this.recipientEmail ? this.recipientEmail : this.form.email }, }, + apollo: { + UserName: { + query() { + return userQuery + }, + fetchPolicy: 'network-only', + variables() { + return { identifier: this.gradidoID } + }, + skip() { + return !this.gradidoID + }, + update({ user }) { + this.userName = `${user.firstName} ${user.lastName}` + }, + error({ message }) { + this.toastError(message) + }, + }, + }, watch: { recipientEmail() { this.setNewRecipientEmail() diff --git a/frontend/src/components/TransactionRows/Name.vue b/frontend/src/components/TransactionRows/Name.vue index 84b235cb3..de87c0ad1 100644 --- a/frontend/src/components/TransactionRows/Name.vue +++ b/frontend/src/components/TransactionRows/Name.vue @@ -36,8 +36,8 @@ export default { methods: { tunnelEmail() { this.$emit('set-tunneled-email', this.linkedUser.email) - if (this.$router.history.current.fullPath !== '/send') - this.$router.push({ path: '/send', query: { gradidoID: this.linkedUser.gradidoID } }) + if (this.$router.history.current.fullPath !== '/send') this.$router.push({ path: '/send' }) + this.$router.push({ query: { gradidoID: this.linkedUser.gradidoID } }) }, }, computed: { diff --git a/frontend/src/graphql/queries.js b/frontend/src/graphql/queries.js index 45f360610..ceaa6043b 100644 --- a/frontend/src/graphql/queries.js +++ b/frontend/src/graphql/queries.js @@ -268,3 +268,12 @@ export const openCreations = gql` } } ` + +export const user = gql` + query($identifier: String!) { + user(identifier: $identifier) { + firstName + lastName + } + } +` From 4c15669c4b38041cc77a250bc85c1323385d8610 Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Tue, 14 Mar 2023 19:48:16 +0100 Subject: [PATCH 13/28] remove unused listeners, remove tunneled email and its methods --- .../src/components/GddSend/TransactionForm.vue | 15 --------------- frontend/src/components/GddTransactionList.vue | 3 --- .../Template/RightSide/LastTransactions.vue | 6 +----- frontend/src/components/TransactionRows/Name.vue | 1 - .../Transactions/TransactionReceive.vue | 1 - .../components/Transactions/TransactionSend.vue | 1 - frontend/src/layouts/DashboardLayout.vue | 12 ------------ frontend/src/pages/Transactions.vue | 1 - 8 files changed, 1 insertion(+), 39 deletions(-) diff --git a/frontend/src/components/GddSend/TransactionForm.vue b/frontend/src/components/GddSend/TransactionForm.vue index 8620337d6..a4e527d95 100644 --- a/frontend/src/components/GddSend/TransactionForm.vue +++ b/frontend/src/components/GddSend/TransactionForm.vue @@ -145,7 +145,6 @@ export default { memo: { type: String, default: '' }, selected: { type: String, default: 'send' }, }, - inject: ['getTunneledEmail'], data() { return { form: { @@ -177,9 +176,6 @@ export default { this.$refs.formValidator.validate() if (this.$route.query && !this.$route.query === {}) this.$router.replace({ query: undefined }) }, - setNewRecipientEmail() { - this.form.email = this.recipientEmail ? this.recipientEmail : this.form.email - }, }, apollo: { UserName: { @@ -201,11 +197,6 @@ export default { }, }, }, - watch: { - recipientEmail() { - this.setNewRecipientEmail() - }, - }, computed: { disabled() { if ( @@ -224,16 +215,10 @@ export default { sendTypes() { return SEND_TYPES }, - recipientEmail() { - return this.getTunneledEmail() - }, gradidoID() { return this.$route.query && this.$route.query.gradidoID }, }, - created() { - this.setNewRecipientEmail() - }, mounted() { if (this.form.email !== '') this.$refs.formValidator.validate() }, diff --git a/frontend/src/components/GddTransactionList.vue b/frontend/src/components/GddTransactionList.vue index deed0dedb..63e203f31 100644 --- a/frontend/src/components/GddTransactionList.vue +++ b/frontend/src/components/GddTransactionList.vue @@ -37,7 +37,6 @@ @@ -45,7 +44,6 @@ @@ -53,7 +51,6 @@ diff --git a/frontend/src/components/Template/RightSide/LastTransactions.vue b/frontend/src/components/Template/RightSide/LastTransactions.vue index 54e959436..b08fbf89a 100644 --- a/frontend/src/components/Template/RightSide/LastTransactions.vue +++ b/frontend/src/components/Template/RightSide/LastTransactions.vue @@ -32,11 +32,7 @@
- +
diff --git a/frontend/src/components/TransactionRows/Name.vue b/frontend/src/components/TransactionRows/Name.vue index de87c0ad1..8695645d8 100644 --- a/frontend/src/components/TransactionRows/Name.vue +++ b/frontend/src/components/TransactionRows/Name.vue @@ -35,7 +35,6 @@ export default { }, methods: { tunnelEmail() { - this.$emit('set-tunneled-email', this.linkedUser.email) if (this.$router.history.current.fullPath !== '/send') this.$router.push({ path: '/send' }) this.$router.push({ query: { gradidoID: this.linkedUser.gradidoID } }) }, diff --git a/frontend/src/components/Transactions/TransactionReceive.vue b/frontend/src/components/Transactions/TransactionReceive.vue index 9d6f0207a..1d7c99ff3 100644 --- a/frontend/src/components/Transactions/TransactionReceive.vue +++ b/frontend/src/components/Transactions/TransactionReceive.vue @@ -14,7 +14,6 @@