Exemplo n.º 1
0
        def run():
            tagValues = SecureTagValueAPI(session.auth.user)
            objects = SecureObjectAPI(session.auth.user)
            objectIDs = self._resolveQuery(session, objects, parsedQuery)
            values = []

            if tags is None:
                # delete all tags user has permissions for
                result = objects.getTagsByObjects(objectIDs,
                                                  Operation.DELETE_TAG_VALUE)
                for objectID, paths in result.iteritems():
                    for path in paths:
                        values.append((objectID, path))
            else:
                # delete only tags requested by user
                result = objects.getTagsByObjects(objectIDs)
                for objectID, paths in result.iteritems():
                    for path in paths:
                        if tags is None or path in tags:
                            values.append((objectID, path))

            if values:
                try:
                    tagValues.delete(values)
                except UnknownPathError as error:
                    session.log.exception(error)
                    path = error.paths[0]
                    raise TNonexistentTag(path.encode('utf-8'))
                except PermissionDeniedError as error:
                    session.log.exception(error)
                    path_, operation = error.pathsAndOperations[0]
                    category, action = getCategoryAndAction(operation)
                    raise TPathPermissionDenied(category, action, path_)
Exemplo n.º 2
0
 def setUp(self):
     super(DatasetImporterTest, self).setUp()
     self.system = createSystemData()
     UserAPI().create([(u'user', u'secret', u'User', u'*****@*****.**')])
     user = getUser(u'user')
     self.objects = SecureObjectAPI(user)
     self.values = SecureTagValueAPI(user)
Exemplo n.º 3
0
        def run():
            objects = SecureObjectAPI(session.auth.user)

            try:
                searchQueries = objects.search(valuesByQuery.keys())
            except UnknownPathError as error:
                session.log.exception(error)
                unknownPath = error.paths[0]
                raise TNonexistentTag(unknownPath.encode('utf-8'))
            except PermissionDeniedError as error:
                session.log.exception(error)
                path_, operation = error.pathsAndOperations[0]
                if operation == Operation.CREATE_OBJECT:
                    raise TUnauthorized()
                else:
                    raise TNonexistentTag(path_)

            # Run queries.
            try:
                with session.timer.track('index-search'):
                    result = blockingCallFromThread(reactor, searchQueries.get)
            except SearchError as error:
                session.log.exception(error)
                raise TParseError(query, error.message)

            # Build a result set from the searches.
            values = {}
            for parsedQuery, objectIDs in result.iteritems():
                for objectID in objectIDs:
                    for tagAndValue in valuesByQuery[parsedQuery]:
                        value = guessValue(tagAndValue.value)
                        # FIXME: this code sucks, but I rather not having
                        # to modify guessValue to return a list, as that
                        # would break other code.
                        # Hopefully, we'll be able to remove this pretty
                        # soon.
                        if isinstance(value, list):
                            value = [item.decode('utf-8') for item in value]
                        if objectID not in values:
                            values[objectID] = {}
                        values[objectID][tagAndValue.path] = value

            # Update values.
            if values:
                tagValues = SecureTagValueAPI(session.auth.user)
                try:
                    result = tagValues.set(values)
                except UnknownPathError as error:
                    session.log.exception(error)
                    path = error.paths[0]
                    raise TNonexistentTag(path.encode('utf-8'))
                except MalformedPathError as error:
                    # FIXME: Modify MalformedPathError to have a path field.
                    raise TInvalidPath(str(error).encode('utf-8'))
                except PermissionDeniedError as error:
                    session.log.exception(error)
                    path_, operation = error.pathsAndOperations[0]
                    category, action = getCategoryAndAction(operation)
                    raise TPathPermissionDenied(category, action, path_)
Exemplo n.º 4
0
 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'*****@*****.**')])
