Graphql - 通用权限保护
Graphql - universal permission guards
我正在尝试在 graphql backend using 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, async (_, { 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 (_, { id }, { 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, async (_, { id }) => {
try {
const notification = await Notification.findById(id);
return notification;
} catch (error) {
throw error;
}
})
task: combineResolvers(isOwner, async (_, { 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
curried 方法.
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;
}
})
},
};
我正在尝试在 graphql backend using 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, async (_, { 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 (_, { id }, { 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, async (_, { id }) => {
try {
const notification = await Notification.findById(id);
return notification;
} catch (error) {
throw error;
}
})
task: combineResolvers(isOwner, async (_, { 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
curried 方法.
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;
}
})
},
};