From 36e790dee6501b2e49097874eb7134cdb5eb85eb Mon Sep 17 00:00:00 2001 From: ansuz Date: Wed, 29 Apr 2020 14:40:42 -0400 Subject: [PATCH 1/7] style support tickets from premium users via a class --- www/admin/app-admin.less | 3 +++ www/support/ui.js | 5 ++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/www/admin/app-admin.less b/www/admin/app-admin.less index 84532c6c5..787c31219 100644 --- a/www/admin/app-admin.less +++ b/www/admin/app-admin.less @@ -47,5 +47,8 @@ color: @colortheme_logo-2; } } + .cp-support-frompremium { + border: 2px solid red; + } } diff --git a/www/support/ui.js b/www/support/ui.js index 2038d8ddd..234953cb6 100644 --- a/www/support/ui.js +++ b/www/support/ui.js @@ -188,6 +188,7 @@ define([ var senderKey = content.sender && content.sender.edPublic; var fromMe = senderKey === privateData.edPublic; var fromAdmin = ctx.adminKeys.indexOf(senderKey) !== -1; + var fromPremium = Boolean(privateData.plan); var userData = h('div.cp-support-showdata', [ Messages.support_showData, @@ -199,8 +200,10 @@ define([ ev.stopPropagation(); }); + var adminClass = (fromAdmin? '.cp-support-fromadmin': ''); + var premiumClass = (fromPremium? '.cp-support-frompremium': ''); var name = Util.fixHTML(content.sender.name) || Messages.anonymous; - return h('div.cp-support-list-message' + (fromAdmin? '.cp-support-fromadmin': ''), { + return h('div.cp-support-list-message' + adminClass + premiumClass, { 'data-hash': hash }, [ h('div.cp-support-message-from' + (fromMe ? '.cp-support-fromme' : ''), [ From 6dc6fed21de3bd4e7c447841241db11d09c703bb Mon Sep 17 00:00:00 2001 From: ansuz Date: Wed, 29 Apr 2020 14:51:09 -0400 Subject: [PATCH 2/7] check whether support tickets came from a premium user, not whether the person viewing the content is a premium user --- www/support/ui.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/www/support/ui.js b/www/support/ui.js index 234953cb6..ba6ae9967 100644 --- a/www/support/ui.js +++ b/www/support/ui.js @@ -188,7 +188,7 @@ define([ var senderKey = content.sender && content.sender.edPublic; var fromMe = senderKey === privateData.edPublic; var fromAdmin = ctx.adminKeys.indexOf(senderKey) !== -1; - var fromPremium = Boolean(privateData.plan); + var fromPremium = Boolean(content.sender.plan); var userData = h('div.cp-support-showdata', [ Messages.support_showData, @@ -201,7 +201,7 @@ define([ }); var adminClass = (fromAdmin? '.cp-support-fromadmin': ''); - var premiumClass = (fromPremium? '.cp-support-frompremium': ''); + var premiumClass = (fromPremium && !fromAdmin? '.cp-support-frompremium': ''); var name = Util.fixHTML(content.sender.name) || Messages.anonymous; return h('div.cp-support-list-message' + adminClass + premiumClass, { 'data-hash': hash From 488f876ad6f617ff554263b57bd419a6804009be Mon Sep 17 00:00:00 2001 From: ansuz Date: Wed, 29 Apr 2020 17:23:29 -0400 Subject: [PATCH 3/7] lint compliance --- lib/log.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/log.js b/lib/log.js index 386ee6b41..a815500b0 100644 --- a/lib/log.js +++ b/lib/log.js @@ -28,7 +28,7 @@ var handlers = {}; handlers[level] = function (ctx, content) { console.log(content); }; }); ['warn', 'error'].forEach(function (level) { - handlers[level] = function (ctx, content) { console.error(content); } + handlers[level] = function (ctx, content) { console.error(content); }; }); var noop = function () {}; From 9975c27e84674e5cdcf73498c742617b605741d2 Mon Sep 17 00:00:00 2001 From: ansuz Date: Wed, 29 Apr 2020 17:24:38 -0400 Subject: [PATCH 4/7] increase timeout from one minute to three and decrease the number of parallel jobs per worker --- lib/workers/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/workers/index.js b/lib/workers/index.js index 911b34337..6858dffb5 100644 --- a/lib/workers/index.js +++ b/lib/workers/index.js @@ -8,7 +8,7 @@ const Workers = module.exports; const PID = process.pid; const DB_PATH = 'lib/workers/db-worker'; -const MAX_JOBS = 16; +const MAX_JOBS = 8; Workers.initialize = function (Env, config, _cb) { var cb = Util.once(Util.mkAsync(_cb)); @@ -97,7 +97,7 @@ Workers.initialize = function (Env, config, _cb) { // track which worker is doing which jobs state.tasks[txid] = msg; - response.expect(txid, cb, 60000); + response.expect(txid, cb, 180000); state.worker.send(msg); }; From dc383615e0f40cbfc72ddf95f8936427f22f63d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Benqu=C3=A9?= Date: Thu, 30 Apr 2020 15:46:21 +0100 Subject: [PATCH 5/7] different color for premium users --- www/admin/app-admin.less | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/www/admin/app-admin.less b/www/admin/app-admin.less index 787c31219..96d89b44b 100644 --- a/www/admin/app-admin.less +++ b/www/admin/app-admin.less @@ -32,9 +32,18 @@ .cp-support-list-message { &:last-child:not(.cp-support-fromadmin) { color: @colortheme_cp-red; - background-color: lighten(@colortheme_cp-red, 25%); + background-color: lighten(@colortheme_form-warning, 25%); .cp-support-showdata { - background-color: lighten(@colortheme_cp-red, 30%); + background-color: lighten(@colortheme_form-warning, 30%); + } + } + + &:last-child { + &.cp-support-frompremium { + background-color: lighten(@colortheme_cp-red, 25%); + .cp-support-showdata { + background-color: lighten(@colortheme_cp-red, 30%); + } } } } @@ -47,8 +56,5 @@ color: @colortheme_logo-2; } } - .cp-support-frompremium { - border: 2px solid red; - } } From ddd12bfd7a1978f71744586ade78ba96c9f5dbac Mon Sep 17 00:00:00 2001 From: ansuz Date: Thu, 30 Apr 2020 16:48:49 -0400 Subject: [PATCH 6/7] remove grey style from mermaid flowcharts --- www/common/diffMarked.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/www/common/diffMarked.js b/www/common/diffMarked.js index fc9c4046c..48f800075 100644 --- a/www/common/diffMarked.js +++ b/www/common/diffMarked.js @@ -23,7 +23,7 @@ define([ init: function () {} }; - var mermaidThemeCSS = ".node rect { fill: #DDD; stroke: #AAA; } " + + var mermaidThemeCSS = //".node rect { fill: #DDD; stroke: #AAA; } " + "rect.task, rect.task0, rect.task2 { stroke-width: 1 !important; rx: 0 !important; } " + "g.grid g.tick line { opacity: 0.25; }" + "g.today line { stroke: red; stroke-width: 1; stroke-dasharray: 3; opacity: 0.5; }"; From 02347d134aaa12793691f334ea844d578fe287c3 Mon Sep 17 00:00:00 2001 From: ansuz Date: Thu, 30 Apr 2020 18:18:05 -0400 Subject: [PATCH 7/7] queue signature validation per-channel to ensure correct ordering --- lib/historyKeeper.js | 1 + lib/hk-util.js | 37 ++++++++++++++++++++++--------------- 2 files changed, 23 insertions(+), 15 deletions(-) diff --git a/lib/historyKeeper.js b/lib/historyKeeper.js index aa320f4b6..7e45faf08 100644 --- a/lib/historyKeeper.js +++ b/lib/historyKeeper.js @@ -38,6 +38,7 @@ module.exports.create = function (config, cb) { channel_cache: {}, queueStorage: WriteQueue(), queueDeletes: WriteQueue(), + queueValidation: WriteQueue(), batchIndexReads: BatchRead("HK_GET_INDEX"), batchMetadata: BatchRead('GET_METADATA'), diff --git a/lib/hk-util.js b/lib/hk-util.js index 562114ec7..81984b300 100644 --- a/lib/hk-util.js +++ b/lib/hk-util.js @@ -859,23 +859,30 @@ HK.onChannelMessage = function (Env, Server, channel, msgStruct) { // trim the checkpoint indicator off the message if it's present let signedMsg = (isCp) ? msgStruct[4].replace(CHECKPOINT_PATTERN, '') : msgStruct[4]; - // convert the message from a base64 string into a Uint8Array - - //const txid = Util.uid(); // Listen for messages - //console.log(+new Date(), "Send verification request"); - Env.validateMessage(signedMsg, metadata.validateKey, w(function (err) { - // no errors means success - if (!err) { return; } - // validation can fail in multiple ways - if (err === 'FAILED') { - // we log this case, but not others for some reason - Log.info("HK_SIGNED_MESSAGE_REJECTED", 'Channel '+channel.id); - } - // always abort if there was an error... - return void w.abort(); - })); + /* queueing this helps avoid race conditions in which workers + validate and write messages in a different order than they were received. + For best effect the validate and store should actually be queued atomically, + but this is a step in the right direction. + */ + var proceed = w(); + Env.queueValidation(channel.id, function (next) { + Env.validateMessage(signedMsg, metadata.validateKey, function (err) { + // always go on to the next item in the queue regardless of the outcome + next(); + + // no errors means success + if (!err) { return proceed(); } + // validation can fail in multiple ways + if (err === 'FAILED') { + // we log this case, but not others for some reason + Log.info("HK_SIGNED_MESSAGE_REJECTED", 'Channel '+channel.id); + } + // always abort if there was an error... + return void w.abort(); + }); + }); }).nThen(function () { // do checkpoint stuff...