diff --git a/www/common/cryptpad-common.js b/www/common/cryptpad-common.js index 0311387ee..4ffbd4c0c 100644 --- a/www/common/cryptpad-common.js +++ b/www/common/cryptpad-common.js @@ -700,6 +700,10 @@ define([ postMessage("GIVE_PAD_ACCESS", data, cb); }; + common.getPadMetadata = function (data, cb) { + postMessage('GET_PAD_METADATA', data, cb); + }; + common.changePadPassword = function (Crypt, href, newPassword, edPublic, cb) { if (!href) { return void cb({ error: 'EINVAL_HREF' }); } var parsed = Hash.parsePadUrl(href); diff --git a/www/common/outer/async-store.js b/www/common/outer/async-store.js index 063d23ad8..417fd0fa8 100644 --- a/www/common/outer/async-store.js +++ b/www/common/outer/async-store.js @@ -1242,10 +1242,9 @@ define([ }; Store.requestPadAccess = function (clientId, data, cb) { - // Get owners from pad metadata - // Try to find an owner in our friend list - // Mailbox... + var owner = data.owner; var channel = channels[data.channel]; + if (!channel) { return void cb({error: 'ENOTFOUND'}); } if (!data.send && channel && (!channel.data || !channel.data.channel)) { var i = 0; var it = setInterval(function () { @@ -1261,11 +1260,12 @@ define([ }, 200); return; } + + // If the owner was not is the pad metadata, check if it is a friend var fData = channel.data || {}; - if (fData.owners) { + if (!owner && fData.owners) { var friends = store.proxy.friends || {}; if (Object.keys(friends).length > 1) { - var owner; fData.owners.some(function (edPublic) { return Object.keys(friends).some(function (curve) { if (curve === "me") { return; } @@ -1276,26 +1276,28 @@ define([ } }); }); - if (owner) { - if (data.send) { - var myData = Messaging.createData(store.proxy); - delete myData.channel; - store.mailbox.sendTo('REQUEST_PAD_ACCESS', { - channel: data.channel, - user: myData - }, { - channel: owner.notifications, - curvePublic: owner.curvePublic - }, function () { - cb({state: true}); - }); - return; - } - return void cb({state: true}); - } } } - cb({sent: false}); + + // If send is true, send the request to the owner. + if (owner) { + if (data.send) { + var myData = Messaging.createData(store.proxy); + delete myData.channel; + store.mailbox.sendTo('REQUEST_PAD_ACCESS', { + channel: data.channel, + user: myData + }, { + channel: owner.notifications, + curvePublic: owner.curvePublic + }, function () { + cb({state: true}); + }); + return; + } + return void cb({state: true}); + } + cb({state: false}); }; Store.givePadAccess = function (clientId, data, cb) { var edPublic = store.proxy.edPublic; @@ -1332,6 +1334,28 @@ define([ cb(); }; + Store.getPadMetadata = function (clientId, data, cb) { + if (!data.channel) { return void cb({ error: 'ENOTFOUND'}); } + var channel = channels[data.channel]; + if (!channel) { return void cb({ error: 'ENOTFOUND' }); } + if (!channel.data || !channel.data.channel) { + var i = 0; + var it = setInterval(function () { + if (channel.data && channel.data.channel) { + clearInterval(it); + Store.getPadMetadata(clientId, data, cb); + return; + } + if (i >= 300) { // One minute timeout + clearInterval(it); + } + i++; + }, 200); + return; + } + cb(channel.data || {}); + }; + // GET_FULL_HISTORY from sframe-common-outer Store.getFullHistory = function (clientId, data, cb) { var network = store.network; diff --git a/www/common/outer/store-rpc.js b/www/common/outer/store-rpc.js index bb8e0a674..18096d96d 100644 --- a/www/common/outer/store-rpc.js +++ b/www/common/outer/store-rpc.js @@ -80,6 +80,7 @@ define([ IS_NEW_CHANNEL: Store.isNewChannel, REQUEST_PAD_ACCESS: Store.requestPadAccess, GIVE_PAD_ACCESS: Store.givePadAccess, + GET_PAD_METADATA: Store.getPadMetadata, // Drive DRIVE_USEROBJECT: Store.userObjectCommand, // Settings, diff --git a/www/common/sframe-common-outer.js b/www/common/sframe-common-outer.js index 72ebec240..eff90150c 100644 --- a/www/common/sframe-common-outer.js +++ b/www/common/sframe-common-outer.js @@ -272,7 +272,7 @@ define([ var parsed = Utils.Hash.parsePadUrl(window.location.href); if (!parsed.type) { throw new Error(); } var defaultTitle = Utils.Hash.getDefaultName(parsed); - var edPublic; + var edPublic, curvePublic, notifications; var forceCreationScreen = cfg.useCreationScreen && sessionStorage[Utils.Constants.displayPadCreationScreen]; delete sessionStorage[Utils.Constants.displayPadCreationScreen]; @@ -284,6 +284,8 @@ define([ if (err) { console.log(err); } metaObj = m; edPublic = metaObj.priv.edPublic; // needed to create an owned pad + curvePublic = metaObj.user.curvePublic; + notifications = metaObj.user.notifications; })); Cryptpad.isTemplate(window.location.href, waitFor(function (err, t) { if (err) { console.log(err); } @@ -948,10 +950,33 @@ define([ if (readOnly && hashes.editHash) { return void cb({error: 'ALREADYKNOWN'}); } - Cryptpad.padRpc.requestAccess({ - send: data, - channel: secret.channel - }, cb); + var owner; + var crypto = Crypto.createEncryptor(secret.keys); + nThen(function (waitFor) { + // 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 + // or an acquaintance (from async-store directly in requestAccess) + Cryptpad.getPadMetadata({ + channel: secret.channel + }, waitFor(function (obj) { + obj = obj || {}; + if (obj.error) { return; } + if (obj.mailbox) { + try { + var dataStr = crypto.decrypt(obj.mailbox, true, true); + var data = JSON.parse(dataStr); + if (!data.notifications || !data.curvePublic) { return; } + owner = data; + } catch (e) { console.error(e); } + } + })); + }).nThen(function () { + Cryptpad.padRpc.requestAccess({ + send: data, + channel: secret.channel, + owner: owner + }, cb); + }); }); if (cfg.messaging) { @@ -1079,6 +1104,10 @@ define([ }; if (data.owned) { rtConfig.metadata.owners = [edPublic]; + rtConfig.metadata.mailbox = Utils.crypto.encrypt(JSON.stringify({ + notifications: notifications, + curvePublic: curvePublic + })); } if (data.expire) { rtConfig.metadata.expire = data.expire; diff --git a/www/common/toolbar3.js b/www/common/toolbar3.js index 6c262e2d1..a2547d223 100644 --- a/www/common/toolbar3.js +++ b/www/common/toolbar3.js @@ -575,7 +575,6 @@ MessengerUI, Messages) { }; var createRequest = function (toolbar, config) { - console.error('test'); if (!config.metadataMgr) { throw new Error("You must provide a `metadataMgr` to display the request access button"); }