From 3b30cfcc555c9a4de1e3a6216839657b0a51fc74 Mon Sep 17 00:00:00 2001 From: yflory Date: Thu, 20 May 2021 16:20:15 +0200 Subject: [PATCH] Recover previous answers --- www/common/cryptpad-common.js | 18 ++++++++++++ www/common/outer/async-store.js | 1 + www/form/inner.js | 45 +++++++++++++++++++++++------ www/form/main.js | 50 +++++++++++++++++++++++++++++++++ 4 files changed, 105 insertions(+), 9 deletions(-) diff --git a/www/common/cryptpad-common.js b/www/common/cryptpad-common.js index ba0624a08..173aa9c9f 100644 --- a/www/common/cryptpad-common.js +++ b/www/common/cryptpad-common.js @@ -100,6 +100,7 @@ define([ cb(keys); }); }; + common.getFormKeys = function (cb) { postMessage("GET", { key: ['curvePrivate'], @@ -111,6 +112,23 @@ define([ }); }); }; + common.getFormAnswer = function (data, cb) { + postMessage("GET", { + key: ['forms', data.channel], + }, cb); + }; + common.storeFormAnswer = function (data) { + postMessage("SET", { + key: ['forms', data.channel], + value: { + hash: data.hash, + curvePrivate: data.curvePrivate + } + }, function (obj) { + if (obj && obj.error) { console.error(obj.error); } + }); + + }; common.makeNetwork = function (cb) { require([ diff --git a/www/common/outer/async-store.js b/www/common/outer/async-store.js index 21bc77798..0e1e9684e 100644 --- a/www/common/outer/async-store.js +++ b/www/common/outer/async-store.js @@ -2696,6 +2696,7 @@ define([ nThen(function (waitFor) { if (!proxy.settings) { proxy.settings = NEW_USER_SETTINGS; } + if (!proxy.forms) { proxy.forms = {}; } if (!proxy.friends_pending) { proxy.friends_pending = {}; } // Call onCacheReady if the manager is not yet defined diff --git a/www/form/inner.js b/www/form/inner.js index f50583e37..b62c4e0da 100644 --- a/www/form/inner.js +++ b/www/form/inner.js @@ -62,6 +62,8 @@ define([ Messages.form_reset = "Reset"; Messages.form_sent = "Sent"; + Messages.form_cantFindAnswers = "Unable to retrieve your existing answers for this form."; + // XXX to update our own answers, we need to store the server hash of the message // and we'll be able to use getHistoryRange to fetch this message when we come back @@ -134,7 +136,7 @@ define([ return { tag: tag, getValue: function () { return $tag.val(); }, - //setValue: function (val) { $tag.val(val); } + setValue: function (val) { $tag.val(val); }, reset: function () { $tag.val(''); } }; }, @@ -148,8 +150,10 @@ define([ if (!opts) { opts = TYPES.radio.defaultOpts; } var name = Util.uid(); var els = opts.values.map(function (data, i) { - return UI.createRadio(name, 'cp-form-'+name+'-'+i, - data, false, { mark: {tabindex:1} }); + var radio = UI.createRadio(name, 'cp-form-'+name+'-'+i, + data, false, { mark: { tabindex:1 } }); + $(radio).find('input').data('val', data); + return radio; }); var tag = h('div.radio-group', els); return { @@ -167,8 +171,17 @@ define([ edit: function (cb) { var v = opts.values.slice(); return editOptions(v, cb); + }, + setValue: function (val) { + this.reset(); + els.some(function (el) { + var $el = $(el).find('input'); + if ($el.data('val') === val) { + $el.prop('checked', true); + return true; + } + }); } - //setValue: function (val) {} }; }, @@ -208,7 +221,7 @@ define([ }); return h('div.cp-form-send-container', [send, reset]); }; - var updateForm = function (framework, content, editable) { + var updateForm = function (framework, content, editable, answers) { var $container = $('div.cp-form-creator-content'); var form = content.form; @@ -224,6 +237,7 @@ define([ var data = model.get(block.opts); data.uid = uid; + if (answers && answers[uid]) { data.setValue(answers[uid]); } var q = h('div.cp-form-block-question', block.q || Messages.form_default); var edit, editContainer; @@ -364,16 +378,17 @@ define([ content.form = {}; framework.localChange(); } - if (!content.answers || !content.answers.channel || !content.answers.publicKey) { + if (!content.answers || !content.answers.channel || !content.answers.publicKey || !content.answers.validateKey) { content.answers = { channel: Hash.createChannelId(), - publicKey: priv.form_public + publicKey: priv.form_public, + validateKey: priv.form_answerValidateKey }; framework.localChange(); } } - if (!content.answers || !content.answers.channel || !content.answers.publicKey) { + if (!content.answers || !content.answers.channel || !content.answers.publicKey || !content.answers.validateKey) { return void UI.errorLoadingScreen(Messages.form_invalid); } // XXX fetch answers and @@ -389,7 +404,19 @@ define([ }); return; } - updateForm(framework, content, false); + + sframeChan.query("Q_FETCH_MY_ANSWERS", { + channel: content.answers.channel, + validateKey: content.answers.validateKey, + publicKey: content.answers.publicKey + }, function (err, obj) { + if (obj && obj.error) { + UI.warn(Messages.form_cantFindAnswers); + } + var answers; + if (obj && !obj.error) { answers = obj; } + updateForm(framework, content, false, answers); + }); }); diff --git a/www/form/main.js b/www/form/main.js index d9eb3e660..089c3433e 100644 --- a/www/form/main.js +++ b/www/form/main.js @@ -22,6 +22,9 @@ define([ var secondary = keys && keys.secondaryKey; if (!secondary) { return; } var curvePair = Nacl.box.keyPair.fromSecretKey(Nacl.util.decodeUTF8(secondary).slice(0,32)); + var validateKey = keys.secondaryValidateKey; + meta.form_answerValidateKey = validateKey; + publicKey = meta.form_public = Nacl.util.encodeBase64(curvePair.publicKey); privateKey = Nacl.util.encodeBase64(curvePair.secretKey); }; @@ -71,6 +74,44 @@ define([ CPNetflux.start(config); }); }); + sframeChan.on("Q_FETCH_MY_ANSWERS", function (data, cb) { + var keys; + var CPNetflux; + var network; + var answer; + var myKeys; + nThen(function (w) { + Cryptpad.getFormKeys(w(function (keys) { + myKeys = keys; + })); + Cryptpad.getFormAnswer({channel: data.channel}, w(function (obj) { + if (!obj || obj.error) { + w.abort(); + return void cb(obj); + } + answer = obj; + })); + }).nThen(function (w) { + Cryptpad.getHistoryRange({ + channel: data.channel, + lastKnownHash: answer.hash, + toHash: answer.hash, + }, function (obj) { + if (obj && obj.error) { return void cb(obj); } + var messages = obj.messages; + var ephemeral_priv = answer.curvePrivate; + var res = Utils.Crypto.Mailbox.openOwnSecretLetter(messages[0].msg, { + validateKey: data.validateKey, + ephemeral_private: Nacl.util.decodeBase64(answer.curvePrivate), + my_private: Nacl.util.decodeBase64(myKeys.curvePrivate), + their_public: Nacl.util.decodeBase64(data.publicKey) + }); + cb(JSON.parse(res.content)); + }); + + }); + + }); sframeChan.on("Q_FORM_SUBMIT", function (data, cb) { var box = data.mailbox; var myKeys; @@ -83,6 +124,10 @@ define([ var keys = Utils.secret && Utils.secret.keys; myKeys.signingKey = keys.secondarySignKey; + var ephemeral_keypair = Nacl.box.keyPair(); + var ephemeral_private = Nacl.util.encodeBase64(ephemeral_keypair.secretKey); + myKeys.ephemeral_keypair = ephemeral_keypair; + var crypto = Utils.Crypto.Mailbox.createEncryptor(myKeys); var text = JSON.stringify(data.results); var ciphertext = crypto.encrypt(text, box.publicKey); @@ -92,6 +137,11 @@ define([ box.channel, ciphertext ], function (err, response) { + Cryptpad.storeFormAnswer({ + channel: box.channel, + hash: hash, + curvePrivate: ephemeral_private + }); cb({error: err, response: response, hash: hash}); }); });