Exemple #1
0
 def run():
     tagValues = SecureTagValueAPI(session.auth.user)
     try:
         result = tagValues.get([objectID], [path])
     except PermissionDeniedError as error:
         session.log.exception(error)
         path_, operation = error.pathsAndOperations[0]
         raise TNonexistentTag(path_)
     except UnknownPathError as error:
         session.log.exception(error)
         raise TNonexistentTag(path)
     if not result:
         raise TNoInstanceOnObject(path, objectId)
     else:
         tagValue = result[objectID][path]
         value = tagValue.value
         # FIXME This is a bit crap, but its easier than modifying
         # Thrift-related logic.
         if isinstance(value, dict):
             mimeType = value['mime-type'].encode('utf-8')
             value = createBinaryThriftValue(value['contents'],
                                             mimeType)
         elif isinstance(value, UUID):
             value = createThriftValue(str(value))
         else:
             value = createThriftValue(value)
         return (value, tagValue)
Exemple #2
0
    def _parseOldPayloadDict(cls, tagValueDict):
        """
        Get a list of Tag/Value pairs from a given payload dictionary.

        @param tagValueDict: A payload C{dict} representing the tag/value
            pairs.
        @return: A list of L{TagPathAndValue} objects.
        """

        # tagsAndValues is what we'll pass to the facade to
        # indicate what values to put on the objects that match the query.
        tagsAndValues = []

        # Check the JSON tag/value specification to make sure all values
        # are primitive types we know how to handle.
        # FIXME: we could use a JSON schema library to facilitate this.
        for tag in tagValueDict:
            try:
                value = tagValueDict[tag][valueKey]
            except TypeError:
                # requestTagValueDict[tag] is not a dict.
                raise error.InvalidPayloadField(tag)
            except KeyError:
                # valueKey not present in requestTagValueDict[tag].
                raise error.PayloadFieldMissing(valueKey)

            valueType = type(value)
            if valueType in (bool, int, float, unicode, types.NoneType):
                # This is a valid primitive type. Nothing to do.
                tvalue = createThriftValue(value)
            elif valueType is list:
                # Make sure we have a list of strings.
                strlist = []
                for s in value:
                    if isinstance(s, unicode):
                        s = s.encode('utf-8')
                    elif not isinstance(s, str):
                        raise error.UnsupportedJSONType()
                    strlist.append(s)
                tvalue = createThriftValue(strlist)
            else:
                raise error.UnsupportedJSONType()

            tagsAndValues.append(TagPathAndValue(tag, tvalue))
        return tagsAndValues
Exemple #3
0
    def _parseOldPayloadDict(cls, tagValueDict):
        """
        Get a list of Tag/Value pairs from a given payload dictionary.

        @param tagValueDict: A payload C{dict} representing the tag/value
            pairs.
        @return: A list of L{TagPathAndValue} objects.
        """

        # tagsAndValues is what we'll pass to the facade to
        # indicate what values to put on the objects that match the query.
        tagsAndValues = []

        # Check the JSON tag/value specification to make sure all values
        # are primitive types we know how to handle.
        # FIXME: we could use a JSON schema library to facilitate this.
        for tag in tagValueDict:
            try:
                value = tagValueDict[tag][valueKey]
            except TypeError:
                # requestTagValueDict[tag] is not a dict.
                raise error.InvalidPayloadField(tag)
            except KeyError:
                # valueKey not present in requestTagValueDict[tag].
                raise error.PayloadFieldMissing(valueKey)

            valueType = type(value)
            if valueType in (bool, int, float, unicode, types.NoneType):
                # This is a valid primitive type. Nothing to do.
                tvalue = createThriftValue(value)
            elif valueType is list:
                # Make sure we have a list of strings.
                strlist = []
                for s in value:
                    if isinstance(s, unicode):
                        s = s.encode('utf-8')
                    elif not isinstance(s, str):
                        raise error.UnsupportedJSONType()
                    strlist.append(s)
                tvalue = createThriftValue(strlist)
            else:
                raise error.UnsupportedJSONType()

            tagsAndValues.append(TagPathAndValue(tag, tvalue))
        return tagsAndValues
