Skip to content

SchemaDirectiveVisitor.visitInputFieldDefinition resolver doesn't fire #858

Closed
@curtisallen

Description

@curtisallen

While attempting to build a custom auth directive I'm unable to get wrapped resolvers to invoke when working with Input types. Is this the expected behavor? In my case I'd like to use a custom directive to limit write access via mutation input arguments. Consider the following example

const { defaultFieldResolver } = require('graphql')
const { SchemaDirectiveVisitor, makeExecutableSchema } = require('graphql-tools')
const { graphqlExpress } = require('apollo-server-express')
const bodyParser = require('body-parser')
const express = require('express')

const app = express()
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({
  extended: true
}))

const typeDefs = `
directive @auth(
  requires: Role = USER,
  action: Action = READ,
) on INPUT_FIELD_DEFINITION

enum Role {
  ADMIN
  USER
}

enum Action {
  READ
  MODIFY
}

type Author {
  id: ID!
  firstName: String
  lastName: String
  role: String
}

input AuthorInput {
  id: ID!
  firstName: String
  lastName: String
  role: String @auth(requires: ADMIN, action: MODIFY)
}

type Mutation {
  submitUser(
    author: AuthorInput!
  ): Author
}

type Query {
  authors: [Author]
}

schema {
  query: Query
  mutation: Mutation
}
`
const resolvers = {
  Mutation: {
    submitUser (_, { author }) {
      // save author
      console.log('saving author...')
      return author
    }
  }
}

class AuthDirective extends SchemaDirectiveVisitor {
  visitInputFieldDefinition (field, details) {
    console.log('visitInputFieldDefinition')
    const { resolve = defaultFieldResolver } = field
    field.resolve = function (...args) {
      console.log('Custom resolver')
      // Auth logic would go here
      return resolve.apply(this, args)
    }
  }
}

const executableSchema = makeExecutableSchema({
  typeDefs,
  resolvers,
  schemaDirectives: { auth: AuthDirective }
})

app.use('/graphql', graphqlExpress((request) => {
  return {
    schema: executableSchema
  }
}))

app.listen(8000, () => console.log(':8000 Listening'))

Starting the server prints

visitInputFieldDefinition
:8000 Listening

Submitting the following graphQL mutation

mutation addPerson {
  submitUser(author: {
    id: "123"
    firstName: "Payton"
    lastName: "Manning"
    role: "admin"
  }) {
    id
    role
  }
}

Prints

saving author...

I'd expect to see

Invoking custom resolver
saving author...

Most examples I see that use custom directives and input types only change filed.type, but I'm hoping to invoke some custom auth logic before the mutation resolver runs.
#640 seems like it should help here but I've been unable to get my auth resolver to invoke.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions