2010年2月28日日曜日

CouchApp !code macro recursion.

I wrote the patch about !code macro behavior several months ago. and now an official topic branch was created by jchris's gread help.

Please check it out from http://github.com/couchapp/couchapp/tree/recursive-macros.

This should be helpful for making your javascript library more flexible.

Here is an example:

approot/lib/a.js is:

// !code b.js
function a(){};

approot/lib/b.js is:

function b(){};

and approot/show/test.js is:

function(doc, req){
   // !code lib/a.js
   ..
}

The current version of couchapp deploys the approot/_show/test as:

function(doc, req){
   // !code b.js
   function a(){};
   ..
}

b.js is not extracted by !code macro.

After applying my patch, the deployed code is:

function(doc, req){
   function b(){};
   function a(){};
   ..
}

2010年2月21日日曜日

Secure programming in CouchDB applications - View protection.

I wrote secure programming notes for CouchDB applications. This is written in Japanese, so I've started the translation into English.

--

The first topic is about "View protection" in CouchDB.

For example, we prepare the view as follows.

function(doc){
  emit([doc.owner, doc.created_at], doc.protected);
}

The result of this view will be as follows.

{ "total_rows": 1234, "offset", 0, "rows": [
{"id" : "...", "key": ["user1", "2009/01/01"], value: {...}},
{"id" : "...", "key": ["user1", "2009/01/01"], value: {...}},
{"id" : "...", "key": ["user1", "2009/01/02"], value: {...}},
{"id" : "...", "key": ["user2", "2009/01/02"], value: {...}},
{"id" : "...", "key": ["user2", "2009/01/02"], value: {...}},
...
]}

If we have a security requirment that only document owner can view the doc.protected field, this view should be handled carefully. The current CouchDB view implemetation has no authentication function so that authorization function cannot be implemented.

So how do we solve this requirement?

The answer is:

  • to use a reverse proxy to forbid direct view access.
  • to use _list functions for view result processing.

And we need to check parameters in our list function.

function(head, req){
  // !code vendor/json/json2.js
  var startkey = JSON.parse(req.query.startkey || "[]");
  var endkey   = JSON.parse(req.query.endkey || "[]");
  if(startkey[0] == endkey[0] &&  
     startkey[0] == req.userCtx.name ){
     while(row == getRow()){
        // row.key[0] == req.userCtx.name is always true.
     }
  }else{
     // not authorized     
  }
}

First entry.

This is a test.