2

我在模式拼接中使用 apollo 链接作为访问控制层。如果用户无权访问特定操作,我不太确定如何使链接返回错误响应。我知道这样的包graphql-shieldgraphql-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返回truefalse

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类,但到目前为止我还没有设法返回错误

4

2 回答 2

0

不知道其他人是否需要这个,但我试图onError使用 Typescript 和 React 在回调中专门获取 NetworkError。终于得到了这个工作:

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;
});

在 observable 响应中返回 GraphQL 错误FetchResult,而在 observable 回调中抛出错误会产生 NetworkError

于 2022-02-01T07:38:24.577 回答
0

经过一番挖掘,我实际上已经弄清楚了。但我不太确定我的方法是否正确。

基本上,我已经调用forward了一个后续的map地方,我返回一个包含errorsdata字段的对象。同样,我想有更好的方法来做到这一点(也许通过扩展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);
});
于 2018-09-25T12:59:02.117 回答