Merge pull request #127 from Algoteers/feature/notifications-module
Feature/notifications module
This commit is contained in:
8 files changed
+73
-265
No files matched your search
@@ -0,0 +1,18 @@
|
||||
# Changelog
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
## [Unreleased]
|
||||
### Changed
|
||||
- [List changes here for upcoming release]
|
||||
|
||||
## 0.1.0 - 2018-12-14
|
||||
### Added
|
||||
- Notifications Module - Sending notifications such as emails, messages to client, etc
|
||||
- Reintroduced CORS whitelist
|
||||
- Created CHANGELOG — for the logging of changes
|
||||
|
||||
### Removed
|
||||
- Removed Sendgrid Mutations (moved to notifications module)
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "master-app",
|
||||
"version": "0.0.1",
|
||||
"version": "0.1.0",
|
||||
"description": "Responsible for loading all web modules and running them.",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
|
||||
+16
-10
@@ -1,13 +1,24 @@
|
||||
NODE_ENV=development
|
||||
|
||||
TEAMS_API_PRESHARED=THIS_IS_VERY_SECRET
|
||||
USERS_API_PRESHARED=THIS_IS_VERY_SECRET
|
||||
EVENTS_API_PRESHARED=THIS_IS_VERY_SECRET
|
||||
KEYVAULT_API_PRESHARED=THIS_IS_VERY_SECRET
|
||||
FINANCIAL_BEINGS_API_PRESHARED=THIS_IS_VERY_SECRET
|
||||
NOTIFICATIONS_API_PRESHARED=THIS_IS_VERY_SECRET
|
||||
|
||||
GRAPHQL_API_URL=https://app-api.advancedalgos.net/graphql
|
||||
TEAMS_API_URL=https://teams-api.advancedalgos.net/graphql
|
||||
USERS_API_URL=https://users-api.advancedalgos.net/graphql
|
||||
EVENTS_API_URL=https://events-api.advancedalgos.net/graphql
|
||||
KEYVAULT_API_URL=https://keyvault-api.advancedalgos.net/graphql
|
||||
# PROJECT_SITE_URL=https://advancedalgos.net
|
||||
PROJECT_SITE_URL=http://localhost:3999
|
||||
# PLATFORM_URL=https://platform.advancedalgos.net
|
||||
PLATFORM_URL=http://localhost:3100
|
||||
|
||||
GRAPHQL_API_URL=https://platform-api-dev.advancedalgos.net/graphql
|
||||
TEAMS_API_URL=https://teams-api-dev.advancedalgos.net/graphql
|
||||
USERS_API_URL=https://users-api-dev.advancedalgos.net/graphql
|
||||
EVENTS_API_URL=https://events-api-dev.advancedalgos.net/graphql
|
||||
KEYVAULT_API_URL=https://keyvault-api-dev.advancedalgos.net/graphql
|
||||
FINANCIAL_BEINGS_API_URL=https://financialbeings-api-dev.advancedalgos.net/graphql
|
||||
NOTIFICATIONS_API_URL=https://notifications-api-dev.advancedalgos.net/graphql
|
||||
|
||||
AUTH0_DOMAIN=auth0-domain
|
||||
AUTH0_AUDIENCE=auth0-audience
|
||||
@@ -16,8 +27,3 @@ AUTH0_ISSUER=auth0-issuer
|
||||
AACLOUD_ID=aacloud-id
|
||||
|
||||
RECAPTCHA=<RECAPTCHA_KEY>
|
||||
|
||||
SG_APIKEY=<SENDGRID_API_KEY>
|
||||
SG_APIKEY_CONTACTS=<SENDGRID_API_KEY_CONTACTS>
|
||||
SG_SIGNUP_EMAILID=<SENDGRID_SIGNUP_EMAILID>
|
||||
SG_CONTACT_EMAILID=<SENDGRID_CONTACT_EMAILID>
|
||||
+35
-9
@@ -9,8 +9,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) {
|
||||
@@ -68,11 +67,15 @@ async function run () {
|
||||
'financialBeings_',
|
||||
process.env.FINANCIAL_BEINGS_API_URL,
|
||||
process.env.FINANCIAL_BEINGS_API_PRESHARED)
|
||||
logger.info('FINANCIAL_BEINGS schema created')
|
||||
logger.info('Financial Beings schema created')
|
||||
const transformedNotificationsSchema = await createTransformedRemoteSchema(
|
||||
'notifications_',
|
||||
process.env.NOTIFICATIONS_API_URL,
|
||||
process.env.NOTIFICATIONS_API_PRESHARED)
|
||||
logger.info('Notifications schema created')
|
||||
|
||||
var schemas = [masterSchema]
|
||||
var schemas = []
|
||||
var resolvers = {}
|
||||
resolvers = Object.assign(resolvers, masterResolvers)
|
||||
|
||||
if (transformedTeamsSchema) {
|
||||
schemas.push(transformedTeamsSchema)
|
||||
@@ -97,7 +100,10 @@ async function run () {
|
||||
if (transformedFinancialBeingsSchema) {
|
||||
schemas.push(transformedFinancialBeingsSchema)
|
||||
}
|
||||
|
||||
if (transformedNotificationsSchema) {
|
||||
schemas.push(transformedNotificationsSchema)
|
||||
}
|
||||
|
||||
const schema = mergeSchemas({
|
||||
schemas,
|
||||
resolvers
|
||||
@@ -164,7 +170,7 @@ async function run () {
|
||||
return error
|
||||
},
|
||||
formatResponse: response => {
|
||||
logger.debug('Response from Apolo Server: ' + response)
|
||||
logger.debug('Response from Apollo Server: ' + response)
|
||||
return response
|
||||
},
|
||||
playground: {
|
||||
@@ -175,9 +181,29 @@ async function run () {
|
||||
}
|
||||
})
|
||||
|
||||
server.applyMiddleware({ app })
|
||||
const whitelist = [
|
||||
process.env.PROJECT_SITE_URL,
|
||||
process.env.PLATFORM_URL,
|
||||
process.env.GRAPHQL_API_URL,
|
||||
process.env.TEAMS_API_URL,
|
||||
process.env.USERS_API_URL,
|
||||
process.env.EVENTS_API_URL,
|
||||
process.env.KEYVAULT_API_URL,
|
||||
process.env.FINANCIAL_BEINGS_API_URL,
|
||||
process.env.NOTIFICATIONS_API_URL
|
||||
]
|
||||
|
||||
app.use(cors())
|
||||
const corsOptionsDelegate = (req, callback) => {
|
||||
let corsOptions
|
||||
if (whitelist.indexOf(req.header('Origin')) !== -1) {
|
||||
corsOptions = { origin: true, credentials: true }
|
||||
} else {
|
||||
corsOptions = { origin: false, credentials: true }
|
||||
}
|
||||
callback(null, corsOptions)
|
||||
}
|
||||
|
||||
server.applyMiddleware({ app, cors: corsOptionsDelegate })
|
||||
|
||||
app.listen(4100)
|
||||
logger.info(`Server running. Open ${process.env.GRAPHQL_API_URL} to run queries.`)
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import merge from 'lodash.merge'
|
||||
import { SendgridMutations } from './mutation'
|
||||
// import { SendgridMutations } from './mutation'
|
||||
|
||||
const resolvers = {
|
||||
Mutation: {
|
||||
...SendgridMutations
|
||||
// ...SendgridMutations
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
import SendgridMutations from './sendgrid'
|
||||
|
||||
export { SendgridMutations }
|
||||
@@ -1,237 +0,0 @@
|
||||
import axios from 'axios'
|
||||
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
|
||||
let origin = process.env.SANDGRID_ORIGN
|
||||
|
||||
export default {
|
||||
async master_NewsletterSignup(parent, { email }, ctx, info) {
|
||||
logger.info('master_NewsletterSignup params email:')
|
||||
logger.info(email)
|
||||
const token = jwt.sign({ email: email }, API_KEY, { expiresIn: '1d' })
|
||||
const params = '/email-verification?token='
|
||||
|
||||
const headers = {
|
||||
'Content-Type': 'application/json',
|
||||
'Access-Control-Allow-Origin' : origin,
|
||||
'Access-Control-Allow-Credentials': 'true'
|
||||
}
|
||||
|
||||
const data = JSON.stringify({
|
||||
"personalizations": [
|
||||
{
|
||||
"to": [
|
||||
{
|
||||
"email": email
|
||||
}
|
||||
],
|
||||
dynamic_template_data: {
|
||||
"aaverifylink": origin + params + token,
|
||||
"subject": 'VERIFY YOUR INTEREST in Advanced Algos'
|
||||
},
|
||||
"subject": 'VERIFY YOUR INTEREST in Advanced Algos'
|
||||
}
|
||||
],
|
||||
"from": {
|
||||
"email": "feedback@advancedalgos.net",
|
||||
"name": "Advanced Algos Team"
|
||||
},
|
||||
"reply_to": {
|
||||
"email": "feedback@advancedalgos.net",
|
||||
"name": "Advanced Algos Team"
|
||||
},
|
||||
"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
|
||||
}
|
||||
})
|
||||
.then(function (response) {
|
||||
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) {
|
||||
logger.error('Sendgrid sendVerify Error:')
|
||||
logger.error(error)
|
||||
throw new ApolloError(`Sendgrid sendVerify Error: ${error.response.data.errors[0].message}`, 404)
|
||||
})
|
||||
return sendVerify
|
||||
},
|
||||
async master_NewsletterSignupVerify(parent, { token }, ctx, info){
|
||||
let origin = process.env.SANDGRID_ORIGN
|
||||
const headers = {
|
||||
'Content-Type': 'application/json',
|
||||
'Access-Control-Allow-Origin' : origin,
|
||||
'Access-Control-Allow-Credentials': 'true'
|
||||
}
|
||||
|
||||
let verifiedToken
|
||||
try {
|
||||
verifiedToken = jwt.verify(token, API_KEY, {maxAge: '1d'})
|
||||
} catch(err) {
|
||||
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
|
||||
|
||||
const subscribe = axios({
|
||||
method: 'post',
|
||||
url: 'https://api.sendgrid.com/v3/contactdb/recipients',
|
||||
data: [{"email": email}],
|
||||
headers:{
|
||||
'content-type': 'application/json',
|
||||
'authorization': 'Bearer ' + API_KEY_CONTACTS
|
||||
}
|
||||
})
|
||||
.then(response => {
|
||||
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 response
|
||||
})
|
||||
.catch(error => {
|
||||
logger.error('Sendgrid verifySubscribe Error:')
|
||||
logger.error(error)
|
||||
throw new ApolloError(`Sendgrid verifySubscribe Error: ${error.response.data.errors[0].message}`, 404)
|
||||
})
|
||||
return subscribe
|
||||
},
|
||||
async master_Contact(parent, { email, subject, message, recaptcha }, ctx, info) {
|
||||
const headers = {
|
||||
'Content-Type': 'application/json',
|
||||
'Access-Control-Allow-Origin' : origin,
|
||||
'Access-Control-Allow-Credentials': 'true'
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
})
|
||||
.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
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,6 @@
|
||||
export const typeDef = `
|
||||
type Mutation {
|
||||
master_NewsletterSignup(email: String!): String
|
||||
master_NewsletterSignupVerify(token: String!): String
|
||||
master_Contact(email: String!, subject: String!, Message: String!, recaptcha: String!): String
|
||||
master_SampleMutation(variable: String!): String
|
||||
}
|
||||
|
||||
schema {
|
||||
|
||||
Reference in new issue
Block a user