Exemple #4
0
 def run():
     tagValues = SecureTagValueAPI(session.auth.user)
     try:
         values = tagValues.get([objectID], [path])
         return createThriftValue(len(values.keys()) > 0)
     except UnknownPathError as error:
         session.log.exception(error)
         raise TNonexistentTag(path.encode('utf-8'))
     except PermissionDeniedError as error:
         session.log.exception(error)
         path_, operation = error.pathsAndOperations[0]
         raise TNonexistentTag(path_)
Exemple #5
0
    def deferred_render_PUT(self, request):
        """
        The following code is reproduced almost verbatim in
        deferred_render_PUT in about.py. So if you change this code,
        you'll likely need to change that, and vice versa.
        """
        usage = registry.findUsage(httpObjectCategoryName, 'PUT',
                                   TagInstanceResource)
        payload = registry.checkRequest(usage, request)
        contentType = request.getHeader('content-type')

        if contentType is None:
            if payload is None:
                contentTypeFirstComponent = contentTypeForPrimitiveJSON
            else:
                raise error.NoContentTypeHeader()
        else:
            # Get the lowercased first component of the content type, as
            # split by semicolon (the HTTP standard for separating the
            # content type from other tags, such as charset).
            #
            # Doing it this way allows us to ignore any other crud in the
            # content-type, for example a charset, when the content type is
            # our own contentTypeForPrimitiveJSON. See
            # https://oodl.es/trac/fluiddb/ticket/572 and the
            # testPrimitiveTypesWithCharsetAlsoInContentType test in
            # integration/wsfe/test_tagValues.py for more details
            #
            # We only need to rstrip the first component of the content
            # type as twisted.web does a strip on the whole header value
            # (so the left side is already stripped).
            contentTypeFirstComponent = \
                contentType.split(';')[0].lower().rstrip()

        if contentTypeFirstComponent == contentTypeForPrimitiveJSON:
            if payload is None:
                value = None
            else:
                value = payloads.parseJSONPayload(payload)
            tv = type(value)
            if tv in (bool, int, float, unicode, types.NoneType):
                tvalue = createThriftValue(value)
            elif tv is list:
                strlist = []
                for s in value:
                    if isinstance(s, unicode):
                        s = s.encode("utf-8")
                    elif not isinstance(s, str):
                        raise error.UnsupportedJSONType()
                    strlist.append(s)
                tvalue = createThriftValue(strlist)
            else:
                raise error.UnsupportedJSONType()
        else:
            tvalue = createBinaryThriftValue(payload, contentType)

        # log.msg("PUT: tvalue is %r" % tvalue)
        yield self.facadeClient.setTagInstance(
            self.session, self.path, self.objectId, tvalue)
        request.setResponseCode(usage.successCode)
        defer.returnValue(None)
