我们有一个具有多个用户和一个复杂权限系统的沙发应用程序。
我们的模型有两种:Foo和bar。
用户具有对自己的Foo and Bar的管理员访问权限,并且可以查看,更改和删除其他人的Foo and bar。
例:
用户Sabrina具有以下模型:
Foo {
_id: 1
}
Foo {
_id: 2
}
Bar {
_id:1
}
Bar {
_id:2
}
当然,实际模型是较大的文档。
她想让Giulia拥有对她的Foos的读取权限,并拥有对她的第一个酒吧的读写权限。她还希望朱莉娅(Giulia)无法看到她的第二个酒吧。
我们如何在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”的新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处理。
最佳答案
您的设计很好。从您的问题来看,您似乎想要文档级身份验证。
couchdb对单个文档不提供任何保护,因此
剩下的唯一选择是按数据库对文档进行分区,并对其设置读写权限。
有两种选择。最简单的一种是使用
rcouch's validate docs on read。我也不是
当然可以,但是我认为rouch db 2.0中的所有功能都已合并,因此,如果您愿意稍等片刻,可以使用couchdb 2.0(现在应该随时可以使用!)。
另一种方法是在_users数据库中执行您正在执行的操作。在_users
数据库中,您可以
创建用户并使用_sessions
api对其进行身份验证。这就是它的工作方式。
您创建的每个新用户都将进入_users
数据库。
在用户文档中,您可以存储允许用户查看哪些文档的列表,或者如果您是
担心单个用户文档将变得太大,然后仅存储指向包含以下内容的数据库的指针:
用户可以查看的实际列表。
首先使用_sessions
api对用户进行身份验证,然后获取用户被授权的文档列表
阅读或编辑。
最后,获取这些文档并将其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});
}
}
日志功能将在日志文件中以及在正在运行的控制台上打印一条日志消息,以便您可以自己查看更新函数被调用了多少次。如果您可以共享结果,将是很好的:)