Merge branch 'unifiedMetadata' into staging
This commit is contained in:
commit
c1656d7b5b
@ -396,32 +396,35 @@ module.exports.create = function (cfg) {
|
|||||||
// parsed[3] is the last known hash (optionnal)
|
// parsed[3] is the last known hash (optionnal)
|
||||||
sendMsg(ctx, user, [seq, 'ACK']);
|
sendMsg(ctx, user, [seq, 'ACK']);
|
||||||
channelName = parsed[1];
|
channelName = parsed[1];
|
||||||
var validateKey = parsed[2];
|
var config = parsed[2];
|
||||||
var lastKnownHash = parsed[3];
|
var metadata = {};
|
||||||
var owners;
|
var lastKnownHash;
|
||||||
var expire;
|
if (config && typeof config === "object") {
|
||||||
if (parsed[2] && typeof parsed[2] === "object") {
|
lastKnownHash = config.lastKnownHash;
|
||||||
validateKey = parsed[2].validateKey;
|
metadata = config.metadata || {};
|
||||||
lastKnownHash = parsed[2].lastKnownHash;
|
if (metadata.expire) {
|
||||||
owners = parsed[2].owners;
|
metadata.expire = +metadata.expire * 1000 + (+new Date());
|
||||||
if (parsed[2].expire) {
|
|
||||||
expire = +parsed[2].expire * 1000 + (+new Date());
|
|
||||||
}
|
}
|
||||||
|
} else if (config) {
|
||||||
|
// This is the old way: parsed[2] is the validateKey and parsed[3] is the last known hash
|
||||||
|
lastKnownHash = parsed[3];
|
||||||
|
metadata.validateKey = parsed[2];
|
||||||
}
|
}
|
||||||
|
metadata.channel = channelName;
|
||||||
|
|
||||||
nThen(function (waitFor) {
|
nThen(function (waitFor) {
|
||||||
if (!tasks) { return; } // tasks are not supported
|
if (!tasks) { return; } // tasks are not supported
|
||||||
if (typeof(expire) !== 'number' || !expire) { return; }
|
if (typeof(metadata.expire) !== 'number' || !metadata.expire) { return; }
|
||||||
|
|
||||||
// the fun part...
|
// the fun part...
|
||||||
// the user has said they want this pad to expire at some point
|
// the user has said they want this pad to expire at some point
|
||||||
tasks.write(expire, "EXPIRE", [ channelName ], waitFor(function (err) {
|
tasks.write(metadata.expire, "EXPIRE", [ channelName ], waitFor(function (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
// if there is an error, we don't want to crash the whole server...
|
// if there is an error, we don't want to crash the whole server...
|
||||||
// just log it, and if there's a problem you'll be able to fix it
|
// just log it, and if there's a problem you'll be able to fix it
|
||||||
// at a later date with the provided information
|
// at a later date with the provided information
|
||||||
Log.error('HK_CREATE_EXPIRE_TASK', err);
|
Log.error('HK_CREATE_EXPIRE_TASK', err);
|
||||||
Log.info('HK_INVALID_EXPIRE_TASK', JSON.stringify([expire, 'EXPIRE', channelName]));
|
Log.info('HK_INVALID_EXPIRE_TASK', JSON.stringify([metadata.expire, 'EXPIRE', channelName]));
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
}).nThen(function (waitFor) {
|
}).nThen(function (waitFor) {
|
||||||
@ -482,20 +485,9 @@ module.exports.create = function (cfg) {
|
|||||||
// the first message in the file
|
// the first message in the file
|
||||||
const chan = ctx.channels[channelName];
|
const chan = ctx.channels[channelName];
|
||||||
if (msgCount === 0 && !historyKeeperKeys[channelName] && chan && chan.indexOf(user) > -1) {
|
if (msgCount === 0 && !historyKeeperKeys[channelName] && chan && chan.indexOf(user) > -1) {
|
||||||
var key = {};
|
historyKeeperKeys[channelName] = metadata;
|
||||||
key.channel = channelName;
|
storeMessage(ctx, chan, JSON.stringify(metadata), false, undefined);
|
||||||
if (validateKey) {
|
sendMsg(ctx, user, [0, HISTORY_KEEPER_ID, 'MSG', user.id, JSON.stringify(metadata)]);
|
||||||
key.validateKey = validateKey;
|
|
||||||
}
|
|
||||||
if (owners) {
|
|
||||||
key.owners = owners;
|
|
||||||
}
|
|
||||||
if (expire) {
|
|
||||||
key.expire = expire;
|
|
||||||
}
|
|
||||||
historyKeeperKeys[channelName] = key;
|
|
||||||
storeMessage(ctx, chan, JSON.stringify(key), false, undefined);
|
|
||||||
sendMsg(ctx, user, [0, HISTORY_KEEPER_ID, 'MSG', user.id, JSON.stringify(key)]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// End of history message:
|
// End of history message:
|
||||||
|
|||||||
@ -422,8 +422,10 @@ define([
|
|||||||
|
|
||||||
var friend = getFriendFromChannel(chan.id) || {};
|
var friend = getFriendFromChannel(chan.id) || {};
|
||||||
var cfg = {
|
var cfg = {
|
||||||
validateKey: keys ? keys.validateKey : undefined,
|
metadata: {
|
||||||
owners: [proxy.edPublic, friend.edPublic],
|
validateKey: keys ? keys.validateKey : undefined,
|
||||||
|
owners: [proxy.edPublic, friend.edPublic],
|
||||||
|
},
|
||||||
lastKnownHash: data.lastKnownHash
|
lastKnownHash: data.lastKnownHash
|
||||||
};
|
};
|
||||||
var msg = ['GET_HISTORY', chan.id, cfg];
|
var msg = ['GET_HISTORY', chan.id, cfg];
|
||||||
|
|||||||
@ -764,6 +764,10 @@ define([
|
|||||||
postMessage("GIVE_PAD_ACCESS", data, cb);
|
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) {
|
common.changePadPassword = function (Crypt, 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);
|
||||||
|
|||||||
@ -1209,10 +1209,7 @@ define([
|
|||||||
},
|
},
|
||||||
noChainPad: true,
|
noChainPad: true,
|
||||||
channel: data.channel,
|
channel: data.channel,
|
||||||
validateKey: data.validateKey,
|
metadata: data.metadata,
|
||||||
owners: data.owners,
|
|
||||||
password: data.password,
|
|
||||||
expire: data.expire,
|
|
||||||
network: store.network,
|
network: store.network,
|
||||||
//readOnly: data.readOnly,
|
//readOnly: data.readOnly,
|
||||||
onConnect: function (wc, sendMessage) {
|
onConnect: function (wc, sendMessage) {
|
||||||
@ -1262,11 +1259,14 @@ define([
|
|||||||
channel.sendMessage(msg, clientId, cb);
|
channel.sendMessage(msg, clientId, cb);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// requestPadAccess is used to check if we have a way to contact the owner
|
||||||
|
// of the pad AND to send the request if we want
|
||||||
|
// data.send === false ==> check if we can contact them
|
||||||
|
// data.send === true ==> send the request
|
||||||
Store.requestPadAccess = function (clientId, data, cb) {
|
Store.requestPadAccess = function (clientId, data, cb) {
|
||||||
// Get owners from pad metadata
|
var owner = data.owner;
|
||||||
// Try to find an owner in our friend list
|
|
||||||
// Mailbox...
|
|
||||||
var channel = channels[data.channel];
|
var channel = channels[data.channel];
|
||||||
|
if (!channel) { return void cb({error: 'ENOTFOUND'}); }
|
||||||
if (!data.send && channel && (!channel.data || !channel.data.channel)) {
|
if (!data.send && channel && (!channel.data || !channel.data.channel)) {
|
||||||
var i = 0;
|
var i = 0;
|
||||||
var it = setInterval(function () {
|
var it = setInterval(function () {
|
||||||
@ -1277,16 +1277,19 @@ define([
|
|||||||
}
|
}
|
||||||
if (i >= 300) { // One minute timeout
|
if (i >= 300) { // One minute timeout
|
||||||
clearInterval(it);
|
clearInterval(it);
|
||||||
|
return void cb({error: 'ETIMEOUT'});
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
}, 200);
|
}, 200);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
var fData = channel.data || {};
|
var fData = channel.data || {};
|
||||||
if (fData.owners) {
|
if (!owner && fData.owners) {
|
||||||
var friends = store.proxy.friends || {};
|
var friends = store.proxy.friends || {};
|
||||||
if (Object.keys(friends).length > 1) {
|
if (Object.keys(friends).length > 1) {
|
||||||
var owner;
|
|
||||||
fData.owners.some(function (edPublic) {
|
fData.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; }
|
||||||
@ -1297,26 +1300,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) {
|
Store.givePadAccess = function (clientId, data, cb) {
|
||||||
var edPublic = store.proxy.edPublic;
|
var edPublic = store.proxy.edPublic;
|
||||||
@ -1353,6 +1358,29 @@ define([
|
|||||||
cb();
|
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);
|
||||||
|
return void cb({error: 'ETIMEOUT'});
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}, 200);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cb(channel.data || {});
|
||||||
|
};
|
||||||
|
|
||||||
// GET_FULL_HISTORY from sframe-common-outer
|
// GET_FULL_HISTORY from sframe-common-outer
|
||||||
Store.getFullHistory = function (clientId, data, cb) {
|
Store.getFullHistory = function (clientId, data, cb) {
|
||||||
var network = store.network;
|
var network = store.network;
|
||||||
@ -1459,14 +1487,16 @@ define([
|
|||||||
websocketURL: NetConfig.getWebsocketURL(),
|
websocketURL: NetConfig.getWebsocketURL(),
|
||||||
channel: secret.channel,
|
channel: secret.channel,
|
||||||
readOnly: false,
|
readOnly: false,
|
||||||
validateKey: secret.keys.validateKey || undefined,
|
|
||||||
crypto: Crypto.createEncryptor(secret.keys),
|
crypto: Crypto.createEncryptor(secret.keys),
|
||||||
userName: 'sharedFolder',
|
userName: 'sharedFolder',
|
||||||
logLevel: 1,
|
logLevel: 1,
|
||||||
ChainPad: ChainPad,
|
ChainPad: ChainPad,
|
||||||
classic: true,
|
classic: true,
|
||||||
network: store.network,
|
network: store.network,
|
||||||
owners: owners
|
metadata: {
|
||||||
|
validateKey: secret.keys.validateKey || undefined,
|
||||||
|
owners: owners
|
||||||
|
}
|
||||||
};
|
};
|
||||||
var rt = Listmap.create(listmapConfig);
|
var rt = Listmap.create(listmapConfig);
|
||||||
store.sharedFolders[id] = rt;
|
store.sharedFolders[id] = rt;
|
||||||
|
|||||||
@ -92,9 +92,11 @@ define([
|
|||||||
var hk = network.historyKeeper;
|
var hk = network.historyKeeper;
|
||||||
var cfg = {
|
var cfg = {
|
||||||
validateKey: obj.validateKey,
|
validateKey: obj.validateKey,
|
||||||
lastKnownHash: chan.lastKnownHash || chan.lastCpHash,
|
metadata: {
|
||||||
owners: obj.owners,
|
lastKnownHash: chan.lastKnownHash || chan.lastCpHash,
|
||||||
expire: obj.expire
|
owners: obj.owners,
|
||||||
|
expire: obj.expire
|
||||||
|
}
|
||||||
};
|
};
|
||||||
var msg = ['GET_HISTORY', wc.id, cfg];
|
var msg = ['GET_HISTORY', wc.id, cfg];
|
||||||
// Add the validateKey if we are the channel creator and we have a validateKey
|
// Add the validateKey if we are the channel creator and we have a validateKey
|
||||||
|
|||||||
@ -80,6 +80,7 @@ define([
|
|||||||
IS_NEW_CHANNEL: Store.isNewChannel,
|
IS_NEW_CHANNEL: Store.isNewChannel,
|
||||||
REQUEST_PAD_ACCESS: Store.requestPadAccess,
|
REQUEST_PAD_ACCESS: Store.requestPadAccess,
|
||||||
GIVE_PAD_ACCESS: Store.givePadAccess,
|
GIVE_PAD_ACCESS: Store.givePadAccess,
|
||||||
|
GET_PAD_METADATA: Store.getPadMetadata,
|
||||||
// Drive
|
// Drive
|
||||||
DRIVE_USEROBJECT: Store.userObjectCommand,
|
DRIVE_USEROBJECT: Store.userObjectCommand,
|
||||||
// Settings,
|
// Settings,
|
||||||
|
|||||||
@ -23,14 +23,12 @@ define([], function () {
|
|||||||
var start = function (conf) {
|
var start = function (conf) {
|
||||||
var channel = conf.channel;
|
var channel = conf.channel;
|
||||||
var Crypto = conf.crypto;
|
var Crypto = conf.crypto;
|
||||||
var validateKey = conf.validateKey;
|
|
||||||
var isNewHash = conf.isNewHash;
|
var isNewHash = conf.isNewHash;
|
||||||
var readOnly = conf.readOnly || false;
|
var readOnly = conf.readOnly || false;
|
||||||
var padRpc = conf.padRpc;
|
var padRpc = conf.padRpc;
|
||||||
var sframeChan = conf.sframeChan;
|
var sframeChan = conf.sframeChan;
|
||||||
var password = conf.password;
|
var metadata= conf.metadata || {};
|
||||||
var owners = conf.owners;
|
var validateKey = metadata.validateKey;
|
||||||
var expire = conf.expire;
|
|
||||||
var onConnect = conf.onConnect || function () { };
|
var onConnect = conf.onConnect || function () { };
|
||||||
conf = undefined;
|
conf = undefined;
|
||||||
|
|
||||||
@ -127,11 +125,8 @@ define([], function () {
|
|||||||
// join the netflux network, promise to handle opening of the channel
|
// join the netflux network, promise to handle opening of the channel
|
||||||
padRpc.joinPad({
|
padRpc.joinPad({
|
||||||
channel: channel || null,
|
channel: channel || null,
|
||||||
validateKey: validateKey,
|
|
||||||
readOnly: readOnly,
|
readOnly: readOnly,
|
||||||
owners: owners,
|
metadata: metadata
|
||||||
password: password,
|
|
||||||
expire: expire
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -272,7 +272,7 @@ define([
|
|||||||
var parsed = Utils.Hash.parsePadUrl(window.location.href);
|
var parsed = Utils.Hash.parsePadUrl(window.location.href);
|
||||||
if (!parsed.type) { throw new Error(); }
|
if (!parsed.type) { throw new Error(); }
|
||||||
var defaultTitle = Utils.Hash.getDefaultName(parsed);
|
var defaultTitle = Utils.Hash.getDefaultName(parsed);
|
||||||
var edPublic, isTemplate;
|
var edPublic, curvePublic, notifications, isTemplate;
|
||||||
var forceCreationScreen = cfg.useCreationScreen &&
|
var forceCreationScreen = cfg.useCreationScreen &&
|
||||||
sessionStorage[Utils.Constants.displayPadCreationScreen];
|
sessionStorage[Utils.Constants.displayPadCreationScreen];
|
||||||
delete sessionStorage[Utils.Constants.displayPadCreationScreen];
|
delete sessionStorage[Utils.Constants.displayPadCreationScreen];
|
||||||
@ -284,6 +284,8 @@ define([
|
|||||||
if (err) { console.log(err); }
|
if (err) { console.log(err); }
|
||||||
metaObj = m;
|
metaObj = m;
|
||||||
edPublic = metaObj.priv.edPublic; // needed to create an owned pad
|
edPublic = metaObj.priv.edPublic; // needed to create an owned pad
|
||||||
|
curvePublic = metaObj.user.curvePublic;
|
||||||
|
notifications = metaObj.user.notifications;
|
||||||
}));
|
}));
|
||||||
if (typeof(isTemplate) === "undefined") {
|
if (typeof(isTemplate) === "undefined") {
|
||||||
Cryptpad.isTemplate(window.location.href, waitFor(function (err, t) {
|
Cryptpad.isTemplate(window.location.href, waitFor(function (err, t) {
|
||||||
@ -973,10 +975,33 @@ define([
|
|||||||
if (readOnly && hashes.editHash) {
|
if (readOnly && hashes.editHash) {
|
||||||
return void cb({error: 'ALREADYKNOWN'});
|
return void cb({error: 'ALREADYKNOWN'});
|
||||||
}
|
}
|
||||||
Cryptpad.padRpc.requestAccess({
|
var owner;
|
||||||
send: data,
|
var crypto = Crypto.createEncryptor(secret.keys);
|
||||||
channel: secret.channel
|
nThen(function (waitFor) {
|
||||||
}, cb);
|
// 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) {
|
if (cfg.messaging) {
|
||||||
@ -1099,13 +1124,21 @@ define([
|
|||||||
readOnly = false;
|
readOnly = false;
|
||||||
updateMeta();
|
updateMeta();
|
||||||
|
|
||||||
var rtConfig = {};
|
var rtConfig = {
|
||||||
|
metadata: {}
|
||||||
|
};
|
||||||
if (data.owned) {
|
if (data.owned) {
|
||||||
rtConfig.owners = [edPublic];
|
rtConfig.metadata.owners = [edPublic];
|
||||||
|
rtConfig.metadata.mailbox = Utils.crypto.encrypt(JSON.stringify({
|
||||||
|
notifications: notifications,
|
||||||
|
curvePublic: curvePublic
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
if (data.expire) {
|
if (data.expire) {
|
||||||
rtConfig.expire = data.expire;
|
rtConfig.metadata.expire = data.expire;
|
||||||
}
|
}
|
||||||
|
rtConfig.metadata.validateKey = (secret.keys && secret.keys.validateKey) || undefined;
|
||||||
|
|
||||||
Utils.rtConfig = rtConfig;
|
Utils.rtConfig = rtConfig;
|
||||||
nThen(function(waitFor) {
|
nThen(function(waitFor) {
|
||||||
if (data.templateId) {
|
if (data.templateId) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user