Как вернуть ответ об ошибке в ссылке apollo?

Я использую ссылку 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 класс, но пока мне не удалось вернуть ошибку

2 ответа

Не знаю, нужно ли это кому-то еще, но я пытался получить NetworkError конкретно в onErrorобратный вызов с использованием Typescript и React. Наконец-то заработало:

      const testLink = new ApolloLink((operation, forward) => {
    let fetchResult: FetchResult = {
        errors: [] // put GraphQL errors here
    }

    let linkResult = Observable.of(fetchResult).map(_ => {
        throw new Error('This is a network error in ApolloClient'); // throw Network errors here
    });
    return linkResult;
});

Возвращать ошибки GraphQL в наблюдаемом FetchResultответ, а выдача ошибки в наблюдаемом обратном вызове вызовет NetworkError

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

В основном я звонил 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);
});
Другие вопросы по тегам