def _remote_survey_url_vioscreen(transaction, account_id, source_id,
                                 language_tag, survey_redirect_url,
                                 vioscreen_ext_sample_id):
    # assumes an instance of Transaction is already available
    acct_repo = AccountRepo(transaction)
    survey_template_repo = SurveyTemplateRepo(transaction)

    if vioscreen_ext_sample_id:
        # User is about to start a vioscreen survey for this sample
        # record this in the database.
        db_vioscreen_id = survey_template_repo.create_vioscreen_id(
            account_id, source_id, vioscreen_ext_sample_id)
    else:
        raise ValueError("Vioscreen Template requires "
                         "vioscreen_ext_sample_id parameter.")

    (birth_year, gender, height, weight) = \
        survey_template_repo.fetch_user_basic_physiology(
        account_id, source_id)

    account = acct_repo.get_account(account_id)
    country_code = account.address.country_code

    url = vioscreen.gen_survey_url(db_vioscreen_id,
                                   language_tag,
                                   survey_redirect_url,
                                   birth_year=birth_year,
                                   gender=gender,
                                   height=height,
                                   weight=weight,
                                   country_code=country_code)

    return url
def setup_test_data():
    teardown_test_data()

    with Transaction() as t:
        acct_repo = AccountRepo(t)

        acc = Account(ACCT_ID_1,
                      "*****@*****.**",
                      "admin",
                      ACCT_MOCK_ISS,
                      ACCT_MOCK_SUB,
                      "Dan",
                      "H",
                      Address(
                          "456 Dan Lane",
                          "Danville",
                          "CA",
                          12345,
                          "US"
                      ),
                      "fakekit",
                      "en_US")
        acct_repo.create_account(acc)

        with t.cursor() as cur:
            cur.execute("UPDATE barcodes.project"
                        " SET is_active = FALSE"
                        " WHERE project_id = 2")
        t.commit()
def validate_admin_access(token_info):
    with Transaction() as t:
        account_repo = AccountRepo(t)
        account = account_repo.find_linked_account(token_info['iss'],
                                                   token_info['sub'])
        if account is None or account.account_type != 'admin':
            raise Unauthorized()
def teardown_test_data():
    with Transaction() as t:
        acct_repo = AccountRepo(t)
        admin_repo = AdminRepo(t)
        acct_repo.delete_account(ACCT_ID_1)
        admin_repo.delete_project_by_name(DUMMY_PROJ_NAME)
        t.commit()
def _validate_account_access(token_info, account_id):
    with Transaction() as t:
        account_repo = AccountRepo(t)
        token_associated_account = account_repo.find_linked_account(
            token_info['iss'],
            token_info['sub'])
        account = account_repo.get_account(account_id)
        if account is None:
            raise NotFound(ACCT_NOT_FOUND_MSG)
        else:
            # Whether or not the token_info is associated with an admin acct
            token_authenticates_admin = \
                token_associated_account is not None and \
                token_associated_account.account_type == 'admin'

            # Enum of how closely token info matches requested account_id
            auth_match = account.account_matches_auth(
                token_info[JWT_EMAIL_CLAIM_KEY],
                token_info[JWT_ISS_CLAIM_KEY],
                token_info[JWT_SUB_CLAIM_KEY])

            # If token doesn't match requested account id, and doesn't grant
            # admin access to the system, deny.
            if auth_match == AuthorizationMatch.NO_MATCH and \
                    not token_authenticates_admin:
                raise Unauthorized()

        return account
    def test_email_stats(self):
        with Transaction() as t:
            accts = AccountRepo(t)
            acct1 = accts.get_account("65dcd6c8-69fa-4de8-a33a-3de4957a0c79")
            acct2 = accts.get_account("556f5dc4-8cf2-49ae-876c-32fbdfb005dd")

            # execute articles get
            for project in [None, "American Gut Project", "NotAProj"]:
                response = self.client.post(
                    "/api/admin/account_email_summary",
                    headers=MOCK_HEADERS,
                    content_type='application/json',
                    data=json.dumps({
                        "emails": [acct1.email, acct2.email],
                        "project": project
                    })
                )
                self.assertEqual(200, response.status_code)
                result = json.loads(response.data)
                self.assertEqual(result[0]["account_id"],
                                 "65dcd6c8-69fa-4de8-a33a-3de4957a0c79")
                self.assertEqual(result[1]["account_id"],
                                 "556f5dc4-8cf2-49ae-876c-32fbdfb005dd")
                if project is None or project == "American Gut Project":
                    self.assertEqual(result[0]["sample-is-valid"], 1)
                else:
                    self.assertEqual(result[0].get("sample-is-valid", 0), 0)
    def get_samples_by_source(self,
                              account_id,
                              source_id,
                              allow_revoked=False):
        sql = "{0}{1}".format(
            self.PARTIAL_SQL, " WHERE"
            " source.account_id = %s"
            " AND source.id = %s"
            " ORDER BY ag_kit_barcodes.barcode asc")

        with self._transaction.cursor() as cur:
            acct_repo = AccountRepo(self._transaction)
            if acct_repo.get_account(account_id) is None:
                raise NotFound("No such account")

            source_repo = SourceRepo(self._transaction)
            if source_repo.get_source(account_id,
                                      source_id,
                                      allow_revoked=allow_revoked) is None:
                raise NotFound("No such source")

            cur.execute(sql, (account_id, source_id))

            samples = []
            for sample_row in cur.fetchall():
                samples.append(self._create_sample_obj(sample_row))
            return samples
Example #8
0
    def retrieve_diagnostics_by_email(self, email):

        acct_repo = AccountRepo(self._transaction)
        ids = acct_repo.get_account_ids_by_email(email)

        accts = [acct_repo.get_account(acct_id) for acct_id in ids]
        diagnostic = {
            "accounts": accts
        }

        return diagnostic
def setup_test_data():
    teardown_test_data()

    with Transaction() as t:
        acct_repo = AccountRepo(t)

        acc = Account(ACCT_ID_1, "*****@*****.**", "admin", ACCT_MOCK_ISS,
                      ACCT_MOCK_SUB, "Dan", "H",
                      Address("456 Dan Lane", "Danville", "CA", 12345,
                              "US"), "fakekit")
        acct_repo.create_account(acc)
        t.commit()
Example #10
0
def find_accounts_for_login(token_info):
    # Note: Returns an array of accounts accessible by token_info because
    # we'll use that functionality when we add in administrator accounts.
    with Transaction() as t:
        acct_repo = AccountRepo(t)
        acct = acct_repo.find_linked_account(
            token_info[JWT_ISS_CLAIM_KEY],
            token_info[JWT_SUB_CLAIM_KEY])

        if acct is None:
            return jsonify([]), 200
        return jsonify([acct.to_api()]), 200
def teardown_test_data():
    with Transaction() as t:
        acct_repo = AccountRepo(t)
        admin_repo = AdminRepo(t)
        acct_repo.delete_account(ACCT_ID_1)
        admin_repo.delete_project_by_name(DUMMY_PROJ_NAME)
        with t.cursor() as cur:
            cur.execute("UPDATE barcodes.project"
                        " SET is_active = TRUE"
                        " WHERE project_id = 2")

        t.commit()
Example #12
0
def _validate_has_account(token_info):
    # WARNING: this does NOT authenticate a user but tests for the
    # presence of an account
    with Transaction() as t:
        account_repo = AccountRepo(t)
        token_associated_account = account_repo.find_linked_account(
            token_info['iss'], token_info['sub'])

    if token_associated_account is None:
        raise Unauthorized()
    else:
        return
Example #13
0
    def create_source(self, source):
        with self._transaction.cursor() as cur:
            acct_repo = AccountRepo(self._transaction)
            if acct_repo.get_account(source.account_id) is None:
                raise NotFound("No such account_id")

            cur.execute(
                "INSERT INTO source (" + SourceRepo.write_cols + ") "
                "VALUES("
                "%s, %s, %s, "
                "%s, %s, "
                "%s, %s, %s, "
                "%s, %s, %s, "
                "%s, %s, %s)", _source_to_row(source))
            return cur.rowcount == 1
