Team invitation

This commit is contained in:
yflory
2019-09-20 15:27:20 +02:00
parent 3a76e84286
commit e4e2c3a19d
8 changed files with 405 additions and 115 deletions

View File

@@ -1,7 +1,8 @@
define([
'/common/common-messaging.js',
'/common/common-hash.js',
], function (Messaging, Hash) {
'/common/common-util.js',
], function (Messaging, Hash, Util) {
var getRandomTimeout = function (ctx) {
var lag = ctx.store.realtime.getLag().lag || 0;
@@ -309,6 +310,72 @@ define([
cb(false);
};
var invitedTo = {};
handlers['INVITE_TO_TEAM'] = function (ctx, box, data, cb) {
var msg = data.msg;
var content = msg.content;
if (msg.author !== content.user.curvePublic) { return void cb(true); }
if (!content.team) {
console.log('Remove invalid notification');
return void cb(true);
}
if (invitedTo[content.team.channel]) { return void cb(true); }
var myTeams = Util.find(ctx, ['store', 'proxy', 'teams'])
var alreadyMember = Object.keys(myTeams).some(function (k) {
var team = myTeams[k];
return team.channel === content.team.channel;
});
if (alreadyMember) { return void cb(true); }
invitedTo[content.team.channel] = true;
cb(false);
};
removeHandlers['INVITE_TO_TEAM'] = function (ctx, box, data) {
var channel = Util.find(data, ['content', 'team', 'channel']);
delete invitedTo[channel];
};
handlers['INVITE_TO_TEAM_ANSWER'] = function (ctx, box, data, cb) {
var msg = data.msg;
var content = msg.content;
if (msg.author !== content.user.curvePublic) { return void cb(true); }
if (!content.teamChannel) {
console.log('Remove invalid notification');
return void cb(true);
}
var myTeams = Util.find(ctx, ['store', 'proxy', 'teams'])
var teamId;
var team;
Object.keys(myTeams).some(function (k) {
var _team = myTeams[k];
if (_team.channel === content.teamChannel) {
teamId = k;
team = _team;
return true;
}
});
if (!teamId) { return void cb(true); }
content.team = team;
if (!content.answer) {
// If they declined the invitation, remove them from the roster (as a pending member)
try {
var module = ctx.store.modules['team'];
module.removeFromTeam(teamId, msg.author);
} catch (e) { console.error(e); }
}
cb(false);
};
return {
add: function (ctx, box, data, cb) {
/**

View File

@@ -310,8 +310,8 @@ define([
// If you're allowed to edit the roster, try to update your data
if (!rosterData.edit) { return; }
var data = {};
var myData = Messaging.createData(ctx.store.proxy);
delete myData.channel;
var myData = Messaging.createData(ctx.store.proxy, false);
myData.pending = false;
data[ctx.store.proxy.curvePublic] = myData;
roster.describe(data, function (err) {
if (!err) { return; }
@@ -448,6 +448,19 @@ define([
});
};
var joinTeam = function (ctx, data, cId, cb) {
var team = data.team;
if (!team.hash || !team.channel || !team.password
|| !team.keys || !team.metadata) { return void cb({error: 'EINVAL'}); }
var id = Util.createRandomInteger();
ctx.store.proxy.teams[id] = team;
ctx.onReadyHandlers[id] = [];
openChannel(ctx, team, id, function (obj) {
if (!(obj && obj.error)) { console.debug('Team joined:' + id); }
cb(obj);
});
};
var getTeamRoster = function (ctx, data, cId, cb) {
var teamId = data.teamId;
if (!teamId) { return void cb({error: 'EINVAL'}); }
@@ -499,6 +512,43 @@ define([
});
};
// TODO send guest keys only in the future
var getInviteData = function (ctx, teamId) {
var teamData = Util.find(ctx, ['store', 'proxy', 'teams', teamId]);
if (!teamData) { return; }
var data = Util.clone(teamData);
delete data.owner;
return data;
};
var inviteToTeam = function (ctx, data, cId, cb) {
var teamId = data.teamId;
if (!teamId) { return void cb({error: 'EINVAL'}); }
var team = ctx.teams[teamId];
if (!team) { return void cb ({error: 'ENOENT'}); }
if (!team.roster) { return void cb({error: 'NO_ROSTER'}); }
var user = data.user;
if (!user || !user.curvePublic || !user.notifications) { return void cb({error: 'MISSING_DATA'}); }
delete user.channel;
delete user.lastKnownHash;
user.pending = true;
var obj = {};
obj[user.curvePublic] = user;
team.roster.add(obj, function (err) {
if (err && err !== 'NO_CHANGE') { return void cb({error: err}); }
ctx.store.mailbox.sendTo('INVITE_TO_TEAM', {
user: Messaging.createData(ctx.store.proxy, false),
team: getInviteData(ctx, teamId)
}, {
channel: user.notifications,
curvePublic: user.curvePublic
}, function (obj) {
cb(obj);
});
});
};
// XXX Listen for changes to the roster pad to know if you've been removed
// XXX onReady, if you've been removed, leave the team
var removeUser = function (ctx, data, cId, cb) {
@@ -584,7 +634,8 @@ define([
pinPads: cfg.pinPads,
emit: emit,
onReadyHandlers: {},
teams: {}
teams: {},
updateMetadata: cfg.updateMetadata
};
var teams = store.proxy.teams = store.proxy.teams || {};
@@ -608,7 +659,8 @@ define([
Object.keys(teams).forEach(function (id) {
t[id] = {
name: teams[id].metadata.name,
edPublic: Util.find(teams[id], ['keys', 'drive', 'edPublic'])
edPublic: Util.find(teams[id], ['keys', 'drive', 'edPublic']),
avatar: Util.find(teams[id], ['metadata', 'avatar'])
};
});
return t;
@@ -616,6 +668,22 @@ define([
team.getTeams = function () {
return Object.keys(ctx.teams);
};
team.removeFromTeam = function (teamId, curve) {
if (!teams[teamId]) { return; }
if (ctx.onReadyHandlers[teamId]) {
ctx.onReadyHandlers[teamId].push({cb : function () {
ctx.teams[teamId].roster.remove([curve], function (err) {
if (err && err !== 'NO_CHANGE') { console.error(err); }
});
}});
return;
}
if (!ctx.teams[teamId]) { return void console.error("TEAM MODULE ERROR"); }
ctx.teams[teamId].roster.remove([curve], function (err) {
if (err && err !== 'NO_CHANGE') { console.error(err); }
});
};
team.removeClient = function (clientId) {
removeClient(ctx, clientId);
};
@@ -644,6 +712,12 @@ define([
if (cmd === 'DESCRIBE_USER') {
return void describeUser(ctx, data, clientId, cb);
}
if (cmd === 'INVITE_TO_TEAM') {
return void inviteToTeam(ctx, data, clientId, cb);
}
if (cmd === 'JOIN_TEAM') {
return void joinTeam(ctx, data, clientId, cb);
}
if (cmd === 'REMOVE_USER') {
return void removeUser(ctx, data, clientId, cb);
}