Как вернуть ответ об ошибке в ссылке apollo? - PullRequest
0 голосов
/ 25 сентября 2018

Я использую ссылку apollo в схеме сшивания в качестве уровня контроля доступа.Я не совсем уверен, как заставить ссылку возвращать ответ об ошибке, если у пользователя нет прав доступа к определенной операции.Я знаю о таких пакетах, как graphql-shield и graphql-middleware, но мне любопытно, что можно добиться базового контроля доступа, используя ссылку apollo.

Вот как выглядит моя ссылка:

  const link = setContext((request, previousContext) => merge({
    headers: {
      ...headers,
      context: `${JSON.stringify(previousContext.graphqlContext ? _.omit(previousContext.graphqlContext, ['logger', 'models']) : {})}`,
    },
  })).concat(middlewareLink).concat(new HttpLink({ uri, fetch }));

У middlewareLink есть checkPermissions, который возвращает true из false в зависимости от роли пользователя

const middlewareLink = new ApolloLink((operation, forward) => {
  const { operationName } = operation;
  if (operationName !== 'IntrospectionQuery') {
    const { variables } = operation;
    const context = operation.getContext().graphqlContext;

    const hasAccess = checkPermissions({ operationName, context, variables });
    if (!hasAccess) {
      // ...
    }
  }
  return forward(operation);
});

Что мне делать, если hasAccess равен false.Я думаю, мне не нужно пересылать операцию, так как на данный момент ясно, что у пользователя нет доступа к ней

ОБНОВЛЕНИЕ

Я думаю, что мне нужносделать, это расширить класс ApolloLink, но до сих пор мне не удалось вернуть ошибку

1 Ответ

0 голосов
/ 25 сентября 2018

После некоторого раскопок я действительно понял это.Но я не совсем уверен, что мой подход правильный.

По сути, я вызвал forward с последующим map, где я возвращаю объект, содержащий поля errors и data.Опять же, я думаю, есть лучший способ сделать это (возможно, путем расширения класса ApolloLink)

const middlewareLink = new ApolloLink((operation, forward) => {
  const { operationName } = operation;
  if (operationName !== 'IntrospectionQuery') {
    const { variables } = operation;
    const context = operation.getContext().graphqlContext;

    try {
      checkPermissions({ operationName, context, variables });
    } catch (err) {
      return forward(operation).map(() => {
        const error = new ForbiddenError('Access denied');
        return { errors: [error], data: null };
      });
    }
  }
  return forward(operation);
});
...