Exemplo n.º 5
0
 def run():
     objects = SecureObjectAPI(session.auth.user)
     objectID = objects.get([about]).get(about)
     if objectID is None:
         return []
     recentActivity = SecureRecentActivityAPI(session.auth.user)
     result = recentActivity.getForObjects([objectID])
     return self._formatResult(result)
Exemplo n.º 6
0
 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)
Exemplo n.º 7
0
 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)
Exemplo n.º 8
0
        def run():
            result = TObjectInfo()
            objects = SecureObjectAPI(session.auth.user)
            tagPaths = objects.getTagsByObjects([objectID])
            if not tagPaths:
                result.tagPaths = []
                return result

            tagPaths = tagPaths[objectID]
            if showAbout and u'fluiddb/about' in tagPaths:
                tagValues = SecureTagValueAPI(session.auth.user)
                values = tagValues.get([objectID], [u'fluiddb/about'])
                about = values[objectID][u'fluiddb/about'].value
                result.about = about.encode('utf-8')
            result.tagPaths = tagPaths
            return result
Exemplo n.º 9
0
 def run():
     try:
         result = SecureObjectAPI(session.auth.user).create(about)
     except PermissionDeniedError as error:
         session.log.exception(error)
         raise TUnauthorized()
     return str(result)
Exemplo n.º 10
0
 def setUp(self):
     super(SecureObjectAPIWithBrokenCacheTest, self).setUp()
     self.system = createSystemData()
     UserAPI().create([(u'user', u'password', u'User',
                        u'*****@*****.**')])
     self.user = getUser(u'user')
     self.objects = SecureObjectAPI(self.user)
Exemplo n.º 11
0
 def setUp(self):
     super(DatasetImporterTest, self).setUp()
     self.system = createSystemData()
     UserAPI().create([(u'user', u'secret', u'User', u'*****@*****.**')])
     user = getUser(u'user')
     self.objects = SecureObjectAPI(user)
     self.values = SecureTagValueAPI(user)
Exemplo n.º 12
0
 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)
Exemplo n.º 13
0
    def _getObjectData(self, user, objects):
        """Reformat the data to directly import it into Fluidinfo.

        @param user: The L{User} to use when preparing data to import.
        @param objects: The C{list} of objects to convert into the
            L{TagValueAPI.set} format.
        @return: A C{dict} with object information that can be used to make a
            L{TagValueAPI.set} call.
        """
        api = SecureObjectAPI(user)
        data = {}
        for objectData in objects:
            # FIXME We could reduce the number of queries here by making
            # ObjectAPI.create take a 'skipExistanceCheck' parameter and using
            # ObjectAPI.get to prefetch object IDs for all existing about
            # values.
            objectID = api.create(objectData['about'])
            data[objectID] = objectData['values']
        return data
Exemplo n.º 14
0
    def _getObjectData(self, user, objects):
        """Reformat the data to directly import it into Fluidinfo.

        @param user: The L{User} to use when preparing data to import.
        @param objects: The C{list} of objects to convert into the
            L{TagValueAPI.set} format.
        @return: A C{dict} with object information that can be used to make a
            L{TagValueAPI.set} call.
        """
        api = SecureObjectAPI(user)
        data = {}
        for objectData in objects:
            # FIXME We could reduce the number of queries here by making
            # ObjectAPI.create take a 'skipExistanceCheck' parameter and using
            # ObjectAPI.get to prefetch object IDs for all existing about
            # values.
            objectID = api.create(objectData['about'])
            data[objectID] = objectData['values']
        return data
Exemplo n.º 15
0
        def run():
            objects = SecureObjectAPI(session.auth.user)

            # _resolveQuery is implemented in FacadeTagValueMixin
            objectIDs = self._resolveQuery(session, objects, parsedQuery)

            # FIXME: This sucks, but right now if the query returns too many
            # objects, RecentActivityAPI will blow up. While we fix this, it's
            # better to return a 400 than a 500.
            if len(objectIDs) > 2000:
                raise TBadRequest('The given query returns to many objects.')

            recentActivity = SecureRecentActivityAPI(session.auth.user)
            result = recentActivity.getForObjects(objectIDs)
            return self._formatResult(result)
