Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

test: Wrap all views in () for CouchDB 1.1 compatibility

  • Loading branch information...
commit 6745a57abc7b2922634c58db13366a80afcd5e35 1 parent 925152d
Jyrki Pulliainen nailor authored
Showing with 134 additions and 16 deletions.
  1. +118 −0 test/couch_util.py
  2. +16 −16 test/test_client.py
118 test/couch_util.py
View
@@ -83,12 +83,102 @@ def setup():
# Got a sensible response
break
+
def teardown():
global _proc
_proc.terminate()
_proc.wait()
+_couch_1_1_user_view = """
+(
+ function(newDoc, oldDoc, userCtx) {
+ if (newDoc._deleted === true) {
+ // allow deletes by admins and matching users
+ // without checking the other fields
+ if ((userCtx.roles.indexOf('_admin') !== -1) ||
+ (userCtx.name == oldDoc.name)) {
+ return;
+ } else {
+ throw({forbidden: 'Only admins may delete other user docs.'});
+ }
+ }
+
+ if ((oldDoc && oldDoc.type !== 'user') || newDoc.type !== 'user') {
+ throw({forbidden : 'doc.type must be user'});
+ } // we only allow user docs for now
+
+ if (!newDoc.name) {
+ throw({forbidden: 'doc.name is required'});
+ }
+
+ if (newDoc.roles && !isArray(newDoc.roles)) {
+ throw({forbidden: 'doc.roles must be an array'});
+ }
+
+ if (newDoc._id !== ('org.couchdb.user:' + newDoc.name)) {
+ throw({
+ forbidden: 'Doc ID must be of the form org.couchdb.user:name'
+ });
+ }
+
+ if (oldDoc) { // validate all updates
+ if (oldDoc.name !== newDoc.name) {
+ throw({forbidden: 'Usernames can not be changed.'});
+ }
+ }
+
+ if (newDoc.password_sha && !newDoc.salt) {
+ throw({
+ forbidden: 'Users with password_sha must have a salt.' +
+ 'See /_utils/script/couch.js for example code.'
+ });
+ }
+
+ if (userCtx.roles.indexOf('_admin') === -1) {
+ if (oldDoc) { // validate non-admin updates
+ if (userCtx.name !== newDoc.name) {
+ throw({
+ forbidden: 'You may only update your own user document.'
+ });
+ }
+ // validate role updates
+ var oldRoles = oldDoc.roles.sort();
+ var newRoles = newDoc.roles.sort();
+
+ if (oldRoles.length !== newRoles.length) {
+ throw({forbidden: 'Only _admin may edit roles'});
+ }
+
+ for (var i = 0; i < oldRoles.length; i++) {
+ if (oldRoles[i] !== newRoles[i]) {
+ throw({forbidden: 'Only _admin may edit roles'});
+ }
+ }
+ } else if (newDoc.roles.length > 0) {
+ throw({forbidden: 'Only _admin may set roles'});
+ }
+ }
+
+ // no system roles in users db
+ for (var i = 0; i < newDoc.roles.length; i++) {
+ if (newDoc.roles[i][0] === '_') {
+ throw({
+ forbidden:
+ 'No system roles (starting with underscore) in users db.'
+ });
+ }
+ }
+
+ // no system names as names
+ if (newDoc.name[0] === '_') {
+ throw({forbidden: 'Username may not start with underscore.'});
+ }
+ }
+)
+"""
+
+
def with_couchdb(func):
@nose.tools.make_decorator(func)
def inner(*args, **kwargs):
@@ -113,6 +203,34 @@ def inner(*args, **kwargs):
method='DELETE',
)
+ # Update _auth with parenthesis, in case we are running too
+ # new spidermonkey, which fails in evaluation
+
+ user_auth_doc = json.loads(
+ cli.fetch('%s/_users/_design/_auth' % baseurl).body
+ )
+
+ user_auth_doc['validate_doc_update'] = _couch_1_1_user_view
+
+ try:
+ response = cli.fetch('%s_session' % baseurl,
+ headers={
+ 'Content-Type': 'application/x-www-form-urlencoded',
+ },
+ method='POST',
+ body='name=admin&password=admin',
+ )
+ cookie = response.headers['Set-Cookie']
+ except HTTPError:
+ cookie = ''
+
+ cli.fetch(
+ '%s/_users/_design/_auth/' % baseurl,
+ body=json.dumps(user_auth_doc),
+ method='PUT',
+ headers={'Cookie': cookie},
+ )
+
return func(baseurl, *args, **kwargs)
return inner
32 test/test_client.py
View
@@ -1027,7 +1027,7 @@ def load_view_cb(result):
'language': 'javascript',
'views': {
'all': {
- 'map': 'function (doc) { emit(null, doc) }',
+ 'map': '(function (doc) { emit(null, doc) })',
}
}
}
@@ -1068,9 +1068,9 @@ def load_view_cb(result):
'language': 'javascript',
'views': {
'all': {
- 'map': 'function (doc) { emit(doc.data, doc) }',
- 'reduce': 'function (key, value) { return \
- value.length }',
+ 'map': '(function (doc) { emit(doc.data, doc) })',
+ 'reduce': '(function (key, value) { return \
+ value.length })',
}
}
}
@@ -1111,7 +1111,7 @@ def load_view_cb(result):
'language': 'javascript',
'views': {
'all': {
- 'map': 'function (doc) { emit(doc.data, doc) }',
+ 'map': '(function (doc) { emit(doc.data, doc) })',
}
}
}
@@ -1161,9 +1161,9 @@ def load_view_cb(result):
'language': 'javascript',
'views': {
'foobar': {
- 'map': 'function (doc) { emit(doc.data, doc) }',
- 'reduce': 'function (key, value) { return \
- value.length }',
+ 'map': '(function (doc) { emit(doc.data, doc) })',
+ 'reduce': '(function (key, value) { return \
+ value.length })',
}
}
}
@@ -1203,7 +1203,7 @@ def view_results(result):
s = trombi.Server(baseurl, io_loop=ioloop)
db = trombi.Database(s, 'doesnotexist')
- db.temporary_view(view_results, 'function() { emit(null);}')
+ db.temporary_view(view_results, '(function() { emit(null);})')
ioloop.start()
@@ -1213,7 +1213,7 @@ def test_temporary_view_nonempty_results(baseurl, ioloop):
def do_test(db):
def doc_ready(doc):
db.temporary_view(view_results,
- 'function(doc) { emit(null, doc); }')
+ '(function(doc) { emit(null, doc); })')
def view_results(results):
eq(len(results), 1)
@@ -1246,8 +1246,8 @@ def doc_ready(doc):
def doc2_ready(doc):
db.temporary_view(
view_results,
- map_fun='function(doc) { emit(null, doc.value); }',
- reduce_fun='function(key, values) { return sum(values); }'
+ map_fun='(function(doc) { emit(null, doc.value); })',
+ reduce_fun='(function(key, values) { return sum(values); })'
)
def view_results(result):
@@ -1451,7 +1451,7 @@ def load_view_cb(result):
'language': 'javascript',
'views': {
'all': {
- 'map': 'function (doc) { emit(null, doc) }',
+ 'map': '(function (doc) { emit(null, doc) })',
}
}
}
@@ -1493,7 +1493,7 @@ def load_view_cb(result):
'language': 'javascript',
'views': {
'all': {
- 'map': 'function (doc) { emit(null, doc) }',
+ 'map': '(function (doc) { emit(null, doc) })',
}
}
}
@@ -1535,8 +1535,8 @@ def load_view_cb(result):
'language': 'javascript',
'views': {
'all': {
- 'map': 'function (doc) { emit(null, \
- {"_id": "bogus"}) }',
+ 'map': '(function (doc) { emit(null, \
+ {"_id": "bogus"}) })',
}
}
}
Please sign in to comment.
Something went wrong with that request. Please try again.