Example #1
0
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)
Example #2
0
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)
Example #3
0
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'))
Example #4
0
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'))
Example #5
0
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'))
Example #6
0
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'))
Example #7
0
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'))
Example #8
0
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)
Example #10
0
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)
Example #11
0
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)
Example #12
0
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)
Example #13
0
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'))
Example #14
0
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'])
Example #16
0
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'))
Example #17
0
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'))
Example #18
0
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'))
Example #19
0
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)
Example #20
0
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)
Example #21
0
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)
Example #23
0
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)
Example #24
0
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))
Example #25
0
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))
Example #26
0
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))
Example #27
0
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'))
Example #28
0
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'))
Example #29
0
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'))
Example #30
0
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'))
Example #31
0
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'))
Example #32
0
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)