Как вернуть ответ об ошибке в ссылке 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);
});