微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Graphql - 通用权限保护

如何解决Graphql - 通用权限保护

我正在尝试使用 graphqlapollo 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;
      }
    })
  },};

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。