def test_basic(self):
        store = TestingMemServerStore()
        brl_user = '******'
        store.create_user(User(brl_user))
        brl_block = BRLBlock('user/user/block/master')
        publisher = TestPublisher(brl_user, store)
        publisher.publish(brl_block, {'r1.h': ('r1', ['user/block/r2.h']),
                                      'r2.h': ('r2', []),
                                      'r3.h': ('r3', [])})

        store = MemServerStore(store)
        translator = ReferenceTranslatorService(store, brl_user)
        ver = BlockVersion(brl_block, 0)
        missing = References()
        missing[ver].add('r1.h')
        closure = CompatibilityClosure(missing)
        full_graph = BlockVersionGraph()
        full_graph.add_nodes([ver])
        build_compatibility_closure(translator, closure, {ver}, full_graph)
        self.assertEqual(References(), closure.broken)

        expected = set()
        expected.add('user/block/r1.h')
        expected.add('user/block/r2.h')
        self.assertEqual(expected, closure.block_cell_names)
Example #2
0
    def test_basic(self):
        store = TestingMemServerStore()
        brl_user = '******'
        store.create_user(User(brl_user))
        brl_block = BRLBlock('user/user/block/master')
        publisher = TestPublisher(brl_user, store)
        publisher.publish(
            brl_block, {
                'r1.h': ('r1', ['user/block/r2.h']),
                'r2.h': ('r2', []),
                'r3.h': ('r3', [])
            })

        store = MemServerStore(store)
        translator = ReferenceTranslatorService(store, brl_user)
        ver = BlockVersion(brl_block, 0)
        missing = References()
        missing[ver].add('r1.h')
        closure = CompatibilityClosure(missing)
        full_graph = BlockVersionGraph()
        full_graph.add_nodes([ver])
        build_compatibility_closure(translator, closure, {ver}, full_graph)
        self.assertEqual(References(), closure.broken)

        expected = set()
        expected.add('user/block/r1.h')
        expected.add('user/block/r2.h')
        self.assertEqual(expected, closure.block_cell_names)
Example #3
0
 def setUp(self):
     """ all find tests have a user, store, and BiiService """
     self.user = BRLUser('find_user')
     self.store = TestingMemServerStore()
     user = User(self.user)
     user.password = '******'
     self.store.create_user(user)
     self.service = BiiService(self.store, self.user)
Example #4
0
class BaseFinderTest(unittest.TestCase):
    def setUp(self):
        """ all find tests have a user, store, and BiiService """
        self.user = BRLUser('find_user')
        self.store = TestingMemServerStore()
        user = User(self.user)
        user.password = '******'
        self.store.create_user(user)
        self.service = BiiService(self.store, self.user)

    def check_result(self,
                     result,
                     resolved=None,
                     unresolved=None,
                     updated=None):
        unresolved = unresolved or []
        unresolved = {CPPDeclaration(str(u)) for u in unresolved}
        self.assertEqual(result.unresolved, unresolved)

        resolved = resolved or []
        refs = ReferencedDependencies()
        for brl, time, block_cell_names in resolved:
            for name in block_cell_names:
                refs[BlockVersion(
                    brl, time)][CPPDeclaration(name)] = {BlockCellName(name)}
        self.assertEqual(result.resolved, refs)

        updated = updated or []
        refs = ReferencedDependencies()
        for brl, time, block_cell_names in updated:
            for name in block_cell_names:
                refs[BlockVersion(
                    brl, time)][CPPDeclaration(name)] = {BlockCellName(name)}
        self.assertEqual(result.updated, refs)

    def build_unresolved_request(self, unresolved_deps):
        if isinstance(unresolved_deps, basestring):
            unresolved_deps = [unresolved_deps]
        request = FinderRequest()
        unresolved = set()
        for dep in unresolved_deps:
            unresolved.add(CPPDeclaration(dep))
        request.unresolved = unresolved
        request.policy = Policy.default()
        return request

    def build_update_request(self, block_version, block_cell_name):
        request = FinderRequest()
        existing = ReferencedDependencies()
        existing[block_version][CPPDeclaration(block_cell_name)].add(
            block_cell_name)
        request.existing = existing
        request.policy = Policy.default()
        request.find = False
        request.update = True
        return request
Example #5
0
class BaseFinderTest(unittest.TestCase):
    def setUp(self):
        """ all find tests have a user, store, and BiiService """
        self.user = BRLUser('find_user')
        self.store = TestingMemServerStore()
        user = User(self.user)
        user.password = '******'
        self.store.create_user(user)
        self.service = BiiService(self.store, self.user)

    def check_result(self, result, resolved=None, unresolved=None, updated=None):
        unresolved = unresolved or []
        unresolved = {CPPDeclaration(str(u)) for u in unresolved}
        self.assertEqual(result.unresolved, unresolved)

        resolved = resolved or []
        refs = ReferencedDependencies()
        for brl, time, block_cell_names in resolved:
            for name in block_cell_names:
                refs[BlockVersion(brl, time)][CPPDeclaration(name)] = {BlockCellName(name)}
        self.assertEqual(result.resolved, refs)

        updated = updated or []
        refs = ReferencedDependencies()
        for brl, time, block_cell_names in updated:
            for name in block_cell_names:
                refs[BlockVersion(brl, time)][CPPDeclaration(name)] = {BlockCellName(name)}
        self.assertEqual(result.updated, refs)

    def build_unresolved_request(self, unresolved_deps):
        if isinstance(unresolved_deps, basestring):
            unresolved_deps = [unresolved_deps]
        request = FinderRequest()
        unresolved = set()
        for dep in unresolved_deps:
            unresolved.add(CPPDeclaration(dep))
        request.unresolved = unresolved
        request.policy = Policy.default()
        return request

    def build_update_request(self, block_version, block_cell_name):
        request = FinderRequest()
        existing = ReferencedDependencies()
        existing[block_version][CPPDeclaration(block_cell_name)].add(block_cell_name)
        request.existing = existing
        request.policy = Policy.default()
        request.find = False
        request.update = True
        return request
