【问题标题】:Access control in Loopback include filterLoopback 中的访问控制包括过滤器
【发布时间】:2017-04-09 03:26:37
【问题描述】:

假设我在 Loopback 中有三个模型:Reader、Book 和 Note。 Reader是User的一个实例,可以登录。关系是这样的:

  • 读者有很多书
  • 读者有很多笔记
  • 书有很多注释
  • 笔记属于读者
  • 笔记属于书

我想要实现的是查询登录阅读器的所有书籍,其中填充了属于书籍和阅读器的注释。

API 调用如下所示:

 /api/reader/me/books?filter[include]=notes

但这会返回属于 Book 的所有笔记,无论它们是否属于 Reader。我可以在 api 调用中添加另一个过滤器,但我需要在服务器端过滤 Notes,以便读者无法访问其他读者的笔记。

我已尝试将此访问控制添加到 Book 模型:

{
  "principalType": "ROLE",
  "principalId": "$owner",
  "permission": "ALLOW",
  "property": "__get__notes"
}

还有这个 acl to Note 模型

[
    {
      "principalType": "ROLE",
      "principalId": "$everyone",
      "permission": "DENY"
    }, {
      "principalType": "ROLE",
      "principalId": "$owner",
      "permission": "ALLOW",
      "property": "*"
    }
]

这样的调用效果很好

 /api/reader/me/books/<bookId>/notes

但不适用于包含过滤器的第一次调用。我应该怎么做才能只在书中填写读者笔记?

非常感谢任何帮助。

【问题讨论】:

  • 我有一个类似的问题,我需要基于每个实例而不是 SL 中使用的每个模型来限制或允许访问。不幸的是,我没有找到合适的方法来做到这一点,不得不实现我自己的授权层。但是,您可以做的一件事是在 afterRemote 钩子上进行简单的过滤,这样您就可以进行某种集合减法以仅返回您可以访问的那些实例。就我而言,这是不可能的,因为我需要用户 B 可以访问用户 A 的实例。但这不是你的情况,所以它可能会起作用。
  • 你可以在这里阅读文档 - loopback.io/doc/en/lb2/Remote-hooks.html - 虽然它不是直截了当,而且可能效率不高

标签: angularjs node.js loopbackjs strongloop


【解决方案1】:

要实现这一点,您必须创建一个远程方法。您必须在应用程序级别应用过滤器。

假设用户详情为 Store in User model

module.exports = function(Reader){

    var async = require('async');
    Reader.fetchBooks = function(userId, callback){
        var app = this.app;
        var updatedReaderList = [];
        Reader.find({
            where: {userId: userId },
            include: {relation: "books"} 
        }, function(err, readerList){
            if(err){
                return callback(err);
            }
            if(readerList){
                if(readerList.length){
                   var series = []; 
                   readerList.forEach(function(reader){
                      var readerObj = reader.toJSON();
                      updatedReaderList.push(readerObj);
                      if(readerObj.books){
                          readerObj.books.forEach(function(book){
                              series.push(function(callback){
                                fetchNotes(app, book, readerObj.id, callback);
                              });
                          } 
                      }
                   });

                  //Now save the data in series..
                  async.series(series, function(err){
                      if(err){
                          callback(err);
                      }else{

                          //Now send the callback
                          callback(null, updatedReaderList);
                      }
                  });

                }else{
                  callback(null, [])
                }
            }else{
              callback(null, [])
            }
        });


    };

    var fetchNotes = function(app, book, readerId, callback){
        var Note = app.models.Note;
        //Fetch only those note whose reader id belongs to current reader and book belongs to same one.
        Note.find({
          where: {
            readerId: readerId,
            bookId: book.id
          }
        }, function(err, noteList){
          if(err){
            return callback(err);
          }else{
            if(noteList){
              book.notes = noteList;
            }
          }
        });
    };
}

现在您可以限制所有其他方法并简单地允许此远程方法。

{
  "principalType": "ROLE",
  "principalId": "$owner",
  "permission": "ALLOW",
  "property": "fetchBooks"
}

注意:你可以使用 promise 来移除回调地狱。

【讨论】:

    猜你喜欢
    • 2015-05-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多