Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/tests/units/node/node.py
diff options
context:
space:
mode:
Diffstat (limited to 'tests/units/node/node.py')
-rwxr-xr-xtests/units/node/node.py281
1 files changed, 199 insertions, 82 deletions
diff --git a/tests/units/node/node.py b/tests/units/node/node.py
index a1bb46b..85dcff3 100755
--- a/tests/units/node/node.py
+++ b/tests/units/node/node.py
@@ -10,22 +10,22 @@ from os.path import exists
from __init__ import tests
-from sugar_network import db, node
+from sugar_network import db, node, model
from sugar_network.client import Client
from sugar_network.toolkit import http, coroutine
from sugar_network.toolkit.rrd import Rrd
from sugar_network.node import stats_user, stats_node, obs
-from sugar_network.node.commands import NodeCommands
-from sugar_network.node.master import MasterCommands
-from sugar_network.resources.volume import Volume, Resource
-from sugar_network.resources.user import User
-from sugar_network.resources.context import Context
-from sugar_network.resources.implementation import Implementation
-from sugar_network.resources.review import Review
-from sugar_network.resources.feedback import Feedback
-from sugar_network.resources.artifact import Artifact
-from sugar_network.resources.solution import Solution
-from sugar_network.resources.user import User
+from sugar_network.node.routes import NodeRoutes
+from sugar_network.node.master import MasterRoutes
+from sugar_network.model.user import User
+from sugar_network.model.context import Context
+from sugar_network.model.implementation import Implementation
+from sugar_network.model.review import Review
+from sugar_network.model.feedback import Feedback
+from sugar_network.model.artifact import Artifact
+from sugar_network.model.solution import Solution
+from sugar_network.model.user import User
+from sugar_network.toolkit.router import Router, Request, Response, fallbackroute, Blob, ACL, route
class NodeTest(tests.Test):
@@ -37,8 +37,8 @@ class NodeTest(tests.Test):
stats_user.stats_user_rras.value = ['RRA:AVERAGE:0.5:1:100']
def test_UserStats(self):
- volume = Volume('db')
- cp = NodeCommands('guid', volume)
+ volume = db.Volume('db', model.RESOURCES)
+ cp = NodeRoutes('guid', volume)
call(cp, method='POST', document='user', principal=tests.UID, content={
'name': 'user',
@@ -110,8 +110,8 @@ class NodeTest(tests.Test):
for i in range(100):
rrd['user'].put({'total': i}, ts + i)
- volume = Volume('db', [User, Context, Review, Feedback, Solution, Artifact])
- cp = NodeCommands('guid', volume)
+ volume = db.Volume('db', model.RESOURCES)
+ cp = NodeRoutes('guid', volume)
self.assertEqual({
'user': [
@@ -134,10 +134,11 @@ class NodeTest(tests.Test):
cp.stats(ts, ts + 12, 3, ['user.total']))
def test_HandleDeletes(self):
- volume = Volume('db')
- cp = NodeCommands('guid', volume)
+ volume = db.Volume('db', model.RESOURCES)
+ volume['user'].create({'guid': tests.UID, 'name': 'user', 'color': '', 'pubkey': tests.PUBKEY})
+ cp = NodeRoutes('guid', volume)
- guid = call(cp, method='POST', document='context', principal='principal', content={
+ guid = call(cp, method='POST', document='context', principal=tests.UID, content={
'type': 'activity',
'title': 'title',
'summary': 'summary',
@@ -154,43 +155,44 @@ class NodeTest(tests.Test):
call(cp, method='GET', document='context', guid=guid, reply=['guid', 'title', 'layer']))
self.assertEqual(['public'], volume['context'].get(guid)['layer'])
+ def subscribe():
+ for event in cp.subscribe():
+ events.append(json.loads(event[6:]))
events = []
- volume.connect(lambda event: events.append(event))
- call(cp, method='DELETE', document='context', guid=guid, principal='principal')
+ coroutine.spawn(subscribe)
coroutine.dispatch()
+ call(cp, method='DELETE', document='context', guid=guid, principal=tests.UID)
+ coroutine.dispatch()
self.assertRaises(http.NotFound, call, cp, method='GET', document='context', guid=guid, reply=['guid', 'title'])
self.assertEqual(['deleted'], volume['context'].get(guid)['layer'])
- self.assertEqual([
- {'event': 'delete', 'document': 'context', 'guid': guid},
- {'event': 'commit', 'document': 'context', 'mtime': int(os.stat('db/context/index/mtime').st_mtime)},
- ],
- events)
+ self.assertEqual({'event': 'delete', 'resource': 'context', 'guid': guid}, events[0])
def test_SimulateDeleteEvents(self):
- volume = Volume('db')
- cp = NodeCommands('guid', volume)
+ volume = db.Volume('db', model.RESOURCES)
+ volume['user'].create({'guid': tests.UID, 'name': 'user', 'color': '', 'pubkey': tests.PUBKEY})
+ cp = NodeRoutes('guid', volume)
- guid = call(cp, method='POST', document='context', principal='principal', content={
+ guid = call(cp, method='POST', document='context', principal=tests.UID, content={
'type': 'activity',
'title': 'title',
'summary': 'summary',
'description': 'description',
})
+ def subscribe():
+ for event in cp.subscribe():
+ events.append(json.loads(event[6:]))
events = []
- volume.connect(lambda event: events.append(event))
- call(cp, method='PUT', document='context', guid=guid, principal='principal', content={'layer': ['deleted']})
+ coroutine.spawn(subscribe)
coroutine.dispatch()
- self.assertEqual([
- {'event': 'delete', 'document': 'context', 'guid': guid},
- {'event': 'commit', 'document': 'context', 'mtime': int(os.stat('db/context/index/mtime').st_mtime)},
- ],
- events)
+ call(cp, method='PUT', document='context', guid=guid, principal=tests.UID, content={'layer': ['deleted']})
+ coroutine.dispatch()
+ self.assertEqual({'event': 'delete', 'resource': 'context', 'guid': guid}, events[0])
def test_RegisterUser(self):
- cp = NodeCommands('guid', Volume('db', [User]))
+ cp = NodeRoutes('guid', db.Volume('db', [User]))
guid = call(cp, method='POST', document='user', principal='fake', content={
'name': 'user',
@@ -203,50 +205,57 @@ class NodeTest(tests.Test):
self.assertEqual('user', call(cp, method='GET', document='user', guid=tests.UID, prop='name'))
def test_UnauthorizedCommands(self):
+ volume = db.Volume('db', model.RESOURCES)
+ volume['user'].create({'guid': tests.UID, 'name': 'user', 'color': '', 'pubkey': tests.PUBKEY})
- class Document(Resource):
+ class Routes(NodeRoutes):
- @db.document_command(method='GET', cmd='probe1',
- permissions=db.ACCESS_AUTH)
+ @route('GET', [None, None], cmd='probe1', acl=ACL.AUTH)
def probe1(self, directory):
pass
- @db.document_command(method='GET', cmd='probe2')
+ @route('GET', [None, None], cmd='probe2')
def probe2(self, directory):
pass
- cp = NodeCommands('guid', Volume('db', [User, Document]))
- guid = call(cp, method='POST', document='document', principal='user', content={})
+ class Document(db.Resource):
+ pass
+
+ cp = Routes('guid', db.Volume('db', [User, Document]))
+ guid = call(cp, method='POST', document='document', principal=tests.UID, content={})
+
self.assertRaises(http.Unauthorized, call, cp, method='GET', cmd='probe1', document='document', guid=guid)
- call(cp, method='GET', cmd='probe1', document='document', guid=guid, principal='user')
+ call(cp, method='GET', cmd='probe1', document='document', guid=guid, principal=tests.UID)
call(cp, method='GET', cmd='probe2', document='document', guid=guid)
def test_ForbiddenCommands(self):
- class Document(Resource):
+ class Routes(NodeRoutes):
- @db.document_command(method='GET', cmd='probe1',
- permissions=db.ACCESS_AUTHOR)
+ @route('GET', [None, None], cmd='probe1', acl=ACL.AUTHOR)
def probe1(self):
pass
- @db.document_command(method='GET', cmd='probe2')
+ @route('GET', [None, None], cmd='probe2')
def probe2(self):
pass
- class User(db.Document):
+ class Document(db.Resource):
pass
- cp = NodeCommands('guid', Volume('db', [User, Document]))
- guid = call(cp, method='POST', document='document', principal='principal', content={})
+ volume = db.Volume('db', [User, Document])
+ volume['user'].create({'guid': tests.UID, 'name': 'user', 'color': '', 'pubkey': tests.PUBKEY})
+ cp = Routes('guid', volume)
+
+ guid = call(cp, method='POST', document='document', principal=tests.UID, content={})
self.assertRaises(http.Forbidden, call, cp, method='GET', cmd='probe1', document='document', guid=guid)
- self.assertRaises(http.Forbidden, call, cp, method='GET', cmd='probe1', document='document', guid=guid, principal='fake')
- call(cp, method='GET', cmd='probe1', document='document', guid=guid, principal='principal')
+ self.assertRaises(http.Unauthorized, call, cp, method='GET', cmd='probe1', document='document', guid=guid, principal='fake')
+ call(cp, method='GET', cmd='probe1', document='document', guid=guid, principal=tests.UID)
call(cp, method='GET', cmd='probe2', document='document', guid=guid)
def test_ForbiddenCommandsForUserResource(self):
- cp = NodeCommands('guid', Volume('db', [User]))
+ cp = NodeRoutes('guid', db.Volume('db', [User]))
call(cp, method='POST', document='user', principal='fake', content={
'name': 'user1',
@@ -258,39 +267,134 @@ class NodeTest(tests.Test):
self.assertEqual('user1', call(cp, method='GET', document='user', guid=tests.UID, prop='name'))
self.assertRaises(http.Unauthorized, call, cp, method='PUT', document='user', guid=tests.UID, content={'name': 'user2'})
- self.assertRaises(http.Forbidden, call, cp, method='PUT', document='user', guid=tests.UID, principal='fake', content={'name': 'user2'})
+ self.assertRaises(http.Unauthorized, call, cp, method='PUT', document='user', guid=tests.UID, principal='fake', content={'name': 'user2'})
call(cp, method='PUT', document='user', guid=tests.UID, principal=tests.UID, content={'name': 'user2'})
self.assertEqual('user2', call(cp, method='GET', document='user', guid=tests.UID, prop='name'))
+ def test_authorize_Config(self):
+ self.touch(('authorization.conf', [
+ '[%s]' % tests.UID,
+ 'root = True',
+ ]))
+
+ class Routes(NodeRoutes):
+
+ @route('PROBE', acl=ACL.SUPERUSER)
+ def probe(self):
+ return 'ok'
+
+ volume = db.Volume('db', [User])
+ volume['user'].create({'guid': tests.UID, 'name': 'user', 'color': '', 'pubkey': tests.PUBKEY})
+ volume['user'].create({'guid': tests.UID2, 'name': 'test', 'color': '', 'pubkey': tests.PUBKEY2})
+ cp = Routes('guid', volume)
+
+ self.assertRaises(http.Forbidden, call, cp, method='PROBE')
+ self.assertRaises(http.Forbidden, call, cp, method='PROBE', principal=tests.UID2)
+ self.assertEqual('ok', call(cp, method='PROBE', principal=tests.UID))
+
+ def test_authorize_FullWriteForRoot(self):
+ self.touch(('authorization.conf', [
+ '[%s]' % tests.UID2,
+ 'root = True',
+ ]))
+
+ class Routes(NodeRoutes):
+
+ @route('PROBE', [None, None], acl=ACL.AUTHOR)
+ def probe(self):
+ pass
+
+ class Document(db.Resource):
+ pass
+
+ volume = db.Volume('db', [User, Document])
+ volume['user'].create({'guid': tests.UID, 'name': 'user', 'color': '', 'pubkey': tests.PUBKEY})
+ volume['user'].create({'guid': tests.UID2, 'name': 'user', 'color': '', 'pubkey': tests.PUBKEY2})
+ cp = Routes('guid', volume)
+
+ guid = call(cp, method='POST', document='document', principal=tests.UID, content={})
+
+ call(cp, 'PROBE', document='document', guid=guid, principal=tests.UID)
+ call(cp, 'PROBE', document='document', guid=guid, principal=tests.UID2)
+
+ def test_authorize_LiveConfigUpdates(self):
+
+ class Routes(NodeRoutes):
+
+ @route('PROBE', acl=ACL.SUPERUSER)
+ def probe(self):
+ pass
+
+ volume = db.Volume('db', [User])
+ volume['user'].create({'guid': tests.UID, 'name': 'user', 'color': '', 'pubkey': tests.PUBKEY})
+ cp = Routes('guid', volume)
+
+ self.assertRaises(http.Forbidden, call, cp, 'PROBE', principal=tests.UID)
+ self.touch(('authorization.conf', [
+ '[%s]' % tests.UID,
+ 'root = True',
+ ]))
+ call(cp, 'PROBE', principal=tests.UID)
+
+ def test_authorize_Anonymous(self):
+
+ class Routes(NodeRoutes):
+
+ @route('PROBE1', acl=ACL.AUTH)
+ def probe1(self, request):
+ pass
+
+ @route('PROBE2', acl=ACL.SUPERUSER)
+ def probe2(self, request):
+ pass
+
+ volume = db.Volume('db', [User])
+ cp = Routes('guid', volume)
+
+ self.assertRaises(http.Unauthorized, call, cp, 'PROBE1')
+ self.assertRaises(http.Forbidden, call, cp, 'PROBE2')
+
+ self.touch(('authorization.conf', [
+ '[anonymous]',
+ 'user = True',
+ 'root = True',
+ ]))
+ call(cp, 'PROBE1')
+ call(cp, 'PROBE2')
+
def test_SetUser(self):
- cp = NodeCommands('guid', Volume('db'))
+ volume = db.Volume('db', model.RESOURCES)
+ volume['user'].create({'guid': tests.UID, 'name': 'user', 'color': '', 'pubkey': tests.PUBKEY})
+ cp = NodeRoutes('guid', volume)
- guid = call(cp, method='POST', document='context', principal='principal', content={
+ guid = call(cp, method='POST', document='context', principal=tests.UID, content={
'type': 'activity',
'title': 'title',
'summary': 'summary',
'description': 'description',
})
self.assertEqual(
- [{'name': 'principal', 'role': 2}],
+ [{'guid': tests.UID, 'name': 'user', 'role': 3}],
call(cp, method='GET', document='context', guid=guid, prop='author'))
def test_find_MaxLimit(self):
- cp = NodeCommands('guid', Volume('db'))
+ volume = db.Volume('db', model.RESOURCES)
+ volume['user'].create({'guid': tests.UID, 'name': 'user', 'color': '', 'pubkey': tests.PUBKEY})
+ cp = NodeRoutes('guid', volume)
- call(cp, method='POST', document='context', principal='principal', content={
+ call(cp, method='POST', document='context', principal=tests.UID, content={
'type': 'activity',
'title': 'title1',
'summary': 'summary',
'description': 'description',
})
- call(cp, method='POST', document='context', principal='principal', content={
+ call(cp, method='POST', document='context', principal=tests.UID, content={
'type': 'activity',
'title': 'title2',
'summary': 'summary',
'description': 'description',
})
- call(cp, method='POST', document='context', principal='principal', content={
+ call(cp, method='POST', document='context', principal=tests.UID, content={
'type': 'activity',
'title': 'title3',
'summary': 'summary',
@@ -305,10 +409,11 @@ class NodeTest(tests.Test):
self.assertEqual(1, len(call(cp, method='GET', document='context', limit=1024)['result']))
def test_DeletedDocuments(self):
- volume = Volume('db')
- cp = NodeCommands('guid', volume)
+ volume = db.Volume('db', model.RESOURCES)
+ volume['user'].create({'guid': tests.UID, 'name': 'user', 'color': '', 'pubkey': tests.PUBKEY})
+ cp = NodeRoutes('guid', volume)
- guid = call(cp, method='POST', document='context', principal='principal', content={
+ guid = call(cp, method='POST', document='context', principal=tests.UID, content={
'type': 'activity',
'title': 'title1',
'summary': 'summary',
@@ -325,9 +430,10 @@ class NodeTest(tests.Test):
def test_CreateGUID(self):
# TODO Temporal security hole, see TODO
- volume2 = Volume('db2')
- cp2 = MasterCommands('guid', volume2)
- call(cp2, method='POST', document='context', principal='principal', content={
+ volume = db.Volume('db', model.RESOURCES)
+ volume['user'].create({'guid': tests.UID, 'name': 'user', 'color': '', 'pubkey': tests.PUBKEY})
+ cp = NodeRoutes('guid', volume)
+ call(cp, method='POST', document='context', principal=tests.UID, content={
'guid': 'foo',
'type': 'activity',
'title': 'title',
@@ -336,12 +442,14 @@ class NodeTest(tests.Test):
})
self.assertEqual(
{'guid': 'foo', 'title': 'title'},
- call(cp2, method='GET', document='context', guid='foo', reply=['guid', 'title']))
+ call(cp, method='GET', document='context', guid='foo', reply=['guid', 'title']))
def test_CreateMalformedGUID(self):
- cp = MasterCommands('guid', Volume('db2'))
+ volume = db.Volume('db', model.RESOURCES)
+ volume['user'].create({'guid': tests.UID, 'name': 'user', 'color': '', 'pubkey': tests.PUBKEY})
+ cp = MasterRoutes('guid', volume)
- self.assertRaises(RuntimeError, call, cp, method='POST', document='context', principal='principal', content={
+ self.assertRaises(RuntimeError, call, cp, method='POST', document='context', principal=tests.UID, content={
'guid': '!?',
'type': 'activity',
'title': 'title',
@@ -350,16 +458,18 @@ class NodeTest(tests.Test):
})
def test_FailOnExistedGUID(self):
- cp = MasterCommands('guid', Volume('db2'))
+ volume = db.Volume('db', model.RESOURCES)
+ volume['user'].create({'guid': tests.UID, 'name': 'user', 'color': '', 'pubkey': tests.PUBKEY})
+ cp = MasterRoutes('guid', volume)
- guid = call(cp, method='POST', document='context', principal='principal', content={
+ guid = call(cp, method='POST', document='context', principal=tests.UID, content={
'type': 'activity',
'title': 'title',
'summary': 'summary',
'description': 'description',
})
- self.assertRaises(RuntimeError, call, cp, method='POST', document='context', principal='principal', content={
+ self.assertRaises(RuntimeError, call, cp, method='POST', document='context', principal=tests.UID, content={
'guid': guid,
'type': 'activity',
'title': 'title',
@@ -550,16 +660,23 @@ class NodeTest(tests.Test):
self.assertEqual(len(activity_info), data.get('unpack_size'))
-
-
-
-
-def call(cp, principal=None, content=None, **kwargs):
- request = db.Request(**kwargs)
- request.principal = principal
+def call(routes, method, document=None, guid=None, prop=None, principal=None, cmd=None, content=None, **kwargs):
+ path = []
+ if document:
+ path.append(document)
+ if guid:
+ path.append(guid)
+ if prop:
+ path.append(prop)
+ request = Request(method=method, path=path)
+ request.update(kwargs)
+ request.cmd = cmd
request.content = content
request.environ = {'HTTP_HOST': '127.0.0.1'}
- return cp.call(request, db.Response())
+ if principal:
+ request.environ['HTTP_X_SN_LOGIN'] = principal
+ router = Router(routes)
+ return router.call(request, Response())
if __name__ == '__main__':