Example #6
0
    def setUp(self):
        unittest.TestCase.setUp(self)
        self.store = TestingMemServerStore()
        self.store.create_user(User("goku"))
        self.store.create_user(User("krilin"))
        self.store.create_user(User("freezer"))
        self.store.create_user(User("bulma"))

        self.public_brl = BRLBlock("goku/goku/block/ballno1")
        bper = ElementPermissions(self.public_brl, private=False)
        self.store.upsert_block_permissions(bper)

        goku = self.store.read_user("goku")
        goku.add_block(self.public_brl)
        self.store.update_user(goku)
Example #7
0
 def setUp(self):
     """ all find tests have a user, store, and BiiService """
     self.user = BRLUser('find_user')
     self.store = TestingMemServerStore()
     user = User(self.user)
     user.password = '******'
     self.store.create_user(user)
     self.service = BiiService(self.store, self.user)
    def test_publish_concurrent_modification(self):
        self.store = TestingMemServerStore()
        brl = 'user'
        self.store.create_user(User(brl))
        self.service = BiiService(self.store, brl)

        self.brl_block = BRLBlock('user/user/block/master')
        request = PublishRequest(BlockVersion(self.brl_block, -1))
        request.cells.append(SimpleCell('user/block/r1.h'))
        request.contents['r1.h'] = Content(id_=None, load=Blob('hola'))
        request.deptable = BlockVersionTable()
        request.tag = DEV
        self.service.publish(request)
        '''Branch 1 (from master) creates new resource'''
        self.brl_block1 = BRLBlock('user/user/block/branch1')
        request = PublishRequest(BlockVersion(self.brl_block, 0))
        request.cells.append(SimpleCell('user/block/r2.h'))
        request.contents['r2.h'] = Content(id_=None, load=Blob('adios'))
        request.deptable = BlockVersionTable()
        with self.assertRaisesRegexp(BiiException, 'Concurrent modification'):
            self.service.publish(request)
    def test_read_published_blocks_info(self, store_cls):
        """Insert a block and read all published blocks info (brl, lastpubdate)"""
        if store_cls == MongoServerStore:
            store = MongoServerStore(self.conn, self.__class__.__name__)
        else:
            store = TestingMemServerStore()
        block = Block(ID((23, 23)), BRLBlock("bonjovi/bonjovi/itsmylife/master"))
        ppack = PublishRequest(block.last_version())
        r1 = SimpleCell('user/block/r1.h')
        ppack.cells.append(r1)
        ppack.contents['r1.h'] = Content(id_=None, load=Blob('hola'))

        block.add_publication(ppack)
        store.create_block(block, False)
        ret = store.read_published_blocks_info()
        first = ret.next()

        self.assertEquals(first[0], "bonjovi/bonjovi/itsmylife/master")
        self.assertEquals(first[1].__class__, datetime.datetime)
    def test_publish_concurrent_modification(self):
        self.store = TestingMemServerStore()
        brl = 'user'
        self.store.create_user(User(brl))
        self.service = BiiService(self.store, brl)

        self.brl_block = BRLBlock('user/user/block/master')
        request = PublishRequest(BlockVersion(self.brl_block, -1))
        request.cells.append(SimpleCell('user/block/r1.h'))
        request.contents['r1.h'] = Content(id_=None, load=Blob('hola'))
        request.deptable = BlockVersionTable()
        request.tag = DEV
        self.service.publish(request)

        '''Branch 1 (from master) creates new resource'''
        self.brl_block1 = BRLBlock('user/user/block/branch1')
        request = PublishRequest(BlockVersion(self.brl_block, 0))
        request.cells.append(SimpleCell('user/block/r2.h'))
        request.contents['r2.h'] = Content(id_=None, load=Blob('adios'))
        request.deptable = BlockVersionTable()
        with self.assertRaisesRegexp(BiiException, 'Concurrent modification'):
            self.service.publish(request)