Exemplo n.º 16
0
        def run():
            tagValues = SecureTagValueAPI(session.auth.user)
            objects = SecureObjectAPI(session.auth.user)
            objectIDs = self._resolveQuery(session, objects, parsedQuery)
            if not objectIDs:
                return dumps({'results': {'id': {}}})
            try:
                values = tagValues.get(objectIDs, tags)
            except UnknownPathError as error:
                # One or more of the requested return Tag's doesn't exist.
                # We'll filter them out and try again because we don't want to
                # fail the request just because of a missing tag.
                filteredTags = set(tags) - set(error.paths)
                if not filteredTags:
                    return dumps({'results': {'id': {}}})
                values = tagValues.get(objectIDs, filteredTags)
            except PermissionDeniedError as error:
                session.log.exception(error)
                path_, operation = error.pathsAndOperations[0]
                raise TNonexistentTag(path_)

            valuesByObjectID = {}
            for objectID, tagPaths in values.iteritems():
                for tagPath, tagValue in tagPaths.iteritems():
                    value = tagValue.value
                    if isinstance(value, dict):
                        size = len(value[u'contents'])
                        mimeType = value[u'mime-type']
                        value = {u'value-type': mimeType,
                                 u'size': size}
                    elif isinstance(value, UUID):
                        value = {'value': str(value)}
                    else:
                        value = {'value': value}
                    value['updated-at'] = tagValue.creationTime.isoformat()
                    value['username'] = tagValue.creator.username
                    objectID = str(objectID)
                    valuesByObjectID.setdefault(objectID, {})[tagPath] = value
            result = {'results': {'id': valuesByObjectID}}
            return dumps(result)
Exemplo n.º 17
0
        def run():
            objects = SecureObjectAPI(session.auth.user)

            # _resolveQuery is implemented in FacadeTagValueMixin
            objectIDs = self._resolveQuery(session, objects, parsedQuery)

            if not objectIDs:
                return []

            # FIXME: This sucks, but right now if the query returns too many
            # objects, RecentActivityAPI will blow up. While we fix this, it's
            # better to return a 400 than a 500.
            if len(objectIDs) > 2000:
                raise TBadRequest('The given query returns to many objects.')

            values = SecureTagValueAPI(session.auth.user)
            result = values.get(objectIDs, [u'fluiddb/users/username'])
            usernames = [result[objectID][u'fluiddb/users/username'].value
                         for objectID in result]

            recentActivity = SecureRecentActivityAPI(session.auth.user)
            result = recentActivity.getForUsers(usernames)
            return self._formatResult(result)
