【问题标题】:Apollo wrong directive call阿波罗错误指令调用
【发布时间】:2020-12-26 19:16:57
【问题描述】:

对于 userPasswordChange 突变由于某种原因被称为 minGroup dirrective 而不是 idIsOwnerOrMinGroup。可能是什么问题?

export const typeDefs = gql`
  directive @minGroup(requires: Group = ADMINS) on OBJECT | FIELD_DEFINITION
  directive @idIsOwnerOrMinGroup(requires: Group = ADMINS) on OBJECT | FIELD_DEFINITION

type Mutation {
   userPasswordChange(oldPassword: String, newPassword: String!, id: Int!): Boolean! @idIsOwnerOrMinGroup(requires: ADMINS)
}`


import { MinGroupDirective } from '../directives/minGroupDirective'
import { IdIsOwnerOrMinGroupDirective } from '../directives/IdIsOwnerOrMinGroupDirective'

export const schemaDirectives = {
  minGroup: MinGroupDirective,
  idIsOwnerOrMinGroup: IdIsOwnerOrMinGroupDirective,
} as any

export const schema = makeExecutableSchema({
  typeDefs,
  resolvers,
  schemaDirectives,
})

type MinGroupRequired = { _minGroup?: AccessGroup }
type MinGroupAvoidRewrap = { _minGroupAvoidRewrap?: true }

export class MinGroupDirective extends SchemaDirectiveVisitor {
  visitObject(type: GraphQLObjectType & MinGroupRequired): void {
    this.ensureFieldsWrapped(type)
    type._minGroup = this.args.requires
  }
  // Visitor methods for nested types like fields and arguments
  // also receive a details object that provides information about
  // the parent and grandparent types.
  visitFieldDefinition(
    field: GraphQLField<any, any> & MinGroupRequired,
    details: {
      field: GraphQLField<any, any>
      objectType: GraphQLObjectType | GraphQLInterfaceType
    }
  ): void {
    this.ensureFieldsWrapped(details.objectType)
    field._minGroup = this.args.requires
  }

  ensureFieldsWrapped(objectType: (GraphQLObjectType | GraphQLInterfaceType) & MinGroupRequired & MinGroupAvoidRewrap): any {
    // Mark the GraphQLObjectType object to avoid re-wrapping:
    if (objectType._minGroupAvoidRewrap) return
    objectType._minGroupAvoidRewrap = true

    const fields = objectType.getFields()

    Object.keys(fields).forEach((fieldName) => {
      const field = fields[fieldName] as GraphQLField<any, any, any> & MinGroupRequired
      const { resolve = defaultFieldResolver } = field

      field.resolve = async function (...args): Promise<any> {
        // Get the required Group from the field first, falling back
        // to the objectType if no Group is required by the field:
        const requiredGroup = field._minGroup || objectType._minGroup

        if (!requiredGroup) return resolve.apply(this, args)

        const ctx: Ctx<CtxUserAny> = args[2]

        if (minGroupCheck(ctx.user.access_group, requiredGroup)) return resolve.apply(this, args)

        throw genGqlError('')
      }
    })
  }
}


type MinGroupRequired = { _minGroup?: AccessGroup }
type MinGroupAvoidRewrap = { _minGroupAvoidRewrap?: true }

export class IdIsOwnerOrMinGroupDirective extends SchemaDirectiveVisitor {
  visitObject(type: GraphQLObjectType & MinGroupRequired): void {
    this.ensureFieldsWrapped(type)
    type._minGroup = this.args.requires
  }
  // Visitor methods for nested types like fields and arguments
  // also receive a details object that provides information about
  // the parent and grandparent types.
  visitFieldDefinition(
    field: GraphQLField<any, any> & MinGroupRequired,
    details: {
      field: GraphQLField<any, any>
      objectType: GraphQLObjectType | GraphQLInterfaceType
    }
  ): void {
    this.ensureFieldsWrapped(details.objectType)
    field._minGroup = this.args.requires
  }

