From 9c19c9bdf117810bcc5293c394b310623d387a26 Mon Sep 17 00:00:00 2001 From: Barry Low Date: Fri, 9 Nov 2018 01:23:16 -0800 Subject: [PATCH] Integrate SendGrid Mutations --- server/.env.example | 1 + server/package-lock.json | 5 + server/package.json | 1 + server/src/index.js | 4 +- server/src/resolvers/index.js | 11 +- server/src/resolvers/mutation/index.js | 5 +- server/src/resolvers/mutation/sendgrid.js | 275 +++++++++++----------- server/src/schema/index.js | 6 +- 8 files changed, 170 insertions(+), 138 deletions(-) diff --git a/server/.env.example b/server/.env.example index c06a793a5..ddb7185f4 100644 --- a/server/.env.example +++ b/server/.env.example @@ -18,5 +18,6 @@ AACLOUD_ID=aacloud-id RECAPTCHA= SG_APIKEY= +SG_APIKEY_CONTACTS= SG_SIGNUP_EMAILID= SG_CONTACT_EMAILID= diff --git a/server/package-lock.json b/server/package-lock.json index fd5c655c7..61262e73f 100644 --- a/server/package-lock.json +++ b/server/package-lock.json @@ -3862,6 +3862,11 @@ "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=" }, + "lodash.merge": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.1.tgz", + "integrity": "sha512-AOYza4+Hf5z1/0Hztxpm2/xiPZgi/cjMqdnKTUWTBSKchJlxXXuUSxCCl8rJlf4g6yww/j6mA8nC8Hw/EZWxKQ==" + }, "lodash.once": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", diff --git a/server/package.json b/server/package.json index 57e2c3caa..c7a16fab5 100644 --- a/server/package.json +++ b/server/package.json @@ -36,6 +36,7 @@ "graphql": "^14.0.2", "graphql-tools": "^4.0.0", "jwks-rsa": "^1.3.0", + "lodash.merge": "^4.6.1", "node-fetch": "^2.2.0", "winston": "^3.1.0" } diff --git a/server/src/index.js b/server/src/index.js index a8194335c..0201a1056 100644 --- a/server/src/index.js +++ b/server/src/index.js @@ -10,6 +10,7 @@ import axios from 'axios' import { createTransformedRemoteSchema } from './createRemoteSchema' import { teams, events } from './links' import { typeDef as masterSchema } from './schema' +import masterResolvers from './resolvers' import logger from './logger' async function getUserId (authId) { @@ -61,6 +62,7 @@ async function run () { var schemas = [masterSchema] var resolvers = {} + resolvers = Object.assign(resolvers, masterResolvers) if (transformedTeamsSchema) { schemas.push(transformedTeamsSchema) @@ -155,7 +157,7 @@ async function run () { schema, context, formatError: error => { - logger.error('An error ocurred inside a module: ' + error) + logger.error(`An error ocurred inside a module: ${JSON.stringify(error)}`) return error }, formatResponse: response => { diff --git a/server/src/resolvers/index.js b/server/src/resolvers/index.js index 1f7db8323..c260c10b3 100644 --- a/server/src/resolvers/index.js +++ b/server/src/resolvers/index.js @@ -1 +1,10 @@ -export { default as Mutation } from './mutations' +import merge from 'lodash.merge' +import { SendgridMutations } from './mutation' + +const resolvers = { + Mutation: { + ...SendgridMutations + } +} + +export default resolvers diff --git a/server/src/resolvers/mutation/index.js b/server/src/resolvers/mutation/index.js index 6c46731d8..70ad9aef6 100644 --- a/server/src/resolvers/mutation/index.js +++ b/server/src/resolvers/mutation/index.js @@ -1,2 +1,3 @@ -import { mergeDirectoryModules } from '../../utils' -export default mergeDirectoryModules(__dirname) +import SendgridMutations from './sendgrid' + +export { SendgridMutations } diff --git a/server/src/resolvers/mutation/sendgrid.js b/server/src/resolvers/mutation/sendgrid.js index 7bf17115c..af9e318d5 100644 --- a/server/src/resolvers/mutation/sendgrid.js +++ b/server/src/resolvers/mutation/sendgrid.js @@ -1,10 +1,11 @@ import axios from 'axios' -import jwt from 'jsonwebtoken') +import jwt from 'jsonwebtoken' import { ApolloError } from 'apollo-server-express' import logger from '../../logger' const API_KEY = process.env.SG_APIKEY +const API_KEY_CONTACTS = process.env.SG_APIKEY_CONTACTS const dev = process.env.NODE_ENV === 'development' ? true : false let origin = 'https://app.advancedalgos.net' @@ -13,7 +14,7 @@ if (dev){ } export default { - async sendgrid_NewsletterSignup(parent, { email }, ctx, info) { + async master_NewsletterSignup(parent, { email }, ctx, info) { const token = jwt.sign({ email: email }, API_KEY, { expiresIn: '1d' }) let origin = 'https://advancedalgos.net' const params = '/email-verification?token=' @@ -21,13 +22,13 @@ export default { origin = 'http://localhost:4100' } - var headers = { + const headers = { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin' : origin, 'Access-Control-Allow-Credentials': 'true' - }; + } - var data = JSON.stringify({ + const data = JSON.stringify({ "personalizations": [ { "to": [ @@ -50,36 +51,35 @@ export default { "email": "feedback@advancedalgos.net", "name": "Advanced Algos Team" }, - "template_id": process.env.SG_EMAILID + "template_id": process.env.SG_SIGNUP_EMAILID }) const sendVerify = axios({ - method: 'post', - url: 'https://api.sendgrid.com/v3/mail/send', - data: data, - headers:{ - 'content-type': 'application/json', - 'authorization': 'Bearer ' + API_KEY - } + method: 'post', + url: 'https://api.sendgrid.com/v3/mail/send', + data: data, + headers:{ + 'content-type': 'application/json', + 'authorization': 'Bearer ' + API_KEY + } }) .then(function (response) { - if (response.status >= 200 && response.status < 300) { - context.res = { - status: response.status, - body: "Email verification sent \n", - headers - } - return context - } else { - throw response.data.errors[0].message - } + logger.info('Sendgrid sendVerify response:') + logger.info(response) + if (response.status >= 200 && response.status < 300) { + return 'SUCCESS' + } else { + throw response.data.errors[0].message + } }) .catch(function (error) { - throw new ApolloError(error.response.data.errors[0].message, 404) + logger.error('Sendgrid sendVerify Error:') + logger.error(error) + throw new ApolloError(`Sendgrid sendVerify Error: ${error.response.data.errors[0].message}`, 404) }) return sendVerify }, - async sendgrid_NewsletterSignupVerify(parent, { token }, ctx, info){ + async master_NewsletterSignupVerify(parent, { token }, ctx, info){ let origin = 'https://app.advancedalgos.net' if (dev){ origin = 'http://localhost:4100' @@ -90,16 +90,20 @@ export default { 'Access-Control-Allow-Credentials': 'true' } - let token; + let verifiedToken try { - verifiedToken = jwt.verify(token, API_KEY, {maxAge: '1d'}) + verifiedToken = jwt.verify(token, API_KEY, {maxAge: '1d'}) } catch(err) { - if (err.name === 'TokenExpiredError'){ - throw new ApolloError('Error: Token Expired. Please resubmit email address.', 400) - } else { - throw new ApolloError(`Error: ${err.message}`, 400) - } + logger.error('Sendgrid verifiedToken Error:') + logger.error(err) + if (err.name === 'TokenExpiredError'){ + throw new ApolloError('Error: Token Expired. Please resubmit email address.', 400) + } else { + throw new ApolloError(`Error: ${err.message}`, 400) + } } + logger.info('Sendgrid verifySignup verifiedToken: ') + logger.info(verifiedToken) const email = verifiedToken.email @@ -109,46 +113,53 @@ export default { data: [{"email": email}], headers:{ 'content-type': 'application/json', - 'authorization': 'Bearer ' + API_KEY + 'authorization': 'Bearer ' + API_KEY_CONTACTS } }) .then(response => { - const recipients = response.data.persisted_recipients - - if (recipients.length > 0 ){ - const addToList = axios({ - method: 'post', - url: 'https://api.sendgrid.com/v3/contactdb/lists/4068018/recipients/' + recipients[0], - headers:{ - 'content-type': 'application/json', - 'authorization': 'Bearer ' + API_KEY - } - }) - .then(response => { - if (response.status >= 200 && response.status < 300) { - return { email } - } else { - throw response.data.errors[0].message - } - }) - .catch(error => { - throw `Email SignUp Error: ${error}` - }) - return addToList; - } else{ - return response.data.errors[0].message - } + logger.info('Sendgrid verifySignup subscribe: ') + logger.info(response) + const recipients = response.data.persisted_recipients + if (recipients.length > 0 ){ + const addToList = axios({ + method: 'post', + url: 'https://api.sendgrid.com/v3/contactdb/lists/4068018/recipients/' + recipients[0], + headers:{ + 'content-type': 'application/json', + 'authorization': 'Bearer ' + API_KEY_CONTACTS + } + }) + .then(response => { + logger.info('Sendgrid verifySignup addToList: ') + logger.info(response) + if (response.status >= 200 && response.status < 300) { + return 'SUCCESS' + } else { + throw response.data.errors[0].message + } + }) + .catch(error => { + logger.error('Sendgrid verifySignUp subscribe Error:') + logger.error(error) + throw `Email SignUp Error: ${error}` + }) + return addToList + } else{ + return response.data.errors[0].message + } }) .then(response => { - return `Success: Added ${response.email} to General List` + return response }) .catch(error => { - throw new ApolloError(error.response.data.errors[0].message, 404) + logger.error('Sendgrid verifySubscribe Error:') + logger.error(error) + throw new ApolloError(`Sendgrid verifySubscribe Error: ${error.response.data.errors[0].message}`, 404) }) return subscribe }, - async sendgrid_Contact(parent, { email, subject, message, recaptcha }, ctx, info) { + async master_Contact(parent, { email, subject, message, recaptcha }, ctx, info) { let origin = 'https://advancedalgos.net' if (dev){ origin = 'http://localhost:4000' @@ -162,77 +173,79 @@ export default { const toEmail = 'feedback@advancedalgos.net' const data = JSON.stringify({ - "personalizations": [ - { - "to": [ - { - "email": email - } - ], - dynamic_template_data: { - "aacontactname": name, - "aacontactemail": email, - "aacontactbody": message - }, - "subject": `AA Corporate Site Contact - Message from ${name}` - } - ], - "from": { - "email": email, - "name": name - }, - "reply_to": { - "email": email, - "name": name - }, - "template_id": process.env.SG_CONTACT_EMAILID - }) - - const checkCaptcha = axios({ - method: 'post', - url: 'https://www.google.com/recaptcha/api/siteverify', - params: { - secret: process.env.RECAPTCHA, - response: recaptcha - } - }) - .then(function (response) { - logger.info(response.data) - if (response.status >= 200 && response.status < 300 && response.data.success) { - context.log('presend SendGrid'); - return axios({ - method: 'post', - url: 'https://api.sendgrid.com/v3/mail/send', - data: data, - headers:{ - 'content-type': 'application/json', - 'authorization': 'Bearer ' + API_KEY + "personalizations": [ + { + "to": [ + { + "email": email } - }) - .then(function (response) { - context.log('sendgrid response: ', response) - if (response.status >= 200 && response.status < 300) { - return `Contact email sent` - } else { - throw response.data.errors[0].message - } - }) - .catch(function (error) { - logger.error(`sendgrid Error: ${JSON.stringify(error)}`) - throw `Contact email send error: ${error.response.data.errors[0].message}` - }) - }else{ - throw response.data + ], + dynamic_template_data: { + "aacontactname": name, + "aacontactemail": email, + "aacontactbody": message + }, + "subject": `AA Corporate Site Contact - Message from ${name}` } - }) - .then(function(response){ - return response - }) - .catch(function (error) { - context.log('function error: ', error, JSON.stringify(error.Error)) - throw new ApolloError(JSON.stringify(error.response), 404) - }) - } - return + ], + "from": { + "email": email, + "name": name + }, + "reply_to": { + "email": email, + "name": name + }, + "template_id": process.env.SG_CONTACT_EMAILID + }) + + const checkCaptcha = axios({ + method: 'post', + url: 'https://www.google.com/recaptcha/api/siteverify', + params: { + secret: process.env.RECAPTCHA, + response: recaptcha + } + }) + .then(function (response) { + logger.info(response.data) + if (response.status >= 200 && response.status < 300 && response.data.success) { + context.log('presend SendGrid') + return axios({ + method: 'post', + url: 'https://api.sendgrid.com/v3/mail/send', + data: data, + headers:{ + 'content-type': 'application/json', + 'authorization': 'Bearer ' + API_KEY + } + }) + .then(function (response) { + logger.info('Sendgrid Contact response: ') + logger.info(response) + if (response.status >= 200 && response.status < 300) { + return `Contact email sent` + } else { + throw response.data.errors[0].message + } + }) + .catch(function (error) { + logger.error(`sendgrid Error: ${JSON.stringify(error)}`) + throw `Contact email send error: ${error.response.data.errors[0].message}` + }) + }else{ + throw response.data + } + }) + .then(function(response){ + return response + }) + .catch(function (error) { + logger.error('Sendgrid Contact RECAPTCHA Error:') + logger.error(error) + throw new ApolloError(`Sendgrid Contact RECAPTCHA Error: ${error.response.data.errors[0].message}`, 404) + }) + + return checkCaptcha } } diff --git a/server/src/schema/index.js b/server/src/schema/index.js index a84fcd35c..4b416cceb 100644 --- a/server/src/schema/index.js +++ b/server/src/schema/index.js @@ -1,8 +1,8 @@ export const typeDef = ` type Mutation { - sendgrid_NewsletterSignup(email: String!): String - sendgrid_NewsletterSignupVerify(email: String!): String - sendgrid_Contact(email: String!, subject: String!, Message: String!, recaptcha: String!): String + master_NewsletterSignup(email: String!): String + master_NewsletterSignupVerify(token: String!): String + master_Contact(email: String!, subject: String!, Message: String!, recaptcha: String!): String } schema {