From bde6bb00328b42948ee994dd144514841cfa6c4f Mon Sep 17 00:00:00 2001 From: yflory Date: Fri, 14 Oct 2022 16:53:38 +0200 Subject: [PATCH] Clean server code --- lib/commands/channel.js | 32 ++++++++++----- lib/rpc.js | 2 +- lib/storage/file.js | 70 ++++++++++++++++++++++----------- www/common/cryptpad-common.js | 5 +-- www/common/outer/async-store.js | 4 +- www/common/outer/store-rpc.js | 2 +- www/common/pinpad.js | 4 +- 7 files changed, 76 insertions(+), 43 deletions(-) diff --git a/lib/commands/channel.js b/lib/commands/channel.js index 5b1789cf6..0481c5870 100644 --- a/lib/commands/channel.js +++ b/lib/commands/channel.js @@ -208,25 +208,37 @@ Channel.trimHistory = function (Env, safeKey, data, cb) { }); }; -Channel.deleteLine = function (Env, safeKey, data, cb) { +// Delete a signed mailbox message. This is used when users want +// to delete their form reponses. +Channel.deleteMailboxMessage = function (Env, safeKey, data, cb) { const channelId = data.channel; const hash = data.hash; const proof = data.proof; - const nonce = Nacl.util.decodeBase64(proof.split('|')[0]); - const proofBytes = Nacl.util.decodeBase64(proof.split('|')[1]); - Env.msgStore.trimChannel(channelId, hash, function (err) { + let nonce, proofBytes; + try { + nonce = Nacl.util.decodeBase64(proof.split('|')[0]); + proofBytes = Nacl.util.decodeBase64(proof.split('|')[1]); + } catch (e) { + return void cb('EINVAL'); + } + Env.msgStore.deleteChannelLine(channelId, hash, function (msg) { + // Check if you're allowed to delete this hash + try { + const mySecret = new Uint8Array(32); + const msgBytes = Nacl.util.decodeBase64(msg).subarray(64); // Remove signature + const theirPublic = msgBytes.subarray(24,56); // 0-24 = nonce; 24-56=publickey (32 bytes) + const hashBytes = Nacl.box.open(proofBytes, nonce, theirPublic, mySecret); + return Nacl.util.encodeUTF8(hashBytes) === hash; + } catch (e) { + return false; + } + }, function (err) { if (err) { return void cb(err); } // clear historyKeeper's cache for this channel Env.historyKeeper.channelClose(channelId); cb(); delete Env.channel_cache[channelId]; delete Env.metadata_cache[channelId]; - }, function (msg) { - const mySecret = new Uint8Array(32); - const msgBytes = Nacl.util.decodeBase64(msg).subarray(64); // Remove signature - const theirPublic = msgBytes.subarray(24,56); // 0-24 = nonce; 24-56=publickey (32 bytes) - const hashBytes = Nacl.box.open(proofBytes, nonce, theirPublic, mySecret); - return Nacl.util.encodeUTF8(hashBytes) === hash; }); }; diff --git a/lib/rpc.js b/lib/rpc.js index 8c6cf2cf7..0abcaac62 100644 --- a/lib/rpc.js +++ b/lib/rpc.js @@ -47,7 +47,7 @@ const AUTHENTICATED_USER_TARGETED = { CLEAR_OWNED_CHANNEL: Channel.clearOwnedChannel, REMOVE_OWNED_CHANNEL: Channel.removeOwnedChannel, TRIM_HISTORY: Channel.trimHistory, - DELETE_LINE: Channel.deleteLine, + DELETE_MAILBOX_MESSAGE: Channel.deleteMailboxMessage, UPLOAD_STATUS: Upload.status, UPLOAD: Upload.upload, UPLOAD_COMPLETE: Upload.complete, diff --git a/lib/storage/file.js b/lib/storage/file.js index 4d4646aad..ef3d2ddfe 100644 --- a/lib/storage/file.js +++ b/lib/storage/file.js @@ -928,7 +928,7 @@ var getMessages = function (env, chanName, handler, cb) { }); }; -var trimChannel = function (env, channelName, hash, _cb, deleteOneLine) { +var filterMessages = function (env, channelName, check, filterHandler, _cb) { var cb = Util.once(Util.mkAsync(_cb)); // this function is queued as a blocking action for the relevant channel @@ -987,8 +987,8 @@ var trimChannel = function (env, channelName, hash, _cb, deleteOneLine) { })); }).nThen(function (w) { // If we want to delete a signle line of the file, make sure this pad allows it - if (!deleteOneLine) { return; } - if (!metadataReference.meta || !metadataReference.meta.deleteLines) { + if (typeof(check) !== "function") { return; } + if (!metadataReference.meta || !check(metadataReference.meta)) { w.abort(); return void cb("EFORBIDDEN"); } @@ -1030,28 +1030,15 @@ var trimChannel = function (env, channelName, hash, _cb, deleteOneLine) { if (!msg) { return void readMore(); } var msgHash = Extras.getHash(msg[4]); - // If we only want to delete the selected hash... - if (deleteOneLine) { - if (msgHash === hash) { - if (!deleteOneLine(msg[4])) { - return void abort(); - } - retain = true; - return void readMore(); - } - return void tempStream.write(s_msg + '\n', function () { + var remove = function () { readMore(); }; + var preserve = function () { + tempStream.write(s_msg + '\n', function () { readMore(); }); - } + }; + var preserveRemaining = function () { retain = true; }; - if (msgHash === hash) { - // everything from this point on should be retained - retain = true; - return void tempStream.write(s_msg + '\n', function () { - readMore(); - }); - } - readMore(); + filterHandler(msg, msgHash, abort, remove, preserve, preserveRemaining); }; readMessagesBin(env, channelName, 0, handler, w(function (err) { @@ -1123,6 +1110,35 @@ var trimChannel = function (env, channelName, hash, _cb, deleteOneLine) { }); }); }; +var deleteChannelLine = function (env, channelName, hash, checkRights, _cb) { + var check = function (meta) { return Boolean(meta.deleteLines); }; + var handler = function (msg, msgHash, abort, remove, preserve, preserveRemaining) { + if (msgHash === hash) { + if (typeof(checkRights) === "function" && !checkRights(msg[4])) { + // Not allowed: abort + return void abort(); + } + // Line found: remove it and preserve all remaining lines + preserveRemaining(); + return void remove(); + } + // Continue until we find the correct hash + preserve(); + }; + filterMessages(env, channelName, check, handler, _cb); +}; +var trimChannel = function (env, channelName, hash, _cb) { + var handler = function (msg, msgHash, abort, remove, preserve, preserveRemaining) { + if (msgHash === hash) { + // Everything from this point on should be retained + preserveRemaining(); + return void preserve(); + } + // Remove until we find our hash + remove(); + }; + filterMessages(env, channelName, null, handler, _cb); +}; module.exports.create = function (conf, _cb) { var cb = Util.once(Util.mkAsync(_cb)); @@ -1251,10 +1267,16 @@ module.exports.create = function (conf, _cb) { clearChannel(env, channelName, Util.both(cb, next)); }); }, - trimChannel: function (channelName, hash, cb, deleteOne) { + trimChannel: function (channelName, hash, cb) { if (!isValidChannelId(channelName)) { return void cb(new Error('EINVAL')); } schedule.blocking(channelName, function (next) { - trimChannel(env, channelName, hash, Util.both(cb, next), deleteOne); + trimChannel(env, channelName, hash, Util.both(cb, next)); + }); + }, + deleteChannelLine: function (channelName, hash, checkRights, cb) { + if (!isValidChannelId(channelName)) { return void cb(new Error('EINVAL')); } + schedule.blocking(channelName, function (next) { + deleteChannelLine(env, channelName, hash, checkRights, Util.both(cb, next)); }); }, diff --git a/www/common/cryptpad-common.js b/www/common/cryptpad-common.js index c859feeae..e586b3873 100644 --- a/www/common/cryptpad-common.js +++ b/www/common/cryptpad-common.js @@ -206,12 +206,11 @@ define([ hash: hash, proof: proof }; - postMessage("DELETE_PAD_LINE", lineData, waitFor(function (obj) { - if (obj && obj.error === 'EFORBIDDEN') { + postMessage("DELETE_MAILBOX_MESSAGE", lineData, waitFor(function (obj) { + if (obj && obj.error) { waitFor.abort(); return void cb(obj); } - if (obj || obj.error) { return; } toDelete.push(hash); })); }).nThen; diff --git a/www/common/outer/async-store.js b/www/common/outer/async-store.js index a5348eec9..6a17b9b1d 100644 --- a/www/common/outer/async-store.js +++ b/www/common/outer/async-store.js @@ -2179,9 +2179,9 @@ define([ } }; - Store.deletePadLine = function (clientId, data, cb) { + Store.deleteMailboxMessage = function (clientId, data, cb) { if (!store.rpc) { return void cb({error: 'RPC_NOT_READY'}); } - store.rpc.deleteLine(data, function (e) { + store.rpc.deleteMailboxMessage(data, function (e) { cb({error:e}); }); }; diff --git a/www/common/outer/store-rpc.js b/www/common/outer/store-rpc.js index 2a3ff94de..1c622d2a0 100644 --- a/www/common/outer/store-rpc.js +++ b/www/common/outer/store-rpc.js @@ -88,7 +88,7 @@ define([ GET_LAST_HASH: Store.getLastHash, GET_SNAPSHOT: Store.getSnapshot, CORRUPTED_CACHE: Store.corruptedCache, - DELETE_PAD_LINE: Store.deletePadLine, + DELETE_MAILBOX_MESSAGE: Store.deleteMailboxMessage, // Drive DRIVE_USEROBJECT: Store.userObjectCommand, // Settings, diff --git a/www/common/pinpad.js b/www/common/pinpad.js index 3dcc6c7c6..e91ebdbf3 100644 --- a/www/common/pinpad.js +++ b/www/common/pinpad.js @@ -249,8 +249,8 @@ var factory = function (Util, Rpc) { }, cb); }; - exp.deleteLine = function (obj, cb) { - rpc.send('DELETE_LINE', { + exp.deleteMailboxMessage = function (obj, cb) { + rpc.send('DELETE_MAILBOX_MESSAGE', { channel: obj.channel, hash: obj.hash, proof: obj.proof