Exemple #6
0
    def testRatingForObjectAboutBarcelona(self):
        """
        Run a series of tests on the ntoll/rating tag on the object about
        barcelona:

          - the tag should initially not be present.
          - we should successfully be able to do a PUT.
          - we should then be able to do a GET, HEAD, and DELETE in that order.
          - a final GET should then indicate the tag is gone.
        """
        about = 'barcelona'
        tag = 'ntoll/rating'
        rating = 6
        objectIdAboutBarcelona = util.generateObjectId()

        fakeQueryResolver = FakeQueryResolver(about, [objectIdAboutBarcelona],
                                              self)
        fakeTagsClient = FakeTagsClient()
        facadeClient = FakeFacadeClient(fakeTagsClient=fakeTagsClient,
                                        fakeQueryResolver=fakeQueryResolver)
        session = FakeSession()
        resource = AboutTagInstanceResource(facadeClient, session, about, tag)

        # Test GET when there is no instance on the object.
        d = defer.Deferred()
        request = FakeRequest('GET', d)
        request.content = StringIO.StringIO()
        resource.render(request)
        yield d
        self.assertEqual(request.status, http.NOT_FOUND)

        # Test PUT.
        payload = json.dumps(rating)
        headers = {
            'Content-Length': [str(len(payload))],
            'Content-Type': [contentTypeForPrimitiveJSON],
        }
        d = defer.Deferred()
        request = FakeRequest('PUT', d, headers)
        request.content = StringIO.StringIO(payload)
        resource.render(request)
        yield d
        self.assertEqual(request.status, http.NO_CONTENT)
        self.assertEqual(
            guessValue(fakeTagsClient.values[tag][objectIdAboutBarcelona]),
            rating)

        # Check that the right path, objectId, and value was passed to the
        # fake tags client.
        self.assertEqual(fakeTagsClient.values, {
            tag: {
                objectIdAboutBarcelona: createThriftValue(rating)
            },
        })

        # Test GET.
        d = defer.Deferred()
        request = FakeRequest('GET', d)
        request.content = StringIO.StringIO()
        resource.render(request)
        body = yield d
        self.assertEqual(request.status, http.OK)
        self.assertEqual(request.getResponseHeader('Content-Type'),
                         contentTypeForPrimitiveJSON)
        receivedRating = json.loads(body)
        self.assertEqual(receivedRating, rating)

        # Test HEAD
        d = defer.Deferred()
        request = FakeRequest('HEAD', d)
        request.content = StringIO.StringIO()
        resource.render(request)
        body = yield d
        self.assertEqual(request.status, http.OK)
        self.assertEqual(body, '')

        # Test DELETE
        d = defer.Deferred()
        request = FakeRequest('DELETE', d)
        request.content = StringIO.StringIO()
        resource.render(request)
        body = yield d
        self.assertEqual(request.status, http.NO_CONTENT)

        # Test GET when, finally, there is no instance on the object.
        d = defer.Deferred()
        request = FakeRequest('GET', d)
        request.content = StringIO.StringIO()
        resource.render(request)
        yield d
        self.assertEqual(request.status, http.NOT_FOUND)

        # Check that the value really was deleted.
        self.assertEqual(fakeTagsClient.values, {tag: {}})
Exemple #7
0
    def testRatingForObjectAboutBarcelona(self):
        """
        Run a series of tests on the ntoll/rating tag on the object about
        barcelona:

          - the tag should initially not be present.
          - we should successfully be able to do a PUT.
          - we should then be able to do a GET, HEAD, and DELETE in that order.
          - a final GET should then indicate the tag is gone.
        """
        about = 'barcelona'
        tag = 'ntoll/rating'
        rating = 6
        objectIdAboutBarcelona = util.generateObjectId()

        fakeQueryResolver = FakeQueryResolver(
            about, [objectIdAboutBarcelona], self)
        fakeTagsClient = FakeTagsClient()
        facadeClient = FakeFacadeClient(fakeTagsClient=fakeTagsClient,
                                        fakeQueryResolver=fakeQueryResolver)
        session = FakeSession()
        resource = AboutTagInstanceResource(facadeClient, session, about, tag)

        # Test GET when there is no instance on the object.
        d = defer.Deferred()
        request = FakeRequest('GET', d)
        request.content = StringIO.StringIO()
        resource.render(request)
        yield d
        self.assertEqual(request.status, http.NOT_FOUND)

        # Test PUT.
        payload = json.dumps(rating)
        headers = {
            'Content-Length': [str(len(payload))],
            'Content-Type': [contentTypeForPrimitiveJSON],
        }
        d = defer.Deferred()
        request = FakeRequest('PUT', d, headers)
        request.content = StringIO.StringIO(payload)
        resource.render(request)
        yield d
        self.assertEqual(request.status, http.NO_CONTENT)
        self.assertEqual(
            guessValue(fakeTagsClient.values[tag][objectIdAboutBarcelona]),
            rating)

        # Check that the right path, objectId, and value was passed to the
        # fake tags client.
        self.assertEqual(fakeTagsClient.values, {
            tag: {objectIdAboutBarcelona: createThriftValue(rating)},
        })

        # Test GET.
        d = defer.Deferred()
        request = FakeRequest('GET', d)
        request.content = StringIO.StringIO()
        resource.render(request)
        body = yield d
        self.assertEqual(request.status, http.OK)
        self.assertEqual(request.getResponseHeader('Content-Type'),
                         contentTypeForPrimitiveJSON)
        receivedRating = json.loads(body)
        self.assertEqual(receivedRating, rating)

        # Test HEAD
        d = defer.Deferred()
        request = FakeRequest('HEAD', d)
        request.content = StringIO.StringIO()
        resource.render(request)
        body = yield d
        self.assertEqual(request.status, http.OK)
        self.assertEqual(body, '')

        # Test DELETE
        d = defer.Deferred()
        request = FakeRequest('DELETE', d)
        request.content = StringIO.StringIO()
        resource.render(request)
        body = yield d
        self.assertEqual(request.status, http.NO_CONTENT)

        # Test GET when, finally, there is no instance on the object.
        d = defer.Deferred()
        request = FakeRequest('GET', d)
        request.content = StringIO.StringIO()
        resource.render(request)
        yield d
        self.assertEqual(request.status, http.NOT_FOUND)

        # Check that the value really was deleted.
        self.assertEqual(fakeTagsClient.values, {tag: {}})
