def authorize_new_patient(): """ This is called once a patient clicks the confirmation link in their email. Redirect a new patient to Fitbit to authorize our app via OAuth 2 Authorization Grant Flow, and then receives access token (for making API calls on the user's behalf) as well as a refresh token (for obtaining a new access token when the access token expires). """ access_code = request.args.get("code") invite_id = request.args.get("state") api = Fitbit() # Require users to be invited by a physician. Only occurs when they receive an email w/ invite_id (aka "state"). if invite_id is None: flash( "Error: an authorization token is required. Please use the confirmation link that was emailed to you.", "warning", ) return redirect("/") if access_code is None: auth_url = api.get_authorization_uri(invite_id) return redirect(auth_url) try: token = api.get_access_token(access_code) except Exception as e: flash(e.message, "warning") return redirect("/") try: response, token = api.api_call(token, "/1/user/-/profile.json") except Exception as e: flash(e.message, "warning") return redirect("/") # fullname = response['user']['fullName'] # Using name entered by Physician on invite instead. fitbit_id = response["user"]["encodedId"] try: invite = PatientInvite.objects.get(id=invite_id) if not invite.accepted: invite.accepted = True PatientInvite.delete(invite) try: existing_patient = Patient.objects.get(slug=fitbit_id) existing_patient.token = token["access_token"] existing_patient.refresh = token["refresh_token"] existing_patient.save() new_patient = existing_patient except DoesNotExist: new_patient = Patient( slug=fitbit_id, first_name=invite.first_name, last_name=invite.last_name, email=invite.email, token=token["access_token"], refresh=token["refresh_token"], date_joined=datetime.now(), health_data_per_day=[], date_last_data_fetch="", ) new_patient.save() # By default, get 5 days worth of data for the brand new patient new_patient_data = PatientData(new_patient) PatientData.get_heart_rate_data_for_x_days(new_patient_data, 5) PatientData.get_activity_data_for_x_days(new_patient_data, 5) # Now save this patient to the inviting physician's list of patients. inviting_physician = invite.inviting_physician inviting_physician.patients.append(new_patient) inviting_physician.save() # Now attach a generic config to Patient for the Physician to edit later min_hr_default = {"value": 50, "window": 15} # BPS / minute max_hr_default = {"value": 110, "window": 15} # BPS / minute min_steps_default = {"value": 500, "window": 60 * 12} # steps / 12 hr max_steps_default = {"value": 5000, "window": 60} # steps / 1 hr config = PatientConfig( minHR=min_hr_default, maxHR=max_hr_default, minSteps=min_steps_default, maxSteps=max_steps_default, patient=new_patient, ) inviting_physician.patient_config.append(config) inviting_physician.save() return redirect("/patient-registered?name=" + invite.first_name) else: flash("It appears you've already confirmed this account.", "warning") return redirect("/") except DoesNotExist as e: flash(e.__str__(), "warning") return redirect("/")
def drop(): from recover.models import Patient, User, PatientInvite PatientInvite.drop_collection() Patient.drop_collection() User.drop_collection()