mirror of
https://github.com/IT4Change/gradido.git
synced 2025-12-13 07:45:54 +00:00
use findUserByIdentifier for emails, use it in send coins
This commit is contained in:
parent
4c15669c4b
commit
761ff80b97
@ -4,7 +4,7 @@ import Decimal from 'decimal.js-light'
|
||||
@ArgsType()
|
||||
export default class TransactionSendArgs {
|
||||
@Field(() => String)
|
||||
email: string
|
||||
identifier: string
|
||||
|
||||
@Field(() => Decimal)
|
||||
amount: Decimal
|
||||
|
||||
@ -24,7 +24,6 @@ import { User } from '@entity/User'
|
||||
import { cleanDB, testEnvironment } from '@test/helpers'
|
||||
import { logger } from '@test/testSetup'
|
||||
import { GraphQLError } from 'graphql'
|
||||
import { findUserByEmail } from './UserResolver'
|
||||
|
||||
let mutate: any, query: any, con: any
|
||||
let testEnv: any
|
||||
@ -81,7 +80,7 @@ describe('send coins', () => {
|
||||
await mutate({
|
||||
mutation: sendCoins,
|
||||
variables: {
|
||||
email: 'wrong@email.com',
|
||||
identifier: 'wrong@email.com',
|
||||
amount: 100,
|
||||
memo: 'test',
|
||||
},
|
||||
@ -109,22 +108,20 @@ describe('send coins', () => {
|
||||
await mutate({
|
||||
mutation: sendCoins,
|
||||
variables: {
|
||||
email: 'stephen@hawking.uk',
|
||||
identifier: 'stephen@hawking.uk',
|
||||
amount: 100,
|
||||
memo: 'test',
|
||||
},
|
||||
}),
|
||||
).toEqual(
|
||||
expect.objectContaining({
|
||||
errors: [new GraphQLError('The recipient account was deleted')],
|
||||
errors: [new GraphQLError('No user to given contact')],
|
||||
}),
|
||||
)
|
||||
})
|
||||
|
||||
it('logs the error thrown', async () => {
|
||||
// find peter to check the log
|
||||
const user = await findUserByEmail('stephen@hawking.uk')
|
||||
expect(logger.error).toBeCalledWith('The recipient account was deleted', user)
|
||||
it('logs the error thrown', () => {
|
||||
expect(logger.error).toBeCalledWith('No user to given contact', 'stephen@hawking.uk')
|
||||
})
|
||||
})
|
||||
|
||||
@ -140,22 +137,23 @@ describe('send coins', () => {
|
||||
await mutate({
|
||||
mutation: sendCoins,
|
||||
variables: {
|
||||
email: 'garrick@ollivander.com',
|
||||
identifier: 'garrick@ollivander.com',
|
||||
amount: 100,
|
||||
memo: 'test',
|
||||
},
|
||||
}),
|
||||
).toEqual(
|
||||
expect.objectContaining({
|
||||
errors: [new GraphQLError('The recipient account is not activated')],
|
||||
errors: [new GraphQLError('No user with this credentials')],
|
||||
}),
|
||||
)
|
||||
})
|
||||
|
||||
it('logs the error thrown', async () => {
|
||||
// find peter to check the log
|
||||
const user = await findUserByEmail('garrick@ollivander.com')
|
||||
expect(logger.error).toBeCalledWith('The recipient account is not activated', user)
|
||||
it('logs the error thrown', () => {
|
||||
expect(logger.error).toBeCalledWith(
|
||||
'No user with this credentials',
|
||||
'garrick@ollivander.com',
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
@ -175,7 +173,7 @@ describe('send coins', () => {
|
||||
await mutate({
|
||||
mutation: sendCoins,
|
||||
variables: {
|
||||
email: 'bob@baumeister.de',
|
||||
identifier: 'bob@baumeister.de',
|
||||
amount: 100,
|
||||
memo: 'test',
|
||||
},
|
||||
@ -199,7 +197,7 @@ describe('send coins', () => {
|
||||
await mutate({
|
||||
mutation: sendCoins,
|
||||
variables: {
|
||||
email: 'peter@lustig.de',
|
||||
identifier: 'peter@lustig.de',
|
||||
amount: 100,
|
||||
memo: 'test',
|
||||
},
|
||||
@ -223,7 +221,7 @@ describe('send coins', () => {
|
||||
await mutate({
|
||||
mutation: sendCoins,
|
||||
variables: {
|
||||
email: 'peter@lustig.de',
|
||||
identifier: 'peter@lustig.de',
|
||||
amount: 100,
|
||||
memo: 'test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test t',
|
||||
},
|
||||
@ -247,7 +245,7 @@ describe('send coins', () => {
|
||||
await mutate({
|
||||
mutation: sendCoins,
|
||||
variables: {
|
||||
email: 'peter@lustig.de',
|
||||
identifier: 'peter@lustig.de',
|
||||
amount: 100,
|
||||
memo: 'testing',
|
||||
},
|
||||
@ -297,7 +295,7 @@ describe('send coins', () => {
|
||||
await mutate({
|
||||
mutation: sendCoins,
|
||||
variables: {
|
||||
email: 'peter@lustig.de',
|
||||
identifier: 'peter@lustig.de',
|
||||
amount: -50,
|
||||
memo: 'testing negative',
|
||||
},
|
||||
@ -320,7 +318,7 @@ describe('send coins', () => {
|
||||
await mutate({
|
||||
mutation: sendCoins,
|
||||
variables: {
|
||||
email: 'peter@lustig.de',
|
||||
identifier: 'peter@lustig.de',
|
||||
amount: 50,
|
||||
memo: 'unrepeatable memo',
|
||||
},
|
||||
@ -375,7 +373,7 @@ describe('send coins', () => {
|
||||
mutate({
|
||||
mutation: sendCoins,
|
||||
variables: {
|
||||
email: 'peter@lustig.de',
|
||||
identifier: 'peter@lustig.de',
|
||||
amount: 10,
|
||||
memo: 'first transaction',
|
||||
},
|
||||
@ -391,7 +389,7 @@ describe('send coins', () => {
|
||||
mutate({
|
||||
mutation: sendCoins,
|
||||
variables: {
|
||||
email: 'peter@lustig.de',
|
||||
identifier: 'peter@lustig.de',
|
||||
amount: 20,
|
||||
memo: 'second transaction',
|
||||
},
|
||||
@ -407,7 +405,7 @@ describe('send coins', () => {
|
||||
mutate({
|
||||
mutation: sendCoins,
|
||||
variables: {
|
||||
email: 'peter@lustig.de',
|
||||
identifier: 'peter@lustig.de',
|
||||
amount: 30,
|
||||
memo: 'third transaction',
|
||||
},
|
||||
@ -423,7 +421,7 @@ describe('send coins', () => {
|
||||
mutate({
|
||||
mutation: sendCoins,
|
||||
variables: {
|
||||
email: 'peter@lustig.de',
|
||||
identifier: 'peter@lustig.de',
|
||||
amount: 40,
|
||||
memo: 'fourth transaction',
|
||||
},
|
||||
|
||||
@ -34,7 +34,7 @@ import { EVENT_TRANSACTION_RECEIVE, EVENT_TRANSACTION_SEND } from '@/event/Event
|
||||
|
||||
import { BalanceResolver } from './BalanceResolver'
|
||||
import { MEMO_MAX_CHARS, MEMO_MIN_CHARS } from './const/const'
|
||||
import { findUserByEmail } from './UserResolver'
|
||||
import { findUserByIdentifier } from './util/findUserByIdentifier'
|
||||
|
||||
import { TRANSACTIONS_LOCK } from '@/util/TRANSACTIONS_LOCK'
|
||||
import LogError from '@/server/LogError'
|
||||
@ -307,10 +307,9 @@ export class TransactionResolver {
|
||||
@Authorized([RIGHTS.SEND_COINS])
|
||||
@Mutation(() => Boolean)
|
||||
async sendCoins(
|
||||
@Args() { email, amount, memo }: TransactionSendArgs,
|
||||
@Args() { identifier, amount, memo }: TransactionSendArgs,
|
||||
@Ctx() context: Context,
|
||||
): Promise<boolean> {
|
||||
logger.info(`sendCoins(email=${email}, amount=${amount}, memo=${memo})`)
|
||||
if (amount.lte(0)) {
|
||||
throw new LogError('Amount to send must be positive', amount)
|
||||
}
|
||||
@ -319,13 +318,9 @@ export class TransactionResolver {
|
||||
const senderUser = getUser(context)
|
||||
|
||||
// validate recipient user
|
||||
const recipientUser = await findUserByEmail(email)
|
||||
if (recipientUser.deletedAt) {
|
||||
throw new LogError('The recipient account was deleted', recipientUser)
|
||||
}
|
||||
const emailContact = recipientUser.emailContact
|
||||
if (!emailContact.emailChecked) {
|
||||
throw new LogError('The recipient account is not activated', recipientUser)
|
||||
const recipientUser = await findUserByIdentifier(identifier)
|
||||
if (!recipientUser) {
|
||||
throw new LogError('The recipient user was not found', recipientUser)
|
||||
}
|
||||
|
||||
await executeTransaction(amount, memo, senderUser, recipientUser)
|
||||
|
||||
@ -2228,8 +2228,8 @@ describe('UserResolver', () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('identifier is no gradido ID', () => {
|
||||
it('throws and logs "No valid gradido ID" error', async () => {
|
||||
describe('identifier is no gradido ID and no email', () => {
|
||||
it('throws and logs "Unknown identifier type" error', async () => {
|
||||
await expect(
|
||||
query({
|
||||
query: userQuery,
|
||||
@ -2239,10 +2239,10 @@ describe('UserResolver', () => {
|
||||
}),
|
||||
).resolves.toEqual(
|
||||
expect.objectContaining({
|
||||
errors: [new GraphQLError('No valid gradido ID')],
|
||||
errors: [new GraphQLError('Unknown identifier type')],
|
||||
}),
|
||||
)
|
||||
expect(logger.error).toBeCalledWith('No valid gradido ID', 'identifier')
|
||||
expect(logger.error).toBeCalledWith('Unknown identifier type', 'identifier')
|
||||
})
|
||||
})
|
||||
|
||||
@ -2267,7 +2267,30 @@ describe('UserResolver', () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('identifier is found', () => {
|
||||
describe('identifier is found via email', () => {
|
||||
it('returns user', async () => {
|
||||
await expect(
|
||||
query({
|
||||
query: userQuery,
|
||||
variables: {
|
||||
identifier: 'bibi@bloxberg.de',
|
||||
},
|
||||
}),
|
||||
).resolves.toEqual(
|
||||
expect.objectContaining({
|
||||
data: {
|
||||
user: {
|
||||
firstName: 'Bibi',
|
||||
lastName: 'Bloxberg',
|
||||
},
|
||||
},
|
||||
errors: undefined,
|
||||
}),
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('identifier is found via gradidoID', () => {
|
||||
it('returns user', async () => {
|
||||
await expect(
|
||||
query({
|
||||
|
||||
@ -68,6 +68,7 @@ import { encryptPassword, verifyPassword } from '@/password/PasswordEncryptor'
|
||||
import { PasswordEncryptionType } from '../enum/PasswordEncryptionType'
|
||||
import LogError from '@/server/LogError'
|
||||
import { EventProtocolType } from '@/event/EventProtocolType'
|
||||
import { findUserByIdentifier } from './util/findUserByIdentifier'
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const sodium = require('sodium-native')
|
||||
@ -815,16 +816,8 @@ export class UserResolver {
|
||||
@Authorized([RIGHTS.USER])
|
||||
@Query(() => User, { nullable: true })
|
||||
async user(@Arg('identifier') identifier: string): Promise<User | null> {
|
||||
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)
|
||||
const user = await findUserByIdentifier(identifier)
|
||||
return user ? new User(user) : null
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -152,7 +152,7 @@ describe('semaphore', () => {
|
||||
})
|
||||
const bibisTransaction = mutate({
|
||||
mutation: sendCoins,
|
||||
variables: { email: 'bob@baumeister.de', amount: '50', memo: 'Das ist für dich, Bob' },
|
||||
variables: { identifier: 'bob@baumeister.de', amount: '50', memo: 'Das ist für dich, Bob' },
|
||||
})
|
||||
await mutate({
|
||||
mutation: login,
|
||||
@ -168,7 +168,7 @@ describe('semaphore', () => {
|
||||
})
|
||||
const bobsTransaction = mutate({
|
||||
mutation: sendCoins,
|
||||
variables: { email: 'bibi@bloxberg.de', amount: '50', memo: 'Das ist für dich, Bibi' },
|
||||
variables: { identifier: 'bibi@bloxberg.de', amount: '50', memo: 'Das ist für dich, Bibi' },
|
||||
})
|
||||
await mutate({
|
||||
mutation: login,
|
||||
|
||||
36
backend/src/graphql/resolver/util/findUserByIdentifier.ts
Normal file
36
backend/src/graphql/resolver/util/findUserByIdentifier.ts
Normal file
@ -0,0 +1,36 @@
|
||||
import { User as DbUser } from '@entity/User'
|
||||
import { UserContact as DbUserContact } from '@entity/UserContact'
|
||||
import LogError from '@/server/LogError'
|
||||
|
||||
export const findUserByIdentifier = async (identifier: string): Promise<DbUser | null> => {
|
||||
let user: DbUser | undefined
|
||||
if (
|
||||
/^[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)
|
||||
) {
|
||||
user = await DbUser.findOne({ where: { gradidoID: identifier } })
|
||||
if (!user) {
|
||||
throw new LogError('No user found to given identifier', identifier)
|
||||
}
|
||||
} else if (/^.{2,}@.{2,}\..{2,}$/.exec(identifier)) {
|
||||
const userContact = await DbUserContact.findOne(
|
||||
{
|
||||
email: identifier,
|
||||
emailChecked: true,
|
||||
},
|
||||
{ relations: ['user'] },
|
||||
)
|
||||
if (!userContact) {
|
||||
throw new LogError('No user with this credentials', identifier)
|
||||
}
|
||||
if (!userContact.user) {
|
||||
throw new LogError('No user to given contact', identifier)
|
||||
}
|
||||
user = userContact.user
|
||||
user.emailContact = userContact
|
||||
} else {
|
||||
// last is alias when implemented
|
||||
throw new LogError('Unknown identifier type', identifier)
|
||||
}
|
||||
|
||||
return user
|
||||
}
|
||||
@ -75,8 +75,8 @@ export const sendActivationEmail = gql`
|
||||
`
|
||||
|
||||
export const sendCoins = gql`
|
||||
mutation ($email: String!, $amount: Decimal!, $memo: String!) {
|
||||
sendCoins(email: $email, amount: $amount, memo: $memo)
|
||||
mutation ($identifier: String!, $amount: Decimal!, $memo: String!) {
|
||||
sendCoins(identifier: $identifier, amount: $amount, memo: $memo)
|
||||
}
|
||||
`
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user