diff --git a/www/common/common-ui-elements.js b/www/common/common-ui-elements.js index 6d2cf84b5..23af78474 100644 --- a/www/common/common-ui-elements.js +++ b/www/common/common-ui-elements.js @@ -915,7 +915,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..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; @@ -1888,9 +1894,16 @@ define([ var $password = $passwordIcon.clone().appendTo($state); $password.attr('title', Messages.fm_passwordProtected || ''); } + if (hrefData.hashData && hrefData.hashData.mode === 'view') { + $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) { + $ro = $readonlyIcon.clone().appendTo($state); + $ro.attr('title', Messages.readonly); } var sf = manager.hasSubfolder(element); @@ -2559,6 +2572,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 +4096,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/sharedfolder.js b/www/common/outer/sharedfolder.js index 4b1482556..e4d8d152c 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(); } @@ -63,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; } @@ -126,10 +122,15 @@ 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); + // 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({ cb: cb, @@ -188,10 +189,15 @@ 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.store.manager.addProxy(obj.id, rt, leave, obj.secondaryKey); + obj.cb(sf.rt, info.metadata); }); sf.metadata = info.metadata; sf.ready = true; 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; }; 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/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 1c58ff831..7ac1bfe88 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); } }); @@ -102,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) {