3 var env = require('gitter-web-env');
5 const config = env.config;
6 const redisClient = env.redis.getClient();
7 var Promise = require('bluebird');
8 var isValidEmail = require('email-validator').validate;
9 var StatusError = require('statuserror');
10 const dolph = require('dolph');
11 var emailNotificationService = require('gitter-web-email-notifications');
12 var roomService = require('gitter-web-rooms');
13 var invitesService = require('gitter-web-invites/lib/invites-service');
18 function addUserToRoomInsteadOfInvite(room, invitingUser, userToInvite) {
19 return roomService.addUserToRoom(room, invitingUser, userToInvite);
25 function createInviteForNewUser(room, invitingUser, type, externalId, emailAddress) {
26 return Promise.try(function() {
27 // If an email address is provided, assert that its valid
30 if (!isValidEmail(emailAddress)) {
31 throw new StatusError(400);
36 // No email address was provided, attempt to
37 // sniff out the email address given the external username and type
38 return invitesService.resolveEmailAddress(invitingUser, type, externalId);
43 .then(function(resolvedEmailAddress) {
44 // The client needs to submit the request with an email address
45 if (!resolvedEmailAddress) throw new StatusError(428);
47 return invitesService.createInvite(room._id, {
49 externalId: externalId,
50 emailAddress: resolvedEmailAddress,
51 invitedByUserId: invitingUser._id
54 .tap(function(invite) {
55 stats.event('new_invite', {
56 userId: invitingUser && (invitingUser.id || invitingUser._id),
57 troupeId: room && (room.id || room._id),
62 return emailNotificationService.sendInvitation(invitingUser, invite, room);
64 .then(function(invite) {
65 return invite.emailAddress;
69 const ROOM_INVITE_RATE_LIMIT_THRESHOLD = config.get('email:inviteEmailAbuseThresholdPerDay') || 10;
70 const ROOM_INVITE_RATE_LIMIT_EXPIRY = 24 * 60 * 60;
71 const roomInviteRateLimiter = Promise.promisify(
74 redisClient: redisClient
80 * status: 'added'/'invited'
81 * emailAddress: '...' // When the user has been invited
82 * user: '...' // When the user was added
84 * @throws HTTP 428 (email address required)
86 async function createInvite(room, invitingUser, options) {
87 const type = options.type;
88 const externalId = options.externalId;
89 const emailAddress = options.emailAddress;
91 // Firstly, try figure out whether this user is already on gitter.
92 const userToInvite = await invitesService.findExistingUser(type, externalId);
95 // The user already exists!
96 // Rather than inviting them, we'll add them
97 // immediately (for now)
98 return addUserToRoomInsteadOfInvite(room, invitingUser, userToInvite).then(function() {
105 // See https://gitlab.com/gitterHQ/webapp/issues/2153
106 if (config.get('email:limitInviteEmails')) {
107 const count = await roomInviteRateLimiter(invitingUser.id, ROOM_INVITE_RATE_LIMIT_EXPIRY);
108 if (count > ROOM_INVITE_RATE_LIMIT_THRESHOLD) {
109 throw new StatusError(
111 `Inviting a user by email is limited to ${ROOM_INVITE_RATE_LIMIT_THRESHOLD} per day, see #2153`
116 // The user doesn't exist. We'll try invite them
117 return createInviteForNewUser(room, invitingUser, type, externalId, emailAddress).then(function(
122 emailAddress: resolvedEmailAddress
129 createInvite: Promise.method(createInvite)