couchdb-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Adam Kocoloski <adam.kocolo...@gmail.com>
Subject Re: New Security and Validation Features
Date Wed, 03 Dec 2008 18:55:09 GMT
On Nov 21, 2008, at 5:12 PM, Damien Katz wrote:

> -Authorization/Validation-
>
> Each design document can contain a document update validation  
> function. Like views, these can be in any language. The language is  
> set at the design document level.
>
> On document update -- either via interactive update or via  
> replication -- each is run in succession. These validation functions  
> are responsible for enforcing document constraints or schemas, and  
> to enforce security.
>
> Validation functions are provided the new document, previous  
> revision of the document on disk, and the user context. The user  
> context has the users name and roles.
>
> If the document values don't pass validation, a forbidden exception  
> is returned If the user isn't allow to update the document, a  
> unauthorized exception is returned.
>
> This scheme can be used for signature based security (is the update  
> signed by an authorized user) or user based security (is the user  
> currently writing the update an authorized user).
>
> This user based example ensures that every document has an authors  
> field and when updating an existing document, you are an allowed  
> author, or a moderator:
>
> function(newDocument, previousDocument, userCtx) {
>  if (!newDocument._deleted && !newDocument.author) {
> 	throw {forbidden, "All documents must have an author specified."}
>  }
>  if (previousDocument &&
> 	previousDocument.author != userCtx.name &&
> 	userCtx.roles.indexOf("Discussion Moderator") == -1) {
> 	throw {unauthorized, "You are not the author of this document."}
>  }
> }
>
> The validation works with replication too, all updates, whether  
> interactive or replicated are validated. But the replication still  
> needs testing and might be buggy on update failures.
>
> That's all for now. Question and comments please.
>
> -Damien

Hi Damien, cool stuff.  Could we have it so that the user context  
passed to the validation function includes a role of "_admin" if the  
user's name is in the DB admins list?  Maybe something as simple as

diff --git a/trunk/src/couchdb/couch_db.erl b/trunk/src/couchdb/ 
couch_db.erl
index 7de5b8d..4eed8bc 100644
--- a/trunk/src/couchdb/couch_db.erl
+++ b/trunk/src/couchdb/couch_db.erl
@@ -231,9 +231,14 @@ validate_doc_update(_Db, #doc{id= <<"_local/",_/ 
binary>>}=Doc, _GetDiskDocFun) -
      Doc;
  validate_doc_update(#db{name=DbName,user_ctx=Ctx}=Db, Doc,  
GetDiskDocFun) ->
      DiskDoc = GetDiskDocFun(),
+    UserName = Ctx#user_ctx.name,
+    Roles = Ctx#user_ctx.roles ++ case lists:member(UserName,  
Db#db.admins) of
+        true -> [<<"_admin">>];
+        false -> []
+    end,
      JsonCtx =  {[{<<"db">>, DbName},
-            {<<"name">>,Ctx#user_ctx.name},
-            {<<"roles">>,Ctx#user_ctx.roles}]},
+            {<<"name">>,UserName},
+            {<<"roles">>,Roles}]},
      [case Fun(Doc, DiskDoc, JsonCtx) of
          ok -> ok;
          Error -> throw(Error)

Best, Adam

Mime
View raw message