Exemple #8
0
    def deferred_render_PUT(self, request):
        """
        PUT a tag value onto an object. Return a Deferred that fires with
        None when the tag value has been set by the facade.

        This code, apart from the yield self._setObjectId(), is taken
        verbatim from deferred_render_PUT in objects.py. So if you change
        this code, you'll likely need to change that, and vice versa.

        @param request: The HTTP request.

        @return: A C{Deferred} that fires with C{None} once the request has
                 completed.
        """
        usage = registry.findUsage(httpAboutCategoryName, 'PUT',
                                   AboutTagInstanceResource)
        payload = registry.checkRequest(usage, request)
        contentType = request.getHeader('content-type')

        if contentType is None:
            if payload is None:
                contentType = contentTypeForPrimitiveJSON
            else:
                raise error.NoContentTypeHeader()
        else:
            contentType = contentType.lower()

        if contentType == contentTypeForPrimitiveJSON:
            if payload is None:
                value = None
            else:
                value = payloads.parseJSONPayload(payload)
            tv = type(value)
            if tv in (bool, int, float, unicode, types.NoneType):
                tvalue = createThriftValue(value)
            elif tv is list:
                strlist = []
                for s in value:
                    if isinstance(s, unicode):
                        s = s.encode("utf-8")
                    elif not isinstance(s, str):
                        raise error.UnsupportedJSONType()
                    strlist.append(s)
                tvalue = createThriftValue(strlist)
            else:
                raise error.UnsupportedJSONType()
        else:
            tvalue = createBinaryThriftValue(payload, contentType)

        try:
            yield self._setObjectId()
        except error.NoSuchObject:
            # There is no object with this about value. So we create it.
            # This is consistent with /objects, which doesn't require an
            # object id to have been returned from createObject in order
            # for people to PUT tag values onto it.
            self.objectId = yield self.facadeClient.createObject(
                session=self.session, about=self.about)

        yield self.facadeClient.setTagInstance(self.session, self.path,
                                               self.objectId, tvalue)
        request.setResponseCode(usage.successCode)
        defer.returnValue(None)
