You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
nodebb/src/user/invite.js

107 lines
3.2 KiB
JavaScript

'use strict';
var async = require('async');
var nconf = require('nconf');
var validator = require('validator');
var db = require('./../database');
var meta = require('../meta');
var emailer = require('../emailer');
var translator = require('../translator');
var utils = require('../utils');
module.exports = function (User) {
User.getInvites = async function (uid) {
const emails = await db.getSetMembers('invitation:uid:' + uid);
return emails.map(email => validator.escape(String(email)));
};
User.getInvitesNumber = async function (uid) {
return await db.setCount('invitation:uid:' + uid);
};
User.getInvitingUsers = async function () {
return await db.getSetMembers('invitation:uids');
};
User.getAllInvites = async function () {
const uids = await User.getInvitingUsers();
const invitations = await async.map(uids, User.getInvites);
return invitations.map(function (invites, index) {
return {
uid: uids[index],
invitations: invites,
};
});
};
User.sendInvitationEmail = async function (uid, email) {
const token = utils.generateUUID();
const registerLink = nconf.get('url') + '/register?token=' + token + '&email=' + encodeURIComponent(email);
const expireDays = meta.config.inviteExpiration;
const expireIn = expireDays * 86400000;
const exists = await User.getUidByEmail(email);
if (exists) {
throw new Error('[[error:email-taken]]');
}
await db.setAdd('invitation:uid:' + uid, email);
await db.setAdd('invitation:uids', uid);
await db.set('invitation:email:' + email, token);
await db.pexpireAt('invitation:email:' + email, Date.now() + expireIn);
const username = await User.getUserField(uid, 'username');
const title = meta.config.title || meta.config.browserTitle || 'NodeBB';
const subject = await translator.translate('[[email:invite, ' + title + ']]', meta.config.defaultLang);
let data = {
site_title: title,
registerLink: registerLink,
subject: subject,
username: username,
template: 'invitation',
expireDays: expireDays,
};
// Append default data to this email payload
data = { ...emailer._defaultPayload, ...data };
await emailer.sendToEmail('invitation', email, meta.config.defaultLang, data);
};
User.verifyInvitation = async function (query) {
if (!query.token || !query.email) {
throw new Error('[[error:invalid-data]]');
}
const token = await db.get('invitation:email:' + query.email);
if (!token || token !== query.token) {
throw new Error('[[error:invalid-token]]');
}
};
User.deleteInvitation = async function (invitedBy, email) {
const invitedByUid = await User.getUidByUsername(invitedBy);
if (!invitedByUid) {
throw new Error('[[error:invalid-username]]');
}
await Promise.all([
deleteFromReferenceList(invitedByUid, email),
db.delete('invitation:email:' + email),
]);
};
User.deleteInvitationKey = async function (email) {
const uids = await User.getInvitingUsers();
await Promise.all(uids.map(uid => deleteFromReferenceList(uid, email)));
await db.delete('invitation:email:' + email);
};
async function deleteFromReferenceList(uid, email) {
await db.setRemove('invitation:uid:' + uid, email);
const count = await db.setCount('invitation:uid:' + uid);
if (count === 0) {
await db.setRemove('invitation:uids', uid);
}
}
};