class SecureNamespaceAPIWithSuperuserTest(FluidinfoTestCase): resources = [('cache', CacheResource()), ('config', ConfigResource()), ('store', DatabaseResource())] def setUp(self): super(SecureNamespaceAPIWithSuperuserTest, self).setUp() system = createSystemData() user = system.users[u'fluiddb'] self.namespaces = SecureNamespaceAPI(user) self.permissions = CachingPermissionAPI(user) def testCreateIsAllowed(self): """ Creating a new L{Namespace} should be allowed if we're a user with a L{Role.SUPERUSER} no matter what permissions we have. """ values = [(u'fluiddb', Operation.CREATE_NAMESPACE, Policy.CLOSED, [])] self.permissions.set(values) result = self.namespaces.create([(u'fluiddb/test', u'description')]) self.assertEqual(1, len(result)) def testDeleteIsAllowed(self): """ Deleting a L{Namespace} should be allowed if we're a user with a L{Role.SUPERUSER} no matter what permissions we have. """ result1 = self.namespaces.create([(u'fluiddb/test', u'description')]) values = [(u'fluiddb/test', Operation.DELETE_NAMESPACE, Policy.CLOSED, [])] self.permissions.set(values) result2 = self.namespaces.delete([u'fluiddb/test']) self.assertEqual(result1, result2) def testSetIsAllowed(self): """ Updating a L{Namespace} should be allowed if we're a user with a L{Role.SUPERUSER} no matter what permissions we have. """ self.namespaces.create([(u'fluiddb/test', u'description')]) values = [(u'fluiddb/test', Operation.UPDATE_NAMESPACE, Policy.CLOSED, [])] self.permissions.set(values) self.namespaces.set({u'fluiddb/test': u'new description'}) def testGetIsAllowed(self): """ Getting information about a L{Namespace} should be allowed if we're a user with a L{Role.SUPERUSER} no matter what permissions we have. """ self.namespaces.create([(u'fluiddb/test', u'description')]) values = [(u'fluiddb/test', Operation.LIST_NAMESPACE, Policy.CLOSED, [])] self.permissions.set(values) result = self.namespaces.get([u'fluiddb'], withDescriptions=False, withTags=True, withNamespaces=True) self.assertEqual(1, len(result))
class SecurePermissionAPI(object): """The public API to secure permission-related functionality. @param user: The L{User} to perform operations on behalf of. """ def __init__(self, user): self._user = user self._permissions = CachingPermissionAPI(user) def get(self, values): """See L{PermissionAPI.get}. @raise PermissionDeniedError: Raised if the user is not authorized to see the specified permissions. """ self._checkPermissions(values) return self._permissions.get(values) def set(self, values): """See L{PermissionAPI.set}. @raise PermissionDeniedError: Raised if the user is not authorized to change the specified permissions. """ self._checkPermissions([(path, operation) for path, operation, _, _ in values]) return self._permissions.set(values) def _checkPermissions(self, values): """Check C{CONTROL} permissions for a set of path-operation pairs. @param values: A sequence of C{(path, Operation)} 2-tuples with the that should be checked. @raise PermissionDeniedError: Raised if the user doesn't have C{CONTROL} permissions for a given path-L{Operation} pair. @raise RuntimeError: Raised if an invalid L{Operation} is provided. """ pathsAndOperations = set() for path, operation in values: if operation in [Operation.WRITE_TAG_VALUE, Operation.READ_TAG_VALUE, Operation.DELETE_TAG_VALUE, Operation.CONTROL_TAG_VALUE]: pathsAndOperations.add((path, Operation.CONTROL_TAG_VALUE)) elif operation in [Operation.UPDATE_TAG, Operation.DELETE_TAG, Operation.CONTROL_TAG]: pathsAndOperations.add((path, Operation.CONTROL_TAG)) elif operation in Operation.NAMESPACE_OPERATIONS: pathsAndOperations.add((path, Operation.CONTROL_NAMESPACE)) else: raise RuntimeError('Invalid operation %r.' % operation) deniedOperations = checkPermissions(self._user, pathsAndOperations) if deniedOperations: raise PermissionDeniedError(self._user.username, deniedOperations)
class SecureTagAPIWithSuperuserTest(FluidinfoTestCase): resources = [('cache', CacheResource()), ('config', ConfigResource()), ('store', DatabaseResource())] def setUp(self): super(SecureTagAPIWithSuperuserTest, self).setUp() system = createSystemData() user = system.users[u'fluiddb'] self.tags = SecureTagAPI(user) self.permissions = CachingPermissionAPI(user) def testCreateIsAllowed(self): """ Creating a new L{Tag} should be allowed if we're a user with a L{Role.SUPERUSER} no matter what permissions we have. """ values = [(u'fluiddb', Operation.CREATE_NAMESPACE, Policy.CLOSED, [])] self.permissions.set(values) result = self.tags.create([(u'fluiddb/test', u'description')]) self.assertEqual(1, len(result)) def testDeleteIsAllowed(self): """ Deleting a L{Tag} should be allowed if we're a user with a L{Role.SUPERUSER} no matter what permissions we have. """ result1 = self.tags.create([(u'fluiddb/test', u'description')]) values = [(u'fluiddb/test', Operation.DELETE_TAG, Policy.CLOSED, [])] self.permissions.set(values) result2 = self.tags.delete([u'fluiddb/test']) self.assertEqual(result1, result2) def testSetIsAllowed(self): """ Updating a L{Tag} should be allowed if we're a user with a L{Role.SUPERUSER} no matter what permissions we have. """ result = self.tags.create([(u'fluiddb/test', u'A description')]) [(objectID, _)] = result values = [(u'fluiddb/test', Operation.UPDATE_TAG, Policy.CLOSED, [])] self.permissions.set(values) self.tags.set({u'fluiddb/test': u'A new description'}) result = self.tags.get([u'fluiddb/test'], withDescriptions=True) expected = { u'fluiddb/test': { 'id': objectID, 'description': u'A new description' } } self.assertEqual(expected, result)
class SecureTagAPIWithSuperuserTest(FluidinfoTestCase): resources = [('cache', CacheResource()), ('config', ConfigResource()), ('store', DatabaseResource())] def setUp(self): super(SecureTagAPIWithSuperuserTest, self).setUp() system = createSystemData() user = system.users[u'fluiddb'] self.tags = SecureTagAPI(user) self.permissions = CachingPermissionAPI(user) def testCreateIsAllowed(self): """ Creating a new L{Tag} should be allowed if we're a user with a L{Role.SUPERUSER} no matter what permissions we have. """ values = [(u'fluiddb', Operation.CREATE_NAMESPACE, Policy.CLOSED, [])] self.permissions.set(values) result = self.tags.create([(u'fluiddb/test', u'description')]) self.assertEqual(1, len(result)) def testDeleteIsAllowed(self): """ Deleting a L{Tag} should be allowed if we're a user with a L{Role.SUPERUSER} no matter what permissions we have. """ result1 = self.tags.create([(u'fluiddb/test', u'description')]) values = [(u'fluiddb/test', Operation.DELETE_TAG, Policy.CLOSED, [])] self.permissions.set(values) result2 = self.tags.delete([u'fluiddb/test']) self.assertEqual(result1, result2) def testSetIsAllowed(self): """ Updating a L{Tag} should be allowed if we're a user with a L{Role.SUPERUSER} no matter what permissions we have. """ result = self.tags.create([(u'fluiddb/test', u'A description')]) [(objectID, _)] = result values = [(u'fluiddb/test', Operation.UPDATE_TAG, Policy.CLOSED, [])] self.permissions.set(values) self.tags.set({u'fluiddb/test': u'A new description'}) result = self.tags.get([u'fluiddb/test'], withDescriptions=True) expected = {u'fluiddb/test': {'id': objectID, 'description': u'A new description'}} self.assertEqual(expected, result)
class SecureTagValueAPIWithSuperuserRoleTest(FluidinfoTestCase): resources = [('cache', CacheResource()), ('config', ConfigResource()), ('store', DatabaseResource())] def setUp(self): super(SecureTagValueAPIWithSuperuserRoleTest, self).setUp() system = createSystemData() self.superuser = system.users[u'fluiddb'] TagAPI(self.superuser).create([(u'fluiddb/tag', u'description')]) self.tagValues = SecureTagValueAPI(self.superuser) self.permissions = CachingPermissionAPI(self.superuser) def testGetIsAllowed(self): """L{SecureTagValueAPI.get} is always allowed for the superuser.""" objectID = uuid4() values = {objectID: {u'fluiddb/tag': 16}} self.tagValues.set(values) self.permissions.set([(u'fluiddb/tag', Operation.READ_TAG_VALUE, Policy.CLOSED, [])]) result = self.tagValues.get(objectIDs=[objectID], paths=[u'fluiddb/tag']) self.assertEqual(16, result[objectID][u'fluiddb/tag'].value) def testSetIsAllowed(self): """L{SecureTagValueAPI.set} is always allowed for the superuser.""" self.permissions.set([(u'fluiddb/tag', Operation.WRITE_TAG_VALUE, Policy.CLOSED, [])]) objectID = uuid4() values = {objectID: {u'fluiddb/tag': 16}} self.tagValues.set(values) result = self.tagValues.get(objectIDs=[objectID], paths=[u'fluiddb/tag']) self.assertEqual(16, result[objectID][u'fluiddb/tag'].value) def testDeleteIsAllowed(self): """L{SecureTagValueAPI.delete} is always allowed for the superuser.""" self.permissions.set([(u'fluiddb/tag', Operation.DELETE_TAG_VALUE, Policy.CLOSED, [])]) objectID = uuid4() values = {objectID: {u'fluiddb/tag': 16}} self.tagValues.set(values) self.tagValues.delete([(objectID, u'fluiddb/tag')]) result = self.tagValues.get(objectIDs=[objectID], paths=[u'fluiddb/tag']) self.assertEqual({}, result)
class SecureTagAPIWithNormalUserTest(FluidinfoTestCase): resources = [('cache', CacheResource()), ('config', ConfigResource()), ('store', DatabaseResource())] def setUp(self): super(SecureTagAPIWithNormalUserTest, self).setUp() createSystemData() UserAPI().create([(u'user', u'password', u'User', u'*****@*****.**') ]) self.user = getUser(u'user') self.permissions = CachingPermissionAPI(self.user) self.tags = SecureTagAPI(self.user) def testCreateIsAllowed(self): """ L{SecureTagAPI.create} should allow the creation of tags whose parent namespace has open C{Operation.CREATE_NAMESPACE} permissions. """ result = self.tags.create([(u'user/test', u'description')]) self.assertEqual(1, len(result)) def testCreateIsDenied(self): """ L{SecureTagAPI.create} should raise L{PermissonDeniedError} if the user doesn't have C{Operation.CREATE_NAMESPACE} permissions on the parent namespace. """ values = [(u'user', Operation.CREATE_NAMESPACE, Policy.CLOSED, [])] self.permissions.set(values) error = self.assertRaises(PermissionDeniedError, self.tags.create, [(u'user/test', u'description')]) self.assertEqual([(u'user', Operation.CREATE_NAMESPACE)], sorted(error.pathsAndOperations)) def testDeleteIsAllowed(self): """ L{SecureTagAPI.delete} should allow the deletion of a tag if the user has C{Operation.DELETE_TAG} permissions. """ result1 = self.tags.create([(u'user/test', u'description')]) result2 = self.tags.delete([u'user/test']) self.assertEqual(result1, result2) def testDeleteIsDenied(self): """ L{SecureTagAPI.delete} should raise L{PermissonDeniedError} if the user doesn't have C{Operation.DELETE_TAG} permissions. """ self.tags.create([(u'user/test', u'description')]) values = [(u'user/test', Operation.DELETE_TAG, Policy.OPEN, [u'user'])] self.permissions.set(values) error = self.assertRaises(PermissionDeniedError, self.tags.delete, [(u'user/test')]) self.assertEqual([(u'user/test', Operation.DELETE_TAG)], sorted(error.pathsAndOperations)) def testSetIsAllowed(self): """ L{SecureTagAPI.get} should allow updating the description of a tag if the user has permissions. """ [(objectID, _)] = self.tags.create([(u'user/test', u'A description')]) self.tags.set({u'user/test': u'A new description'}) result = self.tags.get([u'user/test'], withDescriptions=True) expected = { u'user/test': { 'id': objectID, 'description': u'A new description' } } self.assertEqual(expected, result) def testSetIsDenied(self): """ L{SecureTagAPI.get} should raise L{PermissonDeniedError} if the user doesn't have C{Operation.UPDATE_TAG} permissions when trying to update a tag's description. """ self.tags.create([(u'user/test', u'description')]) values = [(u'user/test', Operation.UPDATE_TAG, Policy.CLOSED, [])] self.permissions.set(values) error = self.assertRaises(PermissionDeniedError, self.tags.set, {u'user/test': u'description'}) self.assertEqual([(u'user/test', Operation.UPDATE_TAG)], sorted(error.pathsAndOperations))
class SecureNamespaceAPIWithNormalUserTest(FluidinfoTestCase): resources = [('cache', CacheResource()), ('config', ConfigResource()), ('store', DatabaseResource())] def setUp(self): super(SecureNamespaceAPIWithNormalUserTest, self).setUp() createSystemData() UserAPI().create([(u'user', u'password', u'User', u'*****@*****.**') ]) self.user = getUser(u'user') self.permissions = CachingPermissionAPI(self.user) self.namespaces = SecureNamespaceAPI(self.user) def testCreateIsAllowed(self): """ L{SecureNamespaceAPI.create} should allow the creation of namespaces whose parent has open CREATE permissions. """ values = [(u'user', Operation.CREATE_NAMESPACE, Policy.OPEN, [])] self.permissions.set(values) result = self.namespaces.create([(u'user/test', u'description')]) self.assertEqual(1, len(result)) def testCreateIsDenied(self): """ L{SecureNamespaceAPI.create} should raise L{PermissonDeniedError} if the user doesn't have CREATE permissions on the parent namespace. """ values = [(u'user', Operation.CREATE_NAMESPACE, Policy.CLOSED, [])] self.permissions.set(values) error = self.assertRaises(PermissionDeniedError, self.namespaces.create, [(u'user/test', u'description')]) self.assertEqual([(u'user', Operation.CREATE_NAMESPACE)], sorted(error.pathsAndOperations)) def testDeleteIsAllowed(self): """ {SecureNamespaceAPI.delete} should allow the deletion of a namespace if the user has DELETE permissions. """ result1 = self.namespaces.create([(u'user/test', u'description')]) values = [(u'user/test', Operation.DELETE_NAMESPACE, Policy.OPEN, [])] self.permissions.set(values) result2 = self.namespaces.delete([u'user/test']) self.assertEqual(result1, result2) def testDeleteIsDenied(self): """ L{SecureNamespaceAPI.delete} should raise L{PermissonDeniedError} if the user doesn't have DELETE permissions. """ self.namespaces.create([(u'user/test', u'description')]) values = [(u'user/test', Operation.DELETE_NAMESPACE, Policy.OPEN, [u'user'])] self.permissions.set(values) error = self.assertRaises(PermissionDeniedError, self.namespaces.delete, [(u'user/test')]) self.assertEqual([(u'user/test', Operation.DELETE_NAMESPACE)], sorted(error.pathsAndOperations)) def testGetChildNamespacesIsAllowed(self): """ L{SecureNamespaceAPI.get} should allow getting a list of child namespaces if the user has permissions. """ self.namespaces.create([(u'user/test', u'description')]) values = [(u'user', Operation.LIST_NAMESPACE, Policy.OPEN, [])] self.permissions.set(values) result = self.namespaces.get([u'user'], withNamespaces=True) self.assertEqual(1, len(result)) def testGetChildNamespacesIsDenied(self): """ L{SecureNamespaceAPI.get} should raise L{PermissonDeniedError} if the user doesn't have LIST permissions when trying to get the child namespaces. """ self.namespaces.create([(u'user/test', u'description')]) values = [(u'user', Operation.LIST_NAMESPACE, Policy.CLOSED, [])] self.permissions.set(values) error = self.assertRaises(PermissionDeniedError, self.namespaces.get, [(u'user')], withNamespaces=True) self.assertEqual([(u'user', Operation.LIST_NAMESPACE)], sorted(error.pathsAndOperations)) def testGetChildTagsIsAllowed(self): """ L{SecureNamespaceAPI.get} should allow getting a list of child tags if the user has permissions. """ self.namespaces.create([(u'user/test', u'description')]) values = [(u'user', Operation.LIST_NAMESPACE, Policy.CLOSED, [u'user']) ] self.permissions.set(values) result = self.namespaces.get([u'user'], withTags=True) self.assertEqual(1, len(result)) def testGetChildTagsIsDenied(self): """ L{SecureNamespaceAPI.get} should raise L{PermissonDeniedError} if the user doesn't have LIST permissions when trying to get the child tags. """ self.namespaces.create([(u'user/test', u'description')]) values = [(u'user', Operation.LIST_NAMESPACE, Policy.OPEN, [u'user'])] self.permissions.set(values) error = self.assertRaises(PermissionDeniedError, self.namespaces.get, [(u'user')], withTags=True) self.assertEqual([(u'user', Operation.LIST_NAMESPACE)], sorted(error.pathsAndOperations)) def testSetIsAllowed(self): """ L{SecureNamespaceAPI.get} should allow updating the description of a namespace if the user has permissions. """ self.namespaces.create([(u'user/test', u'description')]) values = [(u'user/test', Operation.UPDATE_NAMESPACE, Policy.OPEN, [])] self.permissions.set(values) self.namespaces.set({u'user/test': u'description'}) def testSetIsDenied(self): """ L{SecureNamespaceAPI.get} should raise L{PermissonDeniedError} if the user doesn't have UPDATE permissions when trying to update a namespace's description. """ self.namespaces.create([(u'user/test', u'description')]) values = [(u'user/test', Operation.UPDATE_NAMESPACE, Policy.CLOSED, []) ] self.permissions.set(values) error = self.assertRaises(PermissionDeniedError, self.namespaces.set, {u'user/test': u'description'}) self.assertEqual([(u'user/test', Operation.UPDATE_NAMESPACE)], sorted(error.pathsAndOperations))
class FacadeObjectMixinTest(FluidinfoTestCase): resources = [('cache', CacheResource()), ('config', ConfigResource()), ('log', LoggingResource()), ('store', DatabaseResource()), ('threadPool', ThreadPoolResource())] def setUp(self): super(FacadeObjectMixinTest, self).setUp() self.system = createSystemData() self.transact = Transact(self.threadPool) factory = FluidinfoSessionFactory('API-9000') self.facade = Facade(self.transact, factory) UserAPI().create([(u'username', u'password', u'User', u'*****@*****.**')]) self.user = getUser(u'username') self.permissions = CachingPermissionAPI(self.user) @inlineCallbacks def testCreateObjectPermissionDenied(self): """ L{FacadeObjectMixin.createObject} raises a L{TUnauthorized} exception if the user is the anonymous user. """ self.store.commit() with login(u'anon', uuid4(), self.transact) as session: deferred = self.facade.createObject(session) yield self.assertFailure(deferred, TUnauthorized) @inlineCallbacks def testCreateObjectWithoutAboutValue(self): """ L{FacadeObjectAPI.createObject} always returns a valid C{UUID} in a C{str} for a new object ID if an about value is not given. """ self.store.commit() with login(u'username', uuid4(), self.transact) as session: objectID = yield self.facade.createObject(session) self.assertEqual(objectID, str(UUID(objectID))) @inlineCallbacks def testCreateObjectWithAboutValue(self): """ L{FacadeObjectAPI.createObject} always returns a valid C{UUID} in a C{str} for a new object ID if an about value is given and it doesn't already exist. """ self.store.commit() with login(self.user.username, uuid4(), self.transact) as session: objectID = yield self.facade.createObject(session, about='foo') objectID = UUID(objectID) self.store.rollback() value = getAboutTagValues([objectID], [u'foo']).one() self.assertEqual(u'foo', value.value) tag = self.system.tags[u'fluiddb/about'] value = getTagValues(values=[(objectID, tag.id)]).one() self.assertIdentical(self.system.users[u'fluiddb'], value.creator) @inlineCallbacks def testCreateObjectWithDuplicateAboutValue(self): """ L{FacadeObjectAPI.createObject} returns a valid C{UUID} in a C{str} for an existing object ID if an about value is given and already exists in the database. """ objectID = uuid4() createAboutTagValue(objectID, u'bar') values = {objectID: {u'fluiddb/about': u'bar'}} SecureTagValueAPI(self.system.superuser).set(values) self.store.commit() with login(self.user.username, uuid4(), self.transact) as session: resultObjectID = yield self.facade.createObject(session, about='bar') self.assertEqual(str(objectID), resultObjectID) @inlineCallbacks def testGetObject(self): """ L{FacadeObjectAPI.getObject} returns a L{TObjectInfo} with the L{Tag.path}s for which the L{User} has L{Operation.READ_TAG_VALUE}. """ objectID = uuid4() SecureTagAPI(self.user).create([(u'username/foo', u'A description')]) values = {objectID: {u'username/foo': u'bar'}} SecureTagValueAPI(self.user).set(values) self.store.commit() with login(self.user.username, uuid4(), self.transact) as session: objectInfo = yield self.facade.getObject(session, str(objectID)) self.assertEqual([u'username/foo'], objectInfo.tagPaths) self.assertEqual(None, objectInfo.about) @inlineCallbacks def testGetObjectWithAboutValue(self): """ L{FacadeObjectAPI.getObject} returns a L{TObjectInfo} with the L{Tag.path}s for which the L{User} has L{Operation.READ_TAG_VALUE}, and the L{AboutTagValue.value} if it has one and C{showAbout} is C{True}. """ objectID = uuid4() SecureTagAPI(self.user).create([(u'username/foo', u'A description')]) values = {objectID: {u'username/foo': u'bar'}} SecureTagValueAPI(self.user).set(values) aboutTag = self.system.tags[u'fluiddb/about'] createAboutTagValue(objectID, u'bar') createTagValue(self.user.id, aboutTag.id, objectID, u'about value') self.store.commit() with login(self.user.username, uuid4(), self.transact) as session: objectInfo = yield self.facade.getObject(session, str(objectID), showAbout=True) self.assertEqual([u'fluiddb/about', u'username/foo'], sorted(objectInfo.tagPaths)) self.assertEqual('about value', objectInfo.about) @inlineCallbacks def testGetObjectWithAboutValueDoesNotExist(self): """ L{FacadeObjectAPI.getObject} returns a L{TObjectInfo} with the L{Tag.path}s for which the L{User} has L{Operation.READ_TAG_VALUE}, and the L{AboutTagValue.value} if it has one and C{showAbout} is C{True}. """ objectID = uuid4() tag = createTag(self.user, self.user.namespace, u'foo') createTagPermission(tag) createTagValue(self.user.id, tag.id, objectID, u'bar') session = AuthenticatedSession(self.user.username, uuid4()) self.store.commit() with login(self.user.username, uuid4(), self.transact) as session: objectInfo = yield self.facade.getObject(session, str(objectID), showAbout=True) self.assertEqual([u'username/foo'], objectInfo.tagPaths) self.assertIdentical(None, objectInfo.about) @inlineCallbacks def testGetObjectDeniedPaths(self): """ L{FacadeObjectAPI.getObject} returns a L{TObjectInfo} with the L{Tag.path}s for which the L{User} has L{Operation.READ_TAG_VALUE}. """ SecureTagAPI(self.user).create([(u'username/tag1', u'description'), (u'username/tag2', u'description')]) objectID = uuid4() values = { objectID: { u'username/tag1': 16 }, objectID: { u'username/tag2': 16 } } SecureTagValueAPI(self.user).set(values) self.permissions.set([ (u'username/tag1', Operation.READ_TAG_VALUE, Policy.CLOSED, []), (u'username/tag2', Operation.READ_TAG_VALUE, Policy.OPEN, []) ]) self.store.commit() with login(self.user.username, uuid4(), self.transact) as session: objectInfo = yield self.facade.getObject(session, str(objectID)) self.assertEqual([u'username/tag2'], objectInfo.tagPaths) self.assertEqual(None, objectInfo.about) @inlineCallbacks def testGetObjectAllPathsAreDenied(self): """ L{FacadeObjectAPI.getObject} returns a L{TObjectInfo} with the L{Tag.path}s for which the L{User} has L{Operation.READ_TAG_VALUE}, if all of them are denied, L{FacadeObjectAPI.getObject} must return an empty L{TObjectInfo}. """ SecureTagAPI(self.user).create([(u'username/tag1', u'description'), (u'username/tag2', u'description')]) objectID = uuid4() values = { objectID: { u'username/tag1': 16 }, objectID: { u'username/tag2': 16 } } SecureTagValueAPI(self.user).set(values) self.permissions.set([ (u'username/tag1', Operation.READ_TAG_VALUE, Policy.CLOSED, []), (u'username/tag2', Operation.READ_TAG_VALUE, Policy.CLOSED, []) ]) self.store.commit() with login(self.user.username, uuid4(), self.transact) as session: objectInfo = yield self.facade.getObject(session, str(objectID)) self.assertEqual([], objectInfo.tagPaths) self.assertEqual(None, objectInfo.about)
class SecureObjectAPIWithAnonymousRoleTest(FluidinfoTestCase): resources = [('cache', CacheResource()), ('client', IndexResource()), ('config', ConfigResource()), ('store', DatabaseResource())] def setUp(self): super(SecureObjectAPIWithAnonymousRoleTest, self).setUp() system = createSystemData() self.anon = system.users[u'anon'] UserAPI().create([(u'username', u'password', u'User', u'*****@*****.**')]) self.user = getUser(u'username') self.tags = TagAPI(self.user) self.tags.create([(u'username/tag', u'description')]) self.permissions = CachingPermissionAPI(self.user) self.objects = SecureObjectAPI(self.anon) def testCreateIsDenied(self): """ L{SecureObjectAPI.create} raises a L{PermissionDeniedError} if it's invoked by a L{User} with the L{Role.ANONYMOUS}. """ objects = SecureObjectAPI(self.anon) error = self.assertRaises(PermissionDeniedError, objects.create) self.assertEqual(self.anon.username, error.username) self.assertEqual([(None, Operation.CREATE_OBJECT)], error.pathsAndOperations) def testGetTagsByObjectsPathIsAllowed(self): """ L{SecureObjectAPI.getTagsByObjects} will return all the tags for which the anonymous user has C{Operation.READ_TAG_VALUE} permissions. """ objectID = uuid4() values = {objectID: {u'username/tag': 16}} SecureTagValueAPI(self.user).set(values) self.permissions.set([(u'username/tag', Operation.READ_TAG_VALUE, Policy.OPEN, [])]) self.assertEqual({objectID: [u'username/tag']}, self.objects.getTagsByObjects([objectID])) def testGetTagsByObjectsReturnsOnlyAllowedTags(self): """ L{SecureObjectAPI.getTagsByObjects} will return all the tags for which the anonymous user has C{Operation.READ_TAG_VALUE} permissions, but not those for which the user doesn't have. """ self.tags.create([(u'username/tag1', u'description'), (u'username/tag2', u'description')]) objectID = uuid4() values = {objectID: {u'username/tag1': 16, u'username/tag2': 16}} SecureTagValueAPI(self.user).set(values) self.permissions.set([(u'username/tag1', Operation.READ_TAG_VALUE, Policy.CLOSED, []), (u'username/tag2', Operation.READ_TAG_VALUE, Policy.OPEN, [])]) result = self.objects.getTagsByObjects([objectID]) expected = {objectID: [u'username/tag2']} self.assertEqual(expected, result) def testGetTagsByObjectsReturnsNoneIfDenied(self): """ L{SecureObjectAPI.getTagsByObjects} will return an empty C{dict} if the L{User} does not have C{Operation.READ_TAG_VALUE} permission on none of the L{Tag}s an object has. """ self.tags.create([(u'username/tag1', u'description'), (u'username/tag2', u'description')]) objectID = uuid4() values = {objectID: {u'username/tag1': 16, u'username/tag2': 16}} SecureTagValueAPI(self.user).set(values) self.permissions.set([(u'username/tag1', Operation.READ_TAG_VALUE, Policy.CLOSED, []), (u'username/tag2', Operation.READ_TAG_VALUE, Policy.CLOSED, [])]) result = self.objects.getTagsByObjects([objectID]) self.assertEqual({}, result) def testGetTagsByObjectsWithCustomPermission(self): """ L{SecureObjectAPI.getTagsByObjects} optionally accepts a permission type to check for instead of L{Operation.READ_TAG_VALUE}). """ TagAPI(self.user).create([(u'username/open', u'An accessible tag'), (u'username/closed', u'A denied tag')]) objectID = uuid4() SecureTagValueAPI(self.user).set({objectID: {u'username/open': 13, u'username/closed': 17}}) self.permissions.set([(u'username/closed', Operation.DELETE_TAG_VALUE, Policy.CLOSED, [])]) result = self.objects.getTagsByObjects( [objectID], permission=Operation.DELETE_TAG_VALUE) # Result is empty because anonymous users are never allowed to delete # values. self.assertEqual({}, result) def testGetTagsForObjectsOnlyReturnsAccessibleTags(self): """ L{SecureObjectAPI.getTagsForObjects} only returns L{Tag.path}s that the user has C{Operation.READ_TAG_VALUE} permissions for. """ TagAPI(self.user).create([(u'username/tag1', u'description'), (u'username/tag2', u'description')]) objectID = uuid4() SecureTagValueAPI(self.user).set({objectID: {u'username/tag1': 13, u'username/tag2': 17}}) self.permissions.set([(u'username/tag2', Operation.READ_TAG_VALUE, Policy.CLOSED, [])]) self.assertEqual([u'username/tag1'], self.objects.getTagsForObjects([objectID])) @inlineCallbacks def testSearch(self): """ L{SecureObjectAPI.search} resolves the specified L{Query}s if the anonymous user has C{Operation.READ_TAG_VALUE} permissions on the requested L{Tag.path}s. """ objectID = uuid4() index = ObjectIndex(self.client) yield index.update({objectID: {u'username/tag': 42}}) yield self.client.commit() query = parseQuery(u'username/tag = 42') result = self.objects.search([query]) result = yield result.get() self.assertEqual({query: set([objectID])}, result) @inlineCallbacks def testSearchWithoutPermission(self): """ L{SecureObjectAPI.search} raises a L{PermissionDeniedError} if the anonymous user doesn't have C{Operation.READ_TAG_VALUE} permissions on the requested L{Tag.path}s. """ objectID = uuid4() index = ObjectIndex(self.client) yield index.update({objectID: {u'username/tag': 42}}) yield self.client.commit() self.permissions.set([(u'username/tag', Operation.READ_TAG_VALUE, Policy.CLOSED, [])]) query = parseQuery(u'username/tag = 42') error = self.assertRaises(PermissionDeniedError, self.objects.search, [query]) self.assertEqual(u'anon', error.username) self.assertEqual([('username/tag', Operation.READ_TAG_VALUE)], error.pathsAndOperations) @inlineCallbacks def testSearchWithImplicitObjectCreation(self): """ L{SecureObjectAPI.search} doesn't raise a L{PermissionDeniedError} if the anonymous user tries to create new objects using C{fluiddb/about} queries, instead an empty result is returned. """ query = parseQuery(u'fluiddb/about = "TestObject"') result = self.objects.search([query], True) result = yield result.get() self.assertEqual({query: set()}, result)
class FacadePermissionTest(FluidinfoTestCase): resources = [('cache', CacheResource()), ('config', ConfigResource()), ('log', LoggingResource()), ('store', DatabaseResource())] def setUp(self): super(FacadePermissionTest, self).setUp() self.transact = Transact(FakeThreadPool()) factory = FluidinfoSessionFactory('API-9000') self.facade = Facade(self.transact, factory) createSystemData() UserAPI().create([(u'username', u'password', u'User', u'*****@*****.**')]) user = getUser(u'username') self.permissions = CachingPermissionAPI(user) SecureTagAPI(user).create([(u'username/tag', u'description')]) @inlineCallbacks def testGetNamespacePermissions(self): """ L{FacadePermissionMixin.getPermission} returns a L{TPolicyAndExceptions} object with the policy and exceptions list for a given L{Namespace} path. """ self.permissions.set([(u'username', Operation.CREATE_NAMESPACE, Policy.CLOSED, [])]) with login(u'username', uuid4(), self.transact) as session: policyAndExceptions = yield self.facade.getPermission( session, u'namespaces', u'create', u'username') self.assertEqual(u'closed', policyAndExceptions.policy) self.assertEqual([], policyAndExceptions.exceptions) @inlineCallbacks def testGetTagPermissions(self): """ L{FacadePermissionMixin.getPermission} returns a L{TPolicyAndExceptions} object with the policy and exceptions list for a given L{Tag} path. """ self.permissions.set([(u'username/tag', Operation.UPDATE_TAG, Policy.CLOSED, [u'username'])]) with login(u'username', uuid4(), self.transact) as session: policyAndExceptions = yield self.facade.getPermission( session, u'tags', u'update', u'username/tag') self.assertEqual(u'closed', policyAndExceptions.policy) self.assertEqual([u'username'], policyAndExceptions.exceptions) @inlineCallbacks def testGetTagValuePermissions(self): """ L{FacadePermissionMixin.getPermission} returns a L{TPolicyAndExceptions} object with the policy and exceptions list for a given L{TagValue} path. """ self.permissions.set([(u'username/tag', Operation.WRITE_TAG_VALUE, Policy.CLOSED, [])]) with login(u'username', uuid4(), self.transact) as session: policyAndExceptions = yield self.facade.getPermission( session, u'tag-values', u'write', u'username/tag') self.assertEqual(u'closed', policyAndExceptions.policy) self.assertEqual([], policyAndExceptions.exceptions) @inlineCallbacks def testGetWithInvalidAction(self): """ L{FacadePermissionMixin.getPermission} raises a L{TBadRequest} error if the given C{action} is invalid. """ with login(u'username', uuid4(), self.transact) as session: deferred = self.facade.getPermission(session, u'namespaces', u'invalid', u'username') yield self.assertFailure(deferred, TBadRequest) @inlineCallbacks def testGetWithInvalidCategory(self): """ L{FacadePermissionMixin.getPermission} raises a L{TBadRequest} error if the given C{category} is invalid. """ with login(u'username', uuid4(), self.transact) as session: deferred = self.facade.getPermission(session, u'invalid', u'create', u'username') yield self.assertFailure(deferred, TBadRequest) @inlineCallbacks def testGetWithUnknownNamespace(self): """ L{FacadePermissionMixin.getPermission} raises a L{TNonexistentNamespace} error if the given L{Namespace} path does not exist. """ with login(u'username', uuid4(), self.transact) as session: deferred = self.facade.getPermission(session, u'namespaces', u'create', u'unknown') yield self.assertFailure(deferred, TNonexistentNamespace) @inlineCallbacks def testGetWithUnknownTag(self): """ L{FacadePermissionMixin.getPermission} raises a L{TNonexistentTag} error if the given L{Tag} path does not exist. """ with login(u'username', uuid4(), self.transact) as session: deferred = self.facade.getPermission( session, u'tags', u'update', u'username/unknown') yield self.assertFailure(deferred, TNonexistentTag) @inlineCallbacks def testGetNamespacePermissionsIsDenied(self): """ L{FacadePermissionMixin.getPermission} raises a L{TPathPermissionDenied} error if the user doesn't have C{Operation.CONTROL_NAMESPACE} permissions on the given L{Namespace}. """ self.permissions.set([(u'username', Operation.CONTROL_NAMESPACE, Policy.CLOSED, [])]) with login(u'username', uuid4(), self.transact) as session: deferred = self.facade.getPermission(session, u'namespaces', u'update', u'username') yield self.assertFailure(deferred, TPathPermissionDenied) @inlineCallbacks def testGetTagPermissionsIsDenied(self): """ L{FacadePermissionMixin.getPermission} raises a L{TPathPermissionDenied} error if the user doesn't have C{Operation.CONTROL_TAG} permissions on the given L{Tag}. """ self.permissions.set([(u'username/tag', Operation.CONTROL_TAG, Policy.CLOSED, [])]) with login(u'username', uuid4(), self.transact) as session: deferred = self.facade.getPermission(session, u'tags', u'delete', u'username/tag') yield self.assertFailure(deferred, TPathPermissionDenied) @inlineCallbacks def testGetTagValuePermissionsIsDenied(self): """ L{FacadePermissionMixin.getPermission} raises a L{TPathPermissionDenied} error if the user doesn't have C{Operation.CONTROL_TAG_VALUE} permissions on the given L{Tag}. """ self.permissions.set([(u'username/tag', Operation.CONTROL_TAG_VALUE, Policy.CLOSED, [])]) with login(u'username', uuid4(), self.transact) as session: deferred = self.facade.getPermission(session, u'tag-values', u'read', u'username/tag') yield self.assertFailure(deferred, TPathPermissionDenied) @inlineCallbacks def testSetNamespacePermissions(self): """ L{FacadePermissionMixin.updatePermission} updates the permissions for a given L{Namespace} path. """ policyAndExceptions = TPolicyAndExceptions(u'closed', []) with login(u'username', uuid4(), self.transact) as session: yield self.facade.updatePermission(session, u'namespaces', u'create', u'username', policyAndExceptions) pathAndAction = (u'username', Operation.CREATE_NAMESPACE) result = self.permissions.get([pathAndAction]) self.assertEqual((Policy.CLOSED, []), result[pathAndAction]) @inlineCallbacks def testSetTagPermissions(self): """ L{FacadePermissionMixin.updatePermission} updates the permissions for a given L{Tag} path. """ policyAndExceptions = TPolicyAndExceptions(u'open', [u'username']) with login(u'username', uuid4(), self.transact) as session: yield self.facade.updatePermission(session, u'tags', u'update', u'username/tag', policyAndExceptions) pathAndAction = (u'username/tag', Operation.UPDATE_TAG) result = self.permissions.get([pathAndAction]) self.assertEqual((Policy.OPEN, [u'username']), result[pathAndAction]) @inlineCallbacks def testSetTagValuePermissions(self): """ L{FacadePermissionMixin.updatePermission} updates the permissions for a given L{TagValue} path. """ policyAndExceptions = TPolicyAndExceptions(u'closed', [u'username']) with login(u'username', uuid4(), self.transact) as session: yield self.facade.updatePermission(session, u'tag-values', u'write', u'username/tag', policyAndExceptions) pathAndAction = (u'username/tag', Operation.WRITE_TAG_VALUE) result = self.permissions.get([pathAndAction]) self.assertEqual((Policy.CLOSED, [u'username']), result[pathAndAction]) @inlineCallbacks def testSetWithInvalidAction(self): """ L{FacadePermissionMixin.updatePermission} raises a L{TBadRequest} error if the given C{action} is invalid. """ policyAndExceptions = TPolicyAndExceptions(u'closed', []) with login(u'username', uuid4(), self.transact) as session: deferred = self.facade.updatePermission(session, u'namespaces', u'invalid', u'username', policyAndExceptions) yield self.assertFailure(deferred, TBadRequest) @inlineCallbacks def testSetWithInvalidCategory(self): """ L{FacadePermissionMixin.updatePermission} raises a L{TBadRequest} error if the given C{category} is invalid. """ policyAndExceptions = TPolicyAndExceptions(u'closed', []) with login(u'username', uuid4(), self.transact) as session: deferred = self.facade.updatePermission(session, u'invalid', u'update', u'username', policyAndExceptions) yield self.assertFailure(deferred, TBadRequest) @inlineCallbacks def testSetWithInvalidPolicy(self): """ L{FacadePermissionMixin.updatePermission} raises a L{TInvalidPolicy} error if the given C{policy} is invalid. """ policyAndExceptions = TPolicyAndExceptions(u'invalid', []) with login(u'username', uuid4(), self.transact) as session: deferred = self.facade.updatePermission(session, u'namespaces', u'create', u'username', policyAndExceptions) yield self.assertFailure(deferred, TInvalidPolicy) @inlineCallbacks def testSetWithUnknownNamespace(self): """ L{FacadePermissionMixin.updatePermission} raises a L{TNonexistentNamespace} error if the given L{Namespace} path does not exist. """ policyAndExceptions = TPolicyAndExceptions(u'closed', []) with login(u'username', uuid4(), self.transact) as session: deferred = self.facade.updatePermission(session, u'namespaces', u'create', u'unknown', policyAndExceptions) yield self.assertFailure(deferred, TNonexistentNamespace) @inlineCallbacks def testSetWithUnknownTag(self): """ L{FacadePermissionMixin.updatePermission} raises a L{TNonexistentTag} error if the given L{Tag} path does not exist. """ policyAndExceptions = TPolicyAndExceptions(u'closed', []) with login(u'username', uuid4(), self.transact) as session: deferred = self.facade.updatePermission( session, u'tags', u'update', u'username/unknown', policyAndExceptions) yield self.assertFailure(deferred, TNonexistentTag) @inlineCallbacks def testSetWithUnknownUser(self): """ L{FacadePermissionMixin.updatePermission} raises a L{TNoSuchUser} error if a L{User} in the exceptions list doesn't exist. """ policyAndExceptions = TPolicyAndExceptions(u'closed', [u'unknown']) with login(u'username', uuid4(), self.transact) as session: deferred = self.facade.updatePermission( session, u'tags', u'update', u'username/tag', policyAndExceptions) error = yield self.assertFailure(deferred, TNoSuchUser) self.assertEqual('unknown', error.name) @inlineCallbacks def testSetWithSuperuser(self): """ L{FacadePermissionMixin.updatePermission} raises a L{TInvalidUsername} error if a superuser is specified in the exceptions list. """ policyAndExceptions = TPolicyAndExceptions(u'closed', [u'fluiddb']) with login(u'username', uuid4(), self.transact) as session: deferred = self.facade.updatePermission( session, u'tags', u'update', u'username/tag', policyAndExceptions) yield self.assertFailure(deferred, TInvalidUsername) @inlineCallbacks def testSetWithAnonymous(self): """ L{FacadePermissionMixin.updatePermission} raises a L{TInvalidUsername} error if the anonymous user is specified in the exceptions list for non-allowed operations. """ policyAndExceptions = TPolicyAndExceptions(u'closed', [u'anon']) with login(u'username', uuid4(), self.transact) as session: deferred = self.facade.updatePermission( session, u'tags', u'update', u'username/tag', policyAndExceptions) yield self.assertFailure(deferred, TInvalidUsername) @inlineCallbacks def testSetWithUnknownUserUTF8EncodesUsername(self): """ L{FacadePermissionMixin.updatePermission} raises a L{TNoSuchUser} error if a L{User} in the exceptions list doesn't exist. The username passed to L{TNoSuchUser} is UTF-8 encoded. """ policyAndExceptions = TPolicyAndExceptions(u'closed', [u'\N{HIRAGANA LETTER A}']) with login(u'username', uuid4(), self.transact) as session: deferred = self.facade.updatePermission( session, u'tags', u'update', u'username/tag', policyAndExceptions) error = yield self.assertFailure(deferred, TNoSuchUser) self.assertEqual(u'\N{HIRAGANA LETTER A}'.encode('utf-8'), error.name) @inlineCallbacks def testSetNamespacePermissionsIsDenied(self): """ L{FacadePermissionMixin.updatePermission} raises a L{TPathPermissionDenied} error if the user doesn't have C{Operation.CONTROL_NAMESPACE} permissions on the given L{Namespace}. """ self.permissions.set([(u'username', Operation.CONTROL_NAMESPACE, Policy.CLOSED, [])]) policyAndExceptions = TPolicyAndExceptions(u'open', []) with login(u'username', uuid4(), self.transact) as session: deferred = self.facade.updatePermission(session, u'namespaces', u'control', u'username', policyAndExceptions) yield self.assertFailure(deferred, TPathPermissionDenied) @inlineCallbacks def testSetTagPermissionsIsDenied(self): """ L{FacadePermissionMixin.updatePermission} raises a L{TPathPermissionDenied} error if the user doesn't have C{Operation.CONTROL_TAG} permissions on the given L{Tag}. """ self.permissions.set([(u'username/tag', Operation.CONTROL_TAG, Policy.CLOSED, [])]) policyAndExceptions = TPolicyAndExceptions(u'open', []) with login(u'username', uuid4(), self.transact) as session: deferred = self.facade.updatePermission( session, u'tags', u'control', u'username/tag', policyAndExceptions) yield self.assertFailure(deferred, TPathPermissionDenied) @inlineCallbacks def testSetTagValuePermissionsIsDenied(self): """ L{FacadePermissionMixin.updatePermission} raises a L{TPathPermissionDenied} error if the user doesn't have C{Operation.CONTROL_TAG_VALUE} permissions on the given L{Tag}. """ self.permissions.set([(u'username/tag', Operation.CONTROL_TAG_VALUE, Policy.CLOSED, [])]) policyAndExceptions = TPolicyAndExceptions(u'open', []) with login(u'username', uuid4(), self.transact) as session: deferred = self.facade.updatePermission( session, u'tag-values', u'control', u'username/tag', policyAndExceptions) yield self.assertFailure(deferred, TPathPermissionDenied)
class SecureRecentActivityAPIWithAnonymousRoleTest(FluidinfoTestCase): resources = [('cache', CacheResource()), ('client', IndexResource()), ('config', ConfigResource()), ('store', DatabaseResource())] def setUp(self): super(SecureRecentActivityAPIWithAnonymousRoleTest, self).setUp() system = createSystemData() self.anon = system.users[u'anon'] UserAPI().create([(u'user', u'secret', u'User', u'*****@*****.**')]) self.user = getUser(u'user') self.recentActivity = SecureRecentActivityAPI(self.anon) self.permissions = CachingPermissionAPI(self.user) def testGetForObjectsReturnsOnlyAllowedTags(self): """ L{SecureRecentActivityAPI.getForObjects} will return all the tags for which the user has C{Operation.READ_TAG_VALUE} permissions, but not those for which the user doesn't have. """ tagValues = TagValueAPI(self.user) objectID1 = ObjectAPI(self.user).create(u'object1') objectID2 = uuid4() # Use commit() frequently to have different timestamps on each value. self.store.commit() tagValues.set({objectID1: {u'user/tag1': u'A'}}) self.store.commit() tagValues.set({objectID1: {u'user/tag2': u'B'}}) self.store.commit() tagValues.set({objectID2: {u'user/tag1': u'C'}}) self.store.commit() tagValues.set({objectID2: {u'user/tag2': u'D'}}) self.store.commit() tagValues.set({uuid4(): {u'user/tag1': u'E'}}) self.store.commit() tagValues.set({uuid4(): {u'user/tag2': u'F'}}) self.store.commit() self.permissions.set([(u'user/tag2', Operation.READ_TAG_VALUE, Policy.OPEN, [u'anon'])]) expected = [(u'user/tag1', objectID2, None, u'C', u'user'), (u'user/tag1', objectID1, u'object1', u'A', u'user'), (u'fluiddb/about', objectID1, u'object1', u'object1', u'fluiddb')] result = self.recentActivity.getForObjects([objectID1, objectID2]) # Remove the creation times from the result, with the order is enough. result = [(path, objectID, about, value, username) for path, objectID, about, value, username, time in result] self.assertEqual(expected, result) def testGetForUsersReturnsOnlyAllowedTags(self): """ L{SecureRecentActivityAPI.getForUsers} will return all the tags for which the user has C{Operation.READ_TAG_VALUE} permissions, but not those for which the user doesn't have. """ tagValues = TagValueAPI(self.user) objectID1 = ObjectAPI(self.user).create(u'object1') objectID2 = uuid4() # Use commit() frequently to have different timestamps on each value. self.store.commit() tagValues.set({objectID1: {u'user/tag1': u'A'}}) self.store.commit() tagValues.set({objectID1: {u'user/tag2': u'B'}}) self.store.commit() UserAPI().create([(u'user2', u'secret', u'User', u'*****@*****.**')]) tagValues = TagValueAPI(getUser(u'user2')) tagValues.set({objectID1: {u'user2/tag1': u'C'}}) self.store.commit() tagValues.set({objectID2: {u'user2/tag2': u'D'}}) self.store.commit() UserAPI().create([(u'user3', u'secret', u'User', u'*****@*****.**')]) tagValues = TagValueAPI(getUser(u'user3')) tagValues.set({objectID1: {u'user3/tag1': u'C'}}) self.store.commit() tagValues.set({objectID2: {u'user3/tag2': u'D'}}) self.store.commit() self.permissions.set([ (u'user/tag2', Operation.READ_TAG_VALUE, Policy.OPEN, [u'anon']), (u'user2/tag2', Operation.READ_TAG_VALUE, Policy.CLOSED, []) ]) expected = [(u'user2/tag1', objectID1, u'object1', u'C', u'user2'), (u'user/tag1', objectID1, u'object1', u'A', u'user')] result = self.recentActivity.getForUsers([u'user', u'user2']) # Remove the creation times from the result, with the order is enough. result = [(path, objectID, about, value, username) for path, objectID, about, value, username, time in result] self.assertEqual(expected, result)
class SecureNamespaceAPIWithNormalUserTest(FluidinfoTestCase): resources = [('cache', CacheResource()), ('config', ConfigResource()), ('store', DatabaseResource())] def setUp(self): super(SecureNamespaceAPIWithNormalUserTest, self).setUp() createSystemData() UserAPI().create([(u'user', u'password', u'User', u'*****@*****.**')]) self.user = getUser(u'user') self.permissions = CachingPermissionAPI(self.user) self.namespaces = SecureNamespaceAPI(self.user) def testCreateIsAllowed(self): """ L{SecureNamespaceAPI.create} should allow the creation of namespaces whose parent has open CREATE permissions. """ values = [(u'user', Operation.CREATE_NAMESPACE, Policy.OPEN, [])] self.permissions.set(values) result = self.namespaces.create([(u'user/test', u'description')]) self.assertEqual(1, len(result)) def testCreateIsDenied(self): """ L{SecureNamespaceAPI.create} should raise L{PermissonDeniedError} if the user doesn't have CREATE permissions on the parent namespace. """ values = [(u'user', Operation.CREATE_NAMESPACE, Policy.CLOSED, [])] self.permissions.set(values) error = self.assertRaises(PermissionDeniedError, self.namespaces.create, [(u'user/test', u'description')]) self.assertEqual([(u'user', Operation.CREATE_NAMESPACE)], sorted(error.pathsAndOperations)) def testDeleteIsAllowed(self): """ {SecureNamespaceAPI.delete} should allow the deletion of a namespace if the user has DELETE permissions. """ result1 = self.namespaces.create([(u'user/test', u'description')]) values = [(u'user/test', Operation.DELETE_NAMESPACE, Policy.OPEN, [])] self.permissions.set(values) result2 = self.namespaces.delete([u'user/test']) self.assertEqual(result1, result2) def testDeleteIsDenied(self): """ L{SecureNamespaceAPI.delete} should raise L{PermissonDeniedError} if the user doesn't have DELETE permissions. """ self.namespaces.create([(u'user/test', u'description')]) values = [(u'user/test', Operation.DELETE_NAMESPACE, Policy.OPEN, [u'user'])] self.permissions.set(values) error = self.assertRaises(PermissionDeniedError, self.namespaces.delete, [(u'user/test')]) self.assertEqual([(u'user/test', Operation.DELETE_NAMESPACE)], sorted(error.pathsAndOperations)) def testGetChildNamespacesIsAllowed(self): """ L{SecureNamespaceAPI.get} should allow getting a list of child namespaces if the user has permissions. """ self.namespaces.create([(u'user/test', u'description')]) values = [(u'user', Operation.LIST_NAMESPACE, Policy.OPEN, [])] self.permissions.set(values) result = self.namespaces.get([u'user'], withNamespaces=True) self.assertEqual(1, len(result)) def testGetChildNamespacesIsDenied(self): """ L{SecureNamespaceAPI.get} should raise L{PermissonDeniedError} if the user doesn't have LIST permissions when trying to get the child namespaces. """ self.namespaces.create([(u'user/test', u'description')]) values = [(u'user', Operation.LIST_NAMESPACE, Policy.CLOSED, [])] self.permissions.set(values) error = self.assertRaises(PermissionDeniedError, self.namespaces.get, [(u'user')], withNamespaces=True) self.assertEqual([(u'user', Operation.LIST_NAMESPACE)], sorted(error.pathsAndOperations)) def testGetChildTagsIsAllowed(self): """ L{SecureNamespaceAPI.get} should allow getting a list of child tags if the user has permissions. """ self.namespaces.create([(u'user/test', u'description')]) values = [(u'user', Operation.LIST_NAMESPACE, Policy.CLOSED, [u'user'])] self.permissions.set(values) result = self.namespaces.get([u'user'], withTags=True) self.assertEqual(1, len(result)) def testGetChildTagsIsDenied(self): """ L{SecureNamespaceAPI.get} should raise L{PermissonDeniedError} if the user doesn't have LIST permissions when trying to get the child tags. """ self.namespaces.create([(u'user/test', u'description')]) values = [(u'user', Operation.LIST_NAMESPACE, Policy.OPEN, [u'user'])] self.permissions.set(values) error = self.assertRaises(PermissionDeniedError, self.namespaces.get, [(u'user')], withTags=True) self.assertEqual([(u'user', Operation.LIST_NAMESPACE)], sorted(error.pathsAndOperations)) def testSetIsAllowed(self): """ L{SecureNamespaceAPI.get} should allow updating the description of a namespace if the user has permissions. """ self.namespaces.create([(u'user/test', u'description')]) values = [(u'user/test', Operation.UPDATE_NAMESPACE, Policy.OPEN, [])] self.permissions.set(values) self.namespaces.set({u'user/test': u'description'}) def testSetIsDenied(self): """ L{SecureNamespaceAPI.get} should raise L{PermissonDeniedError} if the user doesn't have UPDATE permissions when trying to update a namespace's description. """ self.namespaces.create([(u'user/test', u'description')]) values = [(u'user/test', Operation.UPDATE_NAMESPACE, Policy.CLOSED, [])] self.permissions.set(values) error = self.assertRaises(PermissionDeniedError, self.namespaces.set, {u'user/test': u'description'}) self.assertEqual([(u'user/test', Operation.UPDATE_NAMESPACE)], sorted(error.pathsAndOperations))
class SecureTagValueAPIWithUserRoleTest(FluidinfoTestCase): resources = [('cache', CacheResource()), ('config', ConfigResource()), ('store', DatabaseResource())] def setUp(self): super(SecureTagValueAPIWithUserRoleTest, self).setUp() createSystemData() UserAPI().create([(u'username', u'password', u'User', u'*****@*****.**')]) self.user = getUser(u'username') self.permissions = CachingPermissionAPI(self.user) TagAPI(self.user).create([(u'username/tag', u'description')]) self.tagValues = SecureTagValueAPI(self.user) def testGetIsAllowed(self): """ L{SecureTagAPI.get} is allowed if the user has C{Operation.READ_TAG_VALUE} permissions. """ objectID = uuid4() values = {objectID: {u'username/tag': 16}} self.tagValues.set(values) self.permissions.set([(u'username/tag', Operation.READ_TAG_VALUE, Policy.OPEN, [])]) result = self.tagValues.get(objectIDs=[objectID], paths=[u'username/tag']) self.assertEqual(16, result[objectID][u'username/tag'].value) def testGetIsDenied(self): """ L{SecureTagAPI.get} raises L{PermissionDeniedError} if the user doesn't have C{Operation.READ_TAG_VALUE} permissions. """ objectID = uuid4() values = {objectID: {u'username/tag': 16}} self.tagValues.set(values) self.permissions.set([(u'username/tag', Operation.READ_TAG_VALUE, Policy.CLOSED, [])]) error = self.assertRaises(PermissionDeniedError, self.tagValues.get, objectIDs=[objectID], paths=[u'username/tag']) self.assertEqual([(u'username/tag', Operation.READ_TAG_VALUE)], error.pathsAndOperations) def testSetIsAllowed(self): """ L{SecureTagAPI.set} is allowed if the user has C{Operation.WRITE_TAG_VALUE} permissions. """ self.permissions.set([(u'username/tag', Operation.WRITE_TAG_VALUE, Policy.OPEN, [])]) objectID = uuid4() values = {objectID: {u'username/tag': 16}} self.tagValues.set(values) result = self.tagValues.get(objectIDs=[objectID], paths=[u'username/tag']) self.assertEqual(16, result[objectID][u'username/tag'].value) def testSetIsDenied(self): """ L{SecureTagAPI.set} raises L{PermissionDeniedError} if the user doesn't have C{Operation.WRITE_TAG_VALUE} permissions. """ self.permissions.set([(u'username/tag', Operation.WRITE_TAG_VALUE, Policy.CLOSED, [])]) values = {uuid4(): {u'username/tag': 16}} error = self.assertRaises(PermissionDeniedError, self.tagValues.set, values) self.assertEqual([(u'username/tag', Operation.WRITE_TAG_VALUE)], error.pathsAndOperations) def testDeleteIsAllowed(self): """ L{SecureTagAPI.delete} is allowed if the user has C{Operation.DELETE_TAG_VALUE} permissions. """ self.permissions.set([(u'username/tag', Operation.DELETE_TAG_VALUE, Policy.OPEN, [])]) objectID = uuid4() values = {objectID: {u'username/tag': 16}} self.tagValues.set(values) self.tagValues.delete([(objectID, u'username/tag')]) result = self.tagValues.get(objectIDs=[objectID], paths=[u'username/tag']) self.assertEqual({}, result) def testDeleteIsDenied(self): """ L{SecureTagAPI.delete} raises L{PermissionDeniedError} if the user doesn't have C{Operation.DELETE_TAG_VALUE} permissions. """ objectID = uuid4() values = {objectID: {u'username/tag': 16}} self.tagValues.set(values) self.permissions.set([(u'username/tag', Operation.DELETE_TAG_VALUE, Policy.CLOSED, [])]) error = self.assertRaises(PermissionDeniedError, self.tagValues.delete, [(objectID, u'username/tag')]) self.assertEqual([(u'username/tag', Operation.DELETE_TAG_VALUE)], error.pathsAndOperations)
class SecureTagAPIWithNormalUserTest(FluidinfoTestCase): resources = [('cache', CacheResource()), ('config', ConfigResource()), ('store', DatabaseResource())] def setUp(self): super(SecureTagAPIWithNormalUserTest, self).setUp() createSystemData() UserAPI().create([(u'user', u'password', u'User', u'*****@*****.**')]) self.user = getUser(u'user') self.permissions = CachingPermissionAPI(self.user) self.tags = SecureTagAPI(self.user) def testCreateIsAllowed(self): """ L{SecureTagAPI.create} should allow the creation of tags whose parent namespace has open C{Operation.CREATE_NAMESPACE} permissions. """ result = self.tags.create([(u'user/test', u'description')]) self.assertEqual(1, len(result)) def testCreateIsDenied(self): """ L{SecureTagAPI.create} should raise L{PermissonDeniedError} if the user doesn't have C{Operation.CREATE_NAMESPACE} permissions on the parent namespace. """ values = [(u'user', Operation.CREATE_NAMESPACE, Policy.CLOSED, [])] self.permissions.set(values) error = self.assertRaises(PermissionDeniedError, self.tags.create, [(u'user/test', u'description')]) self.assertEqual([(u'user', Operation.CREATE_NAMESPACE)], sorted(error.pathsAndOperations)) def testDeleteIsAllowed(self): """ L{SecureTagAPI.delete} should allow the deletion of a tag if the user has C{Operation.DELETE_TAG} permissions. """ result1 = self.tags.create([(u'user/test', u'description')]) result2 = self.tags.delete([u'user/test']) self.assertEqual(result1, result2) def testDeleteIsDenied(self): """ L{SecureTagAPI.delete} should raise L{PermissonDeniedError} if the user doesn't have C{Operation.DELETE_TAG} permissions. """ self.tags.create([(u'user/test', u'description')]) values = [(u'user/test', Operation.DELETE_TAG, Policy.OPEN, [u'user'])] self.permissions.set(values) error = self.assertRaises(PermissionDeniedError, self.tags.delete, [(u'user/test')]) self.assertEqual([(u'user/test', Operation.DELETE_TAG)], sorted(error.pathsAndOperations)) def testSetIsAllowed(self): """ L{SecureTagAPI.get} should allow updating the description of a tag if the user has permissions. """ [(objectID, _)] = self.tags.create([(u'user/test', u'A description')]) self.tags.set({u'user/test': u'A new description'}) result = self.tags.get([u'user/test'], withDescriptions=True) expected = {u'user/test': {'id': objectID, 'description': u'A new description'}} self.assertEqual(expected, result) def testSetIsDenied(self): """ L{SecureTagAPI.get} should raise L{PermissonDeniedError} if the user doesn't have C{Operation.UPDATE_TAG} permissions when trying to update a tag's description. """ self.tags.create([(u'user/test', u'description')]) values = [(u'user/test', Operation.UPDATE_TAG, Policy.CLOSED, [])] self.permissions.set(values) error = self.assertRaises(PermissionDeniedError, self.tags.set, {u'user/test': u'description'}) self.assertEqual([(u'user/test', Operation.UPDATE_TAG)], sorted(error.pathsAndOperations))
class SecureObjectAPIWithUserRoleTest(FluidinfoTestCase): resources = [('cache', CacheResource()), ('config', ConfigResource()), ('store', DatabaseResource())] def setUp(self): super(SecureObjectAPIWithUserRoleTest, self).setUp() createSystemData() UserAPI().create([(u'username', u'password', u'User', u'*****@*****.**')]) self.user = getUser(u'username') TagAPI(self.user).create([(u'username/tag', u'description')]) self.permissions = CachingPermissionAPI(self.user) self.objects = SecureObjectAPI(self.user) def testGetTagsByObjectsPathIsAllowed(self): """ L{SecureObjectAPI.getTagsByObjects} will return all the tags for which the user has C{Operation.READ_TAG_VALUE} permissions. """ objectID = uuid4() values = {objectID: {u'username/tag': 16}} SecureTagValueAPI(self.user).set(values) self.permissions.set([(u'username/tag', Operation.READ_TAG_VALUE, Policy.OPEN, [])]) result = self.objects.getTagsByObjects([objectID]) expected = {objectID: [u'username/tag']} self.assertEqual(expected, result) def testGetTagsByObjectsReturnsOnlyAllowedTags(self): """ L{SecureObjectAPI.getTagsByObjects} will return all the tags for which the user has C{Operation.READ_TAG_VALUE} permissions, but not those for which the user doesn't have. """ TagAPI(self.user).create([(u'username/tag1', u'description'), (u'username/tag2', u'description')]) objectID = uuid4() values = {objectID: {u'username/tag1': 16, u'username/tag2': 16}} SecureTagValueAPI(self.user).set(values) self.permissions.set([(u'username/tag1', Operation.READ_TAG_VALUE, Policy.CLOSED, []), (u'username/tag2', Operation.READ_TAG_VALUE, Policy.OPEN, [])]) result = self.objects.getTagsByObjects([objectID]) expected = {objectID: [u'username/tag2']} self.assertEqual(expected, result) def testGetTagsByObjectsReturnsNoneAllowedTags(self): """ L{SecureObjectAPI.getTagsByObjects} will return all the tags for which the user has C{Operation.READ_TAG_VALUE} permissions, but not those for which the user doesn't have. """ TagAPI(self.user).create([(u'username/tag1', u'description'), (u'username/tag2', u'description')]) objectID = uuid4() values = {objectID: {u'username/tag1': 16, u'username/tag2': 16}} SecureTagValueAPI(self.user).set(values) self.permissions.set([(u'username/tag1', Operation.READ_TAG_VALUE, Policy.CLOSED, []), (u'username/tag2', Operation.READ_TAG_VALUE, Policy.CLOSED, [])]) result = self.objects.getTagsByObjects([objectID]) self.assertEqual({}, result) def testGetTagsByObjectsWithCustomPermission(self): """ L{SecureObjectAPI.getTagsByObjects} optionally accepts a permission type to check for instead of L{Operation.READ_TAG_VALUE}). """ TagAPI(self.user).create([(u'username/open', u'An accessible tag'), (u'username/closed', u'A denied tag')]) objectID = uuid4() SecureTagValueAPI(self.user).set({objectID: {u'username/open': 13, u'username/closed': 17}}) self.permissions.set([(u'username/closed', Operation.DELETE_TAG_VALUE, Policy.CLOSED, [])]) result = self.objects.getTagsByObjects( [objectID], permission=Operation.DELETE_TAG_VALUE) self.assertEqual({objectID: [u'username/open']}, result) def testGetTagsForObjectsOnlyReturnsAccessibleTags(self): """ L{SecureObjectAPI.getTagsForObjects} only returns L{Tag.path}s that the user has C{Operation.READ_TAG_VALUE} permissions for. """ TagAPI(self.user).create([(u'username/tag1', u'description'), (u'username/tag2', u'description')]) objectID = uuid4() SecureTagValueAPI(self.user).set({objectID: {u'username/tag1': 13, u'username/tag2': 17}}) self.permissions.set([(u'username/tag2', Operation.READ_TAG_VALUE, Policy.CLOSED, [])]) self.assertEqual([u'username/tag1'], self.objects.getTagsForObjects([objectID]))
class FacadeTagMixinTest(FluidinfoTestCase): resources = [('cache', CacheResource()), ('config', ConfigResource()), ('log', LoggingResource()), ('store', DatabaseResource()), ('threadPool', ThreadPoolResource())] def setUp(self): super(FacadeTagMixinTest, self).setUp() createSystemData() self.transact = Transact(self.threadPool) factory = FluidinfoSessionFactory('API-9000') self.facade = Facade(self.transact, factory) UserAPI().create([(u'username', u'password', u'User', u'*****@*****.**')]) self.user = getUser(u'username') self.permissions = CachingPermissionAPI(self.user) @inlineCallbacks def testGetTagWithoutData(self): """ L{FacadeTagMixin.getTag} raises a L{TNonexistentTag} exception if the requested L{Tag.path} doesn't exist. """ self.store.commit() with login(u'username', uuid4(), self.transact) as session: deferred = self.facade.getTag(session, u'username/unknown', False) yield self.assertFailure(deferred, TNonexistentTag) @inlineCallbacks def testGetTag(self): """ L{FacadeTagMixin.getTag} returns a L{TTag} instance with information about the requested L{Tag}. """ result = TagAPI(self.user).create([(u'username/tag', u'description')]) [(objectID, path)] = result self.store.commit() with login(u'username', uuid4(), self.transact) as session: result = yield self.facade.getTag(session, u'username/tag', False) self.assertEqual(str(objectID), result.objectId) self.assertEqual(u'username/tag', result.path) self.assertTrue(result.indexed) @inlineCallbacks def testGetTagWithDescription(self): """ L{FacadeTagMixin.getTag} includes the L{Tag.description}, if it was requested. """ TagAPI(self.user).create([(u'username/tag', u'A tag.')]) self.store.commit() with login(u'username', uuid4(), self.transact) as session: result = yield self.facade.getTag(session, u'username/tag', True) self.assertEqual(u'A tag.', result.description) @inlineCallbacks def testCreateTag(self): """L{FacadeTagMixin.createTag} creates a new L{Tag}.""" self.store.commit() with login(u'username', uuid4(), self.transact) as session: objectID = yield self.facade.createTag( session, u'username', u'tag', u'A tag.', 'ignored', 'ignored') self.assertNotIdentical(None, objectID) self.store.rollback() tag = getTags(paths=[u'username/tag']).one() self.assertIdentical(self.user, tag.creator) self.assertIdentical(self.user.namespace, tag.namespace) self.assertEqual(u'username/tag', tag.path) self.assertEqual(u'tag', tag.name) self.assertEqual(objectID, str(tag.objectID)) @inlineCallbacks def testCreateTagWithExistingPath(self): """ L{FacadeTagMixin.createTag} raises a L{TTagAlreadyExists} exception if the new L{Tag} already exists. """ TagAPI(self.user).create([(u'username/name', u'A tag.')]) self.store.commit() with login(u'username', uuid4(), self.transact) as session: deferred = self.facade.createTag( session, u'username', u'name', u'A tag.', 'ignored', 'ignored') yield self.assertFailure(deferred, TTagAlreadyExists) @inlineCallbacks def testCreateTagWithInvalidPath(self): """ L{FacadeTagMixin.createTag} raises a L{TInvalidPath} exception if the path of the L{Tag} is not well formed. """ self.store.commit() with login(u'username', uuid4(), self.transact) as session: deferred = self.facade.createTag(session, u'username', u'bad name', u'A tag.', 'ignored', 'ignored') yield self.assertFailure(deferred, TInvalidPath) @inlineCallbacks def testCreateTagWithUnknownParent(self): """ L{FacadeTagMixin.createTag} raises a L{TNonexistentTag} exception if a non-existent parent L{Tag} is specified. """ self.store.commit() with login(u'username', uuid4(), self.transact) as session: deferred = self.facade.createTag( session, u'unknown', u'name', u'A tag.', 'ignored', 'ignored') yield self.assertFailure(deferred, TNonexistentTag) @inlineCallbacks def testCreateIsDenied(self): """ L{Facade.createTag} raises a L{TPathPermissionDenied} exception if the user doesn't have C{CREATE} permissions on the parent L{Namespace}. """ self.permissions.set([(u'username', Operation.CREATE_NAMESPACE, Policy.CLOSED, [])]) self.store.commit() with login(u'username', uuid4(), self.transact) as session: deferred = self.facade.createTag( session, u'username', u'test', u'A tag.', 'ignored', 'ignored') yield self.assertFailure(deferred, TPathPermissionDenied) @inlineCallbacks def testUpdateTag(self): """ L{FacadeTagMixin.updateTag} updates the description for an existing L{Tag}. """ tags = TagAPI(self.user) tags.create([(u'username/name', u'A tag.')]) self.store.commit() with login(u'username', uuid4(), self.transact) as session: yield self.facade.updateTag(session, u'username/name', u'A new description.') self.store.rollback() result = tags.get([u'username/name'], withDescriptions=True) self.assertEqual(u'A new description.', result[u'username/name']['description']) @inlineCallbacks def testUpdateTagWithUnknownPath(self): """ L{FacadeTagMixin.updateTag} raises a L{TNonexistentTag} exception if the requested L{Tag.path} doesn't exist. """ self.store.commit() with login(u'username', uuid4(), self.transact) as session: deferred = self.facade.updateTag(session, u'username/unknown', u'A new description.') yield self.assertFailure(deferred, TNonexistentTag) @inlineCallbacks def testUpdateIsDenied(self): """ L{Facade.updateTag} raises a L{TPathPermissionDenied} exception if the user doesn't have C{UPDATE} permissions on the specified L{Tag}. """ TagAPI(self.user).create([(u'username/test', u'A tag.')]) self.permissions.set([(u'username/test', Operation.UPDATE_TAG, Policy.CLOSED, [])]) self.store.commit() with login(u'username', uuid4(), self.transact) as session: deferred = self.facade.updateTag(session, u'username/test', u'A new description.') yield self.assertFailure(deferred, TPathPermissionDenied) @inlineCallbacks def testDeleteTag(self): """L{FacadeTagMixin.deleteTag} deletes a L{Tag}.""" tags = TagAPI(self.user) tags.create([(u'username/name', u'A tag.')]) self.store.commit() with login(u'username', uuid4(), self.transact) as session: yield self.facade.deleteTag(session, u'username/name') self.store.rollback() self.assertEqual({}, tags.get([u'username/name'])) @inlineCallbacks def testDeleteTagWithUnknownPath(self): """ L{FacadeTagMixin.deleteTag} raises a L{TNonexistentTag} exception if the requested L{Tag.path} doesn't exist. """ self.store.commit() with login(u'username', uuid4(), self.transact) as session: deferred = self.facade.deleteTag(session, u'username/unknown') yield self.assertFailure(deferred, TNonexistentTag) @inlineCallbacks def testDeleteTagWithData(self): """ L{FacadeTagMixin.deleteTag} removes L{TagValue}s associated with the deleted L{Tag}. """ objectID = uuid4() TagAPI(self.user).create([(u'username/tag', u'A tag.')]) tagValues = TagValueAPI(self.user) tagValues.set({objectID: {u'username/tag': 42}}) self.store.commit() with login(u'username', uuid4(), self.transact) as session: yield self.facade.deleteTag(session, u'username/tag') self.store.rollback() self.assertEqual({}, tagValues.get(objectIDs=[objectID], paths=[u'username/tag'])) @inlineCallbacks def testDeleteIsDenied(self): """ L{Facade.deleteTag} raises a L{TPathPermissionDenied} exception if the user doesn't have C{DELETE} permissions on the specified L{Tag}. """ TagAPI(self.user).create([(u'username/test', u'A tag.')]) self.permissions.set([(u'username/test', Operation.DELETE_TAG, Policy.OPEN, [u'username'])]) self.store.commit() with login(u'username', uuid4(), self.transact) as session: deferred = self.facade.deleteTag(session, u'username/test') yield self.assertFailure(deferred, TPathPermissionDenied)
class SecureObjectAPIWithSuperuserRoleTest(FluidinfoTestCase): resources = [('cache', CacheResource()), ('config', ConfigResource()), ('store', DatabaseResource())] def setUp(self): super(SecureObjectAPIWithSuperuserRoleTest, self).setUp() system = createSystemData() self.superuser = system.users[u'fluiddb'] self.permissions = CachingPermissionAPI(self.superuser) self.objects = SecureObjectAPI(self.superuser) UserAPI().create([(u'username', u'password', u'User', u'*****@*****.**')]) def testGetTagsByObjectsIsAlwaysAllowed(self): """ L{SecureObjectAPI.getTagsByObjects} is always allowed for the superuser. """ TagAPI(self.superuser).create([(u'username/tag1', u'description'), (u'username/tag2', u'description')]) objectID = uuid4() values = {objectID: {u'username/tag1': 16, u'username/tag2': 16}} SecureTagValueAPI(self.superuser).set(values) self.permissions.set([(u'username/tag1', Operation.READ_TAG_VALUE, Policy.CLOSED, []), (u'username/tag2', Operation.READ_TAG_VALUE, Policy.OPEN, [])]) result = self.objects.getTagsByObjects([objectID]) self.assertEqual(1, len(result)) self.assertIn(objectID, result) self.assertEqual([u'username/tag1', u'username/tag2'], sorted(result[objectID])) def testGetTagsByObjectsWithCustomPermission(self): """ L{SecureObjectAPI.getTagsByObjects} optionally accepts a permission type to check for instead of L{Operation.READ_TAG_VALUE}). """ TagAPI(self.superuser).create( [(u'username/open', u'An accessible tag'), (u'username/closed', u'A denied tag')]) objectID = uuid4() SecureTagValueAPI(self.superuser).set( {objectID: {u'username/open': 13, u'username/closed': 17}}) self.permissions.set([(u'username/closed', Operation.DELETE_TAG_VALUE, Policy.CLOSED, [])]) result = self.objects.getTagsByObjects( [objectID], permission=Operation.DELETE_TAG_VALUE) # Superuser can always delete values, regardless of permission settings result[objectID].sort() self.assertEqual({objectID: [u'username/closed', u'username/open']}, result) def testGetTagsForObjectsIsAlwaysAllowed(self): """ L{SecureObjectAPI.getTagsForObjects} is always allowed for the superuser. """ TagAPI(self.superuser).create([(u'username/tag1', u'description'), (u'username/tag2', u'description')]) objectID = uuid4() values = {objectID: {u'username/tag1': 16, u'username/tag2': 16}} SecureTagValueAPI(self.superuser).set(values) self.permissions.set([(u'username/tag1', Operation.READ_TAG_VALUE, Policy.CLOSED, []), (u'username/tag2', Operation.READ_TAG_VALUE, Policy.OPEN, [])]) self.assertEqual( sorted([u'username/tag1', u'username/tag2']), sorted(self.objects.getTagsForObjects([objectID])))
class SecureRecentActivityAPIWithAnonymousRoleTest(FluidinfoTestCase): resources = [('cache', CacheResource()), ('client', IndexResource()), ('config', ConfigResource()), ('store', DatabaseResource())] def setUp(self): super(SecureRecentActivityAPIWithAnonymousRoleTest, self).setUp() system = createSystemData() self.anon = system.users[u'anon'] UserAPI().create([(u'user', u'secret', u'User', u'*****@*****.**')]) self.user = getUser(u'user') self.recentActivity = SecureRecentActivityAPI(self.anon) self.permissions = CachingPermissionAPI(self.user) def testGetForObjectsReturnsOnlyAllowedTags(self): """ L{SecureRecentActivityAPI.getForObjects} will return all the tags for which the user has C{Operation.READ_TAG_VALUE} permissions, but not those for which the user doesn't have. """ tagValues = TagValueAPI(self.user) objectID1 = ObjectAPI(self.user).create(u'object1') objectID2 = uuid4() # Use commit() frequently to have different timestamps on each value. self.store.commit() tagValues.set({objectID1: {u'user/tag1': u'A'}}) self.store.commit() tagValues.set({objectID1: {u'user/tag2': u'B'}}) self.store.commit() tagValues.set({objectID2: {u'user/tag1': u'C'}}) self.store.commit() tagValues.set({objectID2: {u'user/tag2': u'D'}}) self.store.commit() tagValues.set({uuid4(): {u'user/tag1': u'E'}}) self.store.commit() tagValues.set({uuid4(): {u'user/tag2': u'F'}}) self.store.commit() self.permissions.set([(u'user/tag2', Operation.READ_TAG_VALUE, Policy.OPEN, [u'anon'])]) expected = [ (u'user/tag1', objectID2, None, u'C', u'user'), (u'user/tag1', objectID1, u'object1', u'A', u'user'), (u'fluiddb/about', objectID1, u'object1', u'object1', u'fluiddb')] result = self.recentActivity.getForObjects([objectID1, objectID2]) # Remove the creation times from the result, with the order is enough. result = [(path, objectID, about, value, username) for path, objectID, about, value, username, time in result] self.assertEqual(expected, result) def testGetForUsersReturnsOnlyAllowedTags(self): """ L{SecureRecentActivityAPI.getForUsers} will return all the tags for which the user has C{Operation.READ_TAG_VALUE} permissions, but not those for which the user doesn't have. """ tagValues = TagValueAPI(self.user) objectID1 = ObjectAPI(self.user).create(u'object1') objectID2 = uuid4() # Use commit() frequently to have different timestamps on each value. self.store.commit() tagValues.set({objectID1: {u'user/tag1': u'A'}}) self.store.commit() tagValues.set({objectID1: {u'user/tag2': u'B'}}) self.store.commit() UserAPI().create([(u'user2', u'secret', u'User', u'*****@*****.**')]) tagValues = TagValueAPI(getUser(u'user2')) tagValues.set({objectID1: {u'user2/tag1': u'C'}}) self.store.commit() tagValues.set({objectID2: {u'user2/tag2': u'D'}}) self.store.commit() UserAPI().create([(u'user3', u'secret', u'User', u'*****@*****.**')]) tagValues = TagValueAPI(getUser(u'user3')) tagValues.set({objectID1: {u'user3/tag1': u'C'}}) self.store.commit() tagValues.set({objectID2: {u'user3/tag2': u'D'}}) self.store.commit() self.permissions.set([(u'user/tag2', Operation.READ_TAG_VALUE, Policy.OPEN, [u'anon']), (u'user2/tag2', Operation.READ_TAG_VALUE, Policy.CLOSED, [])]) expected = [ (u'user2/tag1', objectID1, u'object1', u'C', u'user2'), (u'user/tag1', objectID1, u'object1', u'A', u'user')] result = self.recentActivity.getForUsers([u'user', u'user2']) # Remove the creation times from the result, with the order is enough. result = [(path, objectID, about, value, username) for path, objectID, about, value, username, time in result] self.assertEqual(expected, result)
class FacadeObjectMixinTest(FluidinfoTestCase): resources = [('cache', CacheResource()), ('config', ConfigResource()), ('log', LoggingResource()), ('store', DatabaseResource()), ('threadPool', ThreadPoolResource())] def setUp(self): super(FacadeObjectMixinTest, self).setUp() self.system = createSystemData() self.transact = Transact(self.threadPool) factory = FluidinfoSessionFactory('API-9000') self.facade = Facade(self.transact, factory) UserAPI().create([(u'username', u'password', u'User', u'*****@*****.**')]) self.user = getUser(u'username') self.permissions = CachingPermissionAPI(self.user) @inlineCallbacks def testCreateObjectPermissionDenied(self): """ L{FacadeObjectMixin.createObject} raises a L{TUnauthorized} exception if the user is the anonymous user. """ self.store.commit() with login(u'anon', uuid4(), self.transact) as session: deferred = self.facade.createObject(session) yield self.assertFailure(deferred, TUnauthorized) @inlineCallbacks def testCreateObjectWithoutAboutValue(self): """ L{FacadeObjectAPI.createObject} always returns a valid C{UUID} in a C{str} for a new object ID if an about value is not given. """ self.store.commit() with login(u'username', uuid4(), self.transact) as session: objectID = yield self.facade.createObject(session) self.assertEqual(objectID, str(UUID(objectID))) @inlineCallbacks def testCreateObjectWithAboutValue(self): """ L{FacadeObjectAPI.createObject} always returns a valid C{UUID} in a C{str} for a new object ID if an about value is given and it doesn't already exist. """ self.store.commit() with login(self.user.username, uuid4(), self.transact) as session: objectID = yield self.facade.createObject(session, about='foo') objectID = UUID(objectID) self.store.rollback() value = getAboutTagValues([objectID], [u'foo']).one() self.assertEqual(u'foo', value.value) tag = self.system.tags[u'fluiddb/about'] value = getTagValues(values=[(objectID, tag.id)]).one() self.assertIdentical(self.system.users[u'fluiddb'], value.creator) @inlineCallbacks def testCreateObjectWithDuplicateAboutValue(self): """ L{FacadeObjectAPI.createObject} returns a valid C{UUID} in a C{str} for an existing object ID if an about value is given and already exists in the database. """ objectID = uuid4() createAboutTagValue(objectID, u'bar') values = {objectID: {u'fluiddb/about': u'bar'}} SecureTagValueAPI(self.system.superuser).set(values) self.store.commit() with login(self.user.username, uuid4(), self.transact) as session: resultObjectID = yield self.facade.createObject(session, about='bar') self.assertEqual(str(objectID), resultObjectID) @inlineCallbacks def testGetObject(self): """ L{FacadeObjectAPI.getObject} returns a L{TObjectInfo} with the L{Tag.path}s for which the L{User} has L{Operation.READ_TAG_VALUE}. """ objectID = uuid4() SecureTagAPI(self.user).create([(u'username/foo', u'A description')]) values = {objectID: {u'username/foo': u'bar'}} SecureTagValueAPI(self.user).set(values) self.store.commit() with login(self.user.username, uuid4(), self.transact) as session: objectInfo = yield self.facade.getObject(session, str(objectID)) self.assertEqual([u'username/foo'], objectInfo.tagPaths) self.assertEqual(None, objectInfo.about) @inlineCallbacks def testGetObjectWithAboutValue(self): """ L{FacadeObjectAPI.getObject} returns a L{TObjectInfo} with the L{Tag.path}s for which the L{User} has L{Operation.READ_TAG_VALUE}, and the L{AboutTagValue.value} if it has one and C{showAbout} is C{True}. """ objectID = uuid4() SecureTagAPI(self.user).create([(u'username/foo', u'A description')]) values = {objectID: {u'username/foo': u'bar'}} SecureTagValueAPI(self.user).set(values) aboutTag = self.system.tags[u'fluiddb/about'] createAboutTagValue(objectID, u'bar') createTagValue(self.user.id, aboutTag.id, objectID, u'about value') self.store.commit() with login(self.user.username, uuid4(), self.transact) as session: objectInfo = yield self.facade.getObject(session, str(objectID), showAbout=True) self.assertEqual([u'fluiddb/about', u'username/foo'], sorted(objectInfo.tagPaths)) self.assertEqual('about value', objectInfo.about) @inlineCallbacks def testGetObjectWithAboutValueDoesNotExist(self): """ L{FacadeObjectAPI.getObject} returns a L{TObjectInfo} with the L{Tag.path}s for which the L{User} has L{Operation.READ_TAG_VALUE}, and the L{AboutTagValue.value} if it has one and C{showAbout} is C{True}. """ objectID = uuid4() tag = createTag(self.user, self.user.namespace, u'foo') createTagPermission(tag) createTagValue(self.user.id, tag.id, objectID, u'bar') session = AuthenticatedSession(self.user.username, uuid4()) self.store.commit() with login(self.user.username, uuid4(), self.transact) as session: objectInfo = yield self.facade.getObject(session, str(objectID), showAbout=True) self.assertEqual([u'username/foo'], objectInfo.tagPaths) self.assertIdentical(None, objectInfo.about) @inlineCallbacks def testGetObjectDeniedPaths(self): """ L{FacadeObjectAPI.getObject} returns a L{TObjectInfo} with the L{Tag.path}s for which the L{User} has L{Operation.READ_TAG_VALUE}. """ SecureTagAPI(self.user).create([(u'username/tag1', u'description'), (u'username/tag2', u'description')]) objectID = uuid4() values = {objectID: {u'username/tag1': 16}, objectID: {u'username/tag2': 16}} SecureTagValueAPI(self.user).set(values) self.permissions.set([(u'username/tag1', Operation.READ_TAG_VALUE, Policy.CLOSED, []), (u'username/tag2', Operation.READ_TAG_VALUE, Policy.OPEN, [])]) self.store.commit() with login(self.user.username, uuid4(), self.transact) as session: objectInfo = yield self.facade.getObject(session, str(objectID)) self.assertEqual([u'username/tag2'], objectInfo.tagPaths) self.assertEqual(None, objectInfo.about) @inlineCallbacks def testGetObjectAllPathsAreDenied(self): """ L{FacadeObjectAPI.getObject} returns a L{TObjectInfo} with the L{Tag.path}s for which the L{User} has L{Operation.READ_TAG_VALUE}, if all of them are denied, L{FacadeObjectAPI.getObject} must return an empty L{TObjectInfo}. """ SecureTagAPI(self.user).create([(u'username/tag1', u'description'), (u'username/tag2', u'description')]) objectID = uuid4() values = {objectID: {u'username/tag1': 16}, objectID: {u'username/tag2': 16}} SecureTagValueAPI(self.user).set(values) self.permissions.set([(u'username/tag1', Operation.READ_TAG_VALUE, Policy.CLOSED, []), (u'username/tag2', Operation.READ_TAG_VALUE, Policy.CLOSED, [])]) self.store.commit() with login(self.user.username, uuid4(), self.transact) as session: objectInfo = yield self.facade.getObject(session, str(objectID)) self.assertEqual([], objectInfo.tagPaths) self.assertEqual(None, objectInfo.about)