From 64089c5f6b77507b15ff6ea6e8bfa36573138784 Mon Sep 17 00:00:00 2001 From: ansuz Date: Wed, 5 Apr 2017 17:28:04 +0200 Subject: [PATCH] implement pad pinning --- rpc.js | 38 +++++++++++++++++++------------ www/common/pinpad.js | 49 ++++++++++++++++++++++++++++------------ www/examples/pin/main.js | 36 ++++++++++++++++++++++++++++- 3 files changed, 94 insertions(+), 29 deletions(-) diff --git a/rpc.js b/rpc.js index db4d90a33..705f07f8c 100644 --- a/rpc.js +++ b/rpc.js @@ -127,11 +127,16 @@ var storeMessage = function (store, publicKey, msg, cb) { }; var pinChannel = function (store, publicKey, channel, cb) { - store.message(store, publicKey, ['PIN', channel], cb); + store.message(publicKey, JSON.stringify(['PIN', channel]), cb); }; var unpinChannel = function (store, publicKey, channel, cb) { - store.message(store, publicKey, ['UNPIN', channel], cb); + store.message(publicKey, JSON.stringify(['UNPIN', channel]), cb); +}; + +var resetUserPins = function (store, publicKey, channelList, cb) { + // TODO make this atomic + store.message(publicKey, JSON.stringify(['RESET']), cb); }; var getChannelList = function (store, publicKey, cb) { @@ -171,7 +176,6 @@ var getChannelList = function (store, publicKey, cb) { cb(pinned); }); - }; var hashChannelList = function (A) { @@ -194,11 +198,6 @@ var getHash = function (store, publicKey, cb) { }); }; -var resetUserPins = function (store, publicKey, channelList, cb) { - // TODO - cb('NOT_IMPLEMENTED'); -}; - var expireSessions = function (Cookies) { var now = +new Date(); Object.keys(Cookies).forEach(function (key) { @@ -238,6 +237,7 @@ RPC.create = function (config, cb) { var signature = msg.shift(); var publicKey = msg.shift(); + // make sure a user object is initialized in the cookie jar addUser(publicKey); @@ -252,14 +252,16 @@ RPC.create = function (config, cb) { var serialized = JSON.stringify(msg); - if (!(serialized && publicKey)) { + if (!(serialized && typeof(publicKey) === 'string')) { return void respond('INVALID_MESSAGE_OR_PUBLIC_KEY'); } + if (checkSignature(serialized, signature, publicKey) !== true) { return void respond("INVALID_SIGNATURE_OR_PUBLIC_KEY"); } + var safeKey = publicKey.replace(/\//g, '-'); /* If you have gotten this far, you have signed the message with the public key which you provided. @@ -284,20 +286,28 @@ RPC.create = function (config, cb) { return void Respond(void 0); case 'ECHO': return void Respond(void 0, msg); + + /* TODO + reset should be atomic in case the operation is aborted */ case 'RESET': - return resetUserPins(store, publicKey, [], function (e) { - return void Respond('NOT_IMPLEMENTED', msg); + return resetUserPins(store, safeKey, [], function (e) { + return void Respond(e); }); + + + /* TODO + pin and unpin operations should respond with the new hash */ case 'PIN': - return pinChannel(store, publicKey, msg[1], function (e) { + return pinChannel(store, safeKey, msg[1], function (e) { Respond(e); }); case 'UNPIN': - return unpinChannel(store, publicKey, msg[1], function (e) { + return unpinChannel(store, safeKey, msg[1], function (e) { Respond(e); }); + case 'GET_HASH': - return void getHash(store, publicKey, function (hash) { + return void getHash(store, safeKey, function (hash) { Respond(void 0, hash); }); case 'GET_TOTAL_SIZE': diff --git a/www/common/pinpad.js b/www/common/pinpad.js index 260ac4d66..f2f6bd04a 100644 --- a/www/common/pinpad.js +++ b/www/common/pinpad.js @@ -6,27 +6,22 @@ define([ ], function (Cryptpad, Rpc) { var Nacl = window.nacl; - var localChannelsHash = function (fileList) { - fileList = fileList || Cryptpad.getUserChannelList(); - - var channelIdList = []; - fileList.forEach(function (href) { - var parsedHref = Cryptpad.parsePadUrl(href); - if (!parsedHref || !parsedHref.hash) { return; } - var parsedHash = Cryptpad.parseHash(parsedHref.hash); - if (!parsedHash || !parsedHash.channel) { return; } - channelIdList.push(Cryptpad.base64ToHex(parsedHash.channel)); - }); - var uniqueList = Cryptpad.deduplicateString(channelIdList).sort(); + var uniqueChannelList = function (list) { + list = list || Cryptpad.getUserChannelList(); + return Cryptpad.deduplicateString(list).sort(); + }; + var localChannelsHash = function (fileList) { + var uniqueList = uniqueChannelList(fileList); var hash = Nacl.util.encodeBase64(Nacl .hash(Nacl.util.decodeUTF8( JSON.stringify(uniqueList) ))); - return hash; }; var getServerHash = function (rpc, edPublic, cb) { - rpc.send('GET_HASH', edPublic, cb); + rpc.send('GET_HASH', edPublic, function (e, hash) { + cb(e, hash[0]); + }); }; var getFileSize = function (rpc, file, cb) { @@ -63,6 +58,18 @@ define([ }); }; + var pinChannel = function (rpc, channel, cb) { + rpc.send('PIN', channel, cb); + }; + + var unpinChannel = function (rpc, channel, cb) { + rpc.send('UNPIN', channel, cb); + }; + + var reset = function (rpc, cb) { + rpc.send('RESET', undefined, cb); + }; + /* 1. every time you want to pin or unpid a pad you send a message to the server 2. the server sends back a hash of the sorted list of your pinned pads @@ -96,6 +103,8 @@ define([ exp.publicKey = edPublic; exp.send = rpc.send; + exp.uniqueChannelList = uniqueChannelList; + exp.getFileSize = function (file, cb) { getFileSize(rpc, file, cb); }; @@ -106,6 +115,18 @@ define([ getServerHash(rpc, edPublic, cb); }; + exp.pin = function (channel, cb) { + pinChannel(rpc, channel, cb); + }; + exp.unpin = function (channel, cb) { + unpinChannel(rpc, channel, cb); + }; + exp.reset = function (cb) { + reset(rpc, cb); + }; + + exp.localChannelsHash = localChannelsHash; + cb(e, exp); }); }; diff --git a/www/examples/pin/main.js b/www/examples/pin/main.js index 0f2449f3b..1c3df4d2f 100644 --- a/www/examples/pin/main.js +++ b/www/examples/pin/main.js @@ -47,11 +47,45 @@ define([ }); }; + var synchronize = function (call) { + var localHash = call.localChannelsHash(); + var serverHash; + + call.getServerHash(function (e, hash) { + if (e) { return void console.error(e); } + serverHash = hash; + + if (serverHash === localHash) { + return console.log("all your pads are pinned. There is nothing to do"); + } + + call.reset(function (e, response) { + if (e) { return console.error(e); } + + var list = call.uniqueChannelList(); + + // now start pinning... + list.forEach(function (channel) { + call.pin(channel, function (e, out) { + if (e) { return console.error(e); } + }); + }); + }); + +/* + console.log(JSON.stringify({ + local: localHash, + remote: serverHash, + }, null, 2));*/ + }); + }; + $(function () { Cryptpad.ready(function (err, env) { Pinpad.create(function (e, call) { if (e) { return void console.error(e); } - then(call); + // then(call); + synchronize(call); }); }); });