diff --git a/www/common/drive-ui.js b/www/common/drive-ui.js index 206ead590..e8b9d7235 100644 --- a/www/common/drive-ui.js +++ b/www/common/drive-ui.js @@ -545,7 +545,7 @@ define([ var sfData = files.sharedFolders[id] || {}; var parsed = Hash.parsePadUrl(sfData.href); var secret = Hash.getSecrets('drive', parsed.hash, sfData.password); - manager.addProxy(id, f, null, secret.keys.secondaryKey); + manager.addProxy(id, {proxy: f}, null, secret.keys.secondaryKey); }); // UI containers diff --git a/www/common/outer/async-store.js b/www/common/outer/async-store.js index b88463989..a00ce6b9c 100644 --- a/www/common/outer/async-store.js +++ b/www/common/outer/async-store.js @@ -2034,7 +2034,7 @@ define([ pin: pin, unpin: unpin, loadSharedFolder: loadSharedFolder, - settings: proxy.settings + settings: proxy.settings, }, { outer: true, removeOwnedChannel: function (channel, cb) { Store.removeOwnedChannel('', channel, cb); }, @@ -2043,7 +2043,8 @@ define([ log: function (msg) { // broadcast to all drive apps sendDriveEvent("DRIVE_LOG", msg); - } + }, + rt: store.realtime }); var userObject = store.userObject = manager.user.userObject; addSharedFolderHandler(); diff --git a/www/common/outer/sharedfolder.js b/www/common/outer/sharedfolder.js index 8e6009a17..4e6d548a3 100644 --- a/www/common/outer/sharedfolder.js +++ b/www/common/outer/sharedfolder.js @@ -19,7 +19,52 @@ define([ var allSharedFolders = {}; - SF.load = function (config, id, data, cb) { + // No version: visible edit + // Version 2: encrypted edit links + SF.checkMigration = function (secondaryKey, proxy, uo, cb) { + if (true) { // XXX remove this block to enable migration at load time + // FIXME history + return void cb(); + } + var drive = proxy.drive || proxy; + // View access: can't migrate + if (!secondaryKey) { return void cb(); } + // Already migrated: nothing to do + if (drive.version >= 2) { return void cb(); } + // Not yet migrating: migrate + if (!drive.migrateRo) { return void uo.migrateReadOnly(cb); } + // Already migrating: wait for the end... + var done = false; + var to; + var it = setInterval(function () { + if (drive.version >= 2) { + done = true; + clearTimeout(to); + clearInterval(it); + return void cb(); + } + }, 100); + var to = setTimeout(function () { + clearInterval(it); + uo.migrateReadOnly(function () { + done = true; + cb(); + }); + }, 20000); + var path = proxy.drive ? ['drive', 'version'] : ['version']; + proxy.on('change', path, function () { + if (done) { return; } + if (drive.version >= 2) { + done = true; + clearTimeout(to); + clearInterval(it); + cb(); + } + }); + }; + + SF.load = function (config, id, data, _cb) { + var cb = Util.once(_cb); var network = config.network; var store = config.store; var teamId = store.id || -1; @@ -36,8 +81,10 @@ define([ // The shared folder is already loaded, return its data setTimeout(function () { var leave = function () { SF.leave(secret.channel, teamId); }; - store.manager.addProxy(id, sf.rt.proxy, leave, secondaryKey); - cb(sf.rt, sf.metadata); + var uo = store.manager.addProxy(id, sf.rt, leave, secondaryKey); + SF.checkMigration(secondaryKey, sf.rt.proxy, uo, function () { + cb(sf.rt, sf.metadata); + }); }); sf.team.push(teamId); if (handler) { handler(id, sf.rt); } @@ -85,13 +132,15 @@ define([ if (!sf.queue) { return; } + sf.leave = info.leave; + sf.metadata = info.metadata; sf.queue.forEach(function (obj) { var leave = function () { SF.leave(secret.channel, teamId); }; - obj.store.manager.addProxy(obj.id, rt.proxy, leave, secondaryKey); - obj.cb(rt, info.metadata); + var uo = obj.store.manager.addProxy(obj.id, rt, leave, secondaryKey); + SF.checkMigration(secondaryKey, rt.proxy, uo, function () { + obj.cb(sf.rt, sf.metadata); + }); }); - sf.leave = info.leave; - sf.metadata = info.metadata; sf.ready = true; delete sf.queue; }); diff --git a/www/common/outer/team.js b/www/common/outer/team.js index 8fa3d65a6..428322d2f 100644 --- a/www/common/outer/team.js +++ b/www/common/outer/team.js @@ -181,6 +181,7 @@ define([ }; }; + var secret; team.pin = function (data, cb) { return void cb({error: 'EFORBIDDEN'}); }; team.unpin = function (data, cb) { return void cb({error: 'EFORBIDDEN'}); }; nThen(function (waitFor) { @@ -216,7 +217,6 @@ define([ }); }; var teamData = ctx.store.proxy.teams[team.id]; - var secret; if (teamData) { secret = Hash.getSecrets('team', teamData.hash, teamData.password); } @@ -229,7 +229,6 @@ define([ settings: { drive: Util.find(ctx.store, ['proxy', 'settings', 'drive']) }, - editKey: secret && secret.keys.secondaryKey }, { outer: true, removeOwnedChannel: function (channel, cb) { @@ -250,13 +249,16 @@ define([ log: function (msg) { // broadcast to all drive apps team.sendEvent("DRIVE_LOG", msg); - } + }, + rt: team.realtime, + editKey: secret && secret.keys.secondaryKey }); team.userObject = manager.user.userObject; team.userObject.fixFiles(); }).nThen(function (waitFor) { ctx.teams[id] = team; registerChangeEvents(ctx, team, proxy); + SF.checkMigration(secret && secret.keys.secondaryKey, proxy, team.userObject, waitFor()); SF.loadSharedFolders(ctx.Store, ctx.store.network, team, team.userObject, waitFor); }).nThen(function () { if (!team.rpc) { return; } diff --git a/www/common/outer/userObject.js b/www/common/outer/userObject.js index 79047f4e3..dcb588ac7 100644 --- a/www/common/outer/userObject.js +++ b/www/common/outer/userObject.js @@ -413,6 +413,45 @@ define([ * INTEGRITY CHECK */ + var onSync = function (next) { + if (exp.rt) { + exp.rt.sync(); + Realtime.whenRealtimeSyncs(exp.rt, next); + } else { + window.setTimeout(next, 1000); + } + }; + + exp.migrateReadOnly = function (cb) { + if (!config.editKey) { return void cb({error: 'EFORBIDDEN'}); } + if (files.version >= 2) { return void cb(); } // Already migrated, nothing to do + files.migrateRo = 1; + var next = function () { + var copy = JSON.parse(JSON.stringify(files)); + Object.keys(copy[FILES_DATA]).forEach(function (id) { + var data = copy[FILES_DATA][id] || {}; + // If this pad has a visible href, encrypt it + // "&& data.roHref" is here to make sure this is not a "file" + if (data.href && data.roHref && !data.fileType && data.href.indexOf('#') !== -1) { + data.href = exp.cryptor.encrypt(data.href); + } + }); + Object.keys(copy[SHARED_FOLDERS] || {}).forEach(function (id) { + var data = copy[SHARED_FOLDERS][id] || {}; + // If this folder has a visible href, encrypt it + if (data.href && data.roHref && !data.fileType && data.href.indexOf('#') !== -1) { + data.href = exp.cryptor.encrypt(data.href); + } + }); + copy.version = 2; + delete copy.migrateRo; + + files = copy; + onSync(cb); + }; + onSync(next); + }; + exp.migrate = function (cb) { // Make sure unsorted doesn't exist anymore // Note: Unsorted only works with the old structure where pads are href @@ -491,13 +530,7 @@ define([ delete files.migrate; todo(); }; - if (exp.rt) { - exp.rt.sync(); - // TODO - Realtime.whenRealtimeSyncs(exp.rt, next); - } else { - window.setTimeout(next, 1000); - } + onSync(next); } catch(e) { console.error(e); todo(); diff --git a/www/common/proxy-manager.js b/www/common/proxy-manager.js index 0e057f874..00fceb15e 100644 --- a/www/common/proxy-manager.js +++ b/www/common/proxy-manager.js @@ -14,25 +14,26 @@ define([ }; // Add a shared folder to the list - var addProxy = function (Env, id, proxy, leave, editKey) { + var addProxy = function (Env, id, lm, leave, editKey) { var cfg = getConfig(Env); cfg.sharedFolder = true; cfg.id = id; cfg.editKey = editKey; - var userObject = UserObject.init(proxy, cfg); + cfg.rt = lm.realtime; + var userObject = UserObject.init(lm.proxy, cfg); if (userObject.fixFiles) { // Only in outer userObject.fixFiles(); } Env.folders[id] = { - proxy: proxy, + proxy: lm.proxy, userObject: userObject, leave: leave }; return userObject; }; - // TODO: Remove a shared folder from the list + // XXX: Remove a shared folder from the list var removeProxy = function (Env, id) { var f = Env.folders[id]; if (!f) { return; } diff --git a/www/common/userObject.js b/www/common/userObject.js index 0dfaf9bee..481c64545 100644 --- a/www/common/userObject.js +++ b/www/common/userObject.js @@ -2,12 +2,11 @@ define([ '/customize/application_config.js', '/common/common-util.js', '/common/common-hash.js', - '/common/common-realtime.js', '/common/common-constants.js', '/common/outer/userObject.js', '/customize/messages.js', '/bower_components/chainpad-crypto/crypto.js', -], function (AppConfig, Util, Hash, Realtime, Constants, OuterFO, Messages, Crypto) { +], function (AppConfig, Util, Hash, Constants, OuterFO, Messages, Crypto) { var module = {}; var ROOT = module.ROOT = "root"; diff --git a/www/drive/inner.js b/www/drive/inner.js index 6f5c3de72..ed2461cd0 100644 --- a/www/drive/inner.js +++ b/www/drive/inner.js @@ -52,7 +52,7 @@ define([ folders[fId] = folders[fId] || {}; copyObjectValue(folders[fId], newObj); if (manager && oldIds.indexOf(fId) === -1) { - manager.addProxy(fId, folders[fId], null, secret.keys.secondaryKey); + manager.addProxy(fId, { proxy: folders[fId] }, null, secret.keys.secondaryKey); } })); }); diff --git a/www/teams/inner.js b/www/teams/inner.js index 7d855558c..b313e78e3 100644 --- a/www/teams/inner.js +++ b/www/teams/inner.js @@ -61,7 +61,7 @@ define([ folders[fId] = folders[fId] || {}; copyObjectValue(folders[fId], newObj); if (manager && oldIds.indexOf(fId) === -1) { - manager.addProxy(fId, folders[fId], null, secret.keys.secondaryKey); + manager.addProxy(fId, { proxy: folders[fId] }, null, secret.keys.secondaryKey); } })); });