mirror of
https://github.com/NodeBB/NodeBB.git
synced 2026-02-26 00:21:16 +01:00
147 lines
4.3 KiB
JavaScript
147 lines
4.3 KiB
JavaScript
|
|
'use strict';
|
|
|
|
const async = require('async');
|
|
const nconf = require('nconf');
|
|
const validator = require('validator');
|
|
|
|
const db = require('../database');
|
|
const meta = require('../meta');
|
|
const emailer = require('../emailer');
|
|
const groups = require('../groups');
|
|
const translator = require('../translator');
|
|
const 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((invites, index) => ({
|
|
uid: uids[index],
|
|
invitations: invites,
|
|
}));
|
|
};
|
|
|
|
User.sendInvitationEmail = async function (uid, email, groupsToJoin) {
|
|
if (!uid) {
|
|
throw new Error('[[error:invalid-uid]]');
|
|
}
|
|
|
|
const email_exists = await User.getUidByEmail(email);
|
|
if (email_exists) {
|
|
throw new Error('[[error:email-taken]]');
|
|
}
|
|
|
|
const invitation_exists = await db.exists(`invitation:email:${email}`);
|
|
if (invitation_exists) {
|
|
throw new Error('[[error:email-invited]]');
|
|
}
|
|
|
|
const data = await prepareInvitation(uid, email, groupsToJoin);
|
|
await emailer.sendToEmail('invitation', email, meta.config.defaultLang, data);
|
|
};
|
|
|
|
User.verifyInvitation = async function (query) {
|
|
if (!query.token || !query.email) {
|
|
if (meta.config.registrationType.startsWith('admin-')) {
|
|
throw new Error('[[register:invite.error-admin-only]]');
|
|
} else {
|
|
throw new Error('[[register:invite.error-invite-only]]');
|
|
}
|
|
}
|
|
const token = await db.getObjectField(`invitation:email:${query.email}`, 'token');
|
|
if (!token || token !== query.token) {
|
|
throw new Error('[[register:invite.error-invalid-data]]');
|
|
}
|
|
};
|
|
|
|
User.joinGroupsFromInvitation = async function (uid, email) {
|
|
let groupsToJoin = await db.getObjectField(`invitation:email:${email}`, 'groupsToJoin');
|
|
|
|
try {
|
|
groupsToJoin = JSON.parse(groupsToJoin);
|
|
} catch (e) {
|
|
return;
|
|
}
|
|
|
|
if (!groupsToJoin || groupsToJoin.length < 1) {
|
|
return;
|
|
}
|
|
|
|
await groups.join(groupsToJoin, uid);
|
|
};
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
async function prepareInvitation(uid, email, groupsToJoin) {
|
|
const inviterExists = await User.exists(uid);
|
|
if (!inviterExists) {
|
|
throw new Error('[[error:invalid-uid]]');
|
|
}
|
|
|
|
const token = utils.generateUUID();
|
|
const registerLink = `${nconf.get('url')}/register?token=${token}&email=${encodeURIComponent(email)}`;
|
|
|
|
const expireDays = meta.config.inviteExpiration;
|
|
const expireIn = expireDays * 86400000;
|
|
|
|
await db.setAdd(`invitation:uid:${uid}`, email);
|
|
await db.setAdd('invitation:uids', uid);
|
|
await db.setObject(`invitation:email:${email}`, {
|
|
token,
|
|
groupsToJoin: JSON.stringify(groupsToJoin),
|
|
});
|
|
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);
|
|
|
|
return {
|
|
...emailer._defaultPayload, // Append default data to this email payload
|
|
site_title: title,
|
|
registerLink: registerLink,
|
|
subject: subject,
|
|
username: username,
|
|
template: 'invitation',
|
|
expireDays: expireDays,
|
|
};
|
|
}
|
|
};
|