Example #14
0
def _create_dummy_acct_from_t(t,
                              create_dummy_1=True,
                              iss=ACCT_MOCK_ISS,
                              sub=ACCT_MOCK_SUB):
    if create_dummy_1:
        dummy_acct_id = ACCT_ID_1
        dict_to_copy = DUMMY_ACCT_INFO
    else:
        dummy_acct_id = ACCT_ID_2
        dict_to_copy = DUMMY_ACCT_INFO_2

    input_obj = copy.deepcopy(dict_to_copy)
    input_obj["id"] = dummy_acct_id
    acct_repo = AccountRepo(t)
    acct_repo.create_account(Account.from_dict(input_obj, iss, sub))

    return dummy_acct_id
def update_account(account_id, body, token_info):
    acc = _validate_account_access(token_info, account_id)

    with Transaction() as t:
        acct_repo = AccountRepo(t)
        acc.first_name = body['first_name']
        acc.last_name = body['last_name']
        acc.email = body['email']
        acc.address = Address(body['address']['street'],
                              body['address']['city'],
                              body['address']['state'],
                              body['address']['post_code'],
                              body['address']['country_code'])

        # 422 handling is done inside acct_repo
        acct_repo.update_account(acc)
        t.commit()

        return jsonify(acc.to_api()), 200
Example #16
0
def register_account(body, token_info):
    # First register with AuthRocket, then come here to make the account
    new_acct_id = str(uuid.uuid4())
    body["id"] = new_acct_id
    # Account.from_dict requires a kit_name, even if blank
    kit_name = body.get("kit_name", "")
    body["kit_name"] = kit_name
    code = body.get("code", "")
    body["code"] = code

    account_obj = Account.from_dict(body, token_info[JWT_ISS_CLAIM_KEY],
                                    token_info[JWT_SUB_CLAIM_KEY])

    if kit_name == "" and code == "":
        return jsonify(code=400,
                       message="Account registration requires "
                       "valid kit ID or activation code"), 400

    with Transaction() as t:
        activation_repo = ActivationRepo(t)
        if code != "":
            can_activate, cause = activation_repo.can_activate_with_cause(
                body["email"], code)
            if not can_activate:
                return jsonify(code=404, message=cause), 404
            else:
                activation_repo.use_activation_code(body["email"], code)

        if kit_name != "":
            kit_repo = KitRepo(t)
            kit = kit_repo.get_kit_all_samples(kit_name)
            if kit is None:
                return jsonify(code=404, message="Kit name not found"), 404

        acct_repo = AccountRepo(t)
        acct_repo.create_account(account_obj)
        new_acct = acct_repo.get_account(new_acct_id)
        t.commit()

    response = jsonify(new_acct.to_api())
    response.status_code = 201
    response.headers['Location'] = '/api/accounts/%s' % new_acct_id
    return response
Example #17
0
def claim_legacy_acct(token_info):
    # If there exists a legacy account for the email in the token, which the
    # user represented by the token does not already own but can claim, this
    # claims the legacy account for the user and returns a 200 code with json
    # list containing the object for the claimed account.  Otherwise, this
    # returns an empty json list. This function can also trigger a 422 from the
    # repo layer in the case of inconsistent account data.

    email = token_info[JWT_EMAIL_CLAIM_KEY]
    auth_iss = token_info[JWT_ISS_CLAIM_KEY]
    auth_sub = token_info[JWT_SUB_CLAIM_KEY]

    with Transaction() as t:
        acct_repo = AccountRepo(t)
        acct = acct_repo.claim_legacy_account(email, auth_iss, auth_sub)
        t.commit()

        if acct is None:
            return jsonify([]), 200

        return jsonify([acct.to_api()]), 200
