问题描述
我正在尝试使用 graphql 在 apollo server 后端实现权限保护。以下代码有效:
解析器
const Notification = require('../../database/models/notifications');
const Task = require('../../database/models/tasks');
notification: combineResolvers(isNotificatioNowner,async (_,{ id }) => {
try {
const notification = await Notification.findById(id);
return notification;
} catch (error) {
throw error;
}
})
task: combineResolvers(isTaskOwner,{ id }) => {
try {
const task = await Task.findById(id);
return task;
} catch (error) {
throw error;
}
})
解析器中间件(权限保护)
const Notification = require('../../database/models/notifications');
const Task = require('../../database/models/tasks');
// userId is the id of the logged in user retrieved from the context
module.exports.isNotificatioNowner = async (_,{ id },{ userId }) => {
try {
const notification = await Notification.findById(id);
if (notification.user.toString() !== userId) {
throw new ForbiddenError('You are not the owner');
}
return skip;
} catch (error) {
throw error;
}
}
module.exports.isTaskOwner = async (_,{ userId }) => {
try {
const task = await Task.findById(id);
if (task.user.toString() !== userId) {
throw new ForbiddenError('You are not the owner');
}
return skip;
} catch (error) {
throw error;
}
}
这样下去会产生很多重复的代码,感觉不是很 DRY。因此,我正在尝试创建一个更通用的解决方案,到目前为止没有任何效果。
我的尝试:
解析器
const Notification = require('../../database/models/notifications');
const Task = require('../../database/models/tasks');
notification: combineResolvers(isOwner,{ id }) => {
try {
const notification = await Notification.findById(id);
return notification;
} catch (error) {
throw error;
}
})
task: combineResolvers(isOwner,{ id }) => {
try {
const task = await Task.findById(id);
return task;
} catch (error) {
throw error;
}
})
解析器中间件
const Notification = require('../../database/models/notifications');
const Task = require('../../database/models/tasks');
module.exports.isOwner = async (_,{ id,collection },{ userId }) => {
try {
const document = await collection.findById(id);
if (document.user.toString() !== userId) {
throw new ForbiddenError('You are not the owner');
}
return skip;
} catch (error) {
throw error;
}
}
我无法将集合名称作为参数传递给中间件解析器。
如果能提供任何帮助,我将不胜感激!
解决方法
根据您的代码,您似乎正在寻找使 isOwner
成为 higher-order function,以便您可以传入集合,并且它 returns
柯里化方法。
module.exports.isOwner = (collection) => {
return async (_,{ id },{ userId }) => {
try {
const document = await collection.findById(id);
if (document.user.toString() !== userId) {
throw new ForbiddenError('You are not the owner');
}
return skip;
} catch (error) {
throw error;
}
}
}
用法:
const resolvers = {
Query: {
task: combineResolvers(isOwner(Task),async (_,{ id }) => {
try {
const task = await Task.findById(id);
return task;
} catch (error) {
throw error;
}
})
},};