couchbaselabs / couchbaselabs/walrus
Walrus map function does not copy emit data
- 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