class PublishServiceTest(unittest.TestCase):

    def test_publish_rejected(self):
        store = Mock(MongoServerStore)
        user = Mock()
        user.blocks = {}
        store.read_user = Mock(return_value=user)

        block = Mock(Block)
        block.add_publication.return_value = (Mock(), Mock())
        store.read_block.return_value = block
        brl = BRLBlock('user/user/block/branch')

        p = PublishService(store, 'authUser')
        pack = PublishRequest(BlockVersion(brl, -1))
        pack.cells.append(SimpleCell('user/block/r1.h'))
        pack.contents['r1.h'] = Content(id_=None, load=Blob('hola'))
        pack.deptable = BlockVersionTable()
        with self.assertRaises(ForbiddenException):
            p.publish(pack)

    @patch.object(Enqueuer, "enqueue_job")
    def test_publish(self, enqueuer):
        brl = BRLBlock('owner/user/block/branch')
        # moduleID=BlockID(UserID(123),456)
        store = Mock(MongoServerStore)
        store.read_block_permissions = Mock(return_value=ElementPermissions(brl, private=False))
        user = User("owner")
        user.numeric_id = 1
        user.blocks = {}
        store.read_user = Mock(return_value=user)
        block = Mock(Block)
        block.last_version.return_value = Mock(BlockVersion)
        block.add_publication.return_value = (Mock(list), Mock(list), Mock(list), Mock(list))
        block.deltas = []

        ensure = Security('authUser', store)
        ensure.check_create_block = Mock(return_value=True)
        ensure.check_write_block = Mock(return_value=True)
        ensure.check_read_block = Mock(return_value=True)

        store.read_block.return_value = block
        store.read_published_cells.return_value = {}
        p = PublishService(store, 'authUser')
        p.security = ensure

        pack = PublishRequest(BlockVersion(brl, -1))
        pack.cells.append(SimpleCell('user/block/r1.h'))
        pack.contents['r1.h'] = Content(id_=None, load=Blob('hola'))
        pack.cells.append(SimpleCell('user/block/r2.h'))
        pack.contents['r2.h'] = Content(id_=None, load=Blob('hola'))
        pack.cells.append(SimpleCell('user/block/r3.h'))
        pack.contents['r3.h'] = Content(id_=None, load=Blob('hola'))
        pack.deptable = BlockVersionTable()
        p.publish(pack)

        block.add_publication.assert_called_once_with(pack, p.auth_user)
        store.update_block.assert_called_once_with(block)
        self.assertEqual(1, store.create_published_cells.call_count)
        self.assertEqual(1, store.create_published_contents.call_count)

        # Check sizes
        self.assertEquals(user.blocks_bytes, 12)  # 12 bytes "hola" * 3

        # Publish again, see the size incremented
        pack._bytes = None  # Lazy computed
        p.publish(pack)
        self.assertEquals(user.blocks_bytes, 24)  # 24 bytes: "hola" * 3 * 2 publications

        # Max size exceeded for user
        user.max_workspace_size = 25
        self.assertRaises(ForbiddenException, p.publish, pack)

        # Try to publish only 1 byte
        pack._bytes = None  # Lazy computed
        pack.cells = []
        pack.contents = {}
        pack.cells.append(SimpleCell('user/block/r1.h'))
        pack.contents['r1.h'] = Content(id_=None, load=Blob('h'))
        p.publish(pack)

    @patch.object(Enqueuer, "enqueue_job")
    def test_publish_no_contents(self, enqueuer):
        brl = BRLBlock('owner/user/block/branch')
        store = Mock(MongoServerStore)
        store.read_block_permissions = Mock(return_value=ElementPermissions(brl, private=False))

        p = PublishService(store, 'authUser')
        pack = PublishRequest(BlockVersion(brl, -1))
        pack.cells.append(SimpleCell('user/block/r1.h'))
        pack.contents['r1.h'] = Content(id_=None, load=Blob('hola'))
        pack.versiontag = 'mytag'
        with self.assertRaisesRegexp(PublishException, 'DEV'):
            p.publish(pack)

    @patch.object(Enqueuer, "enqueue_job")
    def test_publish_dev_with_tag(self, enqueuer):
        brl = BRLBlock('owner/user/block/branch')
        store = Mock(MongoServerStore)
        store.read_block_permissions = Mock(return_value=ElementPermissions(brl, private=False))
        user = Mock()
        user.blocks = {}
        store.read_user = Mock(return_value=user)

        block = Mock(Block)
        block.add_publication.return_value = (['mock_id'], [], [], [])
        block.deltas = []
        ensure = Security('authUser', store)
        ensure.check_read_block = Mock(return_value=True)
        ensure.check_create_block = Mock(return_value=True)
        ensure.check_write_block = Mock(return_value=True)
        ensure.check_publish_block = Mock(return_value=True)

        store.read_block.return_value = block
        store.read_published_cells.return_value = {}
        p = PublishService(store, 'authUser')
        p.security = ensure
        pack = PublishRequest(BlockVersion(brl, -1))
        pack.cells.append(SimpleCell('user/block/r1.h'))
        pack.deptable = BlockVersionTable()
        p.publish(pack)

    def test_publish_concurrent_modification(self):
        self.store = TestingMemServerStore()
        brl = 'user'
        self.store.create_user(User(brl))
        self.service = BiiService(self.store, brl)

        self.brl_block = BRLBlock('user/user/block/master')
        request = PublishRequest(BlockVersion(self.brl_block, -1))
        request.cells.append(SimpleCell('user/block/r1.h'))
        request.contents['r1.h'] = Content(id_=None, load=Blob('hola'))
        request.deptable = BlockVersionTable()
        request.tag = DEV
        self.service.publish(request)

        '''Branch 1 (from master) creates new resource'''
        self.brl_block1 = BRLBlock('user/user/block/branch1')
        request = PublishRequest(BlockVersion(self.brl_block, 0))
        request.cells.append(SimpleCell('user/block/r2.h'))
        request.contents['r2.h'] = Content(id_=None, load=Blob('adios'))
        request.deptable = BlockVersionTable()
        with self.assertRaisesRegexp(BiiException, 'Concurrent modification'):
            self.service.publish(request)

    def get_version_info_test(self):
        store = Mock(GenericServerStore)

        # Block doesn't exist and user is other
        p = PublishService(store, 'any_user')
        block_brl = BRLBlock("user/user/theblock/master")
        store.read_block_permissions = Mock(side_effect=NotInStoreException())
        block_info = p.get_block_info(block_brl)
        self.assertFalse(block_info.can_write)

        # Now block exists
        store.read_block_permissions = Mock(return_value=ElementPermissions(block_brl))

        # Block exists and user is the authorized one
        p = PublishService(store, 'theuser')
        block_brl = BRLBlock("theuser/theuser/theblock/master")
        block_info = p.get_block_info(block_brl)
        self.assertTrue(block_info.can_write)

        # No authorized write to an existing block
        p = PublishService(store, 'wronguser')
        user = Mock(User)
        user.administrators = Permissions()
        store.read_user = Mock(return_value=user)
        block_info = p.get_block_info(block_brl)
        self.assertFalse(block_info.can_write)

        # Authorized user with an existing block
        p = PublishService(store, 'theuser')
        block_brl = BRLBlock("theuser/theuser/theblock/master")
        block_info = p.get_block_info(block_brl)
        self.assertTrue(block_info.can_write)