  ensureFieldsWrapped(objectType: (GraphQLObjectType | GraphQLInterfaceType) & MinGroupRequired & MinGroupAvoidRewrap): any {
    // Mark the GraphQLObjectType object to avoid re-wrapping:
    if (objectType._minGroupAvoidRewrap) return
    objectType._minGroupAvoidRewrap = true

    const fields = objectType.getFields()

    Object.keys(fields).forEach((fieldName) => {
      const field = fields[fieldName] as GraphQLField<any, any, any> & MinGroupRequired
      const { resolve = defaultFieldResolver } = field

      field.resolve = async function (...args): Promise<any> {
        // Get the required Group from the field first, falling back
        // to the objectType if no Group is required by the field:
        const requiredGroup = field._minGroup || objectType._minGroup

        if (!requiredGroup) return resolve.apply(this, args)

        const ctx: Ctx<CtxUserAny> = args[2]
        const { id }: { id: number } = args[1]

        if (minGroupCheck(ctx.user.access_group, requiredGroup) || (id && id === (ctx.user as Ctx['user'])?.id))
          return resolve.apply(this, args)

        throw genGqlError('')
      }
    })
  }
}

【问题讨论】:

    标签: graphql apollo


    【解决方案1】:

    似乎他们每次都打电话,不知道为什么。在我将指令从field._minGroup 更改为type._minGroupOrOwner 后,问题就解决了。但我想看看解释。

    type MinGroupOrOwnerRequired = { _minGroupOrOwner?: AccessGroup }
    type MinGroupOrOwnerAvoidRewrap = { _minGroupOrOwnerAvoidRewrap?: true }
    
    export class IdIsOwnerOrMinGroupDirective extends SchemaDirectiveVisitor {
      visitObject(type: GraphQLObjectType & MinGroupOrOwnerRequired): void {
        this.ensureFieldsWrapped(type)
        type._minGroupOrOwner = this.args.requires
      }
      // Visitor methods for nested types like fields and arguments
      // also receive a details object that provides information about
      // the parent and grandparent types.
      visitFieldDefinition(
        field: GraphQLField<any, any> & MinGroupOrOwnerRequired,
        details: {
          field: GraphQLField<any, any>
          objectType: GraphQLObjectType | GraphQLInterfaceType
        }
      ): void {
        this.ensureFieldsWrapped(details.objectType)
        field._minGroupOrOwner = this.args.requires
      }
    
      ensureFieldsWrapped(objectType: (GraphQLObjectType | GraphQLInterfaceType) & MinGroupOrOwnerRequired & MinGroupOrOwnerAvoidRewrap): any {
        // Mark the GraphQLObjectType object to avoid re-wrapping:
        if (objectType._minGroupOrOwnerAvoidRewrap) return
        objectType._minGroupOrOwnerAvoidRewrap = true
    
        const fields = objectType.getFields()
    
        Object.keys(fields).forEach((fieldName) => {
          const field = fields[fieldName] as GraphQLField<any, any, any> & MinGroupOrOwnerRequired
          const { resolve = defaultFieldResolver } = field
    
          field.resolve = async function (...args): Promise<any> {
            // Get the required Group from the field first, falling back
            // to the objectType if no Group is required by the field:
            const requiredGroup = field._minGroupOrOwner || objectType._minGroupOrOwner
    
            if (!requiredGroup) return resolve.apply(this, args)
    
            const ctx: Ctx<CtxUserAny> = args[2]
            const { id }: { id: number } = args[1]
    
            if (minGroupCheck(ctx.user.access_group, requiredGroup) || (id && id === (ctx.user as Ctx['user'])?.id))
              return resolve.apply(this, args)
    
            throw genGqlError('')
          }
        })
      }
    }
    

    【讨论】:

      猜你喜欢
      • 2017-11-20
      • 2021-09-17
      • 2020-07-07
      • 1970-01-01
      • 2013-02-02
      • 2021-12-28
      • 2017-10-15
      • 2017-03-03
      • 2021-09-09
      相关资源
      最近更新 更多