コード例 #1
0
    def test_create_campaign_invalid(self):
        # test to verify unique constraint on title
        with Transaction() as t:
            duplicate_campaign = {
                "title": "Test Campaign",
                "associated_projects": ["1", ]
            }
            campaign_repo = CampaignRepo(t)
            with self.assertRaises(UniqueViolation):
                campaign_repo.create_campaign(**duplicate_campaign)

        # test to verify requirement of associated_projects
        with Transaction() as t:
            campaign_no_projects = {
                "title": "Unique Campaign Name"
            }
            campaign_repo = CampaignRepo(t)
            with self.assertRaises(KeyError):
                campaign_repo.create_campaign(**campaign_no_projects)

        # test to verify that associated_projects must be valid project_ids
        with Transaction() as t:
            campaign_bad_projects = {
                "title": "Unique Campaign Name",
                "associated_projects": ["-1", ]
            }
            campaign_repo = CampaignRepo(t)
            with self.assertRaises(ForeignKeyViolation):
                campaign_repo.create_campaign(**campaign_bad_projects)
コード例 #2
0
    def test_update_project(self):
        with Transaction() as t:
            admin_repo = AdminRepo(t)
            proj_id = admin_repo.create_project(
                Project(project_name=DUMMY_PROJ_NAME,
                        is_microsetta=False,
                        bank_samples=False))
            t.commit()

        # create post input json
        input_json = json.dumps(self.FULL_PROJ_INFO)

        # execute project put (update)
        response = self.client.put(f"/api/admin/projects/{proj_id}",
                                   content_type='application/json',
                                   data=input_json,
                                   headers=MOCK_HEADERS)

        # check response code
        self.assertEqual(204, response.status_code)

        with Transaction() as t:
            with t.dict_cursor() as cur:
                cur.execute(
                    "select * FROM project "
                    "WHERE "
                    "project_id = %s", (proj_id, ))
                row = cur.fetchone()
                stored_result = dict(row)

        expected_result = self.FULL_PROJ_INFO.copy()
        expected_result["project"] = expected_result.pop("project_name")
        expected_result["project_id"] = proj_id
        self.assertEqual(expected_result, stored_result)
コード例 #3
0
def put_interested_user_address_update(body):
    interested_user_id = body['interested_user_id']
    email = body['email']

    valid_data = _validate_iuid_and_email_syntax(interested_user_id, email)
    if not valid_data:
        return jsonify(
            code=404,
            message="Invalid user."
        ), 404
    else:
        with Transaction() as t:
            i_u_repo = InterestedUserRepo(t)
            interested_user = \
                i_u_repo.get_interested_user_by_id(interested_user_id)

            valid_user = _validate_user_match(interested_user, email)
            if not valid_user:
                return jsonify(
                    code=404,
                    message="Invalid user."
                ), 404
            else:
                # reset address_checked flag so the verify_address() function
                # can run and update with Melissa-generated results
                interested_user.address_checked = False
                interested_user.address_1 = body['address_1']
                interested_user.address_2 = body['address_2']
                interested_user.city = body['city']
                interested_user.state = body['state']
                interested_user.postal_code = body['postal']
                update_success = \
                    i_u_repo.update_interested_user(interested_user)

                if update_success is False:
                    return jsonify(
                        code=400,
                        message="Failed to update address."
                    ), 400
                t.commit()

        # open new transaction so we don't lose user data if there's a problem
        # with address validation
        with Transaction() as t:
            interested_user_repo = InterestedUserRepo(t)
            try:
                interested_user_repo.verify_address(interested_user_id)
            except RepoException:
                # we really shouldn't reach this point, but just in case
                return jsonify(
                    code=400,
                    message="Failed to verify address."
                ), 400

            t.commit()

        return jsonify(user_id=interested_user_id), 200
