Loopback中的访问控制包括过滤器

时间:2016-11-24 18:46:46

标签: angularjs node.js loopbackjs strongloop

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

  • 读者有很多书
  • Reader有很多笔记
  • Book有很多笔记
  • 注意属于Reader
  • 注意属于Book

我想要实现的是使用属于Book和Reader的填充Notes来查询已登录Reader的所有Books。

Api电话会是这样的:

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

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

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

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

这个acl to Note model

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

适用于此类调用

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

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

任何帮助都非常感激。

1 个答案:

答案 0 :(得分:0)

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

假设用户详细信息存储在User模型

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删除回调地狱。