|
|
|
@ -26,13 +26,14 @@ define([
|
|
|
|
|
'/bower_components/chainpad/chainpad.dist.js',
|
|
|
|
|
'/bower_components/chainpad-netflux/chainpad-netflux.js',
|
|
|
|
|
'/bower_components/chainpad-listmap/chainpad-listmap.js',
|
|
|
|
|
'/bower_components/netflux-websocket/netflux-client.js',
|
|
|
|
|
'/bower_components/nthen/index.js',
|
|
|
|
|
'/bower_components/saferphore/index.js',
|
|
|
|
|
], function (Sortify, UserObject, ProxyManager, Migrate, Hash, Util, Constants, Feedback,
|
|
|
|
|
Realtime, Messaging, Pinpad, Cache,
|
|
|
|
|
SF, Cursor, OnlyOffice, Mailbox, Profile, Team, Messenger, History,
|
|
|
|
|
NetConfig, AppConfig,
|
|
|
|
|
Crypto, ChainPad, CpNetflux, Listmap, nThen, Saferphore) {
|
|
|
|
|
Crypto, ChainPad, CpNetflux, Listmap, Netflux, nThen, Saferphore) {
|
|
|
|
|
|
|
|
|
|
var onReadyEvt = Util.mkEvent(true);
|
|
|
|
|
var onCacheReadyEvt = Util.mkEvent(true);
|
|
|
|
@ -547,6 +548,7 @@ define([
|
|
|
|
|
//////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
var getAllStores = Store.getAllStores = function () {
|
|
|
|
|
if (!store.proxy) { return []; }
|
|
|
|
|
var stores = [store];
|
|
|
|
|
var teamModule = store.modules['team'];
|
|
|
|
|
if (teamModule) {
|
|
|
|
@ -568,7 +570,7 @@ define([
|
|
|
|
|
getColor().toString(16);
|
|
|
|
|
};
|
|
|
|
|
var getUserColor = function () {
|
|
|
|
|
var color = Util.find(store.proxy, ['settings', 'general', 'cursor', 'color']);
|
|
|
|
|
var color = Util.find(store, ['proxy', 'settings', 'general', 'cursor', 'color']);
|
|
|
|
|
if (!color) {
|
|
|
|
|
color = getRandomColor();
|
|
|
|
|
Store.setAttribute(null, {
|
|
|
|
@ -581,33 +583,34 @@ define([
|
|
|
|
|
|
|
|
|
|
// Get the metadata for sframe-common-outer
|
|
|
|
|
Store.getMetadata = function (clientId, app, cb) {
|
|
|
|
|
var disableThumbnails = Util.find(store.proxy, ['settings', 'general', 'disableThumbnails']);
|
|
|
|
|
var proxy = store.proxy || {};
|
|
|
|
|
var disableThumbnails = Util.find(proxy, ['settings', 'general', 'disableThumbnails']);
|
|
|
|
|
var teams = (store.modules['team'] && store.modules['team'].getTeamsData(app)) || {};
|
|
|
|
|
var metadata = {
|
|
|
|
|
// "user" is shared with everybody via the userlist
|
|
|
|
|
user: {
|
|
|
|
|
name: store.proxy[Constants.displayNameKey] || "",
|
|
|
|
|
uid: store.proxy.uid,
|
|
|
|
|
avatar: Util.find(store.proxy, ['profile', 'avatar']),
|
|
|
|
|
profile: Util.find(store.proxy, ['profile', 'view']),
|
|
|
|
|
name: proxy[Constants.displayNameKey] || store.noDriveName || "",
|
|
|
|
|
uid: proxy.uid || Hash.createChannelId(), // Random uid in nodrive mode
|
|
|
|
|
avatar: Util.find(proxy, ['profile', 'avatar']),
|
|
|
|
|
profile: Util.find(proxy, ['profile', 'view']),
|
|
|
|
|
color: getUserColor(),
|
|
|
|
|
notifications: Util.find(store.proxy, ['mailboxes', 'notifications', 'channel']),
|
|
|
|
|
curvePublic: store.proxy.curvePublic,
|
|
|
|
|
notifications: Util.find(proxy, ['mailboxes', 'notifications', 'channel']),
|
|
|
|
|
curvePublic: proxy.curvePublic,
|
|
|
|
|
},
|
|
|
|
|
// "priv" is not shared with other users but is needed by the apps
|
|
|
|
|
priv: {
|
|
|
|
|
clientId: clientId,
|
|
|
|
|
edPublic: store.proxy.edPublic,
|
|
|
|
|
friends: store.proxy.friends || {},
|
|
|
|
|
settings: store.proxy.settings,
|
|
|
|
|
edPublic: proxy.edPublic,
|
|
|
|
|
friends: proxy.friends || {},
|
|
|
|
|
settings: proxy.settings || NEW_USER_SETTINGS,
|
|
|
|
|
thumbnails: disableThumbnails === false,
|
|
|
|
|
isDriveOwned: Boolean(Util.find(store, ['driveMetadata', 'owners'])),
|
|
|
|
|
support: Util.find(store.proxy, ['mailboxes', 'support', 'channel']),
|
|
|
|
|
support: Util.find(proxy, ['mailboxes', 'support', 'channel']),
|
|
|
|
|
driveChannel: store.driveChannel,
|
|
|
|
|
pendingFriends: store.proxy.friends_pending || {},
|
|
|
|
|
supportPrivateKey: Util.find(store.proxy, ['mailboxes', 'supportadmin', 'keys', 'curvePrivate']),
|
|
|
|
|
accountName: store.proxy.login_name || '',
|
|
|
|
|
offline: store.offline,
|
|
|
|
|
pendingFriends: proxy.friends_pending || {},
|
|
|
|
|
supportPrivateKey: Util.find(proxy, ['mailboxes', 'supportadmin', 'keys', 'curvePrivate']),
|
|
|
|
|
accountName: proxy.login_name || '',
|
|
|
|
|
offline: store.proxy && store.offline,
|
|
|
|
|
teams: teams,
|
|
|
|
|
plan: account.plan
|
|
|
|
|
}
|
|
|
|
@ -853,6 +856,10 @@ define([
|
|
|
|
|
|
|
|
|
|
// Set the display name (username) in the proxy
|
|
|
|
|
Store.setDisplayName = function (clientId, value, cb) {
|
|
|
|
|
if (!store.proxy) {
|
|
|
|
|
store.noDriveName = value;
|
|
|
|
|
return void cb();
|
|
|
|
|
}
|
|
|
|
|
if (store.modules['profile']) {
|
|
|
|
|
store.modules['profile'].setName(value);
|
|
|
|
|
}
|
|
|
|
@ -1444,6 +1451,8 @@ define([
|
|
|
|
|
};
|
|
|
|
|
// Teams support offline/cache mode
|
|
|
|
|
if (obj.type === "team") { return void todo(); }
|
|
|
|
|
// If we're in "noDrive" mode
|
|
|
|
|
if (!store.proxy) { return void todo(); }
|
|
|
|
|
// Other modules should wait for the ready event
|
|
|
|
|
onReadyEvt.reg(todo);
|
|
|
|
|
}
|
|
|
|
@ -1713,6 +1722,10 @@ define([
|
|
|
|
|
if (padData && padData.validateKey && store.messenger) {
|
|
|
|
|
store.messenger.storeValidateKey(data.channel, padData.validateKey);
|
|
|
|
|
}
|
|
|
|
|
if (!store.proxy) {
|
|
|
|
|
postMessage(clientId, "PAD_READY", pad.noCache);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
onReadyEvt.reg(function () {
|
|
|
|
|
postMessage(clientId, "PAD_READY", pad.noCache);
|
|
|
|
|
});
|
|
|
|
@ -1768,6 +1781,7 @@ define([
|
|
|
|
|
channel: data.channel,
|
|
|
|
|
metadata: data.metadata,
|
|
|
|
|
network: store.network || store.networkPromise,
|
|
|
|
|
websocketURL: NetConfig.getWebsocketURL(),
|
|
|
|
|
//readOnly: data.readOnly,
|
|
|
|
|
onConnect: function (wc, sendMessage) {
|
|
|
|
|
channel.sendMessage = function (msg, cId, cb) {
|
|
|
|
@ -2759,6 +2773,7 @@ define([
|
|
|
|
|
var listmapConfig = {
|
|
|
|
|
data: {},
|
|
|
|
|
websocketURL: NetConfig.getWebsocketURL(),
|
|
|
|
|
network: store.network,
|
|
|
|
|
channel: secret.channel,
|
|
|
|
|
readOnly: false,
|
|
|
|
|
validateKey: secret.keys.validateKey || undefined,
|
|
|
|
@ -2914,6 +2929,50 @@ define([
|
|
|
|
|
*/
|
|
|
|
|
var initialized = false;
|
|
|
|
|
|
|
|
|
|
// If we load CryptPad for the first time from an existing pad, don't create a
|
|
|
|
|
// drive automatically.
|
|
|
|
|
var onNoDrive = function (clientId, cb) {
|
|
|
|
|
var andThen = function () {
|
|
|
|
|
// To be able to use all the features inside the pad, we need to
|
|
|
|
|
// initialize the chat (messenger) and the cursor modules.
|
|
|
|
|
loadUniversal(Cursor, 'cursor', function () {});
|
|
|
|
|
loadUniversal(Messenger, 'messenger', function () {});
|
|
|
|
|
store.messenger = store.modules['messenger'];
|
|
|
|
|
|
|
|
|
|
// And now we're ready
|
|
|
|
|
initAnonRpc(null, null, function () {
|
|
|
|
|
cb({});
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// We need an anonymous RPC to be able to check if the pad exists and to get
|
|
|
|
|
// its metadata, so we have to create a network first.
|
|
|
|
|
if (!store.network) {
|
|
|
|
|
var wsUrl = NetConfig.getWebsocketURL();
|
|
|
|
|
return void Netflux.connect(wsUrl).then(function (network) {
|
|
|
|
|
store.network = network;
|
|
|
|
|
// We need to know the HistoryKeeper ID to initialize the anon RPC
|
|
|
|
|
// Join a basic ephemeral channel, get the ID and leave it instantly
|
|
|
|
|
network.join('0000000000000000000000000000000000').then(function (wc) {
|
|
|
|
|
var hk;
|
|
|
|
|
wc.members.forEach(function (p) { if (p.length === 16) { hk = p; } });
|
|
|
|
|
network.historyKeeper = hk;
|
|
|
|
|
wc.leave();
|
|
|
|
|
|
|
|
|
|
andThen();
|
|
|
|
|
}, function (err) {
|
|
|
|
|
console.error(err);
|
|
|
|
|
cb({error: 'GET_HK'});
|
|
|
|
|
});
|
|
|
|
|
}, function (err) {
|
|
|
|
|
console.error(err);
|
|
|
|
|
cb({error: 'OFFLINE'});
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
andThen();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Store.init = function (clientId, data, _callback) {
|
|
|
|
|
var callback = Util.once(_callback);
|
|
|
|
|
|
|
|
|
@ -2948,13 +3007,32 @@ define([
|
|
|
|
|
Cache.disable();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (data.query && data.broadcast) {
|
|
|
|
|
postMessage = function (clientId, cmd, d, cb) {
|
|
|
|
|
data.query(clientId, cmd, d, cb);
|
|
|
|
|
};
|
|
|
|
|
broadcast = function (excludes, cmd, d, cb) {
|
|
|
|
|
data.broadcast(excludes, cmd, d, cb);
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// First tab, no user hash, no anon hash and this app doesn't need a drive
|
|
|
|
|
// ==> don't create a drive
|
|
|
|
|
if (data.noDrive && !data.userHash && !data.anonHash) {
|
|
|
|
|
return void onNoDrive(clientId, function (obj) {
|
|
|
|
|
if (obj && obj.error) {
|
|
|
|
|
// if we can't properly initialize the noDrive mode, use normal mode
|
|
|
|
|
if (obj.error === 'GET_HK') {
|
|
|
|
|
data.noDrive = false;
|
|
|
|
|
Store.init(clientId, data, _callback);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
callback(obj);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
initialized = true;
|
|
|
|
|
postMessage = function (clientId, cmd, d, cb) {
|
|
|
|
|
data.query(clientId, cmd, d, cb);
|
|
|
|
|
};
|
|
|
|
|
broadcast = function (excludes, cmd, d, cb) {
|
|
|
|
|
data.broadcast(excludes, cmd, d, cb);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
store.data = data;
|
|
|
|
|
connect(clientId, data, function (ret) {
|
|
|
|
|