在CouchDB中复制安全性和用户表的好方法

时间:2015-02-25 09:36:52

标签: database couchdb replication

在我们的场景中,我们将本地CouchDB连接到生成数据的node.js服务器。数据包括用户及其对此数据库中某些表的访问权限。

应将此本地CouchDB实例复制到云中的远程CouchDB,包括每个数据库的表 _users和_security 中指定的用户和安全规则。

将所有数据复制到远程CouchDB可以正常工作,但问题是:

  • 只有服务器和数据库管理员才能创建用户。因此,复制任务需要管理员凭据。如果没有其他解决方案,我认为我可以忍受。

  • _security文档是无版本的,因此无法复制。

即使本地CouchDB实例在用户创建时处于脱机状态,是否有一种保持两个数据库同步的好方法。 (用户和安全)。

更新

我想到的一种方法是在服务器上创建一个设计文档,每次创建新用户时都会调用该文档。然后,此函数为新创建的用户创建新数据库,并将用户名添加到_security规则。

我希望避免服务器上的其他应用程序收听 _changes Feed并对新的更新采取行动。

2 个答案:

答案 0 :(得分:0)

  

我想到的一种方法是在服务器上创建一个设计文档,每次创建新用户时都会调用该文档。然后,此函数为新创建的用户创建新数据库,并将用户名添加到_security规则。

有一个名为couch per user的插件可以让你做到这一点。安装它,对于_users数据库中的每个新user,它将自动为该用户创建一个数据库。

你是对的_security文件没有版本。但是常规文件是。因此,如果将_security对象存储为常规couchdb文档,则可以解决复制它们的问题。现在我们需要确保的是,当复制包含_security对象的文档时,它会自动添加到目标数据库的_security中。

如果您认为验证功能为"更新前"事件处理程序然后他们可以用于此任务。我们需要做的是

  1. 创建一个查找包含_security对象的文档的验证函数。
  2. 找到对象后,向数据库的_security字段发出http请求,并在其中存储对象的内容。
  3. "通行证"包含_security的对象,因此它保存在本地数据库中。
  4. 现在默认的javascript验证功能无法进行http调用,因此您需要更改query server。我知道至少erlang和python查询服务器允许你进行http调用。但首先尝试用你最喜欢的语言。

    示例: -

        {
        _id:adsfasf,
        _rev:3-bd25f9790db7a8034d9415da7a4d625,
        "type":"security",
        _security: 
        {
            "admins": {
                "names": [
                    "superuser"
                ],
                "roles": [
                    "admins"
                ]
            },
            "members": {
                "names": [
                    "user1",
                    "user2"
                ],
                "roles": [
                    "developers"
                ]
            }
        }
    
        }
    }
    

    验证功能

    function(newDoc,oldDoc,userCtx,secObj){
    
    if(newDoc.type ==="security"){
    //make an http call to db/_security and post the _security field there
    
      }
    }
    

    您不需要以这种方式收听更改Feed。只需使用普通的couchdb文档和验证函数的组合(在不同的查询服务器中),您就可以执行所需的操作。

    效果问题

    拥有验证功能肯定会减慢插入时间,因为它会在插入之前对每个couchdb文档执行检查。

    Erlang验证功能将是不同查询服务器中速度最快,资源效率最高的功能。在erlang中编写它不是太困难,因为它只是一个if块和一个http请求。这个例子未经测试,但它应该让你开始。

    fun({N_Doc},_Old_Doc,_User,_Sec)->
        case proplists:get_value(<<"type">>,N_Doc) of 
            <<"_serurity">>-> 
               httpc:request(
                   post,
                   {"http://localhost:5984/yourdb/_security", 
                    [], 
                    "application/json",
                    ejson:encode(proplists:get_value(<<"_security">>))},
                   [],[]),
                 1;
        <<"some_bad_value">>->
            {[{<<"forbidden">>, "Nope this won't do"}]};
        _->
           1
        end
    end.
    

    上面的函数只是等待类型&#34; security&#34;的文档。并将其发布到数据库的_security端点。 1回复意味着每件事都没问题。该文档已经过验证,现在可以存储。禁止响应不允许存储文档。希望这可以帮助。

答案 1 :(得分:0)

我刚刚发布了一个名为replicate-couchdb-cluster的新工具,它提供了一种容错方式来复制整个数据库集群。它还允许并发,因此可以大大加快复制群集所需的时间。

您还可以使用docker image轻松设置连续复制。

我希望这有帮助!