Example #12
0
class AuthorizeTest(unittest.TestCase):

    def setUp(self):
        unittest.TestCase.setUp(self)
        self.store = TestingMemServerStore()
        self.store.create_user(User("goku"))
        self.store.create_user(User("krilin"))
        self.store.create_user(User("freezer"))
        self.store.create_user(User("bulma"))

        self.public_brl = BRLBlock("goku/goku/block/ballno1")
        bper = ElementPermissions(self.public_brl, private=False)
        self.store.upsert_block_permissions(bper)

        goku = self.store.read_user("goku")
        goku.add_block(self.public_brl)
        self.store.update_user(goku)

    # TODO: Test num_user limits and message given to user!!!!!!

    def test_anonymous_operations(self):
        ensure = Security(None, self.store)
        ensure.check_read_block(self.public_brl)

    def test_check_make_private_block(self):
        # 0. Goku is paying
        self._subscribe("goku", "enterprise_275_50_x")

        # 1. Already private.
        brl_master = BRLBlock("goku/goku/block/master")
        bper_master = ElementPermissions(brl_master, private=True)
        self.store.upsert_block_permissions(bper_master)

        # 2. Bulma cant make it private even its already private because is not an admin
        ensure = Security("bulma", self.store)
        self._subscribe("bulma", "personal_7_1_x")
        self.assertRaises(ForbiddenException, ensure.check_make_private_a_block, "goku")

        # 3. Now block is public, so bulma can't make it private
        bper_master = ElementPermissions(brl_master, private=False)
        self.store.upsert_block_permissions(bper_master)
        self.assertRaises(ForbiddenException, ensure.check_make_private_a_block, "goku")

        # 4. Grant read and write, and bulma still can't make it private
        bper_master.read.grant("bulma")
        bper_master.write.grant("bulma")
        self.store.upsert_block_permissions(bper_master)
        self.assertRaises(ForbiddenException, ensure.check_make_private_a_block, "goku")

        # 5. Make bulma an admin, now bulma can make it private
        goku = self.store.read_user("goku")
        goku.administrators.grant("bulma")
        self.store.update_user(goku)
        ensure.check_make_private_a_block("goku")

        # 6. Bulma cant make private the block when suscription is not active
        self._subscribe("goku", "free")
        self.assertRaises(ForbiddenException, ensure.check_make_private_a_block, "goku")

    def test_check_make_public_block(self):

        # 1. Already public.
        brl_master = BRLBlock("goku/goku/block/master")
        bper_master = ElementPermissions(brl_master, private=False)
        self.store.upsert_block_permissions(bper_master)

        # 2. Bulma cant make it public even its already public
        ensure = Security("bulma", self.store)
        self._subscribe("bulma", "enterprise_275_50_x")
        self.assertRaises(ForbiddenException, ensure.check_make_private_a_block, "goku")

        # 3. Now block is public, so bulma cant make it public
        bper_master = ElementPermissions(brl_master, private=True)
        self.store.upsert_block_permissions(bper_master)
        self.assertRaises(ForbiddenException, ensure.check_make_public_a_block, "goku")

        # 4. Grant read and write, and bulma still cant make it public
        bper_master.read.grant("bulma")
        bper_master.write.grant("bulma")
        self.store.upsert_block_permissions(bper_master)
        self.assertRaises(ForbiddenException, ensure.check_make_public_a_block, "goku")

        # 5. Make bulma an admin, now bulma can make it public
        goku = self.store.read_user("goku")
        goku.administrators.grant("bulma")
        self.store.update_user(goku)
        ensure.check_make_public_a_block("goku")

        # 5. Bulma can make public the block even when suscription is not active
        self._subscribe("bulma", "free")
        goku = self.store.read_user("goku")
        self.store.update_user(goku)
        ensure.check_make_public_a_block("goku")

    def test_read_block(self):

        # 1. Check we can always access a public block
        brl = BRLBlock("goku/goku/block/master")
        bper = ElementPermissions(brl, private=False)
        self.store.upsert_block_permissions(bper)

        ensure = Security("freezer", self.store)
        self._subscribe("freezer", "enterprise_275_50_x")
        ensure.check_read_block(brl)

        # Even owner is not paying
        self._subscribe("freezer", "free")
        ensure.check_read_block(brl)
        self._subscribe("freezer", "enterprise_275_50_x")

        # 2. Check we can read a private block due to being the owner
        bper = ElementPermissions(brl, private=True)
        self.store.upsert_block_permissions(bper)

        ensure = Security("goku", self.store)
        self._subscribe("freezer", "enterprise_275_50_x")
        ensure.check_read_block(brl)

        # 4. Check we can read the block even subscription is not valid
        self._subscribe("freezer", "free")
        ensure.check_read_block(brl)

        # 5. A user without read permissions cant read the block
        ensure = Security("bulma", self.store)
        self._subscribe("bulma", "enterprise_275_50_x")
        self.assertRaises(ForbiddenException, ensure.check_read_block, brl)

        # 6. Until is granted as administrator or read granted
        goku = self.store.read_user("goku")
        goku.administrators.grant("bulma")
        self.store.update_user(goku)
        ensure.check_read_block(brl)
        goku.administrators.revoke("bulma")
        self.store.update_user(goku)
        self.assertRaises(ForbiddenException, ensure.check_read_block, brl)

        bper = ElementPermissions(brl, private=True)
        bper.read.grant("bulma")
        self.store.upsert_block_permissions(bper)
        ensure.check_read_block(brl)
        bper.read.remove("bulma")
        self.store.upsert_block_permissions(bper)
        self.assertRaises(ForbiddenException, ensure.check_read_block, brl)

    def test_write_block(self):
        # 1. Onwer can write the block if its private
        brl = BRLBlock("goku/goku/block/master")
        self._add_block_to_user("goku", brl, True)

        ensure = Security("goku", self.store)
        self._subscribe("goku", "enterprise_275_50_x")
        ensure.check_write_block(brl)

        # If the owner is not paying he can't write
        ensure = Security("goku", self.store)
        self._subscribe("goku", "free")
        self.assertRaises(ForbiddenException, ensure.check_write_block, brl)
        self._subscribe("goku", "enterprise_275_50_x")

        # 1b. But other not granted user can't write
        ensure = Security("freezer", self.store)
        self._subscribe("freezer", "enterprise_275_50_x")
        self.assertRaises(ForbiddenException, ensure.check_write_block, brl)

        # 2. If bulma is granted as administrator or write he can write
        ensure = Security("bulma", self.store)
        self._subscribe("bulma", "enterprise_275_50_x")
        goku = self.store.read_user("goku")
        goku.administrators.grant("bulma")
        self.store.update_user(goku)
        ensure.check_write_block(brl)
        goku.administrators.revoke("bulma")
        self.store.update_user(goku)
        self.assertRaises(ForbiddenException, ensure.check_write_block, brl)

        bper = ElementPermissions(brl, private=True)
        bper.write.grant("bulma")
        self.store.upsert_block_permissions(bper)
        ensure.check_write_block(brl)
        bper.write.remove("bulma")
        self.store.upsert_block_permissions(bper)
        self.assertRaises(ForbiddenException, ensure.check_write_block, brl)

        # 3. If we give read permissions only, user cant write
        bper = ElementPermissions(brl, private=True)
        bper.read.grant("bulma")
        self.store.upsert_block_permissions(bper)
        self.assertRaises(ForbiddenException, ensure.check_write_block, brl)

    def test_delete_block(self):
        # First create master block permissions. Public
        brl = BRLBlock("goku/goku/block/master")
        bper_master = ElementPermissions(brl, private=True)
        self.store.upsert_block_permissions(bper_master)

        # 1. Owner can always delete a private block, even if i am not paying
        ensure = Security("goku", self.store)
        self._subscribe("goku", "enterprise_275_50_x")
        ensure.check_delete_block(brl)

        self._subscribe("freezer", "free")
        ensure.check_delete_block(brl)

        # 2. Other user can't delete block
        ensure = Security("freezer", self.store)
        self._subscribe("freezer", "enterprise_275_50_x")
        self.assertRaises(ForbiddenException, ensure.check_delete_block, brl)

        # 3. A user with read and write permissions cant delete
        ensure = Security("bulma", self.store)
        bper = ElementPermissions(brl, private=True)
        bper.write.grant("bulma")
        bper.read.grant("bulma")
        self.store.upsert_block_permissions(bper)
        self.assertRaises(ForbiddenException, ensure.check_delete_block, brl)

        # 3. But an admin user can delete it
        goku = self.store.read_user("goku")
        goku.administrators.grant("bulma")
        self.store.update_user(goku)
        ensure.check_delete_block(brl)

    def test_create_block(self):
        brl = BRLBlock("goku/goku/block/master")

        # Always can make a block if its public
        ensure = Security("goku", self.store)
        self._subscribe("goku", "free")
        ensure.check_create_block(brl.owner, private=False)

        # Only can make a private block if subscription is ok
        self.assertRaises(ForbiddenException, ensure.check_create_block, brl.owner, private=True)
        self._subscribe("goku", "enterprise_275_50_x")
        ensure.check_create_block(brl.owner, private=True)

        # Other user can create a block in my namespace if its an admin, not write and read is enought
        ensure = Security("bulma", self.store)
        self._subscribe("bulma", "enterprise_275_50_x")
        self.assertRaises(ForbiddenException, ensure.check_create_block, brl.owner, private=True)

        bper = ElementPermissions(brl.owner, private=True)
        bper.write.grant("bulma")
        bper.read.grant("bulma")
        self.store.upsert_block_permissions(bper)
        self.assertRaises(ForbiddenException, ensure.check_create_block, brl.owner, private=True)

        # 3. But an admin user can delete it
        goku = self.store.read_user("goku")
        goku.administrators.grant("bulma")
        self.store.update_user(goku)
        ensure.check_create_block(brl.owner, private=True)
        ensure.check_create_block(brl.owner, private=False)

    def test_check_publish_block(self):
        # 1. Onwer can write the block if its private
        brl = BRLBlock("goku/goku/block/master")
        self._add_block_to_user("goku", brl, True)

        ensure = Security("goku", self.store)
        self._subscribe("goku", "enterprise_275_50_x")

        pack = PublishRequest(BlockVersion(brl, -1))
        pack.cells.append(SimpleCell('user/block/r1.h'))
        pack.contents['r1.h'] = Content(id_=None, load=Blob('hola'))
        pack.versiontag = 'mytag'

        ensure.check_publish_block(brl, pack)

        # If the owner is not paying he can't write
        ensure = Security("goku", self.store)
        self._subscribe("goku", "free")
        self.assertRaises(ForbiddenException, ensure.check_publish_block, brl, pack)
        self._subscribe("goku", "enterprise_275_50_x")

        # 1b. But other not granted user can't write
        ensure = Security("freezer", self.store)
        self._subscribe("freezer", "enterprise_275_50_x")
        self.assertRaises(ForbiddenException, ensure.check_publish_block, brl, pack)

        # 2. If bulma is granted as administrator or write he can write
        ensure = Security("bulma", self.store)
        self._subscribe("bulma", "enterprise_275_50_x")
        goku = self.store.read_user("goku")
        goku.administrators.grant("bulma")
        self.store.update_user(goku)
        ensure.check_publish_block(brl, pack)
        goku.administrators.revoke("bulma")
        self.store.update_user(goku)
        self.assertRaises(ForbiddenException, ensure.check_publish_block, brl, pack)

        bper = ElementPermissions(brl, private=True)
        bper.write.grant("bulma")
        self.store.upsert_block_permissions(bper)
        ensure.check_publish_block(brl, pack)
        bper.write.remove("bulma")
        self.store.upsert_block_permissions(bper)
        self.assertRaises(ForbiddenException, ensure.check_publish_block, brl, pack)

        # 3. If we give read permissions only, user cant write
        bper = ElementPermissions(brl, private=True)
        bper.read.grant("bulma")
        self.store.upsert_block_permissions(bper)
        self.assertRaises(ForbiddenException, ensure.check_publish_block, brl, pack)

    def test_update_user(self):
        # Can do it himself and their administrators

        ensure = Security("goku", self.store)
        self._subscribe("goku", "enterprise_275_50_x")
        ensure.check_update_user("goku")

        self._subscribe("goku", "free")
        ensure.check_update_user("goku")

        # Other admin-granted user can't do it
        goku = self.store.read_user("goku")
        goku.administrators.grant("bulma")
        self.store.update_user(goku)

        ensure = Security("bulma", self.store)
        ensure.check_update_user("goku")

    def _subscribe(self, brl_user, plan_id):
        sub = self.store.read_user_subscription(brl_user)
        sub.ID = brl_user
        sub.plan_id = plan_id
        self.store.update_user_subscription(sub)
        return sub

    def _add_block_to_user(self, brl_user, brl_block, private):
        brl_block = BRLBlock(brl_block)
        user = self.store.read_user(brl_user)
        user.add_block(brl_block)
        self.store.update_user(user)

        bper_master = ElementPermissions(brl_block, private)
        self.store.upsert_block_permissions(bper_master)

    def test_subscription_limits(self):

        # Create users for test
        self.store.create_user(User("cooper"))
        self.store.create_user(User("bob"))
        self.store.create_user(User("lady_lug"))

        # Coop has a private block and a public block
        public_brl = BRLBlock("cooper/cooper/public_block/master")
        private_brl = BRLBlock("cooper/cooper/private_block/master")
        self._add_block_to_user("cooper", public_brl, False)
        self._add_block_to_user("cooper", private_brl, True)

        # 1 contributor and unlimited private blocks
        self._subscribe("cooper", "personal_7_1_x")

        # Add an administrator
        ensure = Security("cooper", self.store)
        ensure.check_grant_administrator_for("cooper", "bob")
        cooper = self.store.read_user("cooper")
        cooper.administrators.grant("bob")
        self.store.update_user(cooper)

        # Try to add another one, it must fail
        self.assertRaises(PlanUpgradeNeeded,
                          ensure.check_grant_administrator_for,
                          "cooper", "lady_lug")

        # Try to add write permissions to a public block. Its ok
        ensure.check_grant_read_or_write_permissions_to("lady_lug", public_brl)

        # Try to add write permissions to a private block, but a bob (already admin)
        ensure.check_grant_read_or_write_permissions_to("bob", private_brl)

        # Try to add write permissions to a private block. It must fail
        self.assertRaises(PlanUpgradeNeeded,
                          ensure.check_grant_read_or_write_permissions_to,
                          "lady_lug", private_brl)

        # Remove Adminsitrator, try to add write permissions in a private block. Its ok
        cooper = self.store.read_user("cooper")
        cooper.administrators.revoke("bob")
        self.store.update_user(cooper)
        ensure.check_grant_read_or_write_permissions_to("lady_lug", private_brl)
        cooper.administrators.grant("lady_lug")
        self.store.update_user(cooper)

        # Subscribe to a bigger plan and check limits
        self._subscribe("cooper", "startup_35_5_x")
        # Add 4 more
        for tmp in xrange(4):
            new_user = BRLUser("user%s" % tmp)
            ensure.check_grant_read_or_write_permissions_to(new_user, private_brl)
            bper = self.store.read_block_permissions(private_brl)
            bper.write.grant(new_user)
            self.store.upsert_block_permissions(bper)

        # The sixth must fail
        self.assertRaises(PlanUpgradeNeeded,
                          ensure.check_grant_read_or_write_permissions_to,
                          "new_user", private_brl)

        # unless user is already a contributor
        ensure.check_grant_read_or_write_permissions_to("lady_lug", private_brl)

    def test_change_subscription(self):
        # Create users for test
        self.store.create_user(User("cooper"))
        ensure = Security("cooper", self.store)
        self._subscribe("cooper", "startup_35_5_x")

        # Coop has a private block
        private_brl = BRLBlock("cooper/cooper/private_block/master")
        self._add_block_to_user("cooper", private_brl, True)

        for tmp in xrange(4):
            new_user = BRLUser("user%s" % tmp)
            ensure.check_grant_read_or_write_permissions_to(new_user, private_brl)
            bper = self.store.read_block_permissions(private_brl)
            bper.write.grant(new_user)
            self.store.upsert_block_permissions(bper)

        # Try to downgrade to personal plan
        with self.assertRaisesRegexp(ForbiddenException, "You are currently using 4 users, "
                                                         "reduce to 1 before plan downgrade"):
            ensure.check_can_change_current_subscription("cooper", "personal_7_1_x")

        # Remove collaborators to 1
        for tmp in xrange(3):
            new_user = BRLUser("user%s" % tmp)
            ensure.check_grant_read_or_write_permissions_to(new_user, private_brl)
            bper = self.store.read_block_permissions(private_brl)
            bper.write.revoke(new_user)
            self.store.upsert_block_permissions(bper)

        # Try to downgrade to personal plan
        ensure.check_can_change_current_subscription("cooper", "personal_7_1_x")

        # Try to downgrade to free plan
        with self.assertRaisesRegexp(ForbiddenException, "You are currently using 1 users, "
                                                         "reduce to 0 before plan downgrade"):
            ensure.check_can_change_current_subscription("cooper", "free")

        # Remove last collaborator
        bper = self.store.read_block_permissions(private_brl)
        bper.write.revoke("user3")
        self.store.upsert_block_permissions(bper)

        with self.assertRaisesRegexp(ForbiddenException, "You have 1 private blocks, "
                                                         "reduce it to 0 before plan downgrade"):
            ensure.check_can_change_current_subscription("cooper", "free")

    def test_check_read_user_subscription(self):
        # Can do it himself (always, event not paying) and not their administrators
        ensure = Security("goku", self.store)
        self._subscribe("goku", "enterprise_275_50_x")
        ensure.check_read_user_subscription("goku")

        self._subscribe("goku", "free")
        ensure.check_read_user_subscription("goku")

        # Other admin-granted  user cant do it
        goku = self.store.read_user("goku")
        goku.administrators.grant("bulma")
        self.store.update_user(goku)

        ensure = Security("bulma", self.store)
        ensure.check_read_user_subscription("goku")