コード例 #4
0
 def test_code_nondeterminism(self):
     email1 = "*****@*****.**"
     with Transaction() as t:
         activations = ActivationRepo(t)
         code1 = activations.get_activation_code(email1)
         t.rollback()
     with Transaction() as t:
         activations = ActivationRepo(t)
         code2 = activations.get_activation_code(email1)
         t.rollback()
     self.assertNotEqual(code1, code2)
コード例 #5
0
    def test_create_myfoodrepo_id_bad_source_or_account(self):
        # transaction needs to be created each time as the FK violation
        # disrupts the active transaction
        with Transaction() as t:
            template_repo = SurveyTemplateRepo(t)
            with self.assertRaises(ForeignKeyViolation):
                template_repo.create_myfoodrepo_entry(str(uuid.uuid4()),
                                                      TEST2_SOURCE_ID)

        with Transaction() as t:
            template_repo = SurveyTemplateRepo(t)
            with self.assertRaises(ForeignKeyViolation):
                template_repo.create_myfoodrepo_entry(TEST2_ACCOUNT_ID,
                                                      str(uuid.uuid4()))
コード例 #6
0
 def test_retrieve_diagnostics_by_barcode_nonexistent(self):
     with Transaction() as t:
         admin_repo = AdminRepo(t)
         # Uhh, should this return a 404 not found or just an empty
         # diagnostic object...?
         diag = admin_repo.retrieve_diagnostics_by_barcode('NotABarcode :D')
         self.assertIsNone(diag)
コード例 #7
0
def top_food_report(account_id, source_id, survey_id, token_info):
    _validate_account_access(token_info, account_id)

    with Transaction() as t:
        vioscreen_repo = VioscreenRepo(t)

        # Vioscreen username is our survey_id
        status = vioscreen_repo.get_vioscreen_status(account_id, source_id,
                                                     survey_id)
        if status != 3:
            # Oops, we don't have results available for this one
            raise NotFound("No such survey recorded")

        vio = VioscreenAdminAPI()
        sessions = vio.sessions(survey_id)
        # Looks like vioscreen supports multiple sessions per user, do we care?
        session_id = sessions[0]['sessionId']
        report = vio.top_food_report(session_id)

        response = make_response(report)
        response.headers.set("Content-Type", "application/pdf")
        # TODO: Do we want it to download a file or be embedded in the html?
        # response.headers.set('Content-Disposition',
        #                      'attachment',
        #                      filename='top-food-report.pdf')

        return response
コード例 #8
0
def _submit_vioscreen_status(account_id, source_id, info_str):
    # get information out of encrypted vioscreen url
    info = vioscreen.decode_key(info_str).decode("utf-8")
    vio_info = {}
    for keyval in info.split("&"):
        key, val = keyval.split("=")
        vio_info[key] = val

    with Transaction() as t:
        vio_repo = VioscreenRepo(t)

        # Add the status to the survey
        vio_repo.upsert_vioscreen_status(account_id, source_id,
                                         vio_info["username"],
                                         int(vio_info["status"]))
        t.commit()

    response = flask.Response()
    response.status_code = 201
    # TODO FIXME HACK:  This location can't actually return any info about ffq!
    #  But I need SOME response that contains the survey_id or client can't
    #  associate the survey with a sample.
    response.headers['Location'] = '/api/accounts/%s' \
                                   '/sources/%s' \
                                   '/surveys/%s' % \
                                   (account_id,
                                    source_id,
                                    vio_info["username"])
    return response
