Merge branch 'staging' into team
This commit is contained in:
commit
dbe63f254a
@ -442,7 +442,7 @@
|
|||||||
margin-bottom: 15px;
|
margin-bottom: 15px;
|
||||||
}
|
}
|
||||||
.cp-share-grid {
|
.cp-share-grid {
|
||||||
max-height: 228px;
|
max-height: 225px;
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
}
|
}
|
||||||
.cp-recent-only {
|
.cp-recent-only {
|
||||||
@ -478,6 +478,7 @@
|
|||||||
margin-bottom: 6px;
|
margin-bottom: 6px;
|
||||||
cursor: default;
|
cursor: default;
|
||||||
transition: order 0.5s, background-color 0.5s;
|
transition: order 0.5s, background-color 0.5s;
|
||||||
|
margin-top: 1px;
|
||||||
.tools_unselectable();
|
.tools_unselectable();
|
||||||
|
|
||||||
&.cp-selected {
|
&.cp-selected {
|
||||||
|
|||||||
@ -77,6 +77,8 @@ define([
|
|||||||
waitFor.abort();
|
waitFor.abort();
|
||||||
return void cb(err || 'EEMPTY');
|
return void cb(err || 'EEMPTY');
|
||||||
}
|
}
|
||||||
|
delete val.owners;
|
||||||
|
delete val.expire;
|
||||||
Util.extend(data, val);
|
Util.extend(data, val);
|
||||||
if (data.href) { data.href = base + data.href; }
|
if (data.href) { data.href = base + data.href; }
|
||||||
if (data.roHref) { data.roHref = base + data.roHref; }
|
if (data.roHref) { data.roHref = base + data.roHref; }
|
||||||
|
|||||||
@ -769,10 +769,6 @@ define([
|
|||||||
pad.onErrorEvent = Util.mkEvent();
|
pad.onErrorEvent = Util.mkEvent();
|
||||||
pad.onMetadataEvent = Util.mkEvent();
|
pad.onMetadataEvent = 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);
|
||||||
};
|
};
|
||||||
@ -784,14 +780,11 @@ define([
|
|||||||
postMessage('SET_PAD_METADATA', data, cb);
|
postMessage('SET_PAD_METADATA', data, cb);
|
||||||
};
|
};
|
||||||
common.getPadMetadata = function (data, cb) {
|
common.getPadMetadata = function (data, cb) {
|
||||||
common.anonRpcMsg('GET_METADATA', data.channel, function (err, obj) {
|
postMessage('GET_PAD_METADATA', data, cb);
|
||||||
if (err) { return void cb({error: err}); }
|
|
||||||
cb(obj && obj[0]);
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// XXX Teams: change the password of a pad owned by the team
|
// XXX Teams: change the password of a pad owned by the team
|
||||||
common.changePadPassword = function (Crypt, href, newPassword, edPublic, cb) {
|
common.changePadPassword = function (Crypt, Crypto, href, newPassword, edPublic, cb) {
|
||||||
if (!href) { return void cb({ error: 'EINVAL_HREF' }); }
|
if (!href) { return void cb({ error: 'EINVAL_HREF' }); }
|
||||||
var parsed = Hash.parsePadUrl(href);
|
var parsed = Hash.parsePadUrl(href);
|
||||||
if (!parsed.hash) { return void cb({ error: 'EINVAL_HREF' }); }
|
if (!parsed.hash) { return void cb({ error: 'EINVAL_HREF' }); }
|
||||||
@ -799,6 +792,8 @@ define([
|
|||||||
var warning = false;
|
var warning = false;
|
||||||
var newHash, newRoHref;
|
var newHash, newRoHref;
|
||||||
var oldChannel;
|
var oldChannel;
|
||||||
|
var oldSecret;
|
||||||
|
var oldMetadata;
|
||||||
var newSecret;
|
var newSecret;
|
||||||
|
|
||||||
if (parsed.hashData.version >= 2) {
|
if (parsed.hashData.version >= 2) {
|
||||||
@ -815,27 +810,61 @@ define([
|
|||||||
|
|
||||||
var optsGet = {};
|
var optsGet = {};
|
||||||
var optsPut = {
|
var optsPut = {
|
||||||
password: newPassword
|
password: newPassword,
|
||||||
|
metadata: {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
Nthen(function (waitFor) {
|
Nthen(function (waitFor) {
|
||||||
if (parsed.hashData && parsed.hashData.password) {
|
if (parsed.hashData && parsed.hashData.password) {
|
||||||
common.getPadAttribute('password', waitFor(function (err, password) {
|
common.getPadAttribute('password', waitFor(function (err, password) {
|
||||||
optsGet.password = password;
|
optsGet.password = password;
|
||||||
}), href);
|
}), href);
|
||||||
}
|
}
|
||||||
common.getPadAttribute('owners', waitFor(function (err, owners) {
|
}).nThen(function (waitFor) {
|
||||||
if (!Array.isArray(owners) || owners.indexOf(edPublic) === -1) {
|
oldSecret = Hash.getSecrets(parsed.type, parsed.hash, optsGet.password);
|
||||||
// We're not an owner, we shouldn't be able to change the password!
|
oldChannel = oldSecret.channel;
|
||||||
waitFor.abort();
|
common.getPadMetadata({channel: oldChannel}, waitFor(function (metadata) {
|
||||||
return void cb({ error: 'EPERM' });
|
oldMetadata = metadata;
|
||||||
|
}));
|
||||||
|
}).nThen(function (waitFor) {
|
||||||
|
// Get owners, mailbox and expiration time
|
||||||
|
|
||||||
|
var owners = oldMetadata.owners;
|
||||||
|
if (!Array.isArray(owners) || owners.indexOf(edPublic) === -1) {
|
||||||
|
// We're not an owner, we shouldn't be able to change the password!
|
||||||
|
waitFor.abort();
|
||||||
|
return void cb({ error: 'EPERM' });
|
||||||
|
}
|
||||||
|
optsPut.metadata.owners = owners;
|
||||||
|
|
||||||
|
var mailbox = oldMetadata.mailbox;
|
||||||
|
if (mailbox) {
|
||||||
|
// Create the encryptors to be able to decrypt and re-encrypt the mailboxes
|
||||||
|
var oldCrypto = Crypto.createEncryptor(oldSecret.keys);
|
||||||
|
var newCrypto = Crypto.createEncryptor(newSecret.keys);
|
||||||
|
|
||||||
|
var m;
|
||||||
|
if (typeof(mailbox) === "string") {
|
||||||
|
try {
|
||||||
|
m = newCrypto.encrypt(oldCrypto.decrypt(mailbox, true, true));
|
||||||
|
} catch (e) {}
|
||||||
|
} else if (mailbox && typeof(mailbox) === "object") {
|
||||||
|
m = {};
|
||||||
|
Object.keys(mailbox).forEach(function (ed) {
|
||||||
|
console.log(mailbox[ed]);
|
||||||
|
try {
|
||||||
|
m[ed] = newCrypto.encrypt(oldCrypto.decrypt(mailbox[ed], true, true));
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
optsPut.owners = owners;
|
optsPut.metadata.mailbox = m;
|
||||||
}), href);
|
}
|
||||||
// XXX get the mailbox fields, decrypt all the mailboxes, reencrypt them, and put them in the metadata
|
|
||||||
// XXX also use optsPut.metadata (and fix it in cryptget) instead of optsPut.owners
|
var expire = oldMetadata.expire;
|
||||||
common.getPadAttribute('expire', waitFor(function (err, expire) {
|
optsPut.metadata.expire = (expire - (+new Date())) / 1000; // Lifetime in seconds
|
||||||
optsPut.expire = (expire - (+new Date())) / 1000; // Lifetime in seconds
|
|
||||||
}), href);
|
|
||||||
}).nThen(function (waitFor) {
|
}).nThen(function (waitFor) {
|
||||||
Crypt.get(parsed.hash, waitFor(function (err, val) {
|
Crypt.get(parsed.hash, waitFor(function (err, val) {
|
||||||
if (err) {
|
if (err) {
|
||||||
@ -850,8 +879,6 @@ define([
|
|||||||
}), optsPut);
|
}), optsPut);
|
||||||
}), optsGet);
|
}), optsGet);
|
||||||
}).nThen(function (waitFor) {
|
}).nThen(function (waitFor) {
|
||||||
var secret = Hash.getSecrets(parsed.type, parsed.hash, optsGet.password);
|
|
||||||
oldChannel = secret.channel;
|
|
||||||
pad.leavePad({
|
pad.leavePad({
|
||||||
channel: oldChannel
|
channel: oldChannel
|
||||||
}, waitFor());
|
}, waitFor());
|
||||||
|
|||||||
@ -952,6 +952,9 @@ define([
|
|||||||
if (channelData && channelData.wc && channel === channelData.wc.id) {
|
if (channelData && channelData.wc && channel === channelData.wc.id) {
|
||||||
expire = +channelData.data.expire || undefined;
|
expire = +channelData.data.expire || undefined;
|
||||||
}
|
}
|
||||||
|
if (data.expire) {
|
||||||
|
expire = data.expire;
|
||||||
|
}
|
||||||
|
|
||||||
// Check if the pad is stored in any managers.
|
// Check if the pad is stored in any managers.
|
||||||
// If it is stored, update its data, otherwise ask the user where to store it
|
// If it is stored, update its data, otherwise ask the user where to store it
|
||||||
@ -1380,10 +1383,15 @@ define([
|
|||||||
var allData = s.manager.findChannel(data.channel);
|
var allData = s.manager.findChannel(data.channel);
|
||||||
allData.forEach(function (obj) {
|
allData.forEach(function (obj) {
|
||||||
obj.data.owners = metadata.owners;
|
obj.data.owners = metadata.owners;
|
||||||
|
obj.data.atime = +new Date();
|
||||||
if (metadata.expire) {
|
if (metadata.expire) {
|
||||||
obj.data.expire = +metadata.expire;
|
obj.data.expire = +metadata.expire;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
var send = s.sendEvent || sendDriveEvent;
|
||||||
|
send('DRIVE_CHANGE', {
|
||||||
|
path: ['drive', UserObject.FILES_DATA]
|
||||||
|
});
|
||||||
});
|
});
|
||||||
channel.bcast("PAD_METADATA", metadata);
|
channel.bcast("PAD_METADATA", metadata);
|
||||||
},
|
},
|
||||||
@ -1451,32 +1459,15 @@ define([
|
|||||||
// data.send === true ==> send the request
|
// data.send === true ==> send the request
|
||||||
Store.requestPadAccess = function (clientId, data, cb) {
|
Store.requestPadAccess = function (clientId, data, cb) {
|
||||||
var owner = data.owner;
|
var owner = data.owner;
|
||||||
var channel = channels[data.channel];
|
var owners = data.owners;
|
||||||
if (!channel) { return void cb({error: 'ENOTFOUND'}); }
|
|
||||||
if (!data.send && channel && (!channel.data || !channel.data.channel)) {
|
|
||||||
var i = 0;
|
|
||||||
var it = setInterval(function () {
|
|
||||||
if (channel.data && channel.data.channel) {
|
|
||||||
clearInterval(it);
|
|
||||||
Store.requestPadAccess(clientId, data, cb);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (i >= 300) { // One minute timeout
|
|
||||||
clearInterval(it);
|
|
||||||
return void cb({error: 'ETIMEOUT'});
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
}, 200);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the owner was not is the pad metadata, check if it is a friend.
|
// If the owner was not is the pad metadata, check if it is a friend.
|
||||||
// We'll contact the first owner for whom we know the mailbox
|
// We'll contact the first owner for whom we know the mailbox
|
||||||
var fData = channel.data || {};
|
if (!owner && Array.isArray(owners)) {
|
||||||
if (!owner && fData.owners) {
|
|
||||||
var friends = store.proxy.friends || {};
|
var friends = store.proxy.friends || {};
|
||||||
if (Object.keys(friends).length > 1) {
|
// If we have friends, check if an owner is one of them (with a mailbox)
|
||||||
fData.owners.some(function (edPublic) {
|
if (Object.keys(friends).filter(function (curve) { return curve !== 'me'; }).length) {
|
||||||
|
owners.some(function (edPublic) {
|
||||||
return Object.keys(friends).some(function (curve) {
|
return Object.keys(friends).some(function (curve) {
|
||||||
if (curve === "me") { return; }
|
if (curve === "me") { return; }
|
||||||
if (edPublic === friends[curve].edPublic &&
|
if (edPublic === friends[curve].edPublic &&
|
||||||
@ -1545,27 +1536,31 @@ define([
|
|||||||
cb();
|
cb();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Fetch the latest version of the metadata on the server and return it.
|
||||||
|
// If the pad is stored in our drive, update the local values of "owners" and "expire"
|
||||||
Store.getPadMetadata = function (clientId, data, cb) {
|
Store.getPadMetadata = function (clientId, data, cb) {
|
||||||
if (!data.channel) { return void cb({ error: 'ENOTFOUND'}); }
|
if (!data.channel) { return void cb({ error: 'ENOTFOUND'}); }
|
||||||
var channel = channels[data.channel];
|
store.anon_rpc.send('GET_METADATA', data.channel, function (err, obj) {
|
||||||
if (!channel) { return void cb({ error: 'ENOTFOUND' }); }
|
if (err) { return void cb({error: err}); }
|
||||||
if (!channel.data || !channel.data.channel) {
|
var metadata = (obj && obj[0]) || {};
|
||||||
var i = 0;
|
cb(metadata);
|
||||||
var it = setInterval(function () {
|
|
||||||
if (channel.data && channel.data.channel) {
|
// Update owners and expire time in the drive
|
||||||
clearInterval(it);
|
getAllStores().forEach(function (s) {
|
||||||
Store.getPadMetadata(clientId, data, cb);
|
var allData = s.manager.findChannel(data.channel);
|
||||||
return;
|
allData.forEach(function (obj) {
|
||||||
}
|
obj.data.owners = metadata.owners;
|
||||||
if (i >= 300) { // One minute timeout
|
obj.data.atime = +new Date();
|
||||||
clearInterval(it);
|
if (metadata.expire) {
|
||||||
return void cb({error: 'ETIMEOUT'});
|
obj.data.expire = +metadata.expire;
|
||||||
}
|
}
|
||||||
i++;
|
});
|
||||||
}, 200);
|
var send = s.sendEvent || sendDriveEvent;
|
||||||
return;
|
send('DRIVE_CHANGE', {
|
||||||
}
|
path: ['drive', UserObject.FILES_DATA]
|
||||||
cb(channel.data || {});
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
};
|
};
|
||||||
Store.setPadMetadata = function (clientId, data, cb) {
|
Store.setPadMetadata = function (clientId, data, cb) {
|
||||||
if (!data.channel) { return void cb({ error: 'ENOTFOUND'}); }
|
if (!data.channel) { return void cb({ error: 'ENOTFOUND'}); }
|
||||||
|
|||||||
@ -77,7 +77,12 @@ proxy.mailboxes = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Send a message to someone else
|
// Send a message to someone else
|
||||||
var sendTo = Mailbox.sendTo = function (ctx, type, msg, user, cb) {
|
var sendTo = Mailbox.sendTo = function (ctx, type, msg, user, _cb) {
|
||||||
|
var cb = _cb || function (obj) {
|
||||||
|
if (obj && obj.error) {
|
||||||
|
console.error(obj.error);
|
||||||
|
}
|
||||||
|
};
|
||||||
if (!Crypto.Mailbox) {
|
if (!Crypto.Mailbox) {
|
||||||
return void cb({error: "chainpad-crypto is outdated and doesn't support mailboxes."});
|
return void cb({error: "chainpad-crypto is outdated and doesn't support mailboxes."});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -911,7 +911,7 @@ define([
|
|||||||
|
|
||||||
sframeChan.on('Q_PAD_PASSWORD_CHANGE', function (data, cb) {
|
sframeChan.on('Q_PAD_PASSWORD_CHANGE', function (data, cb) {
|
||||||
var href = data.href || window.location.href;
|
var href = data.href || window.location.href;
|
||||||
Cryptpad.changePadPassword(Cryptget, href, data.password, edPublic, cb);
|
Cryptpad.changePadPassword(Cryptget, Crypto, href, data.password, edPublic, cb);
|
||||||
});
|
});
|
||||||
|
|
||||||
sframeChan.on('Q_CHANGE_USER_PASSWORD', function (data, cb) {
|
sframeChan.on('Q_CHANGE_USER_PASSWORD', function (data, cb) {
|
||||||
@ -1010,21 +1010,26 @@ define([
|
|||||||
sframeChan.on('EV_GIVE_ACCESS', function (data, cb) {
|
sframeChan.on('EV_GIVE_ACCESS', function (data, cb) {
|
||||||
Cryptpad.padRpc.giveAccess(data, cb);
|
Cryptpad.padRpc.giveAccess(data, cb);
|
||||||
});
|
});
|
||||||
sframeChan.on('Q_REQUEST_ACCESS', function (data, cb) {
|
// REQUEST_ACCESS is used both to check IF we can contact an owner (send === false)
|
||||||
|
// AND also to send the request if we want (send === true)
|
||||||
|
sframeChan.on('Q_REQUEST_ACCESS', function (send, cb) {
|
||||||
if (readOnly && hashes.editHash) {
|
if (readOnly && hashes.editHash) {
|
||||||
return void cb({error: 'ALREADYKNOWN'});
|
return void cb({error: 'ALREADYKNOWN'});
|
||||||
}
|
}
|
||||||
var owner;
|
var owner, owners;
|
||||||
var crypto = Crypto.createEncryptor(secret.keys);
|
var crypto = Crypto.createEncryptor(secret.keys);
|
||||||
nThen(function (waitFor) {
|
nThen(function (waitFor) {
|
||||||
// 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.pad.getPadMetadata({
|
Cryptpad.getPadMetadata({
|
||||||
channel: secret.channel
|
channel: secret.channel
|
||||||
}, waitFor(function (obj) {
|
}, waitFor(function (obj) {
|
||||||
obj = obj || {};
|
obj = obj || {};
|
||||||
if (obj.error) { return; }
|
if (obj.error) { return; }
|
||||||
|
|
||||||
|
owners = obj.owners;
|
||||||
|
|
||||||
var mailbox;
|
var mailbox;
|
||||||
// Get the first available mailbox (the field can be an string or an object)
|
// 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?
|
// TODO maybe we should send the request to all the owners?
|
||||||
@ -1043,10 +1048,16 @@ define([
|
|||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
}).nThen(function () {
|
}).nThen(function () {
|
||||||
|
// If we are just checking (send === false) and there is a mailbox field, cb state true
|
||||||
|
// If there is no mailbox, we'll have to check if an owner is a friend in the worker
|
||||||
|
if (owner && !send) {
|
||||||
|
return void cb({state: true});
|
||||||
|
}
|
||||||
Cryptpad.padRpc.requestAccess({
|
Cryptpad.padRpc.requestAccess({
|
||||||
send: data,
|
send: send,
|
||||||
channel: secret.channel,
|
channel: secret.channel,
|
||||||
owner: owner
|
owner: owner,
|
||||||
|
owners: owners
|
||||||
}, cb);
|
}, cb);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1149,7 +1149,7 @@
|
|||||||
"owner_unknownUser": "Utilisateur inconnu",
|
"owner_unknownUser": "Utilisateur inconnu",
|
||||||
"owner_removeButton": "Supprimer les propriétaires sélectionnés",
|
"owner_removeButton": "Supprimer les propriétaires sélectionnés",
|
||||||
"owner_removePendingButton": "Annuler les offres sélectionnées",
|
"owner_removePendingButton": "Annuler les offres sélectionnées",
|
||||||
"owner_addButton": "Proposer la co-propriété",
|
"owner_addButton": "Proposer d'être propriétaire",
|
||||||
"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_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_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_addConfirm": "Les co-propriétaires seront en mesure de changer le contenu du document et pourront supprimer vos droits de propriétaire. Continuer ?",
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user