我们有一个拥有多个用户和复杂权限系统的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:admin
,sabrina:foos:read
,sabrina:foos:write
的访问权限。
使用验证功能创建sabrina-foos
数据库,该功能允许对角色sabrina:admin
,sabrina:foos:write
进行写访问。
当Sabrina决定让Giulia看到她的抱负时,我们给Giulia一个角色sabrina:foos:read
当Sabrina创建一个名为“Bar 1”的新栏时,我们会创建一个新的sabrina-bar_1
数据库。
使用_security文档创建sabrina-bar_1
数据库,授予对角色sabrina:admin
,sabrina:bar_1:read
,sabrina:bar_1:write
使用验证功能创建sabrina-bar_1
数据库,该功能允许对角色sabrina:admin
,sabrina:bar_1:write
进行写访问。
当然,作为CouchApp,数据库的创建和用户模型的编辑由节点流程处理。
答案 0 :(得分:4)
你的设计很好。从您的问题看起来您想要文档级别身份验证。 couchdb对单个文档没有任何保护,所以 唯一的选择是按数据库对文档进行分区,并对它们设置读写权限。
有两种选择。最简单的就是使用 rcouch's validate docs on read。我也不是 当然,但我认为在沙发db 2.0中所有的rouch功能都已合并,所以如果你愿意等一下,你可以使用couchdb 2.0(现在应该在任何时候出来!)。
另一种方法是在_users数据库中执行您正在执行的操作。在_users
数据库中,您可以
创建用户并使用_sessions
api对其进行身份验证。所以这是它将如何工作。
_users
数据库。 _sessions
api对用户进行身份验证,然后获取用户获得授权的文档列表
阅读或编辑。 show
提取给用户。 此方法的优点是您需要至少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,这样您就可以自己查看调用更新函数的次数。如果你能分享结果会很好:)