def check(self, namespaces): """ Check given L{Namespace}s for integrity errors. @param namespaces: A sequence of L{Namespace}s to be checked. """ aboutValues = self._getValues(namespaces, u'fluiddb/about') pathValues = self._getValues(namespaces, u'fluiddb/namespaces/path') descriptionValues = self._getValues(namespaces, u'fluiddb/namespaces/description') paths = [namespace.path for namespace in namespaces] namespacePermissions = dict(getNamespacePermissions(paths)) parentPaths = [ getParentPath(namespace.path) for namespace in namespaces if namespace.parentID is not None ] parentNamespaces = getNamespaces(paths=parentPaths) parentNamespaces = dict( (namespace.path, namespace) for namespace in parentNamespaces) users = getUsers() users = dict((user.id, user) for user in users) for namespace in namespaces: expectedAbout = u'Object for the namespace %s' % namespace.path self.checkAboutValue(namespace, aboutValues, expectedAbout) self.checkPathValue(namespace, pathValues) self.checkDescriptionValue(namespace, descriptionValues) self.checkPermissions(namespace, namespacePermissions, users, Operation.NAMESPACE_OPERATIONS) self.checkParent(namespace, parentNamespaces) self.checkValidPath(namespace)
def testCreateChildNamespaceInheritsParentNamespacePermissions(self): """ L{NamespaceAPI.create} creates new L{Namespace}s with L{Operation.CREATE_NAMESPACE} permissions inherited from the parent L{Namespace}'s permissions. """ UserAPI().create([(u'user', u'secret', u'name', u'*****@*****.**')]) user = getUser(u'user') PermissionAPI(self.user).set([ (u'user', Operation.CREATE_NAMESPACE, Policy.OPEN, []), (u'user', Operation.UPDATE_NAMESPACE, Policy.OPEN, []), (u'user', Operation.DELETE_NAMESPACE, Policy.OPEN, []), (u'user', Operation.LIST_NAMESPACE, Policy.CLOSED, [u'user']), (u'user', Operation.CONTROL_NAMESPACE, Policy.OPEN, [])]) self.namespaces.create([(u'user/child', u'A child namespace')]) result = getNamespacePermissions([u'user/child']) namespace, permission = result.one() self.assertEqual((Policy.OPEN, []), permission.get(Operation.CREATE_NAMESPACE)) self.assertEqual((Policy.OPEN, []), permission.get(Operation.UPDATE_NAMESPACE)) self.assertEqual((Policy.OPEN, []), permission.get(Operation.DELETE_NAMESPACE)) self.assertEqual((Policy.CLOSED, [user.id]), permission.get(Operation.LIST_NAMESPACE)) self.assertEqual((Policy.OPEN, []), permission.get(Operation.CONTROL_NAMESPACE))
def check(self, namespaces): """ Check given L{Namespace}s for integrity errors. @param namespaces: A sequence of L{Namespace}s to be checked. """ aboutValues = self._getValues(namespaces, u'fluiddb/about') pathValues = self._getValues(namespaces, u'fluiddb/namespaces/path') descriptionValues = self._getValues(namespaces, u'fluiddb/namespaces/description') paths = [namespace.path for namespace in namespaces] namespacePermissions = dict(getNamespacePermissions(paths)) parentPaths = [getParentPath(namespace.path) for namespace in namespaces if namespace.parentID is not None] parentNamespaces = getNamespaces(paths=parentPaths) parentNamespaces = dict((namespace.path, namespace) for namespace in parentNamespaces) users = getUsers() users = dict((user.id, user) for user in users) for namespace in namespaces: expectedAbout = u'Object for the namespace %s' % namespace.path self.checkAboutValue(namespace, aboutValues, expectedAbout) self.checkPathValue(namespace, pathValues) self.checkDescriptionValue(namespace, descriptionValues) self.checkPermissions(namespace, namespacePermissions, users, Operation.NAMESPACE_OPERATIONS) self.checkParent(namespace, parentNamespaces) self.checkValidPath(namespace)
def testGetNamespacePermissionsWithUnknownPaths(self): """ L{getNamespacePermissions} returns an empty C{ResultSet} if L{Namespace}s and L{NamespacePermission}s matching the specified L{Namespace.path}s are not available. """ self.assertEqual([], list(getNamespacePermissions([u'unknown'])))
def assertNamespace(self, path, description): """ Check that a L{Namespace} is created including its meta-tags C{fluiddb/namespaces/path}, C{fluiddb/namespaces/description} and C{fluiddb/about}. Additionally, check that the assigned permissions are correct. """ result = self.store.find(Namespace, Namespace.path == path) namespace = result.one() self.assertNotIdentical(None, namespace, msg='Namespace %r was not created.' % path) result = self.store.find(TagValue, TagValue.tagID == Tag.id, Tag.path == u'fluiddb/about', TagValue.objectID == namespace.objectID) aboutValue = result.one() self.assertNotIdentical(None, aboutValue, msg='About tag was not created for %r.' % path) self.assertEqual(u'Object for the namespace %s' % path, aboutValue.value, msg='About tag is not correct for %r.' % path) result = self.store.find(TagValue, TagValue.tagID == Tag.id, Tag.path == u'fluiddb/namespaces/path', TagValue.objectID == namespace.objectID) pathValue = result.one() self.assertNotIdentical(None, pathValue, msg='Path tag was not created for %r.' % path) self.assertEqual(path, pathValue.value, msg='Path tag is not correct for %r.' % path) result = self.store.find(TagValue, TagValue.tagID == Tag.id, Tag.path == u'fluiddb/namespaces/description', TagValue.objectID == namespace.objectID) descriptionValue = result.one() self.assertNotIdentical(None, descriptionValue, msg='Description tag was not created for %r.' % path) self.assertEqual(description, descriptionValue.value, msg='Description tag is not correct for %r.' % path) namespace, permission = getNamespacePermissions([path]).one() self.assertNotIdentical(None, permission.namespaceID) self.assertEqual(namespace.id, permission.namespaceID) self.assertEqual((Policy.CLOSED, []), permission.get(Operation.CREATE_NAMESPACE)) self.assertEqual((Policy.CLOSED, []), permission.get(Operation.UPDATE_NAMESPACE)) self.assertEqual((Policy.CLOSED, []), permission.get(Operation.DELETE_NAMESPACE)) self.assertEqual((Policy.CLOSED, []), permission.get(Operation.LIST_NAMESPACE)) self.assertEqual((Policy.CLOSED, []), permission.get(Operation.CONTROL_NAMESPACE))
def testCreateChildNamespaceInheritsParentNamespacePermissions(self): """ L{NamespaceAPI.create} creates new L{Namespace}s with L{Operation.CREATE_NAMESPACE} permissions inherited from the parent L{Namespace}'s permissions. """ UserAPI().create([(u'user', u'secret', u'name', u'*****@*****.**')]) user = getUser(u'user') PermissionAPI(self.user).set([ (u'user', Operation.CREATE_NAMESPACE, Policy.OPEN, []), (u'user', Operation.UPDATE_NAMESPACE, Policy.OPEN, []), (u'user', Operation.DELETE_NAMESPACE, Policy.OPEN, []), (u'user', Operation.LIST_NAMESPACE, Policy.CLOSED, [u'user']), (u'user', Operation.CONTROL_NAMESPACE, Policy.OPEN, []) ]) self.namespaces.create([(u'user/child', u'A child namespace')]) result = getNamespacePermissions([u'user/child']) namespace, permission = result.one() self.assertEqual((Policy.OPEN, []), permission.get(Operation.CREATE_NAMESPACE)) self.assertEqual((Policy.OPEN, []), permission.get(Operation.UPDATE_NAMESPACE)) self.assertEqual((Policy.OPEN, []), permission.get(Operation.DELETE_NAMESPACE)) self.assertEqual((Policy.CLOSED, [user.id]), permission.get(Operation.LIST_NAMESPACE)) self.assertEqual((Policy.OPEN, []), permission.get(Operation.CONTROL_NAMESPACE))
def testPermissionsAreNotCreatedIfCreateFails(self): """ If L{NamespaceAPI.create} fails, no permissions should be created. """ self.assertRaises(MalformedPathError, self.namespaces.create, [(u'!!!!/test', u'description')]) result = getNamespacePermissions([u'username/test']) self.assertTrue(result.is_empty())
def testSet(self): """ L{PermissionAPI.set} updates existing permissions for the given values. """ user1 = createUser(u'user1', u'secret', u'User1', u'*****@*****.**') user2 = createUser(u'user2', u'secret', u'User2', u'*****@*****.**') self.permissions.set([(u'username', Operation.CREATE_NAMESPACE, Policy.OPEN, [u'user1', u'user2'])]) namespace, permission = getNamespacePermissions([u'username']).one() self.assertEqual(Policy.OPEN, permission.createPolicy) self.assertEqual([user1.id, user2.id], permission.createExceptions)
def getNamespacePermissions(self, paths): """Get L{Permission}s for L{Namespace.path}s. @param paths: A sequence of L{Namespace.path}s to retrieve L{Permission}s for. @return: A C{dict} mapping L{Namespace.path}s to L{Permission} instances. """ return dict((namespace.path, permission) for namespace, permission in readonly(getNamespacePermissions(paths)))
def getNamespacePermissions(self, paths): """Get L{Permission}s for L{Namespace.path}s. @param paths: A sequence of L{Namespace.path}s to retrieve L{Permission}s for. @return: A C{dict} mapping L{Namespace.path}s to L{Permission} instances. """ return dict((namespace.path, permission) for namespace, permission in readonly( getNamespacePermissions(paths)))
def testSetWithAnonymousUserAndPermittedOperation(self): """ L{PermissionAPI.set} updates existing permissions for the anonymous user if the operation is allowed for anonymous users. """ anon = self.system.users[u'anon'] values = [(u'username', Operation.LIST_NAMESPACE, Policy.OPEN, [u'anon'])] PermissionAPI(anon).set(values) namespace, permission = getNamespacePermissions([u'username']).one() self.assertEqual(Policy.OPEN, permission.listPolicy) self.assertEqual([anon.id], permission.listExceptions)
def testGetNamespacePermissions(self): """ L{getNamespacePermissions} returns the L{Namespace}s and L{NamespacePermission}s that match the specified L{Namespace.path}s. """ user = createUser(u'name', u'password', u'Name', u'*****@*****.**') parentNamespace = createNamespace(user, u'name') parentPermission = createNamespacePermission(parentNamespace) childNamespace = createNamespace(user, u'name/child', parentID=parentNamespace.id) createNamespacePermission(childNamespace) self.assertEqual((parentNamespace, parentPermission), getNamespacePermissions([u'name']).one())
def _setNamespacePermissions(self, values, idByUsername): """Update L{NamespacePermission}s. @param values: A sequence of C{(path, Operation, Policy, exceptions)} 4-tuples representing L{NamespacePermission}s. @param idByUsername: A C{dict} mapping L{User.username}s to L{User.id}s with data for all the usernames in the exceptions C{list}s. """ result = getNamespacePermissions(values.keys()) for namespace, permission in result: for operation, policy, exceptions in values[namespace.path]: exceptions = [idByUsername[username] for username in exceptions] permission.set(operation, policy, exceptions)
def _setNamespacePermissions(self, values, idByUsername): """Update L{NamespacePermission}s. @param values: A sequence of C{(path, Operation, Policy, exceptions)} 4-tuples representing L{NamespacePermission}s. @param idByUsername: A C{dict} mapping L{User.username}s to L{User.id}s with data for all the usernames in the exceptions C{list}s. """ result = getNamespacePermissions(values.keys()) for namespace, permission in result: for operation, policy, exceptions in values[namespace.path]: exceptions = [ idByUsername[username] for username in exceptions ] permission.set(operation, policy, exceptions)
def _createPermissions(self, tags): """Create L{TagPermission}s for new L{Tag}s. L{Tag}s inherit permissions from their parent tag, if one is available. @param tags: A sequence of new L{Tag}s to create L{TagPermission}s for. """ # Preload parent Namespace and NamespacePermission's into Storm's # cache. Simply creating the objects will be enough to get them into # the cache. If there are many objects we need to be careful about # overloading the cache, but that isn't an issue here. parentPaths = [getParentPath(tag.path) for tag in tags] list(getNamespacePermissions(parentPaths)) for tag in tags: createTagPermission(tag)
def _getNamespacePermissions(self, values): """Get L{NamespacePermission}s for the specified values. @param values: A sequence of C{(Namespace.path, Operation)} 2-tuples. @return: A C{dict} that maps C{(Namespace.path, Operation)} tuples to C{(Policy, exceptions)} 2-tuples, matching the following format:: {(<path>, <operation>): (<policy>, [<user-id>, ...]), ...} """ permissionIndex = {} paths = set(path for path, operation in values) for namespace, permission in readonly(getNamespacePermissions(paths)): permissionIndex[namespace.path] = permission permissions = {} for path, operation in values: permission = permissionIndex[path] policy, exceptions = permission.get(operation) permissions[(path, operation)] = (policy, exceptions) return permissions
def _createPermissions(self, namespaces): """Create L{NamespacePermission}s for new L{Namespace}s. L{Namespace}s inherit permissions from their parent namespace, if one is available. @param namespaces: A sequence of new L{Namespace}s to create L{NamespacePermission}s for. """ paths = [namespace.path for namespace in namespaces] parentPaths = getParentPaths(paths) index = {} for parent, permission in getNamespacePermissions(parentPaths): index[parent.path] = permission for namespace in sorted(namespaces, key=lambda namespace: namespace.path): parentPath = getParentPath(namespace.path) parentPermission = index.get(parentPath) permission = createNamespacePermission( namespace, permissionTemplate=parentPermission) index[namespace.path] = permission
def testReadonlyWithTupleResult(self): """L{readonly} correctly handles tuple results.""" user = createUser(u'username', u'secret', u'name', u'*****@*****.**') namespace = createNamespace(user, u'username') permission = createNamespacePermission(namespace) result = getNamespacePermissions([u'username']) readonlyNamespace, readonlyPermission = readonly(result).one() self.assertNotIdentical(namespace, readonlyNamespace) self.assertEqual(namespace.id, readonlyNamespace.id) self.assertEqual(namespace.objectID, readonlyNamespace.objectID) self.assertEqual(namespace.parentID, readonlyNamespace.parentID) self.assertEqual(namespace.creatorID, readonlyNamespace.creatorID) self.assertEqual(namespace.path, readonlyNamespace.path) self.assertEqual(namespace.name, readonlyNamespace.name) self.assertEqual(namespace.creationTime, readonlyNamespace.creationTime) self.assertNotIdentical(permission, readonlyPermission) self.assertEqual(permission.createPolicy, readonlyPermission.createPolicy) self.assertEqual(permission.createExceptions, readonlyPermission.createExceptions) self.assertEqual(permission.updatePolicy, readonlyPermission.updatePolicy) self.assertEqual(permission.updateExceptions, readonlyPermission.updateExceptions) self.assertEqual(permission.deletePolicy, readonlyPermission.deletePolicy) self.assertEqual(permission.deleteExceptions, readonlyPermission.deleteExceptions) self.assertEqual(permission.listPolicy, readonlyPermission.listPolicy) self.assertEqual(permission.listExceptions, readonlyPermission.listExceptions) self.assertEqual(permission.controlPolicy, readonlyPermission.controlPolicy) self.assertEqual(permission.controlExceptions, readonlyPermission.controlExceptions)