Dedicated form share modal and auditor role

pull/1/head
yflory 4 years ago
parent 6f64d62698
commit 4a1de32994

@ -215,6 +215,17 @@ Version 4: Data URL when not a realtime link yet (new pad or "static" app)
}); });
return k ? Crypto.b64AddSlashes(k) : ''; return k ? Crypto.b64AddSlashes(k) : '';
}; };
var getAuditorKey = function (hashArr) {
var k;
// Check if we have a ownerKey for this pad
hashArr.some(function (data) {
if (/^auditor=/.test(data)) {
k = data.slice(8);
return true;
}
});
return k ? Crypto.b64AddSlashes(k) : '';
};
var getOwnerKey = function (hashArr) { var getOwnerKey = function (hashArr) {
var k; var k;
// Check if we have a ownerKey for this pad // Check if we have a ownerKey for this pad
@ -237,6 +248,7 @@ Version 4: Data URL when not a realtime link yet (new pad or "static" app)
parsed.present = options.indexOf('present') !== -1; parsed.present = options.indexOf('present') !== -1;
parsed.embed = options.indexOf('embed') !== -1; parsed.embed = options.indexOf('embed') !== -1;
parsed.versionHash = getVersionHash(options); parsed.versionHash = getVersionHash(options);
parsed.auditorKey = getAuditorKey(options);
parsed.newPadOpts = getNewPadOpts(options); parsed.newPadOpts = getNewPadOpts(options);
parsed.loginOpts = getLoginOpts(options); parsed.loginOpts = getLoginOpts(options);
parsed.ownerKey = getOwnerKey(options); parsed.ownerKey = getOwnerKey(options);
@ -278,6 +290,7 @@ Version 4: Data URL when not a realtime link yet (new pad or "static" app)
present: parsed.present, present: parsed.present,
ownerKey: parsed.ownerKey, ownerKey: parsed.ownerKey,
versionHash: parsed.versionHash, versionHash: parsed.versionHash,
auditorKey: parsed.auditorKey,
newPadOpts: parsed.newPadOpts, newPadOpts: parsed.newPadOpts,
loginOpts: parsed.loginOpts, loginOpts: parsed.loginOpts,
password: parsed.password password: parsed.password
@ -304,6 +317,10 @@ Version 4: Data URL when not a realtime link yet (new pad or "static" app)
if (versionHash) { if (versionHash) {
hash += 'hash=' + Crypto.b64RemoveSlashes(versionHash) + '/'; hash += 'hash=' + Crypto.b64RemoveSlashes(versionHash) + '/';
} }
var auditorKey = typeof(opts.auditorKey) !== "undefined" ? opts.auditorKey : parsed.auditorKey;
if (auditorKey) {
hash += 'auditor=' + Crypto.b64RemoveSlashes(auditorKey) + '/';
}
if (opts.newPadOpts) { hash += 'newpad=' + opts.newPadOpts + '/'; } if (opts.newPadOpts) { hash += 'newpad=' + opts.newPadOpts + '/'; }
if (opts.loginOpts) { hash += 'login=' + opts.loginOpts + '/'; } if (opts.loginOpts) { hash += 'login=' + opts.loginOpts + '/'; }
return hash; return hash;

@ -494,7 +494,23 @@ define([
var parsed = Hash.parsePadUrl(pathname); var parsed = Hash.parsePadUrl(pathname);
var canPresent = ['code', 'slide'].indexOf(parsed.type) !== -1; var canPresent = ['code', 'slide'].indexOf(parsed.type) !== -1;
var versionHash = hashes.viewHash && opts.versionHash; var versionHash = hashes.viewHash && opts.versionHash;
var canBAR = parsed.type !== 'drive' && !versionHash; var isForm = parsed.type === "form"; // && opts.auditorHash;
var canBAR = parsed.type !== 'drive' && !versionHash && !isForm;
var labelEdit = Messages.share_linkEdit;
var labelView = Messages.share_linkView;
var auditor;
if (isForm) {
Messages.share_formEdit = "Author"; // XXX
Messages.share_formView = "Participant"; // XXX
Messages.share_formAuditor = "Auditor"; // XXX
labelEdit = Messages.share_formEdit;
labelView = Messages.share_formView;
auditor = UI.createRadio('accessRights', 'cp-share-form', Messages.share_formAuditor, false, {
mark: {tabindex:1},
});
}
var burnAfterReading = (hashes.viewHash && canBAR) ? var burnAfterReading = (hashes.viewHash && canBAR) ?
UI.createRadio('accessRights', 'cp-share-bar', Messages.burnAfterReading_linkBurnAfterReading, false, { UI.createRadio('accessRights', 'cp-share-bar', Messages.burnAfterReading_linkBurnAfterReading, false, {
@ -505,12 +521,13 @@ define([
h('label', Messages.share_linkAccess), h('label', Messages.share_linkAccess),
h('div.radio-group',[ h('div.radio-group',[
UI.createRadio('accessRights', 'cp-share-editable-false', UI.createRadio('accessRights', 'cp-share-editable-false',
Messages.share_linkView, true, { mark: {tabindex:1} }), labelView, true, { mark: {tabindex:1} }),
canPresent ? UI.createRadio('accessRights', 'cp-share-present', canPresent ? UI.createRadio('accessRights', 'cp-share-present',
Messages.share_linkPresent, false, { mark: {tabindex:1} }) : undefined, Messages.share_linkPresent, false, { mark: {tabindex:1} }) : undefined,
UI.createRadio('accessRights', 'cp-share-editable-true', UI.createRadio('accessRights', 'cp-share-editable-true',
Messages.share_linkEdit, false, { mark: {tabindex:1} })]), labelEdit, false, { mark: {tabindex:1} }),
burnAfterReading auditor]),
burnAfterReading,
]); ]);
// Burn after reading // Burn after reading
@ -553,6 +570,7 @@ define([
var embed = val.embed; var embed = val.embed;
var present = val.present !== undefined ? val.present : Util.isChecked($rights.find('#cp-share-present')); var present = val.present !== undefined ? val.present : Util.isChecked($rights.find('#cp-share-present'));
var burnAfterReading = Util.isChecked($rights.find('#cp-share-bar')); var burnAfterReading = Util.isChecked($rights.find('#cp-share-bar'));
var formAuditor = Util.isChecked($rights.find('#cp-share-form'));
if (versionHash) { if (versionHash) {
edit = false; edit = false;
present = false; present = false;
@ -569,6 +587,9 @@ define([
} }
var hash = (!hashes.viewHash || (edit && hashes.editHash)) ? hashes.editHash var hash = (!hashes.viewHash || (edit && hashes.editHash)) ? hashes.editHash
: hashes.viewHash; : hashes.viewHash;
if (formAuditor && opts.auditorHash) {
hash = opts.auditorHash;
}
var href = burnAfterReading ? opts.burnAfterReadingUrl var href = burnAfterReading ? opts.burnAfterReadingUrl
: (origin + pathname + '#' + hash); : (origin + pathname + '#' + hash);
var parsed = Hash.parsePadUrl(href); var parsed = Hash.parsePadUrl(href);
@ -594,6 +615,9 @@ define([
$rights.find('#cp-share-present').removeAttr('checked').attr('disabled', true); $rights.find('#cp-share-present').removeAttr('checked').attr('disabled', true);
$rights.find('#cp-share-editable-true').attr('checked', true); $rights.find('#cp-share-editable-true').attr('checked', true);
} }
if (isForm && !opts.auditorHash) {
$rights.find('#cp-share-form').removeAttr('checked').attr('disabled', true);
}
var getLink = function () { var getLink = function () {
return $rights.parent().find('#cp-share-link-preview'); return $rights.parent().find('#cp-share-link-preview');

@ -553,11 +553,13 @@ MessengerUI, Messages, Pages) {
if (toolbar.isDeleted) { if (toolbar.isDeleted) {
return void UI.warn(Messages.deletedFromServer); return void UI.warn(Messages.deletedFromServer);
} }
var privateData = config.metadataMgr.getPrivateData();
var title = (config.title && config.title.getTitle && config.title.getTitle()) var title = (config.title && config.title.getTitle && config.title.getTitle())
|| (config.title && config.title.defaultName) || (config.title && config.title.defaultName)
|| ""; || "";
Common.getSframeChannel().event('EV_SHARE_OPEN', { Common.getSframeChannel().event('EV_SHARE_OPEN', {
title: title title: title,
auditorHash: privateData.form_auditorHash
}); });
}); });

@ -689,6 +689,20 @@ define([
// XXX fetch answers and // XXX fetch answers and
// * viewers ==> check if you've already answered and show form (new or edit) // * viewers ==> check if you've already answered and show form (new or edit)
// * editors ==> show schema and warn users if existing questions already have answers // * editors ==> show schema and warn users if existing questions already have answers
if (priv.form_auditorKey) {
sframeChan.query("Q_FORM_FETCH_ANSWERS", {
channel: content.answers.channel,
validateKey: content.answers.validateKey,
publicKey: content.answers.publicKey,
privateKey: priv.form_auditorKey
}, function (err, obj) {
$body.addClass('cp-app-form-results');
renderResults(content, obj);
});
return;
}
if (APP.isEditor) { if (APP.isEditor) {
sframeChan.query("Q_FORM_FETCH_ANSWERS", { sframeChan.query("Q_FORM_FETCH_ANSWERS", {
channel: content.answers.channel, channel: content.answers.channel,

@ -19,6 +19,13 @@ define([
var privateKey, publicKey; var privateKey, publicKey;
var addData = function (meta, CryptPad, user, Utils) { var addData = function (meta, CryptPad, user, Utils) {
var keys = Utils.secret && Utils.secret.keys; var keys = Utils.secret && Utils.secret.keys;
var parsed = Utils.Hash.parseTypeHash('pad', hash.slice(1));
if (parsed.auditorKey) {
meta.form_auditorKey = parsed.auditorKey;
meta.form_auditorHash = hash;
}
var secondary = keys && keys.secondaryKey; var secondary = keys && keys.secondaryKey;
if (!secondary) { return; } if (!secondary) { return; }
var curvePair = Nacl.box.keyPair.fromSecretKey(Nacl.util.decodeUTF8(secondary).slice(0,32)); var curvePair = Nacl.box.keyPair.fromSecretKey(Nacl.util.decodeUTF8(secondary).slice(0,32));
@ -27,10 +34,19 @@ define([
publicKey = meta.form_public = Nacl.util.encodeBase64(curvePair.publicKey); publicKey = meta.form_public = Nacl.util.encodeBase64(curvePair.publicKey);
privateKey = meta.form_private = Nacl.util.encodeBase64(curvePair.secretKey); privateKey = meta.form_private = Nacl.util.encodeBase64(curvePair.secretKey);
var auditorHash = Utils.Hash.getViewHashFromKeys({
version: 1,
channel: Utils.secret.channel,
keys: { viewKeyStr: Nacl.util.encodeBase64(keys.cryptKey) }
});
var parsed = Utils.Hash.parseTypeHash('pad', auditorHash);
meta.form_auditorHash = parsed.getHash({auditorKey: privateKey});
}; };
var addRpc = function (sframeChan, Cryptpad, Utils) { var addRpc = function (sframeChan, Cryptpad, Utils) {
sframeChan.on('Q_FORM_FETCH_ANSWERS', function (data, cb) { sframeChan.on('Q_FORM_FETCH_ANSWERS', function (data, cb) {
var myKeys; var myKeys = {};
var CPNetflux; var CPNetflux;
var network; var network;
nThen(function (w) { nThen(function (w) {
@ -48,7 +64,6 @@ define([
return true; return true;
} }
}); });
console.error(myKeys);
})); }));
Cryptpad.makeNetwork(w(function (err, nw) { Cryptpad.makeNetwork(w(function (err, nw) {
network = nw; network = nw;

@ -58,6 +58,7 @@ define([
hashes: data.hashes || priv.hashes, hashes: data.hashes || priv.hashes,
common: common, common: common,
title: data.title, title: data.title,
auditorHash: data.auditorHash,
versionHash: data.versionHash, versionHash: data.versionHash,
friends: friends, friends: friends,
onClose: function () { onClose: function () {

Loading…
Cancel
Save