使用couchdb的高级权限

时间:2014-07-24 14:30:53

标签: permissions authorization couchdb couchapp

我们有一个拥有多个用户和复杂权限系统的couchapp应用程序。 我们的模型有两种:Foo和bar。

用户拥有自己的Foo和Bar的管理员权限,并且可以获得查看,更改和删除其他人的Foo和bar的权限。

示例:

用户Sabrina有这些模型:

Foo {
  _id: 1
}
Foo {
  _id: 2
}
Bar {
  _id:1
}
Bar {
  _id:2
}

当然,真正的模型是更大的文档。

她希望让Giulia能够阅读她的Foos,并对她的第一个酒吧进行读写访问。她还希望朱莉娅不能看到她的第二个酒吧。

我们如何在couchdb中建模这种权限?

这是我们正在使用的解决方案,但它似乎很复杂,我们想知道是否有一个更简单的解决方案:

我们有多种角色: {username}:admin:可以读取,写入和删除与用户相关的每个数据库上的所有内容 {username}:foos:read:可以读取与用户相关的foos数据库中的每个文档 {username}:foos:write:可以在foos数据库中编写与用户相关的每个文档 {username}:{bar}:read:可以读取与用户相关的Bar数据库 {username}:{bar}:write:可以编写与用户相关的Bar数据库

当Sabrina注册到应用程序时,我们会创建一个新的sabrina-foos数据库,我们会向用户Sabrina提供角色sabrina:admin

使用sabrina-foos文档创建_security数据库,授予对角色sabrina:adminsabrina:foos:readsabrina:foos:write的访问权限。

使用验证功能创建sabrina-foos数据库,该功能允许对角色sabrina:adminsabrina:foos:write进行写访问。

当Sabrina决定让Giulia看到她的抱负时,我们给Giulia一个角色sabrina:foos:read

当Sabrina创建一个名为“Bar 1”的新栏时,我们会创建一个新的sabrina-bar_1数据库。

使用_security文档创建sabrina-bar_1数据库,授予对角色sabrina:adminsabrina:bar_1:readsabrina:bar_1:write

的访问权限

使用验证功能创建sabrina-bar_1数据库,该功能允许对角色sabrina:adminsabrina:bar_1:write进行写访问。

当然,作为CouchApp,数据库的创建和用户模型的编辑由节点流程处理。

1 个答案:

答案 0 :(得分:4)

你的设计很好。从您的问题看起来您想要文档级别身份验证。 couchdb对单个文档没有任何保护,所以 唯一的选择是按数据库对文档进行分区,并对它们设置读写权限。

有两种选择。最简单的就是使用 rcouch's validate docs on read。我也不是 当然,但我认为在沙发db 2.0中所有的rouch功能都已合并,所以如果你愿意等一下,你可以使用couchdb 2.0(现在应该在任何时候出来!)。

另一种方法是在_users数据库中执行您正在执行的操作。在_users数据库中,您可以 创建用户并使用_sessions api对其进行身份验证。所以这是它将如何工作。

  1. 您创建的每个新用户都将进入_users数据库。
  2. 在用户文档中,您可以存储允许用户查看的文档列表,或者是否存在 担心单个用户文档会变得太大而只是存储一个指向可能包含该数据库的数据库的指针 用户可以查看的实际列表。
  3. 首先使用_sessions api对用户进行身份验证,然后获取用户获得授权的文档列表 阅读或编辑。
  4. 最后将这些文档及show提取给用户。
  5. 此方法的优点是您需要至少2个,最多3个http查询。一个用于验证并获取指向列表的指针。其次是获取要获取的文档的实际列表。第三,获取这些文件。作为回报,您的架构大大简化了。

    _users数据库的一个非常酷的属性是,您可以在配置中增加auth缓存大小以将_user对象保存在内存中,以便访问时间非常快。

      

    如果我有一万份文件,但我只能找到其中一份?这个函数会被称为一万次吗?

    我目前没有安装rcouch,但有一种简单的方法可以通过记录来测试: -

    function(doc, userCtx) {
        log("function called");
        if ((typeof doc.name !== 'undefined') && (doc.name != userCtx.name)) {
            throw({unauthorized: userCtx.name + ' cannnot read ' + doc._id});
        }
    }
    

    日志功能将在日志文件中打印日志消息,并且还在控制台上运行了couchdb,这样您就可以自己查看调用更新函数的次数。如果你能分享结果会很好:)