def ingest_location_update(r): content = request.get_json() necessary_values = ['new_place_id', 'old_place_id', 'identifier'] isGoodRequest = check_for_values_in_request(necessary_values, content) if (isGoodRequest[0] == False): return make_response( { 'response': 'bad request, please try again and specify the ' + str(isGoodRequest[1]) + ' parameter(s) in the JSON request body. Note if there is no old_place_id, send "None" as the value' }, status.HTTP_400_BAD_REQUEST) new_place_id = content['new_place_id'] old_place_id = content['old_place_id'] user_identifier = content['identifier'] #remove from old bucket if there is one if (old_place_id != "None"): r.srem(old_place_id, user_identifier) #add to new bucket r.sadd(new_place_id, user_identifier) return make_response( { 'response': "Successfully added " + user_identifier + " to space " + new_place_id }, status.HTTP_200_OK)
def invite_new_user(r): content = request.get_json() necessary_values = ['phone', 'contacted', 'inviter_identifier'] isGoodRequest = check_for_values_in_request(necessary_values, content) if (isGoodRequest[0] == False): return make_response( { 'response': 'bad request, please try again and specify the ' + str(isGoodRequest[1]) + ' parameter(s) in the JSON request body.' }, status.HTTP_400_BAD_REQUEST) phone = content['phone'] contacted = content['contacted'] inviter_identifier = content['inviter_identifier'] invite_message = "You've been invited to download Exposeure, an app that helps you track your exposure to COVID-19! Find out more at getmyexposure.com" if (contacted == "False"): didSend = send_message(invite_message, phone) if didSend: return make_response( { 'response': 'sent messsage to' + str(phone) + 'successfully!' }, status.HTTP_200_OK) else: return make_response( { 'response': 'did not send messsage to' + str(phone) + 'successfully.' }, status.HTTP_200_OK) else: proto_user = retrieve_or_create_protouser_from_number(phone) current_proto_user_contacts = proto_user.contactedIds current_proto_user_contacts.append(inviter_identifier) proto_user.contactedIds = current_proto_user_contacts proto_user.save() proto_user_id = proto_user.identifier #link this identifier in redis to the push notification feature. r.set(str(proto_user_id), phone) didSend = send_message(invite_message, phone) if didSend: return make_response( { 'response': 'sent messsage to' + str(phone) + 'successfully!', 'new_identifier': proto_user_id }, status.HTTP_200_OK) else: return make_response( { 'response': 'did not send messsage to' + str(phone) + 'successfully.', 'new_identifier': proto_user_id }, status.HTTP_200_OK)
def get_images(): """Computes the response of the '/cluster/resources/images' endpoint. Returns: The images of the context graph. """ gs = app.context_graph_global_state # A dictionary from Image ID to wrapped image objects. # If an image appears more than once, keep only its latest value. images_dict = {} try: for node in kubernetes.get_nodes(gs): for image in docker.get_images(gs, node['id']): images_dict[image['id']] = image except collector_error.CollectorError as e: return flask.jsonify(utilities.make_error(str(e))) except: msg = 'kubernetes.get_images() failed with exception %s' % sys.exc_info( )[0] app.logger.exception(msg) return flask.jsonify(utilities.make_error(msg)) # The images list is sorted by increasing identifiers. images_list = [images_dict[key] for key in sorted(images_dict.keys())] return flask.jsonify(utilities.make_response(images_list, 'resources'))
def get_health(): """Computes the response of the '/healthz' endpoint. Returns: A successful response containing the attribute 'health' and the value 'OK'. """ return flask.jsonify(utilities.make_response('OK', 'health'))
def get_processes(): """Computes the response of the '/cluster/resources/processes' endpoint. Returns: The processes of the context graph. """ processes = [] gs = app.context_graph_global_state try: for node in kubernetes.get_nodes(gs): node_id = node['id'] docker_host = node_id for container in docker.get_containers(gs, docker_host): container_id = container['id'] processes.extend(docker.get_processes(gs, docker_host, container_id)) except collector_error.CollectorError as e: return flask.jsonify(utilities.make_error(str(e))) except: msg = 'get_processes() failed with exception %s' % sys.exc_info()[0] app.logger.exception(msg) return flask.jsonify(utilities.make_error(msg)) return flask.jsonify(utilities.make_response(processes, 'resources'))
def get_images(): """Computes the response of the '/cluster/resources/images' endpoint. Returns: The images of the context graph. """ gs = app.context_graph_global_state # A dictionary from Image ID to wrapped image objects. # If an image appears more than once, keep only its latest value. images_dict = {} try: for node in kubernetes.get_nodes(gs): for image in docker.get_images(gs, node['id']): images_dict[image['id']] = image except collector_error.CollectorError as e: return flask.jsonify(utilities.make_error(str(e))) except: msg = 'kubernetes.get_images() failed with exception %s' % sys.exc_info()[0] app.logger.exception(msg) return flask.jsonify(utilities.make_error(msg)) # The images list is sorted by increasing identifiers. images_list = [images_dict[key] for key in sorted(images_dict.keys())] return flask.jsonify(utilities.make_response(images_list, 'resources'))
def get_processes(): """Computes the response of the '/cluster/resources/processes' endpoint. Returns: The processes of the context graph. """ processes = [] gs = app.context_graph_global_state try: for node in kubernetes.get_nodes(gs): node_id = node['id'] docker_host = node_id for container in docker.get_containers(gs, docker_host): container_id = container['id'] processes.extend( docker.get_processes(gs, docker_host, container_id)) except collector_error.CollectorError as e: return flask.jsonify(utilities.make_error(str(e))) except: msg = 'get_processes() failed with exception %s' % sys.exc_info()[0] app.logger.exception(msg) return flask.jsonify(utilities.make_error(msg)) return flask.jsonify(utilities.make_response(processes, 'resources'))
def purge_all(r, content): lister = r.scan_iter() for place_id in lister: if (r.type(place_id) == b'set'): r.delete(place_id) return make_response({"Response": "Places Have Been Purged"}, status.HTTP_200_OK)
def get_infected_locations(): locationsList = Place.nodes.all() json_list = [] for node in locationsList: location = { "latitude": node.gpsLAT, "longitude":node.gpsLONG, } json_list.append(location) return make_response({'locations':json_list}, status.HTTP_200_OK)
def ingestPushNotificationAndCreateID(r): content = request.get_json() #Step 1, check to ensure that push_token field is present try: push_token = content['push_token'] except: push_token = None if (push_token == None): return make_response( { 'response': 'bad request, there was no \'push_token\' property in the request body' }, status.HTTP_400_BAD_REQUEST) else: #Step 2, generate a custom ID custom_ID = generateID() #Step 3, store ID in our redis cluster r.set(str(custom_ID), push_token) return make_response({"identifier": custom_ID}, status.HTTP_200_OK)
def sign_up(r): content = request.get_json() necessary_values = ['phone', 'push_token'] isGoodRequest = check_for_values_in_request(necessary_values, content) if (isGoodRequest[0] == False): return make_response( { 'response': 'bad request, please try again and specify the ' + str(isGoodRequest[1]) + ' parameter(s) in the JSON request body.' }, status.HTTP_400_BAD_REQUEST) phone = content['phone'] push_token = content['push_token'] #Check if user exists doesHaveProto = does_proto_user_exist(phone) #if it does, get data from user contacted_individuals = [] if doesHaveProto: proto_user = retrieve_or_create_protouser_from_number(phone) identifier = proto_user.identifier contactedIds = proto_user.contactedIds for contacted in contactedIds: contactedJSON = { "identifier": contacted, "contact_time": datetime.datetime.now() } contacted_individuals.append(contactedJSON) proto_user.delete() else: identifier = uuid.uuid1() #Step 3, store ID in our redis cluster r.set(str(identifier), push_token) return make_response( { "identifier": identifier, "contacted_individuals": contacted_individuals }, status.HTTP_200_OK)
def get_elapsed(): """Computes the response of the '/elapsed' endpoint. Returns: A successful response containing the list of elapsed time records of the most recent Kubernetes API invocations since the previous call to the '/elapsed' endpoint. Never returns more than constants.MAX_ELAPSED_QUEUE_SIZE elapsed time records. """ gs = app.context_graph_global_state result = return_elapsed(gs) return flask.jsonify(utilities.make_response(result, 'elapsed'))
def test_make_response(self): """Tests make_response().""" # The timestamp of the first response is the current time. start_time = utilities.now() resp = utilities.make_response([], 'resources') end_time = utilities.now() # Note that timless_json_hash() ignores the value of the timestamp. self.assertEqual( utilities.timeless_json_hash( {'success': True, 'timestamp': utilities.now(), 'resources': []}), utilities.timeless_json_hash(resp)) self.assertTrue(start_time <= resp.get('timestamp') <= end_time) # The timestamp of the second response is the timestamp of the container. resp = utilities.make_response([CONTAINER], 'resources') self.assertEqual( utilities.timeless_json_hash( {'success': True, 'timestamp': utilities.now(), 'resources': [CONTAINER]}), utilities.timeless_json_hash(resp)) self.assertEqual(CONTAINER['timestamp'], resp['timestamp'])
def get_rcontrollers(): """Computes the response of accessing the '/cluster/resources/rcontrollers'. Returns: The replication controllers of the context graph. """ gs = app.context_graph_global_state try: rcontrollers_list = kubernetes.get_rcontrollers(gs) except collector_error.CollectorError as e: return flask.jsonify(utilities.make_error(str(e))) return flask.jsonify(utilities.make_response(rcontrollers_list, 'resources'))
def get_nodes(): """Computes the response of the '/cluster/resources/nodes' endpoint. Returns: The nodes of the context graph. """ gs = app.context_graph_global_state try: nodes_list = kubernetes.get_nodes_with_metrics(gs) except collector_error.CollectorError as e: return flask.jsonify(utilities.make_error(str(e))) return flask.jsonify(utilities.make_response(nodes_list, 'resources'))
def get_reported_symptoms(r): content = request.get_json() necessary_values = ['identifier'] isGoodRequest = check_for_values_in_request(necessary_values, content) if (isGoodRequest[0] == False): return make_response({'response': 'bad request, please try again and specify the ' + str(isGoodRequest[1]) + ' parameter in the JSON request body.'}, status.HTTP_400_BAD_REQUEST) identifier = content['identifier'] push_id = unobfuscate(identifier, r) if (push_id == None or identifier == None): return make_response({'response': '\'identifier\' is invalid. Not Part of our database'}, status.HTTP_400_BAD_REQUEST) else: individual = retrieve_or_create_person_from_identifier(identifier) response_json = { 'test_status': individual.test_status, 'symptoms': individual.symptoms, 'additional_info': individual.additional_info, 'test_date': individual.test_date, 'symptoms_date': individual.symptoms_date, 'has_response': individual.didReport } return make_response(response_json, status.HTTP_200_OK)
def getExposureRisk(): content = request.get_json() necessary_values = ['identifier'] isGoodRequest = check_for_values_in_request(necessary_values, content) if (isGoodRequest[0] == False): return make_response({'response': 'bad request, please try again and specify the ' + str(isGoodRequest[1]) + ' parameter in the JSON request body.'}, status.HTTP_400_BAD_REQUEST) identifier = content['identifier'] is_risky = get_is_at_risk(identifier) if (is_risky == False): toReturn = { "exposure_risk":"NORMAL", "rationale": "We have not detected that you have been in contact with a carrier of COVID-19.", "guidance": "Continue to Comply with local quarantine and lockdown guidelines." } else: toReturn = { "exposure_risk":"AT_RISK", "rationale": "We have detected that you have been in contact with a carrier of COVID-19, or someone who has reported symptoms.", "guidance": "Continue to Comply with local quarantine and lockdown guidelines, but seek medical help if you begin to experience symptoms yourself." } return make_response(toReturn, http_status=status.HTTP_200_OK)
def get_rcontrollers(): """Computes the response of accessing the '/cluster/resources/rcontrollers'. Returns: The replication controllers of the context graph. """ gs = app.context_graph_global_state try: rcontrollers_list = kubernetes.get_rcontrollers(gs) except collector_error.CollectorError as e: return flask.jsonify(utilities.make_error(str(e))) return flask.jsonify( utilities.make_response(rcontrollers_list, 'resources'))
def purge_place(r, content): necessary_values = ['place_id'] isGoodRequest = check_for_values_in_request(necessary_values, content) if (isGoodRequest[0] == False): return make_response( { 'response': 'bad request, please try again and specify the ' + str(isGoodRequest[1]) + ' parameter in the JSON request body.' }, status.HTTP_400_BAD_REQUEST) place_id = content['place_id'] try: members = r.smembers(place_id) except: return make_response( {"response": "That is an invalid place identifier"}, status.HTTP_404_NOT_FOUND) members = list(members) for i in range(len(members)): members[i] = str(members[i]) try: r.srem(place_id, members) return make_response({"response": "place has been cleared"}, status.HTTP_200_OK) except: return make_response({"response": "Something has gone wrong"}, status.HTTP_404_NOT_FOUND)
def get_contacted_ids(r): content = request.get_json() necessary_values = ['place_id'] isGoodRequest = check_for_values_in_request(necessary_values, content) if (isGoodRequest[0] == False): return make_response( { 'response': 'bad request, please try again and specify the ' + str(isGoodRequest[1]) + ' parameter in the JSON request body.' }, status.HTTP_400_BAD_REQUEST) place_id = content['place_id'] try: members = r.smembers(place_id) except: return make_response( {"response": "That is an invalid place identifier"}, status.HTTP_404_NOT_FOUND) members = list(members) for i in range(len(members)): members[i] = str(members[i]) return make_response({"tokens": (members)}, status.HTTP_200_OK)
def get_version(): """Computes the response of the '/version' endpoint. Returns: The value of the docker.get_version() or an error message. """ gs = app.context_graph_global_state try: version = docker.get_version(gs) return flask.jsonify(utilities.make_response(version, 'version')) except collector_error.CollectorError as e: return flask.jsonify(utilities.make_error(str(e))) except: msg = ('get_version() failed with exception %s' % sys.exc_info()[0]) app.logger.exception(msg) return flask.jsonify(utilities.make_error(msg))
def get_elapsed(): """Computes the response of the '/elapsed' endpoint. Returns: A successful response containing the list of elapsed time records of the most recent Kubernetes and Docker access operations since the previous call to the '/elapsed' endpoint. Never returns more than constants.MAX_ELAPSED_QUEUE_SIZE elapsed time records. """ gs = app.context_graph_global_state try: result = return_elapsed(gs) return flask.jsonify(utilities.make_response(result, 'elapsed')) except: msg = 'get_elapsed() failed with exception %s' % sys.exc_info()[0] app.logger.exception(msg) return flask.jsonify(utilities.make_error(msg))
def get_pods(): """Computes the response of the '/cluster/resources/pods' endpoint. Returns: The pods of the context graph. """ gs = app.context_graph_global_state try: pods_list = kubernetes.get_pods(gs, None) except collector_error.CollectorError as e: return flask.jsonify(utilities.make_error(str(e))) except: msg = 'kubernetes.get_pods() failed with exception %s' % sys.exc_info()[0] app.logger.exception(msg) return flask.jsonify(utilities.make_error(msg)) return flask.jsonify(utilities.make_response(pods_list, 'resources'))
def get_services(): """Computes the response of the '/cluster/resources/services' endpoint. Returns: The services of the context graph. """ gs = app.context_graph_global_state try: services_list = kubernetes.get_services(gs) except collector_error.CollectorError as e: return flask.jsonify(utilities.make_error(str(e))) except: msg = ('kubernetes.get_services() failed with exception %s' % sys.exc_info()[0]) app.logger.exception(msg) return flask.jsonify(utilities.make_error(msg)) return flask.jsonify(utilities.make_response(services_list, 'resources'))
def get_minions(): """Computes the response of the '/minions_status' endpoint. Returns: A dictionary from node names to the status of their minion collectors or an error message. """ gs = app.context_graph_global_state minions_status = {} try: for node in kubernetes.get_nodes(gs): assert utilities.is_wrapped_object(node, 'Node') docker_host = node['id'] minions_status[docker_host] = docker.get_minion_status(gs, docker_host) except collector_error.CollectorError as e: return flask.jsonify(utilities.make_error(str(e))) except: msg = 'get_minions_status() failed with exception %s' % sys.exc_info()[0] app.logger.exception(msg) return flask.jsonify(utilities.make_error(msg)) return flask.jsonify(utilities.make_response(minions_status, 'minionsStatus'))
def get_containers(): """Computes the response of the '/cluster/resources/containers' endpoint. Returns: The containers of the context graph. """ containers = [] gs = app.context_graph_global_state try: for node in kubernetes.get_nodes(gs): # The node_id is the Docker host name. docker_host = node['id'] containers.extend(docker.get_containers_with_metrics(gs, docker_host)) except collector_error.CollectorError as e: return flask.jsonify(utilities.make_error(str(e))) except: msg = 'get_containers() failed with exception %s' % sys.exc_info()[0] app.logger.exception(msg) return flask.jsonify(utilities.make_error(msg)) return flask.jsonify(utilities.make_response(containers, 'resources'))
def get_containers(): """Computes the response of the '/cluster/resources/containers' endpoint. Returns: The containers of the context graph. """ containers = [] gs = app.context_graph_global_state try: for node in kubernetes.get_nodes(gs): # The node_id is the Docker host name. docker_host = node['id'] containers.extend( docker.get_containers_with_metrics(gs, docker_host)) except collector_error.CollectorError as e: return flask.jsonify(utilities.make_error(str(e))) except: msg = 'get_containers() failed with exception %s' % sys.exc_info()[0] app.logger.exception(msg) return flask.jsonify(utilities.make_error(msg)) return flask.jsonify(utilities.make_response(containers, 'resources'))
def reportSicknessSum(r): #Step 1, Check to make sure all parameters are there content = request.get_json() necessary_values = ['identifier', 'test_status', 'test_date', 'symptoms_date', 'symptoms', 'additional_info', 'contacted_individuals', 'visited_locations'] isGoodRequest = check_for_values_in_request(necessary_values, content) if (isGoodRequest[0] == False): return make_response({'error': 'bad request, please try again and specify the ' + str(isGoodRequest[1]) + ' parameter in the JSON request body.'}, status.HTTP_400_BAD_REQUEST) identifier = content['identifier'] test_status = content['test_status'] test_date = content['test_date'] symptoms_date = content['symptoms_date'] symptoms = content['symptoms'] additional_info = content['additional_info'] contacted_individuals = content['contacted_individuals'] visited_locations = content['visited_locations'] #Step 2, Check to make sure all parameters are properly formatted/Valid, and then report those parameters to the DB push_id = unobfuscate(identifier, r) if (push_id == None or identifier == None): return make_response({'response': '\'identifier\' is invalid. Not Part of our database'}, status.HTTP_400_BAD_REQUEST) sender = retrieve_or_create_person_from_identifier(identifier) update_person_statistics(sender, test_status, test_date, symptoms_date, symptoms, additional_info) #Step 3, report contacts for individual in contacted_individuals: #3.A See that necessary variables exist try: contacted_identifier = individual["identifier"] except: contacted_identifier = None try: contact_time = individual['contact_time'] except: contact_time = None #If contact time is not valid, change it to current time as approximation contact_time = try_for_datetime_from_string(contact_time) #If contacted_identifier is valid, and it is not a cell phone number (there is a registered account), #then get the push notification code. if (contacted_identifier != None): push_notification_code = unobfuscate(contacted_identifier, r) else: push_notification_code = None #Now, do processing for this individual number based on what data is available #Check if push notification code is actually a cell phone number if (push_notification_code != None): is_cell_phone = isCellPhone(push_notification_code) else: is_cell_phone = False if ((contacted_identifier == None or push_notification_code == None) and is_cell_phone == False): #Simply an invalid code print("skipping this number") elif (is_cell_phone == True): #DO THE PROCESSING FOR CELLULAR DEVICES print("do cell phone number processing") message = "A user of the Exposure App, who you have had contact with, has reported a change in their COVID-19 status. Download Exposure from getmyexposure.com to see your risk" phone_number = str(push_notification_code)[1:] successful_message = send_message(message, phone_number) if (successful_message == False): print("failed to send text message") else: #Do the process for push notifications contacted_individual = retrieve_or_create_person_from_identifier(contacted_identifier) #report to the database that the two individuals contacted report_contact_between_individuals(sender, contacted_individual, contact_time) #now, send the push notification to the contacted_individual: true_code = str(push_notification_code)[1:] print(true_code) message = "We have a problem to report with your coronavirus exposure." try: send_push_message(true_code, message) except: print("failed to send push notification for some reason") #Step 4, Report and Store Locations for location in visited_locations: #4.A See that necessary variables exist try: latitude = location["latitude"] except: latitude = None try: longitude = location["longitude"] except: longitude = None try: contact_time = location['contact_time'] except: contact_time = None #If contact time is not valid, change it to current time as approximation contact_time = try_for_datetime_from_string(contact_time) #If contacted_identifier is valid, and it is not a cell phone number (there is a registered account), #then get the push notification code. #Now, do processing for this individual number based on what data is available if (latitude == None or longitude == None): print("skipping this location") else: contacted_location = retrieve_or_create_place_from_lat_and_long(latitude, longitude) #report to the database that the location was visited report_visited_place(sender, contacted_location, contact_time) return make_response({'response': 'We sent the Push Notifications!!!'}, status.HTTP_200_OK)