couchbaselabs / couchbaselabs/walrus

Walrus map function does not copy emit data

Open
#13 0 comments 0 reactions 0 assignees View on GitHub
icebox
Dominant language
Go
Stars
28
Forks
9
PR merge metrics
No merged PRs in 30d

Description

Sync Gateway allows users to define their own map/reduce functions via the REST API.

To enforce read access security, Sync Gateway wraps the user function with a boilerplate map function. In this wrapper the document metadata doc._sync (inclueds security info) is removed from the document being mapped before calling the user custom map function, this prevents users from accessing security info about the document. The metadata doc._sync is re-inserted once the custom map function has returned.

On Couchbase Server, the emitted data appears in the view without the doc._sync property, but in Walrus it contains the metadata that was re-inserted after the custom map function returned.

To be fully compatible with CBS Walrus should copy the data passed in the emit function to avoid unexpected side effects by code called, in the map function, after emit().

Here is an example of a Sync Gateway custom function that exhibits this behaviour, the doc is emitted as the value from the custom map function 'emit(doc.age, doc)', the doc._sync metadata is re-inserted into the doc on the last line of the wrapper map function.

```
function(doc,meta) {

var sync = doc._sync;
if (sync === undefined || meta.id.substring(0,6) == "_sync:")
return;
if ((sync.flags & 1) || sync.deleted)
return;

var channels = [];
var channelMap = sync.channels;

if (channelMap) {
for (var name in channelMap) {
removed = channelMap[name];
if (!removed)
channels.push(name);
}
}

delete doc._sync;

meta.rev = sync.rev;
meta.channels = channels;

var _emit = emit;
(function(){
var emit = function(key,value) {
_emit(key,[channels, value]);
};
(function (doc, meta) { emit(doc.age, doc); }) (doc, meta);
}());

doc._sync = sync;
}
```

When the view is queried against a Walrus bucket the _sync property is present the returned rows

```
curl -X GET http://localhost:4985/db/_design/myviews/_view/by_age?stale=false
{"total_rows":2,"rows":[{"id":"doc2","key":7,"value":{"_sync":{"history":{"channels":[null],"parents":[-1],"revs":["1-f78569a6b0bd14dfe1f89f4b42b396a7"]},"recent_sequences":[3],"rev":"1-f78569a6b0bd14dfe1f89f4b42b396a7","sequence":3,"time_saved":"2015-09-09T14:57:09.233664177+01:00"},"age":7,"fname":"Bob","lname":"Seven"}},{"id":"doc1","key":10,"value":{"_sync":{"history":{"channels":[null],"parents":[-1],"revs":["1-1ff953c722da99b1d916e2ccc84d9f9b"]},"recent_sequences":[2],"rev":"1-1ff953c722da99b1d916e2ccc84d9f9b","sequence":2,"time_saved":"2015-09-09T14:57:01.596081379+01:00"},"age":10,"fname":"Alice","lname":"Ten"}}],"Collator":{}}
```

Querying the same view against a CBS bucket, the _sync property is not present in the returned rows

```
{"total_rows":2,"rows":[{"id":"doc2","key":7,"value":{"age":7,"fname":"Bob","lname":"Seven"}},{"id":"doc1","key":10,"value":{"age":10,"fname":"Alice","lname":"Ten"}}],"Collator":{}}
```

Contributor guide

No contributing guide indexed for this repository

Research direction

Trace Walrus's view map/reduce handling, focusing on how values passed to emit are stored and later returned by a view query. Reproduce the custom map function example against a Walrus bucket, compare its emitted value with the Couchbase Server result, and consider the issue done when reinserted doc._sync metadata no longer appears in the emitted row.

Written by the indexing model from the issue text.

Assessment

Tech stack
go
Domain
databases
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.