Exemplo n.º 18
0
class CommentImporterTest(FluidinfoTestCase):

    resources = [('cache', CacheResource()), ('config', ConfigResource()),
                 ('log', LoggingResource(format='%(message)s')),
                 ('store', DatabaseResource())]

    def setUp(self):
        super(CommentImporterTest, self).setUp()
        self.system = createSystemData()
        UserAPI().create([(u'fluidinfo.com', u'secret', u'User',
                           u'*****@*****.**')])
        user = getUser(u'fluidinfo.com')
        self.objects = SecureObjectAPI(user)
        self.values = SecureTagValueAPI(user)

    def testUpload(self):
        """
        Comments are uploaded directly to Fluidinfo. After performing an
        upload, all the inserted values must be present in Fluidinfo.
        """
        when = datetime.utcnow()
        floatTime = timegm(when.utctimetuple()) + float(when.strftime('0.%f'))
        isoTime = when.isoformat()
        client = CommentImporter(100)
        client.upload([{
            'about': [u'one', u'two'],
            'importer': u'fluidinfo.com',
            'text': u'Here is my #wonderful comment',
            'timestamp': when,
            'url': u'http://twitter.com/status/9373973',
            'username': u'joe'
        }])
        about = u'fluidinfo.com joe %s' % isoTime
        result = self.objects.get([about])
        objectID = result[about]
        result = self.values.get([objectID], [
            u'fluidinfo.com/info/about',
            u'fluidinfo.com/info/text',
            u'fluidinfo.com/info/timestamp',
            u'fluidinfo.com/info/url',
            u'fluidinfo.com/info/username',
        ])
        comment = result[objectID]
        self.assertEqual([u'one', u'two', u'#wonderful'],
                         comment[u'fluidinfo.com/info/about'].value)
        self.assertEqual(u'Here is my #wonderful comment',
                         comment[u'fluidinfo.com/info/text'].value)
        self.assertEqual(floatTime,
                         comment[u'fluidinfo.com/info/timestamp'].value)
        self.assertEqual(u'http://twitter.com/status/9373973',
                         comment[u'fluidinfo.com/info/url'].value)
        self.assertEqual(u'joe', comment[u'fluidinfo.com/info/username'].value)

    def testUploadWithoutAboutValues(self):
        """
        When no explicit about values are in the uploaded comment, there
        must be no about values stored in Fluidinfo.
        """
        when = datetime.utcnow()
        isoTime = when.isoformat()
        client = CommentImporter(100)
        client.upload([{
            'importer': u'fluidinfo.com',
            'text': u'Here is my comment',
            'timestamp': when,
            'url': u'http://twitter.com/status/9373973',
            'username': u'joe'
        }])
        about = u'fluidinfo.com joe %s' % isoTime
        result = self.objects.get([about])
        objectID = result[about]
        result = self.values.get([objectID], [u'fluidinfo.com/info/about'])
        comment = result[objectID]
        self.assertEqual([], comment[u'fluidinfo.com/info/about'].value)

    def testUploadMultipleComments(self):
        """Multiple comments are inserted in batches."""
        when = datetime.utcnow()
        isoTime = when.isoformat()
        client = CommentImporter(100)
        client.upload([{
            'importer': u'fluidinfo.com',
            'text': u'Here is my #wonderful comment',
            'timestamp': when,
            'url': u'http://twitter.com/status/9373973',
            'username': u'joe'
        }, {
            'importer': u'fluidinfo.com',
            'text': u'A #crazy comment',
            'timestamp': when,
            'url': u'http://twitter.com/status/9279479379',
            'username': u'mike'
        }])

        about1 = u'fluidinfo.com joe %s' % isoTime
        about2 = u'fluidinfo.com mike %s' % isoTime
        result = self.objects.get([about1, about2])

        objectID1 = result[about1]
        objectID2 = result[about2]
        comments = self.values.get([objectID1, objectID2],
                                   [u'fluidinfo.com/info/text'])

        comment1 = comments[objectID1]
        self.assertEqual(u'Here is my #wonderful comment',
                         comment1[u'fluidinfo.com/info/text'].value)

        comment2 = comments[objectID2]
        self.assertEqual(u'A #crazy comment',
                         comment2[u'fluidinfo.com/info/text'].value)

        self.assertTrue(self.log.getvalue().startswith(
            'Importing 2 new comments.\nImported 2/2 new comments.\n'
            'Imported 2 comments in '))

    def testUploadUsesBatchSize(self):
        """
        Comments are uploaded in batches when possible, depending on the batch
        size.
        """
        when = datetime.utcnow()
        client = CommentImporter(1)
        client.upload([{
            'importer': u'fluidinfo.com',
            'text': u'Here is my #wonderful comment',
            'timestamp': when,
            'url': u'http://twitter.com/status/9373973',
            'username': u'joe'
        }, {
            'importer': u'fluidinfo.com',
            'text': u'A #crazy comment',
            'timestamp': when,
            'url': u'http://twitter.com/status/9279479379',
            'username': u'mike'
        }])
        self.assertTrue(self.log.getvalue().startswith(
            'Importing 2 new comments.\nImported 1/2 new comments.\n'
            'Imported 2/2 new comments.\nImported 2 comments in '))

    def testUploadLogsMessage(self):
        """
        Uploads must prefix log output with the passed message.
        """
        when = datetime.utcnow()
        client = CommentImporter(100)
        client.upload([{
            'importer': u'fluidinfo.com',
            'text': u'Here is my #wonderful comment',
            'timestamp': when,
            'url': u'http://twitter.com/status/9373973',
            'username': u'joe'
        }], 'message-xxx')
        self.assertTrue(self.log.getvalue().startswith(
            'message-xxx: Importing 1 new comments.\n'
            'message-xxx: Imported 1/1 new comments.\n'
            'message-xxx: Imported 1 comments in '))
