diff --git a/README.md b/README.md index dabbd1bdc691cd8d73190e0ee15f9f1959e40afa..537cc2044c468a6c5ca231aeb4e4a45e7f758e5d 100644 --- a/README.md +++ b/README.md @@ -86,6 +86,46 @@ const permissions = require('../path/to/myPermissions.js') Please refer to shield's [documentation](https://github.com/maticzav/graphql-shield#overview) for more details. +### Email middleware + +Email notifications get sent out as a side effect of a **_mutation_** in your schema. + +Create a file wherever you like: + +```js +const myFunc = async (resolve, parent, args, ctx, info) => { + // do some stuff before the resolver + + const result = await resolve(parent, args, ctx, info) + + // do some stuff after the resolver + + // send your email + + return result +} + +module.exports = { + // myMutation needs to match a mutation name in your schema + myMutation: myFunc, +} +``` + +Now in your config: + +```js +// config/default.js +const emailService = require('path/to/your/email/file') + +{ + emailMiddleware: { + service: emailService + } +} +``` + +This middleware uses `graphql-middleware` to provide its functionality, so make sure to read its [documentation](https://github.com/prisma-labs/graphql-middleware) and understand its function signature. + ### Cron support All you need for cron-based scheduled tasks to run is to provide the path to your cron jobs. @@ -154,5 +194,4 @@ Useful if you have custom login resolvers. ### Future features -- Notification middleware - Include more pubsweet packages into the bundle diff --git a/src/graphqlApi.js b/src/graphqlApi.js index 5635157df7cb696f92ad09c412433a6afae77060..aafe07f4cd33fcd82bdc5a7370759b3d1d56ce68 100644 --- a/src/graphqlApi.js +++ b/src/graphqlApi.js @@ -1,13 +1,14 @@ const { ApolloServer } = require('apollo-server-express') const isEmpty = require('lodash/isEmpty') +const config = require('config') + const logger = require('@pubsweet/logger') const errors = require('@pubsweet/errors') -const config = require('config') - const connectors = require('pubsweet-server/src/connectors') const loaders = require('pubsweet-server/src/graphql/loaders') const helpers = require('pubsweet-server/src/helpers/authorization') + const schema = require('./graphqlSchema') const hostname = config.has('pubsweet-server.hostname') diff --git a/src/graphqlSchema.js b/src/graphqlSchema.js index 896b6815e6d9fa61515f4951c34d385b06b730a7..0643c11b33d62512039d252554dfa294c9309689 100644 --- a/src/graphqlSchema.js +++ b/src/graphqlSchema.js @@ -2,12 +2,47 @@ const config = require('config') const isEmpty = require('lodash/isEmpty') const { applyMiddleware } = require('graphql-middleware') const { shield } = require('graphql-shield') -let schema = require('pubsweet-server/src/graphql/schema') + +const logger = require('@pubsweet/logger') +const schema = require('pubsweet-server/src/graphql/schema') + +const emailMiddleware = require('./middleware/email') + +const baseMessage = 'Coko server =>' + +const logRegistration = name => + logger.info(`${baseMessage} Middleware: Registered ${name} middleware`) + +const middleware = [] +console.log('') // eslint-disable-line no-console +logger.info(`${baseMessage} Registering graphql middleware...`) + +/** + * Authorization middleware + */ const permissions = config.has('permissions') && config.get('permissions') -if (permissions && !isEmpty(permissions)) { - schema = applyMiddleware(schema, shield(permissions)) +if (!isEmpty(permissions)) { + const authorizationMiddleware = shield(permissions) + middleware.push(authorizationMiddleware) + logRegistration('authorization') } -module.exports = schema +/** + * Email middleware + */ + +const emailConfig = + config.has('emailMiddleware') && config.get('emailMiddleware') + +if (!isEmpty(emailConfig)) { + middleware.push(emailMiddleware) + logRegistration('email') +} + +console.log('') // eslint-disable-line no-console + +const schemaWithMiddleWare = applyMiddleware(schema, ...middleware) + +module.exports = schemaWithMiddleWare diff --git a/src/middleware/email.js b/src/middleware/email.js new file mode 100644 index 0000000000000000000000000000000000000000..fb6f07769cd98ea3b2f118954d0ddce43d5139e5 --- /dev/null +++ b/src/middleware/email.js @@ -0,0 +1,40 @@ +const config = require('config') +const { isEmpty } = require('lodash') +const { middleware } = require('graphql-middleware') + +// const logger = require('@pubsweet/logger') + +const generator = middleware(schema => { + const emailService = + config.has('emailMiddleware.service') && + config.get('emailMiddleware.service') + + if (isEmpty(emailService)) { + throw new Error('Email middleware: No email service provided!') + } + + /** + * Email notifications are only applicable on mutations + */ + const typeMap = schema.getTypeMap() + const { Mutation } = typeMap + const mutationFields = Mutation.getFields() + + const mutationEntries = Object.keys(mutationFields).reduce( + (middlewareSchema, field) => { + const serviceFieldEntry = emailService[field] + if (!serviceFieldEntry) return middlewareSchema + + /* eslint-disable-next-line no-param-reassign */ + middlewareSchema[field] = serviceFieldEntry + return middlewareSchema + }, + {}, + ) + + return { + Mutation: mutationEntries, + } +}) + +module.exports = generator