From 6de97cac149f9a123d50e5968ce632095c3c1c60 Mon Sep 17 00:00:00 2001 From: yflory Date: Tue, 4 Jun 2019 18:44:55 +0200 Subject: [PATCH] Migrate friends --- www/common/common-messenger.js | 1 + www/common/migrate-user-object.js | 129 +++++++++++++++++++++++++++++- www/common/outer/async-store.js | 2 +- www/common/outer/mailbox.js | 2 +- 4 files changed, 130 insertions(+), 4 deletions(-) diff --git a/www/common/common-messenger.js b/www/common/common-messenger.js index 05ebfea54..188f03147 100644 --- a/www/common/common-messenger.js +++ b/www/common/common-messenger.js @@ -44,6 +44,7 @@ define([ profile: proxy.profile && proxy.profile.view, edPublic: proxy.edPublic, curvePublic: proxy.curvePublic, + notifications: Util.find(proxy, ['mailboxes', 'notifications', 'channel']), avatar: proxy.profile && proxy.profile.avatar }; }; diff --git a/www/common/migrate-user-object.js b/www/common/migrate-user-object.js index 54c1c6111..48c14dd41 100644 --- a/www/common/migrate-user-object.js +++ b/www/common/migrate-user-object.js @@ -2,14 +2,17 @@ define([ '/common/common-feedback.js', '/common/common-hash.js', '/common/common-util.js', + '/common/common-messenger.js', + '/common/outer/mailbox.js', '/bower_components/nthen/index.js', -], function (Feedback, Hash, Util, nThen) { + '/bower_components/chainpad-crypto/crypto.js', +], function (Feedback, Hash, Util, Messenger, Mailbox, nThen, Crypto) { // Start migration check // Versions: // 1: migrate pad attributes // 2: migrate indent settings (codemirror) - return function (userObject, cb, progress) { + return function (userObject, cb, progress, store) { var version = userObject.version || 0; nThen(function () { @@ -186,6 +189,128 @@ define([ Feedback.send('Migrate-8', true); userObject.version = version = 8; } + }).nThen(function (waitFor) { + // Migration 9: send our mailbox channel to existing friends + var migrateFriends = function () { + var channels = {}; + var ctx = { + store: store + }; + var myData = Messenger.createData(userObject); + + var close = function (chan) { + var channel = channels[chan]; + if (!channel) { return; } + try { + channel.wc.leave(); + delete channels[chan]; + } catch (e) {} + }; + + var onDirectMessage = function (msg, sender) { + if (sender !== network.historyKeeper) { return; } + var parsed = JSON.parse(msg); + + // Metadata msg? we don't care + if ((parsed.validateKey || parsed.owners) && parsed.channel) { return; } + + // End of history message, "onReady" + if (parsed.channel && channels[parsed.channel]) { + // History cleared while we were offline + // ==> we asked for an invalid last known hash + if (parsed.error && parsed.error === "EINVAL") { + var msg = ['GET_HISTORY', parsed.channel, {}]; + network.sendto(network.historyKeeper, JSON.stringify(msg)) + .then(function () {}, function () {}); + return; + } + // End of history + if (parsed.state && parsed.state === 1) { + // Channel is ready and we didn't receive their mailbox channel: send our channel + myData.channel = parsed.channel; + var updateMsg = ['UPDATE', myData.curvePublic, +new Date(), myData]; + var cryptMsg = channel.encrypt(JSON.stringify(updateMsg)); + channels[parsed.channel].wc.bcast(cryptMsg).then(function () {}, function (err) { + console.error("Can't migrate this friend", channels[parsed.channel].friend, err); + }); + close(parsed.channel); + return; + } + } else if (parsed.channel) { + return; + } + + // History message: we only care about "UPDATE" messages + var chan = parsed[3]; + if (!chan || !channels[chan]) { return; } + var channel = channels[chan]; + var msg = channel.decrypt(parsed[4]); + var parsedMsg = JSON.parse(msg); + if (parsedMsg[0] === 'UPDATE') { + if (parsedMsg[1] === myData.curvePublic) { return; } + var data = parsedMsg[3]; + // If it doesn't contain the mailbox channel, ignore the message + if (!data.notifications) { return; } + // Otherwise we know their channel, we can send them our own + channel.friend.notifications = data.notifications + myData.channel = chan; + Mailbox.sendTo(ctx, 'UPDATE_DATA', myData, { + channel: data.notitications, + curvePublic: data.curvePublic + }, function () { + console.log('friend migrated', friend); + }); + close(chan); + } + }; + + network.on('message', function(msg, sender) { + try { + onDirectMessage(msg, sender); + } catch (e) {} + }); + + var friends = userObject.friends || {}; + Object.keys(friends).forEach(function (curve) { + if (curve.length !== 44) { return; } + var friend = friends[curve]; + + // Check if it is already a "new" friend + if (friend.notifications) { return; } + + /** Old friend: + * 1. Open the messenger channel + * 2. Check if they sent us their mailbox channel + * 3.a. Yes ==> sent them a mail containing our mailbox channel + * 3.b. No ==> post our mailbox data to the messenger channel + */ + network.join(friend.channel).then(function (wc) { + var keys = Crypto.Curve.deriveKeys(friend.curvePublic, userObject.curvePrivate); + var encryptor = Crypto.Curve.createEncryptor(keys); + channels[friend.channel] = { + wc: wc, + friend: friend, + decrypt: encryptor.decrypt, + encrypt: encryptor.encrypt + }; + var cfg = { + lastKnownHash: friend.lastKnownHash + }; + var msg = ['GET_HISTORY', friend.channel, cfg]; + network.sendto(network.historyKeeper, JSON.stringify(msg)) + .then(function () {}, function (err) { + console.error("Can't migrate this friend", friend, err); + }); + }, function (err) { + console.error("Can't migrate this friend", friend, err); + }); + }); + }; + if (version < 9) { + migrateFriends(); + Feedback.send('Migrate-9', true); + userObject.version = version = 9; + } /*}).nThen(function (waitFor) { // Test progress bar in the loading screen var i = 0; diff --git a/www/common/outer/async-store.js b/www/common/outer/async-store.js index 39aac9b54..8df78f11c 100644 --- a/www/common/outer/async-store.js +++ b/www/common/outer/async-store.js @@ -1649,7 +1649,7 @@ define([ state: (2 + (version / 10)), progress: progress }); - }); + }, store); Store.initAnonRpc(null, null, waitFor()); Store.initRpc(null, null, waitFor()); }).nThen(function (waitFor) { diff --git a/www/common/outer/mailbox.js b/www/common/outer/mailbox.js index d2bc41705..550573411 100644 --- a/www/common/outer/mailbox.js +++ b/www/common/outer/mailbox.js @@ -65,7 +65,7 @@ proxy.mailboxes = { }; // Send a message to someone else - var sendTo = function (ctx, type, msg, user, cb) { + var sendTo = Mailbox.sendTo = function (ctx, type, msg, user, cb) { if (!Crypto.Mailbox) { return void cb({error: "chainpad-crypto is outdated and doesn't support mailboxes."}); }