Exemplo n.º 19
0
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)
Exemplo n.º 20
0
class DatasetImporterTest(FluidinfoTestCase):

    resources = [('cache', CacheResource()),
                 ('config', ConfigResource()),
                 ('log', LoggingResource(format='%(message)s')),
                 ('store', DatabaseResource())]

    def setUp(self):
        super(DatasetImporterTest, self).setUp()
        self.system = createSystemData()
        UserAPI().create([(u'user', u'secret', u'User', u'*****@*****.**')])
        user = getUser(u'user')
        self.objects = SecureObjectAPI(user)
        self.values = SecureTagValueAPI(user)

    def testUpload(self):
        """
        Object data is converted into a format compatible with the
        L{TagValueAPI.set} method before being uploaded directly into
        Fluidinfo.
        """
        client = DatasetImporter(100)
        client.upload(u'user',
                      [{'about': u'hello world', 'values': {u'user/bar': 13}}])
        result = self.objects.get([u'hello world'])
        objectID = result[u'hello world']
        result = self.values.get([objectID], [u'user/bar'])
        value = result[objectID][u'user/bar']
        self.assertEqual(13, value.value)

    def testUploadMultipleObjects(self):
        """Multiple objects are inserted in batches."""
        client = DatasetImporter(100)
        client.upload(u'user',
                      [{'about': u'hello world', 'values': {u'user/bar': 13}},
                       {'about': u'wubble', 'values': {u'user/quux': 42}}])
        aboutValues = self.objects.get([u'hello world', u'wubble'])

        objectID = aboutValues[u'hello world']
        result = self.values.get([objectID], [u'user/bar'])
        value = result[objectID][u'user/bar']
        self.assertEqual(13, value.value)

        objectID = aboutValues[u'wubble']
        result = self.values.get([objectID], [u'user/quux'])
        value = result[objectID][u'user/quux']
        self.assertEqual(42, value.value)
        self.assertTrue(self.log.getvalue().startswith(
            'Importing 2 new objects.\nImported 2/2 new objects.\n'
            'Imported 2 objects in '))

    def testUploadUsesBatchSize(self):
        """
        Objects are uploaded in batches when possible, depending on the batch
        size.
        """
        client = DatasetImporter(1)
        client.upload(u'user',
                      [{'about': u'hello world', 'values': {u'user/bar': 13}},
                       {'about': u'wubble', 'values': {u'user/quux': 42}}])
        self.assertTrue(self.log.getvalue().startswith(
            'Importing 2 new objects.\nImported 1/2 new objects.\n'
            'Imported 2/2 new objects.\nImported 2 objects in '))

    def testUploadWithUncreatablePath(self):
        """
        L{DatasetImporter.upload} checks permissions when importing data.  An
        L{UnknownPathError} is raised if a specified tag doesn't exist and the
        L{User} doesn't have permissions to create it.
        """
        client = DatasetImporter(100)
        self.assertRaises(
            UnknownPathError, client.upload, u'user',
            [{'about': u'hello world', 'values': {u'foo/bar': 13}}])

    def testUploadWithPermissionViolation(self):
        """L{DatasetImporter.upload} checks permissions when importing data."""
        UserAPI().create([(u'user1', u'pwd', u'User 1', u'*****@*****.**')])
        client = DatasetImporter(100)
        self.assertRaises(
            PermissionDeniedError, client.upload, u'user',
            [{'about': u'hello world', 'values': {u'user1/bar': 13}}])

    def testUploadWithUnknownUser(self):
        """
        L{DatasetImporter.upload} raises an L{UnknownUserError} if the
        specified L{User} doesn't exist.
        """
        client = DatasetImporter(100)
        self.assertRaises(
            UnknownUserError, client.upload, u'unknown',
            [{'about': u'hello world', 'values': {u'unknown/bar': 13}}])

    def testUploadLogsMessage(self):
        """
        Uploads must prefix log output with the passed message.
        """
        client = DatasetImporter(100)
        client.upload(u'user',
                      [{'about': u'hello world', 'values': {u'user/bar': 13}}],
                      'message-xxx')
        self.assertTrue(self.log.getvalue().startswith(
            'message-xxx: Importing 1 new objects.\n'
            'message-xxx: Imported 1/1 new objects.\n'
            'message-xxx: Imported 1 objects in '))