Example #18
0
    def test_scrub(self):
        with Transaction() as t:
            ar = AccountRepo(t)
            ar.scrub(ACCOUNT_ID)
            obs = ar.get_account(ACCOUNT_ID)

            self.assertEqual(obs.id, self.untouched.id)
            self.assertNotEqual(obs.email, self.untouched.email)
            self.assertEqual(obs.account_type, 'deleted')
            self.assertEqual(obs.auth_issuer, None)
            self.assertEqual(obs.auth_sub, None)
            self.assertEqual(obs.first_name, 'scrubbed')
            self.assertEqual(obs.last_name, 'scrubbed')
            self.assertEqual(obs.address.street, 'scrubbed')
            self.assertEqual(obs.address.city, 'scrubbed')
            self.assertEqual(obs.address.state, 'NA')
            self.assertEqual(obs.address.post_code, 'scrubbed')

            # keeping country is reasonable as it's so broad
            self.assertEqual(obs.address.country_code,
                             self.untouched.address.country_code)
            self.assertEqual(obs.created_with_kit_id,
                             self.untouched.created_with_kit_id)
            self.assertEqual(obs.creation_time,
                             self.untouched.creation_time)
            self.assertNotEqual(obs.update_time,
                                self.untouched.update_time)
            self.assertEqual(obs.language,
                             self.untouched.language)

            email = obs.email
            date, remainder = email.split('@', 1)
            date = date.split('T')[0].strip('"')
            obs_date = datetime.datetime.strptime(date, "%Y-%m-%d")
            today = datetime.datetime.now()
            today = datetime.datetime(year=today.year,
                                      month=today.month,
                                      day=today.day)
            self.assertEqual(obs_date, today)
            self.assertEqual(remainder, 'microsetta.ucsd.edu')
Example #19
0
    def retrieve_diagnostics_by_kit_id(self, supplied_kit_id):
        kit_repo = KitRepo(self._transaction)
        kit = kit_repo.get_kit_all_samples(supplied_kit_id)

        if kit is None:
            return None

        sample_assoc = []
        for sample in kit.samples:
            sample_assoc.append(
                self.retrieve_diagnostics_by_barcode(sample.barcode,
                                                     grab_kit=False))

        with self._transaction.dict_cursor() as cur:
            cur.execute(
                "SELECT "
                "ag_login_id as account_id "
                "FROM "
                "ag_kit "
                "WHERE "
                "supplied_kit_id = %s",
                (supplied_kit_id,))
            row = cur.fetchone()

        pre_microsetta_acct = None
        if row['account_id'] is not None:
            acct_repo = AccountRepo(self._transaction)
            # This kit predated the microsetta migration, let's pull in the
            # account info associated with it
            pre_microsetta_acct = acct_repo.get_account(row['account_id'])

        diagnostic = {
            'kit_id': kit.id,
            'supplied_kit_id': supplied_kit_id,
            'kit': kit,
            'pre_microsetta_acct': pre_microsetta_acct,
            'sample_diagnostic_info': sample_assoc
        }

        return diagnostic
def delete_dummy_accts():
    all_sample_ids = []
    acct_ids = [ACCT_ID_1, ACCT_ID_2]

    with Transaction() as t:
        acct_repo = AccountRepo(t)
        source_repo = SourceRepo(t)
        survey_answers_repo = SurveyAnswersRepo(t)
        sample_repo = SampleRepo(t)

        for curr_acct_id in acct_ids:
            sources = source_repo.get_sources_in_account(curr_acct_id)
            for curr_source in sources:
                source_samples = sample_repo.get_samples_by_source(
                    curr_acct_id, curr_source.id)
                sample_ids = [x.id for x in source_samples]
                all_sample_ids.extend(sample_ids)

                # Dissociate all samples linked to this source from all
                # answered surveys linked to this source, then delete all
                # answered surveys
                delete_dummy_answered_surveys_from_source_with_t(
                    t, curr_acct_id, curr_source.id, sample_ids,
                    survey_answers_repo)

                # Now dissociate all the samples from this source
                for curr_sample_id in sample_ids:
                    sample_repo.dissociate_sample(curr_acct_id, curr_source.id,
                                                  curr_sample_id)

                # Finally, delete the source
                source_repo.delete_source(curr_acct_id, curr_source.id)

            # Delete the account
            acct_repo.delete_account(curr_acct_id)

        # Belt and suspenders: these test emails are used by some tests outside
        # of this module as well, so can't be sure they are paired with the
        # above dummy account ids
        acct_repo.delete_account_by_email(TEST_EMAIL)
        acct_repo.delete_account_by_email(TEST_EMAIL_2)

        # Delete the kit and all samples that were attached to any sources
        # NB: This won't clean up any samples that were created but NOT
        # attached to any sources ...
        if len(all_sample_ids) == 0:
            all_sample_ids = None
        _remove_mock_kit(t, mock_sample_ids=all_sample_ids)

        t.commit()