コード例 #9
0
def read_survey_templates(account_id, source_id, language_tag, token_info):
    _validate_account_access(token_info, account_id)

    # TODO: I don't think surveys have names... only survey groups have names.
    #  So what can I pass down to the user that will make any sense here?

    # Note to future maintainers,
    # 2/21/20: currently the only way to figure this out
    # is to look through the "surveys" and "survey_group" tables, try:
    # select survey_id, american from surveys left join survey_group on
    # survey_group = group_order;

    with Transaction() as t:
        source_repo = SourceRepo(t)
        source = source_repo.get_source(account_id, source_id)
        if source is None:
            return jsonify(code=404, message="No source found"), 404
        template_repo = SurveyTemplateRepo(t)
        if source.source_type == Source.SOURCE_TYPE_HUMAN:
            return jsonify([
                template_repo.get_survey_template_link_info(x)
                for x in [1, 3, 4, 5, 6, SurveyTemplateRepo.VIOSCREEN_ID]
            ]), 200
        elif source.source_type == Source.SOURCE_TYPE_ANIMAL:
            return jsonify([
                template_repo.get_survey_template_link_info(x) for x in [2]
            ]), 200
        else:
            return jsonify([]), 200
コード例 #10
0
    def test_add_transaction_duplicate(self):
        with Transaction() as t:
            r = UserTransaction(t)
            r.add_transaction(TRANSACTION_ONE_ITEM)

            with self.assertRaises(UniqueViolation):
                r.add_transaction(TRANSACTION_ONE_ITEM)
コード例 #11
0
def project_statistics_detailed(token_info, project_id):
    validate_admin_access(token_info)

    with Transaction() as t:
        admin_repo = AdminRepo(t)
        summary = admin_repo.get_project_detailed_statistics(project_id)
        return jsonify(summary), 200
コード例 #12
0
    def test_get_survey(self):
        with Transaction() as t:
            admin_repo = AdminRepo(t)

            BARCODE = '000004216'

            with self.assertRaises(NotFound):
                admin_repo.get_survey_metadata("NOTABARCODE")

            meta = admin_repo.get_survey_metadata(BARCODE,
                                                  survey_template_id=1)

            self.assertEqual(meta['sample_barcode'], BARCODE)
            self.assertIn('host_subject_id', meta)
            # And there should be one survey answered
            self.assertEqual(len(meta['survey_answers']), 1)

            all_meta = admin_repo.get_survey_metadata(BARCODE)

            self.assertEqual(all_meta['sample_barcode'], BARCODE)
            self.assertEqual(all_meta['host_subject_id'],
                             all_meta['host_subject_id'])
            # And there should be more than one survey answered
            self.assertGreater(len(all_meta['survey_answers']), 1)

            # And the meta survey should exist somewhere in all_meta
            found = False
            for survey in all_meta['survey_answers']:
                if "1" in survey["response"] and \
                        survey["response"]["1"][0] == 'DIET_TYPE':
                    found = True
                    self.assertDictEqual(meta['survey_answers'][0],
                                         survey)
            self.assertTrue(found)
コード例 #13
0
    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)
コード例 #14
0
 def test_get_mpeds_does_not_exist(self):
     with Transaction() as t:
         s = VioscreenSessionRepo(t)
         s.upsert_session(VIOSCREEN_SESSION)
         r = VioscreenMPedsRepo(t)
         obs = r.get_mpeds('does not exist')
         self.assertEqual(obs, None)
コード例 #15
0
    def test_create_project(self):
        with Transaction() as t:
            admin_repo = AdminRepo(t)
            with t.cursor() as cur:
                cur.execute("SELECT project "
                            "FROM barcodes.project "
                            "WHERE project = 'doesnotexist'")
                self.assertEqual(len(cur.fetchall()), 0)

                admin_repo.create_project('doesnotexist', True, False)
                cur.execute("SELECT project, is_microsetta, bank_samples, "
                            "plating_start_date "
                            "FROM barcodes.project "
                            "WHERE project = 'doesnotexist'")
                obs = cur.fetchall()
                self.assertEqual(obs, [
                    ('doesnotexist', True, False, None),
                ])

                plating_start_date = date(2020, 7, 31)
                admin_repo.create_project('doesnotexist2', False, True,
                                          plating_start_date)
                cur.execute("SELECT project, is_microsetta, bank_samples, "
                            "plating_start_date "
                            "FROM barcodes.project "
                            "WHERE project = 'doesnotexist2'")
                obs = cur.fetchall()
                self.assertEqual(obs, [
                    ('doesnotexist2', False, True, plating_start_date),
                ])
