GraphQL解析器用于将GraphQL查询解析为实际数据。在这个GraphQL教程中,你将学习如何为这些解析器设置一个GraphQL中间件,以处理授权和权限。下面的代码片段显示了一个带有参数的GraphQL解析器,它在数据库中创建了一个新实体:
export default {
Mutation: {
createFreeCourse: async (
parent,
{ courseId, bundleId },
{ me }
) => {
await createCourse({
uid: me.uid,
courseId,
bundleId,
amount: 0,
paymentType: 'FREE',
});
return true;
},
},
};
在这种情况下,一个用户创建了一个具有GraphQL突变的课程,称为createFreeCourse 。它从解析器的函数参数中获取一些参数,也从解析器的上下文中获取用户本身。现在,如果一个用户没有经过认证,就不应该能够访问数据库。
export default {
Mutation: {
createFreeCourse: async (
parent,
{ courseId, bundleId },
{ me }
) => {
if (!me) {
return new Error('Not authenticated as user.');
}
await createCourse({
uid: me.uid,
courseId,
bundleId,
amount: 0,
paymentType: 'FREE',
});
return true;
},
},
};
对于一个有很多解析器的大型GraphQL服务器来说,这种授权检查会发生很长时间。为了摆脱这种手工工作,我们可以在另一个文件中用graphql-resolvers 包为这个和所有其他解析器写一个中间件函数。
import { skip } from 'graphql-resolvers';
export const isAuthenticated = (parent, args, { me }) =>
me ? skip : new Error('Not authenticated as user.');
毕竟,这个中间件函数只是另一个GraphQL解析器。我们可以在我们以前的解析器中导入它,并将它与graphql-resolvers 包结合起来,成为一个受保护的解析器(也称为防护解析器)。
import { combineResolvers } from 'graphql-resolvers';
import { isAuthenticated } from './middleware/isAuthenticated';
export default {
Mutation: {
createFreeCourse: combine(
isAuthenticated,
async (parent, { courseId, bundleId }, { me }) => {
await createCourse({
uid: me.uid,
courseId,
bundleId,
amount: 0,
paymentType: 'FREE',
});
return true;
}
),
},
};
每次这个GraphQL解析器运行时,它都会在运行实际的解析器之前进行认证检查。让我们用另一个权限检查再进一步。首先,定义另一个解析器中间件函数:
import { skip } from 'graphql-resolvers';
export const isFreeCourse = (parent, { courseId, bundleId }) => {
const price = getPrice(courseId, bundleId);
return price === 0
? skip
: new Error('This course is not for free.');
};
其次,将它用于你的实际解析器:
import { combineResolvers } from 'graphql-resolvers';
import { isAuthenticated } from './middleware/isAuthenticated';
import { isFreeCourse } from './middleware/isFreeCourse';
export default {
Mutation: {
createFreeCourse: combine(
isAuthenticated,
isFreeCourse,
async (parent, { courseId, bundleId }, { me }) => {
await createCourse({
uid: me.uid,
courseId,
bundleId,
amount: 0,
paymentType: 'FREE',
});
return true;
}
),
},
};
正如你所看到的,它并没有以两个组合的解析器结束。你可以在堆栈中添加更多的权限和授权处理,以获得更详细的权限。此外,你可以把它们作为独立的或组合的解析器进行测试。