diff --git a/controllers/members.js b/controllers/members.js index 0672b72..055d90e 100644 --- a/controllers/members.js +++ b/controllers/members.js @@ -27,7 +27,7 @@ module.exports = (app) => { if (!channelAccountProperties) { return res.status(StatusCode.ServerErrorInternal).send({message: `The channel is not available: ${channelAddress}`}) } - const channelMembers = await chanService.getChannelMembers(channelAccountProperties) + const channelMembers = await chanService.getChannelMembers(channelAccountProperties); return res.send(channelMembers); } catch (error) { logger.error(`Error getting members`); diff --git a/services/chanService.js b/services/chanService.js index b23a77f..dc066e6 100644 --- a/services/chanService.js +++ b/services/chanService.js @@ -17,7 +17,7 @@ const {transactionUtils} = require("../gravity/transactionUtils"); const {BadGravityAccountPropertiesError, ChannelRecordValidatorError, InviteRecordValidatorError} = require("../errors/metisError"); const {validator} = require("../services/validator"); const {GravityCrypto} = require("./gravityCrypto"); -// const {axiosDefault} = require("../config/axiosConf"); +import {uniqBy} from 'lodash'; class ChanService { /** @@ -1070,7 +1070,7 @@ class ChanService { logger.debug(`channelAccountProperties.address= ${channelAccountProperties.address}`); const listTag = channelConfig.channelMemberPublicKeyList; return jupiterTransactionsService.dereferenceListAndGetReadableTaggedMessageContainers(channelAccountProperties, listTag) - .then( messageContainers => messageContainers.map(messageContainer => messageContainer.message)) + .then( messageContainers => uniqBy(messageContainers.map(messageContainer => messageContainer.message), 'memberAccountAddress')) } /** @@ -1103,72 +1103,6 @@ class ChanService { addE2EPublicKeyToChannel(userE2EPublicKey, userAddress, channelAccountProperties, userAlias) { logger.verbose(`#### addE2EPublicKeyToChannel(userPublicKey, userAddress, channelAccountProperties)`); return this.jupiterAccountService.addE2EPublicKeyToJupiterAccount(userE2EPublicKey,channelAccountProperties,userAddress, userAlias, 'ChannelAccount'); - // try { - // - // //------------------------------ - // const listTag = channelConfig.channelMemberPublicKeyList - // //------------------------------ - // - // - // - // const latestE2EPublicKeysContainers = await this.jupiterTransactionsService.messageService.dereferenceListAndGetReadableTaggedMessageContainers( - // channelAccountProperties, - // listTag - // ) - // const latestE2EPublicKeys = latestE2EPublicKeysContainers.map(containers => containers.message); - // const latestE2ETransactionIds = latestE2EPublicKeysContainers.map(containers => containers.transactionId); - // if(latestE2EPublicKeys.some(pk => pk === userPublicKey)){ - // throw new mError.MetisErrorPublicKeyExists('', userPublicKey); - // } - // - // - // - // - // //------------------------------ - // const newUserChannel = { - // userAddress, - // userPublicKey, - // date: Date.now() - // }; - // const checksumPublicKey = gu.generateChecksum(userPublicKey); - // const channelUserTag = `${channelConfig.channelMemberPublicKey}.${userAddress}.${checksumPublicKey}`; - // //------------------------------ - // - // - // - // logger.debug(`newUserChannel= ${JSON.stringify(newUserChannel)}`); - // // Send A New E2E Public Key Transaction - // const encryptedMessage = channelAccountProperties.crypto.encryptJson(newUserChannel); - // const newUserTransactionResponse = await this.messageService.sendTaggedAndEncipheredMetisMessage( - // channelAccountProperties.passphrase, - // channelAccountProperties.address, - // encryptedMessage, // encipher message [{ userAddress: userData.account, userPublicKey, date: Date.now() }];, - // channelUserTag, - // FeeManager.feeTypes.account_record, - // channelAccountProperties.publicKey - // ) - // - // // Update the Public keys List - // latestE2ETransactionIds.push(newUserTransactionResponse.transaction); - // const encryptedLatestE2ETransactionIds = channelAccountProperties.crypto.encryptJson(latestE2ETransactionIds); - // await this.messageService.sendTaggedAndEncipheredMetisMessage( - // channelAccountProperties.passphrase, - // channelAccountProperties.address, - // encryptedLatestE2ETransactionIds, // encipher message [{ userAddress: userData.account, userPublicKey, date: Date.now() }];, - // listTag, - // FeeManager.feeTypes.account_record, - // channelAccountProperties.publicKey - // ) - // - // } catch (error) { - // logger.error(`**** addE2EPublicKeyToChannel(userPublicKey, userAddress, channelAccountProperties).catch(error)`); - // if(error instanceof MetisErrorPublicKeyExists){ - // logger.warn(`The PublicKey is already associated with the channel: channel=${channelAccountProperties.address}, user public key: ${userPublicKey}`); - // return; - // } - // logger.error(`error= ${error}`); - // throw error; - // } } } diff --git a/services/gravityCrypto.js b/services/gravityCrypto.js index 6736130..39a57e5 100644 --- a/services/gravityCrypto.js +++ b/services/gravityCrypto.js @@ -236,7 +236,7 @@ class GravityCrypto { */ decryptAndParse(data){ const decryptedValue = this.decryptOrPassThrough(data); - return JSON.parse(decryptedValue); + return typeof decryptedValue === 'object' ? decryptedValue : JSON.parse(decryptedValue); } /** diff --git a/services/jupiterAccountService.js b/services/jupiterAccountService.js index 3e26820..222347d 100644 --- a/services/jupiterAccountService.js +++ b/services/jupiterAccountService.js @@ -473,7 +473,7 @@ class JupiterAccountService { let payload = ''; if (accountType === 'UserAccount') { - listTag = `${userConfig.userPublicKeyList}.${metisConfig.evm}`; + listTag = `${userConfig.userPublicKeyList}`; payload = { recordType: 'e2eUserPublicKeyRecord', e2ePublicKey: e2ePublicKey, @@ -482,7 +482,7 @@ class JupiterAccountService { } } else { if (!gu.isWellFormedJupiterAddress(userAddress)) throw new mError.MetisErrorBadJupiterAddress(`userAddress: ${userAddress}`) - listTag = `${channelConfig.channelMemberPublicKeyList}.${metisConfig.evm}` + listTag = `${channelConfig.channelMemberPublicKeyList}` recordTag = `${channelConfig.channelMemberPublicKey}.${userAddress}.${checksumPublicKey}.${metisConfig.evm}`; payload = { recordType: 'e2eChannelMemberPublicKeyRecord', @@ -520,7 +520,7 @@ class JupiterAccountService { gravityAccountProperties.passphrase, gravityAccountProperties.address, encryptedLatestUserE2ETransactionIds, - listTag, + `${listTag}.${metisConfig.evm}`, FeeManager.feeTypes.account_record, gravityAccountProperties.publicKey ); diff --git a/services/jupiterTransactionMessageService.js b/services/jupiterTransactionMessageService.js index 87db15e..4efb5af 100644 --- a/services/jupiterTransactionMessageService.js +++ b/services/jupiterTransactionMessageService.js @@ -358,7 +358,7 @@ class JupiterTransactionMessageService { return ''; // because of Promise.all we should not do reject. } const message = gu.jsonParseOrPassThrough(messageToParse); - return {message: message, transactionId: messageTransactionId}; + return {message: message, transactionId: messageTransactionId, tag: decryptedMessageContainer.tag}; } catch(error) { logger.error(`**** getReadableMessageContainerFromMessageTransactionIdAndDecrypt(messageTransactionId, crypto, passphrase).catch(error)`); logger.error(`error= ${error}`) diff --git a/services/jupiterTransactionsService.js b/services/jupiterTransactionsService.js index 1b227cd..ace2090 100644 --- a/services/jupiterTransactionsService.js +++ b/services/jupiterTransactionsService.js @@ -114,6 +114,7 @@ class JupiterTransactionsService { firstIndex, lastIndex ); + let filteredTransactions = transactions; if(transactionFilterCallback){ filteredTransactions = transactions.filter(transactionFilterCallback); @@ -542,6 +543,7 @@ class JupiterTransactionsService { if(!listTag){throw new Error('listTag is invalid')} try { const latestReferenceList = await this.fetchLatestReferenceList(gravityAccountProperties, listTag, isMetisEncrypted); + let messages = []; //@TODO instead of forEach use the Tag to fetch and then remove if not in the list latestReferenceList.forEach(transactionId => { @@ -576,7 +578,7 @@ class JupiterTransactionsService { if(!listTag){throw new mError.MetisError('listTag is invalid')} try { - const listContainers = await this.getReadableTaggedMessageContainers(gravityAccountProperties, listTag, isMetisEncrypted); + let listContainers = await this.getReadableTaggedMessageContainers(gravityAccountProperties, listTag, isMetisEncrypted); if (listContainers.length === 0) { logger.warn(`No list found for ${gravityAccountProperties.address}: ${listTag}`); return [] @@ -588,6 +590,20 @@ class JupiterTransactionsService { logger.info(`- account: ${gravityAccountProperties.address}`); logger.info('+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++'); // Get Latest Good List + const cbcContainer = listContainers.find(lc => !lc.tag.includes(`.${metisConfig.evm}`)); + const gcmContainer = listContainers.find(lc => lc.tag.includes(`.${metisConfig.evm}`)); + + const cbcMessage = cbcContainer && cbcContainer.message ? cbcContainer.message : []; + const gcmMessage = gcmContainer && gcmContainer.message ? gcmContainer.message : []; + if(!gu.arraysEqual(cbcMessage, gcmMessage)){ + const cbcAlreadyInGcm = cbcMessage.every(item => gcmMessage.includes(item)); + if(!cbcAlreadyInGcm){ + listContainers = [{ message: [...new Set([...cbcMessage, ...gcmMessage])] }]; + } else { + listContainers = [gcmContainer]; + } + } + const latestListContainer = listContainers.find(listContainer => { // The value of the first element in the array that satisfies the provided testing function. Otherwise, undefined is returned. const list = listContainer.message; @@ -597,7 +613,8 @@ class JupiterTransactionsService { return list.every(item => { return gu.isWellFormedJupiterTransactionId(item); }) - }) + }); + if (latestListContainer === undefined) { logger.warn(`No Good List Found for ${gravityAccountProperties.address} using ${listTag}`); return []; diff --git a/utils/gravityUtils.js b/utils/gravityUtils.js index fb4cd96..e62b067 100644 --- a/utils/gravityUtils.js +++ b/utils/gravityUtils.js @@ -155,7 +155,13 @@ const isWellFormedJupiterTransactionId = function(transactionId){ return false; } - +const arraysEqual = (a1,a2) => { + if(!Array.isArray(a1) || !Array.isArray(a2)){ + return false; + } + /* WARNING: arrays must not contain {objects} or behavior may be undefined */ + return (JSON.stringify(a1) === JSON.stringify(a2)); +} const isWellFormedE2EPublicKey = function(e2ePublicKey){ return !!e2ePublicKey; @@ -571,7 +577,8 @@ module.exports = { isWellFormedUuid, ipLogger, ipLoggerCleanUp, - ipLoggerRepeatedIpAddress + ipLoggerRepeatedIpAddress, + arraysEqual };