我正在模式拼接中使用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
的{{1}}根据用户角色返回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
类,但是到目前为止,我还没有成功返回错误
答案 0 :(得分:0)
经过一些挖掘,我实际上已经弄清楚了。但是我不确定我的方法是否正确。
基本上,我用随后的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);
});