Exemplo n.º 21
0
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]))
Exemplo n.º 22
0
 def run():
     objects = SecureObjectAPI(session.auth.user)
     objectIDs = self._resolveQuery(session, objects, parsedQuery)
     return [str(objectID) for objectID in objectIDs]
Exemplo n.º 23
0
class DatasetImporterTest(FluidinfoTestCase):

    resources = [('cache', CacheResource()), ('config', ConfigResource()),
                 ('log', LoggingResource(format='%(message)s')),
                 ('store', DatabaseResource())]

    def setUp(self):
        super(DatasetImporterTest, self).setUp()
        self.system = createSystemData()
        UserAPI().create([(u'user', u'secret', u'User', u'*****@*****.**')])
        user = getUser(u'user')
        self.objects = SecureObjectAPI(user)
        self.values = SecureTagValueAPI(user)

    def testUpload(self):
        """
        Object data is converted into a format compatible with the
        L{TagValueAPI.set} method before being uploaded directly into
        Fluidinfo.
        """
        client = DatasetImporter(100)
        client.upload(u'user', [{
            'about': u'hello world',
            'values': {
                u'user/bar': 13
            }
        }])
        result = self.objects.get([u'hello world'])
        objectID = result[u'hello world']
        result = self.values.get([objectID], [u'user/bar'])
        value = result[objectID][u'user/bar']
        self.assertEqual(13, value.value)

    def testUploadMultipleObjects(self):
        """Multiple objects are inserted in batches."""
        client = DatasetImporter(100)
        client.upload(u'user', [{
            'about': u'hello world',
            'values': {
                u'user/bar': 13
            }
        }, {
            'about': u'wubble',
            'values': {
                u'user/quux': 42
            }
        }])
        aboutValues = self.objects.get([u'hello world', u'wubble'])

        objectID = aboutValues[u'hello world']
        result = self.values.get([objectID], [u'user/bar'])
        value = result[objectID][u'user/bar']
        self.assertEqual(13, value.value)

        objectID = aboutValues[u'wubble']
        result = self.values.get([objectID], [u'user/quux'])
        value = result[objectID][u'user/quux']
        self.assertEqual(42, value.value)
        self.assertTrue(self.log.getvalue().startswith(
            'Importing 2 new objects.\nImported 2/2 new objects.\n'
            'Imported 2 objects in '))

    def testUploadUsesBatchSize(self):
        """
        Objects are uploaded in batches when possible, depending on the batch
        size.
        """
        client = DatasetImporter(1)
        client.upload(u'user', [{
            'about': u'hello world',
            'values': {
                u'user/bar': 13
            }
        }, {
            'about': u'wubble',
            'values': {
                u'user/quux': 42
            }
        }])
        self.assertTrue(self.log.getvalue().startswith(
            'Importing 2 new objects.\nImported 1/2 new objects.\n'
            'Imported 2/2 new objects.\nImported 2 objects in '))

    def testUploadWithUncreatablePath(self):
        """
        L{DatasetImporter.upload} checks permissions when importing data.  An
        L{UnknownPathError} is raised if a specified tag doesn't exist and the
        L{User} doesn't have permissions to create it.
        """
        client = DatasetImporter(100)
        self.assertRaises(UnknownPathError, client.upload, u'user', [{
            'about': u'hello world',
            'values': {
                u'foo/bar': 13
            }
        }])

    def testUploadWithPermissionViolation(self):
        """L{DatasetImporter.upload} checks permissions when importing data."""
        UserAPI().create([(u'user1', u'pwd', u'User 1', u'*****@*****.**')])
        client = DatasetImporter(100)
        self.assertRaises(PermissionDeniedError, client.upload, u'user',
                          [{
                              'about': u'hello world',
                              'values': {
                                  u'user1/bar': 13
                              }
                          }])

    def testUploadWithUnknownUser(self):
        """
        L{DatasetImporter.upload} raises an L{UnknownUserError} if the
        specified L{User} doesn't exist.
        """
        client = DatasetImporter(100)
        self.assertRaises(UnknownUserError, client.upload, u'unknown',
                          [{
                              'about': u'hello world',
                              'values': {
                                  u'unknown/bar': 13
                              }
                          }])

    def testUploadLogsMessage(self):
        """
        Uploads must prefix log output with the passed message.
        """
        client = DatasetImporter(100)
        client.upload(u'user', [{
            'about': u'hello world',
            'values': {
                u'user/bar': 13
            }
        }], 'message-xxx')
        self.assertTrue(self.log.getvalue().startswith(
            'message-xxx: Importing 1 new objects.\n'
            'message-xxx: Imported 1/1 new objects.\n'
            'message-xxx: Imported 1 objects in '))