Example #21
0
 def test_geocode_accounts_valid(self, test_verify_address):
     test_verify_address.return_value = {
         "address_1": DUMMY_ACCT_INFO_1['address']['street'],
         "address_2": "",
         "city": DUMMY_ACCT_INFO_1['address']['city'],
         "state": DUMMY_ACCT_INFO_1['address']['state'],
         "postal": DUMMY_ACCT_INFO_1['address']['post_code'],
         "country": DUMMY_ACCT_INFO_1['address']['country_code'],
         "latitude": RESULT_LAT,
         "longitude": RESULT_LONG,
         "valid": True
     }
     with Transaction() as t:
         ar = AccountRepo(t)
         acct_1 = Account.from_dict(DUMMY_ACCT_INFO_1,
                                    ACCT_MOCK_ISS_1,
                                    ACCT_MOCK_SUB_1)
         ar.create_account(acct_1)
         ar.geocode_accounts()
         with t.dict_cursor() as cur:
             cur.execute("SELECT latitude, longitude, address_verified, "
                         "cannot_geocode FROM ag.account "
                         "WHERE id = %s",
                         (ACCT_ID_1,))
             r = cur.fetchone()
             self.assertAlmostEqual(r['latitude'], RESULT_LAT, 9)
             self.assertAlmostEqual(r['longitude'], RESULT_LONG, 9)
             self.assertTrue(r['address_verified'])
             self.assertFalse(r['cannot_geocode'])
def delete_account(account_id, token_info):
    validate_admin_access(token_info)

    with Transaction() as t:
        acct_repo = AccountRepo(t)
        src_repo = SourceRepo(t)
        samp_repo = SampleRepo(t)
        sar_repo = SurveyAnswersRepo(t)

        acct = acct_repo.get_account(account_id)
        if acct is None:
            return jsonify(message="Account not found", code=404), 404
        else:
            # the account is already scrubbed so let's stop early
            if acct.account_type == 'deleted':
                return None, 204

        sample_count = 0
        sources = src_repo.get_sources_in_account(account_id)

        for source in sources:
            samples = samp_repo.get_samples_by_source(account_id, source.id)

            has_samples = len(samples) > 0
            sample_count += len(samples)

            for sample in samples:
                # we scrub rather than disassociate in the event that the
                # sample is in our freezers but not with an up-to-date scan
                samp_repo.scrub(account_id, source.id, sample.id)

            surveys = sar_repo.list_answered_surveys(account_id, source.id)
            if has_samples:
                # if we have samples, we need to scrub survey / source
                # free text
                for survey_id in surveys:
                    sar_repo.scrub(account_id, source.id, survey_id)
                src_repo.scrub(account_id, source.id)
            else:
                # if we do not have associated samples, then the source
                # is safe to delete
                for survey_id in surveys:
                    sar_repo.delete_answered_survey(account_id, survey_id)
                src_repo.delete_source(account_id, source.id)

        # an account is safe to delete if there are no associated samples
        if sample_count > 0:
            acct_repo.scrub(account_id)
        else:
            acct_repo.delete_account(account_id)

        t.commit()

    return None, 204
