Merge branch 'ownership' of github.com:xwiki-labs/cryptpad into origin/ownership
This commit is contained in:
commit
0abb4f222d
@ -427,7 +427,7 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-flow: row;
|
flex-flow: row;
|
||||||
|
|
||||||
.cp-share-column {
|
& > .cp-share-column {
|
||||||
width: 50%;
|
width: 50%;
|
||||||
padding: 0 10px;
|
padding: 0 10px;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -717,6 +717,9 @@ module.exports.create = function (cfg) {
|
|||||||
if (channel && metadata_cache[channel] && typeof (metadata) === "object") {
|
if (channel && metadata_cache[channel] && typeof (metadata) === "object") {
|
||||||
Log.silly('SET_METADATA_CACHE', 'Channel '+ channel +', metadata: '+ JSON.stringify(metadata));
|
Log.silly('SET_METADATA_CACHE', 'Channel '+ channel +', metadata: '+ JSON.stringify(metadata));
|
||||||
metadata_cache[channel] = metadata;
|
metadata_cache[channel] = metadata;
|
||||||
|
if (ctx.channels[channel] && ctx.channels[channel].index) {
|
||||||
|
ctx.channels[channel].index.metadata = metadata;
|
||||||
|
}
|
||||||
historyKeeperBroadcast(ctx, channel, metadata);
|
historyKeeperBroadcast(ctx, channel, metadata);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -54,6 +54,51 @@ commands.RM_OWNERS = function (meta, args) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ["ADD_PENDING_OWNERS", ["7eEqelGso3EBr5jHlei6av4r9w2B9XZiGGwA1EgZ-5I="], 1561623438989]
|
||||||
|
commands.ADD_PENDING_OWNERS = function (meta, args) {
|
||||||
|
// bail out if args isn't an array
|
||||||
|
if (!Array.isArray(args)) {
|
||||||
|
throw new Error('METADATA_INVALID_PENDING_OWNERS');
|
||||||
|
}
|
||||||
|
|
||||||
|
// you shouldn't be able to get here if there are no owners
|
||||||
|
// because only an owner should be able to change the owners
|
||||||
|
if (meta.pending_owners && !Array.isArray(meta.pending_owners)) {
|
||||||
|
throw new Error("METADATA_NONSENSE_PENDING_OWNERS");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add pending_owners array if it doesn't exist
|
||||||
|
if (!meta.pending_owners) {
|
||||||
|
meta.pending_owners = deduplicate(args);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// or fill it
|
||||||
|
args.forEach(function (owner) {
|
||||||
|
if (meta.pending_owners.indexOf(owner) >= 0) { return; }
|
||||||
|
meta.pending_owners.push(owner);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// ["RM_PENDING_OWNERS", ["CrufexqXcY-z+eKJlEbNELVy5Sb7E-EAAEFI8GnEtZ0="], 1561623439989]
|
||||||
|
commands.RM_PENDING_OWNERS = function (meta, args) {
|
||||||
|
// what are you doing if you don't have owners to remove?
|
||||||
|
if (!Array.isArray(args)) {
|
||||||
|
throw new Error('METADATA_INVALID_PENDING_OWNERS');
|
||||||
|
}
|
||||||
|
// if there aren't any owners to start, this is also pointless
|
||||||
|
if (!Array.isArray(meta.pending_owners)) {
|
||||||
|
throw new Error("METADATA_NONSENSE_PENDING_OWNERS");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
// ["RESET_OWNERS", ["7eEqelGso3EBr5jHlei6av4r9w2B9XZiGGwA1EgZ-5I="], 1561623439989]
|
// ["RESET_OWNERS", ["7eEqelGso3EBr5jHlei6av4r9w2B9XZiGGwA1EgZ-5I="], 1561623439989]
|
||||||
commands.RESET_OWNERS = function (meta, args) {
|
commands.RESET_OWNERS = function (meta, args) {
|
||||||
// expect a new array, even if it's empty
|
// expect a new array, even if it's empty
|
||||||
@ -73,7 +118,7 @@ commands.UPDATE_EXPIRATION = function () {
|
|||||||
throw new Error("E_NOT_IMPLEMENTED");
|
throw new Error("E_NOT_IMPLEMENTED");
|
||||||
};
|
};
|
||||||
|
|
||||||
var handleCommand = function (meta, line) {
|
var handleCommand = Meta.handleCommand = function (meta, line) {
|
||||||
var command = line[0];
|
var command = line[0];
|
||||||
var args = line[1];
|
var args = line[1];
|
||||||
//var time = line[2];
|
//var time = line[2];
|
||||||
@ -84,6 +129,7 @@ var handleCommand = function (meta, line) {
|
|||||||
|
|
||||||
commands[command](meta, args);
|
commands[command](meta, args);
|
||||||
};
|
};
|
||||||
|
Meta.commands = Object.keys(commands);
|
||||||
|
|
||||||
Meta.createLineHandler = function (ref, errorHandler) {
|
Meta.createLineHandler = function (ref, errorHandler) {
|
||||||
ref.meta = {};
|
ref.meta = {};
|
||||||
@ -125,4 +171,3 @@ Meta.createLineHandler = function (ref, errorHandler) {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
Meta.commands = Object.keys(commands);
|
|
||||||
|
|||||||
48
rpc.js
48
rpc.js
@ -340,6 +340,7 @@ var getMetadata = function (Env, channel, cb) {
|
|||||||
value: value
|
value: value
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
var metadataSem = Saferphore.create(1);
|
||||||
var setMetadata = function (Env, data, unsafeKey, cb) {
|
var setMetadata = function (Env, data, unsafeKey, cb) {
|
||||||
var channel = data.channel;
|
var channel = data.channel;
|
||||||
var command = data.command;
|
var command = data.command;
|
||||||
@ -347,25 +348,52 @@ var setMetadata = function (Env, data, unsafeKey, cb) {
|
|||||||
if (!command || typeof (command) !== 'string') { return void cb ('INVALID_COMMAND'); }
|
if (!command || typeof (command) !== 'string') { return void cb ('INVALID_COMMAND'); }
|
||||||
if (Meta.commands.indexOf(command) === -1) { return void('UNSUPPORTED_COMMAND'); }
|
if (Meta.commands.indexOf(command) === -1) { return void('UNSUPPORTED_COMMAND'); }
|
||||||
|
|
||||||
// XXX should we add checks to "metadata.js" to make sure data.value is
|
metadataSem.take(function (give) {
|
||||||
// valid for the selected command?
|
var g = give();
|
||||||
|
|
||||||
getMetadata(Env, channel, function (err, metadata) {
|
getMetadata(Env, channel, function (err, metadata) {
|
||||||
if (err) { return void cb(err); }
|
if (err) {
|
||||||
if (!(metadata && Array.isArray(metadata.owners))) { return void cb('E_NO_OWNERS'); }
|
g();
|
||||||
|
return void cb(err);
|
||||||
|
}
|
||||||
|
if (!(metadata && Array.isArray(metadata.owners))) {
|
||||||
|
g();
|
||||||
|
return void cb('E_NO_OWNERS');
|
||||||
|
}
|
||||||
|
|
||||||
// Confirm that the channel is owned by the user in question
|
// Confirm that the channel is owned by the user in question
|
||||||
if (metadata.owners.indexOf(unsafeKey) === -1) {
|
// or the user is accepting a pending ownerhsip offer
|
||||||
|
if (metadata.pending_owners && Array.isArray(metadata.pending_owners) &&
|
||||||
|
metadata.pending_owners.indexOf(unsafeKey) !== -1 &&
|
||||||
|
metadata.owners.indexOf(unsafeKey) === -1) {
|
||||||
|
|
||||||
|
// If you are a pending owner, make sure you can only add yourelf as an owner
|
||||||
|
if ((command !== 'ADD_OWNERS' && command !== 'RM_PENDING_OWNERS')
|
||||||
|
|| !Array.isArray(data.value)
|
||||||
|
|| data.value.length !== 1
|
||||||
|
|| data.value[0] !== unsafeKey) {
|
||||||
|
g();
|
||||||
|
return void cb('INSUFFICIENT_PERMISSIONS');
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (metadata.owners.indexOf(unsafeKey) === -1) {
|
||||||
|
g();
|
||||||
return void cb('INSUFFICIENT_PERMISSIONS');
|
return void cb('INSUFFICIENT_PERMISSIONS');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the new metadata line
|
// Add the new metadata line
|
||||||
var line = JSON.stringify([command, data.value]);
|
var line = [command, data.value, +new Date()];
|
||||||
return void Env.msgStore.writeMetadata(channel, line, function (e) {
|
try {
|
||||||
|
Meta.handleCommand(metadata, line);
|
||||||
|
} catch (e) {
|
||||||
|
g();
|
||||||
|
return void cb(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
Env.msgStore.writeMetadata(channel, JSON.stringify(line), function (e) {
|
||||||
|
g();
|
||||||
if (e) {
|
if (e) {
|
||||||
return void cb(e);
|
return void cb(e);
|
||||||
}
|
}
|
||||||
getMetadata(Env, channel, function (err, metadata) {
|
|
||||||
// XXX handle error here?
|
|
||||||
cb(void 0, metadata);
|
cb(void 0, metadata);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -76,6 +76,8 @@ define([
|
|||||||
}));
|
}));
|
||||||
}).nThen(function (waitFor) {
|
}).nThen(function (waitFor) {
|
||||||
var base = common.getMetadataMgr().getPrivateData().origin;
|
var base = common.getMetadataMgr().getPrivateData().origin;
|
||||||
|
// XXX getFileData?
|
||||||
|
// XXX getPadMetadata
|
||||||
common.getPadAttribute('href', waitFor(function (err, val) {
|
common.getPadAttribute('href', waitFor(function (err, val) {
|
||||||
if (!val) { return; }
|
if (!val) { return; }
|
||||||
data.href = base + val;
|
data.href = base + val;
|
||||||
@ -99,29 +101,52 @@ define([
|
|||||||
common.getPadAttribute('ctime', waitFor(function (err, val) {
|
common.getPadAttribute('ctime', waitFor(function (err, val) {
|
||||||
data.ctime = val;
|
data.ctime = val;
|
||||||
}));
|
}));
|
||||||
|
common.getPadAttribute('title', waitFor(function (err, val) {
|
||||||
|
data.title = val;
|
||||||
|
}));
|
||||||
common.getPadAttribute('tags', waitFor(function (err, val) {
|
common.getPadAttribute('tags', waitFor(function (err, val) {
|
||||||
data.tags = val;
|
data.tags = val;
|
||||||
}));
|
}));
|
||||||
|
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) {
|
common.getPadAttribute('owners', waitFor(function (err, val) {
|
||||||
data.owners = val;
|
data.owners = val;
|
||||||
}));
|
}));
|
||||||
common.getPadAttribute('expire', waitFor(function (err, val) {
|
common.getPadAttribute('expire', waitFor(function (err, val) {
|
||||||
data.expire = val;
|
data.expire = val;
|
||||||
}));
|
}));*/
|
||||||
}).nThen(function () {
|
}).nThen(function () {
|
||||||
cb(void 0, data);
|
cb(void 0, data);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
var createOwnerModal = function (common, channel, owners) {
|
var createOwnerModal = function (common, data) {
|
||||||
var friends = common.getFriends(true);
|
var friends = common.getFriends(true);
|
||||||
var sframeChan = common.getSframeChannel();
|
var sframeChan = common.getSframeChannel();
|
||||||
var priv = common.getMetadataMgr().getPrivateData();
|
var priv = common.getMetadataMgr().getPrivateData();
|
||||||
|
var user = common.getMetadataMgr().getUserData();
|
||||||
var edPublic = priv.edPublic;
|
var edPublic = priv.edPublic;
|
||||||
|
var channel = data.channel;
|
||||||
|
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 = $(div1);
|
||||||
|
var $div2 = $(div2);
|
||||||
|
|
||||||
// Remove owner column
|
// Remove owner column
|
||||||
var drawRemove = function () {
|
var drawRemove = function (pending) {
|
||||||
var _owners = {};
|
var _owners = {};
|
||||||
owners.forEach(function (ed) {
|
var o = pending ? pending_owners : owners;
|
||||||
|
o.forEach(function (ed) {
|
||||||
var f;
|
var f;
|
||||||
Object.keys(friends).some(function (c) {
|
Object.keys(friends).some(function (c) {
|
||||||
if (friends[c].edPublic === ed) {
|
if (friends[c].edPublic === ed) {
|
||||||
@ -135,17 +160,19 @@ define([
|
|||||||
edPublic: ed,
|
edPublic: ed,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
var removeCol = UIElements.getFriendsList('Remove an existing owner instantly', {
|
var msg = pending ? 'Remove a pending owner:'
|
||||||
|
: 'Remove an existing owner:'; // XXX
|
||||||
|
var removeCol = UIElements.getFriendsList(msg, {
|
||||||
common: common,
|
common: common,
|
||||||
friends: _owners,
|
friends: _owners,
|
||||||
noFilter: true
|
noFilter: true
|
||||||
}, function () {
|
}, function () {
|
||||||
console.log(arguments);
|
console.log(arguments);
|
||||||
});
|
});
|
||||||
var $div1 = $(removeCol.div);
|
var $div = $(removeCol.div);
|
||||||
var others1 = removeCol.others;
|
var others1 = removeCol.others;
|
||||||
$div1.append(h('div.cp-share-grid', others1));
|
$div.append(h('div.cp-share-grid', others1));
|
||||||
$div1.find('.cp-share-friend').click(function () {
|
$div.find('.cp-share-friend').click(function () {
|
||||||
var sel = $(this).hasClass('cp-selected');
|
var sel = $(this).hasClass('cp-selected');
|
||||||
if (!sel) {
|
if (!sel) {
|
||||||
$(this).addClass('cp-selected');
|
$(this).addClass('cp-selected');
|
||||||
@ -157,10 +184,11 @@ define([
|
|||||||
});
|
});
|
||||||
// When clicking on the remove button, we check the selected users.
|
// When clicking on the remove button, we check the selected users.
|
||||||
// If you try to remove yourself, we'll display an additional warning message
|
// If you try to remove yourself, we'll display an additional warning message
|
||||||
var removeButton = h('button.no-margin', 'Remove owners'); // XXX
|
var btnMsg = pending ? 'Remove pending owners' : 'Remove owners'; // XXX
|
||||||
|
var removeButton = h('button.no-margin', btnMsg);
|
||||||
$(removeButton).click(function () {
|
$(removeButton).click(function () {
|
||||||
// Check selection
|
// Check selection
|
||||||
var $sel = $div1.find('.cp-share-friend.cp-selected');
|
var $sel = $div.find('.cp-share-friend.cp-selected');
|
||||||
var sel = $sel.toArray();
|
var sel = $sel.toArray();
|
||||||
var me = false;
|
var me = false;
|
||||||
var toRemove = sel.map(function (el) {
|
var toRemove = sel.map(function (el) {
|
||||||
@ -173,14 +201,12 @@ define([
|
|||||||
var send = function () {
|
var send = function () {
|
||||||
sframeChan.query('Q_SET_PAD_METADATA', {
|
sframeChan.query('Q_SET_PAD_METADATA', {
|
||||||
channel: channel,
|
channel: channel,
|
||||||
command: 'RM_OWNERS',
|
command: pending ? 'RM_PENDING_OWNERS' : 'RM_OWNERS',
|
||||||
value: toRemove
|
value: toRemove
|
||||||
}, function (err, res) {
|
}, function (err, res) {
|
||||||
err = err || (res && res.error);
|
err = err || (res && res.error);
|
||||||
if (err) { return void UI.warn('ERROR' + err); } // XXX
|
if (err) { return void UI.warn('ERROR' + err); } // XXX
|
||||||
owners = res.owners;
|
redrawAll();
|
||||||
drawRemove().insertBefore($div1);
|
|
||||||
$div1.remove();
|
|
||||||
UI.log('DONE'); // XXX
|
UI.log('DONE'); // XXX
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -192,20 +218,26 @@ define([
|
|||||||
send();
|
send();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
$div1.append(h('p', removeButton));
|
$div.append(h('p', removeButton));
|
||||||
return $div1;
|
return $div;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Add owners column
|
// Add owners column
|
||||||
var drawAdd = function () {
|
var drawAdd = function () {
|
||||||
|
var _friends = JSON.parse(JSON.stringify(friends));
|
||||||
|
Object.keys(_friends).forEach(function (curve) {
|
||||||
|
if (owners.indexOf(_friends[curve].edPublic) !== -1) {
|
||||||
|
delete _friends[curve];
|
||||||
|
}
|
||||||
|
});
|
||||||
var addCol = UIElements.getFriendsList('Ask a friend to be an owner.', {
|
var addCol = UIElements.getFriendsList('Ask a friend to be an owner.', {
|
||||||
common: common,
|
common: common,
|
||||||
friends: friends
|
friends: _friends
|
||||||
}, function () {
|
}, function () {
|
||||||
// XXX onSelect...
|
// XXX onSelect...
|
||||||
console.log(arguments);
|
console.log(arguments);
|
||||||
});
|
});
|
||||||
var $div2 = $(addCol.div);
|
$div2 = $(addCol.div);
|
||||||
var others2 = addCol.others;
|
var others2 = addCol.others;
|
||||||
$div2.append(h('div.cp-share-grid', others2));
|
$div2.append(h('div.cp-share-grid', others2));
|
||||||
$div2.find('.cp-share-friend').click(function () {
|
$div2.find('.cp-share-friend').click(function () {
|
||||||
@ -226,38 +258,86 @@ define([
|
|||||||
var $sel = $div2.find('.cp-share-friend.cp-selected');
|
var $sel = $div2.find('.cp-share-friend.cp-selected');
|
||||||
var sel = $sel.toArray();
|
var sel = $sel.toArray();
|
||||||
var toAdd = sel.map(function (el) {
|
var toAdd = sel.map(function (el) {
|
||||||
return $(el).attr('data-curve');
|
return friends[$(el).attr('data-curve')].edPublic;
|
||||||
}).filter(function (x) { return x; });
|
}).filter(function (x) { return x; });
|
||||||
|
|
||||||
|
NThen(function (waitFor) {
|
||||||
|
var msg = "Are you sure?"; // XXX
|
||||||
|
UI.confirm(msg, waitFor(function (yes) {
|
||||||
|
if (!yes) {
|
||||||
|
waitFor.abort();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}).nThen(function (waitFor) {
|
||||||
|
console.log('koko');
|
||||||
// Send the command
|
// Send the command
|
||||||
var send = function () {
|
|
||||||
// XXX Pinning problem....
|
|
||||||
sframeChan.query('Q_SET_PAD_METADATA', {
|
sframeChan.query('Q_SET_PAD_METADATA', {
|
||||||
channel: channel,
|
channel: channel,
|
||||||
command: 'ADD_OWNERS',
|
command: 'ADD_PENDING_OWNERS',
|
||||||
value: toAdd
|
value: toAdd
|
||||||
}, function (err, res) {
|
}, waitFor(function (err, res) {
|
||||||
|
console.error(arguments);
|
||||||
err = err || (res && res.error);
|
err = err || (res && res.error);
|
||||||
if (err) { return void UI.warn('ERROR' + err); } // XXX
|
if (err) {
|
||||||
owners = res.owners;
|
waitFor.abort();
|
||||||
drawRemove().insertBefore($div2);
|
return void UI.warn('ERROR' + err);
|
||||||
$div2.remove();
|
} // XXX
|
||||||
|
}));
|
||||||
|
}).nThen(function (waitFor) {
|
||||||
|
console.log('okok');
|
||||||
|
// TODO send notifications
|
||||||
|
sel.forEach(function (el) {
|
||||||
|
var friend = friends[$(el).attr('data-curve')];
|
||||||
|
if (!friend) { return; }
|
||||||
|
common.mailbox.sendTo("ADD_OWNER", {
|
||||||
|
channel: channel,
|
||||||
|
href: data.href,
|
||||||
|
password: data.password,
|
||||||
|
title: data.title,
|
||||||
|
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());
|
||||||
|
});
|
||||||
|
}).nThen(function () {
|
||||||
|
redrawAll();
|
||||||
UI.log('DONE'); // XXX
|
UI.log('DONE'); // XXX
|
||||||
});
|
});
|
||||||
};
|
|
||||||
var msg = "Are you sure?"; // XXX
|
|
||||||
UI.confirm(msg, function (yes) {
|
|
||||||
if (!yes) { return; }
|
|
||||||
send();
|
|
||||||
});
|
});
|
||||||
});
|
$div2.append(h('p', addButton));
|
||||||
//$div2.append(h('p', addButton));
|
|
||||||
return $div2;
|
return $div2;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
redrawAll = function () {
|
||||||
|
$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());
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
$div1.append(drawRemove(false)).append(drawRemove(true));
|
||||||
|
$div2.append(drawAdd());
|
||||||
|
|
||||||
// Create modal
|
// Create modal
|
||||||
var link = h('div.cp-share-columns', [
|
var link = h('div.cp-share-columns', [
|
||||||
drawRemove()[0],
|
div1,
|
||||||
drawAdd()[0]
|
div2
|
||||||
|
/*drawRemove()[0],
|
||||||
|
drawAdd()[0]*/
|
||||||
]);
|
]);
|
||||||
var linkButtons = [{
|
var linkButtons = [{
|
||||||
className: 'cancel',
|
className: 'cancel',
|
||||||
@ -310,7 +390,7 @@ define([
|
|||||||
if (owned) {
|
if (owned) {
|
||||||
var manageOwners = h('button.no-margin', 'Manage owners'); // XXX
|
var manageOwners = h('button.no-margin', 'Manage owners'); // XXX
|
||||||
$(manageOwners).click(function () {
|
$(manageOwners).click(function () {
|
||||||
var modal = createOwnerModal(common, data.channel, data.owners);
|
var modal = createOwnerModal(common, data);
|
||||||
UI.openCustomModal(modal, {
|
UI.openCustomModal(modal, {
|
||||||
wide: true,
|
wide: true,
|
||||||
});
|
});
|
||||||
@ -3152,7 +3232,7 @@ define([
|
|||||||
|
|
||||||
UIElements.displayFriendRequestModal = function (common, data) {
|
UIElements.displayFriendRequestModal = function (common, data) {
|
||||||
var msg = data.content.msg;
|
var msg = data.content.msg;
|
||||||
var text = Messages._getKey('contacts_request', [msg.content.displayName]);
|
var text = Messages._getKey('contacts_request', [Util.fixHTML(msg.content.displayName)]);
|
||||||
|
|
||||||
var todo = function (yes) {
|
var todo = function (yes) {
|
||||||
common.getSframeChannel().query("Q_ANSWER_FRIEND_REQUEST", {
|
common.getSframeChannel().query("Q_ANSWER_FRIEND_REQUEST", {
|
||||||
@ -3197,5 +3277,132 @@ define([
|
|||||||
UI.openCustomModal(modal);
|
UI.openCustomModal(modal);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
UIElements.displayAddOwnerModal = function (common, data) {
|
||||||
|
var priv = common.getMetadataMgr().getPrivateData();
|
||||||
|
var user = common.getMetadataMgr().getUserData();
|
||||||
|
var sframeChan = common.getSframeChannel();
|
||||||
|
var msg = data.content.msg;
|
||||||
|
|
||||||
|
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', {
|
||||||
|
href: '#'
|
||||||
|
}, Messages.requestEdit_viewPad);
|
||||||
|
$(link).click(function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
if (msg.content.password) {
|
||||||
|
common.sessionStorage.put('newPadPassword', msg.content.password, function () {
|
||||||
|
common.openURL(msg.content.href);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
common.openURL(msg.content.href);
|
||||||
|
});
|
||||||
|
|
||||||
|
var div = h('div', [
|
||||||
|
UI.setHTML(h('p'), text),
|
||||||
|
link
|
||||||
|
]);
|
||||||
|
|
||||||
|
var answer = function (yes) {
|
||||||
|
common.mailbox.sendTo("ADD_OWNER_ANSWER", {
|
||||||
|
channel: msg.content.channel,
|
||||||
|
href: msg.content.href,
|
||||||
|
password: msg.content.password,
|
||||||
|
title: msg.content.title,
|
||||||
|
answer: yes,
|
||||||
|
user: {
|
||||||
|
displayName: user.name,
|
||||||
|
avatar: user.avatar,
|
||||||
|
profile: user.profile,
|
||||||
|
notifications: user.notifications,
|
||||||
|
curvePublic: user.curvePublic,
|
||||||
|
edPublic: priv.edPublic
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
channel: msg.content.user.notifications,
|
||||||
|
curvePublic: msg.content.user.curvePublic
|
||||||
|
});
|
||||||
|
common.mailbox.dismiss(data, function (err) {
|
||||||
|
console.log(err);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
var todo = function (yes) {
|
||||||
|
if (yes) {
|
||||||
|
// ACCEPT
|
||||||
|
sframeChan.query('Q_SET_PAD_METADATA', {
|
||||||
|
channel: msg.content.channel,
|
||||||
|
command: 'ADD_OWNERS',
|
||||||
|
value: [priv.edPublic]
|
||||||
|
}, function (err, res) {
|
||||||
|
err = err || (res && res.error);
|
||||||
|
if (err) {
|
||||||
|
return void UI.warn('ERROR ' + err);
|
||||||
|
} // XXX
|
||||||
|
UI.log('DONE'); // XXX
|
||||||
|
|
||||||
|
// Send notification to the sender
|
||||||
|
answer(true);
|
||||||
|
|
||||||
|
// Remove yourself from the pending owners
|
||||||
|
sframeChan.query('Q_SET_PAD_METADATA', {
|
||||||
|
channel: msg.content.channel,
|
||||||
|
command: 'RM_PENDING_OWNERS',
|
||||||
|
value: [priv.edPublic]
|
||||||
|
}, function (err, res) {
|
||||||
|
err = err || (res && res.error);
|
||||||
|
if (err) {
|
||||||
|
console.error(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// DECLINE
|
||||||
|
// Remove yourself from the pending owners
|
||||||
|
sframeChan.query('Q_SET_PAD_METADATA', {
|
||||||
|
channel: msg.content.channel,
|
||||||
|
command: 'RM_PENDING_OWNERS',
|
||||||
|
value: [priv.edPublic]
|
||||||
|
}, function (err, res) {
|
||||||
|
err = err || (res && res.error);
|
||||||
|
if (err) {
|
||||||
|
console.error(err);
|
||||||
|
}
|
||||||
|
// Send notification to the sender
|
||||||
|
answer(false);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
var buttons = [{
|
||||||
|
name: Messages.friendRequest_later,
|
||||||
|
onClick: function () {},
|
||||||
|
keys: [27]
|
||||||
|
}, {
|
||||||
|
className: 'primary',
|
||||||
|
name: Messages.friendRequest_accept,
|
||||||
|
onClick: function () {
|
||||||
|
todo(true);
|
||||||
|
},
|
||||||
|
keys: [13]
|
||||||
|
}, {
|
||||||
|
className: 'primary',
|
||||||
|
name: Messages.friendRequest_decline,
|
||||||
|
onClick: function () {
|
||||||
|
todo(false);
|
||||||
|
},
|
||||||
|
keys: [[13, 'ctrl']]
|
||||||
|
}];
|
||||||
|
var modal = UI.dialog.customModal(div, {buttons: buttons});
|
||||||
|
UI.openCustomModal(modal);
|
||||||
|
};
|
||||||
|
|
||||||
return UIElements;
|
return UIElements;
|
||||||
});
|
});
|
||||||
|
|||||||
@ -758,6 +758,10 @@ define([
|
|||||||
pad.onConnectEvent = Util.mkEvent();
|
pad.onConnectEvent = Util.mkEvent();
|
||||||
pad.onErrorEvent = Util.mkEvent();
|
pad.onErrorEvent = Util.mkEvent();
|
||||||
|
|
||||||
|
pad.getPadMetadata = function (data, cb) {
|
||||||
|
postMessage('GET_PAD_METADATA', data, cb);
|
||||||
|
};
|
||||||
|
|
||||||
pad.requestAccess = function (data, cb) {
|
pad.requestAccess = function (data, cb) {
|
||||||
postMessage("REQUEST_PAD_ACCESS", data, cb);
|
postMessage("REQUEST_PAD_ACCESS", data, cb);
|
||||||
};
|
};
|
||||||
@ -769,7 +773,10 @@ define([
|
|||||||
postMessage('SET_PAD_METADATA', data, cb);
|
postMessage('SET_PAD_METADATA', data, cb);
|
||||||
};
|
};
|
||||||
common.getPadMetadata = function (data, cb) {
|
common.getPadMetadata = function (data, cb) {
|
||||||
postMessage('GET_PAD_METADATA', data, cb);
|
common.anonRpcMsg('GET_METADATA', data.channel, function (err, obj) {
|
||||||
|
if (err) { return void cb({error: err}); }
|
||||||
|
cb(obj && obj[0]);
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
common.changePadPassword = function (Crypt, href, newPassword, edPublic, cb) {
|
common.changePadPassword = function (Crypt, href, newPassword, edPublic, cb) {
|
||||||
|
|||||||
@ -210,6 +210,48 @@ define([
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
handlers['ADD_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);
|
||||||
|
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]);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Check authenticity
|
||||||
|
if (msg.author !== msg.content.user.curvePublic) { return; }
|
||||||
|
|
||||||
|
// if not archived, add handlers
|
||||||
|
if (!content.archived) {
|
||||||
|
content.handler = function () {
|
||||||
|
UIElements.displayAddOwnerModal(common, data);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
handlers['ADD_OWNER_ANSWER'] = 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);
|
||||||
|
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]);
|
||||||
|
};
|
||||||
|
if (!content.archived) {
|
||||||
|
content.dismissHandler = defaultDismiss(common, data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// NOTE: don't forget to fixHTML everything returned by "getFormatText"
|
// NOTE: don't forget to fixHTML everything returned by "getFormatText"
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@ -1374,6 +1374,7 @@ define([
|
|||||||
};
|
};
|
||||||
|
|
||||||
Store.getPadMetadata = function (clientId, data, cb) {
|
Store.getPadMetadata = function (clientId, data, cb) {
|
||||||
|
console.log(data);
|
||||||
if (!data.channel) { return void cb({ error: 'ENOTFOUND'}); }
|
if (!data.channel) { return void cb({ error: 'ENOTFOUND'}); }
|
||||||
var channel = channels[data.channel];
|
var channel = channels[data.channel];
|
||||||
if (!channel) { return void cb({ error: 'ENOTFOUND' }); }
|
if (!channel) { return void cb({ error: 'ENOTFOUND' }); }
|
||||||
@ -1396,6 +1397,7 @@ define([
|
|||||||
cb(channel.data || {});
|
cb(channel.data || {});
|
||||||
};
|
};
|
||||||
Store.setPadMetadata = function (clientId, data, cb) {
|
Store.setPadMetadata = function (clientId, data, cb) {
|
||||||
|
console.log(data);
|
||||||
if (!data.channel) { return void cb({ error: 'ENOTFOUND'}); }
|
if (!data.channel) { return void cb({ error: 'ENOTFOUND'}); }
|
||||||
if (!data.command) { return void cb({ error: 'EINVAL' }); }
|
if (!data.command) { return void cb({ error: 'EINVAL' }); }
|
||||||
store.rpc.setMetadata(data, function (err, res) {
|
store.rpc.setMetadata(data, function (err, res) {
|
||||||
|
|||||||
@ -259,6 +259,33 @@ define([
|
|||||||
cb(false);
|
cb(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Hide duplicates when receiving an ADD_OWNER notification:
|
||||||
|
var addOwners = {};
|
||||||
|
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) {
|
||||||
|
console.log('Remove invalid notification');
|
||||||
|
return void cb(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
var channel = content.channel;
|
||||||
|
|
||||||
|
if (addOwners[channel]) { return void cb(true); }
|
||||||
|
addOwners[channel] = true;
|
||||||
|
|
||||||
|
cb(false);
|
||||||
|
};
|
||||||
|
removeHandlers['ADD_OWNER'] = function (ctx, box, data) {
|
||||||
|
var channel = data.content.channel;
|
||||||
|
if (addOwners[channel]) {
|
||||||
|
delete addOwners[channel];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
add: function (ctx, box, data, cb) {
|
add: function (ctx, box, data, cb) {
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -32,13 +32,17 @@ define([
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
mailbox.sendTo = function (type, content, user) {
|
mailbox.sendTo = function (type, content, user, cb) {
|
||||||
|
cb = cb || function () {};
|
||||||
execCommand('SENDTO', {
|
execCommand('SENDTO', {
|
||||||
type: type,
|
type: type,
|
||||||
msg: content,
|
msg: content,
|
||||||
user: user
|
user: user
|
||||||
}, function (err, obj) {
|
}, function (err, obj) {
|
||||||
if (err || (obj && obj.error)) { return void console.error(err || obj.error); }
|
cb(err || (obj && obj.error), obj);
|
||||||
|
if (err || (obj && obj.error)) {
|
||||||
|
return void console.error(err || obj.error);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -981,7 +981,7 @@ define([
|
|||||||
// Try to get the owner's mailbox from the pad metadata first.
|
// Try to get the owner's mailbox from the pad metadata first.
|
||||||
// If it's is an older owned pad, check if the owner is a friend
|
// If it's is an older owned pad, check if the owner is a friend
|
||||||
// or an acquaintance (from async-store directly in requestAccess)
|
// or an acquaintance (from async-store directly in requestAccess)
|
||||||
Cryptpad.getPadMetadata({
|
Cryptpad.pad.getPadMetadata({
|
||||||
channel: secret.channel
|
channel: secret.channel
|
||||||
}, waitFor(function (obj) {
|
}, waitFor(function (obj) {
|
||||||
obj = obj || {};
|
obj = obj || {};
|
||||||
@ -1004,6 +1004,15 @@ define([
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
sframeChan.on('Q_GET_PAD_METADATA', function (data, cb) {
|
||||||
|
if (!data || !data.channel) {
|
||||||
|
data = {
|
||||||
|
channel: secret.channel
|
||||||
|
};
|
||||||
|
}
|
||||||
|
console.log(data);
|
||||||
|
Cryptpad.getPadMetadata(data, cb);
|
||||||
|
});
|
||||||
sframeChan.on('Q_SET_PAD_METADATA', function (data, cb) {
|
sframeChan.on('Q_SET_PAD_METADATA', function (data, cb) {
|
||||||
Cryptpad.setPadMetadata(data, cb);
|
Cryptpad.setPadMetadata(data, cb);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -467,6 +467,13 @@ define([
|
|||||||
}, { timeout: 60000 });
|
}, { timeout: 60000 });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
funcs.getPadMetadata = function (data, cb) {
|
||||||
|
ctx.sframeChan.query('Q_GET_PAD_METADATA', data, function (err, val) {
|
||||||
|
if (err || (val && val.error)) { return void cb({error: err || val.error}); }
|
||||||
|
cb(val);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
funcs.gotoURL = function (url) { ctx.sframeChan.event('EV_GOTO_URL', url); };
|
funcs.gotoURL = function (url) { ctx.sframeChan.event('EV_GOTO_URL', url); };
|
||||||
funcs.openURL = function (url) { ctx.sframeChan.event('EV_OPEN_URL', url); };
|
funcs.openURL = function (url) { ctx.sframeChan.event('EV_OPEN_URL', url); };
|
||||||
funcs.openUnsafeURL = function (url) {
|
funcs.openUnsafeURL = function (url) {
|
||||||
|
|||||||
@ -3716,6 +3716,20 @@ define([
|
|||||||
data.sharedFolder = true;
|
data.sharedFolder = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (manager.isFile(el) && data.roHref) { // Only for pads!
|
||||||
|
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;
|
||||||
|
data.pending_owners = val.pending_owners;
|
||||||
|
}
|
||||||
|
UIElements.getProperties(common, data, cb);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
UIElements.getProperties(common, data, cb);
|
UIElements.getProperties(common, data, cb);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user