From 412670c8a6ab813c15965185fece44d4b253e4f9 Mon Sep 17 00:00:00 2001 From: yflory Date: Tue, 5 Feb 2019 15:58:49 +0100 Subject: [PATCH] PCS with owners and password for spreadsheets --- www/common/common-ui-elements.js | 16 ++++++------ www/common/onlyoffice/inner.js | 20 ++++++++++++--- www/common/onlyoffice/main.js | 42 ++++++++++++++++++++----------- www/common/outer/onlyoffice.js | 1 + www/common/outer/userObject.js | 6 +++++ www/common/proxy-manager.js | 16 +++++++++--- www/common/sframe-common-outer.js | 3 +++ www/common/sframe-common.js | 4 +-- 8 files changed, 77 insertions(+), 31 deletions(-) diff --git a/www/common/common-ui-elements.js b/www/common/common-ui-elements.js index 3e3660ca4..d682e6c74 100644 --- a/www/common/common-ui-elements.js +++ b/www/common/common-ui-elements.js @@ -1992,7 +1992,7 @@ define([ $expire.find('#cp-creation-expire-false').attr('checked', true); } }; - UIElements.getPadCreationScreen = function (common, cfg, cb) { + UIElements.getPadCreationScreen = function (common, cfg, appCfg, cb) { if (!common.isLoggedIn()) { return void cb(); } var sframeChan = common.getSframeChannel(); var metadataMgr = common.getMetadataMgr(); @@ -2119,12 +2119,14 @@ define([ } return b.used - a.used; }); - allData.unshift({ - name: Messages.creation_newTemplate, - id: -1, - //icon: h('span.fa.fa-bookmark') - icon: h('span.cptools.cptools-new-template') - }); + if (!appCfg.noTemplates) { + allData.unshift({ + name: Messages.creation_newTemplate, + id: -1, + //icon: h('span.fa.fa-bookmark') + icon: h('span.cptools.cptools-new-template') + }); + } allData.unshift({ name: Messages.creation_noTemplate, id: 0, diff --git a/www/common/onlyoffice/inner.js b/www/common/onlyoffice/inner.js index f40e42530..aa83ccbed 100644 --- a/www/common/onlyoffice/inner.js +++ b/www/common/onlyoffice/inner.js @@ -870,10 +870,12 @@ define([ var $rightside = toolbar.$rightside; - /*var $save = common.createButton('save', true, {}, function () { - saveToServer(); - }); - $save.appendTo($rightside);*/ + if (window.CP_DEV_MODE) { + var $save = common.createButton('save', true, {}, function () { + saveToServer(); + }); + $save.appendTo($rightside); + } var $export = common.createButton('export', true, {}, exportFile); $export.appendTo($rightside); @@ -940,6 +942,12 @@ define([ }); }; + config.onError = function (err) { + common.onServerError(err, toolbar, function () { + setEditable(false); + }); + }; + config.onRemote = function () { if (initializing) { return; } var userDoc = APP.realtime.getUserDoc(); @@ -1013,6 +1021,10 @@ define([ UI.addLoadingScreen(); })); SFCommon.create(waitFor(function (c) { APP.common = common = c; })); + }).nThen(function (waitFor) { + common.handleNewFile(waitFor, { + noTemplates: true + }); }).nThen(function (/*waitFor*/) { andThen(common); }); diff --git a/www/common/onlyoffice/main.js b/www/common/onlyoffice/main.js index 75f87815c..d056cad42 100644 --- a/www/common/onlyoffice/main.js +++ b/www/common/onlyoffice/main.js @@ -40,8 +40,6 @@ define([ obj.ooType = window.location.pathname.replace(/^\//, '').replace(/\/$/, ''); }; var addRpc = function (sframeChan, Cryptpad, Utils) { - var crypto = Utils.Crypto.createEncryptor(Utils.secret.keys); - sframeChan.on('Q_OO_SAVE', function (data, cb) { var chanId = Utils.Hash.hrefToHexChannelId(data.url); Cryptpad.getPadAttribute('lastVersion', function (err, data) { @@ -63,21 +61,36 @@ define([ Cryptpad.setPadAttribute('rtChannel', data.channel, function () {}); }); }); - Cryptpad.onlyoffice.execCommand({ - cmd: 'OPEN_CHANNEL', - data: { - // XXX add owners? - // owners: something... - channel: data.channel, - lastCpHash: data.lastCpHash, - padChan: Utils.secret.channel, - validateKey: Utils.secret.keys.validateKey + var owners, expire; + nThen(function (waitFor) { + if (Utils.rtConfig) { + owners = Utils.rtConfig.owners; + expire = Utils.rtConfig.expire; + return; } - }, cb); + Cryptpad.getPadAttribute('owners', waitFor(function (err, res) { + owners = res; + })); + Cryptpad.getPadAttribute('expire', waitFor(function (err, res) { + expire = res; + })); + }).nThen(function () { + Cryptpad.onlyoffice.execCommand({ + cmd: 'OPEN_CHANNEL', + data: { + owners: owners, + expire: expire, + channel: data.channel, + lastCpHash: data.lastCpHash, + padChan: Utils.secret.channel, + validateKey: Utils.secret.keys.validateKey + } + }, cb); + }); }); sframeChan.on('Q_OO_COMMAND', function (obj, cb) { if (obj.cmd === 'SEND_MESSAGE') { - obj.data.msg = crypto.encrypt(JSON.stringify(obj.data.msg)); + obj.data.msg = Utils.crypto.encrypt(JSON.stringify(obj.data.msg)); var hash = obj.data.msg.slice(0,64); var _cb = cb; cb = function () { @@ -90,7 +103,7 @@ define([ if (obj.ev === 'MESSAGE' && !/^cp\|/.test(obj.data)) { try { obj.data = { - msg: JSON.parse(crypto.decrypt(obj.data, Utils.secret.keys.validateKey)), + msg: JSON.parse(Utils.crypto.decrypt(obj.data, Utils.secret.keys.validateKey)), hash: obj.data.slice(0,64) }; } catch (e) { @@ -102,6 +115,7 @@ define([ }; SFCommonO.start({ type: 'oo', + useCreationScreen: true, addData: addData, addRpc: addRpc, messaging: true diff --git a/www/common/outer/onlyoffice.js b/www/common/outer/onlyoffice.js index bafd1a7b9..3b57b4123 100644 --- a/www/common/outer/onlyoffice.js +++ b/www/common/outer/onlyoffice.js @@ -87,6 +87,7 @@ define([ validateKey: obj.validateKey, lastKnownHash: chan.lastKnownHash || chan.lastCpHash, owners: obj.owners, + expire: obj.expire }; var msg = ['GET_HISTORY', wc.id, cfg]; // Add the validateKey if we are the channel creator and we have a validateKey diff --git a/www/common/outer/userObject.js b/www/common/outer/userObject.js index ae8879e31..a246b5f5f 100644 --- a/www/common/outer/userObject.js +++ b/www/common/outer/userObject.js @@ -107,8 +107,14 @@ define([ Feedback.send('ERROR_DELETING_OWNED_PAD=' + channelId + '|' + obj.error, true); } }); + // Also remove the realtime channel for onlyoffice + if (fd.rtChannel) { + removeOwnedChannel(fd.rtChannel, function () {}); + } + // XXX fd.lastVersion to delete the encrypted cp? } if (fd.lastVersion) { toClean.push(Hash.hrefToHexChannelId(fd.lastVersion)); } + if (fd.rtChannel) { toClean.push(fd.rtChannel); } if (channelId) { toClean.push(channelId); } if (exp.isSharedFolder(id)) { delete files[SHARED_FOLDERS][id]; diff --git a/www/common/proxy-manager.js b/www/common/proxy-manager.js index 76d5f3ab8..d23ab3ebc 100644 --- a/www/common/proxy-manager.js +++ b/www/common/proxy-manager.js @@ -490,13 +490,13 @@ define([ }); } uo.delete(resolved.main, waitFor(function (err, _toUnpin, _ownedRemoved) { + ownedRemoved = _ownedRemoved; if (!Env.unpinPads || !_toUnpin) { return; } Array.prototype.push.apply(toUnpin, _toUnpin); - ownedRemoved = _ownedRemoved; })); } }).nThen(function (waitFor) { - // Check if removed owned pads are duplicated is some shared folders + // Check if removed owned pads are duplicated in some shared folders // If that's the case, we have to remove them from the shared folders too // We can do that by adding their paths to the list of pads to remove from shared folders if (ownedRemoved) { @@ -526,8 +526,13 @@ define([ // Deleted channels toUnpin = Util.deduplicateString(toUnpin); // Deleted channels that are still in another proxy - var toKeep = _findChannels(Env, toUnpin).map(function (id) { - return _getFileData(Env, id).channel; + var toKeep = []; + _findChannels(Env, toUnpin).forEach(function (id) { + var data = _getFileData(Env, id); + var arr = [data.channel]; + if (data.rtChannel) { arr.push(data.rtChannel); } + if (data.lastVersion) { arr.push(Hash.hrefToHexChannelId(data.lastVersion)); } + Array.prototype.push.apply(toKeep, arr); }); // Compute the unpin list and unpin var unpinList = []; @@ -715,6 +720,9 @@ define([ result.push(otherChan); } } + if (data.rtChannel && result.indexOf(data.rtChannel) === -1) { + result.push(data.rtChannel); + } if (result.indexOf(data.channel) === -1) { result.push(data.channel); } diff --git a/www/common/sframe-common-outer.js b/www/common/sframe-common-outer.js index 4d25d0c50..3c97a4735 100644 --- a/www/common/sframe-common-outer.js +++ b/www/common/sframe-common-outer.js @@ -255,6 +255,7 @@ define([ secret.keys = secret.key; readOnly = false; } + Utils.crypto = Utils.Crypto.createEncryptor(Utils.secret.keys); var parsed = Utils.Hash.parsePadUrl(window.location.href); if (!parsed.type) { throw new Error(); } var defaultTitle = Utils.Hash.getDefaultName(parsed); @@ -953,6 +954,7 @@ define([ password = data.password; var newHash = Utils.Hash.createRandomHash(parsed.type, password); secret = Utils.secret = Utils.Hash.getSecrets(parsed.type, newHash, password); + Utils.crypto = Utils.Crypto.createEncryptor(Utils.secret.keys); // Update the hash in the address bar var ohc = window.onhashchange; @@ -975,6 +977,7 @@ define([ if (data.expire) { rtConfig.expire = data.expire; } + Utils.rtConfig = rtConfig; nThen(function(waitFor) { if (data.templateId) { if (data.templateId === -1) { diff --git a/www/common/sframe-common.js b/www/common/sframe-common.js index 36f9bd449..89c0feab7 100644 --- a/www/common/sframe-common.js +++ b/www/common/sframe-common.js @@ -241,7 +241,7 @@ define([ }; // Store - funcs.handleNewFile = function (waitFor) { + funcs.handleNewFile = function (waitFor, config) { if (window.__CRYPTPAD_TEST__) { return; } var priv = ctx.metadataMgr.getPrivateData(); if (priv.isNewFile) { @@ -262,7 +262,7 @@ define([ return void funcs.createPad(c, waitFor()); } // If we display the pad creation screen, it will handle deleted pads directly - funcs.getPadCreationScreen(c, waitFor()); + funcs.getPadCreationScreen(c, config, waitFor()); } }; funcs.createPad = function (cfg, cb) {