使用couchdb的高级权限

Mat*_*ppo 7 permissions authorization couchdb couchapp

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

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

例:

用户Sabrina有这些模型:

Foo {
  _id: 1
}
Foo {
  _id: 2
}
Bar {
  _id:1
}
Bar {
  _id:2
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

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

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

sabrina-foos数据库与创建_security文档授权访问角色sabrina:admin,sabrina:foos:read,sabrina:foos:write.

sabrina-foos数据库与验证功能,它允许写访问角色创建sabrina:admin,sabrina:foos:write.

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

当Sabrina创建一个名为"Bar 1"的新Bar时,我们会创建一个新sabrina-bar_1数据库.

sabrina-bar_1数据库与_security文件授权访问角色创建sabrina:admin,sabrina:bar_1:read,sabrina:bar_1:write

sabrina-bar_1数据库与验证功能,它允许写访问角色创建sabrina:admin,sabrina:bar_1:write.

当然,作为CouchApp,数据库的创建和用户模型的编辑由Node Process处理.

Aks*_*rma 7

你的设计很好。从您的问题来看,您似乎想要文档级别的身份验证。couchdb 不对单个文档提供保护,因此剩下的唯一选择是按数据库对文档进行分区并对其设置读写权限。

有两种选择。最简单的方法是在 read 上使用 rcouch 的验证文档。我不太确定,但我认为在 couch db 2.0 中,所有 rouch 的功能都已合并,因此如果您愿意等一下,您可以使用 couchdb 2.0(现在应该随时发布!)。

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

  1. 您创建的每个新用户都将进入_users数据库。
  2. 在用户文档中,您可以存储允许用户查看哪些文档的列表,或者如果您担心单个用户文档会变得太大,那么只需存储一个指向可能包含用户可以查看的实际列表的数据库的指针.
  3. 首先使用_sessionsapi 对用户进行身份验证,然后获取用户有权阅读或编辑的文档列表。
  4. 最后获取这些文档并将show其提供给用户。

这种方法的优点是您将需要最少 2 个,最多 3 个 http 查询。一个进行身份验证并获取指向列表的指针。其次获取要获取的实际文档列表。第三个来获取那些文件。作为回报,您的架构得到了极大的简化。

_users数据库的一个非常酷的特性是您可以在配置中增加身份验证缓存大小以将_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});
    }
}
Run Code Online (Sandbox Code Playgroud)

log 函数将在日志文件中打印一条日志消息,也在运行 couchdb 的控制台上打印一条日志消息,这样您就可以亲眼看到更新函数被调用了多少次。如果你能分享结果会很好:)