def testNotes(self): f = HTTPTopLevel('users', 'PUT') usage = HTTPUsage('/dummy', 'an example of great profundity') f.addUsage(usage) note = Note('hey') usage.addNote(note) note = Note('hey') usage.addNote(note) self.assertEqual(len(usage.notes), 2) self.reg.register(f) apis = self.reg.get('users', 'PUT') self.assertEqual(apis, [['users', [('PUT', f)]]]) f = apis[0][1][0][1] self.assertEqual(len(f.usages), 1) self.assertEqual(len(f.usages[0].notes), 2)
def testFindUsage(self): class Dummy1(object): pass class Dummy2(object): pass class Dummy3(object): pass f = HTTPTopLevel('users', 'PUT') self.reg.register(f) usage1 = HTTPUsage('', "Return a list of all users.") usage1.resourceClass = Dummy1 f.addUsage(usage1) f = HTTPTopLevel('dummy', 'GET') self.reg.register(f) usage2 = HTTPUsage('', "Return a list of all dummies.") usage2.resourceClass = Dummy2 f.addUsage(usage2) # Find the usage with class Dummy1. u = self.reg.findUsage('users', 'PUT', usageResourceClass=Dummy1) self.assertTrue(u.resourceClass is usage1.resourceClass) # Find the usage with class Dummy2. u = self.reg.findUsage('dummy', 'GET', usageResourceClass=Dummy2) self.assertTrue(u.resourceClass is usage2.resourceClass) # Ask for a non-existent usage class. self.assertRaises(error.NoSuchUsage, self.reg.findUsage, 'dummy', 'GET', usageResourceClass=Dummy3) # Ask for a non-existent toplevel. self.assertRaises(error.NoSuchToplevel, self.reg.findUsage, 'sunny', 'PUT', usageResourceClass=Dummy2) # Ask for a non-existent verb. self.assertRaises(error.NoSuchVerb, self.reg.findUsage, 'dummy', 'PUT', usageResourceClass=Dummy2)
def testGetWildcards(self): f1 = HTTPTopLevel('objects', 'GET') self.reg.register(f1) f2 = HTTPTopLevel('objects', 'PUT') self.reg.register(f2) f3 = HTTPTopLevel('users', 'GET') self.reg.register(f3) apis = self.reg.get('objects', 'GET') self.assertEqual(apis, [['objects', [('GET', f1)]]]) apis = self.reg.get('objects', '*') self.assertEqual(apis, [['objects', [('GET', f1), ('PUT', f2)]]]) apis = self.reg.get('*', 'GET') self.assertEqual(apis, [['objects', [('GET', f1)]], ['users', [('GET', f3)]]]) apis = self.reg.get('*', 'PUT') self.assertEqual(apis, [['objects', [('PUT', f2)]]]) apis = self.reg.get('*', '*') self.assertEqual(apis, [['objects', [('GET', f1), ('PUT', f2)]], ['users', [('GET', f3)]]])
description.encode('utf-8')) request.setResponseCode(usage.successCode) @defer.inlineCallbacks 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) # ------------------------------ Namespaces POST -------------------------- topLevel = HTTPTopLevel(httpNamespaceCategoryName, 'POST') registry.register(topLevel) # --- POST /namespaces/NAMESPACE1/NAMESPACE2 ------------------------------ usage = HTTPUsage( apiDoc.NS_NS, 'Create a new namespace. Intermediate ' "namespaces are created automatically if they don't already " 'exist.') topLevel.addUsage(usage) usage.resourceClass = NamespacesResource usage.successCode = http.CREATED usage.addNote( Note("""The new namespace will have permissions set according to the user's defaults. There is no permission inheritance
def testRegisterAndGetNonExistentVerb(self): f = HTTPTopLevel('users', 'PUT') self.reg.register(f) self.assertRaises(error.NoSuchVerb, self.reg.get, 'users', '')
def testRegisterAndGetNonExistentToplevel(self): f = HTTPTopLevel('users', 'PUT') self.reg.register(f) self.assertRaises(error.NoSuchToplevel, self.reg.get, 'fred', '')
def testRegisterAndGet(self): f = HTTPTopLevel('users', 'PUT') self.reg.register(f) apis = self.reg.get('users', 'PUT') self.assertEqual(apis, [['users', [('PUT', f)]]])
@return: A C{deferred} which fires with a JSON payload with the information about recent activity for the given user. """ recentActivity = yield self.facadeClient.getRecentUserActivity( self.session, self.username) body = buildPayload('application/json', recentActivity) request.setHeader('Content-length', str(len(body))) request.setHeader('Content-type', 'application/json') request.setResponseCode(http.OK) returnValue(body) # API DOCUMENTATION # GET on /recent topLevel = HTTPTopLevel('recent', 'GET') topLevel.description = dedent(""" The GET method on recent is used to retrieve information about the latest updated tag values on a given object or user.""") registry.register(topLevel) # GET on /recent/objects usage = HTTPUsage('/objects', dedent(""" To request information on the latest tag values on the objects returned by a given query""")) usage.resourceClass = RecentObjectsActivityResource usage.addArgument(Argument( 'query', dedent(""" A query string specifying what sorts of objects to get recent activity for. The query language is described <a
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) # ------------------------------ Objects POST ----------------------------- topLevel = HTTPTopLevel(httpObjectCategoryName, 'POST') topLevel.description = "Create a new Fluidinfo object." registry.register(topLevel) # --- POST /objects ------------------------------------------------------- usage = HTTPUsage('', 'Create a new object. You must provide credentials for ' 'this call to succeed.') topLevel.addUsage(usage) usage.resourceClass = ObjectsResource usage.successCode = http.CREATED apiDoc.addBadRequestPayload(usage) apiDoc.addCannotRespondWithPayload(usage)
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) # ------------------------------ Values GET ----------------------------- topLevel = HTTPTopLevel(httpValueCategoryName, 'GET') topLevel.description = """The GET method on values is used to retrieve tag values from objects matching a query.""" # We could here mention # href="http://doc.fluidinfo.com/fluidDB/api/draft-values-spec.html"> # /values draft spec</a>. registry.register(topLevel) # --- GET /values -------------------------------------------------------- usage = HTTPUsage( '', """Search for objects matching a Fluidinfo query, and return the value of the requested tags on the matching objects.""")
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) # ------------------------------ Objects POST ----------------------------- topLevel = HTTPTopLevel(httpObjectCategoryName, 'POST') topLevel.description = "Create a new Fluidinfo object." registry.register(topLevel) # --- POST /objects ------------------------------------------------------- usage = HTTPUsage( '', 'Create a new object. You must provide credentials for ' 'this call to succeed.') topLevel.addUsage(usage) usage.resourceClass = ObjectsResource usage.successCode = http.CREATED apiDoc.addBadRequestPayload(usage) apiDoc.addCannotRespondWithPayload(usage)
return self else: try: # Make sure we have valid UTF-8 in the about value. about.decode('utf-8') except UnicodeDecodeError: return ErrorResource( http.BAD_REQUEST, error.BadArgument, {'Error-Message': 'About value in URI was not UTF-8'}) else: return AboutObjectResource(self.facadeClient, self.session, about) # ------------------------------ About POST ----------------------------- topLevel = HTTPTopLevel(httpAboutCategoryName, 'POST') topLevel.description = "Create a new object." registry.register(topLevel) # --- POST /about ------------------------------------------------------- usage = HTTPUsage('/' + apiDoc.ABOUTSTR, ('''Create a new object with the given about value. If there is already a Fluidinfo object whose ''' + apiDoc.ABOUT_TAG + ''' tag has the given value, the returned object id will be that of the pre-existing object. In this call, and all others with an about value in the URI, you must convert your about value to UTF-8 and then <a href="http://en.wikipedia.org/wiki/Percent-encoding"> percent-encode</a> it before adding it to the request URI. You must provide valid credentials for this call to succeed. For an example see the PUT request, below.'''))
return self else: try: # Make sure we have valid UTF-8 in the about value. about.decode('utf-8') except UnicodeDecodeError: return ErrorResource( http.BAD_REQUEST, error.BadArgument, {'Error-Message': 'About value in URI was not UTF-8'}) else: return AboutObjectResource( self.facadeClient, self.session, about) # ------------------------------ About POST ----------------------------- topLevel = HTTPTopLevel(httpAboutCategoryName, 'POST') topLevel.description = "Create a new object." registry.register(topLevel) # --- POST /about ------------------------------------------------------- usage = HTTPUsage('/' + apiDoc.ABOUTSTR, ('''Create a new object with the given about value. If there is already a Fluidinfo object whose ''' + apiDoc.ABOUT_TAG + ''' tag has the given value, the returned object id will be that of the pre-existing object. In this call, and all others with an about value in the URI, you must convert your about value to UTF-8 and then <a href="http://en.wikipedia.org/wiki/Percent-encoding"> percent-encode</a> it before adding it to the request URI. You must provide valid credentials for this call to succeed. For an example see the PUT request, below.'''))
information about recent activity for the given user. """ recentActivity = yield self.facadeClient.getRecentUserActivity( self.session, self.username) body = buildPayload('application/json', recentActivity) request.setHeader('Content-length', str(len(body))) request.setHeader('Content-type', 'application/json') request.setResponseCode(http.OK) returnValue(body) # API DOCUMENTATION # GET on /recent topLevel = HTTPTopLevel('recent', 'GET') topLevel.description = dedent(""" The GET method on recent is used to retrieve information about the latest updated tag values on a given object or user.""") registry.register(topLevel) # GET on /recent/objects usage = HTTPUsage( '/objects', dedent(""" To request information on the latest tag values on the objects returned by a given query""")) usage.resourceClass = RecentObjectsActivityResource usage.addArgument( Argument('query', dedent("""
} class PermissionsResource(WSFEResource): def getChild(self, name, request): try: klass = _classForCategory[name] except KeyError: return NoResource() else: return klass(self.facadeClient, self.session) # ------------------------------ Permissions POST ------------------------- topLevel = HTTPTopLevel(httpPermissionCategoryName, 'POST') topLevel.description = """ POST is not supported on permissions, because permissions are automatically set from a user's default permissions when a namespace or tag is first created. Use PUT to adjust the permissions on a given namespace or tag. """ # TODO: Finish this sentence and add it to the description: # To change a user's defaults, do a PUT on.... what exactly? registry.register(topLevel) # ------------------------------ Permissions GET -------------------------- topLevel = HTTPTopLevel('permissions', 'GET') registry.register(topLevel)
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) # ------------------------------ Values GET ----------------------------- topLevel = HTTPTopLevel(httpValueCategoryName, 'GET') topLevel.description = """The GET method on values is used to retrieve tag values from objects matching a query.""" # We could here mention # href="http://doc.fluidinfo.com/fluidDB/api/draft-values-spec.html"> # /values draft spec</a>. registry.register(topLevel) # --- GET /values -------------------------------------------------------- usage = HTTPUsage( '', """Search for objects matching a Fluidinfo query, and return the
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) # ------------------------------ Users POST ------------------------------- topLevel = HTTPTopLevel(httpUserCategoryName, 'POST') topLevel.adminOnly = True registry.register(topLevel) # --- POST /users --------------------------------------------------------- usage = HTTPUsage('', 'Create a new user.') usage.adminOnly = True usage.resourceClass = UsersResource usage.successCode = http.CREATED topLevel.addUsage(usage) apiDoc.addNeedAdmin(usage, apiDoc.CREATE) usage.addReturn(Return( apiDoc.PRECONDITION_FAILED,
description.encode('utf-8')) request.setResponseCode(usage.successCode) @defer.inlineCallbacks 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) # ------------------------------ Namespaces POST -------------------------- topLevel = HTTPTopLevel(httpNamespaceCategoryName, 'POST') registry.register(topLevel) # --- POST /namespaces/NAMESPACE1/NAMESPACE2 ------------------------------ usage = HTTPUsage(apiDoc.NS_NS, 'Create a new namespace. Intermediate ' "namespaces are created automatically if they don't already " 'exist.') topLevel.addUsage(usage) usage.resourceClass = NamespacesResource usage.successCode = http.CREATED usage.addNote(Note("""The new namespace will have permissions set according to the user's defaults. There is no permission inheritance in Fluidinfo."""))
tagInstanceSetCategoryName: ConcreteTagInstancesPermissionResource, } class PermissionsResource(WSFEResource): def getChild(self, name, request): try: klass = _classForCategory[name] except KeyError: return NoResource() else: return klass(self.facadeClient, self.session) # ------------------------------ Permissions POST ------------------------- topLevel = HTTPTopLevel(httpPermissionCategoryName, 'POST') topLevel.description = """ POST is not supported on permissions, because permissions are automatically set from a user's default permissions when a namespace or tag is first created. Use PUT to adjust the permissions on a given namespace or tag. """ # TODO: Finish this sentence and add it to the description: # To change a user's defaults, do a PUT on.... what exactly? registry.register(topLevel) # ------------------------------ Permissions GET -------------------------- topLevel = HTTPTopLevel('permissions', 'GET') registry.register(topLevel) # --- GET /permissions/namespaces/NAMESPACE1/NAMESPACE2 ------------