Merge branch 'staging' of github.com:xwiki-labs/cryptpad into teams-server-features

pull/1/head
ansuz 5 years ago
commit 70161dbd73

@ -462,6 +462,10 @@
}
}
margin-bottom: 15px;
&:empty {
margin: 0;
display: none;
}
}
.cp-share-friend {
width: 70px;
@ -493,6 +497,11 @@
visibility: hidden;
}
}
.cp-ownership {
& > label {
font-weight: bold;
}
}
}
}

@ -28,10 +28,14 @@ commands.ADD_OWNERS = function (meta, args) {
throw new Error("METADATA_NONSENSE_OWNERS");
}
var changed = false;
args.forEach(function (owner) {
if (meta.owners.indexOf(owner) >= 0) { return; }
meta.owners.push(owner);
changed = true;
});
return changed;
};
// ["RM_OWNERS", ["CrufexqXcY-z+eKJlEbNELVy5Sb7E-EAAEFI8GnEtZ0="], 1561623439989]
@ -45,13 +49,24 @@ commands.RM_OWNERS = function (meta, args) {
throw new Error("METADATA_NONSENSE_OWNERS");
}
var changed = false;
// remove owners one by one
// we assume there are no duplicates
args.forEach(function (owner) {
var index = meta.owners.indexOf(owner);
if (index < 0) { return; }
if (meta.mailbox) {
if (typeof(meta.mailbox) === "string") {
delete meta.mailbox;
} else {
delete meta.mailbox[owner];
}
}
meta.owners.splice(index, 1);
changed = true;
});
return changed;
};
// ["ADD_PENDING_OWNERS", ["7eEqelGso3EBr5jHlei6av4r9w2B9XZiGGwA1EgZ-5I="], 1561623438989]
@ -67,16 +82,20 @@ commands.ADD_PENDING_OWNERS = function (meta, args) {
throw new Error("METADATA_NONSENSE_PENDING_OWNERS");
}
var changed = false;
// Add pending_owners array if it doesn't exist
if (!meta.pending_owners) {
meta.pending_owners = deduplicate(args);
return;
return true;
}
// or fill it
args.forEach(function (owner) {
if (meta.pending_owners.indexOf(owner) >= 0) { return; }
meta.pending_owners.push(owner);
changed = true;
});
return changed;
};
// ["RM_PENDING_OWNERS", ["CrufexqXcY-z+eKJlEbNELVy5Sb7E-EAAEFI8GnEtZ0="], 1561623439989]
@ -90,13 +109,17 @@ commands.RM_PENDING_OWNERS = function (meta, args) {
throw new Error("METADATA_NONSENSE_PENDING_OWNERS");
}
var changed = false;
// remove owners one by one
// we assume there are no duplicates
args.forEach(function (owner) {
var index = meta.pending_owners.indexOf(owner);
if (index < 0) { return; }
meta.pending_owners.splice(index, 1);
changed = true;
});
return changed;
};
// ["RESET_OWNERS", ["7eEqelGso3EBr5jHlei6av4r9w2B9XZiGGwA1EgZ-5I="], 1561623439989]
@ -112,6 +135,41 @@ commands.RESET_OWNERS = function (meta, args) {
// overwrite the existing owners with the new one
meta.owners = deduplicate(args);
return true;
};
// ["ADD_MAILBOX", {"7eEqelGso3EBr5jHlei6av4r9w2B9XZiGGwA1EgZ-5I=": mailbox, ...}, 1561623439989]
commands.ADD_MAILBOX = function (meta, args) {
// expect a new array, even if it's empty
if (!args || typeof(args) !== "object") {
throw new Error('METADATA_INVALID_MAILBOX');
}
// assume there are owners to start
if (!Array.isArray(meta.owners)) {
throw new Error("METADATA_NONSENSE_OWNERS");
}
var changed = false;
// For each mailbox we try to add, check if the associated edPublic is an owner
// If they are, add or replace the mailbox
Object.keys(args).forEach(function (edPublic) {
if (meta.owners.indexOf(edPublic) === -1) { return; }
if (typeof(meta.mailbox) === "string") {
var str = meta.mailbox;
meta.mailbox = {};
meta.mailbox[meta.owners[0]] = str;
}
// Make sure mailbox is defined
if (!meta.mailbox) { meta.mailbox = {}; }
meta.mailbox[edPublic] = args[edPublic];
changed = true;
});
return changed;
};
commands.UPDATE_EXPIRATION = function () {
@ -127,7 +185,7 @@ var handleCommand = Meta.handleCommand = function (meta, line) {
throw new Error("METADATA_UNSUPPORTED_COMMAND");
}
commands[command](meta, args);
return commands[command](meta, args);
};
Meta.commands = Object.keys(commands);

