Add team mailbox with the SHARE_PAD example

pull/1/head
yflory 5 years ago
parent d587a23418
commit cb36a49908

@ -272,25 +272,30 @@ define([
var $friends = $div.find('.cp-usergrid-user.cp-selected'); var $friends = $div.find('.cp-usergrid-user.cp-selected');
$friends.each(function (i, el) { $friends.each(function (i, el) {
var curve = $(el).attr('data-curve'); var curve = $(el).attr('data-curve');
// Check if the selected element is a friend or a team
if (curve) { // Friend
if (!curve || !friends[curve]) { return; }
var friend = friends[curve];
if (!friend.notifications || !friend.curvePublic) { return; }
common.mailbox.sendTo("SHARE_PAD", {
href: href,
password: config.password,
isTemplate: config.isTemplate,
name: myName,
title: title
}, {
channel: friend.notifications,
curvePublic: friend.curvePublic
});
return;
}
// Team
var ed = $(el).attr('data-ed'); var ed = $(el).attr('data-ed');
var friend = curve && friends[curve];
var team = teams[ed];
// If the selected element is a friend or a team without edit right,
// send a notification
var mailbox = friend || ((team && team.viewer) ? team : undefined);
if (mailbox) { // Friend
if (friends[curve] && !mailbox.notifications) { return; }
if (mailbox.notifications && mailbox.curvePublic) {
// XXX we should mark this notification as "viewed" in our own proxy
common.mailbox.sendTo("SHARE_PAD", {
href: href,
password: config.password,
isTemplate: config.isTemplate,
name: myName,
title: title
}, {
channel: mailbox.notifications,
curvePublic: mailbox.curvePublic
});
return;
}
}
// If it's a team with edit right, add the pad directly
var team = teams[ed]; var team = teams[ed];
if (!team) { return; } if (!team) { return; }
sframeChan.query('Q_STORE_IN_TEAM', { sframeChan.query('Q_STORE_IN_TEAM', {
@ -409,10 +414,11 @@ define([
// config.teamId only exists when we're trying to share a pad from a team drive // config.teamId only exists when we're trying to share a pad from a team drive
// In this case, we don't want to share the pad with the current team // In this case, we don't want to share the pad with the current team
if (config.teamId && config.teamId === id) { return; } if (config.teamId && config.teamId === id) { return; }
if (!teamsData[id].hasSecondaryKey) { return; }
var t = teamsData[id]; var t = teamsData[id];
teams[t.edPublic] = { teams[t.edPublic] = {
notifications: true, viewer: !teamsData[id].hasSecondaryKey,
notifications: t.notifications,
curvePublic: t.curvePublic,
displayName: t.name, displayName: t.name,
edPublic: t.edPublic, edPublic: t.edPublic,
avatar: t.avatar, avatar: t.avatar,

@ -84,6 +84,10 @@ define([
// Share pad // Share pad
Messages.notification_padSharedTeam = "{0} has shared a pad with the team {2}: <b>{1}</b>"; // XXX
Messages.notification_fileSharedTeam = "{0} has shared a file with the team {2}: <b>{1}</b>"; // XXX
Messages.notification_folderSharedTeam = "{0} has shared a pad with the team {2}: <b>{1}</b>"; // XXX
handlers['SHARE_PAD'] = function(common, data) { handlers['SHARE_PAD'] = function(common, data) {
var content = data.content; var content = data.content;
var msg = content.msg; var msg = content.msg;
@ -91,10 +95,22 @@ define([
var key = type === 'drive' ? 'notification_folderShared' : var key = type === 'drive' ? 'notification_folderShared' :
(type === 'file' ? 'notification_fileShared' : (type === 'file' ? 'notification_fileShared' :
'notification_padShared'); 'notification_padShared');
var teamNotification = /^team-/.test(data.type) && Number(data.type.slice(5));
var teamName = '';
if (teamNotification) {
var privateData = common.getMetadataMgr().getPrivateData();
var teamsData = Util.tryParse(JSON.stringify(privateData.teams)) || {};
var team = teamsData[teamNotification];
if (!team || !team.name) { return; }
key += "Team";
teamName = Util.fixHTML(team.name);
}
var name = Util.fixHTML(msg.content.name) || Messages.anonymous; var name = Util.fixHTML(msg.content.name) || Messages.anonymous;
var title = Util.fixHTML(msg.content.title); var title = Util.fixHTML(msg.content.title);
content.getFormatText = function() { content.getFormatText = function() {
return Messages._getKey(key, [name, title]); return Messages._getKey(key, [name, title, teamName]);
}; };
content.handler = function() { content.handler = function() {
var todo = function() { var todo = function() {
@ -105,6 +121,9 @@ define([
if (msg.content.isTemplate) { if (msg.content.isTemplate) {
common.sessionStorage.put(Constants.newPadPathKey, ['template'], waitFor()); common.sessionStorage.put(Constants.newPadPathKey, ['template'], waitFor());
} }
if (teamNotification) {
common.sessionStorage.put(Constants.newPadTeamKey, teamNotification, waitFor());
}
common.sessionStorage.put('newPadPassword', msg.content.password || '', waitFor()); common.sessionStorage.put('newPadPassword', msg.content.password || '', waitFor());
}).nThen(function() { }).nThen(function() {
todo(); todo();

@ -467,6 +467,15 @@ proxy.mailboxes = {
} }
}); });
Object.keys(store.proxy.teams || {}).forEach(function (teamId) {
var team = store.proxy.teams[teamId];
var teamMailbox = team.keys.mailbox || {};
if (!teamMailbox.channel) { return; }
openChannel(ctx, 'team-'+teamId, teamMailbox, function () {
//console.log('Mailbox team', teamId);
});
});
mailbox.post = function (box, type, content) { mailbox.post = function (box, type, content) {
var b = ctx.boxes[box]; var b = ctx.boxes[box];
if (!b) { return; } if (!b) { return; }
@ -477,8 +486,8 @@ proxy.mailboxes = {
}); });
}; };
mailbox.open = function (key, m, cb) { mailbox.open = function (key, m, cb, team) {
if (TYPES.indexOf(key) === -1) { return; } if (TYPES.indexOf(key) === -1 && !team) { return; }
openChannel(ctx, key, m, cb); openChannel(ctx, key, m, cb);
}; };

@ -494,6 +494,9 @@ define([
var roHash = Hash.getViewHashFromKeys(secret); var roHash = Hash.getViewHashFromKeys(secret);
var keyPair = Nacl.sign.keyPair(); // keyPair.secretKey , keyPair.publicKey var keyPair = Nacl.sign.keyPair(); // keyPair.secretKey , keyPair.publicKey
var curveSeed = Nacl.randomBytes(32);
var curvePair = Nacl.box.keyPair.fromSecretKey(curveSeed);
var rosterSeed = Crypto.Team.createSeed(); var rosterSeed = Crypto.Team.createSeed();
var rosterKeys = Crypto.Team.deriveMemberKeys(rosterSeed, { var rosterKeys = Crypto.Team.deriveMemberKeys(rosterSeed, {
curvePublic: ctx.store.proxy.curvePublic, curvePublic: ctx.store.proxy.curvePublic,
@ -585,6 +588,14 @@ define([
proxy.on('ready', function () { proxy.on('ready', function () {
// Store keys in our drive // Store keys in our drive
var keys = { var keys = {
mailbox: {
channel: Hash.createChannelId(),
viewed: [],
keys: {
curvePrivate: Nacl.util.encodeBase64(curvePair.secretKey),
curvePublic: Nacl.util.encodeBase64(curvePair.publicKey)
}
},
drive: { drive: {
edPrivate: Nacl.util.encodeBase64(keyPair.secretKey), edPrivate: Nacl.util.encodeBase64(keyPair.secretKey),
edPublic: Nacl.util.encodeBase64(keyPair.publicKey) edPublic: Nacl.util.encodeBase64(keyPair.publicKey)
@ -1566,6 +1577,26 @@ define([
}); });
}; };
var deriveMailbox = function (team) {
if (!team) { return; }
if (team.keys && team.keys.mailbox) { return team.keys.mailbox; }
var channel = team.channel;
if (!channel) { return; }
// XXX maybe use something else than channel?
var hash = Nacl.hash(Nacl.util.decodeUTF8(channel));
var seed = hash.slice(0,32);
var channel = Util.uint8ArrayToHex(hash.slice(32,48));
var curvePair = Nacl.box.keyPair.fromSecretKey(seed);
return {
channel: channel,
viewed: [],
keys: {
curvePrivate: Nacl.util.encodeBase64(curvePair.secretKey),
curvePublic: Nacl.util.encodeBase64(curvePair.publicKey)
}
};
};
Team.init = function (cfg, waitFor, emit) { Team.init = function (cfg, waitFor, emit) {
var team = {}; var team = {};
var store = cfg.store; var store = cfg.store;
@ -1595,6 +1626,9 @@ define([
Object.keys(teams).forEach(function (id) { Object.keys(teams).forEach(function (id) {
ctx.onReadyHandlers[id] = []; ctx.onReadyHandlers[id] = [];
if (!Util.find(teams, id, 'keys', 'mailbox')) {
teams[id].keys.mailbox = deriveMailbox(teams[id]);
}
openChannel(ctx, teams[id], id, waitFor(function (err) { openChannel(ctx, teams[id], id, waitFor(function (err) {
if (err) { return void console.error(err); } if (err) { return void console.error(err); }
console.debug('Team '+id+' ready'); console.debug('Team '+id+' ready');
@ -1615,6 +1649,8 @@ define([
edPublic: Util.find(teams[id], ['keys', 'drive', 'edPublic']), edPublic: Util.find(teams[id], ['keys', 'drive', 'edPublic']),
avatar: Util.find(teams[id], ['metadata', 'avatar']), avatar: Util.find(teams[id], ['metadata', 'avatar']),
viewer: !Util.find(teams[id], ['keys', 'drive', 'edPrivate']), viewer: !Util.find(teams[id], ['keys', 'drive', 'edPrivate']),
notifications: Util.find(teams[id], ['keys', 'mailbox', 'channel']),
curvePublic: Util.find(teams[id], ['keys', 'mailbox', 'keys', 'curvePublic']),
}; };
if (safe && ctx.teams[id]) { if (safe && ctx.teams[id]) {

@ -105,11 +105,14 @@ define([
}); });
// Call the onMessage handlers // Call the onMessage handlers
var isNotification = function (type) {
return type === "notificatons" || /^team-/.test(type);
};
var pushMessage = function (data, handler) { var pushMessage = function (data, handler) {
var todo = function (f) { var todo = function (f) {
try { try {
var el; var el;
if (data.type === 'notifications') { if (isNotification(data.type)) {
Notifications.add(Common, data); Notifications.add(Common, data);
el = createElement(data); el = createElement(data);
} }
@ -129,7 +132,7 @@ define([
onViewedHandlers.forEach(function (f) { onViewedHandlers.forEach(function (f) {
try { try {
f(data); f(data);
if (data.type === 'notifications') { if (isNotification(data.type)) {
Notifications.remove(Common, data); Notifications.remove(Common, data);
} }
} catch (e) { } catch (e) {
@ -173,20 +176,23 @@ define([
execCommand('SUBSCRIBE', null, function () {}); execCommand('SUBSCRIBE', null, function () {});
subscribed = true; subscribed = true;
} }
var teams = types.indexOf('team') !== -1;
if (typeof(cfg.onViewed) === "function") { if (typeof(cfg.onViewed) === "function") {
onViewedHandlers.push(function (data) { onViewedHandlers.push(function (data) {
if (types.indexOf(data.type) === -1) { return; } var type = data.type;
if (types.indexOf(type) === -1 && !(teams && /^team-/.test(type))) { return; }
cfg.onViewed(data); cfg.onViewed(data);
}); });
} }
if (typeof(cfg.onMessage) === "function") { if (typeof(cfg.onMessage) === "function") {
onMessageHandlers.push(function (data, el) { onMessageHandlers.push(function (data, el) {
if (types.indexOf(data.type) === -1) { return; } var type = data.type;
if (types.indexOf(type) === -1 && !(teams && /^team-/.test(type))) { return; }
cfg.onMessage(data, el); cfg.onMessage(data, el);
}); });
} }
Object.keys(history).forEach(function (type) { Object.keys(history).forEach(function (type) {
if (types.indexOf(type) === -1) { return; } if (types.indexOf(type) === -1 && !(teams && /^team-/.test(type))) { return; }
history[type].forEach(function (data) { history[type].forEach(function (data) {
pushMessage({ pushMessage({
type: type, type: type,

@ -1025,7 +1025,7 @@ MessengerUI, Messages) {
$button.addClass('fa-bell'); $button.addClass('fa-bell');
}; };
Common.mailbox.subscribe(['notifications'], { Common.mailbox.subscribe(['notifications', 'team'], {
onMessage: function (data, el) { onMessage: function (data, el) {
if (el) { if (el) {
$(div).prepend(el); $(div).prepend(el);

Loading…
Cancel
Save