【问题标题】:Graphql - universal permission guardsGraphql - 通用权限保护
【发布时间】:2021-08-08 03:20:29
【问题描述】:

我正在尝试使用apollo servergraphql 后端实现权限保护。以下代码有效:

解析器

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;
  }
}

这样下去会产生很多重复的代码,感觉不是很干。因此,我正在尝试创建一个更通用的解决方案,但到目前为止还没有成功。



我尝试了什么:


解析器

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;
  }
}

我无法将集合名称作为参数传递给中间件解析器。

我会非常感谢任何形式的帮助!

【问题讨论】:

    标签: graphql apollo middleware apollo-server resolver


    【解决方案1】:

    根据您的代码,您似乎正在寻找将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;
          }
        })
      },
    };
    

    【讨论】:

    • 正是我正在寻找的!非常感谢!!
    猜你喜欢
    • 2012-09-05
    • 2021-04-28
    • 2023-03-18
    • 1970-01-01
    • 2017-09-28
    • 2021-06-23
    • 1970-01-01
    • 1970-01-01
    • 2019-02-03
    相关资源
    最近更新 更多