Example #23
0
def register_account(body, token_info):
    # First register with AuthRocket, then come here to make the account
    new_acct_id = str(uuid.uuid4())
    body["id"] = new_acct_id
    account_obj = Account.from_dict(body, token_info[JWT_ISS_CLAIM_KEY],
                                    token_info[JWT_SUB_CLAIM_KEY])

    with Transaction() as t:
        kit_repo = KitRepo(t)
        kit = kit_repo.get_kit_all_samples(body['kit_name'])
        if kit is None:
            return jsonify(code=404, message="Kit name not found"), 404

        acct_repo = AccountRepo(t)
        acct_repo.create_account(account_obj)
        new_acct = acct_repo.get_account(new_acct_id)
        t.commit()

    response = jsonify(new_acct.to_api())
    response.status_code = 201
    response.headers['Location'] = '/api/accounts/%s' % new_acct_id
    return response
    def get_samples_by_source(self, account_id, source_id):
        with self._transaction.cursor() as cur:
            acct_repo = AccountRepo(self._transaction)
            if acct_repo.get_account(account_id) is None:
                raise NotFound("No such account")

            source_repo = SourceRepo(self._transaction)
            if source_repo.get_source(account_id, source_id) is None:
                raise NotFound("No such source")

            cur.execute(
                "SELECT "
                "ag_kit_barcodes.ag_kit_barcode_id, "
                "ag_kit_barcodes.sample_date, "
                "ag_kit_barcodes.sample_time, "
                "ag_kit_barcodes.site_sampled, "
                "ag_kit_barcodes.notes, "
                "ag_kit_barcodes.barcode, "
                "barcode.scan_date "
                "FROM ag_kit_barcodes "
                "LEFT JOIN barcode "
                "USING (barcode) "
                "LEFT JOIN source "
                "ON ag_kit_barcodes.source_id = source.id "
                "WHERE "
                "source.account_id = %s AND "
                "source.id = %s "
                "ORDER BY barcode.barcode asc", (account_id, source_id))

            samples = []
            for sample_row in cur.fetchall():
                barcode = sample_row[5]
                sample_projects = self._retrieve_projects(barcode)
                s = Sample.from_db(*sample_row, sample_projects)
                samples.append(s)
            return samples
def create_daklapack_orders(body, token_info):
    validate_admin_access(token_info)

    ADDRESSES_KEY = 'addresses'
    extended_body = body.copy()
    results = []

    with Transaction() as t:
        account_repo = AccountRepo(t)
        extended_body[SUBMITTER_ACCT_KEY] = account_repo.find_linked_account(
            token_info['iss'], token_info['sub'])

    for curr_address in extended_body[ADDRESSES_KEY]:
        curr_order_dict = extended_body.copy()
        curr_order_dict.pop(ADDRESSES_KEY)
        curr_order_dict[ADDR_DICT_KEY] = curr_address

        result_info = _create_daklapack_order(curr_order_dict)
        results.append(result_info)

    # return response to caller
    response = jsonify({"order_submissions": results})
    response.status_code = 200
    return response
Example #26
0
def delete_dummy_accts():
    with Transaction() as t:
        source_repo = SourceRepo(t)
        survey_answers_repo = SurveyAnswersRepo(t)
        sources = source_repo.get_sources_in_account(ACCT_ID_1)
        for curr_source in sources:
            answers = survey_answers_repo.list_answered_surveys(
                ACCT_ID_1, curr_source.id)
            for survey_id in answers:
                survey_answers_repo.delete_answered_survey(
                    ACCT_ID_1, survey_id)

            source_repo.delete_source(ACCT_ID_1, curr_source.id)

        acct_repo = AccountRepo(t)
        acct_repo.delete_account(ACCT_ID_1)
        acct_repo.delete_account(ACCT_ID_2)
        # Belt and suspenders: these test emails are used by some tests outside
        # of this module as well, so can't be sure they are paired with the
        # above dummy account ids
        acct_repo.delete_account_by_email(TEST_EMAIL)
        acct_repo.delete_account_by_email(TEST_EMAIL_2)
        t.commit()