コード例 #16
0
    def test_create_project_success_full(self):
        with Transaction() as t:
            admin_repo = AdminRepo(t)
            # Note: using dict_cursor here so results are DictRow
            # objects that can easily be converted to a dictionary
            with t.dict_cursor() as cur:
                cur.execute("SELECT project "
                            "FROM barcodes.project "
                            "WHERE project = 'full_test_proj'")
                self.assertEqual(len(cur.fetchall()), 0)

                full_project_dict = self._FULL_PROJECT_DICT.copy()
                full_project_dict[p.PROJ_NAME_KEY] = 'full_test_proj'
                input = p.Project.from_dict(full_project_dict)

                output_id = admin_repo.create_project(input)

                cur.execute("SELECT * "
                            "FROM barcodes.project "
                            "WHERE project = 'full_test_proj'")
                row = cur.fetchone()
                obs_dict = dict(row)
                full_project_dict["project_id"] = output_id
                full_project_dict[p.DB_PROJ_NAME_KEY] = \
                    full_project_dict.pop(p.PROJ_NAME_KEY)
                self.assertEqual(obs_dict, full_project_dict)
コード例 #17
0
    def test_get_fundrazr_transactions(self):
        # integration test, verify we can pull from fundrazr and insert
        # real obtained data

        # we should have zero transactions as test database doesn't have any
        # resident
        now = datetime.datetime.now()
        with Transaction() as t:
            ut = UserTransaction(t)
            obs = ut.get_transactions(before=now)
            self.assertEqual(obs, [])

            get_fundrazr_transactions(test_transaction=t)

            obs = ut.get_transactions(before=now)

            # staging has like 7 transactions, but let's not assume that'll be
            # true in perpetuity
            self.assertTrue(len(obs) > 0)

            # rerun to make sure we dont get more transactions, and that we
            # properly handle the lack of new transactions
            seen = len(obs)
            get_fundrazr_transactions(test_transaction=t)
            obs = ut.get_transactions(before=now)
            self.assertEqual(len(obs), seen)
コード例 #18
0
 def test_most_recent_transaction(self):
     with Transaction() as t:
         r = UserTransaction(t)
         self._load_some_transactions(r)
         obs = r.most_recent_transaction()
         exp = self.obj1
         self._payment_equal([obs, ], [exp, ])
コード例 #19
0
 def test_get_polyphenol_ffq_id_if_exists_false(self):
     with Transaction() as t:
         template_repo = SurveyTemplateRepo(t)
         obs = \
             template_repo.get_polyphenol_ffq_id_if_exists(TEST1_ACCOUNT_ID,
                                                           TEST1_SOURCE_ID)
         self.assertEqual(obs, (None, None))
コード例 #20
0
 def test_get_food_consumption_does_not_exist(self):
     with Transaction() as t:
         s = VioscreenSessionRepo(t)
         s.upsert_session(VIOSCREEN_SESSION)
         r = VioscreenFoodConsumptionRepo(t)
         obs = r.get_food_consumption('does not exist')
         self.assertEqual(obs, None)
コード例 #21
0
    def test_scan_barcode_success(self):
        with Transaction() as t:
            # TODO FIXME HACK:  Need to build mock barcodes rather than using
            #  these fixed ones

            TEST_BARCODE = '000000001'
            TEST_STATUS = "sample-has-inconsistencies"
            TEST_NOTES = "THIS IS A UNIT TEST"
            admin_repo = AdminRepo(t)

            # check that before doing a scan, no scans are recorded for this
            diag = admin_repo.retrieve_diagnostics_by_barcode(TEST_BARCODE)
            self.assertEqual(len(diag['scans_info']), 0)

            # do a scan
            admin_repo.scan_barcode(TEST_BARCODE, {
                "sample_status": TEST_STATUS,
                "technician_notes": TEST_NOTES
            })

            # show that now a scan is recorded for this barcode
            diag = admin_repo.retrieve_diagnostics_by_barcode(TEST_BARCODE)
            self.assertEqual(len(diag['scans_info']), 1)
            first_scan = diag['scans_info'][0]
            self.assertEqual(first_scan['technician_notes'], TEST_NOTES)
            self.assertEqual(first_scan['sample_status'], TEST_STATUS)
