ApolloServer не запускает пользовательские директивы

Я пытаюсь написать некоторую логику аутентификации на основе документации сервера Apollo, но, похоже, она не срабатывает. Вот мой код:

// schemas/auth-schema.js
import gql from 'graphql-tag';

export const typeDefs = gql`
  directive @auth(requires: Role = ADMIN) on OBJECT | FIELD_DEFINITION
`;
// directives/auth-directive.js
import { SchemaDirectiveVisitor } from 'apollo-server';

export default class AuthDirective extends SchemaDirectiveVisitor {
  visitObject(type) {
    console.info('HERE');
  }
  visitSchema() {
    console.info('HERE');
  }
  visitFieldDefinition() {
    console.info('HERE');
  }
}
// schemas/post-schema.js
import gql from 'graphql-tag';
import { Post } from '../models';

export const typeDefs = gql`
  type Post @auth(requires: ADMIN) {
    body: String!
    description: String!
    id: ID!
    image: String!
    publishedAt: DateTime
    readingTime: Int!
    slug: String!
    title: String!
  }

  input PostInput {
    body: String!
    description: String!
    image: String!
    publishedAt: DateTime
    title: String!
  }

  extend type Query {
    posts: [Post!]! @auth(requires: ADMIN)
  }

  extend type Mutation {
    addPost(input: PostInput!): Post! @auth(requires: ADMIN)
  }
`;

export const resolvers = {
  Query: {
    posts: () => Post.find({}),
  },
  Mutation: {
    addPost: (_, { input }) => Post.create(input),
  },
};

// index.js

import { ApolloServer } from 'apollo-server';
import mongoose from 'mongoose';
import AuthDirective from './directives/auth-directive';
import * as config from './config';

mongoose.set('useNewUrlParser', true);
mongoose.set('useCreateIndex', true);
mongoose.set('debug', config.env !== 'production');

const server = new ApolloServer({
  modules: [
    require('./schema/auth-schema'),
    require('./schema/date-schema'),
    require('./schema/post-schema'),
    require('./schema/role-schema'),
    require('./schema/user-schema'),
  ],
  schemaDirectives: {
    auth: AuthDirective,
  },
});

async function boot() {
  await mongoose.connect(config.mongo.url);
  await server.listen(config.http.port);
  console.info(`server listening on port ${config.http.port}`);
}

async function shutdown() {
  await server.stop();
  await mongoose.disconnect();
  console.info(`server shutted down`);
  process.exit(0);
}

process.on('SIGINT', shutdown);
process.on('SIGTERM', shutdown);

boot();

Итак, я пробовал использовать директиву @auth во всех возможных случаях, и ничего не срабатывает.

type Post @auth(requires: ADMIN) { ... } // not firing

type Query {
  posts: [Post!]! @auth(requires: ADMIN) // not firing
}

Вот что AdminDirective оценивает из консоли: ApolloServer не запускает пользовательские директивы

Что я делаю неправильно?

На первый взгляд, эта установка выглядит правильной. Какую версию аполло-сервера вы используете?

Daniel Rearden 13.02.2019 15:42

@DanielRearden Я использую сервер apollo версии 2.4.0.

brielov 13.02.2019 15:42

Хм, я только что проверил этот код локально, и он отлично работает для меня.

Daniel Rearden 13.02.2019 15:48

Можете ли вы обновить свой вопрос, чтобы показать полный auth-schema.js?

Daniel Rearden 13.02.2019 15:52

Кроме того, если вы запишете значение для AuthDirective внутри index.js, будет ли оно отображаться как определено?

Daniel Rearden 13.02.2019 15:53

@DanielRearden отредактировано

brielov 13.02.2019 16:10

Можете ли вы попробовать использовать makeExecutableSchema({ typeDefs, resolvers, schemaDirectives }); вместо модулей схемы. У меня также были проблемы с использованием свойства schemaDirectives в объекте конфигурации ApolloServer. Может быть проблема с ApolloServer

Christof Aenderl 13.02.2019 17:01
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Что такое Apollo Client и зачем он нужен?
Что такое Apollo Client и зачем он нужен?
Apollo Client - это полнофункциональный клиент GraphQL для JavaScript-приложений, который упрощает получение, управление и обновление данных в...
2
7
1 050
1

Ответы 1

Итак, глядя на код для apollo-server, когда вы используете опцию modules, внутри ваша схема строится с использованием buildServiceDefinition. Хотя эта функция объединяет директивы всех модулей, она не передает ваш объект schemaDirectives и не применяет его.

Другими словами, это похоже на ошибку самого apollo-server. Вы можете подать заявку, а пока просто воспользоваться опциями typeDefs и resolvers, объединив нужные файлы самостоятельно.

Хорошо, похоже, если вы поменяете модули со схемой и используете makeExecutableSchema, все будет работать нормально. Жаль, с другой стороны все выглядело намного чище :'( Спасибо за вашу помощь и время!

brielov 13.02.2019 17:58

Похоже, проблема уже была открыта, но на нее не обращали особого внимания: github.com/apollographql/аполло-сервер/issues/2046

brielov 13.02.2019 18:01

@brielov Вы могли бы взглянуть на использование слияние-graphql-схемы в дополнение к makeExecutableSchema. Это то, что я на самом деле использую в одном проекте.

Daniel Rearden 13.02.2019 18:07

Я обязательно посмотрю на это. Спасибо!

brielov 13.02.2019 18:16

Другие вопросы по теме