mirror of
https://github.com/wassname/talk.git
synced 2026-07-15 11:26:58 +08:00
emails loaded from graph
- introduced graphql method on context - mailer will try to load the email from the graph
This commit is contained in:
+35
-1
@@ -7,6 +7,7 @@ const plugins = require('../services/plugins');
|
||||
const { getBroker } = require('./subscriptions/broker');
|
||||
const debug = require('debug')('talk:graph:context');
|
||||
const { createLogger } = require('../services/logging');
|
||||
const { graphql } = require('graphql');
|
||||
|
||||
/**
|
||||
* Contains the array of plugins that provide context to the server, these top
|
||||
@@ -75,6 +76,39 @@ class Context {
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* graphql will execute a graph request for the current context.
|
||||
*
|
||||
* @param {String} requestString A GraphQL language formatted string
|
||||
* representing the requested operation.
|
||||
* @param {Object} variableValues A mapping of variable name to runtime value
|
||||
* to use for all variables defined in the requestString.
|
||||
* @param {Object} rootValue The value provided as the first argument to
|
||||
* resolver functions on the top level type (e.g. the query object type).
|
||||
* @param {String} operationName The name of the operation to use if
|
||||
* requestString contains multiple possible operations. Can be omitted if
|
||||
* requestString contains only one operation.
|
||||
* @returns {Promise}
|
||||
*/
|
||||
async graphql(
|
||||
requestString,
|
||||
variableValues = {},
|
||||
rootValue = {},
|
||||
operationName = undefined
|
||||
) {
|
||||
// Perform the graph request directly using the graphql client.
|
||||
return graphql(
|
||||
// Use the connected graph schema.
|
||||
this.connectors.graph.schema,
|
||||
requestString,
|
||||
rootValue,
|
||||
// Use this, the context as the context.
|
||||
this,
|
||||
variableValues,
|
||||
operationName
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* forSystem returns a system context object that can be used for internal
|
||||
* operations.
|
||||
@@ -92,7 +126,7 @@ class Context {
|
||||
// Attach the Context to the connectors.
|
||||
connectors.graph.Context = Context;
|
||||
|
||||
// Connect the connect based plugings after the server has started.
|
||||
// Connect the connect based plugins after the server has started.
|
||||
plugins.defer('server', 'connect', ({ plugin, connect }) => {
|
||||
debug(`connecting plugin to connectors '${plugin.name}'`);
|
||||
|
||||
|
||||
+51
-6
@@ -4,8 +4,9 @@ const kue = require('./kue');
|
||||
const i18n = require('./i18n');
|
||||
const path = require('path');
|
||||
const fs = require('fs-extra');
|
||||
const { get, set, merge, template } = require('lodash');
|
||||
const { get, set, merge, template, isObject } = require('lodash');
|
||||
const { TEMPLATE_LOCALS } = require('../middleware/staticTemplate');
|
||||
const Context = require('../graph/context');
|
||||
|
||||
const {
|
||||
SMTP_HOST,
|
||||
@@ -131,6 +132,14 @@ mailer.send = async options => {
|
||||
return;
|
||||
}
|
||||
|
||||
// Try to get the user id or the email address from the passed in options. If
|
||||
// neither are provided, then error out.
|
||||
const email = get(options, 'email');
|
||||
const user = isObject(options.user) ? get(options.user, 'id') : options.user;
|
||||
if (!user && !email) {
|
||||
throw new Error('user not provided');
|
||||
}
|
||||
|
||||
// Create the new locals object and attach the static locals and the i18n
|
||||
// framework.
|
||||
const locals = merge({}, mailer.helpers, options.locals, TEMPLATE_LOCALS, {
|
||||
@@ -147,9 +156,11 @@ mailer.send = async options => {
|
||||
// Create the job to send the email later.
|
||||
return mailer.task.create({
|
||||
title: 'Mail',
|
||||
user,
|
||||
email,
|
||||
message: {
|
||||
to: options.to,
|
||||
subject: `${EMAIL_SUBJECT_PREFIX} ${options.subject}`,
|
||||
from: SMTP_FROM_ADDRESS,
|
||||
text,
|
||||
html,
|
||||
},
|
||||
@@ -162,14 +173,48 @@ mailer.send = async options => {
|
||||
mailer.process = () => {
|
||||
debug(`Now processing ${mailer.task.name} jobs`);
|
||||
|
||||
return mailer.task.process(({ id, data }, done) => {
|
||||
return mailer.task.process(async ({ id, data }, done) => {
|
||||
const { email, user, message } = data;
|
||||
|
||||
debug(`Starting to send mail for Job[${id}]`);
|
||||
|
||||
// Set the `from` field.
|
||||
data.message.from = SMTP_FROM_ADDRESS;
|
||||
// If the message has a specific email already to sent it to, just assign
|
||||
// that to the message. If the email does not have an email, and instead has
|
||||
// a user id, then we should lookup the user with the graph and get their
|
||||
// email.
|
||||
if (email) {
|
||||
message.to = email;
|
||||
} else {
|
||||
// Get the user to send the message to.
|
||||
const ctx = Context.forSystem();
|
||||
|
||||
try {
|
||||
const { data, errors } = await ctx.graphql(
|
||||
`
|
||||
query GetUserEmail($user: ID!) {
|
||||
user(id: $user) {
|
||||
email
|
||||
}
|
||||
}
|
||||
`,
|
||||
{ user }
|
||||
);
|
||||
if (errors) {
|
||||
return done(errors);
|
||||
}
|
||||
const email = get(data, 'user.email');
|
||||
if (!email) {
|
||||
return done(errors.ErrMissingEmail);
|
||||
}
|
||||
|
||||
message.to = email;
|
||||
} catch (err) {
|
||||
return done(err);
|
||||
}
|
||||
}
|
||||
|
||||
// Actually send the email.
|
||||
mailer.transport.sendMail(data.message, err => {
|
||||
mailer.transport.sendMail(message, err => {
|
||||
if (err) {
|
||||
debug(`Failed to send mail for Job[${id}]:`, err);
|
||||
return done(err);
|
||||
|
||||
+4
-10
@@ -400,8 +400,9 @@ class UsersService {
|
||||
|
||||
/**
|
||||
* sendEmailConfirmation sends a confirmation email to the user.
|
||||
*
|
||||
* @param {String} user the user to send the email to
|
||||
* @param {String} email the email for the user to send the email to
|
||||
* @param {String} email the email for the user to send the email to
|
||||
*/
|
||||
static async sendEmailConfirmation(user, email, redirectURI = ROOT_URL) {
|
||||
let token = await UsersService.createEmailConfirmToken(
|
||||
@@ -418,21 +419,14 @@ class UsersService {
|
||||
email,
|
||||
},
|
||||
subject: i18n.t('email.confirm.subject'),
|
||||
to: email,
|
||||
email,
|
||||
});
|
||||
}
|
||||
|
||||
static async sendEmail(user, options) {
|
||||
const email = user.firstEmail;
|
||||
if (!email) {
|
||||
// Rather than throwing an error here, we'll
|
||||
console.warn(new Error('user does not have an email'));
|
||||
return;
|
||||
}
|
||||
|
||||
return mailer.send(
|
||||
merge({}, options, {
|
||||
to: email,
|
||||
user: user.id,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user