Exemplo n.º 24
0
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])))
Exemplo n.º 25
0
class CommentImporterTest(FluidinfoTestCase):

    resources = [('cache', CacheResource()),
                 ('config', ConfigResource()),
                 ('log', LoggingResource(format='%(message)s')),
                 ('store', DatabaseResource())]

    def setUp(self):
        super(CommentImporterTest, self).setUp()
        self.system = createSystemData()
        UserAPI().create([
            (u'fluidinfo.com', u'secret', u'User', u'*****@*****.**')])
        user = getUser(u'fluidinfo.com')
        self.objects = SecureObjectAPI(user)
        self.values = SecureTagValueAPI(user)

    def testUpload(self):
        """
        Comments are uploaded directly to Fluidinfo. After performing an
        upload, all the inserted values must be present in Fluidinfo.
        """
        when = datetime.utcnow()
        floatTime = timegm(when.utctimetuple()) + float(when.strftime('0.%f'))
        isoTime = when.isoformat()
        client = CommentImporter(100)
        client.upload([
            {'about': [u'one', u'two'],
             'importer': u'fluidinfo.com',
             'text': u'Here is my #wonderful comment',
             'timestamp': when,
             'url': u'http://twitter.com/status/9373973',
             'username': u'joe'}
        ])
        about = u'fluidinfo.com joe %s' % isoTime
        result = self.objects.get([about])
        objectID = result[about]
        result = self.values.get([objectID], [u'fluidinfo.com/info/about',
                                              u'fluidinfo.com/info/text',
                                              u'fluidinfo.com/info/timestamp',
                                              u'fluidinfo.com/info/url',
                                              u'fluidinfo.com/info/username',
                                              ])
        comment = result[objectID]
        self.assertEqual([u'one', u'two', u'#wonderful'],
                         comment[u'fluidinfo.com/info/about'].value)
        self.assertEqual(u'Here is my #wonderful comment',
                         comment[u'fluidinfo.com/info/text'].value)
        self.assertEqual(floatTime,
                         comment[u'fluidinfo.com/info/timestamp'].value)
        self.assertEqual(u'http://twitter.com/status/9373973',
                         comment[u'fluidinfo.com/info/url'].value)
        self.assertEqual(u'joe',
                         comment[u'fluidinfo.com/info/username'].value)

    def testUploadWithoutAboutValues(self):
        """
        When no explicit about values are in the uploaded comment, there
        must be no about values stored in Fluidinfo.
        """
        when = datetime.utcnow()
        isoTime = when.isoformat()
        client = CommentImporter(100)
        client.upload([
            {'importer': u'fluidinfo.com',
             'text': u'Here is my comment',
             'timestamp': when,
             'url': u'http://twitter.com/status/9373973',
             'username': u'joe'}
        ])
        about = u'fluidinfo.com joe %s' % isoTime
        result = self.objects.get([about])
        objectID = result[about]
        result = self.values.get([objectID], [u'fluidinfo.com/info/about'])
        comment = result[objectID]
        self.assertEqual([], comment[u'fluidinfo.com/info/about'].value)

    def testUploadMultipleComments(self):
        """Multiple comments are inserted in batches."""
        when = datetime.utcnow()
        isoTime = when.isoformat()
        client = CommentImporter(100)
        client.upload([
            {'importer': u'fluidinfo.com',
             'text': u'Here is my #wonderful comment',
             'timestamp': when,
             'url': u'http://twitter.com/status/9373973',
             'username': u'joe'},
            {'importer': u'fluidinfo.com',
             'text': u'A #crazy comment',
             'timestamp': when,
             'url': u'http://twitter.com/status/9279479379',
             'username': u'mike'}
        ])

        about1 = u'fluidinfo.com joe %s' % isoTime
        about2 = u'fluidinfo.com mike %s' % isoTime
        result = self.objects.get([about1, about2])

        objectID1 = result[about1]
        objectID2 = result[about2]
        comments = self.values.get([objectID1, objectID2],
                                   [u'fluidinfo.com/info/text'])

        comment1 = comments[objectID1]
        self.assertEqual(u'Here is my #wonderful comment',
                         comment1[u'fluidinfo.com/info/text'].value)

        comment2 = comments[objectID2]
        self.assertEqual(u'A #crazy comment',
                         comment2[u'fluidinfo.com/info/text'].value)

        self.assertTrue(self.log.getvalue().startswith(
            'Importing 2 new comments.\nImported 2/2 new comments.\n'
            'Imported 2 comments in '))

    def testUploadUsesBatchSize(self):
        """
        Comments are uploaded in batches when possible, depending on the batch
        size.
        """
        when = datetime.utcnow()
        client = CommentImporter(1)
        client.upload([
            {'importer': u'fluidinfo.com',
             'text': u'Here is my #wonderful comment',
             'timestamp': when,
             'url': u'http://twitter.com/status/9373973',
             'username': u'joe'},
            {'importer': u'fluidinfo.com',
             'text': u'A #crazy comment',
             'timestamp': when,
             'url': u'http://twitter.com/status/9279479379',
             'username': u'mike'}
        ])
        self.assertTrue(self.log.getvalue().startswith(
            'Importing 2 new comments.\nImported 1/2 new comments.\n'
            'Imported 2/2 new comments.\nImported 2 comments in '))

    def testUploadLogsMessage(self):
        """
        Uploads must prefix log output with the passed message.
        """
        when = datetime.utcnow()
        client = CommentImporter(100)
        client.upload([
            {'importer': u'fluidinfo.com',
             'text': u'Here is my #wonderful comment',
             'timestamp': when,
             'url': u'http://twitter.com/status/9373973',
             'username': u'joe'}], 'message-xxx')
        self.assertTrue(self.log.getvalue().startswith(
            'message-xxx: Importing 1 new comments.\n'
            'message-xxx: Imported 1/1 new comments.\n'
            'message-xxx: Imported 1 comments in '))