From 12f3a7ab4abe56cae81664757070db4508753088 Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Tue, 15 Mar 2022 21:03:55 +0100 Subject: [PATCH 01/16] set up seed for transaction links --- backend/src/seeds/factory/transactionLink.ts | 21 +++++++++++++++++++ backend/src/seeds/index.ts | 7 +++++++ .../TransactionLinkInterface.ts | 5 +++++ backend/src/seeds/transactionLink/index.ts | 10 +++++++++ 4 files changed, 43 insertions(+) create mode 100644 backend/src/seeds/factory/transactionLink.ts create mode 100644 backend/src/seeds/transactionLink/TransactionLinkInterface.ts create mode 100644 backend/src/seeds/transactionLink/index.ts diff --git a/backend/src/seeds/factory/transactionLink.ts b/backend/src/seeds/factory/transactionLink.ts new file mode 100644 index 000000000..c1ea13915 --- /dev/null +++ b/backend/src/seeds/factory/transactionLink.ts @@ -0,0 +1,21 @@ +import { ApolloServerTestClient } from 'apollo-server-testing' +import { createTransactionLink } from '@/seeds/graphql/mutations' +import { login } from '@/seeds/graphql/queries' +import { TransactionLinkInterface } from '@/seeds/transactionLink/TransactionLinkInterface' + +export const transactionLinkFactory = async ( + client: ApolloServerTestClient, + transactionLink: TransactionLinkInterface, +): Promise => { + const { mutate, query } = client + + // login + await query({ query: login, variables: { email: transactionLink.email, password: 'Aa12345_' } }) + + const variables = { + amount: transactionLink.amount, + memo: transactionLink.memo, + } + + await mutate({ mutation: createTransactionLink, variables }) +} diff --git a/backend/src/seeds/index.ts b/backend/src/seeds/index.ts index 3943a63e0..37c9992a7 100644 --- a/backend/src/seeds/index.ts +++ b/backend/src/seeds/index.ts @@ -8,8 +8,10 @@ import { name, internet, random } from 'faker' import { users } from './users/index' import { creations } from './creation/index' +import { transactionLinks } from './transactionLink/index' import { userFactory } from './factory/user' import { creationFactory } from './factory/creation' +import { transactionLinkFactory } from './factory/transactionLink' import { entities } from '@entity/index' const context = { @@ -64,6 +66,11 @@ const run = async () => { await creationFactory(seedClient, creations[i]) } + // create Transaction Links + for (let i = 0; i < transactionLinks.length; i++) { + await transactionLinkFactory(seedClient, transactionLinks[i]) + } + await con.close() } diff --git a/backend/src/seeds/transactionLink/TransactionLinkInterface.ts b/backend/src/seeds/transactionLink/TransactionLinkInterface.ts new file mode 100644 index 000000000..94b14992b --- /dev/null +++ b/backend/src/seeds/transactionLink/TransactionLinkInterface.ts @@ -0,0 +1,5 @@ +export interface TransactionLinkInterface { + email: string + amount: number + memo: string +} diff --git a/backend/src/seeds/transactionLink/index.ts b/backend/src/seeds/transactionLink/index.ts new file mode 100644 index 000000000..cd952c47f --- /dev/null +++ b/backend/src/seeds/transactionLink/index.ts @@ -0,0 +1,10 @@ +import { TransactionLinkInterface } from './TransactionLinkInterface' + +export const transactionLinks: TransactionLinkInterface[] = [ + { + email: 'bibi@bloxberg.de', + amount: 19.99, + memo: `Kein Trick, keine Zauberrei, +bei Gradidio sei dabei!`, + }, +] From 5b9463ca2a20b31278d99b7244d0fadd7058ee27 Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Tue, 15 Mar 2022 21:24:44 +0100 Subject: [PATCH 02/16] seed deleted and outdated transaction links --- .../resolver/TransactionLinkResolver.ts | 2 +- backend/src/seeds/factory/transactionLink.ts | 22 ++++++++++ .../TransactionLinkInterface.ts | 2 + backend/src/seeds/transactionLink/index.ts | 42 +++++++++++++++++++ 4 files changed, 67 insertions(+), 1 deletion(-) diff --git a/backend/src/graphql/resolver/TransactionLinkResolver.ts b/backend/src/graphql/resolver/TransactionLinkResolver.ts index 9e2af6111..32f30807b 100644 --- a/backend/src/graphql/resolver/TransactionLinkResolver.ts +++ b/backend/src/graphql/resolver/TransactionLinkResolver.ts @@ -29,7 +29,7 @@ export const transactionLinkCode = (date: Date): string => { const CODE_VALID_DAYS_DURATION = 14 -const transactionLinkExpireDate = (date: Date): Date => { +export const transactionLinkExpireDate = (date: Date): Date => { const validUntil = new Date(date) return new Date(validUntil.setDate(date.getDate() + CODE_VALID_DAYS_DURATION)) } diff --git a/backend/src/seeds/factory/transactionLink.ts b/backend/src/seeds/factory/transactionLink.ts index c1ea13915..665ae03f3 100644 --- a/backend/src/seeds/factory/transactionLink.ts +++ b/backend/src/seeds/factory/transactionLink.ts @@ -2,6 +2,9 @@ import { ApolloServerTestClient } from 'apollo-server-testing' import { createTransactionLink } from '@/seeds/graphql/mutations' import { login } from '@/seeds/graphql/queries' import { TransactionLinkInterface } from '@/seeds/transactionLink/TransactionLinkInterface' +import { transactionLinkExpireDate } from '@/graphql/resolver/TransactionLinkResolver' +import { TransactionLink } from '@entity/TransactionLink' +import { User } from '@entity/User' export const transactionLinkFactory = async ( client: ApolloServerTestClient, @@ -18,4 +21,23 @@ export const transactionLinkFactory = async ( } await mutate({ mutation: createTransactionLink, variables }) + + if (transactionLink.createdAt || transactionLink.deletedAt) { + const user = await User.findOneOrFail({ where: { email: transactionLink.email } }) + const dbTransactionLink = await TransactionLink.findOneOrFail({ + where: { userId: user.id }, + order: { createdAt: 'DESC' }, + }) + + if (transactionLink.createdAt) { + dbTransactionLink.createdAt = transactionLink.createdAt + dbTransactionLink.validUntil = transactionLinkExpireDate(transactionLink.createdAt) + await dbTransactionLink.save() + } + + if (transactionLink.deletedAt) { + dbTransactionLink.deletedAt = new Date() + await dbTransactionLink.save() + } + } } diff --git a/backend/src/seeds/transactionLink/TransactionLinkInterface.ts b/backend/src/seeds/transactionLink/TransactionLinkInterface.ts index 94b14992b..ddc835b33 100644 --- a/backend/src/seeds/transactionLink/TransactionLinkInterface.ts +++ b/backend/src/seeds/transactionLink/TransactionLinkInterface.ts @@ -2,4 +2,6 @@ export interface TransactionLinkInterface { email: string amount: number memo: string + createdAt?: Date + deletedAt?: boolean } diff --git a/backend/src/seeds/transactionLink/index.ts b/backend/src/seeds/transactionLink/index.ts index cd952c47f..25755c0f2 100644 --- a/backend/src/seeds/transactionLink/index.ts +++ b/backend/src/seeds/transactionLink/index.ts @@ -1,10 +1,52 @@ import { TransactionLinkInterface } from './TransactionLinkInterface' export const transactionLinks: TransactionLinkInterface[] = [ + { + email: 'bibi@bloxberg.de', + amount: 19.99, + memo: 'Leider wollte niemand meine Gradidos zum Neujahr haben :(', + createdAt: new Date(2022, 0, 1), + }, { email: 'bibi@bloxberg.de', amount: 19.99, memo: `Kein Trick, keine Zauberrei, bei Gradidio sei dabei!`, }, + { + email: 'bibi@bloxberg.de', + amount: 19.99, + memo: `Kein Trick, keine Zauberrei, +bei Gradidio sei dabei!`, + }, + { + email: 'bibi@bloxberg.de', + amount: 19.99, + memo: `Kein Trick, keine Zauberrei, +bei Gradidio sei dabei!`, + }, + { + email: 'bibi@bloxberg.de', + amount: 19.99, + memo: `Kein Trick, keine Zauberrei, +bei Gradidio sei dabei!`, + }, + { + email: 'bibi@bloxberg.de', + amount: 19.99, + memo: `Kein Trick, keine Zauberrei, +bei Gradidio sei dabei!`, + }, + { + email: 'bibi@bloxberg.de', + amount: 19.99, + memo: `Kein Trick, keine Zauberrei, +bei Gradidio sei dabei!`, + }, + { + email: 'bibi@bloxberg.de', + amount: 19.99, + memo: 'Da habe ich mich wohl etwas übernommen.', + deletedAt: true, + }, ] From 1182b94075e2b1d0ba2865400dcd680c83a1a728 Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Thu, 17 Mar 2022 08:40:02 +0100 Subject: [PATCH 03/16] createUser returns User object, adopt mutations, reduce db calls in seed --- backend/src/graphql/resolver/UserResolver.ts | 6 +-- backend/src/seeds/factory/user.ts | 47 +++++++++++--------- backend/src/seeds/graphql/mutations.ts | 4 +- frontend/src/graphql/mutations.js | 4 +- 4 files changed, 35 insertions(+), 26 deletions(-) diff --git a/backend/src/graphql/resolver/UserResolver.ts b/backend/src/graphql/resolver/UserResolver.ts index 9896ddc97..a18833d58 100644 --- a/backend/src/graphql/resolver/UserResolver.ts +++ b/backend/src/graphql/resolver/UserResolver.ts @@ -313,10 +313,10 @@ export class UserResolver { } @Authorized([RIGHTS.CREATE_USER]) - @Mutation(() => String) + @Mutation(() => User) async createUser( @Args() { email, firstName, lastName, language, publisherId }: CreateUserArgs, - ): Promise { + ): Promise { // TODO: wrong default value (should be null), how does graphql work here? Is it an required field? // default int publisher_id = 0; @@ -396,7 +396,7 @@ export class UserResolver { } finally { await queryRunner.release() } - return 'success' + return new User(dbUser) } // THis is used by the admin only - should we move it to the admin resolver? diff --git a/backend/src/seeds/factory/user.ts b/backend/src/seeds/factory/user.ts index 6d81f26a6..ff4c1d6c9 100644 --- a/backend/src/seeds/factory/user.ts +++ b/backend/src/seeds/factory/user.ts @@ -11,36 +11,41 @@ export const userFactory = async ( ): Promise => { const { mutate } = client - await mutate({ mutation: createUser, variables: user }) - let dbUser = await User.findOneOrFail({ where: { email: user.email } }) + const { + data: { + createUser: { id }, + }, + } = await mutate({ mutation: createUser, variables: user }) if (user.emailChecked) { - const optin = await LoginEmailOptIn.findOneOrFail({ where: { userId: dbUser.id } }) + const optin = await LoginEmailOptIn.findOneOrFail({ userId: id }) await mutate({ mutation: setPassword, variables: { password: 'Aa12345_', code: optin.verificationCode }, }) } - // refetch data - dbUser = await User.findOneOrFail({ where: { email: user.email } }) + if (user.createdAt || user.deletedAt || user.isAdmin) { + // get user from database + const dbUser = await User.findOneOrFail({ id }) - if (user.createdAt || user.deletedAt) { - if (user.createdAt) dbUser.createdAt = user.createdAt - if (user.deletedAt) dbUser.deletedAt = user.deletedAt - await dbUser.save() - } + if (user.createdAt || user.deletedAt) { + if (user.createdAt) dbUser.createdAt = user.createdAt + if (user.deletedAt) dbUser.deletedAt = user.deletedAt + await dbUser.save() + } - if (user.isAdmin) { - const admin = new ServerUser() - admin.username = dbUser.firstName - admin.password = 'please_refactor' - admin.email = dbUser.email - admin.role = 'admin' - admin.activated = 1 - admin.lastLogin = new Date() - admin.created = dbUser.createdAt - admin.modified = dbUser.createdAt - await admin.save() + if (user.isAdmin) { + const admin = new ServerUser() + admin.username = dbUser.firstName + admin.password = 'please_refactor' + admin.email = dbUser.email + admin.role = 'admin' + admin.activated = 1 + admin.lastLogin = new Date() + admin.created = dbUser.createdAt + admin.modified = dbUser.createdAt + await admin.save() + } } } diff --git a/backend/src/seeds/graphql/mutations.ts b/backend/src/seeds/graphql/mutations.ts index 32232e410..306f4350b 100644 --- a/backend/src/seeds/graphql/mutations.ts +++ b/backend/src/seeds/graphql/mutations.ts @@ -52,7 +52,9 @@ export const createUser = gql` lastName: $lastName language: $language publisherId: $publisherId - ) + ) { + id + } } ` diff --git a/frontend/src/graphql/mutations.js b/frontend/src/graphql/mutations.js index d4bf8c1da..98905e8d6 100644 --- a/frontend/src/graphql/mutations.js +++ b/frontend/src/graphql/mutations.js @@ -52,7 +52,9 @@ export const createUser = gql` lastName: $lastName language: $language publisherId: $publisherId - ) + ) { + id + } } ` From 8a350e7cab44bfda90c62f14c9745b782588c3ce Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Thu, 17 Mar 2022 08:48:49 +0100 Subject: [PATCH 04/16] get user id by login query in seeds --- backend/src/seeds/factory/creation.ts | 14 +++++++------- backend/src/seeds/graphql/queries.ts | 1 + 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/backend/src/seeds/factory/creation.ts b/backend/src/seeds/factory/creation.ts index 980e0b3af..d4d4c8101 100644 --- a/backend/src/seeds/factory/creation.ts +++ b/backend/src/seeds/factory/creation.ts @@ -15,14 +15,14 @@ export const creationFactory = async ( ): Promise => { const { mutate, query } = client - // login as Peter Lustig (admin) - await query({ query: login, variables: { email: 'peter@lustig.de', password: 'Aa12345_' } }) + // login as Peter Lustig (admin) and get his user ID + const { + data: { + login: { id }, + }, + } = await query({ query: login, variables: { email: 'peter@lustig.de', password: 'Aa12345_' } }) - // get Peter Lustig's user id - const peterLustig = await User.findOneOrFail({ where: { email: 'peter@lustig.de' } }) - const variables = { ...creation, moderator: peterLustig.id } - - await mutate({ mutation: createPendingCreation, variables }) + await mutate({ mutation: createPendingCreation, variables: { ...creation, moderator: id } }) // get User const user = await User.findOneOrFail({ where: { email: creation.email } }) diff --git a/backend/src/seeds/graphql/queries.ts b/backend/src/seeds/graphql/queries.ts index 942258fde..04f849727 100644 --- a/backend/src/seeds/graphql/queries.ts +++ b/backend/src/seeds/graphql/queries.ts @@ -3,6 +3,7 @@ import gql from 'graphql-tag' export const login = gql` query ($email: String!, $password: String!, $publisherId: Int) { login(email: $email, password: $password, publisherId: $publisherId) { + id email firstName lastName From 689d6c3fb87ba5b36eddc6bd0d6c8f81b6981f94 Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Thu, 17 Mar 2022 08:58:07 +0100 Subject: [PATCH 05/16] get transaction link id by mutation call --- backend/src/seeds/factory/transactionLink.ts | 14 +++++++------- backend/src/seeds/graphql/mutations.ts | 1 + 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/backend/src/seeds/factory/transactionLink.ts b/backend/src/seeds/factory/transactionLink.ts index 665ae03f3..2f54dc70c 100644 --- a/backend/src/seeds/factory/transactionLink.ts +++ b/backend/src/seeds/factory/transactionLink.ts @@ -4,7 +4,6 @@ import { login } from '@/seeds/graphql/queries' import { TransactionLinkInterface } from '@/seeds/transactionLink/TransactionLinkInterface' import { transactionLinkExpireDate } from '@/graphql/resolver/TransactionLinkResolver' import { TransactionLink } from '@entity/TransactionLink' -import { User } from '@entity/User' export const transactionLinkFactory = async ( client: ApolloServerTestClient, @@ -20,14 +19,15 @@ export const transactionLinkFactory = async ( memo: transactionLink.memo, } - await mutate({ mutation: createTransactionLink, variables }) + // get the transaction links's id + const { + data: { + createTransactionLink: { id }, + }, + } = await mutate({ mutation: createTransactionLink, variables }) if (transactionLink.createdAt || transactionLink.deletedAt) { - const user = await User.findOneOrFail({ where: { email: transactionLink.email } }) - const dbTransactionLink = await TransactionLink.findOneOrFail({ - where: { userId: user.id }, - order: { createdAt: 'DESC' }, - }) + const dbTransactionLink = await TransactionLink.findOneOrFail({ id }) if (transactionLink.createdAt) { dbTransactionLink.createdAt = transactionLink.createdAt diff --git a/backend/src/seeds/graphql/mutations.ts b/backend/src/seeds/graphql/mutations.ts index 306f4350b..19ca2a8d0 100644 --- a/backend/src/seeds/graphql/mutations.ts +++ b/backend/src/seeds/graphql/mutations.ts @@ -67,6 +67,7 @@ export const sendCoins = gql` export const createTransactionLink = gql` mutation ($amount: Decimal!, $memo: String!) { createTransactionLink(amount: $amount, memo: $memo) { + id code } } From 51c06741fcb31879f12c3191870fc8a516728ce7 Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Thu, 17 Mar 2022 09:06:40 +0100 Subject: [PATCH 06/16] get test working with chages to the schema --- backend/src/graphql/resolver/UserResolver.test.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/backend/src/graphql/resolver/UserResolver.test.ts b/backend/src/graphql/resolver/UserResolver.test.ts index 1e1e266fb..66e435207 100644 --- a/backend/src/graphql/resolver/UserResolver.test.ts +++ b/backend/src/graphql/resolver/UserResolver.test.ts @@ -69,7 +69,9 @@ describe('UserResolver', () => { }) it('returns success', () => { - expect(result).toEqual(expect.objectContaining({ data: { createUser: 'success' } })) + expect(result).toEqual( + expect.objectContaining({ data: { createUser: { id: expect.any(Number) } } }), + ) }) describe('valid input data', () => { @@ -331,6 +333,7 @@ describe('UserResolver', () => { email: 'bibi@bloxberg.de', firstName: 'Bibi', hasElopage: false, + id: expect.any(Number), isAdmin: false, klickTipp: { newsletterState: false, From ac11d1fa6019b386112c4beef96908638d8a1193 Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Thu, 17 Mar 2022 09:55:15 +0100 Subject: [PATCH 07/16] store user entity created on authentication check in context to avoid further DB calls --- backend/src/graphql/directive/isAuthorized.ts | 1 + backend/src/graphql/resolver/UserResolver.ts | 10 +++------- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/backend/src/graphql/directive/isAuthorized.ts b/backend/src/graphql/directive/isAuthorized.ts index 159a1614c..84756c45a 100644 --- a/backend/src/graphql/directive/isAuthorized.ts +++ b/backend/src/graphql/directive/isAuthorized.ts @@ -35,6 +35,7 @@ const isAuthorized: AuthChecker = async ({ context }, rights) => { const userRepository = await getCustomRepository(UserRepository) try { const user = await userRepository.findByPubkeyHex(context.pubKey) + context.user = user const countServerUsers = await ServerUser.count({ email: user.email }) context.role = countServerUsers > 0 ? ROLE_ADMIN : ROLE_USER } catch { diff --git a/backend/src/graphql/resolver/UserResolver.ts b/backend/src/graphql/resolver/UserResolver.ts index 9896ddc97..39a983c2b 100644 --- a/backend/src/graphql/resolver/UserResolver.ts +++ b/backend/src/graphql/resolver/UserResolver.ts @@ -14,7 +14,6 @@ import UpdateUserInfosArgs from '@arg/UpdateUserInfosArgs' import { klicktippNewsletterStateMiddleware } from '@/middleware/klicktippMiddleware' import { UserSettingRepository } from '@repository/UserSettingRepository' import { Setting } from '@enum/Setting' -import { UserRepository } from '@repository/User' import { LoginEmailOptIn } from '@entity/LoginEmailOptIn' import { sendResetPasswordEmail } from '@/mailer/sendResetPasswordEmail' import { sendAccountActivationEmail } from '@/mailer/sendAccountActivationEmail' @@ -214,8 +213,7 @@ export class UserResolver { @UseMiddleware(klicktippNewsletterStateMiddleware) async verifyLogin(@Ctx() context: any): Promise { // TODO refactor and do not have duplicate code with login(see below) - const userRepository = getCustomRepository(UserRepository) - const userEntity = await userRepository.findByPubkeyHex(context.pubKey) + const userEntity = context.user const user = new User(userEntity) // user.pubkey = userEntity.pubKey.toString('hex') // Elopage Status & Stored PublisherId @@ -585,8 +583,7 @@ export class UserResolver { }: UpdateUserInfosArgs, @Ctx() context: any, ): Promise { - const userRepository = getCustomRepository(UserRepository) - const userEntity = await userRepository.findByPubkeyHex(context.pubKey) + const userEntity = context.user if (firstName) { userEntity.firstName = firstName @@ -664,8 +661,7 @@ export class UserResolver { @Authorized([RIGHTS.HAS_ELOPAGE]) @Query(() => Boolean) async hasElopage(@Ctx() context: any): Promise { - const userRepository = getCustomRepository(UserRepository) - const userEntity = await userRepository.findByPubkeyHex(context.pubKey).catch() + const userEntity = context.user if (!userEntity) { return false } From fd9292b3d5ca6f97658f840d425e086ad4f1694b Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Thu, 17 Mar 2022 09:57:19 +0100 Subject: [PATCH 08/16] user context in admin interface --- backend/src/graphql/resolver/AdminResolver.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/backend/src/graphql/resolver/AdminResolver.ts b/backend/src/graphql/resolver/AdminResolver.ts index f116c3968..f0210dc8d 100644 --- a/backend/src/graphql/resolver/AdminResolver.ts +++ b/backend/src/graphql/resolver/AdminResolver.ts @@ -129,8 +129,7 @@ export class AdminResolver { throw new Error(`Could not find user with userId: ${userId}`) } // moderator user disabled own account? - const userRepository = getCustomRepository(UserRepository) - const moderatorUser = await userRepository.findByPubkeyHex(context.pubKey) + const moderatorUser = context.user if (moderatorUser.id === userId) { throw new Error('Moderator can not delete his own account!') } @@ -294,8 +293,7 @@ export class AdminResolver { @Mutation(() => Boolean) async confirmPendingCreation(@Arg('id') id: number, @Ctx() context: any): Promise { const pendingCreation = await AdminPendingCreation.findOneOrFail(id) - const userRepository = getCustomRepository(UserRepository) - const moderatorUser = await userRepository.findByPubkeyHex(context.pubKey) + const moderatorUser = context.user if (moderatorUser.id === pendingCreation.userId) throw new Error('Moderator can not confirm own pending creation') From b44ef7175616a9956eec4e7f0d9d49306fa76425 Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Thu, 17 Mar 2022 10:05:07 +0100 Subject: [PATCH 09/16] no double DB calls to get user from db in resolvers --- backend/src/graphql/resolver/BalanceResolver.ts | 6 +----- backend/src/graphql/resolver/GdtResolver.ts | 5 +---- .../graphql/resolver/TransactionLinkResolver.ts | 14 ++++---------- .../src/graphql/resolver/TransactionResolver.ts | 3 +-- 4 files changed, 7 insertions(+), 21 deletions(-) diff --git a/backend/src/graphql/resolver/BalanceResolver.ts b/backend/src/graphql/resolver/BalanceResolver.ts index 12d5b2ba4..09d2fdc92 100644 --- a/backend/src/graphql/resolver/BalanceResolver.ts +++ b/backend/src/graphql/resolver/BalanceResolver.ts @@ -2,9 +2,7 @@ /* eslint-disable @typescript-eslint/explicit-module-boundary-types */ import { Resolver, Query, Ctx, Authorized } from 'type-graphql' -import { getCustomRepository } from '@dbTools/typeorm' import { Balance } from '@model/Balance' -import { UserRepository } from '@repository/User' import { calculateDecay } from '@/util/decay' import { RIGHTS } from '@/auth/RIGHTS' import { Transaction } from '@entity/Transaction' @@ -16,9 +14,7 @@ export class BalanceResolver { @Query(() => Balance) async balance(@Ctx() context: any): Promise { // load user and balance - const userRepository = getCustomRepository(UserRepository) - - const user = await userRepository.findByPubkeyHex(context.pubKey) + const { user } = context const now = new Date() const lastTransaction = await Transaction.findOne( diff --git a/backend/src/graphql/resolver/GdtResolver.ts b/backend/src/graphql/resolver/GdtResolver.ts index c8c4cb331..26ae9b210 100644 --- a/backend/src/graphql/resolver/GdtResolver.ts +++ b/backend/src/graphql/resolver/GdtResolver.ts @@ -2,12 +2,10 @@ /* eslint-disable @typescript-eslint/explicit-module-boundary-types */ import { Resolver, Query, Args, Ctx, Authorized, Arg } from 'type-graphql' -import { getCustomRepository } from '@dbTools/typeorm' import CONFIG from '@/config' import { GdtEntryList } from '@model/GdtEntryList' import Paginated from '@arg/Paginated' import { apiGet } from '@/apis/HttpRequest' -import { UserRepository } from '@repository/User' import { Order } from '@enum/Order' import { RIGHTS } from '@/auth/RIGHTS' @@ -22,8 +20,7 @@ export class GdtResolver { @Ctx() context: any, ): Promise { // load user - const userRepository = getCustomRepository(UserRepository) - const userEntity = await userRepository.findByPubkeyHex(context.pubKey) + const userEntity = context.user try { const resultGDT = await apiGet( diff --git a/backend/src/graphql/resolver/TransactionLinkResolver.ts b/backend/src/graphql/resolver/TransactionLinkResolver.ts index 9e2af6111..ead82e182 100644 --- a/backend/src/graphql/resolver/TransactionLinkResolver.ts +++ b/backend/src/graphql/resolver/TransactionLinkResolver.ts @@ -2,11 +2,9 @@ /* eslint-disable @typescript-eslint/explicit-module-boundary-types */ import { Resolver, Args, Arg, Authorized, Ctx, Mutation, Query } from 'type-graphql' -import { getCustomRepository } from '@dbTools/typeorm' import { TransactionLink } from '@model/TransactionLink' import { TransactionLink as dbTransactionLink } from '@entity/TransactionLink' import { User as dbUser } from '@entity/User' -import { UserRepository } from '@repository/User' import TransactionLinkArgs from '@arg/TransactionLinkArgs' import Paginated from '@arg/Paginated' import { calculateBalance } from '@/util/validate' @@ -42,8 +40,7 @@ export class TransactionLinkResolver { @Args() { amount, memo }: TransactionLinkArgs, @Ctx() context: any, ): Promise { - const userRepository = getCustomRepository(UserRepository) - const user = await userRepository.findByPubkeyHex(context.pubKey) + const { user } = context const createdDate = new Date() const validUntil = transactionLinkExpireDate(createdDate) @@ -74,8 +71,7 @@ export class TransactionLinkResolver { @Authorized([RIGHTS.DELETE_TRANSACTION_LINK]) @Mutation(() => Boolean) async deleteTransactionLink(@Arg('id') id: number, @Ctx() context: any): Promise { - const userRepository = getCustomRepository(UserRepository) - const user = await userRepository.findByPubkeyHex(context.pubKey) + const { user } = context const transactionLink = await dbTransactionLink.findOne({ id }) if (!transactionLink) { @@ -116,8 +112,7 @@ export class TransactionLinkResolver { { currentPage = 1, pageSize = 5, order = Order.DESC }: Paginated, @Ctx() context: any, ): Promise { - const userRepository = getCustomRepository(UserRepository) - const user = await userRepository.findByPubkeyHex(context.pubKey) + const { user } = context // const now = new Date() const transactionLinks = await dbTransactionLink.find({ where: { @@ -137,8 +132,7 @@ export class TransactionLinkResolver { @Authorized([RIGHTS.REDEEM_TRANSACTION_LINK]) @Mutation(() => Boolean) async redeemTransactionLink(@Arg('id') id: number, @Ctx() context: any): Promise { - const userRepository = getCustomRepository(UserRepository) - const user = await userRepository.findByPubkeyHex(context.pubKey) + const { user } = context const transactionLink = await dbTransactionLink.findOneOrFail({ id }) const linkedUser = await dbUser.findOneOrFail({ id: transactionLink.userId }) diff --git a/backend/src/graphql/resolver/TransactionResolver.ts b/backend/src/graphql/resolver/TransactionResolver.ts index f64ba19e9..258ea9da6 100644 --- a/backend/src/graphql/resolver/TransactionResolver.ts +++ b/backend/src/graphql/resolver/TransactionResolver.ts @@ -256,8 +256,7 @@ export class TransactionResolver { @Ctx() context: any, ): Promise { // TODO this is subject to replay attacks - const userRepository = getCustomRepository(UserRepository) - const senderUser = await userRepository.findByPubkeyHex(context.pubKey) + const senderUser = context.user if (senderUser.pubKey.length !== 32) { throw new Error('invalid sender public key') } From 577ca00c460f2f30b77df77029f93f91f38d926d Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Thu, 17 Mar 2022 10:46:29 +0100 Subject: [PATCH 10/16] refactor transaction list query, do not allow user id an only creations as args any more. this query only return the transactions of the logged in user --- backend/src/graphql/arg/Paginated.ts | 6 ------ .../graphql/resolver/TransactionResolver.ts | 19 +++---------------- frontend/src/graphql/queries.js | 14 ++------------ 3 files changed, 5 insertions(+), 34 deletions(-) diff --git a/backend/src/graphql/arg/Paginated.ts b/backend/src/graphql/arg/Paginated.ts index f365165de..97326caf2 100644 --- a/backend/src/graphql/arg/Paginated.ts +++ b/backend/src/graphql/arg/Paginated.ts @@ -11,10 +11,4 @@ export default class Paginated { @Field(() => Order, { nullable: true }) order?: Order - - @Field(() => Boolean, { nullable: true }) - onlyCreations?: boolean - - @Field(() => Int, { nullable: true }) - userId?: number } diff --git a/backend/src/graphql/resolver/TransactionResolver.ts b/backend/src/graphql/resolver/TransactionResolver.ts index 258ea9da6..03640817f 100644 --- a/backend/src/graphql/resolver/TransactionResolver.ts +++ b/backend/src/graphql/resolver/TransactionResolver.ts @@ -17,7 +17,6 @@ import Paginated from '@arg/Paginated' import { Order } from '@enum/Order' -import { UserRepository } from '@repository/User' import { TransactionRepository } from '@repository/Transaction' import { TransactionLinkRepository } from '@repository/TransactionLink' @@ -131,22 +130,11 @@ export class TransactionResolver { @Query(() => TransactionList) async transactionList( @Args() - { - currentPage = 1, - pageSize = 25, - order = Order.DESC, - onlyCreations = false, - userId, - }: Paginated, + { currentPage = 1, pageSize = 25, order = Order.DESC }: Paginated, @Ctx() context: any, ): Promise { const now = new Date() - // find user - const userRepository = getCustomRepository(UserRepository) - // TODO: separate those usecases - this is a security issue - const user = userId - ? await userRepository.findOneOrFail({ id: userId }, { withDeleted: true }) - : await userRepository.findByPubkeyHex(context.pubKey) + const user = context.user // find current balance const lastTransaction = await dbTransaction.findOne( @@ -182,7 +170,6 @@ export class TransactionResolver { pageSize, offset, order, - onlyCreations, ) // find involved users; I am involved @@ -208,7 +195,7 @@ export class TransactionResolver { await transactionLinkRepository.summary(user.id, now) // decay & link transactions - if (!onlyCreations && currentPage === 1 && order === Order.DESC) { + if (currentPage === 1 && order === Order.DESC) { transactions.push( virtualDecayTransaction(lastTransaction.balance, lastTransaction.balanceDate, now, self), ) diff --git a/frontend/src/graphql/queries.js b/frontend/src/graphql/queries.js index 5887d585a..c2efe34d8 100644 --- a/frontend/src/graphql/queries.js +++ b/frontend/src/graphql/queries.js @@ -43,18 +43,8 @@ export const logout = gql` ` export const transactionsQuery = gql` - query( - $currentPage: Int = 1 - $pageSize: Int = 25 - $order: Order = DESC - $onlyCreations: Boolean = false - ) { - transactionList( - currentPage: $currentPage - pageSize: $pageSize - order: $order - onlyCreations: $onlyCreations - ) { + query($currentPage: Int = 1, $pageSize: Int = 25, $order: Order = DESC) { + transactionList(currentPage: $currentPage, pageSize: $pageSize, order: $order) { balanceGDT count linkCount From f21e0ed038340e5999af830b49a1dc74707d60db Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Thu, 17 Mar 2022 11:20:26 +0100 Subject: [PATCH 11/16] only creations transaction list with admin rights --- .../CreationTransactionListFormular.vue | 7 ++- admin/src/graphql/creationTransactionList.js | 22 ++++++++ admin/src/graphql/transactionList.js | 31 ------------ backend/src/auth/RIGHTS.ts | 1 + backend/src/graphql/resolver/AdminResolver.ts | 50 +++++++++++++++---- 5 files changed, 65 insertions(+), 46 deletions(-) create mode 100644 admin/src/graphql/creationTransactionList.js delete mode 100644 admin/src/graphql/transactionList.js diff --git a/admin/src/components/CreationTransactionListFormular.vue b/admin/src/components/CreationTransactionListFormular.vue index 0b78ca4b8..ce2b136a4 100644 --- a/admin/src/components/CreationTransactionListFormular.vue +++ b/admin/src/components/CreationTransactionListFormular.vue @@ -5,7 +5,7 @@