53 lines
1.8 KiB
JavaScript
53 lines
1.8 KiB
JavaScript
const _ = require('lodash/fp')
|
|
const { mapSchema, getDirective, MapperKind } = require('@graphql-tools/utils')
|
|
const { defaultFieldResolver } = require('graphql')
|
|
|
|
const { AuthenticationError } = require('../errors')
|
|
|
|
function authDirectiveTransformer(schema, directiveName = 'auth') {
|
|
return mapSchema(schema, {
|
|
// For object types
|
|
[MapperKind.OBJECT_TYPE]: objectType => {
|
|
const directive = getDirective(schema, objectType, directiveName)?.[0]
|
|
if (directive) {
|
|
const requiredAuthRole = directive.requires
|
|
objectType._requiredAuthRole = requiredAuthRole
|
|
}
|
|
return objectType
|
|
},
|
|
|
|
// For field definitions
|
|
[MapperKind.OBJECT_FIELD]: (fieldConfig, _fieldName, typeName) => {
|
|
const directive = getDirective(schema, fieldConfig, directiveName)?.[0]
|
|
if (directive) {
|
|
const requiredAuthRole = directive.requires
|
|
fieldConfig._requiredAuthRole = requiredAuthRole
|
|
}
|
|
|
|
// Get the parent object type
|
|
const objectType = schema.getType(typeName)
|
|
|
|
// Apply auth check to the field's resolver
|
|
const { resolve = defaultFieldResolver } = fieldConfig
|
|
fieldConfig.resolve = function (root, args, context, info) {
|
|
const requiredRoles =
|
|
fieldConfig._requiredAuthRole || objectType._requiredAuthRole
|
|
if (!requiredRoles)
|
|
return resolve.apply(this, [root, args, context, info])
|
|
|
|
const user = context.req.session.user
|
|
if (!user || !_.includes(_.upperCase(user.role), requiredRoles)) {
|
|
throw new AuthenticationError(
|
|
'You do not have permission to access this resource!',
|
|
)
|
|
}
|
|
|
|
return resolve.apply(this, [root, args, context, info])
|
|
}
|
|
|
|
return fieldConfig
|
|
},
|
|
})
|
|
}
|
|
|
|
module.exports = authDirectiveTransformer
|