diff --git a/modules/core/graph/directives/hasRole.js b/modules/core/graph/directives/hasRole.js new file mode 100644 index 000000000..68f6862f8 --- /dev/null +++ b/modules/core/graph/directives/hasRole.js @@ -0,0 +1,38 @@ +const { ApolloError, ForbiddenError, SchemaDirectiveVisitor } = require( 'apollo-server-express' ) +const { defaultFieldResolver } = require( 'graphql' ) +const appRoot = require( 'app-root-path' ) +const knex = require( `${appRoot}/db/knex` ) + +let roles + +module.exports = { + hasRole: class HasRoleDirective extends SchemaDirectiveVisitor { + visitFieldDefinition( field ) { + const { resolver = defaultFieldResolver, name } = field + const requiredRole = this.args.role + console.log( requiredRole ) + + field.resolve = async function ( parent, args, context, info ) { + if ( !roles ) + roles = await knex( 'user_roles' ).select( '*' ) + + if ( !context.auth ) throw new ForbiddenError( 'You must provide an auth token.' ) + if ( context.role === 'server:admin' ) { + // pass + } else { + let role = roles.find( r => r.name === requiredRole ) + let myRole = roles.find( r => r.name === context.role ) + console.log( context.role ) + + if ( role === null ) new ApolloError( 'Invalid server role specified' ) + if ( myRole === null ) new ForbiddenError( 'You do not have the required server role (null)' ) + if ( myRole.weight < role.weight ) + throw new ForbiddenError( 'You do not have the required server role' ) + } + + const data = await resolver.call( this, parent, args, context, info ) + return data + } + } + } +} diff --git a/modules/index.js b/modules/index.js index ef0e8f51a..161409a84 100644 --- a/modules/index.js +++ b/modules/index.js @@ -34,6 +34,7 @@ exports.graph = ( ) => { let typeDefs = [ ` ${scalarSchemas} directive @hasScope(scope: String!) on FIELD_DEFINITION + directive @hasRole(role: String!) on FIELD_DEFINITION type Query { """ @@ -84,5 +85,6 @@ exports.graph = ( ) => { merge( resolvers, o ) } ) + console.log( schemaDirectives ) return { resolvers, typeDefs, schemaDirectives } }