From 7971a6d267676bb31cb8e57eec6b0737f661f962 Mon Sep 17 00:00:00 2001 From: yflory Date: Tue, 16 Mar 2021 17:00:23 +0100 Subject: [PATCH] Major broadcast refactoring --- lib/commands/channel.js | 6 ++++-- lib/commands/core.js | 2 +- lib/commands/metadata.js | 3 ++- lib/decrees.js | 35 +++++++++++++++++++------------- lib/env.js | 2 ++ lib/storage/file.js | 4 ++-- lib/workers/db-worker.js | 3 ++- server.js | 3 ++- www/admin/inner.js | 25 +++++++++++++++++++++++ www/common/common-ui-elements.js | 8 ++++++-- www/common/cryptpad-common.js | 4 ---- www/common/outer/async-store.js | 12 ----------- www/common/outer/mailbox.js | 2 +- www/common/outer/sharedworker.js | 14 ------------- 14 files changed, 68 insertions(+), 55 deletions(-) diff --git a/lib/commands/channel.js b/lib/commands/channel.js index f4d9a84ef..e69f93180 100644 --- a/lib/commands/channel.js +++ b/lib/commands/channel.js @@ -191,7 +191,8 @@ var ARRAY_LINE = /^\[/; */ Channel.isNewChannel = function (Env, channel, cb) { if (!Core.isValidId(channel)) { return void cb('INVALID_CHAN'); } - if (channel.length !== 32) { return void cb('INVALID_CHAN'); } + if (channel.length !== HK.STANDARD_CHANNEL_LENGTH && + channel.length !== HK.ADMIN_CHANNEL_LENGTH) { return void cb('INVALID_CHAN'); } // TODO replace with readMessagesBin var done = false; @@ -229,7 +230,8 @@ Channel.writePrivateMessage = function (Env, args, _cb, Server, netfluxId) { if (!msg) { return void cb("INVALID_MESSAGE"); } // don't support anything except regular channels - if (!Core.isValidId(channelId) || channelId.length !== 32) { + if (!Core.isValidId(channelId) || (channelId.length !== HK.STANDARD_CHANNEL_LENGTH + && channelId.length !== HK.ADMIN_CHANNEL_LENGTH)) { return void cb("INVALID_CHAN"); } diff --git a/lib/commands/core.js b/lib/commands/core.js index f4e6a9f70..42ed0455b 100644 --- a/lib/commands/core.js +++ b/lib/commands/core.js @@ -10,7 +10,7 @@ Core.SESSION_EXPIRATION_TIME = 60 * 1000; Core.isValidId = function (chan) { return chan && chan.length && /^[a-zA-Z0-9=+-]*$/.test(chan) && - [32, 48].indexOf(chan.length) > -1; + [32, 33, 48].indexOf(chan.length) > -1; }; var makeToken = Core.makeToken = function () { diff --git a/lib/commands/metadata.js b/lib/commands/metadata.js index 896c89f31..564c4f00d 100644 --- a/lib/commands/metadata.js +++ b/lib/commands/metadata.js @@ -9,7 +9,8 @@ const HK = require("../hk-util"); Data.getMetadataRaw = function (Env, channel /* channelName */, _cb) { const cb = Util.once(Util.mkAsync(_cb)); if (!Core.isValidId(channel)) { return void cb('INVALID_CHAN'); } - if (channel.length !== HK.STANDARD_CHANNEL_LENGTH) { return cb("INVALID_CHAN_LENGTH"); } + if (channel.length !== HK.STANDARD_CHANNEL_LENGTH && + channel.length !== HK.ADMIN_CHANNEL_LENGTH) { return cb("INVALID_CHAN_LENGTH"); } var cached = Env.metadata_cache[channel]; if (HK.isMetadataMessage(cached)) { diff --git a/lib/decrees.js b/lib/decrees.js index bd539e271..7d2a8e037 100644 --- a/lib/decrees.js +++ b/lib/decrees.js @@ -26,6 +26,7 @@ DISABLE_INTEGRATED_EVICTION // BROADCAST SET_LAST_BROADCAST_HASH +SET_SURVEY_URL NOT IMPLEMENTED: @@ -124,23 +125,29 @@ commands.SET_ARCHIVE_RETENTION_TIME = makeIntegerSetter('archiveRetentionTime'); // CryptPad_AsyncStore.rpc.send('ADMIN', [ 'ADMIN_DECREE', ['SET_ACCOUNT_RETENTION_TIME', [365]]], console.log) commands.SET_ACCOUNT_RETENTION_TIME = makeIntegerSetter('accountRetentionTime'); -// CryptPad_AsyncStore.rpc.send('ADMIN', [ 'ADMIN_DECREE', ['SET_LAST_BROADCAST_HASH', [hash]]], console.log) -commands.SET_LAST_BROADCAST_HASH = function (Env, args) { - if (!Array.isArray(args) || typeof(args[0]) !== "string") { - throw new Error('INVALID_ARGS'); - } - if (args[0] && args[0].length !== 64) { - throw new Error('INVALID_ARGS'); - } - var hash = args[0]; - if (hash === Env.lastBroadcastHash) { return false; } +var args_isString = function (args) { + return Array.isArray(args) && typeof(args[0]) === "string"; +}; - // Hash is valid and has changed: update it and clear the broadcast cache - Env.lastBroadcastHash = hash; - Env.broadcastCache = {}; - return true; +var makeBroadcastSetter = function (attr) { + return function (Env, args) { + if (!args_isString(args)) { + throw new Error('INVALID_ARGS'); + } + var str = args[0]; + if (str === Env[attr]) { return false; } + Env[attr] = str; + Env.broadcastCache = {}; + return true; + }; }; +// CryptPad_AsyncStore.rpc.send('ADMIN', [ 'ADMIN_DECREE', ['SET_LAST_BROADCAST_HASH', [hash]]], console.log) +commands.SET_LAST_BROADCAST_HASH = makeBroadcastSetter('lastBroadcastHash'); + +// CryptPad_AsyncStore.rpc.send('ADMIN', [ 'ADMIN_DECREE', ['SET_SURVEY_URL', [url]]], console.log) +commands.SET_SURVEY_URL = makeBroadcastSetter('surveyURL'); + var Quota = require("./commands/quota"); var Keys = require("./keys"); var Util = require("./common-util"); diff --git a/lib/env.js b/lib/env.js index 285f2906a..1a26fa0f9 100644 --- a/lib/env.js +++ b/lib/env.js @@ -67,7 +67,9 @@ module.exports.create = function (config) { paths: {}, //msgStore: config.store, + // /api/broadcast lastBroadcastHash: '', + surveyURL: undefined, netfluxUsers: {}, diff --git a/lib/storage/file.js b/lib/storage/file.js index d890cb0b9..825f14066 100644 --- a/lib/storage/file.js +++ b/lib/storage/file.js @@ -567,7 +567,7 @@ var listChannels = function (root, handler, cb, fast) { var metadataName; // if the current file is not the channel data, then it must be metadata - if (!/^[0-9a-fA-F]{32}\.ndjson$/.test(item)) { + if (!/^[0-9a-fA-F]{32, 33}\.ndjson$/.test(item)) { metadataName = item; channelName = item.replace(/\.metadata/, ''); @@ -584,7 +584,7 @@ var listChannels = function (root, handler, cb, fast) { } var channel = metadataName.replace(/\.metadata.ndjson$/, ''); - if ([32, 34, 44].indexOf(channel.length) === -1) { return; } + if ([32, 33, 34, 44].indexOf(channel.length) === -1) { return; } // otherwise throw it on the pile sema.take(function (give) { diff --git a/lib/workers/db-worker.js b/lib/workers/db-worker.js index 5274445eb..65f13d23b 100644 --- a/lib/workers/db-worker.js +++ b/lib/workers/db-worker.js @@ -391,7 +391,8 @@ const getPinState = function (data, cb) { const _getFileSize = function (channel, _cb) { var cb = Util.once(Util.mkAsync(_cb)); if (!Core.isValidId(channel)) { return void cb('INVALID_CHAN'); } - if (channel.length === 32) { + if (channel.length === HK.STANDARD_CHANNEL_LENGTH || + channel.length === HK.ADMIN_CHANNEL_LENGTH) { return void store.getChannelSize(channel, function (e, size) { if (e) { if (e.code === 'ENOENT') { return void cb(void 0, 0); } diff --git a/server.js b/server.js index 5bf30f05e..f1bde6dd9 100644 --- a/server.js +++ b/server.js @@ -278,7 +278,8 @@ var serveBroadcast = (function () { return [ 'define(function(){', 'return ' + JSON.stringify({ - lastBroadcastHash: Env.lastBroadcastHash + lastBroadcastHash: Env.lastBroadcastHash, + surveyURL: Env.surveyURL }, null, '\t'), '});' ].join(';\n') diff --git a/www/admin/inner.js b/www/admin/inner.js index bcf5c4757..341b9a93a 100644 --- a/www/admin/inner.js +++ b/www/admin/inner.js @@ -1275,6 +1275,31 @@ define([ reset = function () { $input.val(''); }; + $(button).off('click').click(function () { + var data = getData(); + var val = $input.val() || ''; + + // Invalid url: abort + // NOTE: empty strings are allowed to remove a surveyURL from the decrees + // XXX usability... + if (!data && val) { return void UI.warn(Messages.error); } + + var url = data ? data.url : val; + + sFrameChan.query('Q_ADMIN_RPC', { + cmd: 'ADMIN_DECREE', + data: ['SET_SURVEY_URL', [url]] + }, function (e) { + console.error(e); + if (e) { + UI.warn(Messages.error); console.error(e); + return; + } + if (!url) { return; } + send(); + }); + + }); $form.append([ label, input, diff --git a/www/common/common-ui-elements.js b/www/common/common-ui-elements.js index 5eaf65523..0c0059e13 100644 --- a/www/common/common-ui-elements.js +++ b/www/common/common-ui-elements.js @@ -1756,7 +1756,11 @@ define([ }); } - if (AppConfig.surveyURL) { + // XXX Admin panel overrides AppConfig + // If you set "" in the admin panel, it will remove the AppConfig survey + var surveyURL = typeof(ApiConfig.surveyURL) !== "undefined" ? ApiConfig.surveyURL + : AppConfig.surveyURL; + if (surveyURL) { options.push({ tag: 'a', attributes: { @@ -1764,7 +1768,7 @@ define([ }, content: h('span', Messages.survey), action: function () { - Common.openUnsafeURL(AppConfig.surveyURL); + Common.openUnsafeURL(surveyURL); Feedback.send('SURVEY_CLICKED'); }, }); diff --git a/www/common/cryptpad-common.js b/www/common/cryptpad-common.js index 0cc25b684..68e341562 100644 --- a/www/common/cryptpad-common.js +++ b/www/common/cryptpad-common.js @@ -2129,10 +2129,6 @@ define([ common.onNetworkReconnect.fire(data); }); }, - FORCE_RELOAD: function () { - // XXX not used - common.onNewVersionReconnect.fire(); - }, // OnlyOffice OO_EVENT: common.onlyoffice.onEvent.fire, // Mailbox diff --git a/www/common/outer/async-store.js b/www/common/outer/async-store.js index e007c4611..c1ba88500 100644 --- a/www/common/outer/async-store.js +++ b/www/common/outer/async-store.js @@ -2988,18 +2988,6 @@ define([ Store.newVersionReload = function () { broadcast([], "NETWORK_RECONNECT"); - - /* // XXX NETWORK_RECONNECT only works when a manual /api/config is used - // XXX The following code disconnect all tabs and asks for a page reload BUT - // if the urlArgs has not changed, new tabs will stay on the same DISCONNECTED worker - // XXX ==> we should probably keep NETWORK_RECONNECT but keep this "version reload" only for us - // because other instances have to reload the server when a new version is deployed - Store.disconnect(); - broadcast([], "FORCE_RELOAD"); - if (self.CP_closeWorker) { - setTimeout(self.CP_closeWorker, 200); - } - */ }; Store.disconnect = function () { if (self.accountDeletion) { return; } diff --git a/www/common/outer/mailbox.js b/www/common/outer/mailbox.js index 31ffb8c8f..2ef42409c 100644 --- a/www/common/outer/mailbox.js +++ b/www/common/outer/mailbox.js @@ -46,7 +46,7 @@ define([ } // XXX Debugging code to remove deprecated dev data - if (mailboxes.broadcast && mailboxes.broacast.channel && mailboxes.broadcast.channel.length === 32) { + if (mailboxes.broadcast && mailboxes.broadcast.channel && mailboxes.broadcast.channel.length === 32) { delete mailboxes['broadcast']; } diff --git a/www/common/outer/sharedworker.js b/www/common/outer/sharedworker.js index 21b80e1d5..825deb383 100644 --- a/www/common/outer/sharedworker.js +++ b/www/common/outer/sharedworker.js @@ -9,20 +9,6 @@ localStorage = { self.tabs = {}; -// XXX Not used for now -self.CP_closeWorker = function () { - Object.keys(self.tabs).forEach(function (id) { - var obj = self.tabs[id]; - if (obj.port) { return; } - console.error(id); - try { - obj.port.close(); - } catch (e) { - console.error(e); - } - }); -}; - var postMsg = function (client, data) { client.port.postMessage(data); };