Example #27
0
    def setup_test_data():
        AdminTests.teardown_test_data()

        with Transaction() as t:
            acct_repo = AccountRepo(t)

            acc = Account(STANDARD_ACCT_ID,
                          "*****@*****.**",
                          "standard",
                          "https://MOCKUNITTEST.com",
                          "1234ThisIsNotARealSub",
                          "NotDan",
                          "NotH",
                          Address(
                              "123 Dan Lane",
                              "NotDanville",
                              "CA",
                              12345,
                              "US"
                          ),
                          "fakekit")
            acct_repo.create_account(acc)

            acc = Account(ADMIN_ACCT_ID,
                          "*****@*****.**",
                          "admin",
                          "https://MOCKUNITTEST.com",
                          "5678ThisIsNotARealAdminSub",
                          "Dan",
                          "H",
                          Address(
                              "456 Dan Lane",
                              "Danville",
                              "CA",
                              12345,
                              "US"
                          ),
                          "fakekit")
            acct_repo.create_account(acc)
            t.commit()
def token_grants_admin_access(token_info):
    with Transaction() as t:
        account_repo = AccountRepo(t)
        account = account_repo.find_linked_account(token_info['iss'],
                                                   token_info['sub'])
        return account is not None and account.account_type == 'admin'
Example #29
0
 def teardown_test_data():
     with Transaction() as t:
         acct_repo = AccountRepo(t)
         acct_repo.delete_account(STANDARD_ACCT_ID)
         acct_repo.delete_account(ADMIN_ACCT_ID)
         t.commit()
Example #30
0
    def get_survey_metadata(self, sample_barcode, survey_template_id=None):
        ids = self._get_ids_relevant_to_barcode(sample_barcode)

        if ids is None:
            raise NotFound("No such barcode")

        account_id = ids.get('account_id')
        source_id = ids.get('source_id')
        sample_id = ids.get('sample_id')

        account = None
        source = None
        sample = None
        if sample_id is not None:
            sample_repo = SampleRepo(self._transaction)
            sample = sample_repo._get_sample_by_id(sample_id)

        if source_id is not None and account_id is not None:
            source_repo = SourceRepo(self._transaction)
            account_repo = AccountRepo(self._transaction)
            account = account_repo.get_account(account_id)
            source = source_repo.get_source(account_id, source_id)

        if source is None:
            raise RepoException("Barcode is not associated with a source")

        # TODO: This is my best understanding of how the data must be
        #  transformed to get the host_subject_id, needs verification that it
        #  generates the expected values for preexisting samples.
        prehash = account_id + source.name.lower()
        host_subject_id = sha512(prehash.encode()).hexdigest()

        survey_answers_repo = SurveyAnswersRepo(self._transaction)
        answer_ids = survey_answers_repo.list_answered_surveys_by_sample(
            account_id, source_id, sample_id)

        answer_to_template_map = {}
        for answer_id in answer_ids:
            template_id = survey_answers_repo.find_survey_template_id(
                answer_id)
            answer_to_template_map[answer_id] = template_id

        # if a survey template is specified, filter the returned surveys
        if survey_template_id is not None:
            # TODO: This schema is so awkward for this type of query...
            answers = []
            for answer_id in answer_ids:
                if answer_to_template_map[answer_id] == survey_template_id:
                    answers.append(answer_id)

            if len(answers) == 0:
                raise NotFound("This barcode is not associated with any "
                               "surveys matching this template id")
            if len(answers) > 1:
                #  I really hope this can't happen.  (x . x)
                raise RepoException("This barcode is associated with more "
                                    "than one survey matching this template"
                                    " id")
            answer_ids = answers

        metadata_map = survey_answers_repo.build_metadata_map()

        all_survey_answers = []
        for answer_id in answer_ids:
            answer_model = survey_answers_repo.get_answered_survey(
                account_id, source_id, answer_id, "en-US")

            survey_answers = {}
            for k in answer_model:
                new_k = metadata_map[int(k)]
                survey_answers[k] = [new_k, answer_model[k]]

            all_survey_answers.append({
                "template":
                answer_to_template_map[answer_id],
                "response":
                survey_answers
            })

        pulldown = {
            "sample_barcode": sample_barcode,
            "host_subject_id": host_subject_id,
            "account": account,
            "source": source,
            "sample": sample,
            "survey_answers": all_survey_answers
        }

        return pulldown