class PublishServiceTest(unittest.TestCase):
    def test_publish_rejected(self):
        store = Mock(MongoServerStore)
        user = Mock()
        user.blocks = {}
        store.read_user = Mock(return_value=user)

        block = Mock(Block)
        block.add_publication.return_value = (Mock(), Mock())
        store.read_block.return_value = block
        brl = BRLBlock('user/user/block/branch')

        p = PublishService(store, 'authUser')
        pack = PublishRequest(BlockVersion(brl, -1))
        pack.cells.append(SimpleCell('user/block/r1.h'))
        pack.contents['r1.h'] = Content(id_=None, load=Blob('hola'))
        pack.deptable = BlockVersionTable()
        with self.assertRaises(ForbiddenException):
            p.publish(pack)

    @patch.object(Enqueuer, "enqueue_job")
    def test_publish(self, enqueuer):
        brl = BRLBlock('owner/user/block/branch')
        # moduleID=BlockID(UserID(123),456)
        store = Mock(MongoServerStore)
        store.read_block_permissions = Mock(
            return_value=ElementPermissions(brl, private=False))
        user = User("owner")
        user.numeric_id = 1
        user.blocks = {}
        store.read_user = Mock(return_value=user)
        block = Mock(Block)
        block.last_version.return_value = Mock(BlockVersion)
        block.add_publication.return_value = (Mock(list), Mock(list),
                                              Mock(list), Mock(list))
        block.deltas = []

        ensure = Security('authUser', store)
        ensure.check_create_block = Mock(return_value=True)
        ensure.check_write_block = Mock(return_value=True)
        ensure.check_read_block = Mock(return_value=True)

        store.read_block.return_value = block
        store.read_published_cells.return_value = {}
        p = PublishService(store, 'authUser')
        p.security = ensure

        pack = PublishRequest(BlockVersion(brl, -1))
        pack.cells.append(SimpleCell('user/block/r1.h'))
        pack.contents['r1.h'] = Content(id_=None, load=Blob('hola'))
        pack.cells.append(SimpleCell('user/block/r2.h'))
        pack.contents['r2.h'] = Content(id_=None, load=Blob('hola'))
        pack.cells.append(SimpleCell('user/block/r3.h'))
        pack.contents['r3.h'] = Content(id_=None, load=Blob('hola'))
        pack.deptable = BlockVersionTable()
        p.publish(pack)

        block.add_publication.assert_called_once_with(pack, p.auth_user)
        store.update_block.assert_called_once_with(block)
        self.assertEqual(1, store.create_published_cells.call_count)
        self.assertEqual(1, store.create_published_contents.call_count)

        # Check sizes
        self.assertEquals(user.blocks_bytes, 12)  # 12 bytes "hola" * 3

        # Publish again, see the size incremented
        pack._bytes = None  # Lazy computed
        p.publish(pack)
        self.assertEquals(user.blocks_bytes,
                          24)  # 24 bytes: "hola" * 3 * 2 publications

        # Max size exceeded for user
        user.max_workspace_size = 25
        self.assertRaises(ForbiddenException, p.publish, pack)

        # Try to publish only 1 byte
        pack._bytes = None  # Lazy computed
        pack.cells = []
        pack.contents = {}
        pack.cells.append(SimpleCell('user/block/r1.h'))
        pack.contents['r1.h'] = Content(id_=None, load=Blob('h'))
        p.publish(pack)

    @patch.object(Enqueuer, "enqueue_job")
    def test_publish_no_contents(self, enqueuer):
        brl = BRLBlock('owner/user/block/branch')
        store = Mock(MongoServerStore)
        store.read_block_permissions = Mock(
            return_value=ElementPermissions(brl, private=False))

        p = PublishService(store, 'authUser')
        pack = PublishRequest(BlockVersion(brl, -1))
        pack.cells.append(SimpleCell('user/block/r1.h'))
        pack.contents['r1.h'] = Content(id_=None, load=Blob('hola'))
        pack.versiontag = 'mytag'
        with self.assertRaisesRegexp(PublishException, 'DEV'):
            p.publish(pack)

    @patch.object(Enqueuer, "enqueue_job")
    def test_publish_dev_with_tag(self, enqueuer):
        brl = BRLBlock('owner/user/block/branch')
        store = Mock(MongoServerStore)
        store.read_block_permissions = Mock(
            return_value=ElementPermissions(brl, private=False))
        user = Mock()
        user.blocks = {}
        store.read_user = Mock(return_value=user)

        block = Mock(Block)
        block.add_publication.return_value = (['mock_id'], [], [], [])
        block.deltas = []
        ensure = Security('authUser', store)
        ensure.check_read_block = Mock(return_value=True)
        ensure.check_create_block = Mock(return_value=True)
        ensure.check_write_block = Mock(return_value=True)
        ensure.check_publish_block = Mock(return_value=True)

        store.read_block.return_value = block
        store.read_published_cells.return_value = {}
        p = PublishService(store, 'authUser')
        p.security = ensure
        pack = PublishRequest(BlockVersion(brl, -1))
        pack.cells.append(SimpleCell('user/block/r1.h'))
        pack.deptable = BlockVersionTable()
        p.publish(pack)

    def test_publish_concurrent_modification(self):
        self.store = TestingMemServerStore()
        brl = 'user'
        self.store.create_user(User(brl))
        self.service = BiiService(self.store, brl)

        self.brl_block = BRLBlock('user/user/block/master')
        request = PublishRequest(BlockVersion(self.brl_block, -1))
        request.cells.append(SimpleCell('user/block/r1.h'))
        request.contents['r1.h'] = Content(id_=None, load=Blob('hola'))
        request.deptable = BlockVersionTable()
        request.tag = DEV
        self.service.publish(request)
        '''Branch 1 (from master) creates new resource'''
        self.brl_block1 = BRLBlock('user/user/block/branch1')
        request = PublishRequest(BlockVersion(self.brl_block, 0))
        request.cells.append(SimpleCell('user/block/r2.h'))
        request.contents['r2.h'] = Content(id_=None, load=Blob('adios'))
        request.deptable = BlockVersionTable()
        with self.assertRaisesRegexp(BiiException, 'Concurrent modification'):
            self.service.publish(request)

    def get_version_info_test(self):
        store = Mock(GenericServerStore)

        # Block doesn't exist and user is other
        p = PublishService(store, 'any_user')
        block_brl = BRLBlock("user/user/theblock/master")
        store.read_block_permissions = Mock(side_effect=NotInStoreException())
        block_info = p.get_block_info(block_brl)
        self.assertFalse(block_info.can_write)

        # Now block exists
        store.read_block_permissions = Mock(
            return_value=ElementPermissions(block_brl))

        # Block exists and user is the authorized one
        p = PublishService(store, 'theuser')
        block_brl = BRLBlock("theuser/theuser/theblock/master")
        block_info = p.get_block_info(block_brl)
        self.assertTrue(block_info.can_write)

        # No authorized write to an existing block
        p = PublishService(store, 'wronguser')
        user = Mock(User)
        user.administrators = Permissions()
        store.read_user = Mock(return_value=user)
        block_info = p.get_block_info(block_brl)
        self.assertFalse(block_info.can_write)

        # Authorized user with an existing block
        p = PublishService(store, 'theuser')
        block_brl = BRLBlock("theuser/theuser/theblock/master")
        block_info = p.get_block_info(block_brl)
        self.assertTrue(block_info.can_write)