def deferred_render_GET(self, request): # TODO: usages should be cached locally; lookup is expensive. usage = registry.findUsage(httpTagCategoryName, 'GET', TagsResource) registry.checkRequest(usage, request) responseType = usage.getResponsePayloadTypeFromAcceptHeader(request) args = { returnDescriptionArg: util.getBooleanArg(request, returnDescriptionArg, usage.arguments[returnDescriptionArg].default), } ttag = yield self.facadeClient.getTag( self.session, sep.join(request.postpath), returnDescription=args[returnDescriptionArg]) responseDict = { 'id': ttag.objectId, 'indexed': ttag.indexed, } if args[returnDescriptionArg]: responseDict['description'] = ttag.description registry.checkResponse(responseType, responseDict, usage, request) body = payloads.buildPayload(responseType, responseDict) request.setHeader('Content-length', str(len(body))) request.setHeader('Content-type', responseType) request.setResponseCode(usage.successCode) defer.returnValue(body)
def deferred_render_DELETE(self, request): usage = registry.findUsage(httpNamespaceCategoryName, 'DELETE', NamespacesResource) registry.checkRequest(usage, request) yield self.facadeClient.deleteNamespace(self.session, sep.join(request.postpath)) request.setResponseCode(usage.successCode)
def deferred_render_GET(self, request): usage = registry.findUsage(httpObjectCategoryName, 'GET', ObjectResource) registry.checkRequest(usage, request) responseType = usage.getResponsePayloadTypeFromAcceptHeader(request) showAbout = util.getBooleanArg( request, showAboutArg, usage.arguments[showAboutArg].default) objectInfo = yield self.facadeClient.getObject( self.session, self.objectId, showAbout) responseDict = { tagPathsArg: objectInfo.tagPaths, } if showAbout: if objectInfo.about: responseDict[aboutArg] = objectInfo.about.decode('utf-8') else: responseDict[aboutArg] = None registry.checkResponse(responseType, responseDict, usage, request) body = payloads.buildPayload(responseType, responseDict) request.setHeader('Content-length', str(len(body))) request.setHeader('Content-type', responseType) request.setResponseCode(usage.successCode) defer.returnValue(body)
def deferred_render_GET(self, request): """ Return information about the object whose about value is given in the URI. @param request: The HTTP request. @return: A C{Deferred} that fires with the body of the response. """ usage = registry.findUsage(httpAboutCategoryName, 'GET', AboutObjectResource) registry.checkRequest(usage, request) responseType = usage.getResponsePayloadTypeFromAcceptHeader(request) # Note: we need to escape any double quotes in the about value so # that the query parser doesn't raise a syntax error. See # https://bugs.edge.launchpad.net/fluiddb/+bug/802783 query = '%s = "%s"' % (_aboutPath, self.about.replace('"', r'\"')) objectIds = yield self.facadeClient.resolveQuery(self.session, query) if objectIds: objectId = objectIds.pop() else: raise error.NoSuchObject() objectInfo = yield self.facadeClient.getObject(self.session, objectId, showAbout=False) responseDict = { _tagPathsArg: objectInfo.tagPaths, 'id': objectId, } registry.checkResponse(responseType, responseDict, usage, request) body = payloads.buildPayload(responseType, responseDict) request.setHeader('Content-length', str(len(body))) request.setHeader('Content-type', responseType) request.setResponseCode(usage.successCode) defer.returnValue(body)
def deferred_render_GET(self, request): """ Return information about the object whose about value is given in the URI. @param request: The HTTP request. @return: A C{Deferred} that fires with the body of the response. """ usage = registry.findUsage(httpAboutCategoryName, 'GET', AboutObjectResource) registry.checkRequest(usage, request) responseType = usage.getResponsePayloadTypeFromAcceptHeader(request) # Note: we need to escape any double quotes in the about value so # that the query parser doesn't raise a syntax error. See # https://bugs.edge.launchpad.net/fluiddb/+bug/802783 query = '%s = "%s"' % (_aboutPath, self.about.replace('"', r'\"')) objectIds = yield self.facadeClient.resolveQuery(self.session, query) if objectIds: objectId = objectIds.pop() else: raise error.NoSuchObject() objectInfo = yield self.facadeClient.getObject( self.session, objectId, showAbout=False) responseDict = { _tagPathsArg: objectInfo.tagPaths, 'id': objectId, } registry.checkResponse(responseType, responseDict, usage, request) body = payloads.buildPayload(responseType, responseDict) request.setHeader('Content-length', str(len(body))) request.setHeader('Content-type', responseType) request.setResponseCode(usage.successCode) defer.returnValue(body)
def deferred_render_DELETE(self, request): usage = registry.findUsage(httpNamespaceCategoryName, 'DELETE', NamespacesResource) registry.checkRequest(usage, request) yield self.facadeClient.deleteNamespace(self.session, sep.join(request.postpath)) request.setResponseCode(usage.successCode)
def deferred_render_GET(self, request): """ Handle a GET request for /values with a query and a list of wanted tags. @param request: The incoming C{twisted.web.server.Request} request. @return: A C{Deferred} which will fire with the body of the response. The deferred may errback for a variety of reasons, for example an invalid query, the mention of a non-existent tag or a tag that the caller does not have READ permission for. """ usage = registry.findUsage(httpValueCategoryName, 'GET', ValuesResource) registry.checkRequest(usage, request) responseType = usage.getResponsePayloadTypeFromAcceptHeader(request) query = request.args[queryArg][0] tags = request.args[tagArg] # FIXME An HTTP 500 will occur if a user passes '*' with some other # tags, like 'tag=foo&tag=*'. -jkakar if tags == ['*']: tags = None body = yield self.facadeClient.getValuesForQuery( self.session, query, tags) request.setHeader('Content-length', str(len(body))) request.setHeader('Content-type', responseType) request.setResponseCode(usage.successCode) defer.returnValue(body)
def deferred_render_GET(self, request): usage = registry.findUsage(httpObjectCategoryName, 'GET', ObjectResource) registry.checkRequest(usage, request) responseType = usage.getResponsePayloadTypeFromAcceptHeader(request) showAbout = util.getBooleanArg(request, showAboutArg, usage.arguments[showAboutArg].default) objectInfo = yield self.facadeClient.getObject(self.session, self.objectId, showAbout) responseDict = { tagPathsArg: objectInfo.tagPaths, } if showAbout: if objectInfo.about: responseDict[aboutArg] = objectInfo.about.decode('utf-8') else: responseDict[aboutArg] = None registry.checkResponse(responseType, responseDict, usage, request) body = payloads.buildPayload(responseType, responseDict) request.setHeader('Content-length', str(len(body))) request.setHeader('Content-type', responseType) request.setResponseCode(usage.successCode) defer.returnValue(body)
def deferred_render_GET(self, request): """ Handle a GET request for /values with a query and a list of wanted tags. @param request: The incoming C{twisted.web.server.Request} request. @return: A C{Deferred} which will fire with the body of the response. The deferred may errback for a variety of reasons, for example an invalid query, the mention of a non-existent tag or a tag that the caller does not have READ permission for. """ usage = registry.findUsage(httpValueCategoryName, 'GET', ValuesResource) registry.checkRequest(usage, request) responseType = usage.getResponsePayloadTypeFromAcceptHeader(request) query = request.args[queryArg][0] tags = request.args[tagArg] # FIXME An HTTP 500 will occur if a user passes '*' with some other # tags, like 'tag=foo&tag=*'. -jkakar if tags == ['*']: tags = None body = yield self.facadeClient.getValuesForQuery( self.session, query, tags) request.setHeader('Content-length', str(len(body))) request.setHeader('Content-type', responseType) request.setResponseCode(usage.successCode) defer.returnValue(body)
def deferred_render_GET(self, request): # TODO: usages should be cached locally; lookup is expensive. usage = registry.findUsage(httpTagCategoryName, 'GET', TagsResource) registry.checkRequest(usage, request) responseType = usage.getResponsePayloadTypeFromAcceptHeader(request) args = { returnDescriptionArg: util.getBooleanArg( request, returnDescriptionArg, usage.arguments[returnDescriptionArg].default), } ttag = yield self.facadeClient.getTag( self.session, sep.join(request.postpath), returnDescription=args[returnDescriptionArg]) responseDict = { 'id': ttag.objectId, 'indexed': ttag.indexed, } if args[returnDescriptionArg]: responseDict['description'] = ttag.description registry.checkResponse(responseType, responseDict, usage, request) body = payloads.buildPayload(responseType, responseDict) request.setHeader('Content-length', str(len(body))) request.setHeader('Content-type', responseType) request.setResponseCode(usage.successCode) defer.returnValue(body)
def deferred_render_DELETE(self, request): """ The following code is reproduced almost verbatim in deferred_render_DELETE in about.py. So if you change this code, you'll likely need to change that, and vice versa. """ usage = registry.findUsage(httpObjectCategoryName, 'DELETE', TagInstanceResource) registry.checkRequest(usage, request) yield self.facadeClient.deleteTagInstance( self.session, self.path, self.objectId) request.setResponseCode(usage.successCode) defer.returnValue(None)
def deferred_render_DELETE(self, request): """ The following code is reproduced almost verbatim in deferred_render_DELETE in about.py. So if you change this code, you'll likely need to change that, and vice versa. """ usage = registry.findUsage(httpObjectCategoryName, 'DELETE', TagInstanceResource) registry.checkRequest(usage, request) yield self.facadeClient.deleteTagInstance(self.session, self.path, self.objectId) request.setResponseCode(usage.successCode) defer.returnValue(None)
def deferred_render_GET(self, request): usage = registry.findUsage(httpObjectCategoryName, 'GET', ObjectsResource) registry.checkRequest(usage, request) responseType = usage.getResponsePayloadTypeFromAcceptHeader(request) query = request.args['query'][0] results = yield self.facadeClient.resolveQuery(self.session, query) responseDict = {'ids': list(results)} registry.checkResponse(responseType, responseDict, usage, request) body = payloads.buildPayload(responseType, responseDict) request.setHeader('Content-length', str(len(body))) request.setHeader('Content-type', responseType) request.setResponseCode(usage.successCode) defer.returnValue(body)
def deferred_render_GET(self, request): usage = registry.findUsage(httpObjectCategoryName, 'GET', ObjectsResource) registry.checkRequest(usage, request) responseType = usage.getResponsePayloadTypeFromAcceptHeader(request) query = request.args['query'][0] results = yield self.facadeClient.resolveQuery(self.session, query) responseDict = {'ids': list(results)} registry.checkResponse(responseType, responseDict, usage, request) body = payloads.buildPayload(responseType, responseDict) request.setHeader('Content-length', str(len(body))) request.setHeader('Content-type', responseType) request.setResponseCode(usage.successCode) defer.returnValue(body)
def _GET_HEAD_common(self, request, verb): """ The following code is reproduced almost verbatim in deferred_render_DELETE in about.py. So if you change this code, you'll likely need to change that, and vice versa. """ usage = registry.findUsage(httpObjectCategoryName, verb, TagInstanceResource) registry.checkRequest(usage, request) # This will raise TNoInstanceOnObject if there's no instance, # and that will return a 404 (see util.py). tvalue, tagValue = yield self.facadeClient.getTagInstance( self.session, self.path, self.objectId) value = guessValue(tvalue) accept = request.getHeader('accept') or '*/*' if tvalue.valueType == ThriftValueType.BINARY_TYPE: contentType = tvalue.binaryKeyMimeType if mimeparse.best_match([contentType], accept) == '': raise error.NotAcceptable() body = value # Mark this value as unwrappable for JSON request._fluiddb_jsonp_unwrappable = None else: contentType = mimeparse.best_match(contentTypesForPrimitiveValue, accept) if contentType == '': raise error.NotAcceptable() try: serializer = util.primitiveTypeSerializer[contentType] except KeyError: raise TInternalError('No serializer for %r.' % contentType) else: body = serializer(value) typeValue = self._getTypeHeader(tvalue.valueType) request.setHeader(util.buildHeader('Type'), typeValue) request.setHeader('Content-length', str(len(body))) request.setHeader('Content-type', contentType) # setting the Last-Modified header for fluiddb/id makes no sense if tagValue and tagValue.creationTime: request.setHeader( 'Last-modified', tagValue.creationTime.strftime('%a, %d %b %Y %H:%M:%S')) request.setResponseCode(usage.successCode) defer.returnValue(body)
def _GET_HEAD_common(self, request, verb): """ The following code is reproduced almost verbatim in deferred_render_DELETE in about.py. So if you change this code, you'll likely need to change that, and vice versa. """ usage = registry.findUsage(httpObjectCategoryName, verb, TagInstanceResource) registry.checkRequest(usage, request) # This will raise TNoInstanceOnObject if there's no instance, # and that will return a 404 (see util.py). tvalue, tagValue = yield self.facadeClient.getTagInstance( self.session, self.path, self.objectId) value = guessValue(tvalue) accept = request.getHeader('accept') or '*/*' if tvalue.valueType == ThriftValueType.BINARY_TYPE: contentType = tvalue.binaryKeyMimeType if mimeparse.best_match([contentType], accept) == '': raise error.NotAcceptable() body = value # Mark this value as unwrappable for JSON request._fluiddb_jsonp_unwrappable = None else: contentType = mimeparse.best_match( contentTypesForPrimitiveValue, accept) if contentType == '': raise error.NotAcceptable() try: serializer = util.primitiveTypeSerializer[contentType] except KeyError: raise TInternalError('No serializer for %r.' % contentType) else: body = serializer(value) typeValue = self._getTypeHeader(tvalue.valueType) request.setHeader(util.buildHeader('Type'), typeValue) request.setHeader('Content-length', str(len(body))) request.setHeader('Content-type', contentType) # setting the Last-Modified header for fluiddb/id makes no sense if tagValue and tagValue.creationTime: request.setHeader( 'Last-modified', tagValue.creationTime.strftime('%a, %d %b %Y %H:%M:%S')) request.setResponseCode(usage.successCode) defer.returnValue(body)
def deferred_render_POST(self, request): usage = registry.findUsage(httpObjectCategoryName, 'POST', ObjectsResource) dictionary = registry.checkRequest(usage, request) responseType = usage.getResponsePayloadTypeFromAcceptHeader(request) about = dictionary.get(aboutArg, '') objectId = yield self.facadeClient.createObject( session=self.session, about=about.encode('utf-8')) if request.isSecure(): proto = "https" else: proto = "http" hostname = request.getRequestHostname() # Return the location of the new object by its id. location = '%s://%s/%s/%s' % ( proto, hostname, httpObjectCategoryName, # This is probably overkill urllib.quote(objectId.encode('utf-8'))) responseDict = {'id': objectId, 'URI': location} registry.checkResponse(responseType, responseDict, usage, request) body = payloads.buildPayload(responseType, responseDict) request.setHeader('Content-length', str(len(body))) request.setHeader('Content-type', responseType) request.setHeader('Location', location) request.setResponseCode(usage.successCode) defer.returnValue(body)
def deferred_render_POST(self, request): usage = registry.findUsage(httpObjectCategoryName, 'POST', ObjectsResource) dictionary = registry.checkRequest(usage, request) responseType = usage.getResponsePayloadTypeFromAcceptHeader(request) about = dictionary.get(aboutArg, '') objectId = yield self.facadeClient.createObject( session=self.session, about=about.encode('utf-8')) if request.isSecure(): proto = "https" else: proto = "http" hostname = request.getRequestHostname() # Return the location of the new object by its id. location = '%s://%s/%s/%s' % ( proto, hostname, httpObjectCategoryName, # This is probably overkill urllib.quote(objectId.encode('utf-8'))) responseDict = {'id': objectId, 'URI': location} registry.checkResponse(responseType, responseDict, usage, request) body = payloads.buildPayload(responseType, responseDict) request.setHeader('Content-length', str(len(body))) request.setHeader('Content-type', responseType) request.setHeader('Location', location) request.setResponseCode(usage.successCode) defer.returnValue(body)
def run(): if not request.isSecure() and not getDevelopmentMode(): raise TBadRequest( '/users/<username>/verify requests must use HTTPS') dictionary = registry.checkRequest(usage, request) user = cachingGetUser(self.username.decode('utf-8')) if not user: raise TNoSuchUser(self.username) password = dictionary['password'] if checkPassword(password, user.passwordHash): # FIXME Hard-coding the 'anon' consumer here isn't great, # but for now it means we don't have to change the public # API. -jkakar api = OAuthConsumerAPI() consumer = cachingGetUser(u'anon') accessToken = api.getAccessToken(consumer, user) renewalToken = api.getRenewalToken(consumer, user) return {'accessToken': accessToken.encrypt(), 'fullname': user.fullname, 'renewalToken': renewalToken.encrypt(), 'role': str(user.role), 'valid': True} else: return {'valid': False}
def deferred_render_GET(self, request): # TODO: usages should be cached locally; lookup is expensive. usage = registry.findUsage(httpUserCategoryName, 'GET', ConcreteUserResource) registry.checkRequest(usage, request) responseType = usage.getResponsePayloadTypeFromAcceptHeader(request) tuser = yield self.facadeClient.getUser(self.session, self.username) responseDict = { 'name': tuser.name, 'role': tuser.role, 'id': tuser.objectId, } registry.checkResponse(responseType, responseDict, usage, request) body = payloads.buildPayload(responseType, responseDict) request.setHeader('Content-length', str(len(body))) request.setHeader('Content-type', responseType) request.setResponseCode(usage.successCode) defer.returnValue(body)
def deferred_render_PUT(self, request): usage = registry.findUsage(httpTagCategoryName, 'PUT', TagsResource) dictionary = registry.checkRequest(usage, request) description = dictionary.get('description') or '' yield self.facadeClient.updateTag(self.session, sep.join(request.postpath), description.encode('utf-8')) request.setResponseCode(usage.successCode)
def deferred_render_GET(self, request): # TODO: usages should be cached locally; lookup is expensive. usage = registry.findUsage(httpPermissionCategoryName, 'GET', self.__class__) registry.checkRequest(usage, request) responseType = usage.getResponsePayloadTypeFromAcceptHeader(request) action = request.args[actionArg][0].lower() result = yield self.facadeClient.getPermission( self.session, self.category, action, sep.join(request.postpath)) responseDict = { 'policy': result.policy, 'exceptions': list(result.exceptions), } registry.checkResponse(responseType, responseDict, usage, request) body = payloads.buildPayload(responseType, responseDict) request.setHeader('Content-length', str(len(body))) request.setHeader('Content-type', responseType) request.setResponseCode(usage.successCode) defer.returnValue(body)
def deferred_render_PUT(self, request): usage = registry.findUsage(httpTagCategoryName, 'PUT', TagsResource) dictionary = registry.checkRequest(usage, request) description = dictionary.get('description') or '' yield self.facadeClient.updateTag(self.session, sep.join(request.postpath), description.encode('utf-8')) request.setResponseCode(usage.successCode)
def deferred_render_GET(self, request): # TODO: usages should be cached locally; lookup is expensive. usage = registry.findUsage(httpPermissionCategoryName, 'GET', self.__class__) registry.checkRequest(usage, request) responseType = usage.getResponsePayloadTypeFromAcceptHeader(request) action = request.args[actionArg][0].lower() result = yield self.facadeClient.getPermission( self.session, self.category, action, sep.join(request.postpath)) responseDict = { 'policy': result.policy, 'exceptions': list(result.exceptions), } registry.checkResponse(responseType, responseDict, usage, request) body = payloads.buildPayload(responseType, responseDict) request.setHeader('Content-length', str(len(body))) request.setHeader('Content-type', responseType) request.setResponseCode(usage.successCode) defer.returnValue(body)
def deferred_render_GET(self, request): """Render a response to a C{GET} request to C{recent/objects} @param request: a C{twisted.web.server.Request} specifying meta-information about the request. @return: A C{deferred} which fires with a JSON payload with the information about recent activity for the given object. """ usage = registry.findUsage('recent', 'GET', RecentObjectActivityResource) registry.checkRequest(usage, request) recentActivity = yield self.facadeClient.getRecentObjectActivity( self.session, self.objectID) body = buildPayload('application/json', recentActivity) request.setHeader('Content-length', str(len(body))) request.setHeader('Content-type', 'application/json') request.setResponseCode(http.OK) returnValue(body)
def deferred_render_GET(self, request): """Render a response to a C{GET} request to C{recent/objects} @param request: a C{twisted.web.server.Request} specifying meta-information about the request. @return: A C{deferred} which fires with a JSON payload with the information about recent activity for the given object. """ usage = registry.findUsage('recent', 'GET', RecentObjectActivityResource) registry.checkRequest(usage, request) recentActivity = yield self.facadeClient.getRecentObjectActivity( self.session, self.objectID) body = buildPayload('application/json', recentActivity) request.setHeader('Content-length', str(len(body))) request.setHeader('Content-type', 'application/json') request.setResponseCode(http.OK) returnValue(body)
def deferred_render_DELETE(self, request): """ Handle a DELETE request for /values with a query and a list of wanted tags. @param request: The incoming C{twisted.web.server.Request} request. @return: A C{Deferred} which will fire when the request has completed. The deferred may errback for a variety of reasons, for example an invalid query, the mention of a non-existent tag or a tag that the caller does not have DELETE permission for. """ usage = registry.findUsage(httpValueCategoryName, 'DELETE', ValuesResource) registry.checkRequest(usage, request) query = request.args[queryArg][0] tags = request.args[tagArg] if tags == ['*']: tags = None yield self.facadeClient.deleteValuesForQuery(self.session, query, tags) request.setResponseCode(usage.successCode) defer.returnValue(None)
def deferred_render_DELETE(self, request): """ Handle a DELETE request for /values with a query and a list of wanted tags. @param request: The incoming C{twisted.web.server.Request} request. @return: A C{Deferred} which will fire when the request has completed. The deferred may errback for a variety of reasons, for example an invalid query, the mention of a non-existent tag or a tag that the caller does not have DELETE permission for. """ usage = registry.findUsage(httpValueCategoryName, 'DELETE', ValuesResource) registry.checkRequest(usage, request) query = request.args[queryArg][0] tags = request.args[tagArg] if tags == ['*']: tags = None yield self.facadeClient.deleteValuesForQuery(self.session, query, tags) request.setResponseCode(usage.successCode) defer.returnValue(None)
def deferred_render_POST(self, request): """ Create an object whose about value is the one given in the URI and return information about its object id and location. @param request: The HTTP request. @return: A C{Deferred} that fires with the body of the response. """ usage = registry.findUsage(httpAboutCategoryName, 'POST', AboutObjectResource) registry.checkRequest(usage, request) responseType = usage.getResponsePayloadTypeFromAcceptHeader(request) objectId = yield self.facadeClient.createObject( session=self.session, about=self.about) if request.isSecure(): proto = "https" else: proto = "http" hostname = request.getRequestHostname() # Return the location of the new object by its id. location = '%s://%s/%s/%s' % ( proto, hostname, httpObjectCategoryName, urllib.quote(objectId.encode('utf-8'))) responseDict = { 'id': objectId, 'URI': location, } registry.checkResponse(responseType, responseDict, usage, request) body = payloads.buildPayload(responseType, responseDict) request.setHeader('Content-length', str(len(body))) request.setHeader('Content-type', responseType) request.setHeader('Location', location) request.setResponseCode(usage.successCode) defer.returnValue(body)
def deferred_render_POST(self, request): """ Create an object whose about value is the one given in the URI and return information about its object id and location. @param request: The HTTP request. @return: A C{Deferred} that fires with the body of the response. """ usage = registry.findUsage(httpAboutCategoryName, 'POST', AboutObjectResource) registry.checkRequest(usage, request) responseType = usage.getResponsePayloadTypeFromAcceptHeader(request) objectId = yield self.facadeClient.createObject(session=self.session, about=self.about) if request.isSecure(): proto = "https" else: proto = "http" hostname = request.getRequestHostname() # Return the location of the new object by its id. location = '%s://%s/%s/%s' % (proto, hostname, httpObjectCategoryName, urllib.quote(objectId.encode('utf-8'))) responseDict = { 'id': objectId, 'URI': location, } registry.checkResponse(responseType, responseDict, usage, request) body = payloads.buildPayload(responseType, responseDict) request.setHeader('Content-length', str(len(body))) request.setHeader('Content-type', responseType) request.setHeader('Location', location) request.setResponseCode(usage.successCode) defer.returnValue(body)
def deferred_render_PUT(self, request): # TODO: usages should be cached locally; lookup is expensive. usage = registry.findUsage(httpPermissionCategoryName, 'PUT', self.__class__) dictionary = registry.checkRequest(usage, request) action = request.args[actionArg][0].lower() policyAndExceptions = TPolicyAndExceptions( policy=dictionary['policy'], exceptions=set(dictionary['exceptions'])) yield self.facadeClient.updatePermission( self.session, self.category, action, sep.join(request.postpath), policyAndExceptions) request.setResponseCode(usage.successCode)
def deferred_render_DELETE(self, request): """ Delete a tag from an object. Return a Deferred that fires with None once the facade has done the deletion. The following code, apart from the yield self._setObjectId(), is taken verbatim from deferred_render_DELETE 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, 'DELETE', AboutTagInstanceResource) registry.checkRequest(usage, request) yield self._setObjectId() yield self.facadeClient.deleteTagInstance(self.session, self.path, self.objectId) request.setResponseCode(usage.successCode) defer.returnValue(None)
def deferred_render_PUT(self, request): # TODO: usages should be cached locally; lookup is expensive. usage = registry.findUsage(httpPermissionCategoryName, 'PUT', self.__class__) dictionary = registry.checkRequest(usage, request) action = request.args[actionArg][0].lower() policyAndExceptions = TPolicyAndExceptions( policy=dictionary['policy'], exceptions=set(dictionary['exceptions'])) yield self.facadeClient.updatePermission(self.session, self.category, action, sep.join(request.postpath), policyAndExceptions) request.setResponseCode(usage.successCode)
def deferred_render_DELETE(self, request): """ Delete a tag from an object. Return a Deferred that fires with None once the facade has done the deletion. The following code, apart from the yield self._setObjectId(), is taken verbatim from deferred_render_DELETE 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, 'DELETE', AboutTagInstanceResource) registry.checkRequest(usage, request) yield self._setObjectId() yield self.facadeClient.deleteTagInstance( self.session, self.path, self.objectId) request.setResponseCode(usage.successCode) defer.returnValue(None)
def deferred_render_PUT(self, request): usage = registry.findUsage(httpUserCategoryName, 'PUT', ConcreteUserResource) dictionary = registry.checkRequest(usage, request) name = dictionary.get('name') email = dictionary.get('email') password = dictionary.get('password') role = dictionary.get('role') # All args are optional. Don't bother the facade if there's nothing # to do. if name or email or password or role: update = TUserUpdate(username=self.username, name=name, email=email, password=password, role=role) yield self.facadeClient.updateUser(self.session, update) request.setResponseCode(usage.successCode)
def deferred_render_POST(self, request): usage = registry.findUsage(httpTagCategoryName, 'POST', TagsResource) dictionary = registry.checkRequest(usage, request) responseType = usage.getResponsePayloadTypeFromAcceptHeader(request) parentNamespace = sep.join(request.postpath) name = dictionary['name'] description = dictionary['description'] or '' indexed = dictionary['indexed'] path = sep.join([parentNamespace, name.encode('utf-8')]) objectId = yield self.facadeClient.createTag( session=self.session, parentNamespace=parentNamespace, name=name.encode('utf-8'), description=description.encode('utf-8'), indexed=indexed, # Always request a normal range. We don't let apps do anything # else yet. rangeType=TagRangeType.NORMAL_TYPE) if request.isSecure(): proto = "https" else: proto = "http" hostname = request.getRequestHostname() location = '%s://%s/%s/%s' % ( proto, hostname, httpTagCategoryName, urllib.quote(path)) responseDict = { 'id': objectId, 'URI': location, } registry.checkResponse(responseType, responseDict, usage, request) body = payloads.buildPayload(responseType, responseDict) request.setHeader('Content-length', str(len(body))) request.setHeader('Content-type', responseType) request.setHeader('Location', location) request.setResponseCode(usage.successCode) defer.returnValue(body)
def deferred_render_POST(self, request): usage = registry.findUsage(httpTagCategoryName, 'POST', TagsResource) dictionary = registry.checkRequest(usage, request) responseType = usage.getResponsePayloadTypeFromAcceptHeader(request) parentNamespace = sep.join(request.postpath) name = dictionary['name'] description = dictionary['description'] or '' indexed = dictionary['indexed'] path = sep.join([parentNamespace, name.encode('utf-8')]) objectId = yield self.facadeClient.createTag( session=self.session, parentNamespace=parentNamespace, name=name.encode('utf-8'), description=description.encode('utf-8'), indexed=indexed, # Always request a normal range. We don't let apps do anything # else yet. rangeType=TagRangeType.NORMAL_TYPE) if request.isSecure(): proto = "https" else: proto = "http" hostname = request.getRequestHostname() location = '%s://%s/%s/%s' % (proto, hostname, httpTagCategoryName, urllib.quote(path)) responseDict = { 'id': objectId, 'URI': location, } registry.checkResponse(responseType, responseDict, usage, request) body = payloads.buildPayload(responseType, responseDict) request.setHeader('Content-length', str(len(body))) request.setHeader('Content-type', responseType) request.setHeader('Location', location) request.setResponseCode(usage.successCode) defer.returnValue(body)
def createFromRequest(cls, request, usage): """ Construct the objects from an HTTP request and a usage. @param request: The request object. @param usage: The L{Usage} object. @return: a L{ValuesQuerySchema} object for the given request. """ payload = registry.checkRequest(usage, request) contentType = request.getHeader('content-type') if contentType is None: raise error.NoContentTypeHeader() try: contentTypeParts = parse_mime_type(contentType) except ValueError: raise error.UnknownContentType() if contentTypeParts[:2] != ('application', 'json'): raise error.UnknownContentType() if queryArg in request.args: try: # Decode to unicode from the UTF-8 in the URI. query = request.args[queryArg][0].decode('utf-8') except UnicodeDecodeError: raise error.InvalidUTF8Argument(queryArg) else: query = None payloadDict = cls._getPayloadDict(payload) if query is None: queryItems = cls._parseNewPayloadDict(payloadDict) else: tagsAndValues = cls._parseOldPayloadDict(payloadDict) queryItems = [(query, tagsAndValues)] return ValuesQuerySchema(queryItems)
def createFromRequest(cls, request, usage): """ Construct the objects from an HTTP request and a usage. @param request: The request object. @param usage: The L{Usage} object. @return: a L{ValuesQuerySchema} object for the given request. """ payload = registry.checkRequest(usage, request) contentType = request.getHeader('content-type') if contentType is None: raise error.NoContentTypeHeader() try: contentTypeParts = parse_mime_type(contentType) except ValueError: raise error.UnknownContentType() if contentTypeParts[:2] != ('application', 'json'): raise error.UnknownContentType() if queryArg in request.args: try: # Decode to unicode from the UTF-8 in the URI. query = request.args[queryArg][0].decode('utf-8') except UnicodeDecodeError: raise error.InvalidUTF8Argument(queryArg) else: query = None payloadDict = cls._getPayloadDict(payload) if query is None: queryItems = cls._parseNewPayloadDict(payloadDict) else: tagsAndValues = cls._parseOldPayloadDict(payloadDict) queryItems = [(query, tagsAndValues)] return ValuesQuerySchema(queryItems)
def deferred_render_POST(self, request): usage = registry.findUsage(httpUserCategoryName, 'POST', UsersResource) dictionary = registry.checkRequest(usage, request) responseType = usage.getResponsePayloadTypeFromAcceptHeader(request) username = dictionary['username'] name = dictionary.get('name', username) password = dictionary['password'] email = dictionary['email'] objectId = yield self.facadeClient.createUserWithPassword( session=self.session, username=username.encode('utf-8'), password=password.encode('utf-8'), name=name.encode('utf-8'), email=email.encode('utf-8')) if request.isSecure(): proto = "https" else: proto = "http" hostname = request.getRequestHostname() location = '%s://%s/%s/%s' % ( proto, hostname, httpUserCategoryName, urllib.quote(username.encode('utf-8'))) responseDict = { 'id': objectId, 'URI': location, } registry.checkResponse(responseType, responseDict, usage, request) body = payloads.buildPayload(responseType, responseDict) request.setHeader('Content-length', str(len(body))) request.setHeader('Content-type', responseType) request.setHeader('Location', location) request.setResponseCode(usage.successCode) defer.returnValue(body)
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)
def deferred_render_DELETE(self, request): usage = registry.findUsage(httpUserCategoryName, 'DELETE', ConcreteUserResource) registry.checkRequest(usage, request) yield self.facadeClient.deleteUser(self.session, self.username) request.setResponseCode(usage.successCode)
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)
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)
def _GET_HEAD_common(self, request, verb): """ I handle the common actions taken by GET and HEAD requests, which are virtually identical, except HEAD drops the body. This code, apart from the yield self._setObjectId(), is taken verbatim from _GET_HEAD_common in objects.py. So if you change this code, you'll likely need to change that, and vice versa. @param request: The HTTP request. @param verb: A C{str}, either 'GET' or 'HEAD'. @return: A C{Deferred} which fires with the body of a GET request, having set all the response headers that are common to GET and HEAD. (The body will be dropped (below) for HEAD requests.) """ usage = registry.findUsage(httpAboutCategoryName, verb, AboutTagInstanceResource) registry.checkRequest(usage, request) yield self._setObjectId() # This will raise TNoInstanceOnObject if there's no instance, # and that will return a 404 (see util.py). tvalue, tagValue = yield self.facadeClient.getTagInstance( self.session, self.path, self.objectId) value = guessValue(tvalue) accept = request.getHeader('accept') or '*/*' if tvalue.valueType == ThriftValueType.BINARY_TYPE: contentType = tvalue.binaryKeyMimeType if mimeparse.best_match([contentType], accept) == '': raise error.NotAcceptable() body = value # Mark this value as unwrappable for JSON request._fluiddb_jsonp_unwrappable = None else: contentType = mimeparse.best_match( contentTypesForPrimitiveValue, accept) if contentType == '': raise error.NotAcceptable() try: serializer = util.primitiveTypeSerializer[contentType] except KeyError: raise TInternalError('No serializer for %r.' % contentType) else: body = serializer(value) typeValue = self._getTypeHeader(tvalue.valueType) request.setHeader(util.buildHeader('Type'), typeValue) request.setHeader('Content-length', str(len(body))) request.setHeader('Content-type', contentType) # setting the Last-Modified header for fluiddb/id makes no sense if tagValue and tagValue.creationTime: request.setHeader( 'Last-modified', tagValue.creationTime.strftime('%a, %d %b %Y %H:%M:%S')) request.setResponseCode(usage.successCode) defer.returnValue(body)
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)
def _GET_HEAD_common(self, request, verb): """ I handle the common actions taken by GET and HEAD requests, which are virtually identical, except HEAD drops the body. This code, apart from the yield self._setObjectId(), is taken verbatim from _GET_HEAD_common in objects.py. So if you change this code, you'll likely need to change that, and vice versa. @param request: The HTTP request. @param verb: A C{str}, either 'GET' or 'HEAD'. @return: A C{Deferred} which fires with the body of a GET request, having set all the response headers that are common to GET and HEAD. (The body will be dropped (below) for HEAD requests.) """ usage = registry.findUsage(httpAboutCategoryName, verb, AboutTagInstanceResource) registry.checkRequest(usage, request) yield self._setObjectId() # This will raise TNoInstanceOnObject if there's no instance, # and that will return a 404 (see util.py). tvalue, tagValue = yield self.facadeClient.getTagInstance( self.session, self.path, self.objectId) value = guessValue(tvalue) accept = request.getHeader('accept') or '*/*' if tvalue.valueType == ThriftValueType.BINARY_TYPE: contentType = tvalue.binaryKeyMimeType if mimeparse.best_match([contentType], accept) == '': raise error.NotAcceptable() body = value # Mark this value as unwrappable for JSON request._fluiddb_jsonp_unwrappable = None else: contentType = mimeparse.best_match(contentTypesForPrimitiveValue, accept) if contentType == '': raise error.NotAcceptable() try: serializer = util.primitiveTypeSerializer[contentType] except KeyError: raise TInternalError('No serializer for %r.' % contentType) else: body = serializer(value) typeValue = self._getTypeHeader(tvalue.valueType) request.setHeader(util.buildHeader('Type'), typeValue) request.setHeader('Content-length', str(len(body))) request.setHeader('Content-type', contentType) # setting the Last-Modified header for fluiddb/id makes no sense if tagValue and tagValue.creationTime: request.setHeader( 'Last-modified', tagValue.creationTime.strftime('%a, %d %b %Y %H:%M:%S')) request.setResponseCode(usage.successCode) defer.returnValue(body)