From 039ab83440f29393a59e420c38ee219ff4884fd2 Mon Sep 17 00:00:00 2001 From: yflory Date: Thu, 7 Nov 2019 17:02:22 +0100 Subject: [PATCH 1/6] Improve migration script --- www/common/outer/userObject.js | 18 ++++++++++++------ www/common/userObject.js | 7 +++++-- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/www/common/outer/userObject.js b/www/common/outer/userObject.js index 2ee1a1830..6ba0cd6d2 100644 --- a/www/common/outer/userObject.js +++ b/www/common/outer/userObject.js @@ -480,13 +480,19 @@ define([ var next = function () { var copy = JSON.parse(JSON.stringify(files)); exp.reencrypt(config.editKey, config.editKey, copy); - Object.keys(copy).forEach(function (k) { - files[k] = copy[k]; - }); - files.version = 2; - delete files.migrateRo; + setTimeout(function () { + if (files.version >= 2) { + // Already migrated by another user while we were re-encrypting + return void cb(); + } + Object.keys(copy).forEach(function (k) { + files[k] = copy[k]; + }); + files.version = 2; + delete files.migrateRo; - onSync(cb); + onSync(cb); + }, 1000); }; onSync(next); }; diff --git a/www/common/userObject.js b/www/common/userObject.js index 1c58ff831..57c1a1e6e 100644 --- a/www/common/userObject.js +++ b/www/common/userObject.js @@ -61,7 +61,7 @@ define([ // Href exists and is encrypted var d = cryptor.decrypt(pad.href); // If we can decrypt, return the decrypted value, otherwise continue and return roHref - if (d.indexOf('#') !== -1) { + if (d && d.indexOf('#') !== -1) { return d; } } @@ -69,7 +69,7 @@ define([ }; module.reencrypt = function (oldKey, newKey, obj) { - obj = obj || {}; + if (!obj) { return void console.error("Nothing to reencrypt"); } var oldCryptor = createCryptor(oldKey); var newCryptor = createCryptor(newKey); Object.keys(obj[FILES_DATA]).forEach(function (id) { @@ -78,6 +78,7 @@ define([ // "&& data.roHref" is here to make sure this is not a "file" if (data.href && data.roHref && !data.fileType) { var _href = (data.href && data.href.indexOf('#') === -1) ? oldCryptor.decrypt(data.href) : data.href; + if (!_href) { return; } data.href = newCryptor.encrypt(_href); } }); @@ -86,6 +87,7 @@ define([ // If this folder has a visible href, encrypt it if (data.href) { var _href = (data.href && data.href.indexOf('#') === -1) ? oldCryptor.decrypt(data.href) : data.href; + if (!_href) { return; } data.href = newCryptor.encrypt(_href); } }); @@ -94,6 +96,7 @@ define([ // If this folder has a visible href, encrypt it if (data.href) { var _href = (data.href && data.href.indexOf('#') === -1) ? oldCryptor.decrypt(data.href) : data.href; + if (!_href) { return; } data.href = newCryptor.encrypt(_href); } }); From 722d813e976e9af06533f542aed5193ea58e8295 Mon Sep 17 00:00:00 2001 From: yflory Date: Fri, 8 Nov 2019 10:15:54 +0100 Subject: [PATCH 2/6] Enable read-only migration for teams --- www/common/outer/sharedfolder.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/www/common/outer/sharedfolder.js b/www/common/outer/sharedfolder.js index 4b1482556..60ef8dd9a 100644 --- a/www/common/outer/sharedfolder.js +++ b/www/common/outer/sharedfolder.js @@ -22,10 +22,6 @@ define([ // 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(); } @@ -127,9 +123,13 @@ define([ setTimeout(function () { var leave = function () { SF.leave(secret.channel, teamId); }; var uo = store.manager.addProxy(id, sf.rt, leave, secondaryKey); + /* + // NOTE: Shared folder migration, disable for now SF.checkMigration(secondaryKey, sf.rt.proxy, uo, function () { cb(sf.rt, sf.metadata); }); + */ + cb(sf.rt, sf.metadata); }); sf.teams.push({ cb: cb, @@ -189,9 +189,13 @@ define([ sf.teams.forEach(function (obj) { var leave = function () { SF.leave(secret.channel, teamId); }; var uo = obj.store.manager.addProxy(obj.id, rt, leave, obj.secondaryKey); + /* + // NOTE: Shared folder migration, disable for now SF.checkMigration(secondaryKey, rt.proxy, uo, function () { obj.cb(sf.rt, info.metadata); }); + */ + obj.cb(sf.rt, info.metadata); }); sf.metadata = info.metadata; sf.ready = true; From 5dcc7643da268d70ed7d78a5e37d6e23477cc837 Mon Sep 17 00:00:00 2001 From: yflory Date: Fri, 8 Nov 2019 12:04:30 +0100 Subject: [PATCH 3/6] Fix missing teams in the share modal --- www/common/common-ui-elements.js | 2 +- www/common/drive-ui.js | 12 +++++++++++- www/common/outer/team.js | 3 +++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/www/common/common-ui-elements.js b/www/common/common-ui-elements.js index 1ee5a9608..34fb16474 100644 --- a/www/common/common-ui-elements.js +++ b/www/common/common-ui-elements.js @@ -882,7 +882,7 @@ define([ // config.teamId only exists when we're trying to share a pad from a team drive // In this case, we don't want to share the pad with the current team if (config.teamId && config.teamId === id) { return; } - if (!teamsData[id].secondaryKey) { return; } + if (!teamsData[id].hasSecondaryKey) { return; } var t = teamsData[id]; teams[t.edPublic] = { notifications: true, diff --git a/www/common/drive-ui.js b/www/common/drive-ui.js index f3ef49bcc..3b52e3193 100644 --- a/www/common/drive-ui.js +++ b/www/common/drive-ui.js @@ -1888,9 +1888,16 @@ define([ var $password = $passwordIcon.clone().appendTo($state); $password.attr('title', Messages.fm_passwordProtected || ''); } + if (hrefData.hashData && hrefData.hashData.mode === 'view') { + var $ro = $readonlyIcon.clone().appendTo($state); + $ro.attr('title', Messages.readonly); + } var $shared = $sharedIcon.clone().appendTo($state); $shared.attr('title', Messages.fm_canBeShared); + } else if ($content.data('readOnlyFolder') || APP.readOnly) { + var $ro = $readonlyIcon.clone().appendTo($state); + $ro.attr('title', Messages.readonly); } var sf = manager.hasSubfolder(element); @@ -2559,6 +2566,10 @@ define([ viewHash: ro && roParsed.hash, } }); + // If we're a viewer and this is an old shared folder (no read-only mode), we + // can't share the read-only URL and we don't have access to the edit one. + // We should hide the share button. + if (!modal) { return; } modal = UI.dialog.tabs(modal); $shareBlock.click(function () { UI.openCustomModal(modal, { @@ -4079,7 +4090,6 @@ define([ var roParsed = Hash.parsePadUrl(data.roHref); var padType = parsed.type || roParsed.type; var ro = !sf || (folders[el] && folders[el].version >= 2); - console.log(folders[el]); var padData = { teamId: APP.team, origin: APP.origin, diff --git a/www/common/outer/team.js b/www/common/outer/team.js index ada4361c5..caac0704e 100644 --- a/www/common/outer/team.js +++ b/www/common/outer/team.js @@ -1309,6 +1309,9 @@ define([ if (safe && ctx.teams[id]) { t[id].secondaryKey = ctx.teams[id].secondaryKey; } + if (ctx.teams[id]) { + t[id].hasSecondaryKey = Boolean(ctx.teams[id].secondaryKey); + } }); return t; }; From f42574948e80bbb25f869a65b8681121a96dc9aa Mon Sep 17 00:00:00 2001 From: yflory Date: Fri, 8 Nov 2019 12:07:08 +0100 Subject: [PATCH 4/6] Encrypt href for new pads in old shared folders --- www/common/outer/sharedfolder.js | 2 +- www/common/proxy-manager.js | 7 ------- www/common/userObject.js | 4 ---- 3 files changed, 1 insertion(+), 12 deletions(-) diff --git a/www/common/outer/sharedfolder.js b/www/common/outer/sharedfolder.js index 60ef8dd9a..47cfe5458 100644 --- a/www/common/outer/sharedfolder.js +++ b/www/common/outer/sharedfolder.js @@ -59,7 +59,7 @@ define([ }); }; - // XXX only needed if we want a manual migration from the share modal... + // SFMIGRATION: only needed if we want a manual migration from the share modal... SF.migrate = function (channel) { var sf = allSharedFolders[channel]; if (!sf) { return; } diff --git a/www/common/proxy-manager.js b/www/common/proxy-manager.js index 4c5e2d2e4..1bd88e90b 100644 --- a/www/common/proxy-manager.js +++ b/www/common/proxy-manager.js @@ -39,13 +39,6 @@ define([ userObject: userObject, leave: leave }; - if (false) { // XXX allow shared folder migration while using it - // NOTE: this is not needed if we always use the editKey in userObject, even with old version - var path = proxy.drive ? ['drive', 'version'] : ['version']; - proxy.on('change', path, function () { - userObject.setReadOnly(false, editKey); - }); - } return userObject; }; diff --git a/www/common/userObject.js b/www/common/userObject.js index 57c1a1e6e..7ac1bfe88 100644 --- a/www/common/userObject.js +++ b/www/common/userObject.js @@ -105,10 +105,6 @@ define([ module.init = function (files, config) { var exp = {}; - if (false && !files.version) { // XXX if we remove false, old shared folders won't encrypt new hrefs - config.editKey = undefined; - } - exp.cryptor = createCryptor(config.editKey); exp.setReadOnly = function (state, key) { From f44e6f971985d98fc6c3bbad744f1a4755c81aae Mon Sep 17 00:00:00 2001 From: yflory Date: Fri, 8 Nov 2019 12:08:21 +0100 Subject: [PATCH 5/6] lint compliance --- www/common/outer/sharedfolder.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/www/common/outer/sharedfolder.js b/www/common/outer/sharedfolder.js index 47cfe5458..e4d8d152c 100644 --- a/www/common/outer/sharedfolder.js +++ b/www/common/outer/sharedfolder.js @@ -122,13 +122,14 @@ define([ // The shared folder is already loaded, return its data setTimeout(function () { var leave = function () { SF.leave(secret.channel, teamId); }; - var uo = store.manager.addProxy(id, sf.rt, leave, secondaryKey); /* + var uo = store.manager.addProxy(id, sf.rt, leave, secondaryKey); // NOTE: Shared folder migration, disable for now SF.checkMigration(secondaryKey, sf.rt.proxy, uo, function () { cb(sf.rt, sf.metadata); }); */ + store.manager.addProxy(id, sf.rt, leave, secondaryKey); cb(sf.rt, sf.metadata); }); sf.teams.push({ @@ -188,13 +189,14 @@ define([ } sf.teams.forEach(function (obj) { var leave = function () { SF.leave(secret.channel, teamId); }; - var uo = obj.store.manager.addProxy(obj.id, rt, leave, obj.secondaryKey); /* + var uo = obj.store.manager.addProxy(obj.id, rt, leave, obj.secondaryKey); // NOTE: Shared folder migration, disable for now SF.checkMigration(secondaryKey, rt.proxy, uo, function () { obj.cb(sf.rt, info.metadata); }); */ + obj.store.manager.addProxy(obj.id, rt, leave, obj.secondaryKey); obj.cb(sf.rt, info.metadata); }); sf.metadata = info.metadata; From 5290bcf79169ae49111c50223a0416fc4fb70404 Mon Sep 17 00:00:00 2001 From: yflory Date: Fri, 8 Nov 2019 12:42:06 +0100 Subject: [PATCH 6/6] Remove edit actions in read-only shared folder context menu --- www/common/drive-ui.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/www/common/drive-ui.js b/www/common/drive-ui.js index 3b52e3193..993d50057 100644 --- a/www/common/drive-ui.js +++ b/www/common/drive-ui.js @@ -1122,6 +1122,10 @@ define([ paths.forEach(function (p) { var path = p.path; var $element = p.element; + + if (APP.$content.data('readOnlyFolder') && + manager.isSubpath(path, currentPath)) { editable = false; } + if (!$element.closest("#cp-app-drive-tree").length) { hide.push('expandall'); hide.push('collapseall'); @@ -1267,6 +1271,7 @@ define([ show.forEach(function (className) { var $el = $contextMenu.find('.cp-app-drive-context-' + className); if ((!APP.editable || !editable) && $el.is('.cp-app-drive-context-editable')) { return; } + if ((!APP.editable || !editable) && $el.is('.cp-app-drive-context-editable')) { return; } if (filter($el, className)) { return; } $el.parent('li').show(); filtered.push('.cp-app-drive-context-' + className); @@ -1876,6 +1881,7 @@ define([ if (!element || !manager.isFolder(element)) { return; } // The element with the class '.name' is underlined when the 'li' is hovered var $state = $('', {'class': 'cp-app-drive-element-state'}); + var $ro; if (manager.isSharedFolder(element)) { var data = manager.getSharedFolderData(element); key = data && data.title ? data.title : key; @@ -1889,14 +1895,14 @@ define([ $password.attr('title', Messages.fm_passwordProtected || ''); } if (hrefData.hashData && hrefData.hashData.mode === 'view') { - var $ro = $readonlyIcon.clone().appendTo($state); + $ro = $readonlyIcon.clone().appendTo($state); $ro.attr('title', Messages.readonly); } var $shared = $sharedIcon.clone().appendTo($state); $shared.attr('title', Messages.fm_canBeShared); } else if ($content.data('readOnlyFolder') || APP.readOnly) { - var $ro = $readonlyIcon.clone().appendTo($state); + $ro = $readonlyIcon.clone().appendTo($state); $ro.attr('title', Messages.readonly); }