Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CouchDB: Restricting users to only replicating their own documents

Tags:

couchdb

I'm having trouble finding documentation on the request object argument used in replication filters ('req' in the sample below):

function(doc, req) {
  // what is inside req???
  return false;
}

This old CouchBase blog post has a little code snippet that shows the userCtx variable being a part of the request object:

What is this userCtx? When you make an authenticated request against CouchDB, either using HTTP basic auth, secure cookie auth or OAuth, CouchDB will verify the user’s credentials. If they match a CouchDB user, it populates the req.userCtx object with information about the user.

This userCtx object is extremely useful for restricting replication of documents to the owner of the document. Check out this example:

function(doc, req) {
  // require a valid request user that owns the current doc
  if (!req.userCtx.name) {
    throw("Unauthorized!");
  }
  if(req.userCtx.name == doc.owner) {
    return true;
  }
  return false;
}

But the problem now is that CouchDB requires the filter method to be explicitly chosen by the initiator of the replication (in this case, the initiator is a mobile user of my web app):

curl -X POST http://127.0.0.1:5984/_replicate \
-d '{"source":"database", \
     "target":"http://example.com:5984/database", \
     "filter":"example/filtername"
     }'

The Question

Is there a way to enforce a specific filter by default so that users are restricted to replicating only their own data? I'm thinking the best way to do this is to use a front end to CouchDB, like Nginx, and restrict all replication requests to ones that include that filter. Thoughts? Would love a way to do this without another layer in front of CouchDB.

like image 303
pokstad Avatar asked Oct 07 '12 22:10

pokstad


People also ask

How does CouchDB replication work?

Replication Procedure. During replication, CouchDB will compare the source and the destination database to determine which documents differ between the source and the destination database. It does so by following the Changes Feeds on the source and comparing the documents to the destination.

Is CouchDB an acid?

ACID Properties. The CouchDB file layout and commitment system features all Atomic Consistent Isolated Durable (ACID) properties. On-disk, CouchDB never overwrites committed data or associated structures, ensuring the database file is always in a consistent state.

Which lock model CouchDB uses while updating?

No read locks CouchDB uses MVCC (Multi-Version Concurrency Control) to manage access to databases concurrently. This means that regardless of current database loads, CouchDB can run at full speed and without restrictions to its users.

Where is CouchDB data stored?

By default, the database files are located under /var/lib/couchdb directory (this location will be specified in the couchdb config file under /etc/couchdb directory). In CouchDB, each database is wholly contained in a single append-only file.


1 Answers

Data replication stands right with user ability to read data. Since if your users shares data within single database all of them has right to replicate all of them to their local couches. So you couldn't apply any documents read restriction unless you've split single shared database into several personal ones - this is common use case for such situations.

There is no any way to enforce apply changes feed filter or other parameters like views has. However, you can use rewrites to wraps requests to some resources with predefined query parameters or even with dynamic ones. This is a little not solution that you'd expected, but still better that nginx and some logic at his side: probably, you'd to allow users to specify custom filters with custom query parameters and enforce you're own only if nothing specified, right?

P.S. Inside req object is very useful about current request. Partially it was described at wiki, but it's a little out of date. However, it's easily to view it with simple show function:

function(doc, req){
    return {json: req}
}
like image 109
Kxepal Avatar answered Oct 01 '22 11:10

Kxepal