pairnet 0.2.1 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.js +24 -11
- package/lib/store.js +9 -4
- package/package.json +2 -1
- package/test/index.js +10 -2
package/index.js
CHANGED
|
@@ -33,6 +33,7 @@ const requireEither = require("@validatem/require-either");
|
|
|
33
33
|
const either = require("@validatem/either");
|
|
34
34
|
const arrayOf = require("@validatem/array-of");
|
|
35
35
|
const allowExtraProperties = require("@validatem/allow-extra-properties");
|
|
36
|
+
const isPlainObject = require("@validatem/is-plain-object");
|
|
36
37
|
const isFunction = require("@validatem/is-function");
|
|
37
38
|
const isBuffer = require("@validatem/is-buffer");
|
|
38
39
|
const isBoolean = require("@validatem/is-boolean");
|
|
@@ -143,12 +144,11 @@ module.exports = {
|
|
|
143
144
|
};
|
|
144
145
|
}
|
|
145
146
|
|
|
146
|
-
async function makeRawPairingToken() {
|
|
147
|
+
async function makeRawPairingToken(data) {
|
|
147
148
|
let token = generatePairingToken();
|
|
148
149
|
// TODO: Expiry
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
debug(`[generatePairingToken] Generated pairing token ${token}`);
|
|
150
|
+
await store.setValidPairingToken(token, data ?? {});
|
|
151
|
+
debug(`[generatePairingToken] Generated pairing token ${token}`); // TODO: log associated data?
|
|
152
152
|
return token;
|
|
153
153
|
}
|
|
154
154
|
|
|
@@ -246,11 +246,21 @@ module.exports = {
|
|
|
246
246
|
|
|
247
247
|
return {
|
|
248
248
|
fingerprint: identity.fingerprint,
|
|
249
|
+
getPeerData: async function (fingerprint) {
|
|
250
|
+
let storedData = await store.getPeerData(fingerprint);
|
|
251
|
+
|
|
252
|
+
if (storedData === NotSet) {
|
|
253
|
+
throw new Error(`Specified fingerprint is not known, cannot retrieve peer data`);
|
|
254
|
+
} else {
|
|
255
|
+
return storedData;
|
|
256
|
+
}
|
|
257
|
+
},
|
|
249
258
|
generatePairingToken: async function (_port, _options) {
|
|
250
|
-
let [ port, { compact }] = validateArguments(arguments, {
|
|
259
|
+
let [ port, { compact, data }] = validateArguments(arguments, {
|
|
251
260
|
port: [ required, isPortNumber ],
|
|
252
261
|
options: [ defaultTo({}), {
|
|
253
|
-
compact: [ defaultTo(false), isBoolean ]
|
|
262
|
+
compact: [ defaultTo(false), isBoolean ],
|
|
263
|
+
data: [ defaultTo({}), isPlainObject ],
|
|
254
264
|
}]
|
|
255
265
|
});
|
|
256
266
|
|
|
@@ -261,7 +271,7 @@ module.exports = {
|
|
|
261
271
|
? reduceAddresses(ips.all)
|
|
262
272
|
: ips.all,
|
|
263
273
|
port: port,
|
|
264
|
-
rawToken: await makeRawPairingToken(),
|
|
274
|
+
rawToken: await makeRawPairingToken(data),
|
|
265
275
|
fingerprint: identity.fingerprint,
|
|
266
276
|
});
|
|
267
277
|
},
|
|
@@ -314,12 +324,13 @@ module.exports = {
|
|
|
314
324
|
});
|
|
315
325
|
},
|
|
316
326
|
createServer: async function (_option) {
|
|
317
|
-
let { hostname, port, onConnect, onDisconnect, onQuery } = validateOptions(arguments, {
|
|
327
|
+
let { hostname, port, onConnect, onDisconnect, onQuery, onPaired } = validateOptions(arguments, {
|
|
318
328
|
hostname: [ isNonEmptyString ], /* undefined == listen on all public interfaces */
|
|
319
329
|
port: [ required, isPortNumber ],
|
|
320
330
|
onConnect: [ required, isFunction ],
|
|
321
331
|
onDisconnect: [ isFunction ],
|
|
322
|
-
onQuery: [ required, isFunction ]
|
|
332
|
+
onQuery: [ required, isFunction ],
|
|
333
|
+
onPaired: [ isFunction ]
|
|
323
334
|
});
|
|
324
335
|
|
|
325
336
|
if (protocolConfiguration.isServer) {
|
|
@@ -358,8 +369,10 @@ module.exports = {
|
|
|
358
369
|
let { token } = query;
|
|
359
370
|
|
|
360
371
|
if (await store.isValidPairingToken(token) === true) {
|
|
361
|
-
|
|
362
|
-
await store.removeValidPairingToken(token);
|
|
372
|
+
// TODO: What happens if a client chooses to remain connected after pairing? Can this possibility result in any security issues?
|
|
373
|
+
let data = await store.removeValidPairingToken(token);
|
|
374
|
+
await store.trustPeer(clientFingerprint, { data });
|
|
375
|
+
await onPaired?.(clientFingerprint);
|
|
363
376
|
return true;
|
|
364
377
|
} else {
|
|
365
378
|
// TODO: Force disconnect?
|
package/lib/store.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
+
const assert = require("node:assert");
|
|
3
4
|
const { NotSet } = require("./storages/symbols");
|
|
4
5
|
|
|
5
6
|
module.exports = function (storage) {
|
|
@@ -12,13 +13,17 @@ module.exports = function (storage) {
|
|
|
12
13
|
return storage.set("pairnet_identity", identity);
|
|
13
14
|
},
|
|
14
15
|
isValidPairingToken: async function (token) {
|
|
15
|
-
return (await storage.get(`pairnet_token_${token.toString("hex")}`)
|
|
16
|
+
return (await storage.get(`pairnet_token_${token.toString("hex")}`) !== NotSet);
|
|
16
17
|
},
|
|
17
|
-
setValidPairingToken: async function (token) {
|
|
18
|
-
|
|
18
|
+
setValidPairingToken: async function (token, data) {
|
|
19
|
+
assert(data != null);
|
|
20
|
+
return storage.set(`pairnet_token_${token.toString("hex")}`, data);
|
|
19
21
|
},
|
|
20
22
|
removeValidPairingToken: async function (token) {
|
|
21
|
-
|
|
23
|
+
let key = `pairnet_token_${token.toString("hex")}`;
|
|
24
|
+
let data = storage.get(key);
|
|
25
|
+
await storage.delete(key);
|
|
26
|
+
return data;
|
|
22
27
|
},
|
|
23
28
|
trustPeer: async function (fingerprint, data) {
|
|
24
29
|
return storage.set(`pairnet_peer_${fingerprint}`, data ?? {});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pairnet",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"keywords": [],
|
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
"@validatem/is-buffer": "^0.1.1",
|
|
28
28
|
"@validatem/is-function": "^0.1.0",
|
|
29
29
|
"@validatem/is-non-empty-string": "^0.1.1",
|
|
30
|
+
"@validatem/is-plain-object": "^0.1.1",
|
|
30
31
|
"@validatem/is-port-number": "^1.0.0",
|
|
31
32
|
"@validatem/require-either": "^0.1.0",
|
|
32
33
|
"@validatem/required": "^0.1.1",
|
package/test/index.js
CHANGED
|
@@ -51,17 +51,21 @@ async function makePeer(overrides) {
|
|
|
51
51
|
test("full procedure", async (t) => {
|
|
52
52
|
let peer1 = await makePeer();
|
|
53
53
|
let peer2 = await makePeer();
|
|
54
|
+
let pairedFingerprint;
|
|
54
55
|
|
|
55
56
|
let server = await peer1.createServer({
|
|
56
57
|
hostname: "localhost", port: 4005,
|
|
57
58
|
onQuery: (fingerprint, query) => ({ number: query.number * 2, hasFingerprint: (fingerprint != null) }),
|
|
58
59
|
onConnect: async (peer) => {
|
|
59
60
|
yeetStream(peer.eventStream);
|
|
61
|
+
},
|
|
62
|
+
onPaired: async (fingerprint) => {
|
|
63
|
+
pairedFingerprint = fingerprint;
|
|
60
64
|
}
|
|
61
65
|
});
|
|
62
66
|
|
|
63
67
|
// let token = await peer1.generatePairingToken(4005);
|
|
64
|
-
let rawToken = await peer1.generateRawPairingToken();
|
|
68
|
+
let rawToken = await peer1.generateRawPairingToken({ foo: "bar" });
|
|
65
69
|
|
|
66
70
|
await t.test("fails on wrong fingerprint", { timeout: 500 }, async () => {
|
|
67
71
|
await assert.rejects(async () => {
|
|
@@ -85,6 +89,9 @@ test("full procedure", async (t) => {
|
|
|
85
89
|
await peer.disconnect();
|
|
86
90
|
// FIXME: Test query error reply
|
|
87
91
|
});
|
|
92
|
+
|
|
93
|
+
assert.strictEqual(pairedFingerprint, peer2.fingerprint);
|
|
94
|
+
assert.deepStrictEqual(await peer1.getPeerData(peer2.fingerprint), { data: { foo: "bar" }});
|
|
88
95
|
});
|
|
89
96
|
|
|
90
97
|
await server.stop();
|
|
@@ -105,8 +112,9 @@ test("full procedure with wrapped token", async (t) => {
|
|
|
105
112
|
let fingerprint;
|
|
106
113
|
|
|
107
114
|
await t.test("pair", { timeout: 500 }, async () => {
|
|
108
|
-
let token = await peer1.generatePairingToken(4005);
|
|
115
|
+
let token = await peer1.generatePairingToken(4005, { data: { foo: "bar" }});
|
|
109
116
|
fingerprint = await peer2.pair(token);
|
|
117
|
+
assert.deepStrictEqual(await peer1.getPeerData(peer2.fingerprint), { data: { foo: "bar" }});
|
|
110
118
|
});
|
|
111
119
|
|
|
112
120
|
await t.test("connect", { timeout: 500 }, async () => {
|