Ability to submit form answers

pull/1/head
yflory 4 years ago
parent 10f52230a4
commit 3184ad419e

@ -34,6 +34,12 @@ var factory = function (Util, Crypto, Keys, Nacl) {
var keyPair = Nacl.sign.keyPair.fromSecretKey(privateKey); var keyPair = Nacl.sign.keyPair.fromSecretKey(privateKey);
return Nacl.util.encodeBase64(keyPair.publicKey); return Nacl.util.encodeBase64(keyPair.publicKey);
}; };
Hash.getCurvePublicFromPrivate = function (curvePrivateSafeStr) {
var curvePrivateStr = Crypto.b64AddSlashes(curvePrivateSafeStr);
var privateKey = Nacl.util.decodeBase64(curvePrivateStr);
var keyPair = Nacl.box.keyPair.fromSecretKey(privateKey);
return Nacl.util.encodeBase64(keyPair.publicKey);
};
var getEditHashFromKeys = Hash.getEditHashFromKeys = function (secret) { var getEditHashFromKeys = Hash.getEditHashFromKeys = function (secret) {
var version = secret.version; var version = secret.version;

@ -100,6 +100,17 @@ define([
cb(keys); cb(keys);
}); });
}; };
common.getFormKeys = function (cb) {
postMessage("GET", {
key: ['curvePrivate'],
}, function (obj) {
if (obj.error) { return void cb(); }
cb({
curvePrivate: obj,
curvePublic: Hash.getCurvePublicFromPrivate(obj)
});
});
};
common.makeNetwork = function (cb) { common.makeNetwork = function (cb) {
require([ require([

@ -59,6 +59,13 @@ define([
Messages.form_duplicates = "Duplicate entries have been removed"; Messages.form_duplicates = "Duplicate entries have been removed";
Messages.form_reset = "Reset";
Messages.form_sent = "Sent";
// 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
var makeFormSettings = function (framework) { var makeFormSettings = function (framework) {
// XXX // XXX
// Button to set results as public // Button to set results as public
@ -66,45 +73,7 @@ define([
// Button to clear all answers? // Button to clear all answers?
}; };
var TYPES = { var editOptions = function (v, cb) {
input: {
get: function () {
var tag = h('input');
var $tag = $(tag);
return {
tag: tag,
getValue: function () { return $tag.val(); },
//setValue: function (val) { $tag.val(val); }
};
},
icon: h('i.fa.fa-font')
},
radio: {
defaultOpts: {
values: ["Option 1", "Option 2"] // XXX?
},
get: function (opts) {
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 tag = h('div.radio-group', els);
return {
tag: tag,
getValue: function () {
var res;
els.some(function (el, i) {
if (Util.isChecked($(el).find('input'))) {
res = opts.values[i];
}
});
return res;
},
edit: function (cb) {
var v = opts.values.slice();
var add = h('button.btn.btn-secondary', [ var add = h('button.btn.btn-secondary', [
h('i.fa.fa-plus'), h('i.fa.fa-plus'),
h('span', Messages.tag_add) h('span', Messages.tag_add)
@ -155,6 +124,49 @@ define([
container, container,
h('div', [cancelBlock, saveBlock]) h('div', [cancelBlock, saveBlock])
]; ];
};
var TYPES = {
input: {
get: function () {
var tag = h('input');
var $tag = $(tag);
return {
tag: tag,
getValue: function () { return $tag.val(); },
//setValue: function (val) { $tag.val(val); }
reset: function () { $tag.val(''); }
};
},
icon: h('i.fa.fa-font')
},
radio: {
defaultOpts: {
values: ["Option 1", "Option 2"] // XXX?
},
get: function (opts) {
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 tag = h('div.radio-group', els);
return {
tag: tag,
getValue: function () {
var res;
els.some(function (el, i) {
if (Util.isChecked($(el).find('input'))) {
res = opts.values[i];
}
});
return res;
},
reset: function () { $(tag).find('input').removeAttr('checked'); },
edit: function (cb) {
var v = opts.values.slice();
return editOptions(v, cb);
} }
//setValue: function (val) {} //setValue: function (val) {}
}; };
@ -164,23 +176,60 @@ define([
} }
}; };
var renderForm = function (content, editable) { var makeFormControls = function (framework, content) {
var send = h('button.btn.btn-primary', Messages.poll_commit);
var reset = h('button.btn.btn-danger-alt', Messages.form_reset);
$(reset).click(function () {
if (!Array.isArray(APP.formBlocks)) { return; }
APP.formBlocks.forEach(function (data) {
if (typeof(data.reset) === "function") { data.reset(); }
});
});
var $send = $(send).click(function () {
$send.attr('disabled', 'disabled');
if (!Array.isArray(APP.formBlocks)) { return; }
var results = {};
APP.formBlocks.forEach(function (data) {
results[data.uid] = data.getValue();
});
var sframeChan = framework._.sfCommon.getSframeChannel();
sframeChan.query('Q_FORM_SUBMIT', {
mailbox: content.answers,
results: results
}, function (err, data) {
console.error(data);
if (err || (data && data.error)) {
console.error(err || data.error);
return void UI.warn(Messages.error);
}
UI.alert(Messages.form_sent);
});
});
return h('div.cp-form-send-container', [send, reset]);
}; };
var updateForm = function (framework, content, editable) { var updateForm = function (framework, content, editable) {
var $container = $('div.cp-form-creator-content'); var $container = $('div.cp-form-creator-content');
var form = content.form; var form = content.form;
APP.formBlocks = [];
// XXX order array later // XXX order array later
var elements = Object.keys(form).map(function (uid) { var elements = Object.keys(form).map(function (uid) {
var block = form[uid]; var block = form[uid];
var type = block.type; var type = block.type;
var model = TYPES[type]; var model = TYPES[type];
if (!model) { return; } if (!model) { return; }
var data = model.get(block.opts); var data = model.get(block.opts);
data.uid = uid;
var q = h('div.cp-form-block-question', block.q || Messages.form_default); var q = h('div.cp-form-block-question', block.q || Messages.form_default);
var edit, editContainer; var edit, editContainer;
APP.formBlocks.push(data);
if (editable) { if (editable) {
// Question // Question
@ -231,6 +280,7 @@ define([
} }
$(editContainer).empty(); $(editContainer).empty();
block.opts = newOpts; block.opts = newOpts;
framework.localChange();
var $oldTag = $(data.tag); var $oldTag = $(data.tag);
framework._.cpNfInner.chainpad.onSettle(function () { framework._.cpNfInner.chainpad.onSettle(function () {
$edit.show(); $edit.show();
@ -257,15 +307,23 @@ define([
}); });
$container.empty().append(elements); $container.empty().append(elements);
$container.append(makeFormControls(framework, content));
}; };
var andThen = function (framework) { var andThen = function (framework) {
framework.start(); framework.start();
var content = {}; var content = {};
var $container = $('#cp-app-form-container'); var sframeChan = framework._.sfCommon.getSframeChannel();
var metadataMgr = framework._.cpNfInner.metadataMgr;
var priv = metadataMgr.getPrivateData();
APP.isEditor = Boolean(priv.form_public);
var makeFormCreator = function () { var makeFormCreator = function () {
var controlContainer;
if (APP.isEditor) {
var controls = Object.keys(TYPES).map(function (type) { var controls = Object.keys(TYPES).map(function (type) {
var btn = h('button.btn', [ var btn = h('button.btn', [
@ -284,7 +342,8 @@ define([
}); });
return btn; return btn;
}); });
var controlContainer = h('div.cp-form-creator-control', controls); controlContainer = h('div.cp-form-creator-control', controls);
}
var contentContainer = h('div.cp-form-creator-content'); var contentContainer = h('div.cp-form-creator-content');
var div = h('div.cp-form-creator-container', [ var div = h('div.cp-form-creator-container', [
@ -294,12 +353,9 @@ define([
return div; return div;
}; };
var $container = $('#cp-app-form-container');
$container.append(makeFormCreator()); $container.append(makeFormCreator());
if (!APP.isEditor) { makeFormControls(); }
var sframeChan = framework._.sfCommon.getSframeChannel();
var metadataMgr = framework._.cpNfInner.metadataMgr;
var priv = metadataMgr.getPrivateData();
APP.isEditor = Boolean(priv.form_public);
framework.onReady(function (isNew) { framework.onReady(function (isNew) {
var priv = metadataMgr.getPrivateData(); var priv = metadataMgr.getPrivateData();
@ -340,6 +396,7 @@ define([
framework.onContentUpdate(function (newContent) { framework.onContentUpdate(function (newContent) {
console.log(newContent); console.log(newContent);
content = newContent; content = newContent;
updateForm(framework, content, APP.isEditor);
}); });
framework.setContentGetter(function () { framework.setContentGetter(function () {

@ -63,6 +63,7 @@ define([
config.onReady = function () { config.onReady = function () {
cb(); cb();
// XXX // XXX
network.disconnect();
}; };
config.onMessage = function () { config.onMessage = function () {
// XXX // XXX
@ -70,6 +71,31 @@ define([
CPNetflux.start(config); CPNetflux.start(config);
}); });
}); });
sframeChan.on("Q_FORM_SUBMIT", function (data, cb) {
var box = data.mailbox;
var myKeys;
nThen(function (w) {
Cryptpad.getFormKeys(w(function (keys) {
myKeys = keys;
}));
}).nThen(function (w) {
var keys = Utils.secret && Utils.secret.keys;
myKeys.signingKey = keys.secondarySignKey;
var crypto = Utils.Crypto.Mailbox.createEncryptor(myKeys);
var text = JSON.stringify(data.results);
var ciphertext = crypto.encrypt(text, box.publicKey);
var hash = ciphertext.slice(0,64); // XXX use this to recover our previous answers
Cryptpad.anonRpcMsg("WRITE_PRIVATE_MESSAGE", [
box.channel,
ciphertext
], function (err, response) {
cb({error: err, response: response, hash: hash});
});
});
});
sframeChan.on('EV_FORM_MAILBOX', function (data) { sframeChan.on('EV_FORM_MAILBOX', function (data) {
var curvePair = Nacl.box.keyPair(); var curvePair = Nacl.box.keyPair();
publicKey = Nacl.util.encodeBase64(curvePair.publicKey); publicKey = Nacl.util.encodeBase64(curvePair.publicKey);

Loading…
Cancel
Save