def check(self, tags): """Check given L{Tag}s for integrity errors. @param tags: A sequence of L{Tag}s to be checked. """ aboutValues = self._getValues(tags, u'fluiddb/about') pathValues = self._getValues(tags, u'fluiddb/tags/path') descriptionValues = self._getValues(tags, u'fluiddb/tags/description') tagPermissions = dict(getTagPermissions([tag.path for tag in tags])) parentPaths = [getParentPath(tag.path) for tag in tags] parentNamespaces = getNamespaces(parentPaths) parentNamespaces = dict((namespace.path, namespace) for namespace in parentNamespaces) users = getUsers() users = dict((user.id, user) for user in users) for tag in tags: expectedAbout = u'Object for the attribute %s' % tag.path self.checkAboutValue(tag, aboutValues, expectedAbout) self.checkPathValue(tag, pathValues) self.checkDescriptionValue(tag, descriptionValues) self.checkPermissions(tag, tagPermissions, users, Operation.TAG_OPERATIONS) self.checkParent(tag, parentNamespaces) self.checkValidPath(tag)
def testCreateChildTagInheritsParentNamespacePermissions(self): """ L{TagAPI.create} creates new L{Tag}s with permissions inherited from the parent L{Namespace}'s permissions. """ PermissionAPI(self.user).set([ (u'username', Operation.CREATE_NAMESPACE, Policy.CLOSED, [u'username']), (u'username', Operation.UPDATE_NAMESPACE, Policy.OPEN, []), (u'username', Operation.DELETE_NAMESPACE, Policy.OPEN, []), (u'username', Operation.LIST_NAMESPACE, Policy.CLOSED, [u'username']), (u'username', Operation.CONTROL_NAMESPACE, Policy.OPEN, []) ]) self.tags.create([(u'username/tag', u'A child tag')]) result = getTagPermissions([u'username/tag']) tag, permission = result.one() self.assertEqual((Policy.CLOSED, [self.user.id]), permission.get(Operation.UPDATE_TAG)) self.assertEqual((Policy.CLOSED, [self.user.id]), permission.get(Operation.DELETE_TAG)) self.assertEqual((Policy.OPEN, []), permission.get(Operation.CONTROL_TAG)) self.assertEqual((Policy.CLOSED, [self.user.id]), permission.get(Operation.WRITE_TAG_VALUE)) self.assertEqual((Policy.CLOSED, [self.user.id]), permission.get(Operation.READ_TAG_VALUE)) self.assertEqual((Policy.CLOSED, [self.user.id]), permission.get(Operation.DELETE_TAG_VALUE)) self.assertEqual((Policy.OPEN, []), permission.get(Operation.CONTROL_TAG_VALUE))
def check(self, tags): """Check given L{Tag}s for integrity errors. @param tags: A sequence of L{Tag}s to be checked. """ aboutValues = self._getValues(tags, u'fluiddb/about') pathValues = self._getValues(tags, u'fluiddb/tags/path') descriptionValues = self._getValues(tags, u'fluiddb/tags/description') tagPermissions = dict(getTagPermissions([tag.path for tag in tags])) parentPaths = [getParentPath(tag.path) for tag in tags] parentNamespaces = getNamespaces(parentPaths) parentNamespaces = dict( (namespace.path, namespace) for namespace in parentNamespaces) users = getUsers() users = dict((user.id, user) for user in users) for tag in tags: expectedAbout = u'Object for the attribute %s' % tag.path self.checkAboutValue(tag, aboutValues, expectedAbout) self.checkPathValue(tag, pathValues) self.checkDescriptionValue(tag, descriptionValues) self.checkPermissions(tag, tagPermissions, users, Operation.TAG_OPERATIONS) self.checkParent(tag, parentNamespaces) self.checkValidPath(tag)
def testGetTagPermissionsWithUnknownPaths(self): """ L{getTagPermissions} returns an empty C{ResultSet} if L{Tag}s and L{TagPermission}s matching the specified L{Tag.path}s are not available. """ self.assertEqual([], list(getTagPermissions([u'unknown'])))
def testCreateChildTagWithDelegatedCreator(self): """ L{TagAPI.create} always ensures that a new L{Tag} is usable by the L{User} that created it. In the case of default permissions, the user creating the new L{Tag} is granted L{Operation.UPDATE_TAG}, L{Operation.DELETE_TAG}, L{Operation.WRITE_TAG_VALUE} and L{Operation.DELETE_TAG_VALUE}. """ UserAPI().create([(u'friend', u'secret', u'name', u'*****@*****.**') ]) PermissionAPI(self.user).set([(u'username', Operation.CREATE_NAMESPACE, Policy.CLOSED, [u'username', u'friend'])]) friend = getUser(u'friend') TagAPI(friend).create([(u'username/tag', u'A shared tag')]) result = getTagPermissions([u'username/tag']) tag, permission = result.one() self.assertEqual((Policy.CLOSED, [self.user.id, friend.id]), permission.get(Operation.UPDATE_TAG)) self.assertEqual((Policy.CLOSED, [self.user.id, friend.id]), permission.get(Operation.DELETE_TAG)) self.assertEqual((Policy.CLOSED, [self.user.id]), permission.get(Operation.CONTROL_TAG)) self.assertEqual((Policy.CLOSED, [self.user.id, friend.id]), permission.get(Operation.WRITE_TAG_VALUE)) self.assertEqual((Policy.OPEN, []), permission.get(Operation.READ_TAG_VALUE)) self.assertEqual((Policy.CLOSED, [self.user.id, friend.id]), permission.get(Operation.DELETE_TAG_VALUE)) self.assertEqual((Policy.CLOSED, [self.user.id]), permission.get(Operation.CONTROL_TAG_VALUE))
def testCreatePrivateChildTagWithDelegatedCreator(self): """ L{TagAPI.create} always ensures that a new L{Tag} is usable by the L{User} that created it. If the L{Operation.READ_TAG_VALUE} permission is L{Policy.CLOSED} the creator is added to the exceptions list. """ UserAPI().create([(u'friend', u'secret', u'name', u'*****@*****.**') ]) PermissionAPI(self.user).set([(u'username', Operation.CREATE_NAMESPACE, Policy.CLOSED, [u'username', u'friend']), (u'username', Operation.LIST_NAMESPACE, Policy.CLOSED, [u'username', u'friend'])]) friend = getUser(u'friend') TagAPI(friend).create([(u'username/tag', u'A shared tag')]) result = getTagPermissions([u'username/tag']) tag, permission = result.one() self.assertEqual((Policy.CLOSED, [self.user.id, friend.id]), permission.get(Operation.UPDATE_TAG)) self.assertEqual((Policy.CLOSED, [self.user.id, friend.id]), permission.get(Operation.DELETE_TAG)) self.assertEqual((Policy.CLOSED, [self.user.id]), permission.get(Operation.CONTROL_TAG)) self.assertEqual((Policy.CLOSED, [self.user.id, friend.id]), permission.get(Operation.WRITE_TAG_VALUE)) self.assertEqual((Policy.CLOSED, [self.user.id, friend.id]), permission.get(Operation.READ_TAG_VALUE)) self.assertEqual((Policy.CLOSED, [self.user.id, friend.id]), permission.get(Operation.DELETE_TAG_VALUE)) self.assertEqual((Policy.CLOSED, [self.user.id]), permission.get(Operation.CONTROL_TAG_VALUE))
def getTagPermissions(self, paths): """Get L{Permission}s for L{Tag.path}s. @param paths: A sequence of L{Tag.path}s to retrieve L{Permission}s for. @return: A C{dict} mapping L{Tag.path}s to L{Permission} instances. """ return dict((tag.path, permission) for tag, permission in readonly(getTagPermissions(paths)))
def testGetTagPermissions(self): """ L{getTagPermissions} returns the L{Tag}s and L{TagPermission}s that match the specified L{Tag.path}s. """ user = createUser(u'name', u'password', u'Name', u'*****@*****.**') namespace = createNamespace(user, u'name') createTag(user, namespace, u'unwanted') tag = createTag(user, namespace, u'tag') permission = createTagPermission(tag) self.assertEqual((tag, permission), getTagPermissions([u'name/tag']).one())
def testCheckUserWithMissingPermission(self): """ L{checkPermissions} denies the operation if, for some reason, a permission is not available for the entity being requested. """ TagAPI(self.user).create([(u'username/tag', u'description')]) # FIXME: don't use data functions here. [(tag, permission)] = getTagPermissions([u'username/tag']) self.store.remove(permission) values = [(u'username/tag', Operation.UPDATE_TAG)] deniedOperations = checkPermissions(self.user, values) self.assertEqual([(u'username/tag', Operation.UPDATE_TAG)], deniedOperations)
def testSetInvalidatesCachedTagPermissions(self): """ L{CachingPermissionAPI.set} invalidates L{TagPermission}s to ensure the cache is always fresh. """ TagAPI(self.user).create([(u'username/tag', u'A tag')]) _, permission = getTagPermissions(paths=[u'username/tag']).one() cache = PermissionCache() cache.saveTagPermissions({u'username/tag': permission}) self.permissions.set([(u'username/tag', Operation.UPDATE_TAG, Policy.OPEN, [])]) cached = cache.getTagPermissions([u'username/tag']) self.assertEqual({}, cached.results) self.assertEqual([u'username/tag'], cached.uncachedValues)
def testSetInvalidatesCachedTagPermissions(self): """ L{CachingPermissionAPI.set} invalidates L{TagPermission}s to ensure the cache is always fresh. """ TagAPI(self.user).create([(u'username/tag', u'A tag')]) _, permission = getTagPermissions(paths=[u'username/tag']).one() cache = PermissionCache() cache.saveTagPermissions({u'username/tag': permission}) self.permissions.set([ (u'username/tag', Operation.UPDATE_TAG, Policy.OPEN, [])]) cached = cache.getTagPermissions([u'username/tag']) self.assertEqual({}, cached.results) self.assertEqual([u'username/tag'], cached.uncachedValues)
def testCheckAnonymousWithMissingPermission(self): """ L{checkPermissions} denies the operations, for some reason, a permission is not available for the entity being requested. """ anonymous = self.system.users[u'anon'] TagAPI(self.user).create([(u'username/tag', u'description')]) values = [(u'username/tag', Operation.READ_TAG_VALUE)] # FIXME: don't use data functions here. [(tag, permission)] = getTagPermissions([u'username/tag']) self.store.remove(permission) deniedOperations = checkPermissions(anonymous, values) self.assertEqual([(u'username/tag', Operation.READ_TAG_VALUE)], deniedOperations)
def _setTagPermissions(self, values, idByUsername): """Update L{TagPermission}s. @param values: A sequence of C{(path, Operation, Policy, exceptions)} 4-tuples representing L{TagPermission}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 = getTagPermissions(values.keys()) for tag, permission in result: for operation, policy, exceptions in values[tag.path]: exceptions = [idByUsername[username] for username in exceptions] permission.set(operation, policy, exceptions)
def _setTagPermissions(self, values, idByUsername): """Update L{TagPermission}s. @param values: A sequence of C{(path, Operation, Policy, exceptions)} 4-tuples representing L{TagPermission}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 = getTagPermissions(values.keys()) for tag, permission in result: for operation, policy, exceptions in values[tag.path]: exceptions = [ idByUsername[username] for username in exceptions ] permission.set(operation, policy, exceptions)
def _getTagPermissions(self, values): """Get L{TagPermission}s for the specified values. @param values: A sequence of C{(Tag.path, Operation)} 2-tuples. @return: A C{dict} that maps C{(Tag.path, Operation)} 2-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 tag, permission in readonly(getTagPermissions(paths)): permissionIndex[tag.path] = permission permissions = {} for path, operation in values: permission = permissionIndex[path] policy, exceptions = permission.get(operation) permissions[(path, operation)] = (policy, exceptions) return permissions
def assertDefaultPermissions(self, user, tagPath): """ Assert that a L{TagPermission} exists for the specified L{Tag.path} and that it uses the default system-wide policy. """ tag, permission = getTagPermissions([tagPath]).one() self.assertEqual(Policy.CLOSED, permission.updatePolicy) self.assertEqual([user.id], permission.updateExceptions) self.assertEqual(Policy.CLOSED, permission.deletePolicy) self.assertEqual([user.id], permission.deleteExceptions) self.assertEqual(Policy.CLOSED, permission.controlPolicy) self.assertEqual([user.id], permission.controlExceptions) self.assertEqual(Policy.CLOSED, permission.writeValuePolicy) self.assertEqual([user.id], permission.writeValueExceptions) self.assertEqual(Policy.OPEN, permission.readValuePolicy) self.assertEqual([], permission.readValueExceptions) self.assertEqual(Policy.CLOSED, permission.deleteValuePolicy) self.assertEqual([user.id], permission.deleteValueExceptions) self.assertEqual(Policy.CLOSED, permission.controlValuePolicy) self.assertEqual([user.id], permission.controlValueExceptions)
def assertTag(self, path, description): """ Check that a L{Tag} is created including its meta-tags C{fluiddb/tags/path}, C{fluiddb/tags/description} and C{fluiddb/about}. Additionally, check that the assigned permissions are correct. """ result = self.store.find(Tag, Tag.path == path) tag = result.one() self.assertNotIdentical(None, tag, msg='Tag %r was not created.' % path) result = self.store.find(TagValue, TagValue.tagID == Tag.id, Tag.path == u'fluiddb/about', TagValue.objectID == tag.objectID) aboutValue = result.one() self.assertNotIdentical(None, aboutValue, msg='About tag was not created for %r.' % path) self.assertEqual(u'Object for the attribute %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/tags/path', TagValue.objectID == tag.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/tags/description', TagValue.objectID == tag.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) tag, permission = getTagPermissions([path]).one() self.assertNotIdentical(None, permission.tagID) self.assertEqual(tag.id, permission.tagID) self.assertEqual((Policy.CLOSED, []), permission.get(Operation.UPDATE_TAG)) self.assertEqual((Policy.CLOSED, []), permission.get(Operation.DELETE_TAG)) self.assertEqual((Policy.CLOSED, []), permission.get(Operation.CONTROL_TAG)) self.assertEqual((Policy.CLOSED, []), permission.get(Operation.WRITE_TAG_VALUE)) self.assertEqual((Policy.OPEN, []), permission.get(Operation.READ_TAG_VALUE)) self.assertEqual((Policy.CLOSED, []), permission.get(Operation.DELETE_TAG_VALUE)) self.assertEqual((Policy.CLOSED, []), permission.get(Operation.CONTROL_TAG_VALUE))
def assertTag(self, path, description): """ Check that a L{Tag} is created including its meta-tags C{fluiddb/tags/path}, C{fluiddb/tags/description} and C{fluiddb/about}. Additionally, check that the assigned permissions are correct. """ result = self.store.find(Tag, Tag.path == path) tag = result.one() self.assertNotIdentical(None, tag, msg='Tag %r was not created.' % path) result = self.store.find(TagValue, TagValue.tagID == Tag.id, Tag.path == u'fluiddb/about', TagValue.objectID == tag.objectID) aboutValue = result.one() self.assertNotIdentical(None, aboutValue, msg='About tag was not created for %r.' % path) self.assertEqual(u'Object for the attribute %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/tags/path', TagValue.objectID == tag.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/tags/description', TagValue.objectID == tag.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) tag, permission = getTagPermissions([path]).one() self.assertNotIdentical(None, permission.tagID) self.assertEqual(tag.id, permission.tagID) self.assertEqual((Policy.CLOSED, []), permission.get(Operation.UPDATE_TAG)) self.assertEqual((Policy.CLOSED, []), permission.get(Operation.DELETE_TAG)) self.assertEqual((Policy.CLOSED, []), permission.get(Operation.CONTROL_TAG)) self.assertEqual((Policy.CLOSED, []), permission.get(Operation.WRITE_TAG_VALUE)) self.assertEqual((Policy.OPEN, []), permission.get(Operation.READ_TAG_VALUE)) self.assertEqual((Policy.CLOSED, []), permission.get(Operation.DELETE_TAG_VALUE)) self.assertEqual((Policy.CLOSED, []), permission.get(Operation.CONTROL_TAG_VALUE))