diff --git a/core/src/graphql/logic/interpretEncryptedTransferArgs.ts b/core/src/graphql/logic/interpretEncryptedTransferArgs.ts index b5b2f7f7a..0d522bff7 100644 --- a/core/src/graphql/logic/interpretEncryptedTransferArgs.ts +++ b/core/src/graphql/logic/interpretEncryptedTransferArgs.ts @@ -15,13 +15,13 @@ export const interpretEncryptedTransferArgs = async (args: EncryptedTransferArgs // first find with args.publicKey the community 'requestingCom', which starts the request const requestingCom = await DbCommunity.findOneBy({ publicKey: Buffer.from(args.publicKey, 'hex') }) if (!requestingCom) { - const errmsg = `unknown requesting community with publicKey ${args.publicKey}` + const errmsg = `unknown requesting community with publicKey ${Buffer.from(args.publicKey, 'hex')}` methodLogger.error(errmsg) methodLogger.removeContext('handshakeID') throw new Error(errmsg) } if (!requestingCom.publicJwtKey) { - const errmsg = `missing publicJwtKey of requesting community with publicKey ${args.publicKey}` + const errmsg = `missing publicJwtKey of requesting community with publicKey ${Buffer.from(args.publicKey, 'hex')}` methodLogger.error(errmsg) methodLogger.removeContext('handshakeID') throw new Error(errmsg) @@ -31,7 +31,7 @@ export const interpretEncryptedTransferArgs = async (args: EncryptedTransferArgs const homeCom = await getHomeCommunity() const jwtPayload = await verifyAndDecrypt(args.handshakeID, args.jwt, homeCom!.privateJwtKey!, requestingCom.publicJwtKey) as JwtPayloadType if (!jwtPayload) { - const errmsg = `invalid payload of community with publicKey ${args.publicKey}` + const errmsg = `invalid payload of community with publicKey ${Buffer.from(args.publicKey, 'hex')}` methodLogger.error(errmsg) methodLogger.removeContext('handshakeID') throw new Error(errmsg) diff --git a/federation/src/graphql/api/1_0/resolver/SendCoinsResolver.test.ts b/federation/src/graphql/api/1_0/resolver/SendCoinsResolver.test.ts index 5ba55f88a..d0417cb40 100644 --- a/federation/src/graphql/api/1_0/resolver/SendCoinsResolver.test.ts +++ b/federation/src/graphql/api/1_0/resolver/SendCoinsResolver.test.ts @@ -8,8 +8,8 @@ import Decimal from 'decimal.js-light' import { GraphQLError } from 'graphql' import { getLogger } from 'log4js' import { DataSource } from 'typeorm' -import { SendCoinsArgs } from '../model/SendCoinsArgs' - +import { EncryptedTransferArgs } from 'core' +import { createKeyPair, encryptAndSign, SendCoinsJwtPayloadType, SendCoinsResponseJwtPayloadType, verifyAndDecrypt } from 'shared' let mutate: ApolloServerTestClient['mutate'] // , con: Connection // let query: ApolloServerTestClient['query'] @@ -21,8 +21,8 @@ let testEnv: { CONFIG.FEDERATION_API = '1_0' -let homeCom: DbCommunity -let foreignCom: DbCommunity +let recipientCom: DbCommunity +let senderCom: DbCommunity let sendUser: DbUser let sendContact: DbUserContact let recipUser: DbUser @@ -37,7 +37,7 @@ beforeAll(async () => { }) afterAll(async () => { - // await cleanDB() + await cleanDB() if (testEnv.con?.isInitialized) { await testEnv.con.destroy() } @@ -45,53 +45,54 @@ afterAll(async () => { describe('SendCoinsResolver', () => { const voteForSendCoinsMutation = ` - mutation ($args: SendCoinsArgs!) { - voteForSendCoins(data: $args) { - vote - recipGradidoID - recipFirstName - recipLastName - recipAlias - } + mutation ($args: EncryptedTransferArgs!) { + voteForSendCoins(data: $args) }` const settleSendCoinsMutation = ` - mutation ($args: SendCoinsArgs!) { + mutation ($args: EncryptedTransferArgs!) { settleSendCoins(data: $args) }` const revertSendCoinsMutation = ` - mutation ($args: SendCoinsArgs!) { + mutation ($args: EncryptedTransferArgs!) { revertSendCoins(data: $args) }` const revertSettledSendCoinsMutation = ` - mutation ($args: SendCoinsArgs!) { + mutation ($args: EncryptedTransferArgs!) { revertSettledSendCoins(data: $args) }` beforeEach(async () => { await cleanDB() - homeCom = DbCommunity.create() - homeCom.foreign = false - homeCom.url = 'homeCom-url' - homeCom.name = 'homeCom-Name' - homeCom.description = 'homeCom-Description' - homeCom.creationDate = new Date() - homeCom.publicKey = Buffer.from('homeCom-publicKey') - homeCom.communityUuid = '56a55482-909e-46a4-bfa2-cd025e894eba' - await DbCommunity.insert(homeCom) + // Generate key pair using jose library + const { publicKey: homePublicKey, privateKey: homePrivateKey } = await createKeyPair(); + recipientCom = DbCommunity.create() + recipientCom.foreign = false + recipientCom.url = 'homeCom-url' + recipientCom.name = 'homeCom-Name' + recipientCom.description = 'homeCom-Description' + recipientCom.creationDate = new Date() + recipientCom.publicKey = Buffer.alloc(32, '15F92F8EC2EA685D5FD51EE3588F5B4805EBD330EF9EDD16043F3BA9C35C0D91', 'hex') // 'homeCom-publicKey', 'hex') + recipientCom.publicJwtKey = homePublicKey; + recipientCom.privateJwtKey = homePrivateKey; + recipientCom.communityUuid = '56a55482-909e-46a4-bfa2-cd025e894eba' + await DbCommunity.insert(recipientCom) - foreignCom = DbCommunity.create() - foreignCom.foreign = true - foreignCom.url = 'foreignCom-url' - foreignCom.name = 'foreignCom-Name' - foreignCom.description = 'foreignCom-Description' - foreignCom.creationDate = new Date() - foreignCom.publicKey = Buffer.from('foreignCom-publicKey') - foreignCom.communityUuid = '56a55482-909e-46a4-bfa2-cd025e894ebb' - await DbCommunity.insert(foreignCom) + const { publicKey: foreignPublicKey, privateKey: foreignPrivateKey } = await createKeyPair(); + senderCom = DbCommunity.create() + senderCom.foreign = true + senderCom.url = 'foreignCom-url' + senderCom.name = 'foreignCom-Name' + senderCom.description = 'foreignCom-Description' + senderCom.creationDate = new Date() + senderCom.publicKey = Buffer.alloc(32, '15F92F8EC2EA685D5FD51EE3588F5B4805EBD330EF9EDD16043F3BA9C35C0D92', 'hex') // 'foreignCom-publicKey', 'hex') + senderCom.publicJwtKey = foreignPublicKey; + senderCom.privateJwtKey = foreignPrivateKey; + senderCom.communityUuid = '56a55482-909e-46a4-bfa2-cd025e894ebb' + await DbCommunity.insert(senderCom) sendUser = DbUser.create() sendUser.alias = 'sendUser-alias' - sendUser.communityUuid = '56a55482-909e-46a4-bfa2-cd025e894eba' + sendUser.communityUuid = '56a55482-909e-46a4-bfa2-cd025e894ebb' sendUser.firstName = 'sendUser-FirstName' sendUser.gradidoID = '56a55482-909e-46a4-bfa2-cd025e894ebc' sendUser.lastName = 'sendUser-LastName' @@ -106,7 +107,7 @@ describe('SendCoinsResolver', () => { recipUser = DbUser.create() recipUser.alias = 'recipUser-alias' - recipUser.communityUuid = '56a55482-909e-46a4-bfa2-cd025e894ebb' + recipUser.communityUuid = '56a55482-909e-46a4-bfa2-cd025e894eba' recipUser.firstName = 'recipUser-FirstName' recipUser.gradidoID = '56a55482-909e-46a4-bfa2-cd025e894ebd' recipUser.lastName = 'recipUser-LastName' @@ -120,30 +121,37 @@ describe('SendCoinsResolver', () => { await DbUser.save(recipUser) }) - describe('voteForSendCoins', () => { + describe('voteForSendCoins', () => { describe('unknown recipient community', () => { it('throws an error', async () => { jest.clearAllMocks() - const args = new SendCoinsArgs() - args.recipientCommunityUuid = 'invalid foreignCom' - args.recipientUserIdentifier = recipUser.gradidoID - args.creationDate = new Date().toISOString() - args.amount = new Decimal(100) - args.memo = 'X-Com-TX memo' - if (homeCom.communityUuid) { - args.senderCommunityUuid = homeCom.communityUuid - } - args.senderUserUuid = sendUser.gradidoID - args.senderUserName = fullName(sendUser.firstName, sendUser.lastName) - args.senderAlias = sendUser.alias + const payload = new SendCoinsJwtPayloadType( + 'handshakeID', + 'invalid recipientCom', + recipUser.gradidoID, + new Date().toISOString(), + new Decimal(100), + 'X-Com-TX memo', + senderCom.communityUuid!, + sendUser.gradidoID, + fullName(sendUser.firstName, sendUser.lastName), + sendUser.alias + ) + // invoke encryption as beeing on the foreignCom side to find in voteForSendCoins the correct homeCom + const jws = await encryptAndSign(payload, senderCom.privateJwtKey!, recipientCom.publicJwtKey!) + const args = new EncryptedTransferArgs() + args.publicKey = senderCom.publicKey.toString('hex') + args.jwt = jws + args.handshakeID = 'handshakeID' + const graphQLResponse = await mutate({ + mutation: voteForSendCoinsMutation, + variables: { args }, + }) expect( - await mutate({ - mutation: voteForSendCoinsMutation, - variables: { args }, - }), + graphQLResponse, ).toEqual( expect.objectContaining({ - errors: [new GraphQLError('voteForSendCoins with wrong recipientCommunityUuid')], + errors: [new GraphQLError('voteForSendCoins with wrong recipientCommunityUuid: invalid recipientCom')], }), ) }) @@ -152,20 +160,25 @@ describe('SendCoinsResolver', () => { describe('unknown recipient user', () => { it('throws an error', async () => { jest.clearAllMocks() - const args = new SendCoinsArgs() - if (foreignCom.communityUuid) { - args.recipientCommunityUuid = foreignCom.communityUuid - } - args.recipientUserIdentifier = 'invalid recipient' - args.creationDate = new Date().toISOString() - args.amount = new Decimal(100) - args.memo = 'X-Com-TX memo' - if (homeCom.communityUuid) { - args.senderCommunityUuid = homeCom.communityUuid - } - args.senderUserUuid = sendUser.gradidoID - args.senderUserName = fullName(sendUser.firstName, sendUser.lastName) - args.senderAlias = sendUser.alias + + const payload = new SendCoinsJwtPayloadType( + 'handshakeID', + recipientCom.communityUuid!, + 'invalid recipient', + new Date().toISOString(), + new Decimal(100), + 'X-Com-TX memo', + senderCom.communityUuid!, + sendUser.gradidoID, + fullName(sendUser.firstName, sendUser.lastName), + sendUser.alias + ) + // invoke encryption as beeing on the foreignCom side to find in voteForSendCoins the correct homeCom + const jws = await encryptAndSign(payload, senderCom.privateJwtKey!, recipientCom.publicJwtKey!) + const args = new EncryptedTransferArgs() + args.publicKey = senderCom.publicKey.toString('hex') + args.jwt = jws + args.handshakeID = 'handshakeID' expect( await mutate({ mutation: voteForSendCoinsMutation, @@ -175,7 +188,7 @@ describe('SendCoinsResolver', () => { expect.objectContaining({ errors: [ new GraphQLError( - 'voteForSendCoins with unknown recipientUserIdentifier in the community=', + 'voteForSendCoins with unknown recipientUserIdentifier in the community=homeCom-Name', ), ], }), @@ -186,36 +199,42 @@ describe('SendCoinsResolver', () => { describe('valid X-Com-TX voted per gradidoID', () => { it('throws an error', async () => { jest.clearAllMocks() - const args = new SendCoinsArgs() - if (foreignCom.communityUuid) { - args.recipientCommunityUuid = foreignCom.communityUuid - } - args.recipientUserIdentifier = recipUser.gradidoID - args.creationDate = new Date().toISOString() - args.amount = new Decimal(100) - args.memo = 'X-Com-TX memo' - if (homeCom.communityUuid) { - args.senderCommunityUuid = homeCom.communityUuid - } - args.senderUserUuid = sendUser.gradidoID - args.senderUserName = fullName(sendUser.firstName, sendUser.lastName) - args.senderAlias = sendUser.alias + + const payload = new SendCoinsJwtPayloadType( + 'handshakeID', + recipientCom.communityUuid!, + recipUser.gradidoID, + new Date().toISOString(), + new Decimal(100), + 'X-Com-TX memo', + senderCom.communityUuid!, + sendUser.gradidoID, + fullName(sendUser.firstName, sendUser.lastName), + sendUser.alias + ) + // invoke encryption as beeing on the foreignCom side to find in voteForSendCoins the correct homeCom + const jws = await encryptAndSign(payload, senderCom.privateJwtKey!, recipientCom.publicJwtKey!) + const args = new EncryptedTransferArgs() + args.publicKey = senderCom.publicKey.toString('hex') + args.jwt = jws + args.handshakeID = 'handshakeID' + const responseJwt = await mutate({ + mutation: voteForSendCoinsMutation, + variables: { args }, + }) + const voteResult = await verifyAndDecrypt('handshakeID', responseJwt.data.voteForSendCoins, senderCom.privateJwtKey!, recipientCom.publicJwtKey!) as SendCoinsResponseJwtPayloadType expect( - await mutate({ - mutation: voteForSendCoinsMutation, - variables: { args }, - }), + voteResult, ).toEqual( expect.objectContaining({ - data: { - voteForSendCoins: { - recipGradidoID: '56a55482-909e-46a4-bfa2-cd025e894ebd', - recipFirstName: 'recipUser-FirstName', - recipLastName: 'recipUser-LastName', - recipAlias: 'recipUser-alias', - vote: true, - }, - }, + expiration: '10m', + handshakeID: 'handshakeID', + recipGradidoID: '56a55482-909e-46a4-bfa2-cd025e894ebd', + recipFirstName: 'recipUser-FirstName', + recipLastName: 'recipUser-LastName', + recipAlias: 'recipUser-alias', + tokentype: SendCoinsResponseJwtPayloadType.SEND_COINS_RESPONSE_TYPE, + vote: true, }), ) }) @@ -224,36 +243,39 @@ describe('SendCoinsResolver', () => { describe('valid X-Com-TX voted per alias', () => { it('throws an error', async () => { jest.clearAllMocks() - const args = new SendCoinsArgs() - if (foreignCom.communityUuid) { - args.recipientCommunityUuid = foreignCom.communityUuid - } - args.recipientUserIdentifier = recipUser.alias - args.creationDate = new Date().toISOString() - args.amount = new Decimal(100) - args.memo = 'X-Com-TX memo' - if (homeCom.communityUuid) { - args.senderCommunityUuid = homeCom.communityUuid - } - args.senderUserUuid = sendUser.gradidoID - args.senderUserName = fullName(sendUser.firstName, sendUser.lastName) - args.senderAlias = sendUser.alias + + const payload = new SendCoinsJwtPayloadType( + 'handshakeID', + recipientCom.communityUuid!, + recipUser.alias, + new Date().toISOString(), + new Decimal(100), + 'X-Com-TX memo', + senderCom.communityUuid!, + sendUser.gradidoID, + fullName(sendUser.firstName, sendUser.lastName), + sendUser.alias + ) + // invoke encryption as beeing on the foreignCom side to find in voteForSendCoins the correct homeCom + const jws = await encryptAndSign(payload, senderCom.privateJwtKey!, recipientCom.publicJwtKey!) + const args = new EncryptedTransferArgs() + args.publicKey = senderCom.publicKey.toString('hex') + args.jwt = jws + args.handshakeID = 'handshakeID' + const responseJwt = await mutate({ + mutation: voteForSendCoinsMutation, + variables: { args }, + }) + const voteResult = await verifyAndDecrypt('handshakeID', responseJwt.data.voteForSendCoins, senderCom.privateJwtKey!, recipientCom.publicJwtKey!) as SendCoinsResponseJwtPayloadType expect( - await mutate({ - mutation: voteForSendCoinsMutation, - variables: { args }, - }), + voteResult, ).toEqual( expect.objectContaining({ - data: { - voteForSendCoins: { - recipGradidoID: '56a55482-909e-46a4-bfa2-cd025e894ebd', - recipFirstName: 'recipUser-FirstName', - recipLastName: 'recipUser-LastName', - recipAlias: 'recipUser-alias', - vote: true, - }, - }, + recipGradidoID: '56a55482-909e-46a4-bfa2-cd025e894ebd', + recipFirstName: 'recipUser-FirstName', + recipLastName: 'recipUser-LastName', + recipAlias: 'recipUser-alias', + vote: true, }), ) }) @@ -262,36 +284,40 @@ describe('SendCoinsResolver', () => { describe('valid X-Com-TX voted per email', () => { it('throws an error', async () => { jest.clearAllMocks() - const args = new SendCoinsArgs() - if (foreignCom.communityUuid) { - args.recipientCommunityUuid = foreignCom.communityUuid - } - args.recipientUserIdentifier = recipContact.email - args.creationDate = new Date().toISOString() - args.amount = new Decimal(100) - args.memo = 'X-Com-TX memo' - if (homeCom.communityUuid) { - args.senderCommunityUuid = homeCom.communityUuid - } - args.senderUserUuid = sendUser.gradidoID - args.senderUserName = fullName(sendUser.firstName, sendUser.lastName) - args.senderAlias = sendUser.alias + + + const payload = new SendCoinsJwtPayloadType( + 'handshakeID', + recipientCom.communityUuid!, + recipContact.email, + new Date().toISOString(), + new Decimal(100), + 'X-Com-TX memo', + senderCom.communityUuid!, + sendUser.gradidoID, + fullName(sendUser.firstName, sendUser.lastName), + sendUser.alias + ) + // invoke encryption as beeing on the foreignCom side to find in voteForSendCoins the correct homeCom + const jws = await encryptAndSign(payload, senderCom.privateJwtKey!, recipientCom.publicJwtKey!) + const args = new EncryptedTransferArgs() + args.publicKey = senderCom.publicKey.toString('hex') + args.jwt = jws + args.handshakeID = 'handshakeID' + const responseJwt = await mutate({ + mutation: voteForSendCoinsMutation, + variables: { args }, + }) + const voteResult = await verifyAndDecrypt('handshakeID', responseJwt.data.voteForSendCoins, senderCom.privateJwtKey!, recipientCom.publicJwtKey!) as SendCoinsResponseJwtPayloadType expect( - await mutate({ - mutation: voteForSendCoinsMutation, - variables: { args }, - }), + voteResult, ).toEqual( expect.objectContaining({ - data: { - voteForSendCoins: { - recipGradidoID: '56a55482-909e-46a4-bfa2-cd025e894ebd', - recipFirstName: 'recipUser-FirstName', - recipLastName: 'recipUser-LastName', - recipAlias: 'recipUser-alias', - vote: true, - }, - }, + recipGradidoID: '56a55482-909e-46a4-bfa2-cd025e894ebd', + recipFirstName: 'recipUser-FirstName', + recipLastName: 'recipUser-LastName', + recipAlias: 'recipUser-alias', + vote: true, }), ) }) @@ -302,20 +328,25 @@ describe('SendCoinsResolver', () => { const creationDate = new Date() beforeEach(async () => { - const args = new SendCoinsArgs() - if (foreignCom.communityUuid) { - args.recipientCommunityUuid = foreignCom.communityUuid - } - args.recipientUserIdentifier = recipUser.gradidoID - args.creationDate = creationDate.toISOString() - args.amount = new Decimal(100) - args.memo = 'X-Com-TX memo' - if (homeCom.communityUuid) { - args.senderCommunityUuid = homeCom.communityUuid - } - args.senderUserUuid = sendUser.gradidoID - args.senderUserName = fullName(sendUser.firstName, sendUser.lastName) - args.senderAlias = sendUser.alias + + const payload = new SendCoinsJwtPayloadType( + 'handshakeID', + recipientCom.communityUuid!, + recipUser.gradidoID, + creationDate.toISOString(), + new Decimal(100), + 'X-Com-TX memo', + senderCom.communityUuid!, + sendUser.gradidoID, + fullName(sendUser.firstName, sendUser.lastName), + sendUser.alias + ) + // invoke encryption as beeing on the foreignCom side to find in voteForSendCoins the correct homeCom + const jws = await encryptAndSign(payload, senderCom.privateJwtKey!, recipientCom.publicJwtKey!) + const args = new EncryptedTransferArgs() + args.publicKey = senderCom.publicKey.toString('hex') + args.jwt = jws + args.handshakeID = 'handshakeID' await mutate({ mutation: voteForSendCoinsMutation, variables: { args }, @@ -325,18 +356,25 @@ describe('SendCoinsResolver', () => { describe('unknown recipient community', () => { it('throws an error', async () => { jest.clearAllMocks() - const args = new SendCoinsArgs() - args.recipientCommunityUuid = 'invalid foreignCom' - args.recipientUserIdentifier = recipUser.gradidoID - args.creationDate = creationDate.toISOString() - args.amount = new Decimal(100) - args.memo = 'X-Com-TX memo' - if (homeCom.communityUuid) { - args.senderCommunityUuid = homeCom.communityUuid - } - args.senderUserUuid = sendUser.gradidoID - args.senderUserName = fullName(sendUser.firstName, sendUser.lastName) - args.senderAlias = sendUser.alias + + const payload = new SendCoinsJwtPayloadType( + 'handshakeID', + 'invalid recipientCom', + recipUser.gradidoID, + creationDate.toISOString(), + new Decimal(100), + 'X-Com-TX memo', + senderCom.communityUuid!, + sendUser.gradidoID, + fullName(sendUser.firstName, sendUser.lastName), + sendUser.alias + ) + // invoke encryption as beeing on the foreignCom side to find in voteForSendCoins the correct homeCom + const jws = await encryptAndSign(payload, senderCom.privateJwtKey!, recipientCom.publicJwtKey!) + const args = new EncryptedTransferArgs() + args.publicKey = senderCom.publicKey.toString('hex') + args.jwt = jws + args.handshakeID = 'handshakeID' expect( await mutate({ mutation: revertSendCoinsMutation, @@ -344,7 +382,7 @@ describe('SendCoinsResolver', () => { }), ).toEqual( expect.objectContaining({ - errors: [new GraphQLError('revertSendCoins with wrong recipientCommunityUuid')], + errors: [new GraphQLError('revertSendCoins with wrong recipientCommunityUuid=invalid recipientCom')], }), ) }) @@ -353,20 +391,25 @@ describe('SendCoinsResolver', () => { describe('unknown recipient user', () => { it('throws an error', async () => { jest.clearAllMocks() - const args = new SendCoinsArgs() - if (foreignCom.communityUuid) { - args.recipientCommunityUuid = foreignCom.communityUuid - } - args.recipientUserIdentifier = 'invalid recipient' - args.creationDate = creationDate.toISOString() - args.amount = new Decimal(100) - args.memo = 'X-Com-TX memo' - if (homeCom.communityUuid) { - args.senderCommunityUuid = homeCom.communityUuid - } - args.senderUserUuid = sendUser.gradidoID - args.senderUserName = fullName(sendUser.firstName, sendUser.lastName) - args.senderAlias = sendUser.alias + + const payload = new SendCoinsJwtPayloadType( + 'handshakeID', + recipientCom.communityUuid!, + 'invalid recipient', + creationDate.toISOString(), + new Decimal(100), + 'X-Com-TX memo', + senderCom.communityUuid!, + sendUser.gradidoID, + fullName(sendUser.firstName, sendUser.lastName), + sendUser.alias + ) + // invoke encryption as beeing on the foreignCom side to find in voteForSendCoins the correct homeCom + const jws = await encryptAndSign(payload, senderCom.privateJwtKey!, recipientCom.publicJwtKey!) + const args = new EncryptedTransferArgs() + args.publicKey = senderCom.publicKey.toString('hex') + args.jwt = jws + args.handshakeID = 'handshakeID' expect( await mutate({ mutation: revertSendCoinsMutation, @@ -376,7 +419,7 @@ describe('SendCoinsResolver', () => { expect.objectContaining({ errors: [ new GraphQLError( - 'revertSendCoins with unknown recipientUserIdentifier in the community=', + 'revertSendCoins with unknown recipientUserIdentifier in the community=homeCom-Name', ), ], }), @@ -387,20 +430,26 @@ describe('SendCoinsResolver', () => { describe('valid X-Com-TX reverted', () => { it('throws an error', async () => { jest.clearAllMocks() - const args = new SendCoinsArgs() - if (foreignCom.communityUuid) { - args.recipientCommunityUuid = foreignCom.communityUuid - } - args.recipientUserIdentifier = recipUser.gradidoID - args.creationDate = creationDate.toISOString() - args.amount = new Decimal(100) - args.memo = 'X-Com-TX memo' - if (homeCom.communityUuid) { - args.senderCommunityUuid = homeCom.communityUuid - } - args.senderUserUuid = sendUser.gradidoID - args.senderUserName = fullName(sendUser.firstName, sendUser.lastName) - args.senderAlias = sendUser.alias + + const payload = new SendCoinsJwtPayloadType( + 'handshakeID', + recipientCom.communityUuid!, + recipUser.gradidoID, + creationDate.toISOString(), + new Decimal(100), + 'X-Com-TX memo', + senderCom.communityUuid!, + sendUser.gradidoID, + fullName(sendUser.firstName, sendUser.lastName), + sendUser.alias + ) + // invoke encryption as beeing on the foreignCom side to find in voteForSendCoins the correct homeCom + const jws = await encryptAndSign(payload, senderCom.privateJwtKey!, recipientCom.publicJwtKey!) + const args = new EncryptedTransferArgs() + args.publicKey = senderCom.publicKey.toString('hex') + args.jwt = jws + args.handshakeID = 'handshakeID' + expect( await mutate({ mutation: revertSendCoinsMutation, @@ -421,20 +470,25 @@ describe('SendCoinsResolver', () => { const creationDate = new Date() beforeEach(async () => { - const args = new SendCoinsArgs() - if (foreignCom.communityUuid) { - args.recipientCommunityUuid = foreignCom.communityUuid - } - args.recipientUserIdentifier = recipUser.gradidoID - args.creationDate = creationDate.toISOString() - args.amount = new Decimal(100) - args.memo = 'X-Com-TX memo' - if (homeCom.communityUuid) { - args.senderCommunityUuid = homeCom.communityUuid - } - args.senderUserUuid = sendUser.gradidoID - args.senderUserName = fullName(sendUser.firstName, sendUser.lastName) - args.senderAlias = sendUser.alias + const payload = new SendCoinsJwtPayloadType( + 'handshakeID', + recipientCom.communityUuid!, + recipUser.gradidoID, + creationDate.toISOString(), + new Decimal(100), + 'X-Com-TX memo', + senderCom.communityUuid!, + sendUser.gradidoID, + fullName(sendUser.firstName, sendUser.lastName), + sendUser.alias + ) + // invoke encryption as beeing on the foreignCom side to find in voteForSendCoins the correct homeCom + const jws = await encryptAndSign(payload, senderCom.privateJwtKey!, recipientCom.publicJwtKey!) + const args = new EncryptedTransferArgs() + args.publicKey = senderCom.publicKey.toString('hex') + args.jwt = jws + args.handshakeID = 'handshakeID' + await mutate({ mutation: voteForSendCoinsMutation, variables: { args }, @@ -444,18 +498,24 @@ describe('SendCoinsResolver', () => { describe('unknown recipient community', () => { it('throws an error', async () => { jest.clearAllMocks() - const args = new SendCoinsArgs() - args.recipientCommunityUuid = 'invalid foreignCom' - args.recipientUserIdentifier = recipUser.gradidoID - args.creationDate = creationDate.toISOString() - args.amount = new Decimal(100) - args.memo = 'X-Com-TX memo' - if (homeCom.communityUuid) { - args.senderCommunityUuid = homeCom.communityUuid - } - args.senderUserUuid = sendUser.gradidoID - args.senderUserName = fullName(sendUser.firstName, sendUser.lastName) - args.senderAlias = sendUser.alias + const payload = new SendCoinsJwtPayloadType( + 'handshakeID', + 'invalid recipientCom', + recipUser.gradidoID, + creationDate.toISOString(), + new Decimal(100), + 'X-Com-TX memo', + senderCom.communityUuid!, + sendUser.gradidoID, + fullName(sendUser.firstName, sendUser.lastName), + sendUser.alias + ) + // invoke encryption as beeing on the foreignCom side to find in voteForSendCoins the correct homeCom + const jws = await encryptAndSign(payload, senderCom.privateJwtKey!, recipientCom.publicJwtKey!) + const args = new EncryptedTransferArgs() + args.publicKey = senderCom.publicKey.toString('hex') + args.jwt = jws + args.handshakeID = 'handshakeID' expect( await mutate({ mutation: settleSendCoinsMutation, @@ -463,7 +523,7 @@ describe('SendCoinsResolver', () => { }), ).toEqual( expect.objectContaining({ - errors: [new GraphQLError('settleSendCoins with wrong recipientCommunityUuid')], + errors: [new GraphQLError('settleSendCoins with wrong recipientCommunityUuid=invalid recipientCom')], }), ) }) @@ -472,20 +532,24 @@ describe('SendCoinsResolver', () => { describe('unknown recipient user', () => { it('throws an error', async () => { jest.clearAllMocks() - const args = new SendCoinsArgs() - if (foreignCom.communityUuid) { - args.recipientCommunityUuid = foreignCom.communityUuid - } - args.recipientUserIdentifier = 'invalid recipient' - args.creationDate = creationDate.toISOString() - args.amount = new Decimal(100) - args.memo = 'X-Com-TX memo' - if (homeCom.communityUuid) { - args.senderCommunityUuid = homeCom.communityUuid - } - args.senderUserUuid = sendUser.gradidoID - args.senderUserName = fullName(sendUser.firstName, sendUser.lastName) - args.senderAlias = sendUser.alias + const payload = new SendCoinsJwtPayloadType( + 'handshakeID', + recipientCom.communityUuid!, + 'invalid recipient', + creationDate.toISOString(), + new Decimal(100), + 'X-Com-TX memo', + senderCom.communityUuid!, + sendUser.gradidoID, + fullName(sendUser.firstName, sendUser.lastName), + sendUser.alias + ) + // invoke encryption as beeing on the foreignCom side to find in voteForSendCoins the correct homeCom + const jws = await encryptAndSign(payload, senderCom.privateJwtKey!, recipientCom.publicJwtKey!) + const args = new EncryptedTransferArgs() + args.publicKey = senderCom.publicKey.toString('hex') + args.jwt = jws + args.handshakeID = 'handshakeID' expect( await mutate({ mutation: settleSendCoinsMutation, @@ -495,7 +559,7 @@ describe('SendCoinsResolver', () => { expect.objectContaining({ errors: [ new GraphQLError( - 'settleSendCoins with unknown recipientUserIdentifier in the community=', + 'settleSendCoins with unknown recipientUserIdentifier in the community=' + recipientCom.name, ), ], }), @@ -506,20 +570,24 @@ describe('SendCoinsResolver', () => { describe('valid X-Com-TX settled', () => { it('throws an error', async () => { jest.clearAllMocks() - const args = new SendCoinsArgs() - if (foreignCom.communityUuid) { - args.recipientCommunityUuid = foreignCom.communityUuid - } - args.recipientUserIdentifier = recipUser.gradidoID - args.creationDate = creationDate.toISOString() - args.amount = new Decimal(100) - args.memo = 'X-Com-TX memo' - if (homeCom.communityUuid) { - args.senderCommunityUuid = homeCom.communityUuid - } - args.senderUserUuid = sendUser.gradidoID - args.senderUserName = fullName(sendUser.firstName, sendUser.lastName) - args.senderAlias = sendUser.alias + const payload = new SendCoinsJwtPayloadType( + 'handshakeID', + recipientCom.communityUuid!, + recipUser.gradidoID, + creationDate.toISOString(), + new Decimal(100), + 'X-Com-TX memo', + senderCom.communityUuid!, + sendUser.gradidoID, + fullName(sendUser.firstName, sendUser.lastName), + sendUser.alias + ) + // invoke encryption as beeing on the foreignCom side to find in voteForSendCoins the correct homeCom + const jws = await encryptAndSign(payload, senderCom.privateJwtKey!, recipientCom.publicJwtKey!) + const args = new EncryptedTransferArgs() + args.publicKey = senderCom.publicKey.toString('hex') + args.jwt = jws + args.handshakeID = 'handshakeID' expect( await mutate({ mutation: settleSendCoinsMutation, @@ -540,20 +608,24 @@ describe('SendCoinsResolver', () => { const creationDate = new Date() beforeEach(async () => { - const args = new SendCoinsArgs() - if (foreignCom.communityUuid) { - args.recipientCommunityUuid = foreignCom.communityUuid - } - args.recipientUserIdentifier = recipUser.gradidoID - args.creationDate = creationDate.toISOString() - args.amount = new Decimal(100) - args.memo = 'X-Com-TX memo' - if (homeCom.communityUuid) { - args.senderCommunityUuid = homeCom.communityUuid - } - args.senderUserUuid = sendUser.gradidoID - args.senderUserName = fullName(sendUser.firstName, sendUser.lastName) - args.senderAlias = sendUser.alias + const payload = new SendCoinsJwtPayloadType( + 'handshakeID', + recipientCom.communityUuid!, + recipUser.gradidoID, + creationDate.toISOString(), + new Decimal(100), + 'X-Com-TX memo', + senderCom.communityUuid!, + sendUser.gradidoID, + fullName(sendUser.firstName, sendUser.lastName), + sendUser.alias + ) + // invoke encryption as beeing on the foreignCom side to find in voteForSendCoins the correct homeCom + const jws = await encryptAndSign(payload, senderCom.privateJwtKey!, recipientCom.publicJwtKey!) + const args = new EncryptedTransferArgs() + args.publicKey = senderCom.publicKey.toString('hex') + args.jwt = jws + args.handshakeID = 'handshakeID' await mutate({ mutation: voteForSendCoinsMutation, variables: { args }, @@ -567,18 +639,24 @@ describe('SendCoinsResolver', () => { describe('unknown recipient community', () => { it('throws an error', async () => { jest.clearAllMocks() - const args = new SendCoinsArgs() - args.recipientCommunityUuid = 'invalid foreignCom' - args.recipientUserIdentifier = recipUser.gradidoID - args.creationDate = creationDate.toISOString() - args.amount = new Decimal(100) - args.memo = 'X-Com-TX memo' - if (homeCom.communityUuid) { - args.senderCommunityUuid = homeCom.communityUuid - } - args.senderUserUuid = sendUser.gradidoID - args.senderUserName = fullName(sendUser.firstName, sendUser.lastName) - args.senderAlias = sendUser.alias + const payload = new SendCoinsJwtPayloadType( + 'handshakeID', + 'invalid recipientCom', + recipUser.gradidoID, + creationDate.toISOString(), + new Decimal(100), + 'X-Com-TX memo', + senderCom.communityUuid!, + sendUser.gradidoID, + fullName(sendUser.firstName, sendUser.lastName), + sendUser.alias + ) + // invoke encryption as beeing on the foreignCom side to find in voteForSendCoins the correct homeCom + const jws = await encryptAndSign(payload, senderCom.privateJwtKey!, recipientCom.publicJwtKey!) + const args = new EncryptedTransferArgs() + args.publicKey = senderCom.publicKey.toString('hex') + args.jwt = jws + args.handshakeID = 'handshakeID' expect( await mutate({ mutation: revertSettledSendCoinsMutation, @@ -586,7 +664,7 @@ describe('SendCoinsResolver', () => { }), ).toEqual( expect.objectContaining({ - errors: [new GraphQLError('revertSettledSendCoins with wrong recipientCommunityUuid')], + errors: [new GraphQLError('revertSettledSendCoins with wrong recipientCommunityUuid=invalid recipientCom')], }), ) }) @@ -595,20 +673,24 @@ describe('SendCoinsResolver', () => { describe('unknown recipient user', () => { it('throws an error', async () => { jest.clearAllMocks() - const args = new SendCoinsArgs() - if (foreignCom.communityUuid) { - args.recipientCommunityUuid = foreignCom.communityUuid - } - args.recipientUserIdentifier = 'invalid recipient' - args.creationDate = creationDate.toISOString() - args.amount = new Decimal(100) - args.memo = 'X-Com-TX memo' - if (homeCom.communityUuid) { - args.senderCommunityUuid = homeCom.communityUuid - } - args.senderUserUuid = sendUser.gradidoID - args.senderUserName = fullName(sendUser.firstName, sendUser.lastName) - args.senderAlias = sendUser.alias + const payload = new SendCoinsJwtPayloadType( + 'handshakeID', + recipientCom.communityUuid!, + 'invalid recipient', + creationDate.toISOString(), + new Decimal(100), + 'X-Com-TX memo', + senderCom.communityUuid!, + sendUser.gradidoID, + fullName(sendUser.firstName, sendUser.lastName), + sendUser.alias + ) + // invoke encryption as beeing on the foreignCom side to find in voteForSendCoins the correct homeCom + const jws = await encryptAndSign(payload, senderCom.privateJwtKey!, recipientCom.publicJwtKey!) + const args = new EncryptedTransferArgs() + args.publicKey = senderCom.publicKey.toString('hex') + args.jwt = jws + args.handshakeID = 'handshakeID' expect( await mutate({ mutation: revertSettledSendCoinsMutation, @@ -618,7 +700,7 @@ describe('SendCoinsResolver', () => { expect.objectContaining({ errors: [ new GraphQLError( - 'revertSettledSendCoins with unknown recipientUserIdentifier in the community=', + 'revertSettledSendCoins with unknown recipientUserIdentifier in the community=' + recipientCom.name, ), ], }), @@ -629,20 +711,24 @@ describe('SendCoinsResolver', () => { describe('valid X-Com-TX settled', () => { it('throws an error', async () => { jest.clearAllMocks() - const args = new SendCoinsArgs() - if (foreignCom.communityUuid) { - args.recipientCommunityUuid = foreignCom.communityUuid - } - args.recipientUserIdentifier = recipUser.gradidoID - args.creationDate = creationDate.toISOString() - args.amount = new Decimal(100) - args.memo = 'X-Com-TX memo' - if (homeCom.communityUuid) { - args.senderCommunityUuid = homeCom.communityUuid - } - args.senderUserUuid = sendUser.gradidoID - args.senderUserName = fullName(sendUser.firstName, sendUser.lastName) - args.senderAlias = sendUser.alias + const payload = new SendCoinsJwtPayloadType( + 'handshakeID', + recipientCom.communityUuid!, + recipUser.gradidoID, + creationDate.toISOString(), + new Decimal(100), + 'X-Com-TX memo', + senderCom.communityUuid!, + sendUser.gradidoID, + fullName(sendUser.firstName, sendUser.lastName), + sendUser.alias + ) + // invoke encryption as beeing on the foreignCom side to find in voteForSendCoins the correct homeCom + const jws = await encryptAndSign(payload, senderCom.privateJwtKey!, recipientCom.publicJwtKey!) + const args = new EncryptedTransferArgs() + args.publicKey = senderCom.publicKey.toString('hex') + args.jwt = jws + args.handshakeID = 'handshakeID' expect( await mutate({ mutation: revertSettledSendCoinsMutation, diff --git a/federation/src/graphql/api/1_0/resolver/SendCoinsResolver.ts b/federation/src/graphql/api/1_0/resolver/SendCoinsResolver.ts index 3c6d056af..938dca47c 100644 --- a/federation/src/graphql/api/1_0/resolver/SendCoinsResolver.ts +++ b/federation/src/graphql/api/1_0/resolver/SendCoinsResolver.ts @@ -52,7 +52,7 @@ export class SendCoinsResolver { communityUuid: authArgs.recipientCommunityUuid, }) if (!recipientCom) { - const errmsg = `voteForSendCoins with wrong recipientCommunityUuid` + authArgs.recipientCommunityUuid + const errmsg = `voteForSendCoins with wrong recipientCommunityUuid: ${authArgs.recipientCommunityUuid}` methodLogger.error(errmsg) throw new Error(errmsg) } @@ -60,7 +60,7 @@ export class SendCoinsResolver { communityUuid: authArgs.senderCommunityUuid, }) if (!senderCom) { - const errmsg = `voteForSendCoins with wrong senderCommunityUuid` + authArgs.senderCommunityUuid + const errmsg = `voteForSendCoins with wrong senderCommunityUuid: ${authArgs.senderCommunityUuid}` methodLogger.error(errmsg) throw new Error(errmsg) } @@ -136,7 +136,7 @@ export class SendCoinsResolver { } const authArgs = await interpretEncryptedTransferArgs(args) as SendCoinsJwtPayloadType if (!authArgs) { - const errmsg = `invalid revertSendCoins payload of requesting community with publicKey` + args.publicKey + const errmsg = `invalid revertSendCoins payload of requesting community with publicKey=${args.publicKey}` methodLogger.error(errmsg) throw new Error(errmsg) } @@ -148,7 +148,7 @@ export class SendCoinsResolver { communityUuid: authArgs.recipientCommunityUuid, }) if (!homeCom) { - const errmsg = `revertSendCoins with wrong recipientCommunityUuid` + authArgs.recipientCommunityUuid + const errmsg = `revertSendCoins with wrong recipientCommunityUuid=${authArgs.recipientCommunityUuid}` methodLogger.error(errmsg) throw new Error(errmsg) } @@ -157,7 +157,7 @@ export class SendCoinsResolver { // second check if receiver user exists in this community receiverUser = await findUserByIdentifier(authArgs.recipientUserIdentifier) if (!receiverUser) { - const errmsg = `revertSendCoins with unknown recipientUserIdentifier in the community=` + homeCom.name + const errmsg = `revertSendCoins with unknown recipientUserIdentifier in the community=${homeCom.name}` methodLogger.error(errmsg) throw new Error(errmsg) } @@ -222,7 +222,7 @@ export class SendCoinsResolver { } const authArgs = await interpretEncryptedTransferArgs(args) as SendCoinsJwtPayloadType if (!authArgs) { - const errmsg = `invalid settleSendCoins payload of requesting community with publicKey` + args.publicKey + const errmsg = `invalid settleSendCoins payload of requesting community with publicKey=${args.publicKey}` methodLogger.error(errmsg) throw new Error(errmsg) } @@ -234,7 +234,7 @@ export class SendCoinsResolver { communityUuid: authArgs.recipientCommunityUuid, }) if (!homeCom) { - const errmsg = `settleSendCoins with wrong recipientCommunityUuid` + authArgs.recipientCommunityUuid + const errmsg = `settleSendCoins with wrong recipientCommunityUuid=${authArgs.recipientCommunityUuid}` methodLogger.error(errmsg) throw new Error(errmsg) } @@ -242,7 +242,7 @@ export class SendCoinsResolver { // second check if receiver user exists in this community const receiverUser = await findUserByIdentifier(authArgs.recipientUserIdentifier) if (!receiverUser) { - const errmsg = `settleSendCoins with unknown recipientUserIdentifier in the community=` + homeCom.name + const errmsg = `settleSendCoins with unknown recipientUserIdentifier in the community=${homeCom.name}` methodLogger.error(errmsg) throw new Error(errmsg) } @@ -305,7 +305,7 @@ export class SendCoinsResolver { } const authArgs = await interpretEncryptedTransferArgs(args) as SendCoinsJwtPayloadType if (!authArgs) { - const errmsg = `invalid revertSettledSendCoins payload of requesting community with publicKey` + args.publicKey + const errmsg = `invalid revertSettledSendCoins payload of requesting community with publicKey=${args.publicKey}` methodLogger.error(errmsg) throw new Error(errmsg) } @@ -317,7 +317,7 @@ export class SendCoinsResolver { communityUuid: authArgs.recipientCommunityUuid, }) if (!homeCom) { - const errmsg = `revertSettledSendCoins with wrong recipientCommunityUuid` + authArgs.recipientCommunityUuid + const errmsg = `revertSettledSendCoins with wrong recipientCommunityUuid=${authArgs.recipientCommunityUuid}` methodLogger.error(errmsg) throw new Error(errmsg) } @@ -325,7 +325,7 @@ export class SendCoinsResolver { // second check if receiver user exists in this community const receiverUser = await findUserByIdentifier(authArgs.recipientUserIdentifier) if (!receiverUser) { - const errmsg = `revertSettledSendCoins with unknown recipientUserIdentifier in the community=` + homeCom.name + const errmsg = `revertSettledSendCoins with unknown recipientUserIdentifier in the community=${homeCom.name}` methodLogger.error(errmsg) throw new Error(errmsg) }