コード例 #22
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'])
コード例 #23
0
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()
コード例 #24
0
def sample_pulldown_multiple_survey(token_info, sample_barcode):
    validate_admin_access(token_info)

    with Transaction() as t:
        admin_repo = AdminRepo(t)
        sample_pulldown = admin_repo.get_survey_metadata(sample_barcode)
    return jsonify(sample_pulldown), 200
コード例 #25
0
def create_dummy_answered_survey(dummy_acct_id, dummy_source_id,
                                 survey_template_id=PRIMARY_SURVEY_TEMPLATE_ID,
                                 survey_answers_id=DUMMY_ANSWERED_SURVEY_ID,
                                 survey_model=None, dummy_sample_id=None):

    if survey_model is None:
        survey_model = DUMMY_SURVEY_ANSWERS_MODEL

    with Transaction() as t:
        survey_answers_repo = SurveyAnswersRepo(t)
        survey_answers_id = survey_answers_repo.submit_answered_survey(
            dummy_acct_id,
            dummy_source_id,
            localization.EN_US,
            survey_template_id,
            survey_model,
            survey_answers_id
        )

        if dummy_sample_id is not None:
            survey_answers_repo.associate_answered_survey_with_sample(
                dummy_acct_id, dummy_source_id, dummy_sample_id,
                survey_answers_id)

        t.commit()

    return survey_answers_id
コード例 #26
0
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()
コード例 #27
0
def create_project(body, token_info):
    validate_admin_access(token_info)

    project_name = body['project_name']
    is_microsetta = body['is_microsetta']
    bank_samples = body['bank_samples']
    plating_start_date = body.get('plating_start_date')

    if plating_start_date is not None:
        try:
            plating_start_date = datetime.datetime.strptime(
                plating_start_date, "%Y-%m-%d")
        except ValueError:
            raise BadRequest(
                "plating start date '{0}' is not a valid date in YYYY-MM-DD "
                "format".format(plating_start_date))

    if len(project_name) == 0:
        return jsonify(code=400, message="No project name provided"), 400

    if not bank_samples and plating_start_date is not None:
        raise RepoException("Plating start date cannot be set for"
                            " unbanked projects")

    with Transaction() as t:
        admin_repo = AdminRepo(t)
        admin_repo.create_project(project_name, is_microsetta, bank_samples,
                                  plating_start_date)
        t.commit()

    return {}, 201
コード例 #28
0
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()
コード例 #29
0
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
コード例 #30
0
def submit_answered_survey(account_id, source_id, language_tag, body,
                           token_info):
    _validate_account_access(token_info, account_id)

    if body['survey_template_id'] == SurveyTemplateRepo.VIOSCREEN_ID:
        return _submit_vioscreen_status(account_id, source_id,
                                        body["survey_text"]["key"])

    # TODO: Is this supposed to return new survey id?
    # TODO: Rename survey_text to survey_model/model to match Vue's naming?
    with Transaction() as t:
        survey_answers_repo = SurveyAnswersRepo(t)
        survey_answers_id = survey_answers_repo.submit_answered_survey(
            account_id, source_id, language_tag, body["survey_template_id"],
            body["survey_text"])
        t.commit()

        response = flask.Response()
        response.status_code = 201
        response.headers['Location'] = '/api/accounts/%s' \
                                       '/sources/%s' \
                                       '/surveys/%s' % \
                                       (account_id,
                                        source_id,
                                        survey_answers_id)
        return response