diff --git a/package-lock.json b/package-lock.json index 70342da96..44380e79c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1620,9 +1620,9 @@ } }, "@matrixai/id": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@matrixai/id/-/id-2.1.0.tgz", - "integrity": "sha512-yB8ew2Aj5THx/p+8MyNNxtbaqEhsT0nySV2HZ3vAS79NSHtwa89AWStdXjBg+EtzUiWP1cWrJnU2ScXPNLP3wA==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@matrixai/id/-/id-3.3.0.tgz", + "integrity": "sha512-o3iagu6hW6ya5p87Ptn74pXY9zxbIEH5f91YeaBwo7K/g0e3/OzgBbwHiwTbc9xpxqxBn/mNyZp0ovAWexA4Vw==", "requires": { "multiformats": "^9.4.8", "uuid": "^8.3.2" diff --git a/package.json b/package.json index d8371c5ce..472ff8ed5 100644 --- a/package.json +++ b/package.json @@ -73,7 +73,7 @@ "@grpc/grpc-js": "1.3.7", "@matrixai/async-init": "^1.6.0", "@matrixai/db": "^1.1.2", - "@matrixai/id": "^2.1.0", + "@matrixai/id": "^3.3.0", "@matrixai/logger": "^2.1.0", "@matrixai/workers": "^1.2.5", "ajv": "^7.0.4", diff --git a/src/acl/ACL.ts b/src/acl/ACL.ts index ee337f194..3f82eefb4 100644 --- a/src/acl/ACL.ts +++ b/src/acl/ACL.ts @@ -7,7 +7,7 @@ import type { Ref } from '../types'; import { Mutex } from 'async-mutex'; import Logger from '@matrixai/logger'; -import { utils as idUtils } from '@matrixai/id'; +import { IdInternal, utils as idUtils } from '@matrixai/id'; import { CreateDestroyStartStop, ready, @@ -130,8 +130,16 @@ class ACL { nodeId2: NodeId, ): Promise { return await this._transaction(async () => { - const permId1 = await this.db.get(this.aclNodesDbDomain, nodeId1, true); - const permId2 = await this.db.get(this.aclNodesDbDomain, nodeId2, true); + const permId1 = await this.db.get( + this.aclNodesDbDomain, + nodeId1.toBuffer(), + true, + ); + const permId2 = await this.db.get( + this.aclNodesDbDomain, + nodeId2.toBuffer(), + true, + ); if (permId1 != null && permId2 != null && permId1 === permId2) { return true; } @@ -147,7 +155,7 @@ class ACL { Record > = {}; for await (const o of this.aclNodesDb.createReadStream()) { - const nodeId = (o as any).key as NodeId; + const nodeId = IdInternal.create((o as any).key); const data = (o as any).value as Buffer; const permId = makePermissionId( await this.db.deserializeDecrypt(data, true), @@ -196,15 +204,16 @@ class ACL { ); const nodePerm: Record = {}; const nodeIdsGc: Set = new Set(); - for (const nodeId in nodeIds) { + for (const nodeIdString in nodeIds) { + const nodeId: NodeId = IdInternal.fromString(nodeIdString); const permId = await this.db.get( this.aclNodesDbDomain, - nodeId as NodeId, + nodeId.toBuffer(), true, ); if (permId == null) { // Invalid node id - nodeIdsGc.add(nodeId as NodeId); + nodeIdsGc.add(nodeId); continue; } const permRef = (await this.db.get( @@ -213,7 +222,7 @@ class ACL { )) as Ref; if (!(vaultId in permRef.object.vaults)) { // Vault id is missing from the perm - nodeIdsGc.add(nodeId as NodeId); + nodeIdsGc.add(nodeId); continue; } nodePerm[nodeId] = permRef.object; @@ -244,7 +253,11 @@ class ACL { @ready(new aclErrors.ErrorACLNotRunning()) public async getNodePerm(nodeId: NodeId): Promise { return await this._transaction(async () => { - const permId = await this.db.get(this.aclNodesDbDomain, nodeId, true); + const permId = await this.db.get( + this.aclNodesDbDomain, + nodeId.toBuffer(), + true, + ); if (permId == null) { return; } @@ -275,15 +288,16 @@ class ACL { } const perms: Record = {}; const nodeIdsGc: Set = new Set(); - for (const nodeId in nodeIds) { + for (const nodeIdString in nodeIds) { + const nodeId: NodeId = IdInternal.fromString(nodeIdString); const permId = await this.db.get( this.aclNodesDbDomain, - nodeId as NodeId, + nodeId.toBuffer(), true, ); if (permId == null) { // Invalid node id - nodeIdsGc.add(nodeId as NodeId); + nodeIdsGc.add(nodeId); continue; } const permRef = (await this.db.get( @@ -292,7 +306,7 @@ class ACL { )) as Ref; if (!(vaultId in permRef.object.vaults)) { // Vault id is missing from the perm - nodeIdsGc.add(nodeId as NodeId); + nodeIdsGc.add(nodeId); continue; } perms[nodeId] = permRef.object; @@ -318,7 +332,11 @@ class ACL { action: GestaltAction, ): Promise { return await this._transaction(async () => { - const permId = await this.db.get(this.aclNodesDbDomain, nodeId, true); + const permId = await this.db.get( + this.aclNodesDbDomain, + nodeId.toBuffer(), + true, + ); const ops: Array = []; if (permId == null) { const permId = await aclUtils.generatePermId(); @@ -341,7 +359,7 @@ class ACL { { type: 'put', domain: this.aclNodesDbDomain, - key: nodeId, + key: nodeId.toBuffer(), value: idUtils.toBuffer(permId), raw: true, }, @@ -369,7 +387,11 @@ class ACL { action: GestaltAction, ): Promise { return await this._transaction(async () => { - const permId = await this.db.get(this.aclNodesDbDomain, nodeId, true); + const permId = await this.db.get( + this.aclNodesDbDomain, + nodeId.toBuffer(), + true, + ); if (permId == null) { return; } @@ -394,7 +416,11 @@ class ACL { this.aclVaultsDbDomain, idUtils.toBuffer(vaultId), )) ?? {}; - const permId = await this.db.get(this.aclNodesDbDomain, nodeId, true); + const permId = await this.db.get( + this.aclNodesDbDomain, + nodeId.toBuffer(), + true, + ); if (permId == null) { throw new aclErrors.ErrorACLNodeIdMissing(); } @@ -419,7 +445,7 @@ class ACL { { type: 'put', domain: this.aclNodesDbDomain, - key: nodeId, + key: nodeId.toBuffer(), value: permId, raw: true, }, @@ -448,7 +474,11 @@ class ACL { if (nodeIds == null || !(nodeId in nodeIds)) { return; } - const permId = await this.db.get(this.aclNodesDbDomain, nodeId, true); + const permId = await this.db.get( + this.aclNodesDbDomain, + nodeId.toBuffer(), + true, + ); if (permId == null) { return; } @@ -491,7 +521,7 @@ class ACL { for (const nodeId of nodeIds) { const permIdBuffer = await this.db.get( this.aclNodesDbDomain, - nodeId, + nodeId.toBuffer(), true, ); if (permIdBuffer == null) { @@ -537,7 +567,7 @@ class ACL { ops.push({ domain: this.aclNodesDbDomain, type: 'put', - key: nodeId, + key: nodeId.toBuffer(), value: idUtils.toBuffer(permId), raw: true, }); @@ -558,7 +588,11 @@ class ACL { nodeId: NodeId, perm: Permission, ): Promise> { - const permId = await this.db.get(this.aclNodesDbDomain, nodeId, true); + const permId = await this.db.get( + this.aclNodesDbDomain, + nodeId.toBuffer(), + true, + ); const ops: Array = []; if (permId == null) { const permId = await aclUtils.generatePermId(); @@ -576,7 +610,7 @@ class ACL { { type: 'put', domain: this.aclNodesDbDomain, - key: nodeId, + key: nodeId.toBuffer(), value: idUtils.toBuffer(permId), raw: true, }, @@ -608,7 +642,11 @@ class ACL { @ready(new aclErrors.ErrorACLNotRunning()) public async unsetNodePermOps(nodeId: NodeId): Promise> { - const permId = await this.db.get(this.aclNodesDbDomain, nodeId, true); + const permId = await this.db.get( + this.aclNodesDbDomain, + nodeId.toBuffer(), + true, + ); if (permId == null) { return []; } @@ -635,7 +673,7 @@ class ACL { ops.push({ type: 'del', domain: this.aclNodesDbDomain, - key: nodeId, + key: nodeId.toBuffer(), }); // We do not remove the node id from the vaults // they can be removed later upon inspection @@ -653,10 +691,11 @@ class ACL { return; } const ops: Array = []; - for (const nodeId in nodeIds) { + for (const nodeIdString in nodeIds) { + const nodeId: NodeId = IdInternal.fromString(nodeIdString); const permId = await this.db.get( this.aclNodesDbDomain, - nodeId as NodeId, + nodeId.toBuffer(), true, ); // Skip if the nodeId doesn't exist @@ -703,7 +742,11 @@ class ACL { nodeIdsJoin: Array, perm?: Permission, ): Promise> { - const permId = await this.db.get(this.aclNodesDbDomain, nodeId, true); + const permId = await this.db.get( + this.aclNodesDbDomain, + nodeId.toBuffer(), + true, + ); if (permId == null) { throw new aclErrors.ErrorACLNodeIdMissing(); } @@ -719,7 +762,7 @@ class ACL { for (const nodeIdJoin of nodeIdsJoin) { const permIdJoin = await this.db.get( this.aclNodesDbDomain, - nodeIdJoin, + nodeIdJoin.toBuffer(), true, ); if (permIdJoin === permId) { @@ -750,7 +793,7 @@ class ACL { ops.push({ type: 'put', domain: this.aclNodesDbDomain, - key: nodeIdJoin, + key: nodeIdJoin.toBuffer(), value: permId, raw: true, }); @@ -789,15 +832,16 @@ class ACL { } const ops: Array = []; const nodeIdsGc: Set = new Set(); - for (const nodeId in nodeIds) { + for (const nodeIdString in nodeIds) { + const nodeId: NodeId = IdInternal.fromString(nodeIdString); const permId = await this.db.get( this.aclNodesDbDomain, - nodeId as NodeId, + nodeId.toBuffer(), true, ); if (permId == null) { // Invalid node id - nodeIdsGc.add(nodeId as NodeId); + nodeIdsGc.add(nodeId); continue; } const permRef = (await this.db.get( @@ -806,7 +850,7 @@ class ACL { )) as Ref; if (!(vaultId in permRef.object.vaults)) { // Vault id is missing from the perm - nodeIdsGc.add(nodeId as NodeId); + nodeIdsGc.add(nodeId); continue; } const vaultActions: VaultActions | undefined = diff --git a/src/agent/GRPCClientAgent.ts b/src/agent/GRPCClientAgent.ts index 19f63f3cb..7b882cafe 100644 --- a/src/agent/GRPCClientAgent.ts +++ b/src/agent/GRPCClientAgent.ts @@ -13,7 +13,8 @@ import type * as notificationsPB from '../proto/js/polykey/v1/notifications/noti import Logger from '@matrixai/logger'; import { CreateDestroy, ready } from '@matrixai/async-init/dist/CreateDestroy'; import * as agentErrors from './errors'; -import { GRPCClient, utils as grpcUtils } from '../grpc'; +import * as grpcUtils from '../grpc/utils'; +import GRPCClient from '../grpc/GRPCClient'; import { AgentServiceClient } from '../proto/js/polykey/v1/agent_service_grpc_pb'; interface GRPCClientAgent extends CreateDestroy {} diff --git a/src/agent/service/nodesClosestLocalNodesGet.ts b/src/agent/service/nodesClosestLocalNodesGet.ts index 5ef5fc071..5c643bbe0 100644 --- a/src/agent/service/nodesClosestLocalNodesGet.ts +++ b/src/agent/service/nodesClosestLocalNodesGet.ts @@ -19,7 +19,7 @@ function nodesClosestLocalNodesGet({ ): Promise => { const response = new nodesPB.NodeTable(); try { - const targetNodeId = nodesUtils.makeNodeId(call.request.getNodeId()); + const targetNodeId = nodesUtils.decodeNodeId(call.request.getNodeId()); // Get all local nodes that are closest to the target node from the request const closestNodes = await nodeManager.getClosestLocalNodes(targetNodeId); for (const node of closestNodes) { @@ -27,7 +27,9 @@ function nodesClosestLocalNodesGet({ addressMessage.setHost(node.address.host); addressMessage.setPort(node.address.port); // Add the node to the response's map (mapping of node ID -> node address) - response.getNodeTableMap().set(node.id, addressMessage); + response + .getNodeTableMap() + .set(nodesUtils.encodeNodeId(node.id), addressMessage); } } catch (err) { callback(grpcUtils.fromError(err), response); diff --git a/src/agent/service/nodesCrossSignClaim.ts b/src/agent/service/nodesCrossSignClaim.ts index 55857e140..729bd6064 100644 --- a/src/agent/service/nodesCrossSignClaim.ts +++ b/src/agent/service/nodesCrossSignClaim.ts @@ -6,6 +6,7 @@ import type { KeyManager } from '../../keys'; import type * as nodesPB from '../../proto/js/polykey/v1/nodes/nodes_pb'; import { utils as grpcUtils } from '../../grpc'; import { utils as claimsUtils, errors as claimsErrors } from '../../claims'; +import { utils as nodesUtils } from '../../nodes'; function nodesCrossSignClaim({ keyManager, @@ -66,7 +67,7 @@ function nodesCrossSignClaim({ } // Verify the claim const senderPublicKey = await nodeManager.getPublicKey( - payloadData.node1, + nodesUtils.decodeNodeId(payloadData.node1), ); const verified = await claimsUtils.verifyClaimSignature( constructedEncodedClaim, @@ -79,12 +80,12 @@ function nodesCrossSignClaim({ const doublySignedClaim = await claimsUtils.signIntermediaryClaim({ claim: constructedIntermediaryClaim, privateKey: keyManager.getRootKeyPairPem().privateKey, - signeeNodeId: nodeManager.getNodeId(), + signeeNodeId: nodesUtils.encodeNodeId(nodeManager.getNodeId()), }); // Then create your own intermediary node claim (from X -> Y) const singlySignedClaim = await sigchain.createIntermediaryClaim({ type: 'node', - node1: nodeManager.getNodeId(), + node1: nodesUtils.encodeNodeId(nodeManager.getNodeId()), node2: payloadData.node1, }); // Should never be reached, but just for type safety diff --git a/src/agent/service/nodesHolePunchMessageSend.ts b/src/agent/service/nodesHolePunchMessageSend.ts index d1a1ea8aa..2668bfa41 100644 --- a/src/agent/service/nodesHolePunchMessageSend.ts +++ b/src/agent/service/nodesHolePunchMessageSend.ts @@ -22,7 +22,7 @@ function nodesHolePunchMessageSend({ // back to the source node. if ( nodeManager.getNodeId() === - nodesUtils.makeNodeId(call.request.getTargetId()) + nodesUtils.decodeNodeId(call.request.getTargetId()) ) { const [host, port] = networkUtils.parseAddress( call.request.getEgressAddress(), @@ -32,7 +32,7 @@ function nodesHolePunchMessageSend({ // If so, ask the nodeManager to relay to the node } else if ( await nodeManager.knowsNode( - nodesUtils.makeNodeId(call.request.getSrcId()), + nodesUtils.decodeNodeId(call.request.getSrcId()), ) ) { await nodeManager.relayHolePunchMessage(call.request); diff --git a/src/bin/identities/CommandDiscover.ts b/src/bin/identities/CommandDiscover.ts index ab8aa2b7b..dea63c9cb 100644 --- a/src/bin/identities/CommandDiscover.ts +++ b/src/bin/identities/CommandDiscover.ts @@ -50,7 +50,7 @@ class CommandDiscover extends CommandPolykey { port: clientOptions.clientPort, logger: this.logger.getChild(PolykeyClient.name), }); - if (gestaltId.nodeId) { + if (gestaltId.nodeId != null) { // Discovery by Node. const nodeMessage = new nodesPB.Node(); nodeMessage.setNodeId(gestaltId.nodeId); diff --git a/src/bin/utils/parsers.ts b/src/bin/utils/parsers.ts index 83ca45876..8595eb688 100644 --- a/src/bin/utils/parsers.ts +++ b/src/bin/utils/parsers.ts @@ -1,7 +1,8 @@ import type { IdentityId, ProviderId } from '../../identities/types'; import type { Host, Hostname, Port } from '../../network/types'; -import type { NodeAddress, NodeId, NodeMapping } from '../../nodes/types'; +import type { NodeId, NodeMapping } from '../../nodes/types'; import commander from 'commander'; +import { IdInternal } from '@matrixai/id'; import * as nodesUtils from '../../nodes/utils'; import * as networkUtils from '../../network/utils'; import config from '../../config'; @@ -48,7 +49,7 @@ function parseGestaltId(gestaltId: string) { const parsed = parseIdentityString(gestaltId); providerId = parsed.providerId; identityId = parsed.identityId; - } else if (nodesUtils.isNodeId(gestaltId)) { + } else if (gestaltId != null) { nodeId = gestaltId; } else { throw new commander.InvalidArgumentError( @@ -85,12 +86,11 @@ function getDefaultSeedNodes(network: string): NodeMapping { never(); } for (const id in source) { - const seedNodeId = id as NodeId; - const seedNodeAddress: NodeAddress = { + const seedNodeId = IdInternal.fromString(id); + seedNodes[seedNodeId] = { host: source[seedNodeId].host as Host | Hostname, port: source[seedNodeId].port as Port, }; - seedNodes[seedNodeId] = seedNodeAddress; } return seedNodes; } @@ -122,7 +122,8 @@ function parseSeedNodes(rawSeedNodes: string): [NodeMapping, boolean] { `${rawSeedNode} is not of format 'nodeId@host:port'`, ); } - if (!nodesUtils.isNodeId(idHostPort[0])) { + const seedNodeId = nodesUtils.decodeNodeId(idHostPort[0]); + if (seedNodeId == null) { throw new commander.InvalidOptionArgumentError( `${idHostPort[0]} is not a valid node ID`, ); @@ -133,12 +134,10 @@ function parseSeedNodes(rawSeedNodes: string): [NodeMapping, boolean] { ); } const port = parseNumber(idHostPort[2]); - const seedNodeId = idHostPort[0] as NodeId; - const seedNodeAddress: NodeAddress = { + seedNodeMappings[seedNodeId] = { host: idHostPort[1] as Host | Hostname, port: port as Port, }; - seedNodeMappings[seedNodeId] = seedNodeAddress; } return [seedNodeMappings, defaults]; } diff --git a/src/bin/utils/processors.ts b/src/bin/utils/processors.ts index 9bd561be7..78b37713f 100644 --- a/src/bin/utils/processors.ts +++ b/src/bin/utils/processors.ts @@ -1,6 +1,6 @@ import type { FileSystem } from '../../types'; import type { RecoveryCode } from '../../keys/types'; -import type { NodeId } from '../../nodes/types'; +import type { NodeId, NodeIdEncoded } from '../../nodes/types'; import type { Host, Port } from '../../network/types'; import type { StatusStarting, @@ -17,6 +17,7 @@ import * as binErrors from '../errors'; import * as clientUtils from '../../client/utils'; import { Status } from '../../status'; import config from '../../config'; +import { utils as nodesUtils } from '../../nodes'; /** * Prompts for existing password @@ -191,7 +192,7 @@ async function processRecoveryCode( */ async function processClientOptions( nodePath: string, - nodeId?: NodeId, + nodeId?: NodeIdEncoded, clientHost?: Host, clientPort?: Port, fs = require('fs'), @@ -214,12 +215,13 @@ async function processClientOptions( if (statusInfo === undefined || statusInfo.status !== 'LIVE') { throw new binErrors.ErrorCLIStatusNotLive(); } - if (nodeId == null) nodeId = statusInfo.data.nodeId; + if (nodeId == null) + nodeId = nodesUtils.encodeNodeId(statusInfo.data.nodeId); if (clientHost == null) clientHost = statusInfo.data.clientHost; if (clientPort == null) clientPort = statusInfo.data.clientPort; } return { - nodeId, + nodeId: nodesUtils.decodeNodeId(nodeId), clientHost: clientHost, clientPort: clientPort, }; @@ -233,7 +235,7 @@ async function processClientOptions( */ async function processClientStatus( nodePath: string, - nodeId?: NodeId, + nodeId?: NodeIdEncoded, clientHost?: Host, clientPort?: Port, fs = require('fs'), @@ -261,12 +263,14 @@ async function processClientStatus( clientPort: Port; } > { + let nodeIdDecoded: NodeId | undefined = + nodeId != null ? nodesUtils.decodeNodeId(nodeId) : undefined; // If all parameters are set, no status and no statusInfo is used - if (nodeId != null && clientHost != null && clientPort != null) { + if (nodeIdDecoded != null && clientHost != null && clientPort != null) { return { statusInfo: undefined, status: undefined, - nodeId, + nodeId: nodeIdDecoded, clientHost, clientPort, }; @@ -286,13 +290,13 @@ async function processClientStatus( throw new binErrors.ErrorCLIStatusMissing(); } if (statusInfo.status === 'LIVE') { - if (nodeId == null) nodeId = statusInfo.data.nodeId; + if (nodeIdDecoded == null) nodeIdDecoded = statusInfo.data.nodeId; if (clientHost == null) clientHost = statusInfo.data.clientHost; if (clientPort == null) clientPort = statusInfo.data.clientPort; return { statusInfo, status, - nodeId, + nodeId: nodeIdDecoded, clientHost, clientPort, }; @@ -300,7 +304,7 @@ async function processClientStatus( return { statusInfo, status, - nodeId, + nodeId: nodeIdDecoded, clientHost, clientPort, }; diff --git a/src/claims/types.ts b/src/claims/types.ts index f47af725a..d9a97ddc8 100644 --- a/src/claims/types.ts +++ b/src/claims/types.ts @@ -1,5 +1,5 @@ import type { Opaque } from '../types'; -import type { NodeId } from '../nodes/types'; +import type { NodeIdEncoded } from '../nodes/types'; import type { ProviderId, IdentityId } from '../identities/types'; import type { GeneralJWS, FlattenedJWSInput } from 'jose'; import type { Id, IdString } from '../GenericIdTypes'; @@ -19,7 +19,7 @@ type Claim = { data: ClaimData; // Our custom payload data iat: number; // Timestamp (initialised at JWS field) }; - signatures: Record; // Signee node ID -> claim signature // FIXME: the string union on VaultId is to prevent some false errors. + signatures: Record; // Signee node ID -> claim signature }; /** @@ -38,7 +38,7 @@ type SignatureData = { signature: string; header: { alg: string; // Signing algorithm (e.g. RS256 for RSA keys) - kid: NodeId; // Node ID of the signing keynode + kid: NodeIdEncoded; // Node ID of the signing keynode }; }; @@ -84,12 +84,12 @@ type ClaimData = ClaimLinkNode | ClaimLinkIdentity; // Cryptolink (to either a node or an identity) type ClaimLinkNode = { type: 'node'; - node1: NodeId; - node2: NodeId; + node1: NodeIdEncoded; + node2: NodeIdEncoded; }; type ClaimLinkIdentity = { type: 'identity'; - node: NodeId; + node: NodeIdEncoded; provider: ProviderId; identity: IdentityId; }; diff --git a/src/claims/utils.ts b/src/claims/utils.ts index 4dcfc742c..024892477 100644 --- a/src/claims/utils.ts +++ b/src/claims/utils.ts @@ -5,7 +5,7 @@ import type { SignatureData, ClaimIntermediary, } from './types'; -import type { NodeId } from '../nodes/types'; +import type { NodeIdEncoded } from '../nodes/types'; import type { PublicKeyPem, PrivateKeyPem } from '../keys/types'; import type { POJO } from '../types'; @@ -15,13 +15,13 @@ import { createPublicKey, createPrivateKey } from 'crypto'; import { GeneralSign, generalVerify, generateKeyPair, base64url } from 'jose'; import { md } from 'node-forge'; import canonicalize from 'canonicalize'; - import { claimIdentityValidate, claimNodeSinglySignedValidate, claimNodeDoublySignedValidate, } from './schema'; import * as claimsErrors from './errors'; + import * as nodesPB from '../proto/js/polykey/v1/nodes/nodes_pb'; /** @@ -47,7 +47,7 @@ async function createClaim({ hPrev: string | null; seq: number; data: ClaimData; - kid: NodeId; + kid: NodeIdEncoded; alg?: string; }): Promise { const payload = { @@ -79,7 +79,7 @@ async function signExistingClaim({ }: { claim: ClaimEncoded; privateKey: PrivateKeyPem; - kid: NodeId; + kid: NodeIdEncoded; alg?: string; }): Promise { const decodedClaim = await decodeClaim(claim); @@ -111,7 +111,7 @@ async function signIntermediaryClaim({ }: { claim: ClaimIntermediary; privateKey: PrivateKeyPem; - signeeNodeId: NodeId; + signeeNodeId: NodeIdEncoded; alg?: string; }): Promise { // Won't ever be undefined (at least in agentService), but for type safety @@ -161,7 +161,7 @@ function hashClaim(claim: ClaimEncoded): string { */ function decodeClaim(claim: ClaimEncoded): Claim { const textDecoder = new TextDecoder(); - const signatures: Record = {}; + const signatures: Record = {}; // Add each of the signatures and their decoded headers for (const data of claim.signatures) { // Again, should never be reached @@ -223,12 +223,18 @@ function decodeClaim(claim: ClaimEncoded): Claim { * Decodes the header of a ClaimEncoded. * Assumes encoded header is of form { alg: string, kid: NodeId }. */ -function decodeClaimHeader(header: string): { alg: string; kid: NodeId } { +function decodeClaimHeader(header: string): { + alg: string; + kid: NodeIdEncoded; +} { const textDecoder = new TextDecoder(); const decodedHeader = JSON.parse( textDecoder.decode(base64url.decode(header)), ); - return { alg: decodedHeader.alg, kid: decodedHeader.kid as NodeId }; + return { + alg: decodedHeader.alg, + kid: decodedHeader.kid, + }; } /** @@ -251,13 +257,14 @@ async function encodeClaim(claim: Claim): Promise { ); // Sign the new claim with dummy private keys for now for (const nodeId in claim.signatures) { - const signatureData = claim.signatures[nodeId as NodeId]; + const signatureData = claim.signatures[nodeId]; const header = signatureData.header; // Create a dummy private key for the current alg const { privateKey } = await generateKeyPair(header.alg); - unsignedClaim - .addSignature(privateKey) - .setProtectedHeader({ alg: header.alg, kid: header.kid }); + unsignedClaim.addSignature(privateKey).setProtectedHeader({ + alg: header.alg, + kid: header.kid, + }); } const incorrectClaim = await unsignedClaim.sign(); @@ -275,7 +282,7 @@ async function encodeClaim(claim: Claim): Promise { const decodedHeader = JSON.parse( textDecoder.decode(base64url.decode(data.protected)), ); - const nodeId = decodedHeader.kid as NodeId; + const nodeId = decodedHeader.kid; // Get the correct signature from the original passed Claim const correctSignature = claim.signatures[nodeId].signature; correctSignatureData.push({ diff --git a/src/client/service/agentStatus.ts b/src/client/service/agentStatus.ts index e71cf5a82..aad6e832b 100644 --- a/src/client/service/agentStatus.ts +++ b/src/client/service/agentStatus.ts @@ -7,6 +7,7 @@ import type * as utilsPB from '../../proto/js/polykey/v1/utils/utils_pb'; import process from 'process'; import * as grpcUtils from '../../grpc/utils'; import * as agentPB from '../../proto/js/polykey/v1/agent/agent_pb'; +import { utils as nodeUtils } from '../../nodes'; function agentStatus({ authenticate, @@ -32,7 +33,7 @@ function agentStatus({ const metadata = await authenticate(call.metadata); call.sendMetadata(metadata); response.setPid(process.pid); - response.setNodeId(keyManager.getNodeId()); + response.setNodeId(nodeUtils.encodeNodeId(keyManager.getNodeId())); response.setClientHost(grpcServerClient.host); response.setClientPort(grpcServerClient.port); response.setIngressHost(revProxy.getIngressHost()); diff --git a/src/client/service/gestaltsActionsGetByNode.ts b/src/client/service/gestaltsActionsGetByNode.ts index 9bc6d5e0b..879697f39 100644 --- a/src/client/service/gestaltsActionsGetByNode.ts +++ b/src/client/service/gestaltsActionsGetByNode.ts @@ -22,9 +22,8 @@ function gestaltsActionsGetByNode({ try { const metadata = await authenticate(call.metadata); call.sendMetadata(metadata); - const result = await gestaltGraph.getGestaltActionsByNode( - nodesUtils.makeNodeId(info.getNodeId()), - ); + const nodeId = nodesUtils.decodeNodeId(info.getNodeId()); + const result = await gestaltGraph.getGestaltActionsByNode(nodeId); if (result == null) { // Node doesn't exist, so no permissions. might throw error instead TBD. response.setActionList([]); diff --git a/src/client/service/gestaltsActionsSetByNode.ts b/src/client/service/gestaltsActionsSetByNode.ts index 5c1303cdf..2dda1e227 100644 --- a/src/client/service/gestaltsActionsSetByNode.ts +++ b/src/client/service/gestaltsActionsSetByNode.ts @@ -25,7 +25,7 @@ function gestaltsActionsSetByNode({ call.sendMetadata(metadata); // Setting the action. const action = gestaltsUtils.makeGestaltAction(info.getAction()); - const nodeId = nodesUtils.makeNodeId(info.getNode()?.getNodeId()); + const nodeId = nodesUtils.decodeNodeId(info.getNode()!.getNodeId()); await gestaltGraph.setGestaltActionByNode(nodeId, action); callback(null, response); return; diff --git a/src/client/service/gestaltsActionsUnsetByNode.ts b/src/client/service/gestaltsActionsUnsetByNode.ts index 1f9e3c297..720d6f7f5 100644 --- a/src/client/service/gestaltsActionsUnsetByNode.ts +++ b/src/client/service/gestaltsActionsUnsetByNode.ts @@ -25,7 +25,7 @@ function gestaltsActionsUnsetByNode({ call.sendMetadata(metadata); // Setting the action. const action = gestaltsUtils.makeGestaltAction(info.getAction()); - const nodeId = nodesUtils.makeNodeId(info.getNode()?.getNodeId()); + const nodeId = nodesUtils.decodeNodeId(info.getNode()!.getNodeId()); await gestaltGraph.unsetGestaltActionByNode(nodeId, action); callback(null, response); return; diff --git a/src/client/service/gestaltsDiscoveryByNode.ts b/src/client/service/gestaltsDiscoveryByNode.ts index 507215b8c..19575bb54 100644 --- a/src/client/service/gestaltsDiscoveryByNode.ts +++ b/src/client/service/gestaltsDiscoveryByNode.ts @@ -23,9 +23,8 @@ function gestaltsDiscoveryByNode({ const metadata = await authenticate(call.metadata); call.sendMetadata(metadata); // Constructing identity info. - const gen = discovery.discoverGestaltByNode( - nodesUtils.makeNodeId(info.getNodeId()), - ); + const nodeId = nodesUtils.decodeNodeId(info.getNodeId()!); + const gen = discovery.discoverGestaltByNode(nodeId); for await (const _ of gen) { // Empty } diff --git a/src/client/service/gestaltsGestaltGetByNode.ts b/src/client/service/gestaltsGestaltGetByNode.ts index beeab3df3..83f8d5c2e 100644 --- a/src/client/service/gestaltsGestaltGetByNode.ts +++ b/src/client/service/gestaltsGestaltGetByNode.ts @@ -21,9 +21,8 @@ function gestaltsGestaltGetByNode({ try { const metadata = await authenticate(call.metadata); call.sendMetadata(metadata); - const gestalt = await gestaltGraph.getGestaltByNode( - nodesUtils.makeNodeId(call.request.getNodeId()), - ); + const nodeId = nodesUtils.decodeNodeId(call.request.getNodeId()!); + const gestalt = await gestaltGraph.getGestaltByNode(nodeId); if (gestalt != null) { response.setGestaltGraph(JSON.stringify(gestalt)); } diff --git a/src/client/service/identitiesClaim.ts b/src/client/service/identitiesClaim.ts index c30d94fc5..44d71fb94 100644 --- a/src/client/service/identitiesClaim.ts +++ b/src/client/service/identitiesClaim.ts @@ -9,6 +9,7 @@ import { utils as grpcUtils } from '../../grpc'; import { utils as claimsUtils } from '../../claims'; import { errors as identitiesErrors } from '../../identities'; import * as identitiesPB from '../../proto/js/polykey/v1/identities/identities_pb'; +import { utils as nodeUtils } from '../../nodes'; /** * Augments the keynode with a new identity. @@ -44,7 +45,7 @@ function identitiesClaim({ // Create identity claim on our node const [, claim] = await sigchain.addClaim({ type: 'identity', - node: nodeManager.getNodeId(), + node: nodeUtils.encodeNodeId(nodeManager.getNodeId()), provider: providerId, identity: identityId, }); diff --git a/src/client/service/nodesAdd.ts b/src/client/service/nodesAdd.ts index 4560c0d9a..edd68a6bf 100644 --- a/src/client/service/nodesAdd.ts +++ b/src/client/service/nodesAdd.ts @@ -29,23 +29,17 @@ function nodesAdd({ const metadata = await authenticate(call.metadata); call.sendMetadata(metadata); // Validate the passed node ID and host - const validNodeId = nodesUtils.isNodeId(call.request.getNodeId()); - if (!validNodeId) { - throw new nodesErrors.ErrorInvalidNodeId(); - } + const nodeId = nodesUtils.decodeNodeId(call.request.getNodeId()); const validHost = networkUtils.isValidHost( call.request.getAddress()!.getHost(), ); if (!validHost) { throw new nodesErrors.ErrorInvalidHost(); } - await nodeManager.setNode( - nodesUtils.makeNodeId(call.request.getNodeId()), - { - host: call.request.getAddress()!.getHost(), - port: call.request.getAddress()!.getPort(), - } as NodeAddress, - ); + await nodeManager.setNode(nodeId, { + host: call.request.getAddress()!.getHost(), + port: call.request.getAddress()!.getPort(), + } as NodeAddress); callback(null, response); return; } catch (err) { diff --git a/src/client/service/nodesClaim.ts b/src/client/service/nodesClaim.ts index 7c13ad584..8b929ffaa 100644 --- a/src/client/service/nodesClaim.ts +++ b/src/client/service/nodesClaim.ts @@ -30,7 +30,7 @@ function nodesClaim({ try { const metadata = await authenticate(call.metadata); call.sendMetadata(metadata); - const remoteNodeId = nodesUtils.makeNodeId(call.request.getNodeId()); + const remoteNodeId = nodesUtils.decodeNodeId(call.request.getNodeId()); const gestaltInvite = await notificationsManager.findGestaltInvite( remoteNodeId, ); diff --git a/src/client/service/nodesFind.ts b/src/client/service/nodesFind.ts index 070a904f8..bb4d0dcd7 100644 --- a/src/client/service/nodesFind.ts +++ b/src/client/service/nodesFind.ts @@ -25,10 +25,11 @@ function nodesFind({ try { const metadata = await authenticate(call.metadata); call.sendMetadata(metadata); - const nodeId = nodesUtils.makeNodeId(call.request.getNodeId()); + const nodeIdEncoded = call.request.getNodeId(); + const nodeId = nodesUtils.decodeNodeId(nodeIdEncoded); const address = await nodeManager.findNode(nodeId); response - .setNodeId(nodeId) + .setNodeId(nodeIdEncoded) .setAddress( new nodesPB.Address().setHost(address.host).setPort(address.port), ); diff --git a/src/client/service/nodesPing.ts b/src/client/service/nodesPing.ts index e4da23b73..0653f2976 100644 --- a/src/client/service/nodesPing.ts +++ b/src/client/service/nodesPing.ts @@ -24,9 +24,8 @@ function nodesPing({ try { const metadata = await authenticate(call.metadata); call.sendMetadata(metadata); - const status = await nodeManager.pingNode( - nodesUtils.makeNodeId(call.request.getNodeId()), - ); + const nodeId = nodesUtils.decodeNodeId(call.request.getNodeId()); + const status = await nodeManager.pingNode(nodeId); response.setSuccess(status); callback(null, response); return; diff --git a/src/client/service/notificationsSend.ts b/src/client/service/notificationsSend.ts index 9992f7e73..6476f7ff2 100644 --- a/src/client/service/notificationsSend.ts +++ b/src/client/service/notificationsSend.ts @@ -22,7 +22,7 @@ function notificationsSend({ try { const metadata = await authenticate(call.metadata); call.sendMetadata(metadata); - const receivingId = nodesUtils.makeNodeId(call.request.getReceiverId()); + const receivingId = nodesUtils.decodeNodeId(call.request.getReceiverId()); const data = { type: 'General', message: call.request.getData()?.getMessage(), diff --git a/src/client/service/vaultsScan.ts b/src/client/service/vaultsScan.ts index 98fba456e..75235e770 100644 --- a/src/client/service/vaultsScan.ts +++ b/src/client/service/vaultsScan.ts @@ -17,8 +17,8 @@ function vaultsScan({ call: grpc.ServerWritableStream, ): Promise => { const genWritable = grpcUtils.generatorWritable(call); - // Const nodeId = makeNodeId(call.request.getNodeId()); - + // Const possibleNodeId = nodesUtils.decodeNodeId(call.request.getNodeId()); + // const nodeId = nodesUtils.validateNodeId(possibleNodeId); try { const metadata = await authenticate(call.metadata); call.sendMetadata(metadata); diff --git a/src/discovery/Discovery.ts b/src/discovery/Discovery.ts index 48bcf039b..757faf0a2 100644 --- a/src/discovery/Discovery.ts +++ b/src/discovery/Discovery.ts @@ -18,6 +18,7 @@ import { CreateDestroy, ready } from '@matrixai/async-init/dist/CreateDestroy'; import * as discoveryErrors from './errors'; import * as gestaltsUtils from '../gestalts/utils'; import * as claimsUtils from '../claims/utils'; +import { utils as nodesUtils } from '../nodes'; interface Discovery extends CreateDestroy {} @CreateDestroy() @@ -112,7 +113,8 @@ class Discovery { // The sigchain data of the vertex (containing all cryptolinks) let vertexChainData: ChainData = {}; // If the vertex we've found is our own node, we simply get our own chain - if (vertexGId.nodeId === this.nodeManager.getNodeId()) { + const nodeId = nodesUtils.decodeNodeId(vertexGId.nodeId); + if (nodeId.equals(this.nodeManager.getNodeId())) { const vertexChainDataEncoded = await this.nodeManager.getChainData(); // Decode all our claims - no need to verify (on our own sigchain) for (const c in vertexChainDataEncoded) { @@ -123,9 +125,7 @@ class Discovery { } // Otherwise, request the verified chain data from the node } else { - vertexChainData = await this.nodeManager.requestChainData( - vertexGId.nodeId, - ); + vertexChainData = await this.nodeManager.requestChainData(nodeId); } // TODO: for now, the chain data is treated as a 'disjoint' set of @@ -136,7 +136,7 @@ class Discovery { // Now have the NodeInfo of this vertex const vertexNodeInfo: NodeInfo = { - id: vertexGId.nodeId, + id: nodesUtils.encodeNodeId(nodeId), chain: vertexChainData, }; @@ -150,12 +150,14 @@ class Discovery { // If the claim is to a node if (claim.payload.data.type === 'node') { // Get the chain data of the linked node - const linkedVertexNodeId = claim.payload.data.node2; + const linkedVertexNodeId = nodesUtils.decodeNodeId( + claim.payload.data.node2, + ); const linkedVertexChainData = await this.nodeManager.requestChainData(linkedVertexNodeId); // With this verified chain, we can link const linkedVertexNodeInfo: NodeInfo = { - id: linkedVertexNodeId, + id: nodesUtils.encodeNodeId(linkedVertexNodeId), chain: linkedVertexChainData, }; await this.gestaltGraph.linkNodeAndNode( @@ -200,7 +202,7 @@ class Discovery { } } // Add this node vertex to the visited - visitedVertices.add(gestaltsUtils.keyFromNode(vertexGId.nodeId)); + visitedVertices.add(gestaltsUtils.keyFromNode(nodeId)); } else if (vertexGId.type === 'identity') { // If the next vertex is an identity, perform a social discovery // Firstly get the identity info of this identity @@ -222,14 +224,14 @@ class Discovery { // Claims on an identity provider will always be node -> identity // So just cast payload data as such const data = claim.payload.data as ClaimLinkIdentity; - const linkedVertexNodeId = data.node; + const linkedVertexNodeId = nodesUtils.decodeNodeId(data.node); // Get the chain data of this claimed node (so that we can link in GG) const linkedVertexChainData = await this.nodeManager.requestChainData( linkedVertexNodeId, ); // With this verified chain, we can link const linkedVertexNodeInfo: NodeInfo = { - id: linkedVertexNodeId, + id: nodesUtils.encodeNodeId(linkedVertexNodeId), chain: linkedVertexChainData, }; await this.gestaltGraph.linkNodeAndIdentity( @@ -314,7 +316,7 @@ class Discovery { // Verify the claim with the public key of the node const verified = await claimsUtils.verifyClaimSignature( encoded, - await this.nodeManager.getPublicKey(data.node), + await this.nodeManager.getPublicKey(nodesUtils.decodeNodeId(data.node)), ); // If verified, add to the record if (verified) { diff --git a/src/gestalts/GestaltGraph.ts b/src/gestalts/GestaltGraph.ts index 71cbbb740..0d3d6c7df 100644 --- a/src/gestalts/GestaltGraph.ts +++ b/src/gestalts/GestaltGraph.ts @@ -1,15 +1,15 @@ import type { Buffer } from 'buffer'; import type { + Gestalt, GestaltAction, GestaltActions, - GestaltKey, - GestaltNodeKey, GestaltIdentityKey, + GestaltKey, GestaltKeySet, - Gestalt, + GestaltNodeKey, } from './types'; import type { NodeId, NodeInfo } from '../nodes/types'; -import type { ProviderId, IdentityId, IdentityInfo } from '../identities/types'; +import type { IdentityId, IdentityInfo, ProviderId } from '../identities/types'; import type { Permission } from '../acl/types'; import type { DB, DBLevel, DBOp } from '@matrixai/db'; import type { ACL } from '../acl'; @@ -24,6 +24,7 @@ import * as gestaltsUtils from './utils'; import * as gestaltsErrors from './errors'; import { utils as aclUtils } from '../acl'; import * as utils from '../utils'; +import { utils as nodesUtils } from '../nodes'; interface GestaltGraph extends CreateDestroyStartStop {} @CreateDestroyStartStop( @@ -282,7 +283,7 @@ class GestaltGraph { if (gId.type === 'node') { ops.push( ...(await this.unlinkNodeAndIdentityOps( - gId.nodeId, + nodesUtils.decodeNodeId(gId.nodeId), providerId, identityId, )), @@ -316,7 +317,9 @@ class GestaltGraph { @ready(new gestaltsErrors.ErrorGestaltsGraphNotRunning()) public async setNodeOps(nodeInfo: NodeInfo): Promise> { - const nodeKey = gestaltsUtils.keyFromNode(nodeInfo.id); + const nodeKey = gestaltsUtils.keyFromNode( + nodesUtils.decodeNodeId(nodeInfo.id), + ); const ops: Array = []; let nodeKeyKeys = await this.db.get( this.graphMatrixDbDomain, @@ -326,10 +329,13 @@ class GestaltGraph { nodeKeyKeys = {}; // Sets the gestalt in the acl ops.push( - ...(await this.acl.setNodePermOps(nodeInfo.id, { - gestalt: {}, - vaults: {}, - })), + ...(await this.acl.setNodePermOps( + nodesUtils.decodeNodeId(nodeInfo.id), + { + gestalt: {}, + vaults: {}, + }, + )), ); } ops.push( @@ -383,7 +389,12 @@ class GestaltGraph { for (const key of Object.keys(nodeKeyKeys) as Array) { const gId = gestaltsUtils.ungestaltKey(key); if (gId.type === 'node') { - ops.push(...(await this.unlinkNodeAndNodeOps(nodeId, gId.nodeId))); + ops.push( + ...(await this.unlinkNodeAndNodeOps( + nodeId, + nodesUtils.decodeNodeId(gId.nodeId), + )), + ); } else if (gId.type === 'identity') { ops.push( ...(await this.unlinkNodeAndIdentityOps( @@ -425,7 +436,9 @@ class GestaltGraph { identityInfo: IdentityInfo, ): Promise> { const ops: Array = []; - const nodeKey = gestaltsUtils.keyFromNode(nodeInfo.id); + const nodeKey = gestaltsUtils.keyFromNode( + nodesUtils.decodeNodeId(nodeInfo.id), + ); const identityKey = gestaltsUtils.keyFromIdentity( identityInfo.providerId, identityInfo.identityId, @@ -475,10 +488,13 @@ class GestaltGraph { // join node gestalt's permission to the identity gestalt if (nodeNew && identityNew) { ops.push( - ...(await this.acl.setNodePermOps(nodeInfo.id, { - gestalt: {}, - vaults: {}, - })), + ...(await this.acl.setNodePermOps( + nodesUtils.decodeNodeId(nodeInfo.id), + { + gestalt: {}, + vaults: {}, + }, + )), ); } else if ( !nodeNew && @@ -489,12 +505,13 @@ class GestaltGraph { Object.keys(identityKeyKeys) as Array, [identityKey], ); - const identityNodeIds = Array.from( - identityNodeKeys, - (key) => gestaltsUtils.ungestaltKey(key).nodeId, + const identityNodeIds = Array.from(identityNodeKeys, (key) => + gestaltsUtils.nodeFromKey(key), ); // These must exist - const nodePerm = (await this.acl.getNodePerm(nodeInfo.id)) as Permission; + const nodePerm = (await this.acl.getNodePerm( + nodesUtils.decodeNodeId(nodeInfo.id), + )) as Permission; const identityPerm = (await this.acl.getNodePerm( identityNodeIds[0], )) as Permission; @@ -505,7 +522,7 @@ class GestaltGraph { // and the perm record update ops.push( ...(await this.acl.joinNodePermOps( - nodeInfo.id, + nodesUtils.decodeNodeId(nodeInfo.id), identityNodeIds, permNew, )), @@ -513,10 +530,13 @@ class GestaltGraph { } else if (nodeNew && !identityNew) { if (utils.isEmptyObject(identityKeyKeys)) { ops.push( - ...(await this.acl.setNodePermOps(nodeInfo.id, { - gestalt: {}, - vaults: {}, - })), + ...(await this.acl.setNodePermOps( + nodesUtils.decodeNodeId(nodeInfo.id), + { + gestalt: {}, + vaults: {}, + }, + )), ); } else { let identityNodeKey: GestaltNodeKey; @@ -524,11 +544,11 @@ class GestaltGraph { identityNodeKey = gK as GestaltNodeKey; break; } - const identityNodeId = gestaltsUtils.ungestaltKey( - identityNodeKey!, - ).nodeId; + const identityNodeId = gestaltsUtils.nodeFromKey(identityNodeKey!); ops.push( - ...(await this.acl.joinNodePermOps(identityNodeId, [nodeInfo.id])), + ...(await this.acl.joinNodePermOps(identityNodeId, [ + nodesUtils.decodeNodeId(nodeInfo.id), + ])), ); } } @@ -582,8 +602,10 @@ class GestaltGraph { nodeInfo2: NodeInfo, ): Promise> { const ops: Array = []; - const nodeKey1 = gestaltsUtils.keyFromNode(nodeInfo1.id); - const nodeKey2 = gestaltsUtils.keyFromNode(nodeInfo2.id); + const nodeIdEncoded1 = nodesUtils.decodeNodeId(nodeInfo1.id); + const nodeIdEncoded2 = nodesUtils.decodeNodeId(nodeInfo2.id); + const nodeKey1 = gestaltsUtils.keyFromNode(nodeIdEncoded1); + const nodeKey2 = gestaltsUtils.keyFromNode(nodeIdEncoded2); let nodeKeyKeys1 = await this.db.get( this.graphMatrixDbDomain, nodeKey1, @@ -623,7 +645,7 @@ class GestaltGraph { // join node 1 gestalt's permission to the node 2 gestalt if (nodeNew1 && nodeNew2) { ops.push( - ...(await this.acl.setNodesPermOps([nodeInfo1.id, nodeInfo2.id], { + ...(await this.acl.setNodesPermOps([nodeIdEncoded1, nodeIdEncoded2], { gestalt: {}, vaults: {}, })), @@ -633,16 +655,15 @@ class GestaltGraph { Object.keys(nodeKeyKeys2) as Array, [nodeKey2], ); - const nodeNodeIds2 = Array.from( - nodeNodeKeys2, - (key) => gestaltsUtils.ungestaltKey(key).nodeId, + const nodeNodeIds2 = Array.from(nodeNodeKeys2, (key) => + gestaltsUtils.nodeFromKey(key), ); // These must exist const nodePerm1 = (await this.acl.getNodePerm( - nodeInfo1.id, + nodeIdEncoded1, )) as Permission; const nodePerm2 = (await this.acl.getNodePerm( - nodeInfo2.id, + nodeIdEncoded2, )) as Permission; // Union the perms together const permNew = aclUtils.permUnion(nodePerm1, nodePerm2); @@ -651,18 +672,18 @@ class GestaltGraph { // and the perm record update ops.push( ...(await this.acl.joinNodePermOps( - nodeInfo1.id, + nodeIdEncoded1, nodeNodeIds2, permNew, )), ); } else if (nodeNew1 && !nodeNew2) { ops.push( - ...(await this.acl.joinNodePermOps(nodeInfo2.id, [nodeInfo1.id])), + ...(await this.acl.joinNodePermOps(nodeIdEncoded2, [nodeIdEncoded1])), ); } else if (!nodeNew1 && nodeNew2) { ops.push( - ...(await this.acl.joinNodePermOps(nodeInfo1.id, [nodeInfo2.id])), + ...(await this.acl.joinNodePermOps(nodeIdEncoded1, [nodeIdEncoded2])), ); } nodeKeyKeys1[nodeKey2] = null; @@ -761,9 +782,8 @@ class GestaltGraph { [nodeKey], ); if (!gestaltIdentityKeys.has(identityKey)) { - const nodeIds = Array.from( - gestaltNodeKeys, - (key) => gestaltsUtils.ungestaltKey(key).nodeId, + const nodeIds = Array.from(gestaltNodeKeys, (key) => + gestaltsUtils.nodeFromKey(key), ); // It is assumed that an existing gestalt has a permission const perm = (await this.acl.getNodePerm(nodeId)) as Permission; @@ -832,9 +852,8 @@ class GestaltGraph { [nodeKey1], ); if (!gestaltNodeKeys.has(nodeKey2)) { - const nodeIds = Array.from( - gestaltNodeKeys, - (key) => gestaltsUtils.ungestaltKey(key).nodeId, + const nodeIds = Array.from(gestaltNodeKeys, (key) => + gestaltsUtils.nodeFromKey(key), ); // It is assumed that an existing gestalt has a permission const perm = (await this.acl.getNodePerm(nodeId1)) as Permission; @@ -892,7 +911,7 @@ class GestaltGraph { )) as GestaltKeySet; let nodeId: NodeId | undefined; for (const nodeKey in gestaltKeySet) { - nodeId = gestaltsUtils.ungestaltKey(nodeKey as GestaltNodeKey).nodeId; + nodeId = gestaltsUtils.nodeFromKey(nodeKey as GestaltNodeKey); break; } if (nodeId == null) { @@ -952,7 +971,7 @@ class GestaltGraph { )) as GestaltKeySet; let nodeId: NodeId | undefined; for (const nodeKey in gestaltKeySet) { - nodeId = gestaltsUtils.ungestaltKey(nodeKey as GestaltNodeKey).nodeId; + nodeId = gestaltsUtils.nodeFromKey(nodeKey as GestaltNodeKey); break; } // If there are no linked nodes, this cannot proceed @@ -1009,7 +1028,7 @@ class GestaltGraph { )) as GestaltKeySet; let nodeId: NodeId | undefined; for (const nodeKey in gestaltKeySet) { - nodeId = gestaltsUtils.ungestaltKey(nodeKey as GestaltNodeKey).nodeId; + nodeId = gestaltsUtils.nodeFromKey(nodeKey as GestaltNodeKey); break; } // If there are no linked nodes, this cannot proceed diff --git a/src/gestalts/types.ts b/src/gestalts/types.ts index 6c7e8b9c0..19e8adb54 100644 --- a/src/gestalts/types.ts +++ b/src/gestalts/types.ts @@ -1,5 +1,5 @@ import type { Opaque } from '../types'; -import type { NodeId, NodeInfo } from '../nodes/types'; +import type { NodeIdEncoded, NodeInfo } from '../nodes/types'; import type { IdentityId, ProviderId, IdentityInfo } from '../identities/types'; type GestaltAction = 'notify' | 'scan'; @@ -8,7 +8,7 @@ type GestaltActions = Partial>; type GestaltId = GestaltNodeId | GestaltIdentityId; type GestaltNodeId = { type: 'node'; - nodeId: NodeId; + nodeId: NodeIdEncoded; }; type GestaltIdentityId = { type: 'identity'; diff --git a/src/gestalts/utils.ts b/src/gestalts/utils.ts index 51af8b67d..47bda4ece 100644 --- a/src/gestalts/utils.ts +++ b/src/gestalts/utils.ts @@ -12,6 +12,7 @@ import type { IdentityId, ProviderId } from '../identities/types'; import canonicalize from 'canonicalize'; import { ErrorGestaltsInvalidAction } from './errors'; +import { utils as nodesUtils } from '../nodes'; /** * Construct GestaltKey from GestaltId @@ -37,7 +38,10 @@ function ungestaltKey(gestaltKey: GestaltKey): GestaltId { * Construct GestaltKey from NodeId */ function keyFromNode(nodeId: NodeId): GestaltNodeKey { - return gestaltKey({ type: 'node', nodeId }) as GestaltNodeKey; + return gestaltKey({ + type: 'node', + nodeId: nodesUtils.encodeNodeId(nodeId), + }) as GestaltNodeKey; } /** @@ -60,7 +64,7 @@ function keyFromIdentity( */ function nodeFromKey(nodeKey: GestaltNodeKey): NodeId { const node = ungestaltKey(nodeKey) as GestaltNodeId; - return node.nodeId; + return nodesUtils.decodeNodeId(node.nodeId); } /** diff --git a/src/grpc/GRPCClient.ts b/src/grpc/GRPCClient.ts index 1c2e02bd4..6fc1f4647 100644 --- a/src/grpc/GRPCClient.ts +++ b/src/grpc/GRPCClient.ts @@ -17,6 +17,7 @@ import * as grpcErrors from './errors'; import { utils as keysUtils } from '../keys'; import { utils as networkUtils, errors as networkErrors } from '../network'; import { promisify, promise, timerStart, timerStop } from '../utils'; +import { utils as nodeUtils } from '../nodes'; abstract class GRPCClient { /** @@ -58,6 +59,7 @@ abstract class GRPCClient { flowCountInterceptor: grpcUtils.FlowCountInterceptor; serverCertChain?: Array; }> { + const nodeIdEncoded = nodeUtils.encodeNodeId(nodeId); const address = networkUtils.buildAddress(host, port); logger.info(`Creating ${this.name} connecting to ${address}`); let channelCredentials: ChannelCredentials; @@ -79,7 +81,7 @@ abstract class GRPCClient { // The channel options is needed to be able to look up the server certificate const channelOptions: ChannelOptions = { // Prevents complaints with having an ip address as the server name - 'grpc.ssl_target_name_override': nodeId, + 'grpc.ssl_target_name_override': nodeIdEncoded, }; const flowCountInterceptor = new grpcUtils.FlowCountInterceptor(); const clientOptions: ClientOptions = { @@ -99,13 +101,13 @@ abstract class GRPCClient { ); // Encode as a URI in order to preserve the '+' characters when retrieving // in ForwardProxy from the http_connect_target URL - const encodedNodeId = encodeURIComponent(nodeId); + const nodeIdEncodedForURI = encodeURIComponent(nodeIdEncoded); // Ignore proxy env variables channelOptions['grpc.enable_http_proxy'] = 0; // The proxy target target is the true address channelOptions[ 'grpc.http_connect_target' - ] = `dns:${address}/?nodeId=${encodedNodeId}`; + ] = `dns:${address}/?nodeId=${nodeIdEncodedForURI}`; channelOptions['grpc.http_connect_creds'] = proxyConfig.authToken; client = new clientConstructor(proxyAddress, channelCredentials, { ...channelOptions, @@ -130,7 +132,7 @@ abstract class GRPCClient { port, ); const socket = session.socket as TLSSocket; - const serverCertChain = networkUtils.getCertificateChain(socket); + serverCertChain = networkUtils.getCertificateChain(socket); try { networkUtils.verifyServerCertificateChain(nodeId, serverCertChain); } catch (e) { diff --git a/src/keys/KeyManager.ts b/src/keys/KeyManager.ts index c7c780aaf..dea504132 100644 --- a/src/keys/KeyManager.ts +++ b/src/keys/KeyManager.ts @@ -23,7 +23,6 @@ import { import * as keysUtils from './utils'; import * as keysErrors from './errors'; import * as utils from '../utils'; -import * as networkUtils from '../network/utils'; /** * Manage Root Keys and Root Certificates @@ -277,7 +276,7 @@ class KeyManager { */ @ready(new keysErrors.ErrorKeyManagerNotRunning()) public getNodeId(): NodeId { - return networkUtils.certNodeId(this.getRootCert()); + return keysUtils.publicKeyToNodeId(this.rootKeyPair.publicKey); } @ready(new keysErrors.ErrorKeyManagerNotRunning()) diff --git a/src/keys/utils.ts b/src/keys/utils.ts index b21027835..0d990ef81 100644 --- a/src/keys/utils.ts +++ b/src/keys/utils.ts @@ -1,39 +1,39 @@ import type { + Certificate, + CertificateAsn1, + CertificatePem, KeyPair, KeyPairAsn1, KeyPairPem, - PublicKey, PrivateKey, + PrivateKeyAsn1, PrivateKeyPem, - Certificate, - PublicKeyFingerprintBytes, - PublicKeyFingerprint, - CertificateAsn1, - CertificatePem, + PublicKey, PublicKeyAsn1, - PrivateKeyAsn1, PublicKeyPem, RecoveryCode, } from './types'; +import type { NodeId } from '../nodes/types'; import { Buffer } from 'buffer'; import { - pki, - md, - pss, - random, + asn1, cipher, + md, mgf, - asn1, pkcs5, + pki, + pss, + random, util as forgeUtil, } from 'node-forge'; import * as bip39 from 'bip39'; +import { IdInternal } from '@matrixai/id'; import * as keysErrors from './errors'; import config from '../config'; import * as utils from '../utils'; -import { never } from '../utils'; // Using never as utils.never seems to cause a build error. function thinks it could return undefined. -import { makeNodeId } from '../nodes/utils'; +import { never } from '../utils'; +import { utils as nodesUtils } from '../nodes'; bip39.setDefaultWordlist('english'); @@ -165,22 +165,14 @@ function keyPairCopy(keyPair: KeyPair): KeyPair { return keyPairFromAsn1(keyPairToAsn1(keyPair)); } -function publicKeyToFingerprintBytes( - publicKey: PublicKey, -): PublicKeyFingerprintBytes { +function publicKeyToNodeId(publicKey: PublicKey): NodeId { const fString = pki.getPublicKeyFingerprint(publicKey, { type: 'SubjectPublicKeyInfo', md: md.sha256.create(), encoding: 'binary', }); - return fString; -} - -function publicKeyToFingerprint(publicKey: PublicKey): PublicKeyFingerprint { - const fString = publicKeyToFingerprintBytes(publicKey); const fTypedArray = forgeUtil.binary.raw.decode(fString); - const f = makeNodeId(fTypedArray); - return f; + return IdInternal.create(fTypedArray); } function encryptPrivateKey( @@ -239,14 +231,16 @@ function generateCertificate( ...subjectAttrsExtra, { name: 'commonName', - value: publicKeyToFingerprint(subjectPublicKey), + value: nodesUtils.encodeNodeId(publicKeyToNodeId(subjectPublicKey)), }, ]; const issuerAttrs = [ ...issuerAttrsExtra, { name: 'commonName', - value: publicKeyToFingerprint(publicKeyFromPrivateKey(issuerPrivateKey)), + value: nodesUtils.encodeNodeId( + publicKeyToNodeId(publicKeyFromPrivateKey(issuerPrivateKey)), + ), }, ]; cert.setSubject(subjectAttrs); @@ -287,7 +281,7 @@ function generateCertificate( altNames: [ { type: 2, - value: publicKeyToFingerprint(subjectPublicKey), + value: nodesUtils.encodeNodeId(publicKeyToNodeId(subjectPublicKey)), }, { type: 7, @@ -588,8 +582,7 @@ export { keyPairToPemEncrypted, keyPairFromPemEncrypted, keyPairCopy, - publicKeyToFingerprintBytes, - publicKeyToFingerprint, + publicKeyToNodeId, encryptPrivateKey, decryptPrivateKey, publicKeyFromPrivateKey, diff --git a/src/network/ForwardProxy.ts b/src/network/ForwardProxy.ts index fe6fb68ef..83af4a088 100644 --- a/src/network/ForwardProxy.ts +++ b/src/network/ForwardProxy.ts @@ -13,6 +13,7 @@ import ConnectionForward from './ConnectionForward'; import * as networkUtils from './utils'; import * as networkErrors from './errors'; import { promisify, timerStart, timerStop } from '../utils'; +import { utils as nodesUtils } from '../nodes'; interface ForwardProxy extends StartStop {} @StartStop() @@ -299,7 +300,11 @@ class ForwardProxy { return; } const url = new URL(`pk://${request.url}`); - const nodeId = url.searchParams.get('nodeId') as NodeId | null; + const nodeIdEncodedForURL = url.searchParams.get('nodeId'); + const nodeId = + nodeIdEncodedForURL != null + ? nodesUtils.decodeNodeId(nodeIdEncodedForURL) + : undefined; if (nodeId == null) { await clientSocketEnd('HTTP/1.1 400 Bad Request\r\n' + '\r\n'); clientSocket.destroy(new networkErrors.ErrorForwardProxyMissingNodeId()); diff --git a/src/network/utils.ts b/src/network/utils.ts index baba7f03c..4058177e6 100644 --- a/src/network/utils.ts +++ b/src/network/utils.ts @@ -10,6 +10,7 @@ import { IPv4, IPv6, Validator } from 'ip-num'; import * as networkErrors from './errors'; import { isEmptyObject, promisify } from '../utils'; import { utils as keysUtils } from '../keys'; +import { utils as nodesUtils } from '../nodes'; const pingBuffer = serializeNetworkMessage({ type: 'ping', @@ -168,7 +169,7 @@ function isTLSSocket(socket: Socket | TLSSocket): socket is TLSSocket { */ function certNodeId(cert: Certificate): NodeId { const commonName = cert.subject.getField({ type: '2.5.4.3' }); - return commonName.value as NodeId; + return nodesUtils.decodeNodeId(commonName.value); } /** @@ -214,10 +215,8 @@ function verifyServerCertificateChain( }, ); } - const certNodeId = keysUtils.publicKeyToFingerprint( - cert.publicKey as PublicKey, - ); - if (commonName.value !== certNodeId) { + const certNodeId = keysUtils.publicKeyToNodeId(cert.publicKey as PublicKey); + if (commonName.value !== nodesUtils.encodeNodeId(certNodeId)) { throw new networkErrors.ErrorCertChainKeyInvalid( 'Chain certificate public key does not generate its node id', { @@ -237,7 +236,7 @@ function verifyServerCertificateChain( }, ); } - if (commonName.value === nodeId) { + if (commonName.value === nodesUtils.encodeNodeId(nodeId)) { // Found the certificate claiming the nodeId certClaim = cert; certClaimIndex = certIndex; @@ -311,10 +310,8 @@ function verifyClientCertificateChain(certChain: Array): void { }, ); } - const certNodeId = keysUtils.publicKeyToFingerprint( - cert.publicKey as PublicKey, - ); - if (commonName.value !== certNodeId) { + const certNodeId = keysUtils.publicKeyToNodeId(cert.publicKey as PublicKey); + if (commonName.value !== nodesUtils.encodeNodeId(certNodeId)) { throw new networkErrors.ErrorCertChainKeyInvalid( 'Chain certificate public key does not generate its node id', { diff --git a/src/nodes/NodeConnection.ts b/src/nodes/NodeConnection.ts index fd5ac92b5..b844fa4c2 100644 --- a/src/nodes/NodeConnection.ts +++ b/src/nodes/NodeConnection.ts @@ -18,11 +18,10 @@ import { } from '@matrixai/async-init/dist/CreateDestroyStartStop'; import * as nodesUtils from './utils'; import * as nodesErrors from './errors'; -import * as claimsUtils from '../claims/utils'; -import * as claimsErrors from '../claims/errors'; -import * as keysUtils from '../keys/utils'; -import * as vaultsUtils from '../vaults/utils'; -import * as grpcErrors from '../grpc/errors'; +import { utils as claimsUtils, errors as claimsErrors } from '../claims'; +import { utils as keysUtils } from '../keys'; +import { utils as vaultsUtils } from '../vaults'; +import { errors as grpcErrors } from '../grpc'; import { GRPCClientAgent } from '../agent'; import * as utilsPB from '../proto/js/polykey/v1/utils/utils_pb'; import * as nodesPB from '../proto/js/polykey/v1/nodes/nodes_pb'; @@ -190,9 +189,9 @@ class NodeConnection { // 5. When finished, you have a connection to other node // The GRPCClient is ready to be used for requests this.logger.info( - `Started ${ - this.constructor.name - } from ${this.keyManager.getNodeId()} to ${this.targetNodeId}`, + `Started ${this.constructor.name} from ${nodesUtils.encodeNodeId( + this.keyManager.getNodeId(), + )} to ${nodesUtils.encodeNodeId(this.targetNodeId)}`, ); } @@ -247,7 +246,7 @@ class NodeConnection { const certificates = this.getRootCertChain(); let publicKey: PublicKeyPem | null = null; for (const cert of certificates) { - if (networkUtils.certNodeId(cert) === expectedNodeId) { + if (networkUtils.certNodeId(cert).equals(expectedNodeId)) { publicKey = keysUtils.publicKeyToPem( cert.publicKey as PublicKey, ) as PublicKeyPem; @@ -266,19 +265,20 @@ class NodeConnection { public async getClosestNodes(targetNodeId: NodeId): Promise> { // Construct the message const nodeIdMessage = new nodesPB.Node(); - nodeIdMessage.setNodeId(targetNodeId); + nodeIdMessage.setNodeId(nodesUtils.encodeNodeId(targetNodeId)); // Send through client const response = await this.client.nodesClosestLocalNodesGet(nodeIdMessage); const nodes: Array = []; // Loop over each map element (from the returned response) and populate nodes - response.getNodeTableMap().forEach((address, nodeId: string) => { + response.getNodeTableMap().forEach((address, nodeIdEncoded: string) => { + const nodeId: NodeId = nodesUtils.decodeNodeId(nodeIdEncoded); nodes.push({ - id: nodeId as NodeId, + id: nodeId, address: { host: address.getHost() as Host | Hostname, port: address.getPort() as Port, }, - distance: nodesUtils.calculateDistance(targetNodeId, nodeId as NodeId), + distance: nodesUtils.calculateDistance(targetNodeId, nodeId), }); }); return nodes; @@ -302,8 +302,8 @@ class NodeConnection { signature: Buffer, ): Promise { const relayMsg = new nodesPB.Relay(); - relayMsg.setSrcId(sourceNodeId); - relayMsg.setTargetId(targetNodeId); + relayMsg.setSrcId(sourceNodeId.toString()); + relayMsg.setTargetId(targetNodeId.toString()); relayMsg.setEgressAddress(egressAddress); relayMsg.setSignature(signature.toString()); await this.client.nodesHolePunchMessageSend(relayMsg); @@ -420,7 +420,7 @@ class NodeConnection { { claim: constructedIntermediaryClaim, privateKey: this.keyManager.getRootKeyPairPem().privateKey, - signeeNodeId: this.keyManager.getNodeId(), + signeeNodeId: nodesUtils.encodeNodeId(this.keyManager.getNodeId()), }, ); // Should never be reached, but just for type safety diff --git a/src/nodes/NodeGraph.ts b/src/nodes/NodeGraph.ts index 1784bf28d..f4e21016c 100644 --- a/src/nodes/NodeGraph.ts +++ b/src/nodes/NodeGraph.ts @@ -11,6 +11,7 @@ import { CreateDestroyStartStop, ready, } from '@matrixai/async-init/dist/CreateDestroyStartStop'; +import { IdInternal } from '@matrixai/id'; import * as nodesUtils from './utils'; import * as nodesErrors from './errors'; @@ -410,7 +411,7 @@ class NodeGraph { // 2. Re-add all the nodes from all buckets for (const b of buckets) { for (const n of Object.keys(b)) { - const nodeId = n as NodeId; + const nodeId: NodeId = IdInternal.fromString(n); const newIndex = this.getBucketIndex(nodeId); let expectedBucket = tempBuckets[newIndex]; // The following is more or less copied from setNodeOps @@ -472,7 +473,8 @@ class NodeGraph { // Iterate over all of the nodes in each bucket const distanceToNodes: Array = []; buckets.forEach(function (bucket) { - for (const nodeId of Object.keys(bucket) as Array) { + for (const nodeIdString of Object.keys(bucket)) { + const nodeId: NodeId = IdInternal.fromString(nodeIdString); // Compute the distance from the node, and add it to the array. distanceToNodes.push({ id: nodeId, @@ -559,7 +561,7 @@ class NodeGraph { if (contacted[nodeData.id]) { continue; } - if (nodeData.id === targetNodeId) { + if (nodeData.id.equals(targetNodeId)) { // FoundTarget = true; // Attempt to create a connection to the node. Will throw an error // (ErrorConnectionStart, from ConnectionForward) if the connection diff --git a/src/nodes/NodeManager.ts b/src/nodes/NodeManager.ts index 058fb4689..809a85a26 100644 --- a/src/nodes/NodeManager.ts +++ b/src/nodes/NodeManager.ts @@ -9,7 +9,6 @@ import type { NodeMapping, NodeData, NodeBucket, - NodeConnectionMap, } from '../nodes/types'; import type { SignedNotification } from '../notifications/types'; import type { Host, Hostname, Port } from '../network/types'; @@ -26,12 +25,30 @@ import { CreateDestroyStartStop, ready, } from '@matrixai/async-init/dist/CreateDestroyStartStop'; +import { IdInternal } from '@matrixai/id'; import NodeGraph from './NodeGraph'; import NodeConnection from './NodeConnection'; import * as nodesErrors from './errors'; import { utils as networkUtils, errors as networkErrors } from '../network'; import * as sigchainUtils from '../sigchain/utils'; import * as claimsUtils from '../claims/utils'; +import { utils as nodesUtils } from '../nodes'; + +/** + * Data structure to store all NodeConnections. If a connection to a node n does + * not exist, no entry for n will exist in the map. Alternatively, if a + * connection is currently being instantiated by some thread, an entry will + * exist in the map, but only with the lock (no connection object). Once a + * connection is instantiated, the entry in the map is updated to include the + * connection object. + */ +type NodeConnectionMap = Map< + string, + { + connection?: NodeConnection; + lock: MutexInterface; + } +>; interface NodeManager extends CreateDestroyStartStop {} @CreateDestroyStartStop( @@ -134,7 +151,7 @@ class NodeManager { }); // Add the seed nodes to the NodeGraph for (const id in this.seedNodes) { - const seedNodeId = id as NodeId; + const seedNodeId: NodeId = IdInternal.fromString(id); await this.nodeGraph.setNode(seedNodeId, this.seedNodes[seedNodeId]); } this.logger.info(`Started ${this.constructor.name}`); @@ -154,7 +171,7 @@ class NodeManager { // TODO: Potentially, we could instead re-start any connections in start // This assumes that after stopping the proxies, their connections are // also still valid on restart though. - this.connections.delete(targetNodeId); + this.connections.delete(targetNodeId.toString()); } await this.nodeGraph.stop(); this.logger.info(`Stopped ${this.constructor.name}`); @@ -298,10 +315,10 @@ class NodeManager { const claimId = c as ClaimIdString; const payload = verifiedChainData[claimId].payload; if (payload.data.type === 'node') { - const endNodeId = payload.data.node2; + const endNodeId = nodesUtils.decodeNodeId(payload.data.node2); let endPublicKey: PublicKeyPem; // If the claim points back to our own node, don't attempt to connect - if (endNodeId === this.getNodeId()) { + if (endNodeId.equals(this.getNodeId())) { endPublicKey = this.keyManager.getRootKeyPairPem().publicKey; // Otherwise, get the public key from the root cert chain (by connection) } else { @@ -339,8 +356,8 @@ class NodeManager { // 2. Create your intermediary claim const singlySignedClaim = await sigchain.createIntermediaryClaim({ type: 'node', - node1: this.getNodeId(), - node2: targetNodeId, + node1: nodesUtils.encodeNodeId(this.getNodeId()), + node2: nodesUtils.encodeNodeId(targetNodeId), }); // Receive back your verified doubly signed claim. const doublySignedClaim = await connection.claimNode(singlySignedClaim); @@ -385,11 +402,11 @@ class NodeManager { @ready(new nodesErrors.ErrorNodeManagerNotRunning()) public async relayHolePunchMessage(message: nodesPB.Relay): Promise { const conn = await this.getConnectionToNode( - message.getTargetId() as NodeId, + nodesUtils.decodeNodeId(message.getTargetId()), ); await conn.sendHolePunchMessage( - message.getSrcId() as NodeId, - message.getTargetId() as NodeId, + nodesUtils.decodeNodeId(message.getSrcId()), + nodesUtils.decodeNodeId(message.getTargetId()), message.getEgressAddress(), Buffer.from(message.getSignature()), ); @@ -419,7 +436,7 @@ class NodeManager { ): Promise { let connection: NodeConnection | undefined; let lock: MutexInterface; - let connAndLock = this.connections.get(targetNodeId); + let connAndLock = this.connections.get(targetNodeId.toString()); if (connAndLock != null) { ({ connection, lock } = connAndLock); if (connection != null) { @@ -441,7 +458,7 @@ class NodeManager { } else { lock = new Mutex(); connAndLock = { lock }; - this.connections.set(targetNodeId, connAndLock); + this.connections.set(targetNodeId.toString(), connAndLock); let release; try { release = await lock.acquire(); @@ -481,7 +498,7 @@ class NodeManager { logger: this.logger, }); // Add it to the map of active connections - this.connections.set(targetNodeId, { connection, lock }); + this.connections.set(targetNodeId.toString(), { connection, lock }); return connection; } @@ -507,7 +524,7 @@ class NodeManager { this.seedNodes = {}; try { for (const id in this.seedNodes) { - const seedNodeId = id as NodeId; + const seedNodeId: NodeId = IdInternal.fromString(id); try { connections.set( seedNodeId, @@ -605,9 +622,9 @@ class NodeManager { * Retrieves all the vaults for a peers node */ @ready(new nodesErrors.ErrorNodeManagerNotRunning()) - public async scanNodeVaults(nodeId: string): Promise> { + public async scanNodeVaults(nodeId: NodeId): Promise> { // Create a connection to another node - const connection = await this.getConnectionToNode(nodeId as NodeId); + const connection = await this.getConnectionToNode(nodeId); // Scan the vaults of the node over the connection return await connection.scanVaults(); } diff --git a/src/nodes/types.ts b/src/nodes/types.ts index a2c5654a0..76da3d83c 100644 --- a/src/nodes/types.ts +++ b/src/nodes/types.ts @@ -1,12 +1,11 @@ -import type NodeConnection from './NodeConnection'; -import type { MutexInterface } from 'async-mutex'; import type { Opaque } from '../types'; import type { Host, Hostname, Port } from '../network/types'; import type { Claim, ClaimId } from '../claims/types'; import type { ChainData } from '../sigchain/types'; -import type { IdString } from '../GenericIdTypes'; +import type { Id } from '@matrixai/id'; -type NodeId = Opaque<'NodeId', IdString>; +type NodeId = Opaque<'NodeId', Id>; +type NodeIdEncoded = Opaque<'NodeIdEncoded', string>; type NodeAddress = { host: Host | Hostname; @@ -39,7 +38,7 @@ type NodeClaim = Claim & { * chain: maps ClaimId (lexicographic integer of sequence number) -> Claim */ type NodeInfo = { - id: NodeId; + id: NodeIdEncoded; chain: ChainData; }; @@ -53,22 +52,6 @@ type NodeBucket = { }; }; -/** - * Data structure to store all NodeConnections. If a connection to a node n does - * not exist, no entry for n will exist in the map. Alternatively, if a - * connection is currently being instantiated by some thread, an entry will - * exist in the map, but only with the lock (no connection object). Once a - * connection is instantiated, the entry in the map is updated to include the - * connection object. - */ -type NodeConnectionMap = Map< - NodeId, - { - connection?: NodeConnection; - lock: MutexInterface; - } ->; - // Only 1 domain, so don't need a 'domain' value (like /gestalts/types.ts) type NodeGraphOp_ = { // Bucket index @@ -86,6 +69,7 @@ type NodeGraphOp = export type { NodeId, + NodeIdEncoded, NodeAddress, NodeMapping, NodeData, @@ -93,6 +77,5 @@ export type { NodeInfo, NodeBucketIndex, NodeBucket, - NodeConnectionMap, NodeGraphOp, }; diff --git a/src/nodes/utils.ts b/src/nodes/utils.ts index b0a5e9b98..67e4a9bd1 100644 --- a/src/nodes/utils.ts +++ b/src/nodes/utils.ts @@ -1,7 +1,7 @@ -import type { NodeData, NodeId } from './types'; +import type { NodeData, NodeId, NodeIdEncoded } from './types'; -import { ErrorInvalidNodeId } from './errors'; -import { fromMultibase, isIdString, makeIdString } from '../GenericIdTypes'; +import { IdInternal, utils as idUtils } from '@matrixai/id'; +import * as nodesErrors from './errors'; /** * Compute the distance between two nodes. @@ -9,8 +9,8 @@ import { fromMultibase, isIdString, makeIdString } from '../GenericIdTypes'; * where ^ = bitwise XOR operator */ function calculateDistance(nodeId1: NodeId, nodeId2: NodeId): BigInt { - const bufferId1 = nodeIdToU8(nodeId1); - const bufferId2 = nodeIdToU8(nodeId2); + const bufferId1: Buffer = nodeId1.toBuffer(); + const bufferId2: Buffer = nodeId2.toBuffer(); let distance = BigInt(0); let i = 0; const min = Math.min(bufferId1.length, bufferId2.length); @@ -54,27 +54,6 @@ function calculateBucketIndex( return bucketIndex; } -/** - * Validates that a provided node ID string is a valid node ID. - */ -function isNodeId(nodeId: string): nodeId is NodeId { - return isIdString(nodeId, 32); -} - -function makeNodeId(arg: any): NodeId { - return makeIdString(arg, 32, 'base32hex'); -} - -/** - * Node ID to an array of 8-bit unsigned ints - */ -function nodeIdToU8(id: string): Uint8Array { - // Converting from the multibase string to a buffer of hopefully 32 bytes. - const byteArray = fromMultibase(id); - if (byteArray == null) throw new ErrorInvalidNodeId(); - return byteArray; -} - /** * A sorting compareFn to sort an array of NodeData by increasing distance. */ @@ -88,11 +67,27 @@ function sortByDistance(a: NodeData, b: NodeData) { } } +function encodeNodeId(nodeId: NodeId): NodeIdEncoded { + return idUtils.toMultibase(nodeId, 'base32hex') as NodeIdEncoded; +} + +function decodeNodeId(nodeIdEncoded: NodeIdEncoded | string): NodeId { + const nodeId = IdInternal.fromMultibase(nodeIdEncoded); + if (nodeId == null) + throw new nodesErrors.ErrorInvalidNodeId( + `Was not a valid multibase: ${nodeIdEncoded}`, + ); + if (nodeId.length !== 32) + throw new nodesErrors.ErrorInvalidNodeId( + `Was not 32 bytes long: ${nodeIdEncoded}`, + ); + return nodeId; +} + export { calculateDistance, calculateBucketIndex, - isNodeId, - makeNodeId, - nodeIdToU8, sortByDistance, + encodeNodeId, + decodeNodeId, }; diff --git a/src/notifications/NotificationsManager.ts b/src/notifications/NotificationsManager.ts index 32c536ecd..1726ebdf6 100644 --- a/src/notifications/NotificationsManager.ts +++ b/src/notifications/NotificationsManager.ts @@ -20,6 +20,7 @@ import { utils as idUtils } from '@matrixai/id'; import * as notificationsUtils from './utils'; import * as notificationsErrors from './errors'; import { createNotificationIdGenerator } from './utils'; +import { utils as nodesUtils } from '../nodes'; const MESSAGE_COUNT_KEY = 'numMessages'; @@ -189,7 +190,7 @@ class NotificationsManager { public async sendNotification(nodeId: NodeId, data: NotificationData) { const notification = { data: data, - senderId: this.nodeManager.getNodeId(), + senderId: nodesUtils.encodeNodeId(this.nodeManager.getNodeId()), isRead: false, }; const signedNotification = await notificationsUtils.signNotification( @@ -205,7 +206,9 @@ class NotificationsManager { @ready(new notificationsErrors.ErrorNotificationsNotRunning()) public async receiveNotification(notification: Notification) { await this._transaction(async () => { - const nodePerms = await this.acl.getNodePerm(notification.senderId); + const nodePerms = await this.acl.getNodePerm( + nodesUtils.decodeNodeId(notification.senderId), + ); if (nodePerms === undefined) { throw new notificationsErrors.ErrorNotificationsPermissionsNotFound(); } @@ -293,7 +296,7 @@ class NotificationsManager { for (const notification of notifications) { if ( notification.data.type === 'GestaltInvite' && - notification.senderId === fromNode + nodesUtils.decodeNodeId(notification.senderId).equals(fromNode) ) { return notification; } diff --git a/src/notifications/types.ts b/src/notifications/types.ts index 3cb778899..428000a3a 100644 --- a/src/notifications/types.ts +++ b/src/notifications/types.ts @@ -1,5 +1,5 @@ import type { Opaque } from '../types'; -import type { NodeId } from '../nodes/types'; +import type { NodeIdEncoded } from '../nodes/types'; import type { VaultName, VaultActions } from '../vaults/types'; import type { Id, IdString } from '../GenericIdTypes'; @@ -25,7 +25,7 @@ type NotificationData = GestaltInvite | VaultShare | General; type Notification = { data: NotificationData; - senderId: NodeId; + senderId: NodeIdEncoded; isRead: boolean; }; diff --git a/src/sessions/SessionManager.ts b/src/sessions/SessionManager.ts index cfc4103e8..6ee4bbbc9 100644 --- a/src/sessions/SessionManager.ts +++ b/src/sessions/SessionManager.ts @@ -11,6 +11,7 @@ import { Mutex } from 'async-mutex'; import * as sessionsUtils from './utils'; import * as sessionsErrors from './errors'; import * as keysUtils from '../keys/utils'; +import { utils as nodesUtils } from '../nodes'; interface SessionManager extends CreateDestroyStartStop {} @CreateDestroyStartStop( @@ -154,8 +155,8 @@ class SessionManager { expiry: number | undefined = this.expiry, ): Promise { const payload = { - iss: this.keyManager.getNodeId(), - sub: this.keyManager.getNodeId(), + iss: nodesUtils.encodeNodeId(this.keyManager.getNodeId()), + sub: nodesUtils.encodeNodeId(this.keyManager.getNodeId()), }; const token = await sessionsUtils.createSessionToken( payload, diff --git a/src/sigchain/Sigchain.ts b/src/sigchain/Sigchain.ts index 220c8932c..6414902ab 100644 --- a/src/sigchain/Sigchain.ts +++ b/src/sigchain/Sigchain.ts @@ -7,9 +7,9 @@ import type { ClaimIntermediary, ClaimType, } from '../claims/types'; -import type { NodeId } from '../nodes/types'; import type { KeyManager } from '../keys'; import type { DB, DBLevel, DBOp } from '@matrixai/db'; +import type { NodeIdEncoded } from '../nodes/types'; import Logger from '@matrixai/logger'; import { Mutex } from 'async-mutex'; @@ -21,6 +21,7 @@ import { utils as idUtils } from '@matrixai/id'; import * as sigchainErrors from './errors'; import * as claimsUtils from '../claims/utils'; import { createClaimIdGenerator, makeClaimIdString } from '../sigchain/utils'; +import { utils as nodesUtils } from '../nodes'; interface Sigchain extends CreateDestroyStartStop {} @CreateDestroyStartStop( @@ -139,7 +140,7 @@ class Sigchain { // Creating the ID generator const latestId = await this.getLatestClaimId(); this.generateClaimId = createClaimIdGenerator( - this.keyManager.getNodeId(), + nodesUtils.encodeNodeId(this.keyManager.getNodeId()), latestId, ); this.logger.info(`Started ${this.constructor.name}`); @@ -200,7 +201,7 @@ class Sigchain { alg?: string; }): Promise { // Get kid from the claim data - let kid: NodeId; + let kid: NodeIdEncoded; if (data.type === 'node') { kid = data.node1; } else { diff --git a/src/sigchain/utils.ts b/src/sigchain/utils.ts index f97b1ec43..2d9276697 100644 --- a/src/sigchain/utils.ts +++ b/src/sigchain/utils.ts @@ -1,9 +1,9 @@ import type { PublicKeyPem } from '../keys/types'; import type { ChainData, ChainDataEncoded } from './types'; import type { ClaimId, ClaimIdString } from '../claims/types'; +import type { NodeIdEncoded } from '../nodes/types'; -import type { NodeId } from '../nodes/types'; -import { IdSortable } from '@matrixai/id'; +import { IdInternal, IdSortable } from '@matrixai/id'; import * as claimsUtils from '../claims/utils'; import { isIdString, isId, makeIdString, makeId } from '../GenericIdTypes'; @@ -45,10 +45,10 @@ function makeClaimIdString(arg) { return makeIdString(arg); } -function createClaimIdGenerator(nodeId: NodeId, lastClaimId?: ClaimId) { +function createClaimIdGenerator(nodeId: NodeIdEncoded, lastClaimId?: ClaimId) { const generator = new IdSortable({ lastId: lastClaimId, - nodeId: Buffer.from(nodeId), + nodeId: IdInternal.fromString(nodeId).toBuffer(), }); return () => makeClaimId(Buffer.from(generator.get())); } diff --git a/src/status/Status.ts b/src/status/Status.ts index 82e0d389c..b1f5e4e32 100644 --- a/src/status/Status.ts +++ b/src/status/Status.ts @@ -6,13 +6,16 @@ import type { StatusDead, } from './types'; import type { FileSystem, FileHandle } from '../types'; +import type { NodeId } from '../nodes/types'; import Logger from '@matrixai/logger'; import lock from 'fd-lock'; import { StartStop, ready } from '@matrixai/async-init/dist/StartStop'; +import { IdInternal } from '@matrixai/id'; import * as statusErrors from './errors'; import * as statusUtils from './utils'; import { sleep, poll } from '../utils'; import * as errors from '../errors'; +import { utils as nodesUtils } from '../nodes'; interface Status extends StartStop {} @StartStop() @@ -136,7 +139,7 @@ class Status { } let statusInfo; try { - statusInfo = JSON.parse(statusData); + statusInfo = JSON.parse(statusData, this.nodeIdReviver); } catch (e) { throw new statusErrors.ErrorStatusParse('JSON parsing failed'); } @@ -175,7 +178,7 @@ class Status { try { await statusFile.truncate(); await statusFile.write( - JSON.stringify(statusInfo, undefined, 2) + '\n', + JSON.stringify(statusInfo, this.nodeIdReplacer, 2) + '\n', 0, 'utf-8', ); @@ -228,7 +231,7 @@ class Status { } let statusInfo; try { - statusInfo = JSON.parse(statusData); + statusInfo = JSON.parse(statusData, this.nodeIdReviver); } catch (e) { throw new statusErrors.ErrorStatusParse('JSON parsing failed'); } @@ -249,7 +252,7 @@ class Status { try { await statusFile.truncate(); await statusFile.write( - JSON.stringify(statusInfo, undefined, 2) + '\n', + JSON.stringify(statusInfo, this.nodeIdReplacer, 2) + '\n', 0, 'utf-8', ); @@ -310,6 +313,17 @@ class Status { } return statusInfo; } + + private nodeIdReplacer = (key, value) => { + if (key === 'nodeId') + return nodesUtils.encodeNodeId(IdInternal.create(value.data)); + return value; + }; + + private nodeIdReviver = (key, value) => { + if (key === 'nodeId') return nodesUtils.decodeNodeId(value); + return value; + }; } export default Status; diff --git a/src/status/StatusSchema.json b/src/status/StatusSchema.json index 23c6e0b19..b4c2c4fab 100644 --- a/src/status/StatusSchema.json +++ b/src/status/StatusSchema.json @@ -28,7 +28,7 @@ "type": "object", "properties": { "pid": { "type": "number" }, - "nodeId": { "type": "string" }, + "nodeId": { "type": "object" }, "clientHost": { "type": "string" }, "clientPort": { "type": "number" }, "ingressHost": { "type": "string" }, diff --git a/src/vaults/VaultInternal.ts b/src/vaults/VaultInternal.ts index 6a900c11c..dcc80ae05 100644 --- a/src/vaults/VaultInternal.ts +++ b/src/vaults/VaultInternal.ts @@ -16,6 +16,7 @@ import { CreateDestroy, ready } from '@matrixai/async-init/dist/CreateDestroy'; import * as vaultsUtils from './utils'; import * as vaultsErrors from './errors'; import { makeVaultIdPretty } from './utils'; +import { utils as nodesUtils } from '../nodes'; const lastTag = 'last'; @@ -237,7 +238,7 @@ class VaultInternal { dir: this.baseDir, gitdir: this.gitDir, author: { - name: this.keyManager.getNodeId(), + name: nodesUtils.encodeNodeId(this.keyManager.getNodeId()), }, message: message.toString(), }); diff --git a/src/vaults/VaultManager.ts b/src/vaults/VaultManager.ts index dcd979393..61ed6eb2f 100644 --- a/src/vaults/VaultManager.ts +++ b/src/vaults/VaultManager.ts @@ -39,6 +39,7 @@ import * as utils from '../utils'; import * as gitUtils from '../git/utils'; import * as gitErrors from '../git/errors'; import * as gestaltErrors from '../gestalts/errors'; +import { utils as nodesUtils } from '../nodes'; interface VaultManager extends CreateDestroyStartStop {} @CreateDestroyStartStop( @@ -354,8 +355,16 @@ class VaultManager { const nodes = gestalt.nodes; for (const node in nodes) { await this.acl.setNodeAction(nodeId, 'scan'); - await this.acl.setVaultAction(vaultId, nodes[node].id, 'pull'); - await this.acl.setVaultAction(vaultId, nodes[node].id, 'clone'); + await this.acl.setVaultAction( + vaultId, + nodesUtils.decodeNodeId(nodes[node].id), + 'pull', + ); + await this.acl.setVaultAction( + vaultId, + nodesUtils.decodeNodeId(nodes[node].id), + 'clone', + ); } await this.notificationsManager.sendNotification(nodeId, { type: 'VaultShare', @@ -642,7 +651,7 @@ class VaultManager { ref: 'HEAD', singleBranch: true, author: { - name: pullNodeId, + name: nodesUtils.encodeNodeId(pullNodeId!), }, }); } catch (err) { diff --git a/src/vaults/utils.ts b/src/vaults/utils.ts index b3fb797a4..ab7e33568 100644 --- a/src/vaults/utils.ts +++ b/src/vaults/utils.ts @@ -21,6 +21,7 @@ import * as vaultsPB from '../proto/js/polykey/v1/vaults/vaults_pb'; import * as nodesPB from '../proto/js/polykey/v1/nodes/nodes_pb'; import * as keysUtils from '../keys/utils'; import { isIdString, isId, makeIdString, makeId } from '../GenericIdTypes'; +import { utils as nodesUtils } from '../nodes'; async function generateVaultKey(bits: number = 256): Promise { return (await keysUtils.generateKey(bits)) as VaultKey; @@ -232,7 +233,7 @@ async function requestVaultNames( nodeId: NodeId, ): Promise { const request = new nodesPB.Node(); - request.setNodeId(nodeId); + request.setNodeId(nodesUtils.encodeNodeId(nodeId)); const vaultList = client.vaultsScan(request); const data: string[] = []; for await (const vault of vaultList) { diff --git a/tests/PolykeyClient.test.ts b/tests/PolykeyClient.test.ts index c4c3a8ad3..2082c3cf5 100644 --- a/tests/PolykeyClient.test.ts +++ b/tests/PolykeyClient.test.ts @@ -55,7 +55,9 @@ describe('PolykeyClient', () => { fs, logger, }); - expect(pkClient.grpcClient.nodeId).toBe(pkAgent.keyManager.getNodeId()); + expect(pkClient.grpcClient.nodeId).toStrictEqual( + pkAgent.keyManager.getNodeId(), + ); expect(pkClient.grpcClient.host).toBe(pkAgent.grpcServerClient.host); expect(pkClient.grpcClient.port).toBe(pkAgent.grpcServerClient.port); expect(pkClient.grpcClient.secured).toBe(true); diff --git a/tests/acl/ACL.test.ts b/tests/acl/ACL.test.ts index c40e11e53..a6f8c46f6 100644 --- a/tests/acl/ACL.test.ts +++ b/tests/acl/ACL.test.ts @@ -11,11 +11,23 @@ import { utils as idUtils } from '@matrixai/id'; import { ACL, errors as aclErrors } from '@/acl'; import { utils as keysUtils } from '@/keys'; import { utils as vaultsUtils } from '@/vaults'; +import * as testUtils from '../utils'; describe(ACL.name, () => { const logger = new Logger(`${ACL.name} test`, LogLevel.WARN, [ new StreamHandler(), ]); + + // Node Ids + const nodeIdX = testUtils.generateRandomNodeId(); + const nodeIdY = testUtils.generateRandomNodeId(); + const nodeIdG1First = testUtils.generateRandomNodeId(); + const nodeIdG1Second = testUtils.generateRandomNodeId(); + const nodeIdG1Third = testUtils.generateRandomNodeId(); + const nodeIdG1Fourth = testUtils.generateRandomNodeId(); + const nodeIdG2First = testUtils.generateRandomNodeId(); + const nodeIdG2Second = testUtils.generateRandomNodeId(); + let dataDir: string; let db: DB; let vaultId1: VaultId; @@ -66,32 +78,32 @@ describe(ACL.name, () => { await expect(async () => { await acl.start(); }).rejects.toThrow(aclErrors.ErrorACLDestroyed); - await expect( - acl.sameNodePerm('x' as NodeId, 'y' as NodeId), - ).rejects.toThrow(aclErrors.ErrorACLNotRunning); + await expect(acl.sameNodePerm(nodeIdX, nodeIdY)).rejects.toThrow( + aclErrors.ErrorACLNotRunning, + ); await expect(acl.getNodePerms()).rejects.toThrow( aclErrors.ErrorACLNotRunning, ); await expect(acl.getVaultPerms()).rejects.toThrow( aclErrors.ErrorACLNotRunning, ); - await expect(acl.getNodePerm('x' as NodeId)).rejects.toThrow( + await expect(acl.getNodePerm(nodeIdX)).rejects.toThrow( aclErrors.ErrorACLNotRunning, ); await expect(acl.getVaultPerm(1 as VaultId)).rejects.toThrow( aclErrors.ErrorACLNotRunning, ); await expect( - acl.setNodeAction('x' as NodeId, {} as GestaltAction), + acl.setNodeAction(nodeIdX, {} as GestaltAction), ).rejects.toThrow(aclErrors.ErrorACLNotRunning); await expect( - acl.unsetNodeAction('x' as NodeId, {} as GestaltAction), + acl.unsetNodeAction(nodeIdX, {} as GestaltAction), ).rejects.toThrow(aclErrors.ErrorACLNotRunning); await expect( - acl.setVaultAction(1 as VaultId, 'x' as NodeId, {} as VaultAction), + acl.setVaultAction(1 as VaultId, nodeIdX, {} as VaultAction), ).rejects.toThrow(aclErrors.ErrorACLNotRunning); await expect( - acl.unsetVaultAction(1 as VaultId, 'x' as NodeId, {} as VaultAction), + acl.unsetVaultAction(1 as VaultId, nodeIdX, {} as VaultAction), ).rejects.toThrow(aclErrors.ErrorACLNotRunning); await expect(acl.setNodesPerm([], {} as Permission)).rejects.toThrow( aclErrors.ErrorACLNotRunning, @@ -99,25 +111,25 @@ describe(ACL.name, () => { await expect(acl.setNodesPermOps([], {} as Permission)).rejects.toThrow( aclErrors.ErrorACLNotRunning, ); - await expect( - acl.setNodePerm('x' as NodeId, {} as Permission), - ).rejects.toThrow(aclErrors.ErrorACLNotRunning); - await expect( - acl.setNodePermOps('x' as NodeId, {} as Permission), - ).rejects.toThrow(aclErrors.ErrorACLNotRunning); - await expect(acl.unsetNodePerm('x' as NodeId)).rejects.toThrow( + await expect(acl.setNodePerm(nodeIdX, {} as Permission)).rejects.toThrow( aclErrors.ErrorACLNotRunning, ); - await expect(acl.unsetNodePermOps('x' as NodeId)).rejects.toThrow( + await expect(acl.setNodePermOps(nodeIdX, {} as Permission)).rejects.toThrow( + aclErrors.ErrorACLNotRunning, + ); + await expect(acl.unsetNodePerm(nodeIdX)).rejects.toThrow( + aclErrors.ErrorACLNotRunning, + ); + await expect(acl.unsetNodePermOps(nodeIdX)).rejects.toThrow( aclErrors.ErrorACLNotRunning, ); await expect(acl.unsetVaultPerms(1 as VaultId)).rejects.toThrow( aclErrors.ErrorACLNotRunning, ); - await expect(acl.joinNodePerm('x' as NodeId, [])).rejects.toThrow( + await expect(acl.joinNodePerm(nodeIdX, [])).rejects.toThrow( aclErrors.ErrorACLNotRunning, ); - await expect(acl.joinNodePermOps('x' as NodeId, [])).rejects.toThrow( + await expect(acl.joinNodePermOps(nodeIdX, [])).rejects.toThrow( aclErrors.ErrorACLNotRunning, ); await expect(acl.joinVaultPerms(1 as VaultId, [])).rejects.toThrow( @@ -127,7 +139,7 @@ describe(ACL.name, () => { test('trust and untrust gestalts', async () => { const acl = await ACL.createACL({ db, logger }); // Gestalt 1 - await acl.setNodesPerm(['g1-first', 'g1-second'] as Array, { + await acl.setNodesPerm([nodeIdG1First, nodeIdG1Second] as Array, { gestalt: { notify: null, }, @@ -136,7 +148,7 @@ describe(ACL.name, () => { }, }); // Gestalt2 - await acl.setNodesPerm(['g2-first', 'g2-second'] as Array, { + await acl.setNodesPerm([nodeIdG2First, nodeIdG2Second] as Array, { gestalt: { notify: null, }, @@ -145,15 +157,15 @@ describe(ACL.name, () => { }, }); // Check g1 perm - const g1Perm1 = await acl.getNodePerm('g1-first' as NodeId); - const g1Perm2 = await acl.getNodePerm('g1-second' as NodeId); + const g1Perm1 = await acl.getNodePerm(nodeIdG1First); + const g1Perm2 = await acl.getNodePerm(nodeIdG1Second); expect(g1Perm1).toBeDefined(); expect(g1Perm1).toEqual(g1Perm2); expect(g1Perm1!.gestalt).toHaveProperty('notify'); expect(g1Perm1!.vaults[vaultId1]).toHaveProperty('pull'); // Check g2 perm - const g2Perm = await acl.getNodePerm('g2-first' as NodeId); - const g2Perm_ = await acl.getNodePerm('g2-second' as NodeId); + const g2Perm = await acl.getNodePerm(nodeIdG2First); + const g2Perm_ = await acl.getNodePerm(nodeIdG2Second); expect(g2Perm).toBeDefined(); expect(g2Perm).toEqual(g2Perm_); expect(g2Perm!.gestalt).toHaveProperty('notify'); @@ -163,44 +175,42 @@ describe(ACL.name, () => { ...g1Perm1!, gestalt: {}, }; - await acl.setNodePerm('g1-first' as NodeId, g1PermNew); + await acl.setNodePerm(nodeIdG1First, g1PermNew); // Check that g1-second also gets the same permission - const g1Perm3 = await acl.getNodePerm('g1-second' as NodeId); + const g1Perm3 = await acl.getNodePerm(nodeIdG1Second); expect(g1Perm3).toEqual(g1PermNew); const nodePerms = await acl.getNodePerms(); - expect(nodePerms).toEqual([ - { - 'g1-first': g1PermNew, - 'g1-second': g1PermNew, - }, - { - 'g2-first': g2Perm, - 'g2-second': g2Perm, - }, - ]); + expect(nodePerms).toContainEqual({ + [nodeIdG1First]: g1PermNew, + [nodeIdG1Second]: g1PermNew, + }); + expect(nodePerms).toContainEqual({ + [nodeIdG2First]: g2Perm, + [nodeIdG2Second]: g2Perm, + }); // Check that the permission object is identical // this should be a performance optimisation - expect(nodePerms[0]['g1-first']).toBe(nodePerms[0]['g1-second']); + expect(nodePerms[0][nodeIdG1First]).toBe(nodePerms[0][nodeIdG1Second]); await acl.stop(); }); test('setting and unsetting vault actions', async () => { const acl = await ACL.createACL({ db, logger }); // The node id must exist as a gestalt first await expect(() => - acl.setVaultAction(vaultId1, 'g1-1' as NodeId, 'pull'), + acl.setVaultAction(vaultId1, nodeIdG1First, 'pull'), ).rejects.toThrow(aclErrors.ErrorACLNodeIdMissing); - await acl.setNodesPerm(['g1-1'] as Array, { + await acl.setNodesPerm([nodeIdG1First] as Array, { gestalt: { notify: null, }, vaults: {}, }); let vaultPerm: Record; - await acl.setVaultAction(vaultId1, 'g1-1' as NodeId, 'pull'); + await acl.setVaultAction(vaultId1, nodeIdG1First, 'pull'); // Idempotent - await acl.setVaultAction(vaultId1, 'g1-1' as NodeId, 'pull'); + await acl.setVaultAction(vaultId1, nodeIdG1First, 'pull'); vaultPerm = await acl.getVaultPerm(vaultId1); - expect(vaultPerm['g1-1']).toEqual({ + expect(vaultPerm[nodeIdG1First]).toEqual({ gestalt: { notify: null, }, @@ -208,11 +218,11 @@ describe(ACL.name, () => { vault1xxxxxxxxxx: { pull: null }, }, }); - await acl.unsetVaultAction(vaultId1, 'g1-1' as NodeId, 'pull'); + await acl.unsetVaultAction(vaultId1, nodeIdG1First, 'pull'); // Idempotent - await acl.unsetVaultAction(vaultId1, 'g1-1' as NodeId, 'pull'); + await acl.unsetVaultAction(vaultId1, nodeIdG1First, 'pull'); vaultPerm = await acl.getVaultPerm(vaultId1); - expect(vaultPerm['g1-1']).toEqual({ + expect(vaultPerm[nodeIdG1First]).toEqual({ gestalt: { notify: null, }, @@ -220,15 +230,15 @@ describe(ACL.name, () => { vault1xxxxxxxxxx: {}, }, }); - await acl.setVaultAction(vaultId1, 'g1-1' as NodeId, 'pull'); - await acl.setVaultAction(vaultId1, 'g1-1' as NodeId, 'clone'); + await acl.setVaultAction(vaultId1, nodeIdG1First, 'pull'); + await acl.setVaultAction(vaultId1, nodeIdG1First, 'clone'); vaultPerm = await acl.getVaultPerm(vaultId1); - expect(vaultPerm['g1-1'].vaults[vaultId1]).toHaveProperty('pull'); - expect(vaultPerm['g1-1'].vaults[vaultId1]).toHaveProperty('clone'); + expect(vaultPerm[nodeIdG1First].vaults[vaultId1]).toHaveProperty('pull'); + expect(vaultPerm[nodeIdG1First].vaults[vaultId1]).toHaveProperty('clone'); const vaultPerms = await acl.getVaultPerms(); expect(vaultPerms).toEqual({ vault1xxxxxxxxxx: { - 'g1-1': { + [nodeIdG1First]: { gestalt: { notify: null, }, @@ -250,27 +260,30 @@ describe(ACL.name, () => { vault1xxxxxxxxxx: { pull: null }, }, }; - await acl.setNodesPerm(['g1-first', 'g1-second'] as Array, g1Perm); - await acl.joinNodePerm( - 'g1-second' as NodeId, - ['g1-third', 'g1-fourth'] as Array, + await acl.setNodesPerm( + [nodeIdG1First, nodeIdG1Second] as Array, + g1Perm, ); - const nodePerm = await acl.getNodePerm('g1-fourth' as NodeId); + await acl.joinNodePerm(nodeIdG1Second, [ + nodeIdG1Third, + nodeIdG1Fourth, + ] as Array); + const nodePerm = await acl.getNodePerm(nodeIdG1Fourth); expect(nodePerm).toEqual(g1Perm); const nodePerms = await acl.getNodePerms(); expect(nodePerms).toEqual([ { - 'g1-first': g1Perm, - 'g1-second': g1Perm, - 'g1-third': g1Perm, - 'g1-fourth': g1Perm, + [nodeIdG1First]: g1Perm, + [nodeIdG1Second]: g1Perm, + [nodeIdG1Third]: g1Perm, + [nodeIdG1Fourth]: g1Perm, }, ]); await acl.stop(); }); test('joining existing vault permissions', async () => { const acl = await ACL.createACL({ db, logger }); - await acl.setNodesPerm(['g1-1'] as Array, { + await acl.setNodesPerm([nodeIdG1First] as Array, { gestalt: { notify: null, }, @@ -278,19 +291,19 @@ describe(ACL.name, () => { vault1xxxxxxxxxx: { clone: null }, }, }); - await acl.setVaultAction(vaultId1, 'g1-1' as NodeId, 'pull'); + await acl.setVaultAction(vaultId1, nodeIdG1First, 'pull'); await acl.joinVaultPerms(vaultId1, [vaultId2, vaultId3]); const vaultPerm1 = await acl.getVaultPerm(vaultId1); const vaultPerm2 = await acl.getVaultPerm(vaultId2); const vaultPerm3 = await acl.getVaultPerm(vaultId3); expect(vaultPerm1).toEqual(vaultPerm2); expect(vaultPerm2).toEqual(vaultPerm3); - expect(vaultPerm1['g1-1'].vaults[vaultId1]).toHaveProperty('clone'); - expect(vaultPerm1['g1-1'].vaults[vaultId1]).toHaveProperty('pull'); + expect(vaultPerm1[nodeIdG1First].vaults[vaultId1]).toHaveProperty('clone'); + expect(vaultPerm1[nodeIdG1First].vaults[vaultId1]).toHaveProperty('pull'); const vaultPerms = await acl.getVaultPerms(); expect(vaultPerms).toMatchObject({ vault1xxxxxxxxxx: { - 'g1-1': { + [nodeIdG1First]: { gestalt: { notify: null, }, @@ -302,7 +315,7 @@ describe(ACL.name, () => { }, }, vault2xxxxxxxxxx: { - 'g1-1': { + [nodeIdG1First]: { gestalt: { notify: null, }, @@ -314,7 +327,7 @@ describe(ACL.name, () => { }, }, vault3xxxxxxxxxx: { - 'g1-1': { + [nodeIdG1First]: { gestalt: { notify: null, }, @@ -327,8 +340,12 @@ describe(ACL.name, () => { }, }); // Object identity for performance - expect(vaultPerms[vaultId1]['g1-1']).toEqual(vaultPerms[vaultId2]['g1-1']); - expect(vaultPerms[vaultId2]['g1-1']).toEqual(vaultPerms[vaultId3]['g1-1']); + expect(vaultPerms[vaultId1][nodeIdG1First]).toEqual( + vaultPerms[vaultId2][nodeIdG1First], + ); + expect(vaultPerms[vaultId2][nodeIdG1First]).toEqual( + vaultPerms[vaultId3][nodeIdG1First], + ); await acl.stop(); }); test('node removal', async () => { @@ -341,13 +358,16 @@ describe(ACL.name, () => { vault1xxxxxxxxxx: { pull: null }, }, }; - await acl.setNodesPerm(['g1-first', 'g1-second'] as Array, g1Perm); - await acl.unsetNodePerm('g1-first' as NodeId); - expect(await acl.getNodePerm('g1-first' as NodeId)).toBeUndefined(); - const g1Perm_ = await acl.getNodePerm('g1-second' as NodeId); + await acl.setNodesPerm( + [nodeIdG1First, nodeIdG1Second] as Array, + g1Perm, + ); + await acl.unsetNodePerm(nodeIdG1First); + expect(await acl.getNodePerm(nodeIdG1First)).toBeUndefined(); + const g1Perm_ = await acl.getNodePerm(nodeIdG1Second); expect(g1Perm_).toEqual(g1Perm); - await acl.unsetNodePerm('g1-second' as NodeId); - expect(await acl.getNodePerm('g1-second' as NodeId)).toBeUndefined(); + await acl.unsetNodePerm(nodeIdG1Second); + expect(await acl.getNodePerm(nodeIdG1Second)).toBeUndefined(); expect(await acl.getNodePerms()).toHaveLength(0); await acl.stop(); }); @@ -359,15 +379,18 @@ describe(ACL.name, () => { }, vaults: {}, }; - await acl.setNodesPerm(['g1-first', 'g1-second'] as Array, g1Perm); + await acl.setNodesPerm( + [nodeIdG1First, nodeIdG1Second] as Array, + g1Perm, + ); // V1 and v2 are pointing to the same gestalt // but using different node ids as the representative - await acl.setVaultAction(vaultId1, 'g1-first' as NodeId, 'clone'); - await acl.setVaultAction(vaultId2, 'g1-second' as NodeId, 'pull'); + await acl.setVaultAction(vaultId1, nodeIdG1First, 'clone'); + await acl.setVaultAction(vaultId2, nodeIdG1Second, 'pull'); let vaultPerm; vaultPerm = await acl.getVaultPerm(vaultId2); expect(vaultPerm).toEqual({ - 'g1-second': { + [nodeIdG1Second]: { gestalt: { notify: null, }, @@ -381,7 +404,7 @@ describe(ACL.name, () => { await acl.unsetVaultPerms(vaultId1); vaultPerm = await acl.getVaultPerm(vaultId2); expect(vaultPerm).toEqual({ - 'g1-second': { + [nodeIdG1Second]: { gestalt: { notify: null, }, @@ -396,89 +419,87 @@ describe(ACL.name, () => { const acl = await ACL.createACL({ db, logger }); const p1 = acl.getNodePerms(); const p2 = acl.transaction(async (acl) => { - await acl.setNodesPerm(['g1-first', 'g1-second'] as Array, { + await acl.setNodesPerm([nodeIdG1First, nodeIdG1Second] as Array, { gestalt: { notify: null, }, vaults: {}, }); - await acl.setNodesPerm(['g2-first', 'g2-second'] as Array, { + await acl.setNodesPerm([nodeIdG2First, nodeIdG2Second] as Array, { gestalt: { notify: null, }, vaults: {}, }); - await acl.setVaultAction(vaultId1, 'g1-first' as NodeId, 'pull'); - await acl.setVaultAction(vaultId1, 'g2-first' as NodeId, 'clone'); - await acl.joinNodePerm( - 'g1-second' as NodeId, - ['g1-third', 'g1-fourth'] as Array, - ); + await acl.setVaultAction(vaultId1, nodeIdG1First, 'pull'); + await acl.setVaultAction(vaultId1, nodeIdG2First, 'clone'); + await acl.joinNodePerm(nodeIdG1Second, [ + nodeIdG1Third, + nodeIdG1Fourth, + ] as Array); // V3 and v4 joins v1 // this means v3 and v4 now has g1 and g2 permissions await acl.joinVaultPerms(vaultId1, [vaultId3, vaultId4]); // Removing v3 await acl.unsetVaultPerms(vaultId3); // Removing g1-second - await acl.unsetNodePerm('g1-second' as NodeId); + await acl.unsetNodePerm(nodeIdG1Second); // Unsetting pull just for v1 for g1 - await acl.unsetVaultAction(vaultId1, 'g1-first' as NodeId, 'pull'); + await acl.unsetVaultAction(vaultId1, nodeIdG1First, 'pull'); return await acl.getNodePerms(); }); const p3 = acl.getNodePerms(); const results = await Promise.all([p1, p2, p3]); expect(results[0]).toEqual([]); - expect(results[1]).toEqual([ - { - 'g1-first': { - gestalt: { - notify: null, - }, - vaults: { - vault1xxxxxxxxxx: {}, - vault4xxxxxxxxxx: { pull: null }, - }, + expect(results[1]).toContainEqual({ + [nodeIdG1First]: { + gestalt: { + notify: null, }, - 'g1-fourth': { - gestalt: { - notify: null, - }, - vaults: { - vault1xxxxxxxxxx: {}, - vault4xxxxxxxxxx: { pull: null }, - }, + vaults: { + vault1xxxxxxxxxx: {}, + vault4xxxxxxxxxx: { pull: null }, }, - 'g1-third': { - gestalt: { - notify: null, - }, - vaults: { - vault1xxxxxxxxxx: {}, - vault4xxxxxxxxxx: { pull: null }, - }, + }, + [nodeIdG1Fourth]: { + gestalt: { + notify: null, + }, + vaults: { + vault1xxxxxxxxxx: {}, + vault4xxxxxxxxxx: { pull: null }, }, }, - { - 'g2-first': { - gestalt: { - notify: null, - }, - vaults: { - vault1xxxxxxxxxx: { clone: null }, - vault4xxxxxxxxxx: { clone: null }, - }, + [nodeIdG1Third]: { + gestalt: { + notify: null, }, - 'g2-second': { - gestalt: { - notify: null, - }, - vaults: { - vault1xxxxxxxxxx: { clone: null }, - vault4xxxxxxxxxx: { clone: null }, - }, + vaults: { + vault1xxxxxxxxxx: {}, + vault4xxxxxxxxxx: { pull: null }, }, }, - ]); + }); + expect(results[1]).toContainEqual({ + [nodeIdG2First]: { + gestalt: { + notify: null, + }, + vaults: { + vault1xxxxxxxxxx: { clone: null }, + vault4xxxxxxxxxx: { clone: null }, + }, + }, + [nodeIdG2Second]: { + gestalt: { + notify: null, + }, + vaults: { + vault1xxxxxxxxxx: { clone: null }, + vault4xxxxxxxxxx: { clone: null }, + }, + }, + }); // If p2 was executed ahead of p3 // then results[2] would equal results[1] // if p3 was executed ahead of p2 diff --git a/tests/agent/GRPCClientAgent.test.ts b/tests/agent/GRPCClientAgent.test.ts index a2a68c27c..a39ab0c4f 100644 --- a/tests/agent/GRPCClientAgent.test.ts +++ b/tests/agent/GRPCClientAgent.test.ts @@ -1,5 +1,5 @@ import type * as grpc from '@grpc/grpc-js'; -import type { NodeAddress, NodeInfo } from '@/nodes/types'; +import type { NodeAddress, NodeIdEncoded, NodeInfo } from '@/nodes/types'; import type { ClaimIdString, ClaimIntermediary } from '@/claims/types'; import type { Host, Port, TLSConfig } from '@/network/types'; import fs from 'fs'; @@ -19,11 +19,11 @@ import { errors as agentErrors } from '@/agent'; import { ForwardProxy, ReverseProxy } from '@/network'; import { NotificationsManager } from '@/notifications'; import { utils as claimsUtils, errors as claimsErrors } from '@/claims'; -import { makeNodeId } from '@/nodes/utils'; import * as keysUtils from '@/keys/utils'; import * as utilsPB from '@/proto/js/polykey/v1/utils/utils_pb'; import * as vaultsPB from '@/proto/js/polykey/v1/vaults/vaults_pb'; import * as nodesPB from '@/proto/js/polykey/v1/nodes/nodes_pb'; +import { utils as nodesUtils } from '@/nodes'; import * as testAgentUtils from './utils'; import * as testUtils from '../utils'; import TestNodeConnection from '../nodes/TestNodeConnection'; @@ -34,9 +34,10 @@ describe(GRPCClientAgent.name, () => { new StreamHandler(), ]); const node1: NodeInfo = { - id: makeNodeId('v359vgrgmqf1r5g4fvisiddjknjko6bmm4qv7646jr7fi9enbfuug'), + id: 'v359vgrgmqf1r5g4fvisiddjknjko6bmm4qv7646jr7fi9enbfuug' as NodeIdEncoded, chain: {}, }; + const nodeId1 = nodesUtils.decodeNodeId(node1.id); let mockedGenerateKeyPair: jest.SpyInstance; let mockedGenerateDeterministicKeyPair: jest.SpyInstance; beforeAll(async () => { @@ -197,7 +198,7 @@ describe(GRPCClientAgent.name, () => { // Await vaultManager.setVaultPermissions('12345' as NodeId, vault.vaultId); // await vaultManager.unsetVaultPermissions('12345' as NodeId, vault.vaultId); const vaultPermMessage = new vaultsPB.NodePermission(); - vaultPermMessage.setNodeId(node1.id); + vaultPermMessage.setNodeId(nodesUtils.encodeNodeId(nodeId1)); // VaultPermMessage.setVaultId(vault.vaultId); const response = await client.vaultsPermissionsCheck(vaultPermMessage); expect(response.getPermission()).toBeFalsy(); @@ -211,7 +212,7 @@ describe(GRPCClientAgent.name, () => { // const vault = await vaultManager.createVault('TestAgentVault' as VaultName); await gestaltGraph.setNode(node1); const nodeIdMessage = new nodesPB.Node(); - nodeIdMessage.setNodeId(node1.id); + nodeIdMessage.setNodeId(nodesUtils.encodeNodeId(nodeId1)); const response = client.vaultsScan(nodeIdMessage); const data: string[] = []; for await (const resp of response) { @@ -252,12 +253,14 @@ describe(GRPCClientAgent.name, () => { let xToYNodeConnection: TestNodeConnection; - const nodeIdX = makeNodeId( + const nodeIdX = nodesUtils.decodeNodeId( 'vrsc24a1er424epq77dtoveo93meij0pc8ig4uvs9jbeld78n9nl0', ); - const nodeIdY = makeNodeId( + const nodeIdXEncoded = nodesUtils.encodeNodeId(nodeIdX); + const nodeIdY = nodesUtils.decodeNodeId( 'vrcacp9vsb4ht25hds6s4lpp2abfaso0mptcfnh499n35vfcn2gkg', ); + const nodeIdYEncoded = nodesUtils.encodeNodeId(nodeIdY); beforeEach(async () => { yKeysPath = path.join(dataDir, 'keys-y'); @@ -280,7 +283,7 @@ describe(GRPCClientAgent.name, () => { logger: logger, }); // @ts-ignore - force push into the protected connections map - nodeManager.connections.set(nodeIdY, { + nodeManager.connections.set(nodeIdY.toString(), { connection: xToYNodeConnection, lock: new Mutex(), }); @@ -308,10 +311,10 @@ describe(GRPCClientAgent.name, () => { seq: 1, data: { type: 'node', - node1: nodeIdY, - node2: nodeIdX, + node1: nodeIdYEncoded, + node2: nodeIdXEncoded, }, - kid: nodeIdY, + kid: nodeIdYEncoded, }); const intermediary: ClaimIntermediary = { payload: claim.payload, @@ -364,7 +367,7 @@ describe(GRPCClientAgent.name, () => { const doublyResponse = await claimsUtils.signIntermediaryClaim({ claim: constructedIntermediary, privateKey: yKeyManager.getRootKeyPairPem().privateKey, - signeeNodeId: nodeIdY, + signeeNodeId: nodeIdYEncoded, }); const doublyMessage = claimsUtils.createCrossSignMessage({ doublySignedClaim: doublyResponse, diff --git a/tests/agent/utils.ts b/tests/agent/utils.ts index 29508ca1e..50a42fdeb 100644 --- a/tests/agent/utils.ts +++ b/tests/agent/utils.ts @@ -1,5 +1,4 @@ import type { Host, Port } from '@/network/types'; -import type { NodeId } from '@/nodes/types'; import type { IAgentServiceServer } from '@/proto/js/polykey/v1/agent_service_grpc_pb'; import type { KeyManager } from '@/keys'; @@ -15,6 +14,7 @@ import { GRPCClientAgent, AgentServiceService, } from '@/agent'; +import * as testUtils from '../utils'; async function openTestAgentServer({ keyManager, @@ -58,7 +58,7 @@ async function openTestAgentClient(port: number): Promise { new StreamHandler(), ]); const agentClient = await GRPCClientAgent.createGRPCClientAgent({ - nodeId: 'NODEID' as NodeId, + nodeId: testUtils.generateRandomNodeId(), host: '127.0.0.1' as Host, port: port as Port, logger: logger, diff --git a/tests/bin/agent/start.test.ts b/tests/bin/agent/start.test.ts index e9870b204..11efce264 100644 --- a/tests/bin/agent/start.test.ts +++ b/tests/bin/agent/start.test.ts @@ -562,7 +562,7 @@ describe('start', () => { const statusInfo2 = await status.waitFor('LIVE'); expect(statusInfo2.status).toBe('LIVE'); // Node Id hasn't changed - expect(statusInfo1.data.nodeId).toBe(statusInfo2.data.nodeId); + expect(statusInfo1.data.nodeId).toStrictEqual(statusInfo2.data.nodeId); agentProcess2.kill('SIGTERM'); await testBinUtils.processExit(agentProcess2); // Check that the password has changed @@ -578,7 +578,7 @@ describe('start', () => { const statusInfo3 = await status.waitFor('LIVE'); expect(statusInfo3.status).toBe('LIVE'); // Node ID hasn't changed - expect(statusInfo1.data.nodeId).toBe(statusInfo3.data.nodeId); + expect(statusInfo1.data.nodeId).toStrictEqual(statusInfo3.data.nodeId); agentProcess3.kill('SIGTERM'); await testBinUtils.processExit(agentProcess3); // Checks deterministic generation using the same recovery code @@ -608,7 +608,7 @@ describe('start', () => { const statusInfo4 = await status.waitFor('LIVE'); expect(statusInfo4.status).toBe('LIVE'); // Same Node ID as before - expect(statusInfo1.data.nodeId).toBe(statusInfo4.data.nodeId); + expect(statusInfo1.data.nodeId).toStrictEqual(statusInfo4.data.nodeId); agentProcess4.kill('SIGTERM'); await testBinUtils.processExit(agentProcess4); }, diff --git a/tests/bin/agent/status.test.ts b/tests/bin/agent/status.test.ts index 4181b1a16..644f6a932 100644 --- a/tests/bin/agent/status.test.ts +++ b/tests/bin/agent/status.test.ts @@ -5,6 +5,7 @@ import Logger, { LogLevel, StreamHandler } from '@matrixai/logger'; import { Status } from '@/status'; import * as binErrors from '@/bin/errors'; import config from '@/config'; +import { utils as nodesUtils } from '@/nodes'; import * as testBinUtils from '../utils'; import * as testUtils from '../../utils'; @@ -154,7 +155,7 @@ describe('status', () => { expect(JSON.parse(stdout)).toMatchObject({ status: 'LIVE', pid: expect.any(Number), - nodeId: statusInfo.data.nodeId, + nodeId: nodesUtils.encodeNodeId(statusInfo.data.nodeId), clientHost: statusInfo.data.clientHost, clientPort: statusInfo.data.clientPort, ingressHost: statusInfo.data.ingressHost, @@ -192,7 +193,7 @@ describe('status', () => { '--password-file', passwordPath, '--node-id', - statusInfo.data.nodeId, + nodesUtils.encodeNodeId(statusInfo.data.nodeId), '--client-host', statusInfo.data.clientHost, '--client-port', @@ -205,7 +206,7 @@ describe('status', () => { expect(JSON.parse(stdout)).toMatchObject({ status: 'LIVE', pid: expect.any(Number), - nodeId: statusInfo.data.nodeId, + nodeId: nodesUtils.encodeNodeId(statusInfo.data.nodeId), clientHost: statusInfo.data.clientHost, clientPort: statusInfo.data.clientPort, ingressHost: statusInfo.data.ingressHost, diff --git a/tests/bin/identities/identities.test.ts b/tests/bin/identities/identities.test.ts index 80507ed9d..2e6818b57 100644 --- a/tests/bin/identities/identities.test.ts +++ b/tests/bin/identities/identities.test.ts @@ -1,14 +1,14 @@ import type { IdentityId, IdentityInfo, ProviderId } from '@/identities/types'; -import type { NodeInfo } from '@/nodes/types'; +import type { NodeIdEncoded, NodeInfo } from '@/nodes/types'; import type { ClaimLinkIdentity, ClaimLinkNode } from '@/claims/types'; import os from 'os'; import path from 'path'; import fs from 'fs'; import Logger, { LogLevel, StreamHandler } from '@matrixai/logger'; import { PolykeyAgent } from '@'; -import { makeNodeId } from '@/nodes/utils'; import * as claimsUtils from '@/claims/utils'; import * as identitiesUtils from '@/identities/utils'; +import { utils as nodesUtils } from '@/nodes'; import * as testBinUtils from '../utils'; import * as testNodesUtils from '../../nodes/utils'; import TestProvider from '../../identities/TestProvider'; @@ -37,43 +37,43 @@ describe('CLI Identities', () => { let mockedBrowser: jest.SpyInstance; // Defining constants - const nodeId1 = makeNodeId( - 'vrsc24a1er424epq77dtoveo93meij0pc8ig4uvs9jbeld78n9nl0', - ); - const nodeId2 = makeNodeId( - 'vrcacp9vsb4ht25hds6s4lpp2abfaso0mptcfnh499n35vfcn2gkg', - ); - const nodeId3 = makeNodeId( - 'v359vgrgmqf1r5g4fvisiddjknjko6bmm4qv7646jr7fi9enbfuug', - ); - const nodeId4 = makeNodeId( - 'vm5guqfrrhlrsa70qpauen8jd0lmb0v6j8r8c94p34n738vlvu7vg', - ); - const dummyNode = makeNodeId( - 'vi3et1hrpv2m2lrplcm7cu913kr45v51cak54vm68anlbvuf83ra0', - ); + const nodeId1Encoded = + 'vrsc24a1er424epq77dtoveo93meij0pc8ig4uvs9jbeld78n9nl0' as NodeIdEncoded; + const nodeId1 = nodesUtils.decodeNodeId(nodeId1Encoded); + const nodeId2Encoded = + 'vrcacp9vsb4ht25hds6s4lpp2abfaso0mptcfnh499n35vfcn2gkg' as NodeIdEncoded; + const nodeId2 = nodesUtils.decodeNodeId(nodeId2Encoded); + const nodeId3Encoded = + 'v359vgrgmqf1r5g4fvisiddjknjko6bmm4qv7646jr7fi9enbfuug' as NodeIdEncoded; + // Const nodeId3 = nodesUtils.decodeNodeId(nodeId3Encoded); + const nodeId4Encoded = + 'vm5guqfrrhlrsa70qpauen8jd0lmb0v6j8r8c94p34n738vlvu7vg' as NodeIdEncoded; + // Const nodeId4 = nodesUtils.decodeNodeId(nodeId4Encoded); + const dummyNodeEncoded = + 'vi3et1hrpv2m2lrplcm7cu913kr45v51cak54vm68anlbvuf83ra0' as NodeIdEncoded; + // Const dummyNode = nodesUtils.decodeNodeId(dummyNodeEncoded); const logger = new Logger('pkStdio Test', LogLevel.WARN, [ new StreamHandler(), ]); const node1: NodeInfo = { - id: nodeId1, - chain: {}, - }; - const keynode: NodeInfo = { - id: nodeId2, + id: nodeId1Encoded, chain: {}, }; const node2: NodeInfo = { - id: nodeId3, + id: nodeId2Encoded, chain: {}, }; const node3: NodeInfo = { - id: nodeId4, + id: nodeId3Encoded, + chain: {}, + }; + const keynode: NodeInfo = { + id: nodeId4Encoded, chain: {}, }; const invaldNode: NodeInfo = { - id: dummyNode, + id: dummyNodeEncoded, chain: {}, }; const identity1: IdentityInfo = { @@ -113,7 +113,8 @@ describe('CLI Identities', () => { nodePath: nodePath, logger: logger, }); - keynode.id = polykeyAgent.nodeManager.getNodeId(); + + keynode.id = nodesUtils.encodeNodeId(polykeyAgent.nodeManager.getNodeId()); testProvider = new TestProvider(); polykeyAgent.identitiesManager.registerProvider(testProvider); @@ -157,7 +158,7 @@ describe('CLI Identities', () => { const result = await testBinUtils.pkStdio(commands, {}, dataDir); expect(result.exitCode).toBe(0); // Succeeds. const actions = await polykeyAgent.gestaltGraph.getGestaltActionsByNode( - node1.id, + nodeId1, ); const actionKeys = Object.keys(actions!); expect(actionKeys).toContain('notify'); @@ -167,7 +168,7 @@ describe('CLI Identities', () => { expect(result2.exitCode).toBe(0); // Succeeds. const actions2 = await polykeyAgent.gestaltGraph.getGestaltActionsByNode( - node1.id, + nodeId1, ); const actionKeys2 = Object.keys(actions2!); expect(actionKeys2).toContain('notify'); @@ -258,18 +259,15 @@ describe('CLI Identities', () => { describe('commandDisallowGestalts', () => { test('Should disallow permissions on Node.', async () => { // Setting permissions. - await polykeyAgent.gestaltGraph.setGestaltActionByNode( - node1.id, - 'notify', - ); - await polykeyAgent.gestaltGraph.setGestaltActionByNode(node1.id, 'scan'); + await polykeyAgent.gestaltGraph.setGestaltActionByNode(nodeId1, 'notify'); + await polykeyAgent.gestaltGraph.setGestaltActionByNode(nodeId1, 'scan'); const commands = genCommands(['disallow', node1.id, 'notify']); const result = await testBinUtils.pkStdio(commands, {}, dataDir); expect(result.exitCode).toBe(0); // Succeeds. const actions = await polykeyAgent.gestaltGraph.getGestaltActionsByNode( - node1.id, + nodeId1, ); const actionKeys = Object.keys(actions!); expect(actionKeys).toContain('scan'); @@ -342,11 +340,8 @@ describe('CLI Identities', () => { describe('commandPermissionsGestalts', () => { test('Should get permissions on Node.', async () => { // Setting permissions. - await polykeyAgent.gestaltGraph.setGestaltActionByNode( - node1.id, - 'notify', - ); - await polykeyAgent.gestaltGraph.setGestaltActionByNode(node1.id, 'scan'); + await polykeyAgent.gestaltGraph.setGestaltActionByNode(nodeId1, 'notify'); + await polykeyAgent.gestaltGraph.setGestaltActionByNode(nodeId1, 'scan'); const commands = genCommands(['permissions', node1.id]); const result = await testBinUtils.pkStdio(commands, {}, dataDir); @@ -386,7 +381,7 @@ describe('CLI Identities', () => { expect(result.exitCode).toBe(0); // Succeeds. const actions = await polykeyAgent.gestaltGraph.getGestaltActionsByNode( - node1.id, + nodeId1, ); const actionKeys = Object.keys(actions!); expect(actionKeys).toContain('notify'); @@ -435,18 +430,15 @@ describe('CLI Identities', () => { describe('commandUntrustGestalts', () => { test('Should unset trust on Node.', async () => { // Setting permissions. - await polykeyAgent.gestaltGraph.setGestaltActionByNode( - node1.id, - 'notify', - ); - await polykeyAgent.gestaltGraph.setGestaltActionByNode(node1.id, 'scan'); + await polykeyAgent.gestaltGraph.setGestaltActionByNode(nodeId1, 'notify'); + await polykeyAgent.gestaltGraph.setGestaltActionByNode(nodeId1, 'scan'); const commands = genCommands(['untrust', node1.id]); const result = await testBinUtils.pkStdio(commands, {}, dataDir); expect(result.exitCode).toBe(0); // Succeeds. const actions = await polykeyAgent.gestaltGraph.getGestaltActionsByNode( - node1.id, + nodeId1, ); const actionKeys = Object.keys(actions!); expect(actionKeys).toContain('scan'); @@ -568,15 +560,17 @@ describe('CLI Identities', () => { }); }); describe('commandGetGestalts', () => { + const nodeIdEncoded = node1.id; test('Should list gestalt by Node', async () => { - const commands = ['identities', 'get', '-np', nodePath, node1.id]; + const commands = ['identities', 'get', '-np', nodePath, nodeIdEncoded]; const result = await testBinUtils.pkStdio(commands, {}, dataDir); expect(result.exitCode).toBe(0); - expect(result.stdout).toContain(node1.id); + expect(result.stdout).toContain(nodeIdEncoded); expect(result.stdout).toContain(identity1.providerId); expect(result.stdout).toContain(identity1.identityId); }); test('Should list gestalt by Identity', async () => { + const nodeIdEncoded = node1.id; const commands = [ 'identities', 'get', @@ -586,19 +580,16 @@ describe('CLI Identities', () => { ]; const result = await testBinUtils.pkStdio(commands, {}, dataDir); expect(result.exitCode).toBe(0); - expect(result.stdout).toContain(node1.id); + expect(result.stdout).toContain(nodeIdEncoded); expect(result.stdout).toContain(identity1.providerId); expect(result.stdout).toContain(identity1.identityId); }); }); describe('commandListGestalts', () => { test('Should list gestalts with permissions.', async () => { - await polykeyAgent.gestaltGraph.setGestaltActionByNode( - node1.id, - 'notify', - ); - await polykeyAgent.gestaltGraph.setGestaltActionByNode(node1.id, 'scan'); - await polykeyAgent.gestaltGraph.setGestaltActionByNode(node2.id, 'scan'); + await polykeyAgent.gestaltGraph.setGestaltActionByNode(nodeId1, 'notify'); + await polykeyAgent.gestaltGraph.setGestaltActionByNode(nodeId1, 'scan'); + await polykeyAgent.gestaltGraph.setGestaltActionByNode(nodeId2, 'scan'); const commands = ['identities', 'list', '-np', nodePath]; const result = await testBinUtils.pkStdio(commands, {}, dataDir); @@ -689,13 +680,13 @@ describe('CLI Identities', () => { // Adding sigchain details. const claimBtoC: ClaimLinkNode = { type: 'node', - node1: nodeB.nodeManager.getNodeId(), - node2: nodeC.nodeManager.getNodeId(), + node1: nodesUtils.encodeNodeId(nodeB.nodeManager.getNodeId()), + node2: nodesUtils.encodeNodeId(nodeC.nodeManager.getNodeId()), }; const claimCtoB: ClaimLinkNode = { type: 'node', - node1: nodeC.nodeManager.getNodeId(), - node2: nodeB.nodeManager.getNodeId(), + node1: nodesUtils.encodeNodeId(nodeC.nodeManager.getNodeId()), + node2: nodesUtils.encodeNodeId(nodeB.nodeManager.getNodeId()), }; await nodeB.sigchain.addClaim(claimBtoC); await nodeB.sigchain.addClaim(claimCtoB); @@ -709,7 +700,7 @@ describe('CLI Identities', () => { const claimIdentToB: ClaimLinkIdentity = { type: 'identity', - node: nodeB.nodeManager.getNodeId(), + node: nodesUtils.encodeNodeId(nodeB.nodeManager.getNodeId()), provider: testProvider.id, identity: identityId, }; @@ -747,17 +738,22 @@ describe('CLI Identities', () => { 'discover', '-np', nodePath, - nodeB.nodeManager.getNodeId(), + nodesUtils.encodeNodeId(nodeB.nodeManager.getNodeId()), + '-vvvv', ]; - const result = await testBinUtils.pkStdio(commands, {}, dataDir); + const result = await testBinUtils.pkStdio(commands); expect(result.exitCode).toBe(0); // We expect to find a gestalt now. const gestalt = await polykeyAgent.gestaltGraph.getGestalts(); expect(gestalt.length).not.toBe(0); const gestaltString = JSON.stringify(gestalt); - expect(gestaltString).toContain(nodeB.nodeManager.getNodeId()); - expect(gestaltString).toContain(nodeC.nodeManager.getNodeId()); + expect(gestaltString).toContain( + nodesUtils.encodeNodeId(nodeB.nodeManager.getNodeId()), + ); + expect(gestaltString).toContain( + nodesUtils.encodeNodeId(nodeC.nodeManager.getNodeId()), + ); expect(gestaltString).toContain(identityId); // Unauthenticate identity await polykeyAgent.identitiesManager.delToken( @@ -785,8 +781,12 @@ describe('CLI Identities', () => { const gestalt = await polykeyAgent.gestaltGraph.getGestalts(); expect(gestalt.length).not.toBe(0); const gestaltString = JSON.stringify(gestalt); - expect(gestaltString).toContain(nodeB.nodeManager.getNodeId()); - expect(gestaltString).toContain(nodeC.nodeManager.getNodeId()); + expect(gestaltString).toContain( + nodesUtils.encodeNodeId(nodeB.nodeManager.getNodeId()), + ); + expect(gestaltString).toContain( + nodesUtils.encodeNodeId(nodeC.nodeManager.getNodeId()), + ); expect(gestaltString).toContain(identityId); // Unauthenticate identity await polykeyAgent.identitiesManager.delToken( diff --git a/tests/bin/keys/renew.test.ts b/tests/bin/keys/renew.test.ts index ad8a4ba6f..4336cc2f7 100644 --- a/tests/bin/keys/renew.test.ts +++ b/tests/bin/keys/renew.test.ts @@ -71,7 +71,7 @@ describe('renew', () => { expect(fwdTLSConfig1).toEqual(expectedTLSConfig1); expect(revTLSConfig1).toEqual(expectedTLSConfig1); expect(serverTLSConfig1).toEqual(expectedTLSConfig1); - expect(nodeId1).toBe(nodeIdStatus1); + expect(nodeId1.equals(nodeIdStatus1)).toBe(true); // Renew keypair const passPath = path.join(dataDir, 'passwordNew'); await fs.promises.writeFile(passPath, 'password-new'); @@ -104,7 +104,7 @@ describe('renew', () => { expect(rootKeyPair2.publicKey).not.toBe(rootKeyPair1.publicKey); expect(nodeId1).not.toBe(nodeId2); expect(nodeIdStatus1).not.toBe(nodeIdStatus2); - expect(nodeId2).toBe(nodeIdStatus2); + expect(nodeId2.equals(nodeIdStatus2)).toBe(true); // Revert side effects await fs.promises.writeFile(passPath, password); ({ exitCode } = await testBinUtils.pkStdio( diff --git a/tests/bin/keys/reset.test.ts b/tests/bin/keys/reset.test.ts index a643dea54..d5b18ae5e 100644 --- a/tests/bin/keys/reset.test.ts +++ b/tests/bin/keys/reset.test.ts @@ -71,7 +71,7 @@ describe('renew', () => { expect(fwdTLSConfig1).toEqual(expectedTLSConfig1); expect(revTLSConfig1).toEqual(expectedTLSConfig1); expect(serverTLSConfig1).toEqual(expectedTLSConfig1); - expect(nodeId1).toBe(nodeIdStatus1); + expect(nodeId1.equals(nodeIdStatus1)).toBe(true); // Renew keypair const passPath = path.join(dataDir, 'passwordNew'); await fs.promises.writeFile(passPath, 'password-new'); @@ -104,7 +104,7 @@ describe('renew', () => { expect(rootKeyPair2.publicKey).not.toBe(rootKeyPair1.publicKey); expect(nodeId1).not.toBe(nodeId2); expect(nodeIdStatus1).not.toBe(nodeIdStatus2); - expect(nodeId2).toBe(nodeIdStatus2); + expect(nodeId2.equals(nodeIdStatus2)).toBe(true); // Revert side effects await fs.promises.writeFile(passPath, password); ({ exitCode } = await testBinUtils.pkStdio( diff --git a/tests/bin/nodes/add.test.ts b/tests/bin/nodes/add.test.ts index b238c9479..e1feba991 100644 --- a/tests/bin/nodes/add.test.ts +++ b/tests/bin/nodes/add.test.ts @@ -3,9 +3,11 @@ import os from 'os'; import path from 'path'; import fs from 'fs'; import Logger, { LogLevel, StreamHandler } from '@matrixai/logger'; +import { IdInternal } from '@matrixai/id'; import PolykeyAgent from '@/PolykeyAgent'; import * as nodesUtils from '@/nodes/utils'; import * as testBinUtils from '../utils'; +import * as testUtils from '../../utils'; jest.mock('@/keys/utils', () => ({ ...jest.requireActual('@/keys/utils'), @@ -21,10 +23,8 @@ describe('add', () => { let passwordFile: string; let polykeyAgent: PolykeyAgent; - const validNodeId = nodesUtils.makeNodeId( - 'vrsc24a1er424epq77dtoveo93meij0pc8ig4uvs9jbeld78n9nl0', - ); - const invalidNodeId = 'INVALIDID' as NodeId; + const validNodeId = testUtils.generateRandomNodeId(); + const invalidNodeId = IdInternal.fromString('INVALIDID'); const validHost = '0.0.0.0'; const invalidHost = 'INVALIDHOST'; const port = 55555; @@ -69,7 +69,7 @@ describe('add', () => { test('add a node', async () => { const commands = genCommands([ 'add', - validNodeId, + nodesUtils.encodeNodeId(validNodeId), validHost, port.toString(), ]); @@ -87,7 +87,7 @@ describe('add', () => { async () => { const commands = genCommands([ 'add', - invalidNodeId, + nodesUtils.encodeNodeId(invalidNodeId), validHost, port.toString(), ]); @@ -102,7 +102,7 @@ describe('add', () => { async () => { const commands = genCommands([ 'add', - validNodeId, + nodesUtils.encodeNodeId(validNodeId), invalidHost, port.toString(), ]); diff --git a/tests/bin/nodes/claim.test.ts b/tests/bin/nodes/claim.test.ts index 67f20bc53..dd096e0ea 100644 --- a/tests/bin/nodes/claim.test.ts +++ b/tests/bin/nodes/claim.test.ts @@ -1,9 +1,10 @@ -import type { NodeId } from '@/nodes/types'; +import type { NodeId, NodeIdEncoded } from '@/nodes/types'; import os from 'os'; import path from 'path'; import fs from 'fs'; import Logger, { LogLevel, StreamHandler } from '@matrixai/logger'; import PolykeyAgent from '@/PolykeyAgent'; +import { utils as nodesUtils } from '@/nodes'; import * as testBinUtils from '../utils'; import * as testNodesUtils from '../../nodes/utils'; @@ -25,6 +26,7 @@ describe('claim', () => { let keynodeId: NodeId; let remoteOnlineNodeId: NodeId; + let remoteOnlineNodeIdEncoded: NodeIdEncoded; // Helper functions function genCommands(options: Array) { @@ -57,6 +59,7 @@ describe('claim', () => { logger, }); remoteOnlineNodeId = remoteOnline.nodeManager.getNodeId(); + remoteOnlineNodeIdEncoded = nodesUtils.encodeNodeId(remoteOnlineNodeId); await testNodesUtils.nodesConnect(polykeyAgent, remoteOnline); await remoteOnline.nodeManager.setNode(keynodeId, { @@ -106,11 +109,14 @@ describe('claim', () => { test( 'send a gestalt invite', async () => { - const commands = genCommands(['claim', remoteOnlineNodeId]); + const commands = genCommands([ + 'claim', + nodesUtils.encodeNodeId(remoteOnlineNodeId), + ]); const result = await testBinUtils.pkStdio(commands); expect(result.exitCode).toBe(0); // Succeeds. expect(result.stdout).toContain('Gestalt Invite'); - expect(result.stdout).toContain(remoteOnlineNodeId); + expect(result.stdout).toContain(remoteOnlineNodeIdEncoded); }, global.polykeyStartupTimeout * 4, ); @@ -121,23 +127,26 @@ describe('claim', () => { // Needs to be forced, as the local node has already received an invitation const commands = genCommands([ 'claim', - remoteOnlineNodeId, + nodesUtils.encodeNodeId(remoteOnlineNodeId), '--force-invite', ]); const result = await testBinUtils.pkStdio(commands, {}, dataDir); expect(result.exitCode).toBe(0); // Succeeds. expect(result.stdout).toContain('Gestalt Invite'); - expect(result.stdout).toContain(remoteOnlineNodeId); + expect(result.stdout).toContain(remoteOnlineNodeIdEncoded); }); test('claim the remote node', async () => { await remoteOnline.notificationsManager.sendNotification(keynodeId, { type: 'GestaltInvite', }); // Received an invitation, so will attempt to perform the claiming process - const commands = genCommands(['claim', remoteOnlineNodeId]); + const commands = genCommands([ + 'claim', + nodesUtils.encodeNodeId(remoteOnlineNodeId), + ]); const result = await testBinUtils.pkStdio(commands, {}, dataDir); expect(result.exitCode).toBe(0); // Succeeds. expect(result.stdout).toContain('cryptolink claim'); - expect(result.stdout).toContain(remoteOnlineNodeId); + expect(result.stdout).toContain(remoteOnlineNodeIdEncoded); }); }); diff --git a/tests/bin/nodes/find.test.ts b/tests/bin/nodes/find.test.ts index 7393a2fee..039cd7342 100644 --- a/tests/bin/nodes/find.test.ts +++ b/tests/bin/nodes/find.test.ts @@ -107,7 +107,10 @@ describe('find', () => { }); test('find an online node', async () => { - const commands = genCommands(['find', remoteOnlineNodeId]); + const commands = genCommands([ + 'find', + nodesUtils.encodeNodeId(remoteOnlineNodeId), + ]); const result = await testBinUtils.pkStdio(commands, {}, dataDir); expect(result.exitCode).toBe(0); expect(result.stdout).toContain('Found node at'); @@ -117,7 +120,7 @@ describe('find', () => { // Checking json format. const commands2 = genCommands([ 'find', - remoteOnlineNodeId, + nodesUtils.encodeNodeId(remoteOnlineNodeId), '--format', 'json', ]); @@ -132,10 +135,15 @@ describe('find', () => { expect(result2.stdout).toContain('host'); expect(result2.stdout).toContain('port'); expect(result2.stdout).toContain('id'); - expect(result2.stdout).toContain(remoteOnlineNodeId); + expect(result2.stdout).toContain( + nodesUtils.encodeNodeId(remoteOnlineNodeId), + ); }); test('find an offline node', async () => { - const commands = genCommands(['find', remoteOfflineNodeId]); + const commands = genCommands([ + 'find', + nodesUtils.encodeNodeId(remoteOfflineNodeId), + ]); const result = await testBinUtils.pkStdio(commands, {}, dataDir); expect(result.exitCode).toBe(0); expect(result.stdout).toContain('Found node at'); @@ -145,7 +153,7 @@ describe('find', () => { // Checking json format. const commands2 = genCommands([ 'find', - remoteOfflineNodeId, + nodesUtils.encodeNodeId(remoteOfflineNodeId), '--format', 'json', ]); @@ -160,23 +168,30 @@ describe('find', () => { expect(result2.stdout).toContain('host'); expect(result2.stdout).toContain('port'); expect(result2.stdout).toContain('id'); - expect(result2.stdout).toContain(remoteOfflineNodeId); + expect(result2.stdout).toContain( + nodesUtils.encodeNodeId(remoteOfflineNodeId), + ); }); test( 'fail to find an unknown node', async () => { - const unknownNodeId = nodesUtils.makeNodeId( + const unknownNodeId = nodesUtils.decodeNodeId( 'vrcacp9vsb4ht25hds6s4lpp2abfaso0mptcfnh499n35vfcn2gkg', ); - const commands = genCommands(['find', unknownNodeId]); + const commands = genCommands([ + 'find', + nodesUtils.encodeNodeId(unknownNodeId), + ]); const result = await testBinUtils.pkStdio(commands, {}, dataDir); expect(result.exitCode).toBe(1); - expect(result.stdout).toContain(`Failed to find node ${unknownNodeId}`); + expect(result.stdout).toContain( + `Failed to find node ${nodesUtils.encodeNodeId(unknownNodeId)}`, + ); // Checking json format. const commands2 = genCommands([ 'find', - unknownNodeId, + nodesUtils.encodeNodeId(unknownNodeId), '--format', 'json', ]); diff --git a/tests/bin/nodes/ping.test.ts b/tests/bin/nodes/ping.test.ts index 902d7e915..00a1262bf 100644 --- a/tests/bin/nodes/ping.test.ts +++ b/tests/bin/nodes/ping.test.ts @@ -37,6 +37,9 @@ describe('ping', () => { dataDir = await fs.promises.mkdtemp( path.join(os.tmpdir(), 'polykey-test-'), ); + rootDataDir = await fs.promises.mkdtemp( + path.join(os.tmpdir(), 'polykey-test-'), + ); nodePath = path.join(dataDir, 'keynode'); passwordFile = path.join(dataDir, 'passwordFile'); await fs.promises.writeFile(passwordFile, 'password'); @@ -95,7 +98,10 @@ describe('ping', () => { test( 'fail when pinging an offline node', async () => { - const commands = genCommands(['ping', remoteOfflineNodeId]); + const commands = genCommands([ + 'ping', + nodesUtils.encodeNodeId(remoteOfflineNodeId), + ]); const result = await testBinUtils.pkStdio(commands, {}, dataDir); expect(result.exitCode).toBe(1); // Should fail with no response. for automation purposes. expect(result.stdout).toContain('No response received'); @@ -103,7 +109,7 @@ describe('ping', () => { // Checking for json output const commands2 = genCommands([ 'ping', - remoteOfflineNodeId, + nodesUtils.encodeNodeId(remoteOfflineNodeId), '--format', 'json', ]); @@ -116,16 +122,24 @@ describe('ping', () => { test( 'fail if node cannot be found', async () => { - const fakeNodeId = nodesUtils.makeNodeId( + const fakeNodeId = nodesUtils.decodeNodeId( 'vrsc24a1er424epq77dtoveo93meij0pc8ig4uvs9jbeld78n9nl0', ); - const commands = genCommands(['ping', fakeNodeId]); - const result = await testBinUtils.pkStdio(commands, {}, dataDir); + const commands = genCommands([ + 'ping', + nodesUtils.encodeNodeId(fakeNodeId), + ]); + const result = await testBinUtils.pk(commands); expect(result.exitCode).not.toBe(0); // Should fail if node doesn't exist. expect(result.stdout).toContain('Failed to resolve node ID'); // Json format. - const commands2 = genCommands(['ping', fakeNodeId, '--format', 'json']); + const commands2 = genCommands([ + 'ping', + nodesUtils.encodeNodeId(fakeNodeId), + '--format', + 'json', + ]); const result2 = await testBinUtils.pkStdio(commands2, {}, dataDir); expect(result2.exitCode).not.toBe(0); // Should fail if node doesn't exist. expect(result2.stdout).toContain('success'); @@ -136,7 +150,10 @@ describe('ping', () => { global.failedConnectionTimeout * 2, ); test('succeed when pinging a live node', async () => { - const commands = genCommands(['ping', remoteOnlineNodeId]); + const commands = genCommands([ + 'ping', + nodesUtils.encodeNodeId(remoteOnlineNodeId), + ]); const result = await testBinUtils.pkStdio(commands, {}, dataDir); expect(result.exitCode).toBe(0); expect(result.stdout).toContain('Node is Active.'); @@ -144,7 +161,7 @@ describe('ping', () => { // Checking for Json output. const commands2 = genCommands([ 'ping', - remoteOnlineNodeId, + nodesUtils.encodeNodeId(remoteOnlineNodeId), '--format', 'json', ]); diff --git a/tests/bin/notifications/notifications.test.ts b/tests/bin/notifications/notifications.test.ts index 387767d08..b8fa99b9b 100644 --- a/tests/bin/notifications/notifications.test.ts +++ b/tests/bin/notifications/notifications.test.ts @@ -8,6 +8,7 @@ import Logger, { LogLevel, StreamHandler } from '@matrixai/logger'; import { utils as idUtils } from '@matrixai/id'; import PolykeyAgent from '@/PolykeyAgent'; import { makeVaultId } from '@/vaults/utils'; +import { utils as nodesUtils } from '@/nodes'; import * as testBinUtils from '../utils'; jest.mock('@/keys/utils', () => ({ @@ -106,7 +107,11 @@ describe('CLI Notifications', () => { }, vaults: {}, }); - const commands = genCommandsSender(['send', receiverNodeId, 'msg']); + const commands = genCommandsSender([ + 'send', + nodesUtils.encodeNodeId(receiverNodeId), + 'msg', + ]); const result = await testBinUtils.pkStdio(commands, {}, senderDataDir); expect(result.exitCode).toBe(0); // Succeeds const notifications = @@ -121,7 +126,11 @@ describe('CLI Notifications', () => { gestalt: {}, vaults: {}, }); - const commands = genCommandsSender(['send', receiverNodeId, 'msg']); + const commands = genCommandsSender([ + 'send', + nodesUtils.encodeNodeId(receiverNodeId), + 'msg', + ]); const result = await testBinUtils.pkStdio(commands, {}, senderDataDir); expect(result.exitCode).toBe(0); // Succeeds const notifications = @@ -139,17 +148,17 @@ describe('CLI Notifications', () => { }); const senderCommands1 = genCommandsSender([ 'send', - receiverNodeId, + nodesUtils.encodeNodeId(receiverNodeId), 'msg1', ]); const senderCommands2 = genCommandsSender([ 'send', - receiverNodeId, + nodesUtils.encodeNodeId(receiverNodeId), 'msg2', ]); const senderCommands3 = genCommandsSender([ 'send', - receiverNodeId, + nodesUtils.encodeNodeId(receiverNodeId), 'msg3', ]); await testBinUtils.pkStdio(senderCommands1, {}, senderDataDir); @@ -167,7 +176,7 @@ describe('CLI Notifications', () => { expect(result1.stdout).toContain('msg3'); const senderCommands4 = genCommandsSender([ 'send', - receiverNodeId, + nodesUtils.encodeNodeId(receiverNodeId), 'msg4', ]); await testBinUtils.pkStdio(senderCommands4, {}, senderDataDir); @@ -191,17 +200,17 @@ describe('CLI Notifications', () => { }); const senderCommands1 = genCommandsSender([ 'send', - receiverNodeId, + nodesUtils.encodeNodeId(receiverNodeId), 'msg1', ]); const senderCommands2 = genCommandsSender([ 'send', - receiverNodeId, + nodesUtils.encodeNodeId(receiverNodeId), 'msg2', ]); const senderCommands3 = genCommandsSender([ 'send', - receiverNodeId, + nodesUtils.encodeNodeId(receiverNodeId), 'msg3', ]); await testBinUtils.pkStdio(senderCommands1, {}, senderDataDir); @@ -211,7 +220,7 @@ describe('CLI Notifications', () => { await testBinUtils.pkStdio(receiverCommands1, {}, receiverDataDir); const senderCommands4 = genCommandsSender([ 'send', - receiverNodeId, + nodesUtils.encodeNodeId(receiverNodeId), 'msg4', ]); await testBinUtils.pkStdio(senderCommands4, {}, senderDataDir); @@ -236,17 +245,17 @@ describe('CLI Notifications', () => { }); const senderCommands1 = genCommandsSender([ 'send', - receiverNodeId, + nodesUtils.encodeNodeId(receiverNodeId), 'msg1', ]); const senderCommands2 = genCommandsSender([ 'send', - receiverNodeId, + nodesUtils.encodeNodeId(receiverNodeId), 'msg2', ]); const senderCommands3 = genCommandsSender([ 'send', - receiverNodeId, + nodesUtils.encodeNodeId(receiverNodeId), 'msg3', ]); await testBinUtils.pkStdio(senderCommands1, {}, senderDataDir); @@ -272,17 +281,17 @@ describe('CLI Notifications', () => { }); const senderCommands1 = genCommandsSender([ 'send', - receiverNodeId, + nodesUtils.encodeNodeId(receiverNodeId), 'msg1', ]); const senderCommands2 = genCommandsSender([ 'send', - receiverNodeId, + nodesUtils.encodeNodeId(receiverNodeId), 'msg2', ]); const senderCommands3 = genCommandsSender([ 'send', - receiverNodeId, + nodesUtils.encodeNodeId(receiverNodeId), 'msg3', ]); await testBinUtils.pkStdio(senderCommands1, {}, senderDataDir); @@ -344,7 +353,7 @@ describe('CLI Notifications', () => { }; const notificationData3: NotificationData = { type: 'VaultShare', - vaultId: makeVaultId(idUtils.fromString('vaultId')).toString(), + vaultId: makeVaultId(idUtils.fromString('vaultIdxxxxxxxxx')).toString(), vaultName: 'vaultName' as VaultName, actions: { clone: null, @@ -381,17 +390,17 @@ describe('CLI Notifications', () => { }); const senderCommands1 = genCommandsSender([ 'send', - receiverNodeId, + nodesUtils.encodeNodeId(receiverNodeId), 'msg1', ]); const senderCommands2 = genCommandsSender([ 'send', - receiverNodeId, + nodesUtils.encodeNodeId(receiverNodeId), 'msg2', ]); const senderCommands3 = genCommandsSender([ 'send', - receiverNodeId, + nodesUtils.encodeNodeId(receiverNodeId), 'msg3', ]); await testBinUtils.pkStdio(senderCommands1, {}, senderDataDir); diff --git a/tests/bin/vaults/vaults.test.ts b/tests/bin/vaults/vaults.test.ts index 86cadb604..fed187a05 100644 --- a/tests/bin/vaults/vaults.test.ts +++ b/tests/bin/vaults/vaults.test.ts @@ -1,12 +1,12 @@ -import type { NodeInfo } from '@/nodes/types'; +import type { NodeIdEncoded, NodeInfo } from '@/nodes/types'; import type { Vault, VaultName } from '@/vaults/types'; import os from 'os'; import path from 'path'; import fs from 'fs'; import Logger, { LogLevel, StreamHandler } from '@matrixai/logger'; import PolykeyAgent from '@/PolykeyAgent'; -import { makeNodeId } from '@/nodes/utils'; import { makeVaultIdPretty } from '@/vaults/utils'; +import { utils as nodesUtils } from '@/nodes'; import * as testBinUtils from '../utils'; jest.mock('@/keys/utils', () => ({ @@ -39,26 +39,26 @@ describe('CLI vaults', () => { let vaultName: VaultName; // Constants - const nodeId1 = makeNodeId( - 'vrsc24a1er424epq77dtoveo93meij0pc8ig4uvs9jbeld78n9nl0', - ); - const nodeId2 = makeNodeId( - 'vrcacp9vsb4ht25hds6s4lpp2abfaso0mptcfnh499n35vfcn2gkg', - ); - const nodeId3 = makeNodeId( - 'v359vgrgmqf1r5g4fvisiddjknjko6bmm4qv7646jr7fi9enbfuug', - ); + const nodeId1Encoded = + 'vrsc24a1er424epq77dtoveo93meij0pc8ig4uvs9jbeld78n9nl0' as NodeIdEncoded; + const nodeId1 = nodesUtils.decodeNodeId(nodeId1Encoded); + const nodeId2Encoded = + 'vrcacp9vsb4ht25hds6s4lpp2abfaso0mptcfnh499n35vfcn2gkg' as NodeIdEncoded; + // Const nodeId2 = nodesUtils.decodeNodeId(nodeId2Encoded); + const nodeId3Encoded = + 'v359vgrgmqf1r5g4fvisiddjknjko6bmm4qv7646jr7fi9enbfuug' as NodeIdEncoded; + // Const nodeId3 = nodesUtils.decodeNodeId(nodeId3Encoded); const node1: NodeInfo = { - id: nodeId1, + id: nodeId1Encoded, chain: {}, }; const node2: NodeInfo = { - id: nodeId2, + id: nodeId2Encoded, chain: {}, }; const node3: NodeInfo = { - id: nodeId3, + id: nodeId3Encoded, chain: {}, }; @@ -212,7 +212,14 @@ describe('CLI vaults', () => { }); describe.skip('commandSetPermsVault', () => { test('should share a vault', async () => { - command = ['vaults', 'share', '-np', dataDir, vaultName, node1.id]; + command = [ + 'vaults', + 'share', + '-np', + dataDir, + vaultName, + nodesUtils.encodeNodeId(nodeId1), + ]; await polykeyAgent.vaultManager.createVault(vaultName); const id = await polykeyAgent.vaultManager.getVaultId(vaultName); expect(id).toBeTruthy(); @@ -232,7 +239,14 @@ describe('CLI vaults', () => { }); describe.skip('commandUnsetPermsVault', () => { test('should un-share a vault', async () => { - command = ['vaults', 'unshare', '-np', dataDir, vaultName, node1.id]; + command = [ + 'vaults', + 'unshare', + '-np', + dataDir, + vaultName, + nodesUtils.encodeNodeId(nodeId1), + ]; // Creating vault. await polykeyAgent.vaultManager.createVault(vaultName); const id = await polykeyAgent.vaultManager.getVaultId(vaultName); @@ -295,7 +309,7 @@ describe('CLI vaults', () => { expect(id).toBeTruthy(); await targetPolykeyAgent.gestaltGraph.setNode({ - id: polykeyAgent.nodeManager.getNodeId(), + id: nodesUtils.encodeNodeId(polykeyAgent.nodeManager.getNodeId()), chain: {}, }); fail(); @@ -329,7 +343,7 @@ describe('CLI vaults', () => { '-np', dataDir, '-ni', - targetNodeId as string, + nodesUtils.encodeNodeId(targetNodeId), '-vi', makeVaultIdPretty(vault.vaultId), ]; @@ -371,7 +385,7 @@ describe('CLI vaults', () => { expect(id).toBeTruthy(); await targetPolykeyAgent.gestaltGraph.setNode({ - id: polykeyAgent.nodeManager.getNodeId(), + id: nodesUtils.encodeNodeId(polykeyAgent.nodeManager.getNodeId()), chain: {}, }); fail(); @@ -422,7 +436,7 @@ describe('CLI vaults', () => { '-vn', vaultName, '-ni', - targetNodeId, + nodesUtils.encodeNodeId(targetNodeId), ]; const result = await testBinUtils.pkStdio([...command]); @@ -496,7 +510,7 @@ describe('CLI vaults', () => { '-np', dataDir, '-ni', - targetNodeId as string, + nodesUtils.encodeNodeId(targetNodeId), ]; const result = await testBinUtils.pkStdio([...command]); expect(result.exitCode).toBe(0); diff --git a/tests/claims/utils.test.ts b/tests/claims/utils.test.ts index f00a32bfb..f7c6e6410 100644 --- a/tests/claims/utils.test.ts +++ b/tests/claims/utils.test.ts @@ -1,7 +1,6 @@ import type { GeneralJWSInput } from 'jose'; import type { PrivateKeyPem, PublicKeyPem } from '@/keys/types'; import type { IdentityId, ProviderId } from '@/identities/types'; -import type { NodeId } from '@/nodes/types'; import type { Claim } from '@/claims/types'; import { createPublicKey, createPrivateKey } from 'crypto'; import { generalVerify, GeneralSign } from 'jose'; @@ -9,10 +8,17 @@ import canonicalize from 'canonicalize'; import { sleep } from '@/utils'; import * as claimsUtils from '@/claims/utils'; import * as claimsErrors from '@/claims/errors'; -import * as keysUtils from '@/keys/utils'; +import { utils as keysUtils } from '@/keys'; +import { utils as nodesUtils } from '@/nodes'; import * as testUtils from '../utils'; describe('claims/utils', () => { + // Node Ids + const nodeId1 = testUtils.generateRandomNodeId(); + const nodeId1Encoded = nodesUtils.encodeNodeId(nodeId1); + const nodeId2 = testUtils.generateRandomNodeId(); + const nodeId2Encoded = nodesUtils.encodeNodeId(nodeId2); + let publicKey: PublicKeyPem; let privateKey: PrivateKeyPem; beforeAll(async () => { @@ -28,10 +34,10 @@ describe('claims/utils', () => { seq: 1, data: { type: 'node', - node1: 'node1' as NodeId, - node2: 'node2' as NodeId, + node1: nodeId1Encoded, + node2: nodeId2Encoded, }, - kid: 'node1' as NodeId, + kid: nodeId1Encoded, }); const identityClaim = await claimsUtils.createClaim({ privateKey, @@ -39,11 +45,11 @@ describe('claims/utils', () => { seq: 1, data: { type: 'identity', - node: 'node1' as NodeId, + node: nodeId1Encoded, provider: 'provider1' as ProviderId, identity: 'identity1' as IdentityId, }, - kid: 'node1' as NodeId, + kid: nodeId1Encoded, }); // Verify the claims with the module itself (to check the fields) @@ -52,7 +58,10 @@ describe('claims/utils', () => { const jwkPublicKey = createPublicKey(publicKey); const { payload: nodePayload, protectedHeader: nodeProtectedHeader } = await generalVerify(nodeClaim as GeneralJWSInput, jwkPublicKey); - expect(nodeProtectedHeader).toStrictEqual({ alg: 'RS256', kid: 'node1' }); + expect(nodeProtectedHeader).toStrictEqual({ + alg: 'RS256', + kid: nodeId1Encoded, + }); const textDecoder = new TextDecoder(); const decodedNodePayload = JSON.parse(textDecoder.decode(nodePayload)); expect(decodedNodePayload).toStrictEqual({ @@ -60,8 +69,8 @@ describe('claims/utils', () => { seq: 1, data: { type: 'node', - node1: 'node1' as NodeId, - node2: 'node2' as NodeId, + node1: nodeId1Encoded, + node2: nodeId2Encoded, }, iat: expect.any(Number), }); @@ -72,7 +81,7 @@ describe('claims/utils', () => { } = await generalVerify(identityClaim as GeneralJWSInput, jwkPublicKey); expect(identityProtectedHeader).toStrictEqual({ alg: 'RS256', - kid: 'node1', + kid: nodeId1Encoded, }); const decodedIdentityPayload = JSON.parse( textDecoder.decode(identityPayload), @@ -82,7 +91,7 @@ describe('claims/utils', () => { seq: 1, data: { type: 'identity', - node: 'node1' as NodeId, + node: nodeId1Encoded, provider: 'provider1' as ProviderId, identity: 'identity1' as IdentityId, }, @@ -96,10 +105,10 @@ describe('claims/utils', () => { seq: 1, data: { type: 'node', - node1: 'node1' as NodeId, - node2: 'node2' as NodeId, + node1: nodeId1Encoded, + node2: nodeId2Encoded, }, - kid: 'node1' as NodeId, + kid: nodeId1Encoded, }); const decoded = claimsUtils.decodeClaim(claim); expect(decoded).toStrictEqual({ @@ -108,8 +117,8 @@ describe('claims/utils', () => { seq: 1, data: { type: 'node', - node1: 'node1' as NodeId, - node2: 'node2' as NodeId, + node1: nodeId1Encoded, + node2: nodeId2Encoded, }, iat: expect.any(Number), }, @@ -119,12 +128,12 @@ describe('claims/utils', () => { // Check we only have 1 signature expect(Object.keys(decoded.signatures).length).toBe(1); // Check signature of 'node1' - expect(decoded.signatures['node1']).toBeDefined(); - const header = decoded.signatures['node1'].header; - const signature = decoded.signatures['node1'].signature; + expect(decoded.signatures[nodeId1Encoded]).toBeDefined(); + const header = decoded.signatures[nodeId1Encoded].header; + const signature = decoded.signatures[nodeId1Encoded].signature; expect(typeof signature).toBe('string'); expect(header.alg).toBe('RS256'); - expect(header.kid).toBe('node1'); + expect(header.kid).toBe(nodeId1Encoded); }); test('decodes a doubly signed node claim', async () => { const claim = await claimsUtils.createClaim({ @@ -133,16 +142,16 @@ describe('claims/utils', () => { seq: 1, data: { type: 'node', - node1: 'node1' as NodeId, - node2: 'node2' as NodeId, + node1: nodeId1Encoded, + node2: nodeId2Encoded, }, - kid: 'node1' as NodeId, + kid: nodeId1Encoded, }); // Add another signature to the claim const doublySignedClaim = await claimsUtils.signExistingClaim({ claim, privateKey, - kid: 'node2' as NodeId, + kid: nodeId2Encoded, }); const decoded = claimsUtils.decodeClaim(doublySignedClaim); expect(decoded).toStrictEqual({ @@ -151,8 +160,8 @@ describe('claims/utils', () => { seq: 1, data: { type: 'node', - node1: 'node1' as NodeId, - node2: 'node2' as NodeId, + node1: nodeId1Encoded, + node2: nodeId2Encoded, }, iat: expect.any(Number), }, @@ -162,19 +171,19 @@ describe('claims/utils', () => { // Check we have both signatures expect(Object.keys(decoded.signatures).length).toBe(2); // Check signature of 'node1' - expect(decoded.signatures['node1']).toBeDefined(); - const header1 = decoded.signatures['node1'].header; - const signature1 = decoded.signatures['node1'].signature; + expect(decoded.signatures[nodeId1Encoded]).toBeDefined(); + const header1 = decoded.signatures[nodeId1Encoded].header; + const signature1 = decoded.signatures[nodeId1Encoded].signature; expect(typeof signature1).toBe('string'); expect(header1.alg).toBe('RS256'); - expect(header1.kid).toBe('node1'); + expect(header1.kid).toBe(nodeId1Encoded); // Check signature of 'node2' - expect(decoded.signatures['node2']).toBeDefined(); - const header2 = decoded.signatures['node2'].header; - const signature2 = decoded.signatures['node2'].signature; + expect(decoded.signatures[nodeId2Encoded]).toBeDefined(); + const header2 = decoded.signatures[nodeId2Encoded].header; + const signature2 = decoded.signatures[nodeId2Encoded].signature; expect(typeof signature2).toBe('string'); expect(header2.alg).toBe('RS256'); - expect(header2.kid).toBe('node2'); + expect(header2.kid).toBe(nodeId2Encoded); }); test('decodes an identity claim', async () => { const claim = await claimsUtils.createClaim({ @@ -183,11 +192,11 @@ describe('claims/utils', () => { seq: 1, data: { type: 'identity', - node: 'node1' as NodeId, + node: nodeId1Encoded, provider: 'provider1' as ProviderId, identity: 'identity1' as IdentityId, }, - kid: 'node1' as NodeId, + kid: nodeId1Encoded, }); const decoded = claimsUtils.decodeClaim(claim); expect(decoded).toStrictEqual({ @@ -196,7 +205,7 @@ describe('claims/utils', () => { seq: 1, data: { type: 'identity', - node: 'node1' as NodeId, + node: nodeId1Encoded, provider: 'provider1' as ProviderId, identity: 'identity1' as IdentityId, }, @@ -208,12 +217,12 @@ describe('claims/utils', () => { // Check we only have 1 signature expect(Object.keys(decoded.signatures).length).toBe(1); // Check signature of 'node1' - expect(decoded.signatures['node1']).toBeDefined(); - const header = decoded.signatures['node1'].header; - const signature = decoded.signatures['node1'].signature; + expect(decoded.signatures[nodeId1Encoded]).toBeDefined(); + const header = decoded.signatures[nodeId1Encoded].header; + const signature = decoded.signatures[nodeId1Encoded].signature; expect(typeof signature).toBe('string'); expect(header.alg).toBe('RS256'); - expect(header.kid).toBe('node1'); + expect(header.kid).toBe(nodeId1Encoded); }); test('fails to decode an invalid claim', async () => { const payload = { @@ -224,9 +233,10 @@ describe('claims/utils', () => { const canonicalizedPayload = canonicalize(payload); const byteEncoder = new TextEncoder(); const claim = new GeneralSign(byteEncoder.encode(canonicalizedPayload)); - claim - .addSignature(createPrivateKey(privateKey)) - .setProtectedHeader({ alg: 'RS256', kid: 'node1' as NodeId }); + claim.addSignature(createPrivateKey(privateKey)).setProtectedHeader({ + alg: 'RS256', + kid: nodeId1Encoded, + }); const signedClaim = await claim.sign(); expect(() => claimsUtils.decodeClaim(signedClaim)).toThrow( claimsErrors.ErrorClaimValidationFailed, @@ -239,10 +249,10 @@ describe('claims/utils', () => { seq: 1, data: { type: 'node', - node1: 'node1' as NodeId, - node2: 'node2' as NodeId, + node1: nodeId1Encoded, + node2: nodeId2Encoded, }, - kid: 'node1' as NodeId, + kid: nodeId1Encoded, }); expect(claim.signatures[0].protected).toBeDefined(); const decodedHeader = claimsUtils.decodeClaimHeader( @@ -250,7 +260,7 @@ describe('claims/utils', () => { ); expect(decodedHeader).toStrictEqual({ alg: 'RS256', - kid: 'node1' as NodeId, + kid: nodeId1Encoded, }); }); test('re-encodes a claim', async () => { @@ -260,10 +270,10 @@ describe('claims/utils', () => { seq: 1, data: { type: 'node', - node1: 'node1' as NodeId, - node2: 'node2' as NodeId, + node1: nodeId1Encoded, + node2: nodeId2Encoded, }, - kid: 'node1' as NodeId, + kid: nodeId1Encoded, }); const decodedClaim = claimsUtils.decodeClaim(claim); const reEncodedClaim = await claimsUtils.encodeClaim(decodedClaim); @@ -288,12 +298,15 @@ describe('claims/utils', () => { seq: 1, data: { type: 'node', - node1: 'node1' as NodeId, - node2: 'node2' as NodeId, + node1: nodeId1Encoded, + node2: nodeId2Encoded, }, iat: expect.any(Number), }); - expect(protectedHeader).toStrictEqual({ alg: 'RS256', kid: 'node1' }); + expect(protectedHeader).toStrictEqual({ + alg: 'RS256', + kid: nodeId1Encoded, + }); // TODO: Check when using multiple signatures // Order of signatures array (probably) doesn't matter @@ -305,10 +318,10 @@ describe('claims/utils', () => { seq: 1, data: { type: 'node', - node1: 'node1' as NodeId, - node2: 'node2' as NodeId, + node1: nodeId1Encoded, + node2: nodeId2Encoded, }, - kid: 'node1' as NodeId, + kid: nodeId1Encoded, }); expect(await claimsUtils.verifyClaimSignature(claim, publicKey)).toBe(true); @@ -328,10 +341,10 @@ describe('claims/utils', () => { seq: 1, data: { type: 'node', - node1: 'node1' as NodeId, - node2: 'node2' as NodeId, + node1: nodeId1Encoded, + node2: nodeId2Encoded, }, - kid: 'node1' as NodeId, + kid: nodeId1Encoded, }); const hash1 = claimsUtils.hashClaim(claim1); expect(claimsUtils.verifyHashOfClaim(claim1, hash1)).toBe(true); @@ -345,10 +358,10 @@ describe('claims/utils', () => { seq: 1, data: { type: 'node', - node1: 'node1' as NodeId, - node2: 'node2' as NodeId, + node1: nodeId1Encoded, + node2: nodeId2Encoded, }, - kid: 'node1' as NodeId, + kid: nodeId1Encoded, }); const hash2 = claimsUtils.hashClaim(claim2); expect(claimsUtils.verifyHashOfClaim(claim2, hash2)).toBe(true); @@ -363,17 +376,17 @@ describe('claims/utils', () => { seq: 1, data: { type: 'node', - node1: 'node1' as NodeId, - node2: 'node2' as NodeId, + node1: nodeId1Encoded, + node2: nodeId2Encoded, }, iat: Date.now(), // Timestamp (initialised at JWS field) }, signatures: { - node1: { + [nodeId1Encoded]: { signature: 'signature', header: { alg: 'RS256', - kid: 'node1' as NodeId, + kid: nodeId1Encoded, }, }, }, // Signee node ID -> claim signature @@ -388,24 +401,24 @@ describe('claims/utils', () => { seq: 1, data: { type: 'node', - node1: 'node1' as NodeId, - node2: 'node2' as NodeId, + node1: nodeId1Encoded, + node2: nodeId2Encoded, }, iat: Date.now(), // Timestamp (initialised at JWS field) }, signatures: { - node1: { + [nodeId1Encoded]: { signature: 'signature', header: { alg: 'RS256', - kid: 'node1' as NodeId, + kid: nodeId1Encoded, }, }, - node2: { + [nodeId2Encoded]: { signature: 'signature', header: { alg: 'RS256', - kid: 'node2' as NodeId, + kid: nodeId2Encoded, }, }, }, // Signee node ID -> claim signature @@ -420,18 +433,18 @@ describe('claims/utils', () => { seq: 3, data: { type: 'identity', - node: 'node1' as NodeId, + node: nodeId1Encoded, identity: 'identity1' as IdentityId, provider: 'provider1' as ProviderId, }, iat: Date.now(), }, signatures: { - node1: { + [nodeId1Encoded]: { signature: 'signature', header: { alg: 'RS256', - kid: 'node1' as NodeId, + kid: nodeId1Encoded, }, }, }, @@ -447,8 +460,8 @@ describe('claims/utils', () => { seq: 1, data: { type: 'node', - node1: 'node1' as NodeId, - node2: 'node2' as NodeId, + node1: nodeId1Encoded, + node2: nodeId2Encoded, }, iat: Date.now(), // Timestamp (initialised at JWS field) }, @@ -457,7 +470,7 @@ describe('claims/utils', () => { signature: 'signature', header: { alg: 'RS256', - kid: 'node1', + kid: nodeId1Encoded, }, }, }, // Signee node ID -> claim signature @@ -481,12 +494,12 @@ describe('claims/utils', () => { expect(() => claimsUtils.validateSinglySignedNodeClaim(claim)).toThrow( claimsErrors.ErrorSinglySignedClaimValidationFailed, ); - claim.payload.data.node1 = 'node1'; + claim.payload.data.node1 = nodeId1Encoded; claim.payload.data.node2 = 2; expect(() => claimsUtils.validateSinglySignedNodeClaim(claim)).toThrow( claimsErrors.ErrorSinglySignedClaimValidationFailed, ); - claim.payload.data.node2 = 'node2'; + claim.payload.data.node2 = nodeId2Encoded; claim.payload.iat = 'invalid'; expect(() => claimsUtils.validateSinglySignedNodeClaim(claim)).toThrow( claimsErrors.ErrorSinglySignedClaimValidationFailed, @@ -502,14 +515,14 @@ describe('claims/utils', () => { signature: 'signature', header: { alg: 'RS256', - kid: 'node1', + kid: nodeId1Encoded, }, }, node2: { signature: 'signature', header: { alg: 'RS256', - kid: 'node2', + kid: nodeId2Encoded, }, }, }; @@ -531,8 +544,8 @@ describe('claims/utils', () => { seq: 1, data: { type: 'node', - node1: 'node1' as NodeId, - node2: 'node2' as NodeId, + node1: nodeId1Encoded, + node2: nodeId2Encoded, }, iat: Date.now(), // Timestamp (initialised at JWS field) }, @@ -541,14 +554,14 @@ describe('claims/utils', () => { signature: 'signature', header: { alg: 'RS256', - kid: 'node1', + kid: nodeId1Encoded, }, }, node2: { signature: 'signature', header: { alg: 'RS256', - kid: 'node2', + kid: nodeId2Encoded, }, }, }, // Signee node ID -> claim signature @@ -572,12 +585,12 @@ describe('claims/utils', () => { expect(() => claimsUtils.validateDoublySignedNodeClaim(claim)).toThrow( claimsErrors.ErrorDoublySignedClaimValidationFailed, ); - claim.payload.data.node1 = 'node1'; + claim.payload.data.node1 = nodeId1Encoded; claim.payload.data.node2 = 2; expect(() => claimsUtils.validateDoublySignedNodeClaim(claim)).toThrow( claimsErrors.ErrorDoublySignedClaimValidationFailed, ); - claim.payload.data.node2 = 'node2'; + claim.payload.data.node2 = nodeId2Encoded; claim.payload.iat = 'invalid'; expect(() => claimsUtils.validateDoublySignedNodeClaim(claim)).toThrow( claimsErrors.ErrorDoublySignedClaimValidationFailed, @@ -588,7 +601,7 @@ describe('claims/utils', () => { signature: 'signature', header: { alg: 'RS256', - kid: 'node1', + kid: nodeId1Encoded, }, }, }; @@ -601,14 +614,14 @@ describe('claims/utils', () => { signature: 'signature', header: { alg: 'RS256', - kid: 'node1', + kid: nodeId1Encoded, }, }, node2: { signature: 'signature', header: { alg: 'RS256', - kid: 'node2', + kid: nodeId2Encoded, }, }, node3: { @@ -637,7 +650,7 @@ describe('claims/utils', () => { seq: 1, data: { type: 'identity', - node: 'node1' as NodeId, + node: nodeId1Encoded, identity: 'identity1' as IdentityId, provider: 'provider1' as ProviderId, }, @@ -648,7 +661,7 @@ describe('claims/utils', () => { signature: 'signature', header: { alg: 'RS256', - kid: 'node1', + kid: nodeId1Encoded, }, }, }, @@ -672,7 +685,7 @@ describe('claims/utils', () => { expect(() => claimsUtils.validateIdentityClaim(claim)).toThrow( claimsErrors.ErrorSinglySignedClaimValidationFailed, ); - claim.payload.data.node = 'node1'; + claim.payload.data.node = nodeId1Encoded; claim.payload.data.identity = 2; expect(() => claimsUtils.validateIdentityClaim(claim)).toThrow( claimsErrors.ErrorSinglySignedClaimValidationFailed, @@ -698,14 +711,14 @@ describe('claims/utils', () => { signature: 'signature', header: { alg: 'RS256', - kid: 'node1', + kid: nodeId1Encoded, }, }, node2: { signature: 'signature', header: { alg: 'RS256', - kid: 'node2', + kid: nodeId2Encoded, }, }, }; @@ -717,7 +730,7 @@ describe('claims/utils', () => { signature: 'signature', header: { alg: 'RS256', - kid: 'node1', + kid: nodeId1Encoded, }, }, }; diff --git a/tests/client/GRPCClientClient.test.ts b/tests/client/GRPCClientClient.test.ts index 1bd989c18..4db264524 100644 --- a/tests/client/GRPCClientClient.test.ts +++ b/tests/client/GRPCClientClient.test.ts @@ -14,6 +14,7 @@ import { errors as clientErrors } from '@/client'; import config from '@/config'; import * as binProcessors from '@/bin/utils/processors'; import * as utilsPB from '@/proto/js/polykey/v1/utils/utils_pb'; +import { utils as nodesUtils } from '@/nodes'; import * as testClientUtils from './utils'; import * as testUtils from '../utils'; @@ -112,7 +113,9 @@ describe(GRPCClientClient.name, () => { const emptyMessage = new utilsPB.EmptyMessage(); const response = await client.agentStatus(emptyMessage, meta); expect(typeof response.getPid()).toBe('number'); - expect(response.getNodeId()).toBe(statusInfo.data.nodeId); + expect(response.getNodeId()).toBe( + nodesUtils.encodeNodeId(statusInfo.data.nodeId), + ); expect(response.getClientHost()).toBe(statusInfo.data.clientHost); expect(response.getClientPort()).toBe(statusInfo.data.clientPort); expect(response.getIngressHost()).toBe(statusInfo.data.ingressHost); diff --git a/tests/client/rpcGestalts.test.ts b/tests/client/rpcGestalts.test.ts index 72e6fe96d..88019f823 100644 --- a/tests/client/rpcGestalts.test.ts +++ b/tests/client/rpcGestalts.test.ts @@ -3,7 +3,7 @@ import type { IdentitiesManager } from '@/identities'; import type { GestaltGraph } from '@/gestalts'; import type { NodeManager } from '@/nodes'; import type { IdentityId, IdentityInfo, ProviderId } from '@/identities/types'; -import type { NodeInfo } from '@/nodes/types'; +import type { NodeIdEncoded, NodeInfo } from '@/nodes/types'; import type * as gestaltsPB from '@/proto/js/polykey/v1/gestalts/gestalts_pb'; import type { ClientServiceClient } from '@/proto/js/polykey/v1/client_service_grpc_pb'; import os from 'os'; @@ -47,9 +47,9 @@ describe('Client service', () => { let passwordFile: string; let callCredentials: grpc.Metadata; - const nodeId2 = nodesUtils.makeNodeId( - 'vrcacp9vsb4ht25hds6s4lpp2abfaso0mptcfnh499n35vfcn2gkg', - ); + const nodeId2Encoded = + 'vrcacp9vsb4ht25hds6s4lpp2abfaso0mptcfnh499n35vfcn2gkg' as NodeIdEncoded; + const nodeId2 = nodesUtils.decodeNodeId(nodeId2Encoded); const testToken = { providerId: 'test-provider' as ProviderId, @@ -59,7 +59,7 @@ describe('Client service', () => { }, }; const node2: NodeInfo = { - id: nodeId2, + id: nodeId2Encoded, chain: {}, }; const identity1: IdentityInfo = { @@ -120,7 +120,7 @@ describe('Client service', () => { client = await testUtils.openSimpleClientClient(port); node1 = { - id: nodeManager.getNodeId(), + id: nodesUtils.encodeNodeId(nodeManager.getNodeId()), chain: {}, }; }, global.polykeyStartupTimeout); @@ -167,14 +167,14 @@ describe('Client service', () => { identity1.providerId, identity1.identityId, ); - await gestaltGraph.getGestaltByNode(node2.id); + await gestaltGraph.getGestaltByNode(nodeId2); const gestaltsString = JSON.stringify(gestalts); expect(gestaltsString).toContain(identity1.providerId); expect(gestaltsString).toContain(identity1.identityId); - expect(gestaltsString).toContain(node2.id); + expect(gestaltsString).toContain(nodesUtils.encodeNodeId(nodeId2)); expect(gestalts).toHaveLength(2); - await gestaltGraph.unsetNode(node2.id); + await gestaltGraph.unsetNode(nodeId2); await gestaltGraph.unsetIdentity( identity1.providerId, identity1.identityId, @@ -183,19 +183,24 @@ describe('Client service', () => { test('should set independent node and identity gestalts', async () => { await gestaltGraph.setNode(node2); await gestaltGraph.setIdentity(identity1); - const gestaltNode = await gestaltGraph.getGestaltByNode(node2.id); + const gestaltNode = await gestaltGraph.getGestaltByNode(nodeId2); const gestaltIdentity = await gestaltGraph.getGestaltByIdentity( identity1.providerId, identity1.identityId, ); - const gkNode = gestaltsUtils.keyFromNode(node2.id); + const gkNode = gestaltsUtils.keyFromNode(nodeId2); const gkIdentity = gestaltsUtils.keyFromIdentity( identity1.providerId, identity1.identityId, ); expect(gestaltNode).toStrictEqual({ matrix: { [gkNode]: {} }, - nodes: { [gkNode]: node2 }, + nodes: { + [gkNode]: { + id: nodesUtils.encodeNodeId(nodeId2), + chain: {}, + }, + }, identities: {}, }); expect(gestaltIdentity).toStrictEqual({ @@ -212,7 +217,7 @@ describe('Client service', () => { await createGestaltState(); const nodeMessage = new nodesPB.Node(); - nodeMessage.setNodeId(node2.id); + nodeMessage.setNodeId(nodesUtils.encodeNodeId(nodeId2)); // Making the call const res = await gestaltsGetNode(nodeMessage, callCredentials); @@ -220,7 +225,7 @@ describe('Client service', () => { expect(jsonString).toContain('IdentityIdABC'); // Contains IdentityID expect(jsonString).toContain('github.com'); // Contains github provider - expect(jsonString).toContain(node2.id); // Contains NodeId + expect(jsonString).toContain(nodesUtils.encodeNodeId(nodeId2)); // Contains NodeId }); test('should get gestalt from identity.', async () => { const gestaltsGetIdentity = grpcUtils.promisifyUnaryCall( @@ -237,7 +242,7 @@ describe('Client service', () => { expect(jsonString).toContain('IdentityIdABC'); // Contains IdentityID expect(jsonString).toContain('github.com'); // Contains github provider - expect(jsonString).toContain(node2.id); // Contains NodeId + expect(jsonString).toContain(nodesUtils.encodeNodeId(nodeId2)); // Contains NodeId }); test('should discover gestalt via Node.', async () => { const gestaltsDiscoverNode = @@ -247,7 +252,7 @@ describe('Client service', () => { ); const nodeMessage = new nodesPB.Node(); - nodeMessage.setNodeId(node2.id); + nodeMessage.setNodeId(nodesUtils.encodeNodeId(nodeId2)); // I have no idea how to test this. so we just check for expected error for now await expect(() => gestaltsDiscoverNode(nodeMessage, callCredentials), @@ -282,19 +287,19 @@ describe('Client service', () => { ); await gestaltGraph.setNode(node1); await gestaltGraph.setNode(node2); - await gestaltGraph.setGestaltActionByNode(node2.id, 'scan'); - await gestaltGraph.setGestaltActionByNode(node2.id, 'notify'); + await gestaltGraph.setGestaltActionByNode(nodeId2, 'scan'); + await gestaltGraph.setGestaltActionByNode(nodeId2, 'notify'); const nodeMessage = new nodesPB.Node(); - nodeMessage.setNodeId(node2.id); + nodeMessage.setNodeId(nodesUtils.encodeNodeId(nodeId2)); // Should have permissions scan and notify as above const test1 = await gestaltsGetActionsByNode(nodeMessage, callCredentials); expect(test1.getActionList().length).toBe(2); expect(test1.getActionList().includes('scan')).toBeTruthy(); expect(test1.getActionList().includes('notify')).toBeTruthy(); - nodeMessage.setNodeId(nodeManager.getNodeId()); + nodeMessage.setNodeId(nodesUtils.encodeNodeId(nodeManager.getNodeId())); // Should have no permissions const test2 = await gestaltsGetActionsByNode(nodeMessage, callCredentials); expect(test2.getActionList().length).toBe(0); @@ -352,18 +357,18 @@ describe('Client service', () => { const setActionsMessage = new permissionsPB.ActionSet(); const nodeMessage = new nodesPB.Node(); - nodeMessage.setNodeId(node2.id); + nodeMessage.setNodeId(nodesUtils.encodeNodeId(nodeId2)); setActionsMessage.setNode(nodeMessage); setActionsMessage.setAction('scan'); // Should have permissions scan and notify as above await gestaltsSetActionByNode(setActionsMessage, callCredentials); - const check1 = await gestaltGraph.getGestaltActionsByNode(node2.id); + const check1 = await gestaltGraph.getGestaltActionsByNode(nodeId2); expect(Object.keys(check1!)).toContain('scan'); setActionsMessage.setAction('notify'); await gestaltsSetActionByNode(setActionsMessage, callCredentials); - const check2 = await gestaltGraph.getGestaltActionsByNode(node2.id); + const check2 = await gestaltGraph.getGestaltActionsByNode(nodeId2); expect(Object.keys(check2!)).toContain('notify'); }); test('should set gestalt permissions by Identity.', async () => { @@ -409,11 +414,11 @@ describe('Client service', () => { ); await gestaltGraph.setNode(node1); await gestaltGraph.setNode(node2); - await gestaltGraph.setGestaltActionByNode(node2.id, 'scan'); - await gestaltGraph.setGestaltActionByNode(node2.id, 'notify'); + await gestaltGraph.setGestaltActionByNode(nodeId2, 'scan'); + await gestaltGraph.setGestaltActionByNode(nodeId2, 'notify'); const nodeMessage = new nodesPB.Node(); - nodeMessage.setNodeId(node2.id); + nodeMessage.setNodeId(nodesUtils.encodeNodeId(nodeId2)); const setActionsMessage = new permissionsPB.ActionSet(); setActionsMessage.setNode(nodeMessage); @@ -421,7 +426,7 @@ describe('Client service', () => { // Should have permissions scan and notify as above await gestaltsUnsetActionByNode(setActionsMessage, callCredentials); - const check1 = await gestaltGraph.getGestaltActionsByNode(node2.id); + const check1 = await gestaltGraph.getGestaltActionsByNode(nodeId2); const keys = Object.keys(check1!); expect(keys.length).toBe(1); expect(keys).toContain('notify'); @@ -429,7 +434,7 @@ describe('Client service', () => { setActionsMessage.setAction('notify'); await gestaltsUnsetActionByNode(setActionsMessage, callCredentials); - const check2 = await gestaltGraph.getGestaltActionsByNode(node2.id); + const check2 = await gestaltGraph.getGestaltActionsByNode(nodeId2); const keys2 = Object.keys(check2!); expect(keys2.length).toBe(0); }); @@ -464,14 +469,14 @@ describe('Client service', () => { // Should have permissions scan and notify as above await gestaltsUnsetActionByIdentity(setActionsMessage, callCredentials); - const check1 = await gestaltGraph.getGestaltActionsByNode(node2.id); + const check1 = await gestaltGraph.getGestaltActionsByNode(nodeId2); const keys = Object.keys(check1!); expect(keys.length).toBe(1); expect(keys).toContain('notify'); expect(keys.includes('scan')).toBeFalsy(); setActionsMessage.setAction('notify'); await gestaltsUnsetActionByIdentity(setActionsMessage, callCredentials); - const check2 = await gestaltGraph.getGestaltActionsByNode(node2.id); + const check2 = await gestaltGraph.getGestaltActionsByNode(nodeId2); const keys2 = Object.keys(check2!); expect(keys2.length).toBe(0); }); diff --git a/tests/client/service/agentUnlock.test.ts b/tests/client/service/agentUnlock.test.ts index a30dabfa4..952259e47 100644 --- a/tests/client/service/agentUnlock.test.ts +++ b/tests/client/service/agentUnlock.test.ts @@ -1,5 +1,4 @@ import type { Host, Port } from '@/network/types'; -import type { NodeId } from '@/nodes/types'; import Logger, { LogLevel, StreamHandler } from '@matrixai/logger'; import { Metadata } from '@grpc/grpc-js'; import { GRPCServer } from '@/grpc'; @@ -10,6 +9,7 @@ import { } from '@/client'; import agentUnlock from '@/client/service/agentUnlock'; import * as utilsPB from '@/proto/js/polykey/v1/utils/utils_pb'; +import { utils as nodesUtils } from '@/nodes'; describe('agentUnlock', () => { const logger = new Logger('agentUnlock test', LogLevel.WARN, [ @@ -33,7 +33,9 @@ describe('agentUnlock', () => { port: 0 as Port, }); grpcClient = await GRPCClientClient.createGRPCClientClient({ - nodeId: 'vrcacp9vsb4ht25hds6s4lpp2abfaso0mptcfnh499n35vfcn2gkg' as NodeId, + nodeId: nodesUtils.decodeNodeId( + 'vrcacp9vsb4ht25hds6s4lpp2abfaso0mptcfnh499n35vfcn2gkg', + ), host: '127.0.0.1' as Host, port: grpcServer.port, logger, diff --git a/tests/client/service/identitiesAuthenticate.test.ts b/tests/client/service/identitiesAuthenticate.test.ts index 2e15b7a14..123171969 100644 --- a/tests/client/service/identitiesAuthenticate.test.ts +++ b/tests/client/service/identitiesAuthenticate.test.ts @@ -1,6 +1,5 @@ import type { IdentityId, ProviderId } from '@/identities/types'; import type { Host, Port } from '@/network/types'; -import type { NodeId } from '@/nodes/types'; import fs from 'fs'; import path from 'path'; import os from 'os'; @@ -16,6 +15,7 @@ import { } from '@/client'; import identitiesAuthenticate from '@/client/service/identitiesAuthenticate'; import * as identitiesPB from '@/proto/js/polykey/v1/identities/identities_pb'; +import { utils as nodesUtils } from '@/nodes'; import TestProvider from '../../identities/TestProvider'; describe('identitiesAuthenticate', () => { @@ -66,7 +66,9 @@ describe('identitiesAuthenticate', () => { port: 0 as Port, }); grpcClient = await GRPCClientClient.createGRPCClientClient({ - nodeId: 'vrcacp9vsb4ht25hds6s4lpp2abfaso0mptcfnh499n35vfcn2gkg' as NodeId, + nodeId: nodesUtils.decodeNodeId( + 'vrcacp9vsb4ht25hds6s4lpp2abfaso0mptcfnh499n35vfcn2gkg', + ), host: '127.0.0.1' as Host, port: grpcServer.port, logger, diff --git a/tests/client/service/identitiesClaim.test.ts b/tests/client/service/identitiesClaim.test.ts index 93eb06213..ed2092261 100644 --- a/tests/client/service/identitiesClaim.test.ts +++ b/tests/client/service/identitiesClaim.test.ts @@ -1,7 +1,7 @@ import type { Host, Port } from '@/network/types'; -import type { NodeId } from '@/nodes/types'; import type { IdentityId, ProviderId } from '@/identities/types'; import type { ClaimLinkIdentity } from '@/claims/types'; +import type { NodeIdEncoded } from '@/nodes/types'; import fs from 'fs'; import path from 'path'; import os from 'os'; @@ -42,7 +42,7 @@ describe('identitiesClaim', () => { }; const claimData: ClaimLinkIdentity = { type: 'identity', - node: 'vrcacp9vsb4ht25hds6s4lpp2abfaso0mptcfnh499n35vfcn2gkg' as NodeId, + node: 'vrcacp9vsb4ht25hds6s4lpp2abfaso0mptcfnh499n35vfcn2gkg' as NodeIdEncoded, provider: testToken.providerId, identity: testToken.identityId, }; diff --git a/tests/client/service/identitiesInfoGet.test.ts b/tests/client/service/identitiesInfoGet.test.ts index d15f920d6..2370a0164 100644 --- a/tests/client/service/identitiesInfoGet.test.ts +++ b/tests/client/service/identitiesInfoGet.test.ts @@ -1,6 +1,5 @@ import type { IdentityId, ProviderId } from '@/identities/types'; import type { Host, Port } from '@/network/types'; -import type { NodeId } from '@/nodes/types'; import fs from 'fs'; import path from 'path'; import os from 'os'; @@ -16,6 +15,7 @@ import { } from '@/client'; import identitiesInfoGet from '@/client/service/identitiesInfoGet'; import * as identitiesPB from '@/proto/js/polykey/v1/identities/identities_pb'; +import { utils as nodesUtils } from '@/nodes'; import TestProvider from '../../identities/TestProvider'; describe('identitiesInfoGet', () => { @@ -75,7 +75,9 @@ describe('identitiesInfoGet', () => { port: 0 as Port, }); grpcClient = await GRPCClientClient.createGRPCClientClient({ - nodeId: 'vrcacp9vsb4ht25hds6s4lpp2abfaso0mptcfnh499n35vfcn2gkg' as NodeId, + nodeId: nodesUtils.decodeNodeId( + 'vrcacp9vsb4ht25hds6s4lpp2abfaso0mptcfnh499n35vfcn2gkg', + ), host: '127.0.0.1' as Host, port: grpcServer.port, logger, diff --git a/tests/client/service/identitiesInfoGetConnected.test.ts b/tests/client/service/identitiesInfoGetConnected.test.ts index 10bdb8fb3..e4094ad13 100644 --- a/tests/client/service/identitiesInfoGetConnected.test.ts +++ b/tests/client/service/identitiesInfoGetConnected.test.ts @@ -1,6 +1,5 @@ import type { IdentityData, IdentityId, ProviderId } from '@/identities/types'; import type { Host, Port } from '@/network/types'; -import type { NodeId } from '@/nodes/types'; import fs from 'fs'; import path from 'path'; import os from 'os'; @@ -16,6 +15,7 @@ import { } from '@/client'; import identitiesInfoGetConnected from '@/client/service/identitiesInfoGetConnected'; import * as identitiesPB from '@/proto/js/polykey/v1/identities/identities_pb'; +import { utils as nodesUtils } from '@/nodes'; import TestProvider from '../../identities/TestProvider'; describe('identitiesInfoGetConnected', () => { @@ -93,7 +93,9 @@ describe('identitiesInfoGetConnected', () => { port: 0 as Port, }); grpcClient = await GRPCClientClient.createGRPCClientClient({ - nodeId: 'vrcacp9vsb4ht25hds6s4lpp2abfaso0mptcfnh499n35vfcn2gkg' as NodeId, + nodeId: nodesUtils.decodeNodeId( + 'vrcacp9vsb4ht25hds6s4lpp2abfaso0mptcfnh499n35vfcn2gkg', + ), host: '127.0.0.1' as Host, port: grpcServer.port, logger, diff --git a/tests/client/service/identitiesProvidersList.test.ts b/tests/client/service/identitiesProvidersList.test.ts index 074893527..35d15c67d 100644 --- a/tests/client/service/identitiesProvidersList.test.ts +++ b/tests/client/service/identitiesProvidersList.test.ts @@ -1,5 +1,4 @@ import type { Host, Port } from '@/network/types'; -import type { NodeId } from '@/nodes/types'; import type { ProviderId } from '@/identities/types'; import fs from 'fs'; import path from 'path'; @@ -17,6 +16,7 @@ import { import identitiesProvidersList from '@/client/service/identitiesProvidersList'; import * as identitiesPB from '@/proto/js/polykey/v1/identities/identities_pb'; import * as utilsPB from '@/proto/js/polykey/v1/utils/utils_pb'; +import { utils as nodesUtils } from '@/nodes'; import TestProvider from '../../identities/TestProvider'; describe('identitiesProvidersList', () => { @@ -71,7 +71,9 @@ describe('identitiesProvidersList', () => { port: 0 as Port, }); grpcClient = await GRPCClientClient.createGRPCClientClient({ - nodeId: 'vrcacp9vsb4ht25hds6s4lpp2abfaso0mptcfnh499n35vfcn2gkg' as NodeId, + nodeId: nodesUtils.decodeNodeId( + 'vrcacp9vsb4ht25hds6s4lpp2abfaso0mptcfnh499n35vfcn2gkg', + ), host: '127.0.0.1' as Host, port: grpcServer.port, logger, diff --git a/tests/client/service/identitiesTokenDelete.test.ts b/tests/client/service/identitiesTokenDelete.test.ts index f04780dd8..805c60bd1 100644 --- a/tests/client/service/identitiesTokenDelete.test.ts +++ b/tests/client/service/identitiesTokenDelete.test.ts @@ -1,5 +1,4 @@ import type { Host, Port } from '@/network/types'; -import type { NodeId } from '@/nodes/types'; import type { IdentityId, ProviderId } from '@/identities/types'; import fs from 'fs'; import path from 'path'; @@ -17,6 +16,7 @@ import { import identitiesTokenDelete from '@/client/service/identitiesTokenDelete'; import * as identitiesPB from '@/proto/js/polykey/v1/identities/identities_pb'; import * as utilsPB from '@/proto/js/polykey/v1/utils/utils_pb'; +import { utils as nodesUtils } from '@/nodes'; import TestProvider from '../../identities/TestProvider'; describe('identitiesTokenDelete', () => { @@ -65,7 +65,9 @@ describe('identitiesTokenDelete', () => { port: 0 as Port, }); grpcClient = await GRPCClientClient.createGRPCClientClient({ - nodeId: 'vrcacp9vsb4ht25hds6s4lpp2abfaso0mptcfnh499n35vfcn2gkg' as NodeId, + nodeId: nodesUtils.decodeNodeId( + 'vrcacp9vsb4ht25hds6s4lpp2abfaso0mptcfnh499n35vfcn2gkg', + ), host: '127.0.0.1' as Host, port: grpcServer.port, logger, diff --git a/tests/client/service/identitiesTokenGet.test.ts b/tests/client/service/identitiesTokenGet.test.ts index b33038dda..ecda3a347 100644 --- a/tests/client/service/identitiesTokenGet.test.ts +++ b/tests/client/service/identitiesTokenGet.test.ts @@ -1,5 +1,4 @@ import type { Host, Port } from '@/network/types'; -import type { NodeId } from '@/nodes/types'; import type { IdentityId, ProviderId } from '@/identities/types'; import fs from 'fs'; import path from 'path'; @@ -16,6 +15,7 @@ import { } from '@/client'; import identitiesTokenGet from '@/client/service/identitiesTokenGet'; import * as identitiesPB from '@/proto/js/polykey/v1/identities/identities_pb'; +import { utils as nodesUtils } from '@/nodes'; import TestProvider from '../../identities/TestProvider'; describe('identitiesTokenGet', () => { @@ -64,7 +64,9 @@ describe('identitiesTokenGet', () => { port: 0 as Port, }); grpcClient = await GRPCClientClient.createGRPCClientClient({ - nodeId: 'vrcacp9vsb4ht25hds6s4lpp2abfaso0mptcfnh499n35vfcn2gkg' as NodeId, + nodeId: nodesUtils.decodeNodeId( + 'vrcacp9vsb4ht25hds6s4lpp2abfaso0mptcfnh499n35vfcn2gkg', + ), host: '127.0.0.1' as Host, port: grpcServer.port, logger, diff --git a/tests/client/service/identitiesTokenPut.test.ts b/tests/client/service/identitiesTokenPut.test.ts index 2664c7b57..6f1bf7a11 100644 --- a/tests/client/service/identitiesTokenPut.test.ts +++ b/tests/client/service/identitiesTokenPut.test.ts @@ -1,5 +1,4 @@ import type { Host, Port } from '@/network/types'; -import type { NodeId } from '@/nodes/types'; import type { IdentityId, ProviderId } from '@/identities/types'; import fs from 'fs'; import path from 'path'; @@ -17,6 +16,7 @@ import { import identitiesTokenPut from '@/client/service/identitiesTokenPut'; import * as identitiesPB from '@/proto/js/polykey/v1/identities/identities_pb'; import * as utilsPB from '@/proto/js/polykey/v1/utils/utils_pb'; +import { utils as nodesUtils } from '@/nodes'; import TestProvider from '../../identities/TestProvider'; describe('identitiesTokenPut', () => { @@ -65,7 +65,9 @@ describe('identitiesTokenPut', () => { port: 0 as Port, }); grpcClient = await GRPCClientClient.createGRPCClientClient({ - nodeId: 'vrcacp9vsb4ht25hds6s4lpp2abfaso0mptcfnh499n35vfcn2gkg' as NodeId, + nodeId: nodesUtils.decodeNodeId( + 'vrcacp9vsb4ht25hds6s4lpp2abfaso0mptcfnh499n35vfcn2gkg', + ), host: '127.0.0.1' as Host, port: grpcServer.port, logger, diff --git a/tests/client/service/keysKeyPairRenew.test.ts b/tests/client/service/keysKeyPairRenew.test.ts index 56513fcad..6a1545f9c 100644 --- a/tests/client/service/keysKeyPairRenew.test.ts +++ b/tests/client/service/keysKeyPairRenew.test.ts @@ -120,7 +120,7 @@ describe('keysKeyPairRenew', () => { expect(fwdTLSConfig1).toEqual(expectedTLSConfig1); expect(revTLSConfig1).toEqual(expectedTLSConfig1); expect(serverTLSConfig1).toEqual(expectedTLSConfig1); - expect(nodeId1).toBe(nodeIdStatus1); + expect(nodeId1.equals(nodeIdStatus1)).toBe(true); // Run command const request = new keysPB.Key(); request.setName('somepassphrase'); @@ -150,6 +150,6 @@ describe('keysKeyPairRenew', () => { expect(rootKeyPair2.publicKey).not.toBe(rootKeyPair1.publicKey); expect(nodeId1).not.toBe(nodeId2); expect(nodeIdStatus1).not.toBe(nodeIdStatus2); - expect(nodeId2).toBe(nodeIdStatus2); + expect(nodeId2.equals(nodeIdStatus2)).toBe(true); }); }); diff --git a/tests/client/service/keysKeyPairReset.test.ts b/tests/client/service/keysKeyPairReset.test.ts index 2dca42d67..70f70e283 100644 --- a/tests/client/service/keysKeyPairReset.test.ts +++ b/tests/client/service/keysKeyPairReset.test.ts @@ -120,7 +120,7 @@ describe('keysKeyPairReset', () => { expect(fwdTLSConfig1).toEqual(expectedTLSConfig1); expect(revTLSConfig1).toEqual(expectedTLSConfig1); expect(serverTLSConfig1).toEqual(expectedTLSConfig1); - expect(nodeId1).toBe(nodeIdStatus1); + expect(nodeId1.equals(nodeIdStatus1)).toBe(true); // Run command const request = new keysPB.Key(); request.setName('somepassphrase'); @@ -150,6 +150,6 @@ describe('keysKeyPairReset', () => { expect(rootKeyPair2.publicKey).not.toBe(rootKeyPair1.publicKey); expect(nodeId1).not.toBe(nodeId2); expect(nodeIdStatus1).not.toBe(nodeIdStatus2); - expect(nodeId2).toBe(nodeIdStatus2); + expect(nodeId2.equals(nodeIdStatus2)).toBe(true); }); }); diff --git a/tests/client/service/nodesAdd.test.ts b/tests/client/service/nodesAdd.test.ts index 1885a6c2a..472f2e36a 100644 --- a/tests/client/service/nodesAdd.test.ts +++ b/tests/client/service/nodesAdd.test.ts @@ -1,5 +1,4 @@ import type { Host, Port } from '@/network/types'; -import type { NodeId } from '@/nodes/types'; import fs from 'fs'; import path from 'path'; import os from 'os'; @@ -19,6 +18,7 @@ import { import nodesAdd from '@/client/service/nodesAdd'; import * as nodesPB from '@/proto/js/polykey/v1/nodes/nodes_pb'; import * as utilsPB from '@/proto/js/polykey/v1/utils/utils_pb'; +import { utils as nodesUtils } from '@/nodes'; import * as testUtils from '../../utils'; describe('nodesAdd', () => { @@ -147,7 +147,9 @@ describe('nodesAdd', () => { ); expect(response).toBeInstanceOf(utilsPB.EmptyMessage); const result = await nodeManager.getNode( - 'vrsc24a1er424epq77dtoveo93meij0pc8ig4uvs9jbeld78n9nl0' as NodeId, + nodesUtils.decodeNodeId( + 'vrsc24a1er424epq77dtoveo93meij0pc8ig4uvs9jbeld78n9nl0', + ), ); expect(result).toBeDefined(); expect(result!.host).toBe('127.0.0.1'); diff --git a/tests/client/service/nodesClaim.test.ts b/tests/client/service/nodesClaim.test.ts index a12286721..8982e2df7 100644 --- a/tests/client/service/nodesClaim.test.ts +++ b/tests/client/service/nodesClaim.test.ts @@ -1,6 +1,6 @@ import type { Host, Port } from '@/network/types'; -import type { NodeId } from '@/nodes/types'; import type { Notification } from '@/notifications/types'; +import type { NodeIdEncoded } from '@/nodes/types'; import fs from 'fs'; import path from 'path'; import os from 'os'; @@ -35,7 +35,8 @@ describe('nodesClaim', () => { data: { type: 'GestaltInvite', }, - senderId: 'vrcacp9vsb4ht25hds6s4lpp2abfaso0mptcfnh499n35vfcn2gkg' as NodeId, + senderId: + 'vrcacp9vsb4ht25hds6s4lpp2abfaso0mptcfnh499n35vfcn2gkg' as NodeIdEncoded, isRead: false, }; let mockedGenerateKeyPair: jest.SpyInstance; diff --git a/tests/client/service/notificationsRead.test.ts b/tests/client/service/notificationsRead.test.ts index 252dc8022..2de1aeb45 100644 --- a/tests/client/service/notificationsRead.test.ts +++ b/tests/client/service/notificationsRead.test.ts @@ -1,5 +1,4 @@ import type { Host, Port } from '@/network/types'; -import type { NodeId } from '@/nodes/types'; import type { VaultName } from '@/vaults/types'; import fs from 'fs'; import path from 'path'; @@ -9,7 +8,7 @@ import { Metadata } from '@grpc/grpc-js'; import { DB } from '@matrixai/db'; import { KeyManager, utils as keysUtils } from '@/keys'; import { GRPCServer } from '@/grpc'; -import { NodeManager } from '@/nodes'; +import { NodeManager, utils as nodesUtils } from '@/nodes'; import { Sigchain } from '@/sigchain'; import { ForwardProxy, ReverseProxy } from '@/network'; import { NotificationsManager } from '@/notifications'; @@ -27,6 +26,8 @@ describe('notificationsRead', () => { const logger = new Logger('notificationsRead test', LogLevel.WARN, [ new StreamHandler(), ]); + const nodeIdSender = testUtils.generateRandomNodeId(); + const nodeIdSenderEncoded = nodesUtils.encodeNodeId(nodeIdSender); const password = 'helloworld'; const authenticate = async (metaClient, metaServer = new Metadata()) => metaServer; @@ -49,7 +50,7 @@ describe('notificationsRead', () => { type: 'General', message: 'test', }, - senderId: 'sender' as NodeId, + senderId: nodeIdSenderEncoded, isRead: true, }, ]) @@ -59,7 +60,7 @@ describe('notificationsRead', () => { type: 'General', message: 'test1', }, - senderId: 'sender' as NodeId, + senderId: nodeIdSenderEncoded, isRead: true, }, { @@ -67,7 +68,7 @@ describe('notificationsRead', () => { type: 'General', message: 'test2', }, - senderId: 'sender' as NodeId, + senderId: nodeIdSenderEncoded, isRead: true, }, ]) @@ -77,7 +78,7 @@ describe('notificationsRead', () => { type: 'General', message: 'test2', }, - senderId: 'sender' as NodeId, + senderId: nodeIdSenderEncoded, isRead: true, }, { @@ -85,7 +86,7 @@ describe('notificationsRead', () => { type: 'General', message: 'test1', }, - senderId: 'sender' as NodeId, + senderId: nodeIdSenderEncoded, isRead: true, }, ]) @@ -94,7 +95,7 @@ describe('notificationsRead', () => { data: { type: 'GestaltInvite', }, - senderId: 'sender' as NodeId, + senderId: nodeIdSenderEncoded, isRead: true, }, ]) @@ -109,7 +110,7 @@ describe('notificationsRead', () => { pull: null, }, }, - senderId: 'sender' as NodeId, + senderId: nodeIdSenderEncoded, isRead: true, }, ]) @@ -240,7 +241,7 @@ describe('notificationsRead', () => { expect(output).toHaveLength(1); expect(output[0].hasGeneral()).toBeTruthy(); expect(output[0].getGeneral()!.getMessage()).toBe('test'); - expect(output[0].getSenderId()).toBe('sender'); + expect(output[0].getSenderId()).toBe(nodeIdSenderEncoded); expect(output[0].getIsRead()).toBeTruthy(); // Check request was parsed correctly expect(mockedReadNotifications.mock.calls[0][0].unread).toBeFalsy(); @@ -261,11 +262,11 @@ describe('notificationsRead', () => { expect(output).toHaveLength(2); expect(output[0].hasGeneral()).toBeTruthy(); expect(output[0].getGeneral()!.getMessage()).toBe('test1'); - expect(output[0].getSenderId()).toBe('sender'); + expect(output[0].getSenderId()).toBe(nodeIdSenderEncoded); expect(output[0].getIsRead()).toBeTruthy(); expect(output[1].hasGeneral()).toBeTruthy(); expect(output[1].getGeneral()!.getMessage()).toBe('test2'); - expect(output[1].getSenderId()).toBe('sender'); + expect(output[1].getSenderId()).toBe(nodeIdSenderEncoded); expect(output[1].getIsRead()).toBeTruthy(); // Check request was parsed correctly expect(mockedReadNotifications.mock.calls[1][0].unread).toBeTruthy(); @@ -286,11 +287,11 @@ describe('notificationsRead', () => { expect(output).toHaveLength(2); expect(output[0].hasGeneral()).toBeTruthy(); expect(output[0].getGeneral()!.getMessage()).toBe('test2'); - expect(output[0].getSenderId()).toBe('sender'); + expect(output[0].getSenderId()).toBe(nodeIdSenderEncoded); expect(output[0].getIsRead()).toBeTruthy(); expect(output[1].hasGeneral()).toBeTruthy(); expect(output[1].getGeneral()!.getMessage()).toBe('test1'); - expect(output[1].getSenderId()).toBe('sender'); + expect(output[1].getSenderId()).toBe(nodeIdSenderEncoded); expect(output[1].getIsRead()).toBeTruthy(); // Check request was parsed correctly expect(mockedReadNotifications.mock.calls[2][0].unread).toBeFalsy(); @@ -311,7 +312,7 @@ describe('notificationsRead', () => { expect(output).toHaveLength(1); expect(output[0].hasGestaltInvite()).toBeTruthy(); expect(output[0].getGestaltInvite()).toBe('GestaltInvite'); - expect(output[0].getSenderId()).toBe('sender'); + expect(output[0].getSenderId()).toBe(nodeIdSenderEncoded); expect(output[0].getIsRead()).toBeTruthy(); // Check request was parsed correctly expect(mockedReadNotifications.mock.calls[3][0].unread).toBeFalsy(); @@ -335,7 +336,7 @@ describe('notificationsRead', () => { expect(output[0].getVaultShare()!.getVaultName()).toBe('vault'); expect(output[0].getVaultShare()!.getActionsList()).toContain('clone'); expect(output[0].getVaultShare()!.getActionsList()).toContain('pull'); - expect(output[0].getSenderId()).toBe('sender'); + expect(output[0].getSenderId()).toBe(nodeIdSenderEncoded); expect(output[0].getIsRead()).toBeTruthy(); // Check request was parsed correctly expect(mockedReadNotifications.mock.calls[4][0].unread).toBeFalsy(); diff --git a/tests/client/service/notificationsSend.test.ts b/tests/client/service/notificationsSend.test.ts index 012e012c7..a328e9732 100644 --- a/tests/client/service/notificationsSend.test.ts +++ b/tests/client/service/notificationsSend.test.ts @@ -8,7 +8,7 @@ import { Metadata } from '@grpc/grpc-js'; import { DB } from '@matrixai/db'; import { KeyManager, utils as keysUtils } from '@/keys'; import { GRPCServer } from '@/grpc'; -import { NodeManager } from '@/nodes'; +import { NodeManager, utils as nodesUtils } from '@/nodes'; import { Sigchain } from '@/sigchain'; import { ForwardProxy, ReverseProxy } from '@/network'; import { @@ -182,9 +182,9 @@ describe('notificationsSend', () => { // Check we signed and sent the notification expect(mockedSignNotification.mock.calls.length).toBe(1); expect(mockedSendNotification.mock.calls.length).toBe(1); - expect(mockedSendNotification.mock.calls[0][0]).toBe( - 'vrsc24a1er424epq77dtoveo93meij0pc8ig4uvs9jbeld78n9nl0', - ); + expect( + nodesUtils.encodeNodeId(mockedSendNotification.mock.calls[0][0]), + ).toBe('vrsc24a1er424epq77dtoveo93meij0pc8ig4uvs9jbeld78n9nl0'); expect(mockedSendNotification.mock.calls[0][1]).toBe('signedNotification'); // Check notification content expect(mockedSignNotification.mock.calls[0][0]).toEqual({ @@ -192,7 +192,7 @@ describe('notificationsSend', () => { type: 'General', message: 'test', }, - senderId: keyManager.getNodeId(), + senderId: nodesUtils.encodeNodeId(keyManager.getNodeId()), isRead: false, }); }); diff --git a/tests/discovery/Discovery.test.ts b/tests/discovery/Discovery.test.ts index 499a0593b..114a8a598 100644 --- a/tests/discovery/Discovery.test.ts +++ b/tests/discovery/Discovery.test.ts @@ -1,7 +1,6 @@ import type { ClaimLinkIdentity } from '@/claims/types'; import type { IdentityId, ProviderId } from '@/identities/types'; import type { Host, Port } from '@/network/types'; -import type { NodeId } from '@/nodes/types'; import fs from 'fs'; import path from 'path'; import os from 'os'; @@ -18,6 +17,7 @@ import { KeyManager, utils as keysUtils } from '@/keys'; import { ACL } from '@/acl'; import { Sigchain } from '@/sigchain'; import { ForwardProxy, ReverseProxy } from '@/network'; +import { utils as nodesUtils } from '@/nodes'; import TestProvider from '../identities/TestProvider'; import * as testUtils from '../utils'; import * as testNodesUtils from '../nodes/utils'; @@ -69,12 +69,12 @@ describe('Discovery', () => { keyManager = await KeyManager.createKeyManager({ password, keysPath, - logger, + logger: logger.getChild('KeyManager'), }); const dbPath = path.join(dataDir, 'db'); db = await DB.createDB({ dbPath, - logger, + logger: logger.getChild('db'), crypto: { key: keyManager.dbKey, ops: { @@ -85,26 +85,26 @@ describe('Discovery', () => { }); acl = await ACL.createACL({ db, - logger, + logger: logger.getChild('acl'), }); gestaltGraph = await GestaltGraph.createGestaltGraph({ db, acl, - logger, + logger: logger.getChild('gestaltGraph'), }); identitiesManager = await IdentitiesManager.createIdentitiesManager({ db, - logger, + logger: logger.getChild('identities'), }); identitiesManager.registerProvider(testProvider); sigchain = await Sigchain.createSigchain({ db, keyManager, - logger, + logger: logger.getChild('sigChain'), }); fwdProxy = new ForwardProxy({ authToken: 'abc123', - logger, + logger: logger.getChild('fwxProxy'), }); await fwdProxy.start({ tlsConfig: { @@ -112,7 +112,7 @@ describe('Discovery', () => { certChainPem: await keyManager.getRootCertChainPem(), }, }); - revProxy = new ReverseProxy({ logger }); + revProxy = new ReverseProxy({ logger: logger.getChild('revProxy') }); await revProxy.start({ serverHost: '127.0.0.1' as Host, serverPort: 55555 as Port, @@ -127,7 +127,7 @@ describe('Discovery', () => { sigchain, fwdProxy, revProxy, - logger, + logger: logger.getChild('nodeManager'), }); // Set up other gestalt nodeA = await PolykeyAgent.createPolykeyAgent({ @@ -136,7 +136,7 @@ describe('Discovery', () => { keysConfig: { rootKeyPairBits: 2048, }, - logger, + logger: logger.getChild('nodeA'), }); nodeB = await PolykeyAgent.createPolykeyAgent({ password: password, @@ -144,7 +144,7 @@ describe('Discovery', () => { keysConfig: { rootKeyPairBits: 2048, }, - logger, + logger: logger.getChild('nodeB'), }); await testNodesUtils.nodesConnect(nodeA, nodeB); await nodeManager.setNode(nodeA.nodeManager.getNodeId(), { @@ -159,7 +159,7 @@ describe('Discovery', () => { }); const identityClaim: ClaimLinkIdentity = { type: 'identity', - node: nodeB.nodeManager.getNodeId(), + node: nodesUtils.encodeNodeId(nodeB.nodeManager.getNodeId()), provider: testProvider.id, identity: identityId, }; @@ -200,7 +200,7 @@ describe('Discovery', () => { discovery.discoverGestaltByIdentity('' as ProviderId, '' as IdentityId); }).toThrow(discoveryErrors.ErrorDiscoveryDestroyed); expect(() => { - discovery.discoverGestaltByNode('' as NodeId); + discovery.discoverGestaltByNode(testUtils.generateRandomNodeId()); }).toThrow(discoveryErrors.ErrorDiscoveryDestroyed); }); test('discovery by node', async () => { @@ -219,8 +219,12 @@ describe('Discovery', () => { const gestalt = await gestaltGraph.getGestalts(); expect(gestalt.length).not.toBe(0); const gestaltString = JSON.stringify(gestalt); - expect(gestaltString).toContain(nodeA.nodeManager.getNodeId()); - expect(gestaltString).toContain(nodeB.nodeManager.getNodeId()); + expect(gestaltString).toContain( + nodesUtils.encodeNodeId(nodeA.nodeManager.getNodeId()), + ); + expect(gestaltString).toContain( + nodesUtils.encodeNodeId(nodeB.nodeManager.getNodeId()), + ); expect(gestaltString).toContain(identityId); await discovery.destroy(); await gestaltGraph.stop(); @@ -247,8 +251,12 @@ describe('Discovery', () => { const gestalt = await gestaltGraph.getGestalts(); expect(gestalt.length).not.toBe(0); const gestaltString = JSON.stringify(gestalt); - expect(gestaltString).toContain(nodeA.nodeManager.getNodeId()); - expect(gestaltString).toContain(nodeB.nodeManager.getNodeId()); + expect(gestaltString).toContain( + nodesUtils.encodeNodeId(nodeA.nodeManager.getNodeId()), + ); + expect(gestaltString).toContain( + nodesUtils.encodeNodeId(nodeB.nodeManager.getNodeId()), + ); expect(gestaltString).toContain(identityId); await discovery.destroy(); await gestaltGraph.stop(); diff --git a/tests/gestalts/GestaltGraph.test.ts b/tests/gestalts/GestaltGraph.test.ts index b818c9842..7cd3ab7a4 100644 --- a/tests/gestalts/GestaltGraph.test.ts +++ b/tests/gestalts/GestaltGraph.test.ts @@ -22,11 +22,22 @@ import { } from '@/gestalts'; import { ACL } from '@/acl'; import * as keysUtils from '@/keys/utils'; +import { utils as nodesUtils } from '@/nodes'; +import * as testUtils from '../utils'; describe('GestaltGraph', () => { const logger = new Logger('GestaltGraph Test', LogLevel.WARN, [ new StreamHandler(), ]); + const nodeIdABC = testUtils.generateRandomNodeId(); + const nodeIdABCEncoded = nodesUtils.encodeNodeId(nodeIdABC); + const nodeIdDEE = testUtils.generateRandomNodeId(); + const nodeIdDEEEncoded = nodesUtils.encodeNodeId(nodeIdDEE); + const nodeIdDEF = testUtils.generateRandomNodeId(); + const nodeIdDEFEncoded = nodesUtils.encodeNodeId(nodeIdDEF); + const nodeIdZZZ = testUtils.generateRandomNodeId(); + const nodeIdZZZEncoded = nodesUtils.encodeNodeId(nodeIdZZZ); + let dataDir: string; let db: DB; let acl: ACL; @@ -68,8 +79,8 @@ describe('GestaltGraph', () => { seq: 1, data: { type: 'node', - node1: 'abc' as NodeId, - node2: 'dee' as NodeId, + node1: nodeIdABCEncoded, + node2: nodeIdDEEEncoded, }, iat: 1618203162, }, @@ -82,8 +93,8 @@ describe('GestaltGraph', () => { seq: 1, data: { type: 'node', - node1: 'dee' as NodeId, // TODO: use type guards for all `as NodeID` usages here. - node2: 'abc' as NodeId, + node1: nodeIdDEEEncoded, // TODO: use type guards for all `as NodeID` usages here. + node2: nodeIdABCEncoded, }, iat: 1618203162, }, @@ -98,7 +109,7 @@ describe('GestaltGraph', () => { seq: 1, data: { type: 'identity', - node: 'abc' as NodeId, + node: nodeIdABCEncoded, provider: 'github.com' as ProviderId, identity: 'abc' as IdentityId, }, @@ -114,7 +125,7 @@ describe('GestaltGraph', () => { seq: 1, data: { type: 'identity', - node: 'abc' as NodeId, + node: nodeIdABCEncoded, provider: 'github.com' as ProviderId, identity: 'abc' as IdentityId, }, @@ -161,21 +172,26 @@ describe('GestaltGraph', () => { logger, }); const nodeInfo: NodeInfo = { - id: 'abc' as NodeId, + id: nodeIdABCEncoded, chain: {}, }; await gestaltGraph.setNode(nodeInfo); - const gestalt = await gestaltGraph.getGestaltByNode(nodeInfo.id); - const gk = gestaltsUtils.keyFromNode(nodeInfo.id); + const gestalt = await gestaltGraph.getGestaltByNode(nodeIdABC); + const gk = gestaltsUtils.keyFromNode(nodeIdABC); expect(gestalt).toStrictEqual({ matrix: { [gk]: {} }, - nodes: { [gk]: nodeInfo }, + nodes: { + [gk]: { + id: nodesUtils.encodeNodeId(nodeIdABC), + chain: nodeInfo.chain, + }, + }, identities: {}, }); - await gestaltGraph.unsetNode(nodeInfo.id); - await gestaltGraph.unsetNode(nodeInfo.id); + await gestaltGraph.unsetNode(nodeIdABC); + await gestaltGraph.unsetNode(nodeIdABC); await expect( - gestaltGraph.getGestaltByNode(nodeInfo.id), + gestaltGraph.getGestaltByNode(nodeIdABC), ).resolves.toBeUndefined(); await gestaltGraph.stop(); await gestaltGraph.destroy(); @@ -229,7 +245,7 @@ describe('GestaltGraph', () => { logger, }); const nodeInfo: NodeInfo = { - id: 'abc' as NodeId, + id: nodeIdABCEncoded, chain: {}, }; const identityInfo: IdentityInfo = { @@ -239,19 +255,24 @@ describe('GestaltGraph', () => { }; await gestaltGraph.setNode(nodeInfo); await gestaltGraph.setIdentity(identityInfo); - const gestaltNode = await gestaltGraph.getGestaltByNode(nodeInfo.id); + const gestaltNode = await gestaltGraph.getGestaltByNode(nodeIdABC); const gestaltIdentity = await gestaltGraph.getGestaltByIdentity( identityInfo.providerId, identityInfo.identityId, ); - const gkNode = gestaltsUtils.keyFromNode(nodeInfo.id); + const gkNode = gestaltsUtils.keyFromNode(nodeIdABC); const gkIdentity = gestaltsUtils.keyFromIdentity( identityInfo.providerId, identityInfo.identityId, ); expect(gestaltNode).toStrictEqual({ matrix: { [gkNode]: {} }, - nodes: { [gkNode]: nodeInfo }, + nodes: { + [gkNode]: { + id: nodesUtils.encodeNodeId(nodeIdABC), + chain: nodeInfo.chain, + }, + }, identities: {}, }); expect(gestaltIdentity).toStrictEqual({ @@ -269,7 +290,7 @@ describe('GestaltGraph', () => { logger, }); const nodeInfo: NodeInfo = { - id: 'abc' as NodeId, + id: nodeIdABCEncoded, chain: {}, }; const identityInfo: IdentityInfo = { @@ -286,19 +307,24 @@ describe('GestaltGraph', () => { acl, logger, }); - const gestaltNode = await gestaltGraph.getGestaltByNode(nodeInfo.id); + const gestaltNode = await gestaltGraph.getGestaltByNode(nodeIdABC); const gestaltIdentity = await gestaltGraph.getGestaltByIdentity( identityInfo.providerId, identityInfo.identityId, ); - const gkNode = gestaltsUtils.keyFromNode(nodeInfo.id); + const gkNode = gestaltsUtils.keyFromNode(nodeIdABC); const gkIdentity = gestaltsUtils.keyFromIdentity( identityInfo.providerId, identityInfo.identityId, ); expect(gestaltNode).toStrictEqual({ matrix: { [gkNode]: {} }, - nodes: { [gkNode]: nodeInfo }, + nodes: { + [gkNode]: { + id: nodesUtils.encodeNodeId(nodeIdABC), + chain: nodeInfo.chain, + }, + }, identities: {}, }); expect(gestaltIdentity).toStrictEqual({ @@ -320,7 +346,7 @@ describe('GestaltGraph', () => { const nodeInfo1Chain: ChainData = {}; nodeInfo1Chain['A'] = nodeClaimAbcToDee; const nodeInfo1: NodeInfo = { - id: 'abc' as NodeId, + id: nodeIdABCEncoded, chain: nodeInfo1Chain, }; // NodeInfo on node 'dee'. Contains claims: @@ -328,17 +354,17 @@ describe('GestaltGraph', () => { const nodeInfo2Chain: ChainData = {}; nodeInfo2Chain['A'] = nodeClaimDeeToAbc; const nodeInfo2: NodeInfo = { - id: 'dee' as NodeId, + id: nodeIdDEEEncoded, chain: nodeInfo2Chain, }; await gestaltGraph.linkNodeAndNode(nodeInfo1, nodeInfo2); - const gestaltNode1 = await gestaltGraph.getGestaltByNode(nodeInfo1.id); - const gestaltNode2 = await gestaltGraph.getGestaltByNode(nodeInfo2.id); + const gestaltNode1 = await gestaltGraph.getGestaltByNode(nodeIdABC); + const gestaltNode2 = await gestaltGraph.getGestaltByNode(nodeIdDEE); expect(gestaltNode1).not.toBeUndefined(); expect(gestaltNode2).not.toBeUndefined(); expect(gestaltNode1).toStrictEqual(gestaltNode2); - const gkNode1 = gestaltsUtils.keyFromNode(nodeInfo1.id); - const gkNode2 = gestaltsUtils.keyFromNode(nodeInfo2.id); + const gkNode1 = gestaltsUtils.keyFromNode(nodeIdABC); + const gkNode2 = gestaltsUtils.keyFromNode(nodeIdDEE); expect(gestaltNode1).toStrictEqual({ matrix: { [gkNode1]: { @@ -349,8 +375,14 @@ describe('GestaltGraph', () => { }, }, nodes: { - [gkNode1]: nodeInfo1, - [gkNode2]: nodeInfo2, + [gkNode1]: { + id: nodesUtils.encodeNodeId(nodeIdABC), + chain: nodeInfo1.chain, + }, + [gkNode2]: { + id: nodesUtils.encodeNodeId(nodeIdDEE), + chain: nodeInfo2.chain, + }, }, identities: {}, }); @@ -368,7 +400,7 @@ describe('GestaltGraph', () => { const nodeInfo1Chain: ChainData = {}; nodeInfo1Chain['A'] = identityClaimAbcToGH; const nodeInfo: NodeInfo = { - id: 'abc' as NodeId, + id: nodeIdABCEncoded, chain: nodeInfo1Chain, }; // IdentityInfo on identity from GitHub. Contains claims: @@ -381,14 +413,14 @@ describe('GestaltGraph', () => { claims: identityInfoClaims, }; await gestaltGraph.linkNodeAndIdentity(nodeInfo, identityInfo); - const gestaltNode = await gestaltGraph.getGestaltByNode(nodeInfo.id); + const gestaltNode = await gestaltGraph.getGestaltByNode(nodeIdABC); const gestaltIdentity = await gestaltGraph.getGestaltByIdentity( identityInfo.providerId, identityInfo.identityId, ); expect(gestaltNode).not.toBeUndefined(); expect(gestaltNode).toStrictEqual(gestaltIdentity); - const gkNode = gestaltsUtils.keyFromNode(nodeInfo.id); + const gkNode = gestaltsUtils.keyFromNode(nodeIdABC); const gkIdentity = gestaltsUtils.keyFromIdentity( identityInfo.providerId, identityInfo.identityId, @@ -403,7 +435,10 @@ describe('GestaltGraph', () => { }, }, nodes: { - [gkNode]: nodeInfo, + [gkNode]: { + id: nodesUtils.encodeNodeId(nodeIdABC), + chain: nodeInfo.chain, + }, }, identities: { [gkIdentity]: identityInfo, @@ -426,7 +461,7 @@ describe('GestaltGraph', () => { identityClaimAbcToGH.payload.seq = 2; nodeInfo1Chain['B'] = identityClaimAbcToGH; const nodeInfo1: NodeInfo = { - id: 'abc' as NodeId, + id: nodeIdABCEncoded, chain: nodeInfo1Chain, }; // NodeInfo on node 'dee'. Contains claims: @@ -434,7 +469,7 @@ describe('GestaltGraph', () => { const nodeInfo2Chain: ChainData = {}; nodeInfo2Chain['A'] = nodeClaimDeeToAbc; const nodeInfo2: NodeInfo = { - id: 'dee' as NodeId, + id: nodeIdDEEEncoded, chain: nodeInfo2Chain, }; // IdentityInfo on identity from GitHub. Contains claims: @@ -448,8 +483,8 @@ describe('GestaltGraph', () => { }; await gestaltGraph.linkNodeAndIdentity(nodeInfo1, identityInfo); await gestaltGraph.linkNodeAndNode(nodeInfo1, nodeInfo2); - const gestaltNode1 = await gestaltGraph.getGestaltByNode(nodeInfo1.id); - const gestaltNode2 = await gestaltGraph.getGestaltByNode(nodeInfo2.id); + const gestaltNode1 = await gestaltGraph.getGestaltByNode(nodeIdABC); + const gestaltNode2 = await gestaltGraph.getGestaltByNode(nodeIdDEE); const gestaltIdentity = await gestaltGraph.getGestaltByIdentity( identityInfo.providerId, identityInfo.identityId, @@ -459,8 +494,8 @@ describe('GestaltGraph', () => { expect(gestaltIdentity).not.toBeUndefined(); expect(gestaltNode1).toStrictEqual(gestaltNode2); expect(gestaltNode2).toStrictEqual(gestaltIdentity); - const gkNode1 = gestaltsUtils.keyFromNode(nodeInfo1.id); - const gkNode2 = gestaltsUtils.keyFromNode(nodeInfo2.id); + const gkNode1 = gestaltsUtils.keyFromNode(nodeIdABC); + const gkNode2 = gestaltsUtils.keyFromNode(nodeIdDEE); const gkIdentity = gestaltsUtils.keyFromIdentity( identityInfo.providerId, identityInfo.identityId, @@ -479,8 +514,14 @@ describe('GestaltGraph', () => { }, }, nodes: { - [gkNode1]: nodeInfo1, - [gkNode2]: nodeInfo2, + [gkNode1]: { + id: nodesUtils.encodeNodeId(nodeIdABC), + chain: nodeInfo1.chain, + }, + [gkNode2]: { + id: nodesUtils.encodeNodeId(nodeIdDEE), + chain: nodeInfo2.chain, + }, }, identities: { [gkIdentity]: identityInfo, @@ -496,7 +537,7 @@ describe('GestaltGraph', () => { logger, }); const nodeInfo: NodeInfo = { - id: 'abc' as NodeId, + id: nodeIdABCEncoded, chain: {}, }; await gestaltGraph.setNode(nodeInfo); @@ -511,7 +552,7 @@ describe('GestaltGraph', () => { identityInfo.providerId, identityInfo.identityId, ); - const nodeGestalt = await gestaltGraph.getGestaltByNode(nodeInfo.id); + const nodeGestalt = await gestaltGraph.getGestaltByNode(nodeIdABC); expect(gestalts).toContainEqual(identityGestalt); expect(gestalts).toContainEqual(nodeGestalt); expect(gestalts).toHaveLength(2); @@ -535,18 +576,18 @@ describe('GestaltGraph', () => { logger, }); const nodeInfo: NodeInfo = { - id: 'abc' as NodeId, + id: nodeIdABCEncoded, chain: {}, }; - expect(await acl.getNodePerm(nodeInfo.id)).toBeUndefined(); + expect(await acl.getNodePerm(nodeIdABC)).toBeUndefined(); await gestaltGraph.setNode(nodeInfo); - const perm = await acl.getNodePerm(nodeInfo.id); + const perm = await acl.getNodePerm(nodeIdABC); expect(perm).toBeDefined(); expect(perm).toMatchObject({ gestalt: {}, vaults: {}, }); - const actions = await gestaltGraph.getGestaltActionsByNode(nodeInfo.id); + const actions = await gestaltGraph.getGestaltActionsByNode(nodeIdABC); expect(actions).toBeDefined(); expect(actions).toMatchObject({}); await gestaltGraph.stop(); @@ -579,15 +620,15 @@ describe('GestaltGraph', () => { logger, }); const nodeInfo: NodeInfo = { - id: 'abc' as NodeId, + id: nodeIdABCEncoded, chain: {}, }; await gestaltGraph.setNode(nodeInfo); - await gestaltGraph.setGestaltActionByNode(nodeInfo.id, 'notify'); + await gestaltGraph.setGestaltActionByNode(nodeIdABC, 'notify'); let actions; - actions = await gestaltGraph.getGestaltActionsByNode(nodeInfo.id); + actions = await gestaltGraph.getGestaltActionsByNode(nodeIdABC); expect(actions).toHaveProperty('notify'); - const perm = await acl.getNodePerm(nodeInfo.id); + const perm = await acl.getNodePerm(nodeIdABC); expect(perm).toBeDefined(); expect(perm).toMatchObject({ gestalt: { @@ -595,8 +636,8 @@ describe('GestaltGraph', () => { }, vaults: {}, }); - await gestaltGraph.unsetGestaltActionByNode(nodeInfo.id, 'notify'); - actions = await gestaltGraph.getGestaltActionsByNode(nodeInfo.id); + await gestaltGraph.unsetGestaltActionByNode(nodeIdABC, 'notify'); + actions = await gestaltGraph.getGestaltActionsByNode(nodeIdABC); expect(actions).not.toHaveProperty('notify'); await gestaltGraph.stop(); await gestaltGraph.destroy(); @@ -613,7 +654,7 @@ describe('GestaltGraph', () => { const nodeInfo1Chain: ChainData = {}; nodeInfo1Chain['A'] = nodeClaimAbcToDee; const nodeInfo1: NodeInfo = { - id: 'abc' as NodeId, + id: nodeIdABCEncoded, chain: nodeInfo1Chain, }; // NodeInfo on node 'dee'. Contains claims: @@ -621,19 +662,19 @@ describe('GestaltGraph', () => { const nodeInfo2Chain: ChainData = {}; nodeInfo2Chain['A'] = nodeClaimDeeToAbc; const nodeInfo2: NodeInfo = { - id: 'dee' as NodeId, + id: nodeIdDEEEncoded, chain: nodeInfo2Chain, }; await gestaltGraph.linkNodeAndNode(nodeInfo1, nodeInfo2); let actions1, actions2; - actions1 = await gestaltGraph.getGestaltActionsByNode(nodeInfo1.id); - actions2 = await gestaltGraph.getGestaltActionsByNode(nodeInfo2.id); + actions1 = await gestaltGraph.getGestaltActionsByNode(nodeIdABC); + actions2 = await gestaltGraph.getGestaltActionsByNode(nodeIdDEE); expect(actions1).not.toBeUndefined(); expect(actions2).not.toBeUndefined(); expect(actions1).toEqual(actions2); - await gestaltGraph.setGestaltActionByNode(nodeInfo1.id, 'notify'); - actions1 = await gestaltGraph.getGestaltActionsByNode(nodeInfo1.id); - actions2 = await gestaltGraph.getGestaltActionsByNode(nodeInfo2.id); + await gestaltGraph.setGestaltActionByNode(nodeIdABC, 'notify'); + actions1 = await gestaltGraph.getGestaltActionsByNode(nodeIdABC); + actions2 = await gestaltGraph.getGestaltActionsByNode(nodeIdDEE); expect(actions1).toEqual({ notify: null }); expect(actions1).toEqual(actions2); await gestaltGraph.stop(); @@ -647,23 +688,23 @@ describe('GestaltGraph', () => { }); // 2 existing nodes will have a joined permission const nodeInfo1: NodeInfo = { - id: 'abc' as NodeId, + id: nodeIdABCEncoded, chain: {}, }; const nodeInfo2: NodeInfo = { - id: 'dee' as NodeId, + id: nodeIdDEEEncoded, chain: {}, }; await gestaltGraph.setNode(nodeInfo1); await gestaltGraph.setNode(nodeInfo2); - await gestaltGraph.setGestaltActionByNode(nodeInfo1.id, 'notify'); - await gestaltGraph.setGestaltActionByNode(nodeInfo2.id, 'scan'); + await gestaltGraph.setGestaltActionByNode(nodeIdABC, 'notify'); + await gestaltGraph.setGestaltActionByNode(nodeIdDEE, 'scan'); // NodeInfo on node 'abc'. Contains claims: // abc -> dee const nodeInfo1Chain: ChainData = {}; nodeInfo1Chain['A'] = nodeClaimAbcToDee; const nodeInfo1Linked: NodeInfo = { - id: 'abc' as NodeId, + id: nodeIdABCEncoded, chain: nodeInfo1Chain, }; // NodeInfo on node 'dee'. Contains claims: @@ -671,16 +712,12 @@ describe('GestaltGraph', () => { const nodeInfo2Chain: ChainData = {}; nodeInfo2Chain['A'] = nodeClaimDeeToAbc; const nodeInfo2Linked: NodeInfo = { - id: 'dee' as NodeId, + id: nodeIdDEEEncoded, chain: nodeInfo2Chain, }; await gestaltGraph.linkNodeAndNode(nodeInfo1Linked, nodeInfo2Linked); - const actions1 = await gestaltGraph.getGestaltActionsByNode( - nodeInfo1Linked.id, - ); - const actions2 = await gestaltGraph.getGestaltActionsByNode( - nodeInfo2Linked.id, - ); + const actions1 = await gestaltGraph.getGestaltActionsByNode(nodeIdABC); + const actions2 = await gestaltGraph.getGestaltActionsByNode(nodeIdDEE); expect(actions1).not.toBeUndefined(); expect(actions2).not.toBeUndefined(); expect(actions1).toEqual({ notify: null, scan: null }); @@ -696,17 +733,17 @@ describe('GestaltGraph', () => { }); // Node 1 exists, but node 2 is new const nodeInfo1: NodeInfo = { - id: 'abc' as NodeId, + id: nodeIdABCEncoded, chain: {}, }; await gestaltGraph.setNode(nodeInfo1); - await gestaltGraph.setGestaltActionByNode(nodeInfo1.id, 'notify'); + await gestaltGraph.setGestaltActionByNode(nodeIdABC, 'notify'); // NodeInfo on node 'abc'. Contains claims: // abc -> dee const nodeInfo1Chain: ChainData = {}; nodeInfo1Chain['A'] = nodeClaimAbcToDee; const nodeInfo1Linked: NodeInfo = { - id: 'abc' as NodeId, + id: nodeIdABCEncoded, chain: nodeInfo1Chain, }; // NodeInfo on node 'dee'. Contains claims: @@ -714,13 +751,13 @@ describe('GestaltGraph', () => { const nodeInfo2Chain: ChainData = {}; nodeInfo2Chain['A'] = nodeClaimDeeToAbc; const nodeInfo2Linked: NodeInfo = { - id: 'dee' as NodeId, + id: nodeIdDEEEncoded, chain: nodeInfo2Chain, }; await gestaltGraph.linkNodeAndNode(nodeInfo1Linked, nodeInfo2Linked); let actions1, actions2; - actions1 = await gestaltGraph.getGestaltActionsByNode(nodeInfo1Linked.id); - actions2 = await gestaltGraph.getGestaltActionsByNode(nodeInfo2Linked.id); + actions1 = await gestaltGraph.getGestaltActionsByNode(nodeIdABC); + actions2 = await gestaltGraph.getGestaltActionsByNode(nodeIdDEE); expect(actions1).not.toBeUndefined(); expect(actions2).not.toBeUndefined(); expect(actions1).toEqual({ notify: null }); @@ -736,8 +773,8 @@ describe('GestaltGraph', () => { seq: 1, data: { type: 'node', - node1: 'zzz' as NodeId, - node2: 'dee' as NodeId, + node1: nodeIdZZZEncoded, + node2: nodeIdDEEEncoded, }, iat: 1618203162, }, @@ -748,15 +785,13 @@ describe('GestaltGraph', () => { const nodeInfo3Chain: ChainData = {}; nodeInfo3Chain['A'] = nodeClaimZzzToDee; const nodeInfo3Linked: NodeInfo = { - id: 'zzz' as NodeId, + id: nodeIdZZZEncoded, chain: nodeInfo3Chain, }; await gestaltGraph.linkNodeAndNode(nodeInfo3Linked, nodeInfo2Linked); - actions1 = await gestaltGraph.getGestaltActionsByNode(nodeInfo1Linked.id); - actions2 = await gestaltGraph.getGestaltActionsByNode(nodeInfo2Linked.id); - const actions3 = await gestaltGraph.getGestaltActionsByNode( - nodeInfo3Linked.id, - ); + actions1 = await gestaltGraph.getGestaltActionsByNode(nodeIdABC); + actions2 = await gestaltGraph.getGestaltActionsByNode(nodeIdDEE); + const actions3 = await gestaltGraph.getGestaltActionsByNode(nodeIdZZZ); expect(actions1).not.toBeUndefined(); expect(actions2).not.toBeUndefined(); expect(actions3).not.toBeUndefined(); @@ -776,7 +811,7 @@ describe('GestaltGraph', () => { const nodeInfo1Chain: ChainData = {}; nodeInfo1Chain['A'] = identityClaimAbcToGH; const nodeInfo: NodeInfo = { - id: 'abc' as NodeId, + id: nodeIdABCEncoded, chain: nodeInfo1Chain, }; // IdentityInfo on identity from GitHub. Contains claims: @@ -790,7 +825,7 @@ describe('GestaltGraph', () => { }; await gestaltGraph.linkNodeAndIdentity(nodeInfo, identityInfo); let actions1, actions2; - actions1 = await gestaltGraph.getGestaltActionsByNode(nodeInfo.id); + actions1 = await gestaltGraph.getGestaltActionsByNode(nodeIdABC); actions2 = await gestaltGraph.getGestaltActionsByIdentity( identityInfo.providerId, identityInfo.identityId, @@ -804,7 +839,7 @@ describe('GestaltGraph', () => { identityInfo.identityId, 'notify', ); - actions1 = await gestaltGraph.getGestaltActionsByNode(nodeInfo.id); + actions1 = await gestaltGraph.getGestaltActionsByNode(nodeIdABC); actions2 = await gestaltGraph.getGestaltActionsByIdentity( identityInfo.providerId, identityInfo.identityId, @@ -821,7 +856,7 @@ describe('GestaltGraph', () => { logger, }); const nodeInfo: NodeInfo = { - id: 'abc' as NodeId, + id: nodeIdABCEncoded, chain: {}, }; const identityInfo: IdentityInfo = { @@ -831,13 +866,13 @@ describe('GestaltGraph', () => { }; await gestaltGraph.setNode(nodeInfo); await gestaltGraph.setIdentity(identityInfo); - await gestaltGraph.setGestaltActionByNode(nodeInfo.id, 'notify'); + await gestaltGraph.setGestaltActionByNode(nodeIdABC, 'notify'); // NodeInfo on node 'abc'. Contains claims: // abc -> GitHub const nodeInfo1Chain: ChainData = {}; nodeInfo1Chain['A'] = identityClaimAbcToGH; const nodeInfoLinked: NodeInfo = { - id: 'abc' as NodeId, + id: nodeIdABCEncoded, chain: nodeInfo1Chain, }; // IdentityInfo on identity from GitHub. Contains claims: @@ -851,7 +886,7 @@ describe('GestaltGraph', () => { }; await gestaltGraph.linkNodeAndIdentity(nodeInfoLinked, identityInfoLinked); let actions1, actions2; - actions1 = await gestaltGraph.getGestaltActionsByNode(nodeInfo.id); + actions1 = await gestaltGraph.getGestaltActionsByNode(nodeIdABC); actions2 = await gestaltGraph.getGestaltActionsByIdentity( identityInfo.providerId, identityInfo.identityId, @@ -861,7 +896,7 @@ describe('GestaltGraph', () => { expect(actions1).toEqual({ notify: null }); expect(actions1).toEqual(actions2); const nodeInfo2: NodeInfo = { - id: 'def' as NodeId, + id: nodeIdDEFEncoded, chain: {}, }; await gestaltGraph.setNode(nodeInfo2); @@ -875,7 +910,7 @@ describe('GestaltGraph', () => { identityInfo.identityId, 'scan', ); - await gestaltGraph.setGestaltActionByNode(nodeInfo2.id, 'notify'); + await gestaltGraph.setGestaltActionByNode(nodeIdDEF, 'notify'); const defSignature: Record = {}; defSignature['def'] = 'defSignature'; @@ -886,7 +921,7 @@ describe('GestaltGraph', () => { seq: 1, data: { type: 'identity', - node: 'def' as NodeId, + node: nodeIdDEFEncoded, provider: 'github.com' as ProviderId, identity: 'abc' as IdentityId, }, @@ -899,7 +934,7 @@ describe('GestaltGraph', () => { const nodeInfo2Chain: ChainData = {}; nodeInfo1Chain['A'] = identityClaimDefToGH; const nodeInfo2Linked: NodeInfo = { - id: 'def' as NodeId, + id: nodeIdDEFEncoded, chain: nodeInfo2Chain, }; @@ -911,7 +946,7 @@ describe('GestaltGraph', () => { seq: 2, data: { type: 'identity', - node: 'def' as NodeId, + node: nodeIdDEF, provider: 'github.com' as ProviderId, identity: 'abc' as IdentityId, }, @@ -934,12 +969,12 @@ describe('GestaltGraph', () => { nodeInfo2Linked, identityInfoLinkedAgain, ); - actions1 = await gestaltGraph.getGestaltActionsByNode(nodeInfo.id); + actions1 = await gestaltGraph.getGestaltActionsByNode(nodeIdABC); actions2 = await gestaltGraph.getGestaltActionsByIdentity( identityInfo.providerId, identityInfo.identityId, ); - const actions3 = await gestaltGraph.getGestaltActionsByNode(nodeInfo2.id); + const actions3 = await gestaltGraph.getGestaltActionsByNode(nodeIdDEF); expect(actions1).not.toBeUndefined(); expect(actions2).not.toBeUndefined(); expect(actions3).not.toBeUndefined(); @@ -956,7 +991,7 @@ describe('GestaltGraph', () => { logger, }); const nodeInfo: NodeInfo = { - id: 'abc' as NodeId, + id: nodeIdABCEncoded, chain: {}, }; await gestaltGraph.setNode(nodeInfo); @@ -965,7 +1000,7 @@ describe('GestaltGraph', () => { const nodeInfo1Chain: ChainData = {}; nodeInfo1Chain['A'] = identityClaimAbcToGH; const nodeInfoLinked: NodeInfo = { - id: 'abc' as NodeId, + id: nodeIdABCEncoded, chain: nodeInfo1Chain, }; // IdentityInfo on identity from GitHub. Contains claims: @@ -979,7 +1014,7 @@ describe('GestaltGraph', () => { }; await gestaltGraph.linkNodeAndIdentity(nodeInfoLinked, identityInfoLinked); let actions1, actions2; - actions1 = await gestaltGraph.getGestaltActionsByNode(nodeInfo.id); + actions1 = await gestaltGraph.getGestaltActionsByNode(nodeIdABC); actions2 = await gestaltGraph.getGestaltActionsByIdentity( identityInfoLinked.providerId, identityInfoLinked.identityId, @@ -998,7 +1033,7 @@ describe('GestaltGraph', () => { identityInfoLinked.identityId, 'notify', ); - actions1 = await gestaltGraph.getGestaltActionsByNode(nodeInfo.id); + actions1 = await gestaltGraph.getGestaltActionsByNode(nodeIdABC); actions2 = await gestaltGraph.getGestaltActionsByIdentity( identityInfoLinked.providerId, identityInfoLinked.identityId, @@ -1030,7 +1065,7 @@ describe('GestaltGraph', () => { const nodeInfo1Chain: ChainData = {}; nodeInfo1Chain['A'] = identityClaimAbcToGH; const nodeInfoLinked: NodeInfo = { - id: 'abc' as NodeId, + id: nodeIdABCEncoded, chain: nodeInfo1Chain, }; // IdentityInfo on identity from GitHub. Contains claims: @@ -1044,7 +1079,7 @@ describe('GestaltGraph', () => { }; await gestaltGraph.linkNodeAndIdentity(nodeInfoLinked, identityInfoLinked); let actions1, actions2; - actions1 = await gestaltGraph.getGestaltActionsByNode(nodeInfoLinked.id); + actions1 = await gestaltGraph.getGestaltActionsByNode(nodeIdABC); actions2 = await gestaltGraph.getGestaltActionsByIdentity( identityInfo.providerId, identityInfo.identityId, @@ -1053,9 +1088,9 @@ describe('GestaltGraph', () => { expect(actions2).not.toBeUndefined(); expect(actions1).toEqual(actions2); expect(actions1).toEqual({}); - await gestaltGraph.setGestaltActionByNode(nodeInfoLinked.id, 'scan'); - await gestaltGraph.setGestaltActionByNode(nodeInfoLinked.id, 'notify'); - actions1 = await gestaltGraph.getGestaltActionsByNode(nodeInfoLinked.id); + await gestaltGraph.setGestaltActionByNode(nodeIdABC, 'scan'); + await gestaltGraph.setGestaltActionByNode(nodeIdABC, 'notify'); + actions1 = await gestaltGraph.getGestaltActionsByNode(nodeIdABC); actions2 = await gestaltGraph.getGestaltActionsByIdentity( identityInfo.providerId, identityInfo.identityId, @@ -1081,7 +1116,7 @@ describe('GestaltGraph', () => { const nodeInfo1Chain: ChainData = {}; nodeInfo1Chain['A'] = nodeClaimAbcToDee; const nodeInfo1: NodeInfo = { - id: 'abc' as NodeId, + id: nodeIdABCEncoded, chain: nodeInfo1Chain, }; // NodeInfo on node 'dee'. Contains claims: @@ -1089,33 +1124,33 @@ describe('GestaltGraph', () => { const nodeInfo2Chain: ChainData = {}; nodeInfo2Chain['A'] = nodeClaimDeeToAbc; const nodeInfo2: NodeInfo = { - id: 'dee' as NodeId, + id: nodeIdDEEEncoded, chain: nodeInfo2Chain, }; await gestaltGraph.linkNodeAndNode(nodeInfo1, nodeInfo2); - await gestaltGraph.setGestaltActionByNode(nodeInfo1.id, 'scan'); - await gestaltGraph.setGestaltActionByNode(nodeInfo1.id, 'notify'); + await gestaltGraph.setGestaltActionByNode(nodeIdABC, 'scan'); + await gestaltGraph.setGestaltActionByNode(nodeIdABC, 'notify'); let nodePerms; nodePerms = await acl.getNodePerms(); expect(Object.keys(nodePerms)).toHaveLength(1); - await gestaltGraph.unlinkNodeAndNode(nodeInfo1.id, nodeInfo2.id); + await gestaltGraph.unlinkNodeAndNode(nodeIdABC, nodeIdDEE); let actions1, actions2; let perm1, perm2; - actions1 = await gestaltGraph.getGestaltActionsByNode(nodeInfo1.id); - actions2 = await gestaltGraph.getGestaltActionsByNode(nodeInfo2.id); + actions1 = await gestaltGraph.getGestaltActionsByNode(nodeIdABC); + actions2 = await gestaltGraph.getGestaltActionsByNode(nodeIdDEE); expect(actions1).toEqual({ scan: null, notify: null }); expect(actions2).toEqual({ scan: null, notify: null }); - perm1 = await acl.getNodePerm(nodeInfo1.id); - perm2 = await acl.getNodePerm(nodeInfo2.id); + perm1 = await acl.getNodePerm(nodeIdABC); + perm2 = await acl.getNodePerm(nodeIdDEE); expect(perm1).toEqual(perm2); - await gestaltGraph.unsetGestaltActionByNode(nodeInfo1.id, 'notify'); - await gestaltGraph.unsetGestaltActionByNode(nodeInfo2.id, 'scan'); - actions1 = await gestaltGraph.getGestaltActionsByNode(nodeInfo1.id); - actions2 = await gestaltGraph.getGestaltActionsByNode(nodeInfo2.id); + await gestaltGraph.unsetGestaltActionByNode(nodeIdABC, 'notify'); + await gestaltGraph.unsetGestaltActionByNode(nodeIdDEE, 'scan'); + actions1 = await gestaltGraph.getGestaltActionsByNode(nodeIdABC); + actions2 = await gestaltGraph.getGestaltActionsByNode(nodeIdDEE); expect(actions1).toEqual({ scan: null }); expect(actions2).toEqual({ notify: null }); - perm1 = await acl.getNodePerm(nodeInfo1.id); - perm2 = await acl.getNodePerm(nodeInfo2.id); + perm1 = await acl.getNodePerm(nodeIdABC); + perm2 = await acl.getNodePerm(nodeIdDEE); expect(perm1).not.toEqual(perm2); nodePerms = await acl.getNodePerms(); expect(Object.keys(nodePerms)).toHaveLength(2); @@ -1133,7 +1168,7 @@ describe('GestaltGraph', () => { const nodeInfo1Chain: ChainData = {}; nodeInfo1Chain['A'] = identityClaimAbcToGH; const nodeInfo: NodeInfo = { - id: 'abc' as NodeId, + id: nodeIdABCEncoded, chain: nodeInfo1Chain, }; // IdentityInfo on identity from GitHub. Contains claims: @@ -1160,11 +1195,11 @@ describe('GestaltGraph', () => { nodePerms = await acl.getNodePerms(); expect(Object.keys(nodePerms)).toHaveLength(1); await gestaltGraph.unlinkNodeAndIdentity( - nodeInfo.id, + nodeIdABC, identityInfo.providerId, identityInfo.identityId, ); - const actions1 = await gestaltGraph.getGestaltActionsByNode(nodeInfo.id); + const actions1 = await gestaltGraph.getGestaltActionsByNode(nodeIdABC); const actions2 = await gestaltGraph.getGestaltActionsByIdentity( identityInfo.providerId, identityInfo.identityId, @@ -1188,7 +1223,7 @@ describe('GestaltGraph', () => { const nodeInfo1Chain: ChainData = {}; nodeInfo1Chain['A'] = nodeClaimAbcToDee; const nodeInfo1: NodeInfo = { - id: 'abc' as NodeId, + id: nodeIdABCEncoded, chain: nodeInfo1Chain, }; // NodeInfo on node 'dee'. Contains claims: @@ -1196,23 +1231,22 @@ describe('GestaltGraph', () => { const nodeInfo2Chain: ChainData = {}; nodeInfo2Chain['A'] = nodeClaimDeeToAbc; const nodeInfo2: NodeInfo = { - id: 'dee' as NodeId, + id: nodeIdDEEEncoded, chain: nodeInfo2Chain, }; await gestaltGraph.linkNodeAndNode(nodeInfo1, nodeInfo2); - await gestaltGraph.setGestaltActionByNode(nodeInfo1.id, 'scan'); - await gestaltGraph.setGestaltActionByNode(nodeInfo1.id, 'notify'); - let nodePerms; - nodePerms = await acl.getNodePerms(); + await gestaltGraph.setGestaltActionByNode(nodeIdABC, 'scan'); + await gestaltGraph.setGestaltActionByNode(nodeIdABC, 'notify'); + let nodePerms = await acl.getNodePerms(); expect(Object.keys(nodePerms)).toHaveLength(1); - await gestaltGraph.unsetNode(nodeInfo1.id); + await gestaltGraph.unsetNode(nodeIdABC); // It's still 1 node perm // its just that node 1 is eliminated nodePerms = await acl.getNodePerms(); expect(Object.keys(nodePerms)).toHaveLength(1); - expect(nodePerms[0]).not.toHaveProperty(nodeInfo1.id); - expect(nodePerms[0]).toHaveProperty(nodeInfo2.id); - await gestaltGraph.unsetNode(nodeInfo2.id); + expect(nodePerms[0]).not.toHaveProperty(nodeIdABC.toString()); + expect(nodePerms[0]).toHaveProperty(nodeIdDEE.toString()); + await gestaltGraph.unsetNode(nodeIdDEE); nodePerms = await acl.getNodePerms(); expect(Object.keys(nodePerms)).toHaveLength(0); await gestaltGraph.stop(); diff --git a/tests/grpc/GRPCClient.test.ts b/tests/grpc/GRPCClient.test.ts index 4fc3e763c..194f79294 100644 --- a/tests/grpc/GRPCClient.test.ts +++ b/tests/grpc/GRPCClient.test.ts @@ -17,6 +17,7 @@ import { errors as grpcErrors } from '@/grpc'; import * as clientUtils from '@/client/utils'; import * as utilsPB from '@/proto/js/polykey/v1/utils/utils_pb'; import * as utils from './utils'; +import * as testUtils from '../utils'; describe('GRPCClient', () => { const logger = new Logger('GRPCClient Test', LogLevel.WARN, [ @@ -59,7 +60,9 @@ describe('GRPCClient', () => { }, }, }); - const keyManager = { getNodeId: () => 'nodeID' as NodeId } as KeyManager; // Cheeky mocking. + const keyManager = { + getNodeId: () => testUtils.generateRandomNodeId(), + } as KeyManager; // Cheeky mocking. sessionManager = await SessionManager.createSessionManager({ db, keyManager, diff --git a/tests/grpc/utils/utils.ts b/tests/grpc/utils/utils.ts index 9aa2bff36..3cd55e61b 100644 --- a/tests/grpc/utils/utils.ts +++ b/tests/grpc/utils/utils.ts @@ -8,6 +8,7 @@ import { TestServiceService, TestServiceClient, } from '@/proto/js/polykey/v1/test_service_grpc_pb'; +import { utils as nodesUtils } from '@/nodes'; import createTestService from './testService'; async function openTestServer( @@ -57,7 +58,7 @@ async function openTestClientSecure( ): Promise { const clientOptions = { // Prevents complaints with having an ip address as the server name - 'grpc.ssl_target_name_override': nodeId, + 'grpc.ssl_target_name_override': nodesUtils.encodeNodeId(nodeId), }; const clientCredentials = grpcUtils.clientSecureCredentials( keyPrivatePem, diff --git a/tests/identities/IdentitiesManager.test.ts b/tests/identities/IdentitiesManager.test.ts index 497f6592c..d1933b658 100644 --- a/tests/identities/IdentitiesManager.test.ts +++ b/tests/identities/IdentitiesManager.test.ts @@ -16,7 +16,9 @@ import { DB } from '@matrixai/db'; import { IdentitiesManager, providers } from '@/identities'; import * as identitiesErrors from '@/identities/errors'; import * as keysUtils from '@/keys/utils'; +import { utils as nodesUtils } from '@/nodes'; import TestProvider from './TestProvider'; +import * as testUtils from '../utils'; describe('IdentitiesManager', () => { const logger = new Logger('IdentitiesManager Test', LogLevel.WARN, [ @@ -215,12 +217,14 @@ describe('IdentitiesManager', () => { expect(identityDatas).toHaveLength(1); expect(identityDatas).not.toContainEqual(identityData); // Now publish a claim + const nodeIdSome = testUtils.generateRandomNodeId(); + const nodeIdSomeEncoded = nodesUtils.encodeNodeId(nodeIdSome); const signatures: Record = {}; - signatures['somenode' as NodeId] = { + signatures[nodeIdSome] = { signature: 'examplesignature', header: { alg: 'RS256', - kid: 'somenode' as NodeId, + kid: nodeIdSomeEncoded, }, }; const rawClaim: Claim = { @@ -230,7 +234,7 @@ describe('IdentitiesManager', () => { iat: Math.floor(Date.now() / 1000), data: { type: 'identity', - node: 'somenode' as NodeId, + node: nodesUtils.encodeNodeId(nodeIdSome), provider: testProvider.id, identity: identityId, } as ClaimData, diff --git a/tests/keys/KeyManager.test.ts b/tests/keys/KeyManager.test.ts index 7dafd65c4..773b5d3eb 100644 --- a/tests/keys/KeyManager.test.ts +++ b/tests/keys/KeyManager.test.ts @@ -124,7 +124,7 @@ describe('KeyManager', () => { recoveryCode, }); expect(await keyManager.checkPassword('newpassword')).toBe(true); - expect(keyManager.getNodeId()).toBe(nodeId); + expect(keyManager.getNodeId()).toStrictEqual(nodeId); await keyManager.stop(); }, global.defaultTimeout * 2, @@ -157,7 +157,7 @@ describe('KeyManager', () => { expect(keyManager2.getRecoveryCode()).toBe(recoveryCode); const nodeId2 = keyManager2.getNodeId(); await keyManager2.stop(); - expect(nodeId1).toBe(nodeId2); + expect(nodeId1).toStrictEqual(nodeId2); }, global.defaultTimeout * 2, ); diff --git a/tests/keys/utils.test.ts b/tests/keys/utils.test.ts index 11b2a1563..7a2f728db 100644 --- a/tests/keys/utils.test.ts +++ b/tests/keys/utils.test.ts @@ -91,9 +91,9 @@ describe('utils', () => { 256, recoveryCode, ); - const nodeId1 = keysUtils.publicKeyToFingerprint(keyPair1.publicKey); - const nodeId2 = keysUtils.publicKeyToFingerprint(keyPair2.publicKey); - expect(nodeId1).toBe(nodeId2); + const nodeId1 = keysUtils.publicKeyToNodeId(keyPair1.publicKey); + const nodeId2 = keysUtils.publicKeyToNodeId(keyPair2.publicKey); + expect(nodeId1).toStrictEqual(nodeId2); }, global.defaultTimeout * 2, ); diff --git a/tests/network/ForwardProxy.test.ts b/tests/network/ForwardProxy.test.ts index a8dd2fb5c..a54c9558c 100644 --- a/tests/network/ForwardProxy.test.ts +++ b/tests/network/ForwardProxy.test.ts @@ -1,7 +1,6 @@ import type { Socket } from 'net'; import type { KeyPairPem } from '@/keys/types'; import type { Host, Port } from '@/network/types'; -import type { NodeId } from '@/nodes/types'; import http from 'http'; import net from 'net'; import tls from 'tls'; @@ -14,6 +13,7 @@ import { } from '@/network'; import * as keysUtils from '@/keys/utils'; import { promisify, promise, timerStart, timerStop, poll } from '@/utils'; +import { utils as nodesUtils } from '@/nodes'; import * as testUtils from '../utils'; /** @@ -58,6 +58,11 @@ describe(ForwardProxy.name, () => { const logger = new Logger(`${ForwardProxy.name} test`, LogLevel.WARN, [ new StreamHandler(), ]); + const nodeIdABC = testUtils.generateRandomNodeId(); + const nodeIdABCEncoded = nodesUtils.encodeNodeId(nodeIdABC); + const nodeIdSome = testUtils.generateRandomNodeId(); + const nodeIdSomeEncoded = nodesUtils.encodeNodeId(nodeIdSome); + const nodeIdRandom = testUtils.generateRandomNodeId(); const authToken = 'abc123'; let keyPairPem: KeyPairPem; let certPem: string; @@ -137,7 +142,7 @@ describe(ForwardProxy.name, () => { fwdProxy.getProxyHost(), fwdProxy.getProxyPort(), 'incorrect auth token', - `127.0.0.1:80?nodeId=${encodeURIComponent('SOMENODEID')}`, + `127.0.0.1:80?nodeId=${encodeURIComponent(nodeIdSomeEncoded)}`, ), ).rejects.toThrow('407'); // No node id @@ -155,7 +160,7 @@ describe(ForwardProxy.name, () => { fwdProxy.getProxyHost(), fwdProxy.getProxyPort(), authToken, - `?nodeId=${encodeURIComponent('SOMENODEID')}`, + `?nodeId=${encodeURIComponent(nodeIdSomeEncoded)}`, ), ).rejects.toThrow('400'); await fwdProxy.stop(); @@ -173,14 +178,14 @@ describe(ForwardProxy.name, () => { }); // Cannot open connection to port 0 await expect(() => - fwdProxy.openConnection('abc' as NodeId, '127.0.0.1' as Host, 0 as Port), + fwdProxy.openConnection(nodeIdABC, '127.0.0.1' as Host, 0 as Port), ).rejects.toThrow(networkErrors.ErrorConnectionStart); await expect(() => httpConnect( fwdProxy.getProxyHost(), fwdProxy.getProxyPort(), authToken, - `127.0.0.1:0?nodeId=${encodeURIComponent('abc')}`, + `127.0.0.1:0?nodeId=${encodeURIComponent(nodeIdABCEncoded)}`, ), ).rejects.toThrow('502'); await fwdProxy.stop(); @@ -215,7 +220,7 @@ describe(ForwardProxy.name, () => { const utpSocketHangPort = utpSocketHang.address().port; await expect(() => fwdProxy.openConnection( - 'abc' as NodeId, + nodeIdABC, '127.0.0.1' as Host, utpSocketHangPort as Port, ), @@ -225,7 +230,7 @@ describe(ForwardProxy.name, () => { const timer = timerStart(2000); await expect(() => fwdProxy.openConnection( - 'abc' as NodeId, + nodeIdABC, '127.0.0.1' as Host, utpSocketHangPort as Port, timer, @@ -238,7 +243,9 @@ describe(ForwardProxy.name, () => { fwdProxy.getProxyHost(), fwdProxy.getProxyPort(), authToken, - `127.0.0.1:${utpSocketHangPort}?nodeId=${encodeURIComponent('abc')}`, + `127.0.0.1:${utpSocketHangPort}?nodeId=${encodeURIComponent( + nodeIdABCEncoded, + )}`, ), ).rejects.toThrow('504'); expect(recievedCount).toBe(3); @@ -272,7 +279,7 @@ describe(ForwardProxy.name, () => { const utpSocketEndPort = utpSocketEnd.address().port; await expect(() => fwdProxy.openConnection( - 'abc' as NodeId, + nodeIdABC, '127.0.0.1' as Host, utpSocketEndPort as Port, ), @@ -281,7 +288,7 @@ describe(ForwardProxy.name, () => { // The actual error is UTP_ECONNRESET to be precise await expect(() => fwdProxy.openConnection( - 'abc' as NodeId, + nodeIdABC, '127.0.0.1' as Host, utpSocketEndPort as Port, ), @@ -293,7 +300,9 @@ describe(ForwardProxy.name, () => { fwdProxy.getProxyHost(), fwdProxy.getProxyPort(), authToken, - `127.0.0.1:${utpSocketEndPort}?nodeId=${encodeURIComponent('abc')}`, + `127.0.0.1:${utpSocketEndPort}?nodeId=${encodeURIComponent( + nodeIdABCEncoded, + )}`, ), ).rejects.toThrow('502'); expect(recievedCount).toBe(3); @@ -381,7 +390,7 @@ describe(ForwardProxy.name, () => { // This is a TLS handshake failure await expect(() => fwdProxy.openConnection( - 'somerandomnodeid' as NodeId, + nodeIdRandom, utpSocketHost as Host, utpSocketPort as Port, ), @@ -489,7 +498,7 @@ describe(ForwardProxy.name, () => { fwdProxy.getProxyPort(), authToken, `${utpSocketHost}:${utpSocketPort}?nodeId=${encodeURIComponent( - 'somerandomnodeid', + nodeIdSomeEncoded, )}`, ), ).rejects.toThrow('502'); @@ -603,7 +612,7 @@ describe(ForwardProxy.name, () => { expect(fwdProxy.getConnectionCount()).toBe(0); await expect(() => fwdProxy.openConnection( - 'somerandomnodeid' as NodeId, + nodeIdRandom, utpSocketHost as Host, utpSocketPort as Port, ), @@ -721,7 +730,7 @@ describe(ForwardProxy.name, () => { fwdProxy.getProxyPort(), authToken, `${utpSocketHost}:${utpSocketPort}?nodeId=${encodeURIComponent( - 'somerandomnodeid', + nodeIdSomeEncoded, )}`, ), ).rejects.toThrow('526'); @@ -1026,6 +1035,7 @@ describe(ForwardProxy.name, () => { ); const serverCertPem = keysUtils.certToPem(serverCert); const serverNodeId = networkUtils.certNodeId(serverCert); + const serverNodeIdEncoded = nodesUtils.encodeNodeId(serverNodeId); const fwdProxy = new ForwardProxy({ authToken, logger: logger.getChild( @@ -1114,7 +1124,7 @@ describe(ForwardProxy.name, () => { fwdProxy.getProxyPort(), authToken, `${utpSocketHost}:${utpSocketPort}?nodeId=${encodeURIComponent( - serverNodeId, + serverNodeIdEncoded, )}`, ); await expect(remoteReadyP).resolves.toBeUndefined(); @@ -1172,6 +1182,7 @@ describe(ForwardProxy.name, () => { ); const serverCertPem = keysUtils.certToPem(serverCert); const serverNodeId = networkUtils.certNodeId(serverCert); + const serverNodeIdEncoded = nodesUtils.encodeNodeId(serverNodeId); const fwdProxy = new ForwardProxy({ authToken, logger: logger.getChild( @@ -1263,7 +1274,7 @@ describe(ForwardProxy.name, () => { fwdProxy.getProxyPort(), authToken, `${utpSocketHost}:${utpSocketPort}?nodeId=${encodeURIComponent( - serverNodeId, + serverNodeIdEncoded, )}`, ); await expect(remoteReadyP).resolves.toBeUndefined(); @@ -1341,6 +1352,7 @@ describe(ForwardProxy.name, () => { ); const serverCertPem = keysUtils.certToPem(serverCert); const serverNodeId = networkUtils.certNodeId(serverCert); + const serverNodeIdEncoded = nodesUtils.encodeNodeId(serverNodeId); const fwdProxy = new ForwardProxy({ authToken, logger: logger.getChild( @@ -1429,7 +1441,7 @@ describe(ForwardProxy.name, () => { fwdProxy.getProxyPort(), authToken, `${utpSocketHost}:${utpSocketPort}?nodeId=${encodeURIComponent( - serverNodeId, + serverNodeIdEncoded, )}`, ); await expect(remoteReadyP).resolves.toBeUndefined(); @@ -1497,6 +1509,7 @@ describe(ForwardProxy.name, () => { ); const serverCertPem = keysUtils.certToPem(serverCert); const serverNodeId = networkUtils.certNodeId(serverCert); + const serverNodeIdEncoded = nodesUtils.encodeNodeId(serverNodeId); const fwdProxy = new ForwardProxy({ authToken, logger, @@ -1588,7 +1601,7 @@ describe(ForwardProxy.name, () => { fwdProxy.getProxyPort(), authToken, `${utpSocketHost}:${utpSocketPort}?nodeId=${encodeURIComponent( - serverNodeId, + serverNodeIdEncoded, )}`, ); expect(clientSocket).toBeInstanceOf(net.Socket); @@ -1740,6 +1753,7 @@ describe(ForwardProxy.name, () => { ); const serverCertPem = keysUtils.certToPem(serverCert); const serverNodeId = networkUtils.certNodeId(serverCert); + const serverNodeIdEncoded = nodesUtils.encodeNodeId(serverNodeId); const fwdProxy = new ForwardProxy({ authToken, connKeepAliveTimeoutTime: 1000, @@ -1828,7 +1842,7 @@ describe(ForwardProxy.name, () => { fwdProxy.getProxyPort(), authToken, `${utpSocketHost}:${utpSocketPort}?nodeId=${encodeURIComponent( - serverNodeId, + serverNodeIdEncoded, )}`, ); await expect(remoteReadyP).resolves.toBeUndefined(); diff --git a/tests/nodes/NodeConnection.test.ts b/tests/nodes/NodeConnection.test.ts index 35aac2fb9..5b98a7bf6 100644 --- a/tests/nodes/NodeConnection.test.ts +++ b/tests/nodes/NodeConnection.test.ts @@ -6,6 +6,7 @@ import fs from 'fs'; import Logger, { StreamHandler, LogLevel } from '@matrixai/logger'; import { DB } from '@matrixai/db'; +import { IdInternal } from '@matrixai/id'; import { ForwardProxy, ReverseProxy } from '@/network'; import { NodeConnection, NodeManager } from '@/nodes'; import { VaultManager } from '@/vaults'; @@ -20,9 +21,9 @@ import { NotificationsManager } from '@/notifications'; import * as nodesUtils from '@/nodes/utils'; import * as nodesErrors from '@/nodes/errors'; import * as networkErrors from '@/network/errors'; -import { makeNodeId } from '@/nodes/utils'; import { poll } from '@/utils'; import * as nodesTestUtils from './utils'; +import * as testUtils from '../utils'; // Mocks. jest.mock('@/keys/utils', () => ({ @@ -34,7 +35,7 @@ jest.mock('@/keys/utils', () => ({ describe('NodeConnection', () => { const password = 'password'; const node: NodeInfo = { - id: 'NodeId' as NodeId, + id: nodesUtils.encodeNodeId(testUtils.generateRandomNodeId()), chain: {}, }; const logger = new Logger('NodeConnection Test', LogLevel.WARN, [ @@ -63,7 +64,7 @@ describe('NodeConnection', () => { let agentServer: GRPCServer; - const nodeIdGenerator = (number: number) => { + const nodeIdGenerator = (number: number): NodeId => { const idArray = new Uint8Array([ 223, 24, @@ -98,7 +99,7 @@ describe('NodeConnection', () => { 77, number, ]); - return makeNodeId(idArray); + return IdInternal.fromBuffer(Buffer.from(idArray)); }; // Meep IPs unique. Ideally we'd use the generated IP and port. But this is good for now. @@ -292,6 +293,7 @@ describe('NodeConnection', () => { targetPort: targetPort, forwardProxy: clientFwdProxy, keyManager: clientKeyManager, + connTimeout: 1000, logger: logger, }); await expect(nodeConnection.destroy()).rejects.toThrow( @@ -308,7 +310,9 @@ describe('NodeConnection', () => { nodeConnection.getRootCertChain(); }).toThrow(nodesErrors.ErrorNodeConnectionNotRunning); await expect(async () => { - await nodeConnection.getClosestNodes('abc' as NodeId); + await nodeConnection.getClosestNodes( + IdInternal.fromString('abc'), + ); }).rejects.toThrow(nodesErrors.ErrorNodeConnectionNotRunning); // Explicitly close the connection such that there's no interference in next test await serverRevProxy.closeConnection(sourceHost, sourcePort); @@ -330,6 +334,7 @@ describe('NodeConnection', () => { }, (e) => { if (e instanceof networkErrors.ErrorConnectionNotComposed) return false; + if (e instanceof networkErrors.ErrorConnectionNotRunning) return false; return true; }, ); @@ -351,7 +356,7 @@ describe('NodeConnection', () => { targetNodeId: targetNodeId, targetHost: '128.0.0.1' as Host, targetPort: 12345 as Port, - connTimeout: 300, + connTimeout: 1000, forwardProxy: clientFwdProxy, keyManager: clientKeyManager, logger: logger, @@ -420,7 +425,7 @@ describe('NodeConnection', () => { // const vault5 = await serverVaultManager.createVault('Vault5' as VaultName); await serverGestaltGraph.setNode({ - id: sourceNodeId, + id: nodesUtils.encodeNodeId(sourceNodeId), chain: {}, }); diff --git a/tests/nodes/NodeGraph.test.ts b/tests/nodes/NodeGraph.test.ts index c9f9ac4ad..d36e8cbbb 100644 --- a/tests/nodes/NodeGraph.test.ts +++ b/tests/nodes/NodeGraph.test.ts @@ -6,12 +6,12 @@ import path from 'path'; import fs from 'fs'; import Logger, { LogLevel, StreamHandler } from '@matrixai/logger'; import { DB } from '@matrixai/db'; +import { IdInternal } from '@matrixai/id'; import { NodeManager, errors as nodesErrors } from '@/nodes'; import { KeyManager, utils as keysUtils } from '@/keys'; import { ForwardProxy, ReverseProxy } from '@/network'; import * as nodesUtils from '@/nodes/utils'; import { Sigchain } from '@/sigchain'; -import { makeNodeId } from '@/nodes/utils'; import * as nodesTestUtils from './utils'; // Mocks. @@ -27,27 +27,21 @@ describe('NodeGraph', () => { let nodeGraph: NodeGraph; let nodeId: NodeId; - const nodeId1 = makeNodeId( - new Uint8Array([ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 5, - ]), - ); - const nodeId2 = makeNodeId( - new Uint8Array([ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 8, - ]), - ); - const nodeId3 = makeNodeId( - new Uint8Array([ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 124, - ]), - ); + const nodeId1 = IdInternal.create([ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 5, + ]); + const nodeId2 = IdInternal.create([ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 8, + ]); + const nodeId3 = IdInternal.create([ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 124, + ]); // Const nodeId2 = makeNodeId('vrcacp9vsb4ht25hds6s4lpp2abfaso0mptcfnh499n35vfcn2gkg'); // const nodeId3 = makeNodeId('v359vgrgmqf1r5g4fvisiddjknjko6bmm4qv7646jr7fi9enbfuug'); - const dummyNode = makeNodeId( + const dummyNode = nodesUtils.decodeNodeId( 'vi3et1hrpv2m2lrplcm7cu913kr45v51cak54vm68anlbvuf83ra0', ); @@ -63,7 +57,7 @@ describe('NodeGraph', () => { let sigchain: Sigchain; const nodeIdGenerator = (number: number) => { - const idArray = new Uint8Array([ + const idArray = [ 223, 24, 34, @@ -96,8 +90,8 @@ describe('NodeGraph', () => { 23, 77, number, - ]); - return makeNodeId(idArray); + ]; + return IdInternal.create(idArray); }; beforeAll(async () => { @@ -582,7 +576,7 @@ describe('NodeGraph', () => { let nodeCount = 0; for (const b of newBuckets) { for (const n of Object.keys(b)) { - const nodeId = makeNodeId(n); + const nodeId = IdInternal.fromString(n); // Check that it was a node in the original DB expect(initialNodes[nodeId]).toBeDefined(); // Check it's in the correct bucket diff --git a/tests/nodes/NodeManager.test.ts b/tests/nodes/NodeManager.test.ts index c91123f60..6f70c3e07 100644 --- a/tests/nodes/NodeManager.test.ts +++ b/tests/nodes/NodeManager.test.ts @@ -7,14 +7,15 @@ import path from 'path'; import fs from 'fs'; import Logger, { LogLevel, StreamHandler } from '@matrixai/logger'; import { DB } from '@matrixai/db'; +import { IdInternal } from '@matrixai/id'; import { PolykeyAgent } from '@'; import { KeyManager, utils as keysUtils } from '@/keys'; import { NodeManager, errors as nodesErrors } from '@/nodes'; import { ForwardProxy, ReverseProxy } from '@/network'; import { Sigchain } from '@/sigchain'; import { utils as claimsUtils } from '@/claims'; -import { makeNodeId } from '@/nodes/utils'; import { sleep } from '@/utils'; +import { utils as nodesUtils } from '@/nodes'; // Mocks. jest.mock('@/keys/utils', () => ({ @@ -42,13 +43,13 @@ describe('NodeManager', () => { const serverHost = '::1' as Host; const serverPort = 1 as Port; - const nodeId1 = makeNodeId( + const nodeId1 = nodesUtils.decodeNodeId( 'vrsc24a1er424epq77dtoveo93meij0pc8ig4uvs9jbeld78n9nl0', ); - const nodeId2 = makeNodeId( + const nodeId2 = nodesUtils.decodeNodeId( 'vrcacp9vsb4ht25hds6s4lpp2abfaso0mptcfnh499n35vfcn2gkg', ); - const dummyNode = makeNodeId( + const dummyNode = nodesUtils.decodeNodeId( 'vi3et1hrpv2m2lrplcm7cu913kr45v51cak54vm68anlbvuf83ra0', ); @@ -193,7 +194,9 @@ describe('NodeManager', () => { expect(initialConnLock).toBeUndefined(); await nodeManager.getConnectionToNode(targetNodeId); // @ts-ignore get connection + lock from protected NodeConnectionMap - const finalConnLock = nodeManager.connections.get(targetNodeId); + const finalConnLock = nodeManager.connections.get( + targetNodeId.toString(), + ); // Check entry is in map and lock is released expect(finalConnLock).toBeDefined(); expect(finalConnLock?.lock.isLocked()).toBeFalsy(); @@ -228,7 +231,9 @@ describe('NodeManager', () => { // @ts-ignore accessing protected NodeConnectionMap expect(nodeManager.connections.size).toBe(1); // @ts-ignore get connection + lock from protected NodeConnectionMap - const finalConnLock = nodeManager.connections.get(targetNodeId); + const finalConnLock = nodeManager.connections.get( + targetNodeId.toString(), + ); // Check entry is in map and lock is released expect(finalConnLock).toBeDefined(); expect(finalConnLock?.lock.isLocked()).toBeFalsy(); @@ -516,7 +521,9 @@ describe('NodeManager', () => { }, signatures: expect.any(Object), }); - const signatureNodeIds = Object.keys(decoded.signatures) as NodeId[]; + const signatureNodeIds = Object.keys(decoded.signatures).map( + (idString) => IdInternal.fromString(idString), + ); expect(signatureNodeIds.length).toBe(2); // Verify the 2 signatures expect(signatureNodeIds).toContain(xNodeId); @@ -550,7 +557,9 @@ describe('NodeManager', () => { }, signatures: expect.any(Object), }); - const signatureNodeIds = Object.keys(decoded.signatures) as NodeId[]; + const signatureNodeIds = Object.keys(decoded.signatures).map( + (idString) => IdInternal.fromString(idString), + ); expect(signatureNodeIds.length).toBe(2); // Verify the 2 signatures expect(signatureNodeIds).toContain(xNodeId); diff --git a/tests/nodes/utils.test.ts b/tests/nodes/utils.test.ts index 66e786632..b596fcbed 100644 --- a/tests/nodes/utils.test.ts +++ b/tests/nodes/utils.test.ts @@ -1,84 +1,57 @@ import type { NodeId } from '@/nodes/types'; -import * as nodesUtils from '@/nodes/utils'; -import { isNodeId, makeNodeId } from '@/nodes/utils'; +import { IdInternal } from '@matrixai/id'; +import { utils as nodesUtils } from '@/nodes'; describe('Nodes utils', () => { test('basic distance calculation', async () => { - const nodeId1 = makeNodeId( - new Uint8Array([ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 5, - ]), - ); - const nodeId2 = makeNodeId( - new Uint8Array([ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 23, 0, - 0, 0, 0, 0, 0, 0, 0, 1, - ]), - ); + const nodeId1 = IdInternal.create([ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 5, + ]); + const nodeId2 = IdInternal.create([ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 23, 0, + 0, 0, 0, 0, 0, 0, 0, 1, + ]); + const distance = nodesUtils.calculateDistance(nodeId1, nodeId2); expect(distance).toEqual(316912758671486456376015716356n); }); test('calculates correct first bucket (bucket 0)', async () => { // "1" XOR "0" = distance of 1 // Therefore, bucket 0 - const nodeId1 = makeNodeId( - new Uint8Array([ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1, - ]), - ); - const nodeId2 = makeNodeId( - new Uint8Array([ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - ]), - ); + const nodeId1 = IdInternal.create([ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, + ]); + const nodeId2 = IdInternal.create([ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + ]); const bucketIndex = nodesUtils.calculateBucketIndex(nodeId1, nodeId2, 256); expect(bucketIndex).toBe(0); }); test('calculates correct arbitrary bucket (bucket 63)', async () => { - const nodeId1 = makeNodeId( - new Uint8Array([ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 255, 0, 0, 0, 0, 0, 0, 0, - ]), - ); - const nodeId2 = makeNodeId( - new Uint8Array([ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - ]), - ); + const nodeId1 = IdInternal.create([ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 255, 0, 0, 0, 0, 0, 0, 0, + ]); + const nodeId2 = IdInternal.create([ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + ]); const bucketIndex = nodesUtils.calculateBucketIndex(nodeId1, nodeId2, 256); expect(bucketIndex).toBe(63); }); test('calculates correct last bucket (bucket 255)', async () => { - const nodeId1 = makeNodeId( - new Uint8Array([ - 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - ]), - ); - const nodeId2 = makeNodeId( - new Uint8Array([ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - ]), - ); + const nodeId1 = IdInternal.create([ + 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ]); + const nodeId2 = IdInternal.create([ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + ]); const bucketIndex = nodesUtils.calculateBucketIndex(nodeId1, nodeId2, 256); expect(bucketIndex).toBe(255); }); - test('testing type guard.', async () => { - const invalidNodeId = 'invalid!!'; - const validNodeIdString = - 'vh3jik6l5ntqj9er9t3n1330e46pmh27btroh3b8hsc5i9qt71di0'; - const validNodeId = validNodeIdString as NodeId; - expect(isNodeId(validNodeIdString)).toBeTruthy(); - expect(isNodeId(makeNodeId(validNodeIdString))).toBeTruthy(); - expect(isNodeId(validNodeId)).toBeTruthy(); - expect(isNodeId(invalidNodeId)).toBeFalsy(); - expect(isNodeId(invalidNodeId as NodeId)).toBeFalsy(); - // Expect(makeNodeId(invalidNodeId)).toThrow(); - }); }); diff --git a/tests/nodes/utils.ts b/tests/nodes/utils.ts index 088d6801a..d535cd116 100644 --- a/tests/nodes/utils.ts +++ b/tests/nodes/utils.ts @@ -1,9 +1,7 @@ import type { NodeId, NodeAddress } from '@/nodes/types'; import type { PolykeyAgent } from '@'; -import * as nodesUtils from '@/nodes/utils'; -import { makeNodeId } from '@/nodes/utils'; -import { fromMultibase } from '@/GenericIdTypes'; +import { IdInternal } from '@matrixai/id'; /** * Generates a node ID that, according to Kademlia, will be placed into 'nodeId's @@ -14,7 +12,7 @@ import { fromMultibase } from '@/GenericIdTypes'; */ function generateNodeIdForBucket(nodeId: NodeId, bucketIndex: number): NodeId { const lowerBoundDistance = BigInt(2) ** BigInt(bucketIndex); - const bufferId = nodesUtils.nodeIdToU8(nodeId); + const bufferId = Buffer.from(nodeId.toBuffer()); // Console.log(bufferId); const bufferDistance = bigIntToBuffer(lowerBoundDistance); // Console.log(bufferDistance); @@ -25,7 +23,7 @@ function generateNodeIdForBucket(nodeId: NodeId, bucketIndex: number): NodeId { // Reverse the buffers such that we XOR from right to left bufferId.reverse(); bufferDistance.reverse(); - const newIdArray = new Uint8Array(max); + const newIdArray = Buffer.alloc(max); // XOR the 'rightmost' bytes first for (let i = 0; i < bufferId.length && i < bufferDistance.length; i++) { @@ -43,8 +41,7 @@ function generateNodeIdForBucket(nodeId: NodeId, bucketIndex: number): NodeId { // Reverse the XORed array back to normal newIdArray.reverse(); // Convert to an ASCII string - // console.log(newIdArray); - return makeNodeId(newIdArray); + return IdInternal.fromBuffer(newIdArray); } /** @@ -57,10 +54,10 @@ function generateNodeIdForBucket(nodeId: NodeId, bucketIndex: number): NodeId { * nodes appearing in larger-indexed buckets. */ function incrementNodeId(nodeId: NodeId): NodeId { - const nodeIdArray = fromMultibase(nodeId)!; + const nodeIdArray = Buffer.from(nodeId.toBuffer()); const lastCharIndex = nodeIdArray.length - 1; nodeIdArray[lastCharIndex] = nodeIdArray[lastCharIndex] + 1; - return makeNodeId(nodeIdArray); + return IdInternal.fromBuffer(nodeIdArray); } /** diff --git a/tests/notifications/NotificationsManager.test.ts b/tests/notifications/NotificationsManager.test.ts index 258b41319..b31b1e2f6 100644 --- a/tests/notifications/NotificationsManager.test.ts +++ b/tests/notifications/NotificationsManager.test.ts @@ -22,6 +22,8 @@ import { AgentServiceService, createAgentService } from '@/agent'; import * as networkUtils from '@/network/utils'; import { generateVaultId } from '@/vaults/utils'; +import { utils as nodesUtils } from '@/nodes'; +import * as testUtils from '../utils'; // Mocks. jest.mock('@/keys/utils', () => ({ @@ -33,7 +35,7 @@ jest.mock('@/keys/utils', () => ({ describe('NotificationsManager', () => { const password = 'password'; const node: NodeInfo = { - id: 'NodeId' as NodeId, + id: nodesUtils.encodeNodeId(testUtils.generateRandomNodeId()), chain: {}, }; const logger = new Logger('NotificationsManager Test', LogLevel.WARN, [ @@ -359,7 +361,7 @@ describe('NotificationsManager', () => { ); const notifs = await receiverNotificationsManager.readNotifications(); expect(notifs[0].data).toEqual(notificationData); - expect(notifs[0].senderId).toEqual(senderNodeId); + expect(notifs[0].senderId).toEqual(nodesUtils.encodeNodeId(senderNodeId)); expect(notifs[0].isRead).toBeTruthy(); await senderNotificationsManager.stop(); diff --git a/tests/notifications/utils.test.ts b/tests/notifications/utils.test.ts index 20878f8fd..5e2ba2808 100644 --- a/tests/notifications/utils.test.ts +++ b/tests/notifications/utils.test.ts @@ -1,4 +1,3 @@ -import type { NodeId } from '@/nodes/types'; import type { Notification, NotificationData } from '@/notifications/types'; import type { VaultActions, VaultName } from '@/vaults/types'; import { createPublicKey } from 'crypto'; @@ -11,9 +10,12 @@ import * as notificationsErrors from '@/notifications/errors'; import { createNotificationIdGenerator } from '@/notifications/utils'; import { sleep } from '@/utils'; import { makeVaultId } from '@/vaults/utils'; +import { utils as nodesUtils } from '@/nodes'; +import * as testUtils from '../utils'; describe('Notifications utils', () => { - const nodeId = 'SomeRandomNodeId' as NodeId; + const nodeId = testUtils.generateRandomNodeId(); + const nodeIdEncoded = nodesUtils.encodeNodeId(nodeId); const vaultId = makeVaultId( idUtils.fromString('vaultIdxxxxxxxxx'), ).toString(); @@ -49,14 +51,14 @@ describe('Notifications utils', () => { type: 'General', message: 'msg', } as NotificationData, - senderId: nodeId, + senderId: nodeIdEncoded, isRead: false, }; const gestaltInviteNotification: Notification = { data: { type: 'GestaltInvite', } as NotificationData, - senderId: nodeId, + senderId: nodeIdEncoded, isRead: false, }; const vaultShareNotification: Notification = { @@ -69,7 +71,7 @@ describe('Notifications utils', () => { pull: null, } as VaultActions, } as NotificationData, - senderId: nodeId, + senderId: nodeIdEncoded, isRead: false, }; @@ -97,7 +99,7 @@ describe('Notifications utils', () => { type: 'General', message: 'msg', }); - expect(result.payload.senderId).toEqual(nodeId); + expect(result.payload.senderId).toEqual(nodeIdEncoded); expect(result.payload.isRead).toBeFalsy(); expect(result.protectedHeader.jwk).toEqual(jwkPublicKey); @@ -105,7 +107,7 @@ describe('Notifications utils', () => { expect(result.payload.data).toEqual({ type: 'GestaltInvite', }); - expect(result.payload.senderId).toEqual(nodeId); + expect(result.payload.senderId).toEqual(nodeIdEncoded); expect(result.payload.isRead).toBeFalsy(); expect(result.protectedHeader.jwk).toEqual(jwkPublicKey); @@ -119,7 +121,7 @@ describe('Notifications utils', () => { pull: null, }, }); - expect(result.payload.senderId).toEqual(nodeId); + expect(result.payload.senderId).toEqual(nodeIdEncoded); expect(result.payload.isRead).toBeFalsy(); expect(result.protectedHeader.jwk).toEqual(jwkPublicKey); }); @@ -130,14 +132,14 @@ describe('Notifications utils', () => { type: 'General', message: 'msg', } as NotificationData, - senderId: nodeId, + senderId: nodeIdEncoded, isRead: false, }; const gestaltInviteNotification: Notification = { data: { type: 'GestaltInvite', } as NotificationData, - senderId: nodeId, + senderId: nodeIdEncoded, isRead: false, }; const vaultShareNotification: Notification = { @@ -150,7 +152,7 @@ describe('Notifications utils', () => { pull: null, } as VaultActions, } as NotificationData, - senderId: nodeId, + senderId: nodeIdEncoded, isRead: false, }; @@ -178,7 +180,7 @@ describe('Notifications utils', () => { type: 'General', message: 'msg', }); - expect(decodedGeneralNotification.senderId).toEqual(nodeId); + expect(decodedGeneralNotification.senderId).toEqual(nodeIdEncoded); expect(decodedGeneralNotification.isRead).toBeFalsy(); const decodedGestaltInviteNotification = @@ -188,7 +190,7 @@ describe('Notifications utils', () => { expect(decodedGestaltInviteNotification.data).toEqual({ type: 'GestaltInvite', }); - expect(decodedGestaltInviteNotification.senderId).toEqual(nodeId); + expect(decodedGestaltInviteNotification.senderId).toEqual(nodeIdEncoded); expect(decodedGestaltInviteNotification.isRead).toBeFalsy(); const decodedVaultShareNotification = @@ -204,17 +206,19 @@ describe('Notifications utils', () => { pull: null, }, }); - expect(decodedVaultShareNotification.senderId).toEqual(nodeId); + expect(decodedVaultShareNotification.senderId).toEqual(nodeIdEncoded); expect(decodedVaultShareNotification.isRead).toBeFalsy(); }); test('validates correct notifications', async () => { + const nodeIdOther = testUtils.generateRandomNodeId(); + const nodeIdOtherEncoded = nodesUtils.encodeNodeId(nodeIdOther); const generalNotification: Notification = { data: { type: 'General', message: 'msg', } as NotificationData, - senderId: 'nodeId' as NodeId, + senderId: nodeIdOtherEncoded, isRead: false, }; expect( @@ -225,7 +229,7 @@ describe('Notifications utils', () => { data: { type: 'GestaltInvite', } as NotificationData, - senderId: nodeId, + senderId: nodeIdEncoded, isRead: false, }; expect( @@ -242,7 +246,7 @@ describe('Notifications utils', () => { pull: null, } as VaultActions, } as NotificationData, - senderId: nodeId, + senderId: nodeIdEncoded, isRead: false, }; expect( @@ -256,7 +260,7 @@ describe('Notifications utils', () => { data: { type: 'Invalid Type', }, - senderId: nodeId, + senderId: nodeIdEncoded, isRead: false, }; expect(() => @@ -268,7 +272,7 @@ describe('Notifications utils', () => { data: { type: 'General', }, - senderId: nodeId, + senderId: nodeIdEncoded, isRead: false, }; expect(() => @@ -281,7 +285,7 @@ describe('Notifications utils', () => { type: 'GestaltInvite', message: 'msg', }, - senderId: nodeId, + senderId: nodeIdEncoded, isRead: false, }; expect(() => @@ -296,7 +300,7 @@ describe('Notifications utils', () => { vaultName: 'vaultName' as VaultName, actions: 'clone + pull', }, - senderId: nodeId, + senderId: nodeIdEncoded, isRead: false, }; expect(() => @@ -309,7 +313,7 @@ describe('Notifications utils', () => { type: 'General', message: 'message', }, - sendingId: nodeId, + sendingId: nodeIdEncoded, isRead: false, }; expect(() => diff --git a/tests/sigchain/Sigchain.test.ts b/tests/sigchain/Sigchain.test.ts index ab0f65330..b6ff170ef 100644 --- a/tests/sigchain/Sigchain.test.ts +++ b/tests/sigchain/Sigchain.test.ts @@ -1,5 +1,5 @@ import type { ProviderId, IdentityId } from '@/identities/types'; -import type { NodeId } from '@/nodes/types'; +import type { NodeIdEncoded } from '@/nodes/types'; import type { Claim, ClaimData } from '@/claims/types'; import os from 'os'; import path from 'path'; @@ -10,6 +10,7 @@ import { KeyManager, utils as keysUtils } from '@/keys'; import { Sigchain } from '@/sigchain'; import * as claimsUtils from '@/claims/utils'; import * as sigchainErrors from '@/sigchain/errors'; +import { utils as nodesUtils } from '@/nodes'; import * as testUtils from '../utils'; describe('Sigchain', () => { @@ -17,7 +18,28 @@ describe('Sigchain', () => { new StreamHandler(), ]); const password = 'password'; - const srcNodeId = 'NodeId1' as NodeId; + const srcNodeIdEncoded = nodesUtils.encodeNodeId( + testUtils.generateRandomNodeId(), + ); + const nodeId2Encoded = nodesUtils.encodeNodeId( + testUtils.generateRandomNodeId(), + ); + const nodeId3Encoded = nodesUtils.encodeNodeId( + testUtils.generateRandomNodeId(), + ); + const nodeIdAEncoded = nodesUtils.encodeNodeId( + testUtils.generateRandomNodeId(), + ); + const nodeIdBEncoded = nodesUtils.encodeNodeId( + testUtils.generateRandomNodeId(), + ); + const nodeIdCEncoded = nodesUtils.encodeNodeId( + testUtils.generateRandomNodeId(), + ); + const nodeIdDEncoded = nodesUtils.encodeNodeId( + testUtils.generateRandomNodeId(), + ); + let mockedGenerateKeyPair: jest.SpyInstance; let mockedGenerateDeterministicKeyPair: jest.SpyInstance; beforeAll(async () => { @@ -96,8 +118,8 @@ describe('Sigchain', () => { const sigchain = await Sigchain.createSigchain({ keyManager, db, logger }); const cryptolink: ClaimData = { type: 'node', - node1: srcNodeId, - node2: 'NodeId2' as NodeId, + node1: srcNodeIdEncoded, + node2: nodeId2Encoded, }; const [claimId] = await sigchain.addClaim(cryptolink); @@ -112,8 +134,8 @@ describe('Sigchain', () => { seq: 1, data: { type: 'node', - node1: srcNodeId, - node2: 'NodeId2' as NodeId, + node1: srcNodeIdEncoded, + node2: nodeId2Encoded, }, iat: expect.any(Number), }, @@ -123,10 +145,10 @@ describe('Sigchain', () => { // Check the signature is valid expect(Object.keys(decoded.signatures).length).toBe(1); - expect(decoded.signatures[srcNodeId]).toBeDefined; - expect(decoded.signatures[srcNodeId].header).toStrictEqual({ + expect(decoded.signatures[srcNodeIdEncoded]).toBeDefined; + expect(decoded.signatures[srcNodeIdEncoded].header).toStrictEqual({ alg: 'RS256', - kid: srcNodeId, + kid: srcNodeIdEncoded, }); const verified = await claimsUtils.verifyClaimSignature( claim, @@ -140,15 +162,15 @@ describe('Sigchain', () => { const sigchain = await Sigchain.createSigchain({ keyManager, db, logger }); const cryptolink: ClaimData = { type: 'node', - node1: srcNodeId, - node2: 'NodeId2' as NodeId, + node1: srcNodeIdEncoded, + node2: nodeId2Encoded, }; const [claimId1] = await sigchain.addClaim(cryptolink); const cryptolink2: ClaimData = { type: 'node', - node1: srcNodeId, - node2: 'NodeId3' as NodeId, + node1: srcNodeIdEncoded, + node2: nodeId3Encoded, }; const [claimId2] = await sigchain.addClaim(cryptolink2); @@ -163,8 +185,8 @@ describe('Sigchain', () => { seq: 1, data: { type: 'node', - node1: srcNodeId, - node2: 'NodeId2' as NodeId, + node1: srcNodeIdEncoded, + node2: nodeId2Encoded, }, iat: expect.any(Number), }, @@ -178,8 +200,8 @@ describe('Sigchain', () => { seq: 2, data: { type: 'node', - node1: srcNodeId, - node2: 'NodeId3' as NodeId, + node1: srcNodeIdEncoded, + node2: nodeId3Encoded, }, iat: expect.any(Number), }, @@ -189,10 +211,10 @@ describe('Sigchain', () => { // Check the signature is valid in each claim expect(Object.keys(decoded1.signatures).length).toBe(1); - expect(decoded1.signatures[srcNodeId]).toBeDefined; - expect(decoded1.signatures[srcNodeId].header).toStrictEqual({ + expect(decoded1.signatures[srcNodeIdEncoded]).toBeDefined; + expect(decoded1.signatures[srcNodeIdEncoded].header).toStrictEqual({ alg: 'RS256', - kid: srcNodeId, + kid: srcNodeIdEncoded, }); const verified1 = await claimsUtils.verifyClaimSignature( claim1, @@ -201,10 +223,10 @@ describe('Sigchain', () => { expect(verified1).toBe(true); expect(Object.keys(decoded2.signatures).length).toBe(1); - expect(decoded2.signatures[srcNodeId]).toBeDefined; - expect(decoded2.signatures[srcNodeId].header).toStrictEqual({ + expect(decoded2.signatures[srcNodeIdEncoded]).toBeDefined; + expect(decoded2.signatures[srcNodeIdEncoded].header).toStrictEqual({ alg: 'RS256', - kid: srcNodeId, + kid: srcNodeIdEncoded, }); const verified2 = await claimsUtils.verifyClaimSignature( claim2, @@ -236,10 +258,10 @@ describe('Sigchain', () => { seq: seq1 + 1, data: { type: 'node', - node1: 'A' as NodeId, - node2: 'B' as NodeId, + node1: nodeIdAEncoded, + node2: nodeIdBEncoded, }, - kid: 'A' as NodeId, + kid: nodeIdAEncoded, }); await sigchain.addExistingClaim(claim1); const hPrev2 = await sigchain.getHashPrevious(); @@ -254,10 +276,10 @@ describe('Sigchain', () => { seq: seq2 + 1, data: { type: 'node', - node1: 'A' as NodeId, - node2: 'C' as NodeId, + node1: nodeIdAEncoded, + node2: nodeIdCEncoded, }, - kid: 'A' as NodeId, + kid: nodeIdAEncoded, }); await sigchain.addExistingClaim(claim2); const hPrev3 = await sigchain.getHashPrevious(); @@ -272,10 +294,10 @@ describe('Sigchain', () => { seq: seq3 + 1, data: { type: 'node', - node1: 'A' as NodeId, - node2: 'D' as NodeId, + node1: nodeIdAEncoded, + node2: nodeIdDEncoded, }, - kid: 'D' as NodeId, + kid: nodeIdDEncoded, }); await expect(() => sigchain.addExistingClaim(claimInvalidHash), @@ -288,10 +310,10 @@ describe('Sigchain', () => { seq: 1, data: { type: 'node', - node1: 'A' as NodeId, - node2: 'D' as NodeId, + node1: nodeIdAEncoded, + node2: nodeIdDEncoded, }, - kid: 'D' as NodeId, + kid: nodeIdDEncoded, }); await expect(() => sigchain.addExistingClaim(claimInvalidSeqNum), @@ -299,20 +321,23 @@ describe('Sigchain', () => { }); test('retrieves chain data', async () => { const sigchain = await Sigchain.createSigchain({ keyManager, db, logger }); + const node2s: NodeIdEncoded[] = []; // Add 10 claims for (let i = 1; i <= 5; i++) { + const node2 = nodesUtils.encodeNodeId(testUtils.generateRandomNodeId()); + node2s.push(node2); const nodeLink: ClaimData = { type: 'node', - node1: srcNodeId, - node2: ('NodeId' + i.toString()) as NodeId, + node1: srcNodeIdEncoded, + node2: node2, }; await sigchain.addClaim(nodeLink); } for (let i = 6; i <= 10; i++) { const identityLink: ClaimData = { type: 'identity', - node: srcNodeId, + node: srcNodeIdEncoded, provider: ('ProviderId' + i.toString()) as ProviderId, identity: ('IdentityId' + i.toString()) as IdentityId, }; @@ -325,15 +350,16 @@ describe('Sigchain', () => { const claim = chainData[chainDataKeys[i - 1]]; const decodedClaim = claimsUtils.decodeClaim(claim); if (i <= 5) { + const node2 = node2s[i - 1]; expect(decodedClaim.payload.data).toEqual({ type: 'node', - node1: srcNodeId, - node2: ('NodeId' + i.toString()) as NodeId, + node1: srcNodeIdEncoded, + node2: node2, }); } else { expect(decodedClaim.payload.data).toEqual({ type: 'identity', - node: srcNodeId, + node: srcNodeIdEncoded, provider: ('ProviderId' + i.toString()) as ProviderId, identity: ('IdentityId' + i.toString()) as IdentityId, }); @@ -342,22 +368,25 @@ describe('Sigchain', () => { }); test('retrieves all cryptolinks (nodes and identities) from sigchain (in expected lexicographic order)', async () => { const sigchain = await Sigchain.createSigchain({ keyManager, db, logger }); + const nodes: NodeIdEncoded[] = []; // Add 30 claims for (let i = 1; i <= 30; i++) { // If even, add a node link if (i % 2 === 0) { + const node2 = nodesUtils.encodeNodeId(testUtils.generateRandomNodeId()); + nodes[i] = node2; const nodeLink: ClaimData = { type: 'node', - node1: srcNodeId, - node2: ('NodeId' + i.toString()) as NodeId, + node1: srcNodeIdEncoded, + node2: node2, }; await sigchain.addClaim(nodeLink); // If odd, add an identity link } else { const identityLink: ClaimData = { type: 'identity', - node: srcNodeId, + node: srcNodeIdEncoded, provider: ('ProviderId' + i.toString()) as ProviderId, identity: ('IdentityId' + i.toString()) as IdentityId, }; @@ -382,6 +411,7 @@ describe('Sigchain', () => { expect(seqNum).toBe(expectedSeqNum); // Verify the structure of claim + const node2 = nodes[expectedSeqNum]; const expected: Claim = { payload: { hPrev: claimsUtils.hashClaim( @@ -390,8 +420,8 @@ describe('Sigchain', () => { seq: expectedSeqNum, data: { type: 'node', - node1: srcNodeId, - node2: ('NodeId' + expectedSeqNum.toString()) as NodeId, + node1: srcNodeIdEncoded, + node2: node2, }, iat: expect.any(Number), }, @@ -400,10 +430,10 @@ describe('Sigchain', () => { expect(d).toEqual(expected); // Verify the signature expect(Object.keys(d.signatures).length).toBe(1); - expect(d.signatures[srcNodeId]).toBeDefined; - expect(d.signatures[srcNodeId].header).toStrictEqual({ + expect(d.signatures[srcNodeIdEncoded]).toBeDefined; + expect(d.signatures[srcNodeIdEncoded].header).toStrictEqual({ alg: 'RS256', - kid: srcNodeId, + kid: srcNodeIdEncoded, }); const verified = await claimsUtils.verifyClaimSignature( nodeLinks[i], @@ -442,7 +472,7 @@ describe('Sigchain', () => { seq: expectedSeqNum, data: { type: 'identity', - node: srcNodeId, + node: srcNodeIdEncoded, provider: ('ProviderId' + expectedSeqNum.toString()) as ProviderId, identity: ('IdentityId' + expectedSeqNum.toString()) as IdentityId, }, @@ -453,10 +483,10 @@ describe('Sigchain', () => { expect(id).toEqual(expected); // Verify the signature expect(Object.keys(id.signatures).length).toBe(1); - expect(id.signatures[srcNodeId]).toBeDefined; - expect(id.signatures[srcNodeId].header).toStrictEqual({ + expect(id.signatures[srcNodeIdEncoded]).toBeDefined; + expect(id.signatures[srcNodeIdEncoded].header).toStrictEqual({ alg: 'RS256', - kid: srcNodeId, + kid: srcNodeIdEncoded, }); const verified = await claimsUtils.verifyClaimSignature( nodeLinks[i], diff --git a/tests/status/Status.test.ts b/tests/status/Status.test.ts index 44c710b4f..8a158febe 100644 --- a/tests/status/Status.test.ts +++ b/tests/status/Status.test.ts @@ -1,17 +1,26 @@ -import type { NodeId } from '@/nodes/types'; import type { Host, Port } from '@/network/types'; +import type { StatusLive } from '@/status/types'; import fs from 'fs'; import os from 'os'; import path from 'path'; import Logger, { LogLevel, StreamHandler } from '@matrixai/logger'; import config from '@/config'; import { Status, errors as statusErrors } from '@/status'; +import * as testUtils from '../utils'; describe('Status', () => { const logger = new Logger(`${Status.name} Test`, LogLevel.WARN, [ new StreamHandler(), ]); let dataDir: string; + + const nodeId1 = testUtils.generateRandomNodeId(); + // Const nodeId1Encoded = nodesUtils.encodeNodeId(nodeId1); + const nodeId2 = testUtils.generateRandomNodeId(); + // Const nodeId2Encoded = nodesUtils.encodeNodeId(nodeId2); + const nodeId3 = testUtils.generateRandomNodeId(); + // Const nodeId3Encoded = nodesUtils.encodeNodeId(nodeId3); + beforeEach(async () => { dataDir = await fs.promises.mkdtemp(path.join(os.tmpdir(), 'status-test-')); }); @@ -57,7 +66,7 @@ describe('Status', () => { expect(statusInfo1!.data.pid).toBe(0); await status.finishStart({ pid: 0, - nodeId: 'node' as NodeId, + nodeId: nodeId1, clientHost: '::1' as Host, clientPort: 0 as Port, ingressHost: '127.0.0.1' as Host, @@ -127,9 +136,9 @@ describe('Status', () => { await expect(status.updateStatusLive({})).rejects.toThrow( statusErrors.ErrorStatusLiveUpdate, ); - const statusData1 = { + const statusData1: StatusLive['data'] = { pid: 0, - nodeId: 'node' as NodeId, + nodeId: nodeId1, clientHost: '::1' as Host, clientPort: 0 as Port, ingressHost: '127.0.0.1' as Host, @@ -140,15 +149,15 @@ describe('Status', () => { }; await status.finishStart(statusData1); const statusInfo = await status.updateStatusLive({ - nodeId: 'new node' as NodeId, - anotherthing: 'something', + nodeId: nodeId2, + anotherThing: 'something', }); expect(statusInfo).toStrictEqual({ status: 'LIVE', data: { ...statusData1, - nodeId: 'new node' as NodeId, - anotherthing: 'something', + nodeId: nodeId2, + anotherThing: 'something', }, }); await status.beginStop({ pid: 0 }); @@ -200,7 +209,7 @@ describe('Status', () => { clientPort: 0 as Port, ingressHost: '127.0.0.1' as Host, ingressPort: 0 as Port, - nodeId: '' as NodeId, + nodeId: nodeId3, pid: 0, }); const statusInfoLive = await statusWaitFor; @@ -245,7 +254,7 @@ describe('Status', () => { clientPort: 0 as Port, ingressHost: '127.0.0.1' as Host, ingressPort: 3425 as Port, - nodeId: '' as NodeId, + nodeId: nodeId3, pid: 0, }), status.readStatus(), @@ -257,7 +266,7 @@ describe('Status', () => { clientPort: 3445 as Port, ingressHost: '127.0.0.1' as Host, ingressPort: 0 as Port, - nodeId: '' as NodeId, + nodeId: nodeId3, pid: 0, }), status.beginStop({ @@ -269,7 +278,7 @@ describe('Status', () => { clientPort: 0 as Port, ingressHost: '127.0.0.1' as Host, ingressPort: 0 as Port, - nodeId: '' as NodeId, + nodeId: nodeId3, pid: 0, }), ]); @@ -303,7 +312,7 @@ describe('Status', () => { clientPort: 0 as Port, ingressHost: '127.0.0.1' as Host, ingressPort: 0 as Port, - nodeId: '' as NodeId, + nodeId: nodeId3, pid: 0, }); const p2 = status.beginStop({ pid: 1 }); diff --git a/tests/utils.ts b/tests/utils.ts index 4eed7f203..8b3c5b55b 100644 --- a/tests/utils.ts +++ b/tests/utils.ts @@ -1,8 +1,10 @@ import type { StatusLive } from '@/status/types'; +import type { NodeId } from '@/nodes/types'; import path from 'path'; import fs from 'fs'; import lock from 'fd-lock'; import Logger, { LogLevel, StreamHandler } from '@matrixai/logger'; +import { IdInternal } from '@matrixai/id'; import { PolykeyAgent } from '@'; import { Status } from '@/status'; import { utils as keysUtils } from '@/keys'; @@ -169,4 +171,10 @@ async function setupGlobalAgent( }; } -export { setupGlobalKeypair, setupGlobalAgent }; +function generateRandomNodeId(): NodeId { + // Make it easy to read with an identifier + const random = keysUtils.getRandomBytesSync(16).toString('hex'); + return IdInternal.fromString(random); +} + +export { setupGlobalKeypair, setupGlobalAgent, generateRandomNodeId }; diff --git a/tests/vaults/VaultInternal.test.ts b/tests/vaults/VaultInternal.test.ts index 8c0489e6b..defec75f8 100644 --- a/tests/vaults/VaultInternal.test.ts +++ b/tests/vaults/VaultInternal.test.ts @@ -9,14 +9,8 @@ import { VaultInternal } from '@/vaults'; import { generateVaultId, generateVaultKey } from '@/vaults/utils'; import * as vaultsErrors from '@/vaults/errors'; import { sleep } from '@/utils'; -import { KeyManager } from '@/keys'; - -// Mocks. -jest.mock('@/keys/utils', () => ({ - ...jest.requireActual('@/keys/utils'), - generateDeterministicKeyPair: - jest.requireActual('@/keys/utils').generateKeyPair, -})); +import { KeyManager, utils as keysUtils } from '@/keys'; +import * as testUtils from '../utils'; describe('VaultInternal', () => { let dataDir: string; @@ -28,8 +22,21 @@ describe('VaultInternal', () => { let efs: EncryptedFS; const logger = new Logger('Vault', LogLevel.WARN, [new StreamHandler()]); let keyManager: KeyManager; + let mockedGenerateKeyPair: jest.SpyInstance; + let mockedGenerateDeterministicKeyPair: jest.SpyInstance; beforeEach(async () => { + const globalKeyPair = await testUtils.setupGlobalKeypair(); + mockedGenerateKeyPair = jest + .spyOn(keysUtils, 'generateKeyPair') + .mockResolvedValue(globalKeyPair); + mockedGenerateDeterministicKeyPair = jest + .spyOn(keysUtils, 'generateDeterministicKeyPair') + .mockResolvedValue(globalKeyPair); + + dataDir = await fs.promises.mkdtemp( + path.join(os.tmpdir(), 'polykey-test-'), + ); dataDir = await fs.promises.mkdtemp( path.join(os.tmpdir(), 'polykey-test-'), ); @@ -59,6 +66,8 @@ describe('VaultInternal', () => { }); afterEach(async () => { + mockedGenerateKeyPair.mockRestore(); + mockedGenerateDeterministicKeyPair.mockRestore(); await vault.destroy(); await efs.stop(); await efs.destroy(); diff --git a/tests/vaults/VaultManager.test.ts b/tests/vaults/VaultManager.test.ts index 5db37e4c4..65df7e69f 100644 --- a/tests/vaults/VaultManager.test.ts +++ b/tests/vaults/VaultManager.test.ts @@ -23,21 +23,15 @@ import { NotificationsManager } from '@/notifications'; import { errors as vaultErrors } from '@/vaults'; import { utils as vaultUtils } from '@/vaults'; -import { makeVaultId } from '@/vaults/utils'; - -// Mocks. -jest.mock('@/keys/utils', () => ({ - ...jest.requireActual('@/keys/utils'), - generateDeterministicKeyPair: - jest.requireActual('@/keys/utils').generateKeyPair, -})); +import { utils as nodesUtils } from '@/nodes'; +import * as testUtils from '../utils'; describe('VaultManager', () => { const password = 'password'; const logger = new Logger('VaultManager Test', LogLevel.WARN, [ new StreamHandler(), ]); - const nonExistantVaultId = makeVaultId(idUtils.fromString('DoesNotExist')); + const nonExistantVaultId = idUtils.fromString('DoesNotExist') as VaultId; let dataDir: string; let vaultsPath: string; let vaultsKey: VaultKey; @@ -68,7 +62,18 @@ describe('VaultManager', () => { const secondVaultName = 'SecondTestVault' as VaultName; const thirdVaultName = 'ThirdTestVault' as VaultName; + let mockedGenerateKeyPair: jest.SpyInstance; + let mockedGenerateDeterministicKeyPair: jest.SpyInstance; + beforeAll(async () => { + const globalKeyPair = await testUtils.setupGlobalKeypair(); + mockedGenerateKeyPair = jest + .spyOn(keysUtils, 'generateKeyPair') + .mockResolvedValue(globalKeyPair); + mockedGenerateDeterministicKeyPair = jest + .spyOn(keysUtils, 'generateDeterministicKeyPair') + .mockResolvedValue(globalKeyPair); + fwdProxy = new ForwardProxy({ authToken: 'abc', logger: logger, @@ -168,6 +173,8 @@ describe('VaultManager', () => { }); }); afterAll(async () => { + mockedGenerateKeyPair.mockRestore(); + mockedGenerateDeterministicKeyPair.mockRestore(); await fwdProxy.stop(); }); @@ -585,7 +592,7 @@ describe('VaultManager', () => { certChainPem: await targetKeyManager.getRootCertChainPem(), }; node = { - id: nodeManager.getNodeId(), + id: nodesUtils.encodeNodeId(nodeManager.getNodeId()), chain: { nodes: {}, identities: {} } as ChainData, }; targetFwdProxy = new ForwardProxy({ @@ -674,7 +681,7 @@ describe('VaultManager', () => { }); altNodeId = altKeyManager.getNodeId(); await targetGestaltGraph.setNode({ - id: altNodeId, + id: nodesUtils.encodeNodeId(altNodeId), chain: {}, }); altRevTLSConfig = { diff --git a/tests/vaults/VaultOps.test.ts b/tests/vaults/VaultOps.test.ts index f92839bf2..b07c08029 100644 --- a/tests/vaults/VaultOps.test.ts +++ b/tests/vaults/VaultOps.test.ts @@ -1,5 +1,4 @@ import type { Vault, VaultId } from '@/vaults/types'; -import type { NodeId } from '@/nodes/types'; import fs from 'fs'; import path from 'path'; import os from 'os'; @@ -11,13 +10,7 @@ import { VaultInternal, vaultOps } from '@/vaults'; import { KeyManager } from '@/keys'; import { generateVaultId } from '@/vaults/utils'; import * as keysUtils from '@/keys/utils'; - -// Mocks. -jest.mock('@/keys/utils', () => ({ - ...jest.requireActual('@/keys/utils'), - generateDeterministicKeyPair: - jest.requireActual('@/keys/utils').generateKeyPair, -})); +import * as testUtils from '../utils'; describe('VaultOps', () => { const password = 'password'; @@ -28,19 +21,31 @@ describe('VaultOps', () => { let dataDir: string; + let keyManager: KeyManager; let baseEfs: EncryptedFS; let vaultId: VaultId; let vaultInternal: VaultInternal; let vault: Vault; + let mockedGenerateKeyPair: jest.SpyInstance; + let mockedGenerateDeterministicKeyPair: jest.SpyInstance; + beforeAll(async () => { + const globalKeyPair = await testUtils.setupGlobalKeypair(); + mockedGenerateKeyPair = jest + .spyOn(keysUtils, 'generateKeyPair') + .mockResolvedValue(globalKeyPair); + mockedGenerateDeterministicKeyPair = jest + .spyOn(keysUtils, 'generateDeterministicKeyPair') + .mockResolvedValue(globalKeyPair); + dataDir = await fs.promises.mkdtemp( path.join(os.tmpdir(), 'polykey-test-'), ); const keysPath = path.join(dataDir, 'keys'); - const keyManager = await KeyManager.createKeyManager({ + keyManager = await KeyManager.createKeyManager({ keysPath, password, logger, @@ -53,13 +58,15 @@ describe('VaultOps', () => { logger, }); await baseEfs.start(); - await keyManager.stop(); - await keyManager.destroy(); }); afterAll(async () => { + mockedGenerateKeyPair.mockRestore(); + mockedGenerateDeterministicKeyPair.mockRestore(); await baseEfs.stop(); await baseEfs.destroy(); + await keyManager.stop(); + await keyManager.destroy(); await fs.promises.rm(dataDir, { force: true, recursive: true, @@ -71,13 +78,8 @@ describe('VaultOps', () => { await baseEfs.mkdir(path.join(idUtils.toString(vaultId), 'contents'), { recursive: true, }); - const fakeKeynode = { - getNodeId: () => { - return 'DummyNodeId' as NodeId; - }, - }; vaultInternal = await VaultInternal.create({ - keyManager: fakeKeynode as KeyManager, + keyManager: keyManager, vaultId, efs: baseEfs, logger: logger.getChild(VaultInternal.name),