CouchDB write/read 仅限(无编辑)用户

CouchDB write/read only (no edit) user

Toolchain/frameworks

我正在使用 django==2.1.3python-cloudant==2.1.3 以及 运行 CouchDB ver. 2.2.0,几乎完成了 setup/configuration 到 Fauxton 的所有工作.我喜欢认为我大体上了解自己的方式 python/django,并且我正在一个小项目中测试这种方法以了解它是如何工作的

问题描述

假设我有一个相当简单的 CRUD 应用程序,只有 1 个模型:

class Asset(models.Model):
    asset_id = models.CharField(max_length=32)
    asset_name = models.CharField(max_length=32)

我有一个用于创建资产的视图

class CreateAssetView(views.View):
    def get(self, request, *args, **kwargs):
        #some code here


    def post(self, request, *args, **kwargs):
        #some code here|
        #log request data into database
        client = CouchDB('myusername', 'mypassword', url='http://127.0.0.1:5984', connect=True)
        db = client['assets']

        log_data = {'view_name': self.view_name, 'post_data': post_data,'user': request.user.username,
                    'time': str(timezone.now())}
        db.create_document(log_data)
        return render(...)

我知道我应该使用中间件(我计划这样做)来完成日志记录部分,并且在这种情况下可能只使用 django 的 CreateView,我现在只是在早期开发期间使用这种方法.

我遇到的问题是创建一个具有 myusernamemypassword 权限的用户:

  1. 写新文件
  2. 阅读旧文档
  3. 未编辑 已创建文档

我什至可以只接受 1 和 3(并且只使用管理员阅读)。我花了一点时间玩弄 Fauxton 的权限界面,但我基本上只能创建一个 user 并分配一个 role (甚至无法分配一个密码 :/)

澄清

Asset不是CouchDB文件,那是正常的SQL模型,我只想把有post数据的日志转储到CouchDB

任何help/gudiance/documentation指点将不胜感激

概览

Couchdb 具有一级 administrator setup in configuration instead of setup in the _users 数据库并分配了 _admin 权限以防止任何被锁定的可能性。

然后每个单独的数据库都有一个粗略的级别 security policy 2 个级别:

  1. 管理员
  2. 成员

指定方式:

  1. 名字
  2. 角色

创建 4 个字段。

对于数据库可以包含的两种类型的文档,这些级别控制访问的方式略有不同:

  1. id: _design/* - 设计文档可以包含将在某些上下文中执行的函数
  2. id: other - 普通文档就是普通数据

两个级别的数据库访问权限都具有对数据库中所有文档的读取权限,但管理员对 _design 文档具有写入权限。对普通文档的写入权限通常授予所有被授予对数据库的任何访问权限的用户,但可以受到 validate design documents.

的限制

总结

设置唯一安全策略的过程是:

  1. 在设置 _users 时以消费者身份体验提供的验证设计文档。
  2. 设置新数据库及其基本安全性,为您的用户提供成员访问权限。
  3. 使用限制成员写访问的验证函数将设计文档添加到新数据库。

1 设置 _users 条目

为用户添加角色

作为管理员将 role: ["logger"] 添加到用户文档并保存,请注意,由于默认 _users 设计文档的这一部分,这必须由管理员完成:

        // DB: _users doc: _design/_auth
        function(newDoc, oldDoc, userCtx, secObj) {
        ..
        if (oldRoles.length !== newRoles.length) {
            throw({forbidden: 'Only _admin may edit roles'});
        }

更改用户密码。

管理员或用户都可以通过在文档中设置 password:"mynewpassword" 来更改密码(在保存过程中 couchdb 将转换为 hashed/salted 密码)。这适用于用户,因为他们可以 add/modify 除了他们的姓名和角色之外的字段,只要用户正在编辑他们自己的文档:

        // DB: _users doc: _design/_auth
        function(newDoc, oldDoc, userCtx, secObj) {
        ..
        if (userCtx.name !== newDoc.name) {
            throw({
                forbidden: 'You may only update your own user document.'
            });
        }
        // then checks that they don't modify roles

您可以对分配了 adminlogger 角色的用户重复此过程,以创建您分配权限的委派管理员可以重新配置数据库,或者您可以继续使用 couchdb 管理员及其 _admin 所有管理的角色。

2 设置新数据库及其基本安全性

创建一个名为 logger 的数据库 为记录器分配 security policy:

{
    "admins": {
        "names": [

        ],
        "roles": [
            "adminlogger"
        ]
    },
    "members": {
        "names": [

        ],
        "roles": [
            "logger"
        ]
    }
}

3。在新数据库

中新建一个validate design document

作为 _admin 用户或具有 adminlogger 角色的用户,通过复制 _users 设计文档、删除 _rev 并修改函数来创建新的验证设计文档:

// DB: logger doc: _design/auth
function(newDoc, oldDoc, userCtx, secObj) {
     // Don't let non-admins write a pre-existing document:
     if (!is_server_or_database_admin()) {
          if (!!oldDoc) {
              throw({
                forbidden: 'You may not update existing documents.'
            });
          }
     }
     // Where the function to define admins can be copied verbatim from the doc:
     var is_server_or_database_admin = function(userCtx, secObj) {
        // see if the user is a server admin
        if(userCtx.roles.indexOf('_admin') !== -1) {
            return true; // a server admin
        }

        // see if the user a database admin specified by name
        if(secObj && secObj.admins && secObj.admins.names) {
            if(secObj.admins.names.indexOf(userCtx.name) !== -1) {
                return true; // database admin
            }
        }

        // see if the user a database admin specified by role
        if(secObj && secObj.admins && secObj.admins.roles) {
            var db_roles = secObj.admins.roles;
            for(var idx = 0; idx < userCtx.roles.length; idx++) {
                var user_role = userCtx.roles[idx];
                if(db_roles.indexOf(user_role) !== -1) {
                    return true; // role matches!
                }
            }
        }

        return false; // default to no admin
    }
}    

如果您遵循这些步骤,那么您在步骤 1 中赋予记录器角色的用户可以 运行 您的代码仅在步骤 2 和 3 中配置的记录器数据库中写入新文档。