@ -340,6 +340,7 @@ var getMetadata = function (Env, channel, cb) {
value: value
}
*/
// XXX global saferphore may cause issues here, a queue "per channel" is probably better
var metadataSem = Saferphore.create(1);
var setMetadata = function (Env, data, unsafeKey, cb) {
var channel = data.channel;
@ -382,13 +383,20 @@ var setMetadata = function (Env, data, unsafeKey, cb) {
// Add the new metadata line
var line = [command, data.value, +new Date()];
var changed = false;
try {
Meta.handleCommand(metadata, line);
changed = Meta.handleCommand(metadata, line);
} catch (e) {
g();
return void cb(e);
}
// if your command is valid but it didn't result in any change to the metadata,
// call back now and don't write any "useless" line to the log
if (!changed) {
g();
return void cb(void 0, metadata);
}
Env.msgStore.writeMetadata(channel, JSON.stringify(line), function (e) {
g();
if (e) {

@ -83,6 +83,9 @@ define([
store.messenger.updateMyData();
}
var myData = createData(store.proxy);
if (store.proxy.friends) {
store.proxy.friends.me = myData;
}
var todo = function (friend) {
if (!friend || !friend.notifications) { return; }
myData.channel = friend.channel;

@ -230,6 +230,11 @@ define([
});
};
messenger.onFriendUpdate = function (curve) {
var friend = getFriend(proxy, curve);
checkFriendData(curve, friend, friend.channel);
};
// Id message allows us to map a netfluxId with a public curve key
var onIdMessage = function (msg, sender) {
var channel, parsed0;
@ -374,12 +379,14 @@ define([
|| mySyncData.profile !== myData.profile
|| mySyncData.avatar !== myData.avatar) {
delete myData.channel;
Object.keys(channels).forEach(function (chan) {
var channel = channels[chan];
Object.keys(friends).forEach(function (curve) {
var friend = friends[curve];
var chan = friend.channel;
if (friend.notifications) { return; }
if (!chan) { return; }
if (!channel) {
return void console.error('NO_SUCH_CHANNEL');
}
var channel = channels[chan];
if (!channel) { return; }
if (channel.readOnly) { return; }
var msg = [Types.update, myData.curvePublic, +new Date(), myData];
@ -397,7 +404,6 @@ define([
info: myData,
types: ['displayName', 'profile', 'avatar'],
});
friends.me = myData;
}
};

@ -71,56 +71,22 @@ define([
var getPropertiesData = function (common, cb) {
var data = {};
NThen(function (waitFor) {
common.getPadAttribute('password', waitFor(function (err, val) {
data.password = val;
}));
}).nThen(function (waitFor) {
var base = common.getMetadataMgr().getPrivateData().origin;
// XXX getFileData?
// XXX getPadMetadata
common.getPadAttribute('href', waitFor(function (err, val) {
if (!val) { return; }
data.href = base + val;
}));
common.getPadAttribute('roHref', waitFor(function (err, val) {
if (!val) { return; }
data.roHref = base + val;
}));
common.getPadAttribute('channel', waitFor(function (err, val) {
data.channel = val;
}));
common.getPadAttribute('rtChannel', waitFor(function (err, val) {
data.rtChannel = val;
}));
common.getPadAttribute('lastVersion', waitFor(function (err, val) {
data.lastVersion = val;
}));
common.getPadAttribute('atime', waitFor(function (err, val) {
data.atime = val;
}));
common.getPadAttribute('ctime', waitFor(function (err, val) {
data.ctime = val;
}));
common.getPadAttribute('title', waitFor(function (err, val) {
data.title = val;
}));
common.getPadAttribute('tags', waitFor(function (err, val) {
data.tags = val;
common.getPadAttribute('', waitFor(function (err, val) {
if (err || !val) {
waitFor.abort();
return void cb(err || 'EEMPTY');
}
Util.extend(data, val);
if (data.href) { data.href = base + data.href; }
if (data.roHref) { data.roHref = base + data.roHref; }
}));
common.getPadMetadata(null, waitFor(function (obj) {
console.log(obj);
if (obj && obj.error) { return; }
data.owners = obj.owners;
data.expire = obj.expire;
data.pending_owners = obj.pending_owners;
}));
/*
common.getPadAttribute('owners', waitFor(function (err, val) {
data.owners = val;
}));
common.getPadAttribute('expire', waitFor(function (err, val) {
data.expire = val;
}));*/
}).nThen(function () {
cb(void 0, data);
});
@ -132,20 +98,20 @@ define([
var user = common.getMetadataMgr().getUserData();
var edPublic = priv.edPublic;
var channel = data.channel;
var owners = data.owners;
var pending_owners = data.pending_owners;
var owners = data.owners || [];
var pending_owners = data.pending_owners || [];
var redrawAll = function () {};
var div1 = h('div.cp-share-friends.cp-share-column');
var div2 = h('div.cp-share-friends.cp-share-column');
var div1 = h('div.cp-share-friends.cp-share-column.cp-ownership');
var div2 = h('div.cp-share-friends.cp-share-column.cp-ownership');
var $div1 = $(div1);
var $div2 = $(div2);
// Remove owner column
var drawRemove = function (pending) {
var _owners = {};
var o = pending ? pending_owners : owners;
var o = (pending ? pending_owners : owners) || [];
o.forEach(function (ed) {
var f;
Object.keys(friends).some(function (c) {
@ -154,20 +120,25 @@ define([
return true;
}
});
if (ed === edPublic) {
f = f || user;
if (f.name) {
f.displayName = f.name;
}
}
_owners[ed] = f || {
displayName: 'Unknown user: '+ ed, // XXX
displayName: Messages._getKey('owner_unknownUser', [ed]),
notifications: true,
edPublic: ed,
};
});
var msg = pending ? 'Remove a pending owner:'
: 'Remove an existing owner:'; // XXX
var msg = pending ? Messages.owner_removePendingText
: Messages.owner_removeText;
var removeCol = UIElements.getFriendsList(msg, {
common: common,
friends: _owners,
noFilter: true
}, function () {
console.log(arguments);
});
var $div = $(removeCol.div);
var others1 = removeCol.others;
@ -184,12 +155,13 @@ define([
});
// When clicking on the remove button, we check the selected users.
// If you try to remove yourself, we'll display an additional warning message
var btnMsg = pending ? 'Remove pending owners' : 'Remove owners'; // XXX
var btnMsg = pending ? Messages.owner_removePendingButton : Messages.owner_removeButton;
var removeButton = h('button.no-margin', btnMsg);
$(removeButton).click(function () {
// Check selection
var $sel = $div.find('.cp-share-friend.cp-selected');
var sel = $sel.toArray();
if (!sel.length) { return; }
var me = false;
var toRemove = sel.map(function (el) {
var ed = $(el).attr('data-ed');
@ -197,25 +169,54 @@ define([
if (ed === edPublic) { me = true; }
return ed;
}).filter(function (x) { return x; });
NThen(function (waitFor) {
var msg = me ? Messages.owner_removeMeConfirm : Messages.owner_removeConfirm;
UI.confirm(msg, waitFor(function (yes) {
if (!yes) {
waitFor.abort();
return;
}
}));
}).nThen(function (waitFor) {
// Send the command
var send = function () {
sframeChan.query('Q_SET_PAD_METADATA', {
channel: channel,
command: pending ? 'RM_PENDING_OWNERS' : 'RM_OWNERS',
value: toRemove
}, function (err, res) {
}, waitFor(function (err, res) {
err = err || (res && res.error);
if (err) { return void UI.warn('ERROR' + err); } // XXX
if (err) {
waitFor.abort();
redrawAll();
UI.log('DONE'); // XXX
var text = err === "INSUFFICIENT_PERMISSIONS" ? Messages.fm_forbidden
: Messages.error;
return void UI.warn(text);
}
UI.log(Messages.saved);
}));
}).nThen(function (waitFor) {
sel.forEach(function (el) {
var friend = friends[$(el).attr('data-curve')];
if (!friend) { return; }
common.mailbox.sendTo("RM_OWNER", {
channel: channel,
title: data.title,
pending: pending,
user: {
displayName: user.name,
avatar: user.avatar,
profile: user.profile,
notifications: user.notifications,
curvePublic: user.curvePublic,
edPublic: priv.edPublic
}
}, {
channel: friend.notifications,
curvePublic: friend.curvePublic
}, waitFor());
});
};
var msg = me ?
"Are you sure? You're going to give up on your rights, this can't be undone!" :
"Are you sure?"; // XXX
UI.confirm(msg, function (yes) {
if (!yes) { return; }
send();
}).nThen(function () {
redrawAll();
});
});
$div.append(h('p', removeButton));
@ -226,16 +227,16 @@ define([
var drawAdd = function () {
var _friends = JSON.parse(JSON.stringify(friends));
Object.keys(_friends).forEach(function (curve) {
if (owners.indexOf(_friends[curve].edPublic) !== -1) {
if (owners.indexOf(_friends[curve].edPublic) !== -1 ||
pending_owners.indexOf(_friends[curve].edPublic) !== -1) {
delete _friends[curve];
}
});
var addCol = UIElements.getFriendsList('Ask a friend to be an owner.', {
var addCol = UIElements.getFriendsList(Messages.owner_addText, {
common: common,
friends: _friends
}, function () {
// XXX onSelect...
console.log(arguments);
//console.log(arguments);
});
$div2 = $(addCol.div);
var others2 = addCol.others;
@ -249,20 +250,20 @@ define([
order = order ? 'order:'+order : '';
$(this).removeClass('cp-selected').attr('style', order);
}
// XXX onSelect...
});
// When clicking on the add button, we get the selected users.
var addButton = h('button.no-margin', 'Add owners'); // XXX
var addButton = h('button.no-margin', Messages.owner_addButton);
$(addButton).click(function () {
// Check selection
var $sel = $div2.find('.cp-share-friend.cp-selected');
var sel = $sel.toArray();
if (!sel.length) { return; }
var toAdd = sel.map(function (el) {
return friends[$(el).attr('data-curve')].edPublic;
}).filter(function (x) { return x; });
NThen(function (waitFor) {
var msg = "Are you sure?"; // XXX
var msg = Messages.owner_addConfirm;
UI.confirm(msg, waitFor(function (yes) {
if (!yes) {
waitFor.abort();
@ -270,23 +271,22 @@ define([
}
}));
}).nThen(function (waitFor) {
console.log('koko');
// Send the command
sframeChan.query('Q_SET_PAD_METADATA', {
channel: channel,
command: 'ADD_PENDING_OWNERS',
value: toAdd
}, waitFor(function (err, res) {
console.error(arguments);
err = err || (res && res.error);
if (err) {
waitFor.abort();
return void UI.warn('ERROR' + err);
} // XXX
redrawAll();
var text = err === "INSUFFICIENT_PERMISSIONS" ? Messages.fm_forbidden
: Messages.error;
return void UI.warn(text);
}
}));
}).nThen(function (waitFor) {
console.log('okok');
// TODO send notifications
sel.forEach(function (el) {
var friend = friends[$(el).attr('data-curve')];
if (!friend) { return; }
@ -310,28 +310,42 @@ define([
});
}).nThen(function () {
redrawAll();
UI.log('DONE'); // XXX
UI.log(Messages.saved);
});
});
$div2.append(h('p', addButton));
return $div2;
};
redrawAll = function () {
redrawAll = function (md) {
var todo = function (obj) {
if (obj && obj.error) { return; }
owners = obj.owners || [];
pending_owners = obj.pending_owners || [];
$div1.empty();
$div2.empty();
common.getPadMetadata(null, function (obj) {
if (obj && obj.error) { return; }
owners = obj.owners;
pending_owners = obj.pending_owners;
$div1.append(drawRemove(false)).append(drawRemove(true));
$div2.append(drawAdd());
});
};
if (md) { return void todo(md); }
common.getPadMetadata({
channel: data.channel
}, todo);
};
$div1.append(drawRemove(false)).append(drawRemove(true));
$div2.append(drawAdd());
var handler = sframeChan.on('EV_RT_METADATA', function (md) {
if (!$div1.length) {
return void handler.stop();
}
owners = md.owners || [];
pending_owners = md.pending_owners || [];
redrawAll(md);
});
// Create modal
var link = h('div.cp-share-columns', [
div1,
@ -341,16 +355,18 @@ define([
]);
var linkButtons = [{
className: 'cancel',
name: 'CLOSE', // XXX existing key?
name: Messages.filePicker_close,
onClick: function () {},
keys: [27]
}];
return UI.dialog.customModal(link, {buttons: linkButtons});
};
var getRightsProperties = function (common, data, cb) {
var $d = $('<div>');
if (!data) { return void cb(void 0, $d); }
var $div = $('<div>');
if (!data) { return void cb(void 0, $div); }
var draw = function () {
var $d = $('<div>');
$('<label>', {'for': 'cp-app-prop-owners'}).text(Messages.creation_owners)
.appendTo($d);
var owners = Messages.creation_noOwner;
@ -388,7 +404,7 @@ define([
id: 'cp-app-prop-owners',
}));
if (owned) {
var manageOwners = h('button.no-margin', 'Manage owners'); // XXX
var manageOwners = h('button.no-margin', Messages.owner_openModalButton);
$(manageOwners).click(function () {
var modal = createOwnerModal(common, data);
UI.openCustomModal(modal, {
@ -479,8 +495,25 @@ define([
$d.append(changePass);
}
}
return $d;
};
cb(void 0, $d);
var sframeChan = common.getSframeChannel();
var handler = sframeChan.on('EV_RT_METADATA', function (md) {
if (!$div.length) {
handler.stop();
return;
}
md = JSON.parse(JSON.stringify(md));
data.owners = md.owners;
data.expire = md.expire;
data.pending_owners = md.pending_owners;
$div.empty();
$div.append(draw());
});
$div.append(draw());
cb(void 0, $div);
};
var getPadProperties = function (common, data, cb) {
var $d = $('<div>');
@ -567,6 +600,8 @@ define([
} else {
cb(void 0, $d);
}
};
UIElements.getProperties = function (common, data, cb) {
var c1;
@ -3068,6 +3103,7 @@ define([
};
var storePopupState = false;
var autoStoreModal = {};
UIElements.displayStorePadPopup = function (common, data) {
if (storePopupState) { return; }
storePopupState = true;
@ -3087,6 +3123,8 @@ define([
var initialHide = data && data.autoStore && data.autoStore === -1;
var modal = UI.cornerPopup(text, actions, footer, {hidden: initialHide});
autoStoreModal[priv.channel] = modal;
$(modal.popup).find('.cp-corner-footer a').click(function (e) {
e.preventDefault();
common.openURL('/settings/');
@ -3094,6 +3132,7 @@ define([
$(hide).click(function () {
UIElements.displayCrowdfunding(common);
delete autoStoreModal[priv.channel];
modal.delete();
});
var waitingForStoringCb = false;
@ -3109,6 +3148,7 @@ define([
}
return void UI.warn(Messages.autostore_error);
}
delete autoStoreModal[priv.channel];
modal.delete();
UIElements.displayCrowdfunding(common);
UI.log(Messages.autostore_saved);
@ -3286,7 +3326,6 @@ define([
var name = Util.fixHTML(msg.content.user.displayName) || Messages.anonymous;
var title = Util.fixHTML(msg.content.title);
Messages.owner_add = '{0} wants you to be an owner of the pad <b>{1}</b>. Do you accept?'; //XXX
var text = Messages._getKey('owner_add', [name, title]);
var link = h('a', {
@ -3343,13 +3382,32 @@ define([
}, function (err, res) {
err = err || (res && res.error);
if (err) {
return void UI.warn('ERROR ' + err);
} // XXX
UI.log('DONE'); // XXX
var text = err === "INSUFFICIENT_PERMISSIONS" ? Messages.fm_forbidden
: Messages.error;
return void UI.warn(text);
}
UI.log(Messages.saved);
// Send notification to the sender
answer(true);
var data = JSON.parse(JSON.stringify(msg.content));
data.metadata = res;
// Add the pad to your drive
// This command will also add your mailbox to the metadata log
// The callback is called when the pad is stored, independantly of the metadata command
sframeChan.query('Q_ACCEPT_OWNERSHIP', data, function (err, res) {
if (err || (res && res.error)) {
return void console.error(err | res.error);
}
UI.log(Messages.saved);
if (autoStoreModal[data.channel]) {
autoStoreModal[data.channel].delete();
delete autoStoreModal[data.channel];
}
});
// Remove yourself from the pending owners
sframeChan.query('Q_SET_PAD_METADATA', {
channel: msg.content.channel,

@ -757,6 +757,7 @@ define([
pad.onDisconnectEvent = Util.mkEvent();
pad.onConnectEvent = Util.mkEvent();
pad.onErrorEvent = Util.mkEvent();
pad.onMetadataEvent = Util.mkEvent();
pad.getPadMetadata = function (data, cb) {
postMessage('GET_PAD_METADATA', data, cb);
@ -1208,6 +1209,7 @@ define([
PAD_DISCONNECT: common.padRpc.onDisconnectEvent.fire,
PAD_CONNECT: common.padRpc.onConnectEvent.fire,
PAD_ERROR: common.padRpc.onErrorEvent.fire,
PAD_METADATA: common.padRpc.onMetadataEvent.fire,
// Drive
DRIVE_LOG: common.drive.onLog.fire,
DRIVE_CHANGE: common.drive.onChange.fire,

@ -218,7 +218,6 @@ define([
// Display the notification
var name = Util.fixHTML(msg.content.user.displayName) || Messages.anonymous;
var title = Util.fixHTML(msg.content.title);
Messages.owner_request = '{0} wants you to be an owner of <b>{1}</b>'; // XXX
content.getFormatText = function () {
return Messages._getKey('owner_request', [name, title]);
};
@ -241,8 +240,6 @@ define([
// Display the notification
var name = Util.fixHTML(msg.content.user.displayName) || Messages.anonymous;
var title = Util.fixHTML(msg.content.title);
Messages.owner_request_accepted = '{0} has accepted your offer to be an owner of <b>{1}</b>'; // XXX
Messages.owner_request_declined = '{0} has declined your offer to be an owner of <b>{1}</b>'; // XXX
var key = 'owner_request_' + (msg.content.answer ? 'accepted' : 'declined');
content.getFormatText = function () {
return Messages._getKey(key, [name, title]);
@ -252,6 +249,22 @@ define([
}
};
handlers['RM_OWNER'] = function (common, data) {
var content = data.content;
var msg = content.msg;
// Display the notification
var name = Util.fixHTML(msg.content.user.displayName) || Messages.anonymous;
var title = Util.fixHTML(msg.content.title);
var key = 'owner_removed' + (msg.content.pending ? 'Pending' : '');
content.getFormatText = function () {
return Messages._getKey(key, [name, title]);
};
if (!content.archived) {
content.dismissHandler = defaultDismiss(common, data);
}
};
// NOTE: don't forget to fixHTML everything returned by "getFormatText"
return {

@ -1205,7 +1205,6 @@ define([
}
},
onMetadataUpdate: function (metadata) {
console.log('onMetadataUpdate', metadata);
channel.data = metadata || {};
var allData = store.manager.findChannel(data.channel);
allData.forEach(function (obj) {
@ -1214,7 +1213,7 @@ define([
obj.data.expire = +metadata.expire;
}
});
//channel.bcast("PAD_METADATA", metadata);
channel.bcast("PAD_METADATA", metadata);
},
crypto: {
// The encryption and decryption is done in the outer window.
@ -1374,7 +1373,6 @@ define([
};
Store.getPadMetadata = function (clientId, data, cb) {
console.log(data);
if (!data.channel) { return void cb({ error: 'ENOTFOUND'}); }
var channel = channels[data.channel];
if (!channel) { return void cb({ error: 'ENOTFOUND' }); }
@ -1397,7 +1395,6 @@ define([
cb(channel.data || {});
};
Store.setPadMetadata = function (clientId, data, cb) {
console.log(data);
if (!data.channel) { return void cb({ error: 'ENOTFOUND'}); }
if (!data.command) { return void cb({ error: 'EINVAL' }); }
store.rpc.setMetadata(data, function (err, res) {

@ -153,6 +153,9 @@ define([
Object.keys(msg.content).forEach(function (key) {
friend[key] = msg.content[key];
});
if (ctx.store.messenger) {
ctx.store.messenger.onFriendUpdate(curve, friend);
}
ctx.updateMetadata();
cb(true);
};
@ -264,7 +267,6 @@ define([
handlers['ADD_OWNER'] = function (ctx, box, data, cb) {
var msg = data.msg;
var content = msg.content;
console.log(msg);
if (msg.author !== content.user.curvePublic) { return void cb(true); }
if (!content.href || !content.title || !content.channel) {
@ -275,7 +277,10 @@ console.log(msg);
var channel = content.channel;
if (addOwners[channel]) { return void cb(true); }
addOwners[channel] = true;
addOwners[channel] = {
type: box.type,
hash: data.hash
};
cb(false);
};
@ -286,6 +291,24 @@ console.log(msg);
}
};
handlers['RM_OWNER'] = function (ctx, box, data, cb) {
var msg = data.msg;
var content = msg.content;
if (msg.author !== content.user.curvePublic) { return void cb(true); }
if (!content.channel) {
console.log('Remove invalid notification');
return void cb(true);
}
var channel = content.channel;
if (addOwners[channel] && content.pending) {
return void cb(false, addOwners[channel]);
}
cb(false);
};
return {
add: function (ctx, box, data, cb) {
/**

@ -495,8 +495,8 @@ define([
_addSharedFolder(Env, {
path: parentPath,
name: folderName,
owned: data.owned, // XXX FIXME hardcoded preference
password: data.password || '', // XXX FIXME hardcoded preference
owned: data.owned,
password: data.password || '',
}, waitFor(function (id) {
// _addSharedFolder can be an id or an error
if (typeof(id) === 'object' && id && id.error) {
@ -741,29 +741,17 @@ define([
return void cb(null, Env.user.proxy[UserObject.SHARED_FOLDERS][sfId][data.attr]);
}
var datas = findHref(Env, data.href);
var nt = nThen;
var res = {};
datas.forEach(function (d) {
nt = nt(function (waitFor) {
var atime, value;
var w = waitFor();
nThen(function (waitFor2) {
d.userObject.getPadAttribute(data.href, 'atime', waitFor2(function (err, v) {
atime = v;
}));
d.userObject.getPadAttribute(data.href, data.attr, waitFor2(function (err, v) {
value = v;
}));
}).nThen(function () {
var atime = d.data.atime;
var value = data.attr ? d.data[data.attr] : JSON.parse(JSON.stringify(d.data));
if (!res.value || res.atime < atime) {
res.atime = atime;
res.value = value;
}
w();
});
}).nThen;
});
nt(function () { cb(null, res.value); });
cb(null, res.value);
};
var getTagsList = function (Env) {

@ -118,6 +118,10 @@ define([], function () {
onOpen(data);
});
padRpc.onMetadataEvent.reg(function (data) {
sframeChan.event('EV_RT_METADATA', data);
});
padRpc.onErrorEvent.reg(function (err) {
sframeChan.event('EV_RT_ERROR', err);
});

@ -476,6 +476,43 @@ define([
});
});
sframeChan.on('Q_ACCEPT_OWNERSHIP', function (data, cb) {
var _data = {
password: data.password,
href: data.href,
channel: data.channel,
title: data.title,
owners: data.metadata.owners,
expire: data.metadata.expire,
forceSave: true
};
Cryptpad.setPadTitle(_data, function (err) {
cb({error: err});
});
// Also add your mailbox to the metadata object
var padParsed = Utils.Hash.parsePadUrl(data.href);
var padSecret = Utils.Hash.getSecrets(padParsed.type, padParsed.hash, data.password);
var padCrypto = Utils.Crypto.createEncryptor(padSecret.keys);
try {
var value = {};
value[edPublic] = padCrypto.encrypt(JSON.stringify({
notifications: notifications,
curvePublic: curvePublic
}));
var msg = {
channel: data.channel,
command: 'ADD_MAILBOX',
value: value
};
Cryptpad.setPadMetadata(msg, function (res) {
if (res.error) { console.error(res.error); }
});
} catch (err) {
return void console.error(err);
}
});
sframeChan.on('Q_IMPORT_MEDIATAG', function (obj, cb) {
var key = obj.key;
var channel = obj.channel;
@ -986,9 +1023,17 @@ define([
}, waitFor(function (obj) {
obj = obj || {};
if (obj.error) { return; }
if (obj.mailbox) {
var mailbox;
// Get the first available mailbox (the field can be an string or an object)
// TODO maybe we should send the request to all the owners?
if (typeof (obj.mailbox) === "string") {
mailbox = obj.mailbox;
} else if (obj.mailbox && obj.owners && obj.owners.length) {
mailbox = obj.mailbox[obj.owners[0]];
}
if (mailbox) {
try {
var dataStr = crypto.decrypt(obj.mailbox, true, true);
var dataStr = crypto.decrypt(mailbox, true, true);
var data = JSON.parse(dataStr);
if (!data.notifications || !data.curvePublic) { return; }
owner = data;
@ -1010,7 +1055,6 @@ define([
channel: secret.channel
};
}
console.log(data);
Cryptpad.getPadMetadata(data, cb);
});
sframeChan.on('Q_SET_PAD_METADATA', function (data, cb) {
@ -1142,7 +1186,8 @@ define([
};
if (data.owned) {
rtConfig.metadata.owners = [edPublic];
rtConfig.metadata.mailbox = Utils.crypto.encrypt(JSON.stringify({
rtConfig.metadata.mailbox = {};
rtConfig.metadata.mailbox[edPublic] = Utils.crypto.encrypt(JSON.stringify({
notifications: notifications,
curvePublic: curvePublic
}));

@ -1139,5 +1139,26 @@
"features_noData": "Aucune donnée personnelle requise",
"features_pricing": "Entre {0} et {2}€ par mois",
"features_emailRequired": "Adresse email requise",
"register_emailWarning0": "Il semble que vous ayez entré votre adresse email à la place du nom d'utilisateur.",
"register_emailWarning1": "Vous pouvez continuer, mais ces données ne sont pas nécessaires et ne seront pas envoyées à notre serveur.",
"register_emailWarning2": "Vous ne pourrez pas réinitialiser votre mot de passe en utilisant votre adresse email comme sur beaucoup d'autres services",
"register_emailWarning3": "Si vous souhaitez tout de même utiliser votre adresse email comme nom d'utilisateur, appuyez sur OK",
"owner_removeText": "Supprimer un propriétaire existant",
"owner_removePendingText": "Annuler une offre en attente",
"owner_addText": "Proposer à un ami d'être co-propriétaire de ce document",
"owner_unknownUser": "Utilisateur inconnu",
"owner_removeButton": "Supprimer les propriétaires sélectionnés",
"owner_removePendingButton": "Annuler les offres sélectionnées",
"owner_addButton": "Proposer la co-propriété",
"owner_removeConfirm": "Êtes-vous sûr de vouloir suppprimer les droits de propriétaire pour les utilisateurs sélectionnés ? Ils seront notifiés de cette action.",
"owner_removeMeConfirm": "Vous êtes sur le point de renoncer à vos droits de propriétaire. Vous ne serez pas en mesure d'annuler cette action. Continuer ?",
"owner_addConfirm": "Les co-propriétaires seront en mesure de changer le contenu du document et pourront supprimer vos droits de propriétaire. Continuer ?",
"owner_openModalButton": "Gérer les propriétaires",
"owner_add": "{0} souhaite que vous soyez propriétaire du pad <b>{1}</b>. Acceptez-vous ?",
"owner_request": "{0} souhaite que vous soyez propriétaire de <b>{1}</b>",
"owner_request_accepted": "{0} a accepté votre offre de devenir propriétaire de <b>{1}</b>",
"owner_request_declined": "{0} a refusé votre offre de devenir propriétaire de <b>{1}</b>",
"owner_removed": "{0} a supprimé vos droits de propriétaire de <b>{1}</b>",
"owner_removedPending": "{0} a annulé l'offre de co-propriété reçue pour <b>{1}</b>",
"padNotPinnedVariable": "Ce pad va expirer après {4} jours d'inactivité, {0}connectez-vous{1} ou {2}enregistrez-vous{3} pour le préserver."
}

@ -3720,7 +3720,6 @@ define([
sframeChan.query('Q_GET_PAD_METADATA', {
channel: data.channel
}, function (err, val) {
console.log(arguments);
if (!err && !(val && val.error)) {
data.owners = val.owners;
data.expire = val.expire;

Loading…
Cancel
Save