Document toolboxDocument toolbox

Design for Pharma Partner

In brief: Pharma partner's researcher will sign in to researcher portal and select a valid PIN to enroll a user (creating an account). Then on the phone, they'll enter the pin to initialize the application (sign in).

Study

Add flag, isExternalIdValidated. At the very least it should toggle between current behavior (any string can be set) and a stricter set of rules.

I would have this flag validate and assign an ID, require it at sign up, and not allow it to be unassigned, only deleted when the user is deleted (for testing). There are actually many behaviors and there may need to be more than one flag:

  • should ID be validated?
  • should ID be assigned?
  • is the ID required at sign up (that is, don't create an account until you've validated the external ID you're going to use for it)
  • can the ID be unassigned or re-assigned?
  • can the ID be deleted once assigned?

This work is done. As currently implemented, when you turn on external ID validation, the study developers must upload a set of IDs to the system and then creation of users either through sign up or through the researcher UI requires that you provide one of these valid, unused IDs. Once added they cannot be changed. For partners that wish to add IDs as they go, we have created a UI that allows them to add then use a single ID.

ExternalId Table

  • String studyId (key)
  • String externalId (range)
  • String healthCode
  • long reservation

To assign healthCode to an ID is to assign it, but I propose a reservation design so that during sign up, we can validate and hold an ID until we have an account with a healthCode that we can register. The reservation would only be for 30 seconds or so.

This has been implemented.

ExternalIdDao

Follows the external ID service. The service might assume methods for FPHS and the FPHS Dao as well, not sure.

ExternalIdService

// With optional filter to return only unassigned IDs, useful for Pharma Partner, and an idFilter to filter down to an ID. I imagine
// a scenario where a researcher is searching for a particular ID in order to create an account from it.
getExternalIds(StudyIdentifier studyId, int offsetBy, int pageSize, String idFilter, Boolean assignmentFilter);

// Existing IDs would be completely ignored. To reset IDs, as was done multiple times in FPHS, let's implement
// the ability for researchers or admins to delete users through the researcher UI. 
addExternalIds(StudyIdentifier studyId, List<String> externalIdentifiers);

// Returns true if there's no healthCode and the reservation timestamp minus time of request is 
// less than some timeout value (or zero/unset). If it is going to return true, it sets the reservation
// field to current timestamp, preventing other callers from proceeding to use the ID. If the call that
// reserved the ID fails, it will become available again after the timeout.
boolean reserveExternalId(StudyIdentifier studyId, String externalIdentifier);

// Assigns the ID once you have the healthCode. If reservation failed, the caller should not 
// proceed to call this method. After this of course, any attempts to assign or reserve should fail.
assignExternalId(StudyIdentifier studyId, String externalIdentifier, String healthCode);

// Call as part of deleting a user.
unassignExternalId(StudyIdentifier studyId, String externalIdentifier);

Finally, to handle other ways of validating IDs, we could have the service use an ExternalIdProvider that can be configured per study. The default provider would use our DAO, tables and APIs, but we could create others to contact external services, etc. Spring makes this easy to do.

This has all been implemented. At this time, we did not subsume FPHS' functionality under this new API. FPHS still operates with its own custom external ID provisioning.

ExternalIdController / Other controllers

GET /v3/studies/self/externalIds?offsetBy=n&pageSize=n&idFilter=<string>&assignmentFilter=<boolean>
get paged list of identifiers, should be able to filter on assigned/unassigned for Pharma Partner. Would basically just return the IDs and assignment status

POST /3/studies/self/externalIds
add identifiers in bulk. Does not reset existing identifiers

POST /v3/participants
Create a user, including the externalId. Creation should fail if externalId is in invalid or assigned. Used for Pharma Partner. NOTE: For Pharma Partner, we might just use sign up. But this call could allow researcher to set all sorts of stuff up front when creating a user.

The rest is tied into existing APIs. Validation and assignment would occur anywhere we change externalId:

POST /v3/auth/signUp
Should be able to provide an externalId at sign up, sign up should fail if the ID is invalid or assigned. 

POST /v3/participants/member/options
Should validate that the externalId, if provided, is valid and unassigned (in studies that do this). Also does not allow ID to be changed if it exists.

POST /v3/users/self/externalId
Should validate that the externalId, if provided, is valid and unassigned (in studies that do this). Also does not allow ID to be changed if it exists.

DELETE /v3/users
Unassigns the external ID associated with the user

Everything here has been implemented except the provisioning of an external ID during sign up. Current pharma partners don't need this because they are operating in a lab. It is currently being added to sign up.

Researcher UI

We should create a Pharma Partner-specific screen in researcher UI that simplifies creating a user down to selecting a free external ID. Then they can then enter the code on the device. Actually creating a user off of an externalID might be generically useful.

This has been implemented under the external identifiers section of the application.

SignUp

Can provide an externalId at sign up and sign up will be rejected if the ID is invalid or assigned. This does allow for enumeration of the IDs, unfortunately, but meets some researcher needs (FPHS). This is not needed for Pharma Partner but will almost certainly be needed in the future.

Currently being implemented for future applications.