Exemple #9
0
    def deferred_render_PUT(self, request):
        """
        PUT a tag value onto an object. Return a Deferred that fires with
        None when the tag value has been set by the facade.

        This code, apart from the yield self._setObjectId(), is taken
        verbatim from deferred_render_PUT in objects.py. So if you change
        this code, you'll likely need to change that, and vice versa.

        @param request: The HTTP request.

        @return: A C{Deferred} that fires with C{None} once the request has
                 completed.
        """
        usage = registry.findUsage(httpAboutCategoryName, 'PUT',
                                   AboutTagInstanceResource)
        payload = registry.checkRequest(usage, request)
        contentType = request.getHeader('content-type')

        if contentType is None:
            if payload is None:
                contentType = contentTypeForPrimitiveJSON
            else:
                raise error.NoContentTypeHeader()
        else:
            contentType = contentType.lower()

        if contentType == contentTypeForPrimitiveJSON:
            if payload is None:
                value = None
            else:
                value = payloads.parseJSONPayload(payload)
            tv = type(value)
            if tv in (bool, int, float, unicode, types.NoneType):
                tvalue = createThriftValue(value)
            elif tv is list:
                strlist = []
                for s in value:
                    if isinstance(s, unicode):
                        s = s.encode("utf-8")
                    elif not isinstance(s, str):
                        raise error.UnsupportedJSONType()
                    strlist.append(s)
                tvalue = createThriftValue(strlist)
            else:
                raise error.UnsupportedJSONType()
        else:
            tvalue = createBinaryThriftValue(payload, contentType)

        try:
            yield self._setObjectId()
        except error.NoSuchObject:
            # There is no object with this about value. So we create it.
            # This is consistent with /objects, which doesn't require an
            # object id to have been returned from createObject in order
            # for people to PUT tag values onto it.
            self.objectId = yield self.facadeClient.createObject(
                session=self.session, about=self.about)

        yield self.facadeClient.setTagInstance(
            self.session, self.path, self.objectId, tvalue)
        request.setResponseCode(usage.successCode)
        defer.returnValue(None)
Exemple #10
0
 def getTagInstance(self, session, path, objectId):
     """
     Returns an object previously stored in C{values}.
     """
     tvalue = createThriftValue(self.values[objectId][path])
     return defer.succeed((tvalue, None))
Exemple #11
0
 def __init__(self, path=None, value=None):
     if not isinstance(value, ThriftValue):
         value = createThriftValue(value)
     self.path = path
     self.value = value
Exemple #12
0
    def deferred_render_PUT(self, request):
        """
        The following code is reproduced almost verbatim in
        deferred_render_PUT in about.py. So if you change this code,
        you'll likely need to change that, and vice versa.
        """
        usage = registry.findUsage(httpObjectCategoryName, 'PUT',
                                   TagInstanceResource)
        payload = registry.checkRequest(usage, request)
        contentType = request.getHeader('content-type')

        if contentType is None:
            if payload is None:
                contentTypeFirstComponent = contentTypeForPrimitiveJSON
            else:
                raise error.NoContentTypeHeader()
        else:
            # Get the lowercased first component of the content type, as
            # split by semicolon (the HTTP standard for separating the
            # content type from other tags, such as charset).
            #
            # Doing it this way allows us to ignore any other crud in the
            # content-type, for example a charset, when the content type is
            # our own contentTypeForPrimitiveJSON. See
            # https://oodl.es/trac/fluiddb/ticket/572 and the
            # testPrimitiveTypesWithCharsetAlsoInContentType test in
            # integration/wsfe/test_tagValues.py for more details
            #
            # We only need to rstrip the first component of the content
            # type as twisted.web does a strip on the whole header value
            # (so the left side is already stripped).
            contentTypeFirstComponent = \
                contentType.split(';')[0].lower().rstrip()

        if contentTypeFirstComponent == contentTypeForPrimitiveJSON:
            if payload is None:
                value = None
            else:
                value = payloads.parseJSONPayload(payload)
            tv = type(value)
            if tv in (bool, int, float, unicode, types.NoneType):
                tvalue = createThriftValue(value)
            elif tv is list:
                strlist = []
                for s in value:
                    if isinstance(s, unicode):
                        s = s.encode("utf-8")
                    elif not isinstance(s, str):
                        raise error.UnsupportedJSONType()
                    strlist.append(s)
                tvalue = createThriftValue(strlist)
            else:
                raise error.UnsupportedJSONType()
        else:
            tvalue = createBinaryThriftValue(payload, contentType)

        # log.msg("PUT: tvalue is %r" % tvalue)
        yield self.facadeClient.setTagInstance(self.session, self.path,
                                               self.objectId, tvalue)
        request.setResponseCode(usage.successCode)
        defer.returnValue(None)