def runTest(self): rapidrecdb.add_site(self.sitename) rrs = RapidRecSite(self.sitename) #rrs.set_field_analyzer('nonexistentfield', 4) # test inserting a duplicate record - this should be permitted rrs.insert_relation(src_group='user', src_name='5', tgt_group='item', tgt_name='10', field='rating') rrs.insert_relation(src_group='user', src_name='5', tgt_group='item', tgt_name='10', field='rating') #self.assertEqual(rrs.get_field_id('rating'), 2, # "Field id for rating should have been created when the first " + # "rating record was inserted into raw.") #rrs.set_field_analyzer('rating', 1) #self.assertEqual(rrs.get_field_id('rating'), 2, # "rating was created second; it should have rating = 2, even " + # "though it has been updated since creation.") #self.assertEqual(rrs.get_field_id('newfield'), -1, # "newfield does not exist and thus should have an invalid field_id") #self.assertEqual(rrs.get_field_id('nonexistentfield'), 1, # "nonexistentfield should have been created first and thus have id=1") rrs.insert_meta('user', 3, 'name', 'Bob')
def runTest(self): rapidrecdb.add_site(self.sitename) # test for good site names # whitespace before & after is okay (it is stripped during filtering) rrs = RapidRecSite(' ' + self.sitename) rrs = RapidRecSite(self.sitename + ' ') rrs = RapidRecSite(' \n ' + self.sitename + ' \t \n') # this name is fine, but the database shouldn't exist self.assertRaises(dbAccess.ConnectionError, RapidRecSite, 'this1sitedoesntexist') # test for bad site names self.assertRaises(filters.RangeError, RapidRecSite, '1openingdigit') self.assertRaises(filters.RangeError, RapidRecSite, 'thisnameisjusttoolongtouseforasitename') self.assertRaises(filters.RangeError, RapidRecSite, 'test`;SELECT * FROM `raw`;') self.assertRaises(filters.RangeError, RapidRecSite, 'no spaces allowed') self.assertRaises(filters.RangeError, RapidRecSite, 'nopunctuation!') rrs = RapidRecSite(self.sitename) # test for good field names rrs.set_field_analyzer('item', 'goodname', 'filter2') rrs.set_field_analyzer('item', 'MixEdCaSEgeTsStRIpPed', 'filter2') rrs.set_field_analyzer('item', 'numbersarefine2', 'filter2') rrs.set_field_analyzer('item', 'm9857032985794fgf', 'filter2') rrs.set_field_analyzer('item', ' \tleadingandtrailingwhitespacesareokay \n ', 'filter2') self.assertRaises(filters.RangeError, rrs.set_field_analyzer, 'item', 'no whitespace inside', 'filter2') self.assertRaises(filters.RangeError, rrs.set_field_analyzer, 'item', '`; select no sql hacking either;', 'filter2') self.assertRaises(filters.RangeError, rrs.set_field_analyzer, 'item', '1cannotstartwithanumber', 'filter2')
def run(self): processing_start_time = time.time() self.root = "response" self.response = {} if not self.headers: return self.failure("Header 'host' required for all requests.") hostname = self.headers["host"].partition(":")[0] hostname_matches = re.findall("(\w+).(rapidrec.com|localhost)", hostname) if not hostname_matches: return self.failure( "Could not determine sitename. Please use " + "[sitename].rapidrec.com for all requests." ) else: self.sitename = hostname_matches[0][0] # Check the validity of the sitename try: self.sitename = filters.check_name(self.sitename, 32) except (filters.TypeError, filters.RangeError): return self.failure("Invalid site: %s" % self.sitename) # Check that the site exists by instantiating RapidRecSite try: rrsite = RapidRecSite(self.sitename) except RapidRecSite.ConnectionError: return self.failure("Unknown site: %s" % self.sitename) # Check the remote IP against the list of allowed IPs remoteip = self.request.getClientIP() # Break a comma-separated string into a list, with one tuple per IP ('IP', unused, 'cidr') try: iplist = str(rrsite.get_config_field("ip_allow")).split(",") except RapidRecSite.ConfigFieldNotFound: iplist = ["0.0.0.0/0"] while "" in iplist: iplist.remove("") iplist.append("127.0.0.1") if self.sitename.startswith("test"): iplist.append("68.9.232.69") # for development only if not ipfilter.is_ip_in_list(remoteip, iplist): return self.failure("Access forbidden from your IP: %s is not in { %s }" % (remoteip, ", ".join(iplist))) # At this point, the request is considered authentic. # We now proceed to process the request. # Find the path list and query (if any) by breaking up the QUERY_STRING # (fullpath, unused, query) = self.path.partition('?') fullpath = self.path path = fullpath.split("/") # Remove empty strings from the path list caused # by duplicate and unnecessary slashes in the path while "" in path: path.remove("") depth = 0 args = {} if self.method == "post": if "content-length" not in self.headers: return self.failure("content-length required when POSTing") self.contentLength = int(self.headers["content-length"]) self.request.content.seek(0, 0) args["postdata"] = self.request.content.read(self.contentLength) elif self.method != "get": return self.failure("Method not supported. Only GET and POST operations are allowed.") objtypes = ["users", "items", "movies"] try: if len(path) <= depth: raise (res.errors.UnimplementedError) elif path[depth] == "config": # /config... depth += 1 raise (res.errors.UnimplementedError) elif path[depth] in objtypes: # /objs... args["type"] = "user" if path[depth] == "users" else "item" depth += 1 if len(path) <= depth: # /objs Handler = res.objs.Handler else: # /objs/{obj}... args["name"] = path[depth] depth += 1 if len(path) <= depth: # /objs/{obj} Handler = res.obj.Handler elif path[depth] in objtypes: # /objs/{obj}/objs... args["tgt_type"] = "user" if path[depth] == "users" else "item" depth += 1 if len(path) <= depth: # /objs/{obj}/objs raise (res.errors.UnimplementedError) else: # /objs/{obj}/objs/{obj}... args["tgt_name"] = path[depth] depth += 1 if len(path) <= depth: # /objs/{obj}/objs/{obj} Handler = res.objobj.Handler else: # /objs/{obj}/objs/{obj}/{resource}... args["resource"] = path[depth] depth += 1 if len(path) <= depth: # /objs/{obj}/objs/{obj}/{resource} Handler = res.objobjres.Handler else: # /objs/{obj}/objs/{obj}/{resource}/... raise (res.errors.UnsupportedError) else: # /objs/{obj}/resource args["resource"] = path[depth] depth += 1 if len(path) <= depth: # /objs/{obj}/{resource} Handler = res.objres.Handler else: # /objs/{obj}/{resource}/... raise (res.errors.UnsupportedError) else: # /{not-supported}... raise (res.errors.UnsupportedError) # Here is where we actually service queries that look valid so far handler = Handler(rrsite, self.response, self.method, self.request.args, args) handler.run() xmlext.set_status(self.response, "OKAY", "Query completed successfully.") except res.errors.ContentLengthMissingError: xmlext.set_status(self.response, "ERROR", "Content-length missing.") except res.errors.MethodError: xmlext.set_status(self.response, "ERROR", "Method not supported.") except res.errors.QueryError: xmlext.set_status(self.response, "ERROR", "Invalid query.") except res.errors.UnsupportedError: xmlext.set_status(self.response, "ERROR", "Resource not supported.") except res.errors.UnimplementedError: xmlext.set_status(self.response, "ERROR", "Resource not implemented.") except res.errors.PostError: xmlext.set_status(self.response, "ERROR", "Could not understand request body.") except res.errors.IdError: xmlext.set_status(self.response, "ERROR", "Invalid user or item identifier.") except res.errors.UnknownError: xmlext.set_status(self.response, "ERROR", "Unknown Error.") processing_finish_time = time.time() processing_time_elapsed = processing_finish_time - processing_start_time treexml.insert_node(self.response, "system_usage", "%f" % processing_time_elapsed) # print response self.respXML() self.send(treexml.encode(self.root, self.response)) return self.finishreq()