mirror of https://github.com/xwiki-labs/cryptpad
Dedicated form share modal and auditor role
This commit is contained in:
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…
Reference in New Issue