Example #1
0
  def testPendingClientRegsDelete(self):
    fakeEmail = "*****@*****.**"

    client = Client("testclient")
    client.update(createKey = False)
    common.makeValid(client)
    (resultPre, resultReg) = client.preRegister("this_is_the_super_secret_id", fakeEmail)
    studyList = Client.getPendingClientRegs(fakeEmail)
    self.assertEqual(studyList, ["testclient"])
  
    Client.deletePendingClientRegs(fakeEmail) 
    afterDelList = Client.getPendingClientRegs(fakeEmail)
    self.assertEqual(afterDelList, [])
  def testPendingClientRegsDelete(self):
    fakeEmail = "*****@*****.**"

    client = Client("testclient")
    client.update(createKey = False)
    common.makeValid(client)
    (resultPre, resultReg) = client.preRegister("this_is_the_super_secret_id", fakeEmail)
    studyList = Client.getPendingClientRegs(fakeEmail)
    self.assertEqual(studyList, ["testclient"])
  
    Client.deletePendingClientRegs(fakeEmail) 
    afterDelList = Client.getPendingClientRegs(fakeEmail)
    self.assertEqual(afterDelList, [])
Example #3
0
  def register(userEmail):
    import uuid
    from datetime import datetime
    from emission.core.wrapper.client import Client

    # We are accessing three databases here:
    # - The list of pending registrations (people who have filled out demographic
    # information but not installed the app)
    # - The mapping from the userEmail to the user UUID
    # - The mapping from the UUID to other profile information about the user
    # The first two are indexed by the user email. We will use the same field
    # name in both to indicate that it is a shared key. This also allows us to
    # have a simple query that we can reuse.
    userEmailQuery = {'user_email': userEmail}

    # First, we construct the email -> uuid mapping and store it in the appropriate database.
    # At this point, we don't know or care whether the user is part of a study
    # We also store a create timestamp just because that's always a good idea
    # What happens if the user calls register() again? Do we want to generate a new UUID?
    # Do we want to update the create timestamp?
    # For now, let's assume that the answer to both of those questions is yes,
    # because that allows us to use upsert :)
    # A bonus fix is that if something is messed up in the DB, calling create again will fix it.

    # This is the UUID that will be stored in the trip database
    # in order to do some fig leaf of anonymity
    # Since we now generate truly anonymized UUIDs, and we expect that the
    # register operation is idempotent, we need to check and ensure that we don't
    # change the UUID if it already exists.
    existing_entry = get_uuid_db().find_one({"user_email": userEmail})
    if existing_entry is None:
        anonUUID = uuid.uuid4()
    else:
        anonUUID = existing_entry['uuid']
    emailUUIDObject = {'user_email': userEmail, 'uuid': anonUUID, 'update_ts': datetime.now()}
    writeResultMap = get_uuid_db().update(userEmailQuery, emailUUIDObject, upsert=True)
    # Note, if we did want the create_ts to not be overwritten, we can use the
    # writeResult to decide how to deal with the values

    # Now, we look to see if the user is part of a study. We can either store
    # this information in the profile database, or the mapping, or both. For now,
    # let us store this in the profile database since it is sufficient for it to
    # be associated with the UUID, we anticipate using it for customization, and
    # we assume that other customization stuff will be stored in the profile.

    # We could also assume that we will create the profile if we created the map
    # and update if we updated. But that has some reliability issues. For
    # example, what if creating the map succeeded but creating the profile
    # failed? Subsequently calling the method again to try and fix the profile
    # will continue to fail because we will be trying to update.
    # Much better to deal with it separately by doing a separate upsert

    # Second decision: what do we do if the user is not part of a study? Create a
    # profile anyway with an empty list, or defer the creation of the profile?
    # 
    # Decision: create profile with empty list for two reasons:
    # a) for most of the functions, we want to use the profile data. We should
    # only use the email -> uuid map in the API layer to get the UUID, and use
    # the UUID elsewhere. So we need to have profiles for non-study participants
    # as well.
    # b) it will also make the scripts to update the profile in the background
    # easier to write. They won't have to query the email -> UUID database and
    # create the profile if it doesn't exist - they can just work off the profile
    # database.
    # TODO: Write a script that periodically goes through and identifies maps
    # that don't have an associated profile and fix them
    study_list = Client.getPendingClientRegs(userEmail)
    writeResultProfile = User.createProfile(anonUUID, datetime.now(), study_list)
     
    if 'err' not in writeResultProfile:
      # update was successful!
      # Either upserted or updatedExisting will be true
      # We can now cleanup the entry from the pending database
      # Note that we could also move this to a separate cleanup script because
      # eventual consistency is good enough for us
      # If there is a profile entry for a particular signup, then delete it
      Client.deletePendingClientRegs(userEmail)
    return User.fromUUID(anonUUID)
  def register(userEmail):
    import uuid
    from datetime import datetime
    from emission.core.wrapper.client import Client

    # We are accessing three databases here:
    # - The list of pending registrations (people who have filled out demographic
    # information but not installed the app)
    # - The mapping from the userEmail to the user UUID
    # - The mapping from the UUID to other profile information about the user
    # The first two are indexed by the user email. We will use the same field
    # name in both to indicate that it is a shared key. This also allows us to
    # have a simple query that we can reuse.
    userEmailQuery = {'user_email': userEmail}

    # First, we construct the email -> uuid mapping and store it in the appropriate database.
    # At this point, we don't know or care whether the user is part of a study
    # We also store a create timestamp just because that's always a good idea
    # What happens if the user calls register() again? Do we want to generate a new UUID?
    # Do we want to update the create timestamp?
    # For now, let's assume that the answer to both of those questions is yes,
    # because that allows us to use upsert :)
    # A bonus fix is that if something is messed up in the DB, calling create again will fix it.

    # This is the UUID that will be stored in the trip database
    # in order to do some fig leaf of anonymity
    # Since we now generate truly anonymized UUIDs, and we expect that the
    # register operation is idempotent, we need to check and ensure that we don't
    # change the UUID if it already exists.
    existing_entry = get_uuid_db().find_one({"user_email": userEmail})
    if existing_entry is None:
        anonUUID = uuid.uuid4()
    else:
        anonUUID = existing_entry['uuid']
    emailUUIDObject = {'user_email': userEmail, 'uuid': anonUUID, 'update_ts': datetime.now()}
    writeResultMap = get_uuid_db().update(userEmailQuery, emailUUIDObject, upsert=True)
    # Note, if we did want the create_ts to not be overwritten, we can use the
    # writeResult to decide how to deal with the values

    # Now, we look to see if the user is part of a study. We can either store
    # this information in the profile database, or the mapping, or both. For now,
    # let us store this in the profile database since it is sufficient for it to
    # be associated with the UUID, we anticipate using it for customization, and
    # we assume that other customization stuff will be stored in the profile.

    # We could also assume that we will create the profile if we created the map
    # and update if we updated. But that has some reliability issues. For
    # example, what if creating the map succeeded but creating the profile
    # failed? Subsequently calling the method again to try and fix the profile
    # will continue to fail because we will be trying to update.
    # Much better to deal with it separately by doing a separate upsert

    # Second decision: what do we do if the user is not part of a study? Create a
    # profile anyway with an empty list, or defer the creation of the profile?
    # 
    # Decision: create profile with empty list for two reasons:
    # a) for most of the functions, we want to use the profile data. We should
    # only use the email -> uuid map in the API layer to get the UUID, and use
    # the UUID elsewhere. So we need to have profiles for non-study participants
    # as well.
    # b) it will also make the scripts to update the profile in the background
    # easier to write. They won't have to query the email -> UUID database and
    # create the profile if it doesn't exist - they can just work off the profile
    # database.
    # TODO: Write a script that periodically goes through and identifies maps
    # that don't have an associated profile and fix them
    study_list = Client.getPendingClientRegs(userEmail)
    writeResultProfile = User.createProfile(anonUUID, datetime.now(), study_list)
     
    if 'err' not in writeResultProfile:
      # update was successful!
      # Either upserted or updatedExisting will be true
      # We can now cleanup the entry from the pending database
      # Note that we could also move this to a separate cleanup script because
      # eventual consistency is good enough for us
      # If there is a profile entry for a particular signup, then delete it
      Client.deletePendingClientRegs(userEmail)
    return User.fromUUID(anonUUID)