Пример #1
0
def setup_trial_and_user(cidc_api, monkeypatch) -> int:
    """
    Insert a trial and a cimac-user into the database, and set the user
    as the current user.
    """
    # this is necessary for adding/removing permissions from this user
    # without trying to contact GCP
    mock_gcloud_client(monkeypatch)

    user = Users(email=user_email,
                 role=CIDCRole.CIMAC_USER.value,
                 approval_date=datetime.now())
    mock_current_user(user, monkeypatch)

    with cidc_api.app_context():
        TrialMetadata(
            trial_id="test_trial",
            metadata_json={
                prism.PROTOCOL_ID_FIELD_NAME: trial_id,
                "participants": [],
                "allowed_cohort_names": ["Arm_Z"],
                "allowed_collection_event_names": [],
            },
        ).insert()

        user.insert()
        return user.id
Пример #2
0
def mock_admin_user(cidc_api, monkeypatch) -> int:
    user = Users(**{**users["json"], "email": "*****@*****.**", "id": None})
    mock_current_user(user, monkeypatch)

    with cidc_api.app_context():
        user.insert()
        return user.id
Пример #3
0
def test_poll_upload_merge_status(cidc_api, clean_db, monkeypatch):
    """
    Check pull_upload_merge_status endpoint behavior
    """
    user_id = setup_trial_and_user(cidc_api, monkeypatch)
    with cidc_api.app_context():
        user = Users.find_by_id(user_id)
    make_cimac_biofx_user(user_id, cidc_api)

    metadata = {PROTOCOL_ID_FIELD_NAME: trial_id}

    with cidc_api.app_context():
        other_user = Users(email="*****@*****.**")
        other_user.insert()
        upload_job = UploadJobs.create(
            upload_type="wes",
            uploader_email=user.email,
            gcs_file_map={},
            metadata=metadata,
            gcs_xlsx_uri="",
        )
        upload_job.insert()
        upload_job_id = upload_job.id

    client = cidc_api.test_client()

    # Upload not found
    res = client.get(
        f"/ingestion/poll_upload_merge_status/12345?token={upload_job.token}")
    assert res.status_code == 404

    upload_job_url = (
        f"/ingestion/poll_upload_merge_status/{upload_job_id}?token={upload_job.token}"
    )

    # Upload not-yet-ready
    res = client.get(upload_job_url)
    assert res.status_code == 200
    assert "retry_in" in res.json and res.json["retry_in"] == 5
    assert "status" not in res.json

    test_details = "A human-friendly reason for this "
    for status in [
            UploadJobStatus.MERGE_COMPLETED.value,
            UploadJobStatus.MERGE_FAILED.value,
    ]:
        # Simulate cloud function merge status update
        with cidc_api.app_context():
            upload_job._set_status_no_validation(status)
            upload_job.status_details = test_details
            upload_job.update()

        # Upload ready
        res = client.get(upload_job_url)
        assert res.status_code == 200
        assert "retry_in" not in res.json
        assert "status" in res.json and res.json["status"] == status
        assert ("status_details" in res.json
                and res.json["status_details"] == test_details)
def setup_user(cidc_api, monkeypatch) -> int:
    current_user = Users(
        email="*****@*****.**",
        role=CIDCRole.CIMAC_USER.value,
        approval_date=datetime.now(),
    )
    mock_current_user(current_user, monkeypatch)

    with cidc_api.app_context():
        current_user.insert()
        return current_user.id
Пример #5
0
def test_permissions_broad_perms(clean_db, monkeypatch):
    gcloud_client = mock_gcloud_client(monkeypatch)
    user = Users(email="*****@*****.**")
    user.insert()
    trial = TrialMetadata(trial_id=TRIAL_ID, metadata_json=METADATA)
    trial.insert()
    other_trial = TrialMetadata(
        trial_id="other-trial",
        metadata_json={**METADATA, "protocol_identifier": "other-trial"},
    )
    other_trial.insert()
    for ut in ["wes_fastq", "olink"]:
        for tid in [trial.trial_id, other_trial.trial_id]:
            Permissions(
                granted_to_user=user.id,
                trial_id=tid,
                upload_type=ut,
                granted_by_user=user.id,
            ).insert()

    # Can't insert a permission for access to all trials and assays
    with pytest.raises(ValueError, match="must have a trial id or upload type"):
        Permissions(granted_to_user=user.id, granted_by_user=user.id).insert()

    # Inserting a trial-level permission should delete other more specific related perms.
    trial_query = clean_db.query(Permissions).filter(
        Permissions.trial_id == trial.trial_id
    )
    assert trial_query.count() == 2
    Permissions(
        trial_id=trial.trial_id, granted_to_user=user.id, granted_by_user=user.id
    ).insert()
    assert trial_query.count() == 1
    perm = trial_query.one()
    assert perm.trial_id == trial.trial_id
    assert perm.upload_type is None

    # Inserting an upload-level permission should delete other more specific related perms.
    olink_query = clean_db.query(Permissions).filter(Permissions.upload_type == "olink")
    assert olink_query.count() == 1
    assert olink_query.one().trial_id == other_trial.trial_id
    Permissions(
        upload_type="olink", granted_to_user=user.id, granted_by_user=user.id
    ).insert()
    assert olink_query.count() == 1
    perm = olink_query.one()
    assert perm.trial_id is None
    assert perm.upload_type == "olink"

    # Getting perms for a particular user-trial-type returns broader perms
    perm = Permissions.find_for_user_trial_type(user.id, trial.trial_id, "ihc")
    assert perm is not None and perm.upload_type is None
    perm = Permissions.find_for_user_trial_type(user.id, "some random trial", "olink")
    assert perm is not None and perm.trial_id is None
Пример #6
0
def test_user_get_data_access_report(clean_db, monkeypatch):
    """Test that user data access info is collected as expected"""
    mock_gcloud_client(monkeypatch)

    admin_user = Users(
        email="*****@*****.**",
        organization="CIDC",
        approval_date=datetime.now(),
        role=CIDCRole.ADMIN.value,
    )
    admin_user.insert()

    cimac_user = Users(
        email="*****@*****.**",
        organization="DFCI",
        approval_date=datetime.now(),
        role=CIDCRole.CIMAC_USER.value,
    )
    cimac_user.insert()

    trial = TrialMetadata(trial_id=TRIAL_ID, metadata_json=METADATA)
    trial.insert()

    upload_types = ["wes_bam", "ihc"]

    # Note that admins don't need permissions to view data,
    # so we're deliberately issuing unnecessary permissions here.
    for user in [admin_user, cimac_user]:
        for t in upload_types:
            Permissions(
                granted_to_user=user.id,
                granted_by_user=admin_user.id,
                trial_id=trial.trial_id,
                upload_type=t,
            ).insert()

    bio = io.BytesIO()
    result_df = Users.get_data_access_report(bio)
    bio.seek(0)

    # Make sure bytes were written to the BytesIO instance
    assert bio.getbuffer().nbytes > 0

    # Make sure report data has expected info
    assert set(result_df.columns) == set(
        ["email", "role", "organization", "trial_id", "permissions"]
    )
    for user in [admin_user, cimac_user]:
        user_df = result_df[result_df.email == user.email]
        assert set([user.role]) == set(user_df.role)
        assert set([user.organization]) == set(user_df.organization)
        if user == admin_user:
            assert set(["*"]) == set(user_df.permissions)
        else:
            assert set(user_df.permissions).issubset(["wes_bam,ihc", "ihc,wes_bam"])
def setup_user(cidc_api, monkeypatch) -> int:
    # this is necessary for adding/removing permissions from this user
    # without trying to contact GCP
    mock_gcloud_client(monkeypatch)

    current_user = Users(
        email="*****@*****.**",
        role=CIDCRole.CIMAC_USER.value,
        approval_date=datetime.now(),
    )
    mock_current_user(current_user, monkeypatch)

    with cidc_api.app_context():
        current_user.insert()
        return current_user.id
Пример #8
0
def test_common_count(clean_db):
    """Test counting behavior, inherited from CommonColumns"""
    num = 105
    for i in range(num):
        name = f"user_{i}"
        Users(email=f"{name}@example.com", first_n=name).insert()

    # Count without filter
    assert Users.count() == num

    # Count with filter
    def f(q):
        return q.filter(Users.first_n.like("%9%"))

    num_expected = len(list(f"user_{i}" for i in range(100) if "9" in str(i)))
    assert Users.count(filter_=f) == num_expected
Пример #9
0
def register_user(user_id, app):
    """Register the given user as a cimac-user."""
    with app.app_context():
        user = Users.find_by_id(user_id)
        user.approval_date = datetime.now()
        user.role = CIDCRole.CIMAC_USER.value
        user.update()
Пример #10
0
def test_assay_upload_ingestion_success(clean_db, monkeypatch, caplog):
    """Check that the ingestion success method works as expected"""
    caplog.set_level(logging.DEBUG)

    new_user = Users.create(PROFILE)
    trial = TrialMetadata.create(TRIAL_ID, METADATA)
    assay_upload = UploadJobs.create(
        upload_type="ihc",
        uploader_email=EMAIL,
        gcs_file_map={},
        metadata={PROTOCOL_ID_FIELD_NAME: TRIAL_ID},
        gcs_xlsx_uri="",
        commit=False,
    )

    clean_db.commit()

    # Ensure that success can't be declared from a starting state
    with pytest.raises(Exception, match="current status"):
        assay_upload.ingestion_success(trial)

    # Update assay_upload status to simulate a completed but not ingested upload
    assay_upload.status = UploadJobStatus.UPLOAD_COMPLETED.value
    assay_upload.ingestion_success(trial)

    # Check that status was updated and email wasn't sent by default
    db_record = UploadJobs.find_by_id(assay_upload.id)
    assert db_record.status == UploadJobStatus.MERGE_COMPLETED.value
    assert "Would send email with subject '[UPLOAD SUCCESS]" not in caplog.text

    # Check that email gets sent when specified
    assay_upload.ingestion_success(trial, send_email=True)
    assert "Would send email with subject '[UPLOAD SUCCESS]" in caplog.text
Пример #11
0
def test_common_insert(clean_db):
    """Test insert, inherited from CommonColumns"""
    # Check disabling committing
    u1 = Users(email="a")
    u1.insert(commit=False)
    assert not u1.id

    # Insert a new record without disabling committing
    u2 = Users(email="b")
    u2.insert()
    assert u1.id and u1._etag
    assert u2.id and u2._etag
    assert u1._etag != u2._etag

    assert Users.find_by_id(u1.id)
    assert Users.find_by_id(u2.id)
Пример #12
0
def disable_inactive_users(*args):
    """Disable any users who have become inactive."""
    with sqlalchemy_session() as session:
        print("Disabling inactive users...")
        disabled = Users.disable_inactive_users(session=session)
        for u in disabled:
            print(f"Disabled inactive: {u[0]}")
        print("done.")
Пример #13
0
def test_permissions_revoke_all_iam_permissions(clean_db, monkeypatch):
    """
    Smoke test that Permissions.revoke_all_iam_permissions calls revoke_download_access the right arguments.
    """
    gcloud_client = mock_gcloud_client(monkeypatch)
    user = Users(email="*****@*****.**")
    user.insert()
    trial = TrialMetadata(trial_id=TRIAL_ID, metadata_json=METADATA)
    trial.insert()

    upload_types = ["wes_bam", "ihc", "rna_fastq", "plasma"]
    for upload_type in upload_types:
        Permissions(
            granted_to_user=user.id,
            trial_id=trial.trial_id,
            upload_type=upload_type,
            granted_by_user=user.id,
        ).insert()

    Permissions.revoke_all_iam_permissions()
    gcloud_client.revoke_download_access.assert_has_calls(
        [call(user.email, trial.trial_id, upload_type) for upload_type in upload_types]
    )

    # not called on admins or nci biobank users
    gcloud_client.revoke_download_access.reset_mock()
    for role in [CIDCRole.ADMIN.value, CIDCRole.NCI_BIOBANK_USER.value]:
        user.role = role
        user.update()
        Permissions.revoke_all_iam_permissions()
        gcloud_client.revoke_download_access.assert_not_called()
Пример #14
0
def setup_upload_jobs(cidc_api) -> Tuple[int, int]:
    """
    Insert two uploads into the database created by different users
    and return their IDs.
    """
    with cidc_api.app_context():
        other_user = Users(email="*****@*****.**")
        other_user.insert()

        job1 = UploadJobs(
            uploader_email=user_email,
            trial_id=trial_id,
            status=UploadJobStatus.STARTED.value,
            metadata_patch={
                "test": {
                    "upload_placeholder": "baz"
                },
                "test2": "foo"
            },
            upload_type="",
            gcs_xlsx_uri="",
            gcs_file_map={"bip": "baz"},
            multifile=False,
        )
        job2 = UploadJobs(
            uploader_email=other_user.email,
            trial_id=trial_id,
            status=UploadJobStatus.STARTED.value,
            metadata_patch={
                "array": [{
                    "upload_placeholder": "baz"
                }, {
                    "test2": "foo"
                }]
            },
            upload_type="",
            gcs_xlsx_uri="",
            gcs_file_map={"bip": "baz"},
            multifile=False,
        )

        job1.insert()
        job2.insert()

        return job1.id, job2.id
Пример #15
0
def setup_users(cidc_api, monkeypatch, registered=True) -> Tuple[int, int]:
    """
    Insert two users into the database. If `registered=False`, don't
    register the first user.
    """
    current_user = Users(id=1, email="*****@*****.**")
    other_user = Users(id=2, email="*****@*****.**")

    mock_current_user(current_user, monkeypatch)

    with cidc_api.app_context():
        if registered:
            current_user.role = CIDCRole.CIMAC_USER.value
            current_user.approval_date = datetime.now()
        current_user.insert()
        other_user.insert()

        return current_user.id, other_user.id
Пример #16
0
def test_merge_extra_metadata(cidc_api, clean_db, monkeypatch):
    """Ensure merging of extra metadata follows the expected execution flow"""
    user_id = setup_trial_and_user(cidc_api, monkeypatch)
    with cidc_api.app_context():
        user = Users.find_by_id(user_id)
    make_cimac_biofx_user(user_id, cidc_api)

    with cidc_api.app_context():
        assay_upload = UploadJobs.create(
            upload_type="assay_with_extra_md",
            uploader_email=user.email,
            gcs_file_map={},
            metadata={
                PROTOCOL_ID_FIELD_NAME: trial_id,
                "whatever": {
                    "hierarchy": [
                        {
                            "we just need a": "uuid-1",
                            "to be able": "to merge"
                        },
                        {
                            "and": "uuid-2"
                        },
                    ]
                },
            },
            gcs_xlsx_uri="",
            commit=False,
        )
        assay_upload.id = 137
        assay_upload.insert()

        custom_extra_md_parse = MagicMock()
        custom_extra_md_parse.side_effect = lambda f: {
            "extra_md": f.read().decode()
        }
        monkeypatch.setattr(
            "cidc_schemas.prism.merger.EXTRA_METADATA_PARSERS",
            {"assay_with_extra_md": custom_extra_md_parse},
        )

        form_data = {
            "job_id": 137,
            "uuid-1": (io.BytesIO(b"fake file 1"), "fname1"),
            "uuid-2": (io.BytesIO(b"fake file 2"), "fname2"),
        }

        client = cidc_api.test_client()
        res = client.post("/ingestion/extra-assay-metadata", data=form_data)
        assert res.status_code == 200
        assert custom_extra_md_parse.call_count == 2

        fetched_jobs = UploadJobs.list()
        assert 1 == len(fetched_jobs)
        au = fetched_jobs[0]
        assert "extra_md" in au.metadata_patch["whatever"]["hierarchy"][0]
        assert "extra_md" in au.metadata_patch["whatever"]["hierarchy"][1]
Пример #17
0
def setup_db_records(cidc_api):
    extra = {"_etag": ETAG}
    with cidc_api.app_context():
        Users(**users["json"], **extra).insert(compute_etag=False)
        TrialMetadata(**trial_metadata["json"], **extra).insert(compute_etag=False)
        DownloadableFiles(**downloadable_files["json"], **extra).insert(
            compute_etag=False
        )
        Permissions(**permissions["json"], **extra).insert(compute_etag=False)
        UploadJobs(**upload_jobs["json"], **extra).insert(compute_etag=False)
Пример #18
0
def test_permissions_delete(clean_db, monkeypatch, caplog):
    gcloud_client = mock_gcloud_client(monkeypatch)
    user = Users(email="*****@*****.**")
    user.insert()
    trial = TrialMetadata(trial_id=TRIAL_ID, metadata_json=METADATA)
    trial.insert()
    perm = Permissions(
        granted_to_user=user.id,
        trial_id=trial.trial_id,
        upload_type="wes_bam",
        granted_by_user=user.id,
    )
    perm.insert()

    # Deleting a record by a user doesn't exist leads to an error
    gcloud_client.reset_mocks()
    with pytest.raises(NoResultFound, match="no user with id"):
        perm.delete(deleted_by=999999)

    # Deletion of an existing permission leads to no error
    gcloud_client.reset_mocks()
    with caplog.at_level(logging.DEBUG):
        perm.delete(deleted_by=user.id)
    gcloud_client.revoke_download_access.assert_called_once()
    gcloud_client.grant_download_access.assert_not_called()
    assert any(
        log_record.message.strip()
        == f"admin-action: {user.email} removed from {user.email} the permission wes_bam on {trial.trial_id}"
        for log_record in caplog.records
    )

    # Deleting an already-deleted record is idempotent
    gcloud_client.reset_mocks()
    perm.delete(deleted_by=user)
    gcloud_client.revoke_download_access.assert_called_once()
    gcloud_client.grant_download_access.assert_not_called()

    # Deleting a record whose user doesn't exist leads to an error
    gcloud_client.reset_mocks()
    with pytest.raises(NoResultFound, match="no user with id"):
        Permissions(granted_to_user=999999).delete(deleted_by=user)

    gcloud_client.revoke_download_access.assert_not_called()
    gcloud_client.grant_download_access.assert_not_called()

    # If revoking a permission from a "network-viewer", no GCS IAM actions are taken
    gcloud_client.revoke_download_access.reset_mock()
    user.role = CIDCRole.NETWORK_VIEWER.value
    user.update()
    perm = Permissions(
        granted_to_user=user.id,
        trial_id=trial.trial_id,
        upload_type="ihc",
        granted_by_user=user.id,
    )
    perm.insert()
    perm.delete(deleted_by=user)
    gcloud_client.revoke_download_access.assert_not_called()
Пример #19
0
def test_get_self(cidc_api, clean_db, monkeypatch):
    """Check that get self returns the current user's info."""
    user_id, _ = setup_users(cidc_api, monkeypatch, registered=False)

    with cidc_api.app_context():
        user = Users.find_by_id(user_id)

    client = cidc_api.test_client()

    res = client.get("users/self")
    assert res.status_code == 200
    assert res.json == UserSchema().dump(user)
Пример #20
0
def refresh_download_permissions(*args):
    """
    Extend the expiry date for GCS download permissions belonging to users
    who accessed the system in the last 2 (or so) days. If we don't do this, 
    users whose accounts are still active might lose GCS download permission prematurely.
    """
    active_today = lambda q: q.filter(
        # Provide a 3 day window to ensure we don't miss anyone
        # if, e.g., this function fails to run on a certain day.
        Users._accessed
        > datetime.today() - timedelta(days=3)
    )
    with sqlalchemy_session() as session:
        active_users = Users.list(
            page_size=Users.count(session=session, filter_=active_today),
            session=session,
            filter_=active_today,
        )
        for user in active_users:
            print(f"Refreshing IAM download permissions for {user.email}")
            Permissions.grant_iam_permissions(user, session=session)
Пример #21
0
def test_filter_user_lookups(app, db, monkeypatch):
    """Check user GET-request role-based filtering"""
    monkeypatch.setattr(app.auth, "token_auth", fake_token_auth)

    client = app.test_client()

    # Create two new users
    with app.app_context():
        Users.create(profile)
        Users.create(other_profile)

    # Check that a user can only look themselves up
    response = client.get(USERS, headers=AUTH_HEADER)
    assert response.status_code == 200
    users = response.json["_items"]
    assert len(users) == 1
    assert users[0]["email"] == profile["email"]

    filtered_response = client.get(
        USERS + '?where{"email": "%s"}' % EMAIL, headers=AUTH_HEADER
    )
    assert filtered_response.status_code == 200
    assert filtered_response.json["_items"] == response.json["_items"]

    # If the user tries to look up someone else, they get nothing back
    response = client.get(
        USERS + '?where={"email": "%s"}' % other_profile["email"], headers=AUTH_HEADER
    )
    assert response.status_code == 200
    assert len(response.json["_items"]) == 0

    # Make a user an admin
    with app.app_context():
        db.query(Users).filter_by(email=EMAIL).update({"role": "cidc-admin"})
        db.commit()

    # Admins should be able to list all users
    response = client.get(USERS, headers=AUTH_HEADER)
    assert response.status_code == 200
    assert len(response.json["_items"]) == 2
Пример #22
0
def test_create_upload_job(db):
    """Try to create an upload job"""
    new_user = Users.create(PROFILE)

    gcs_file_uris = ["my/first/wes/blob1", "my/first/wes/blob2"]
    metadata_json_patch = {"foo": "bar"}

    # Create a fresh upload job
    new_job = UploadJobs.create("dummy_assay", EMAIL, gcs_file_uris,
                                metadata_json_patch)
    job = UploadJobs.find_by_id(new_job.id)
    assert_same_elements(new_job.gcs_file_uris, job.gcs_file_uris)
    assert job.status == "started"
Пример #23
0
def test_permissions_grant_iam_permissions(clean_db, monkeypatch):
    """
    Smoke test that Permissions.grant_iam_permissions calls grant_download_access with the right arguments.
    """
    refresh_intake_access = MagicMock()
    monkeypatch.setattr(
        "cidc_api.models.models.refresh_intake_access", refresh_intake_access
    )

    gcloud_client = mock_gcloud_client(monkeypatch)
    user = Users(email="*****@*****.**", role=CIDCRole.NETWORK_VIEWER.value)
    user.insert()
    trial = TrialMetadata(trial_id=TRIAL_ID, metadata_json=METADATA)
    trial.insert()

    upload_types = ["wes_bam", "ihc", "rna_fastq", "plasma"]
    for upload_type in upload_types:
        Permissions(
            granted_to_user=user.id,
            trial_id=trial.trial_id,
            upload_type=upload_type,
            granted_by_user=user.id,
        ).insert()

    # IAM permissions not granted to network viewers
    Permissions.grant_iam_permissions(user=user)
    gcloud_client.grant_download_access.assert_not_called()

    # IAM permissions should be granted for any other role
    user.role = CIDCRole.CIMAC_USER.value
    Permissions.grant_iam_permissions(user=user)
    for upload_type in upload_types:
        assert (
            call(user.email, trial.trial_id, upload_type)
            in gcloud_client.grant_download_access.call_args_list
        )

    refresh_intake_access.assert_called_once_with(user.email)
Пример #24
0
def setup_permissions(cidc_api, monkeypatch) -> Tuple[int, int]:
    """
    Create two users, one trial, and three permissions in `db`.
    Two permissions will belong to the first user, and the third will
    belong to the second one. Returns the first and second user ids 
    as a tuple.
    """
    current_user = Users(
        id=1,
        email="*****@*****.**",
        role=CIDCRole.CIMAC_USER.value,
        approval_date=datetime.now(),
    )
    other_user = Users(id=2, email="*****@*****.**")

    mock_current_user(current_user, monkeypatch)

    with cidc_api.app_context():
        # Create users
        current_user.insert()
        other_user.insert()

        # Create trial
        TrialMetadata.create(
            TRIAL_ID,
            {
                "protocol_identifier": TRIAL_ID,
                "allowed_collection_event_names": [],
                "allowed_cohort_names": [],
                "participants": [],
            },
        )

        # Create permissions
        def create_permission(uid, assay):
            Permissions(
                granted_by_user=uid,
                granted_to_user=uid,
                trial_id=TRIAL_ID,
                upload_type=assay,
            ).insert()

        create_permission(current_user.id, "ihc")
        create_permission(current_user.id, "olink")
        create_permission(other_user.id, "olink")

        return current_user.id, other_user.id
Пример #25
0
def test_authenticate_and_get_user(cidc_api, monkeypatch):
    """Check that authenticate_and_get_user works as expected"""
    # Auth success
    monkeypatch.setattr("cidc_api.shared.auth.check_auth", lambda *args: True)
    test_user = Users(email="*****@*****.**")
    with cidc_api.app_context():
        auth._set_current_user(test_user)
        user = auth.authenticate_and_get_user()
        assert user == test_user

    # Auth failure
    monkeypatch.setattr("cidc_api.shared.auth.check_auth",
                        make_raiser(Unauthorized))
    user = auth.authenticate_and_get_user()
    assert user is None
Пример #26
0
def test_user_confirm_approval(clean_db, monkeypatch):
    """Ensure that users are notified when their account goes from pending to approved."""
    confirm_account_approval = MagicMock()
    monkeypatch.setattr(
        "cidc_api.shared.emails.confirm_account_approval", confirm_account_approval
    )

    user = Users(email="*****@*****.**")
    user.insert()

    # The confirmation email shouldn't be sent for updates unrelated to account approval
    user.update(changes={"first_n": "foo"})
    confirm_account_approval.assert_not_called()

    # The confirmation email should be sent for updates related to account approval
    user.update(changes={"approval_date": datetime.now()})
    confirm_account_approval.assert_called_once_with(user, send_email=True)
Пример #27
0
def test_add_approval_date(app, db, monkeypatch):
    """Test that a user's approval_date is updated when their role is changed for the first time."""
    monkeypatch.setattr(app.auth, "token_auth", fake_token_auth)

    # Create one registered admin and one new user
    with app.app_context():
        db.add(Users(role="cidc-admin", approval_date=datetime.now(), **profile))
        db.commit()
        Users.create(other_profile)

    client = app.test_client()

    def get_new_user():
        response = client.get(
            USERS + '?where={"email": "%s"}' % other_profile["email"],
            headers=AUTH_HEADER,
        )
        return response.json["_items"][0]

    def update_role_and_get_approval_date(role: str):
        new_user = get_new_user()
        response = client.patch(
            f"{USERS}/{new_user['id']}",
            headers={**AUTH_HEADER, "If-Match": new_user["_etag"]},
            json={"role": role},
        )
        assert response.status_code == 200
        updated_new_user = get_new_user()
        approval_date = updated_new_user.get("approval_date")
        assert approval_date is not None
        return approval_date

    # Approval date should be set on first role update
    first_approval = update_role_and_get_approval_date("developer")
    second_approval = update_role_and_get_approval_date("cidc-admin")
    assert first_approval == second_approval
Пример #28
0
def test_upload_job_no_file_map(clean_db):
    """Try to create an assay upload"""
    new_user = Users.create(PROFILE)

    metadata_patch = {PROTOCOL_ID_FIELD_NAME: TRIAL_ID}
    gcs_xlsx_uri = "xlsx/assays/wes/12:0:1.5123095"

    TrialMetadata.create(TRIAL_ID, METADATA)

    new_job = UploadJobs.create(
        prism.SUPPORTED_MANIFESTS[0], EMAIL, None, metadata_patch, gcs_xlsx_uri
    )
    assert list(new_job.upload_uris_with_data_uris_with_uuids()) == []

    job = UploadJobs.find_by_id_and_email(new_job.id, PROFILE["email"])
    assert list(job.upload_uris_with_data_uris_with_uuids()) == []
Пример #29
0
def test_assay_upload_merge_extra_metadata(clean_db, monkeypatch):
    """Try to create an assay upload"""
    new_user = Users.create(PROFILE)

    TrialMetadata.create(TRIAL_ID, METADATA)

    assay_upload = UploadJobs.create(
        upload_type="assay_with_extra_md",
        uploader_email=EMAIL,
        gcs_file_map={},
        metadata={
            PROTOCOL_ID_FIELD_NAME: TRIAL_ID,
            "whatever": {
                "hierarchy": [
                    {"we just need a": "uuid-1", "to be able": "to merge"},
                    {"and": "uuid-2"},
                ]
            },
        },
        gcs_xlsx_uri="",
        commit=False,
    )
    assay_upload.id = 111
    clean_db.commit()

    custom_extra_md_parse = MagicMock()
    custom_extra_md_parse.side_effect = lambda f: {"extra": f.read().decode()}
    monkeypatch.setattr(
        "cidc_schemas.prism.merger.EXTRA_METADATA_PARSERS",
        {"assay_with_extra_md": custom_extra_md_parse},
    )

    UploadJobs.merge_extra_metadata(
        111,
        {
            "uuid-1": io.BytesIO(b"within extra md file 1"),
            "uuid-2": io.BytesIO(b"within extra md file 2"),
        },
        session=clean_db,
    )

    assert 1 == clean_db.query(UploadJobs).count()
    au = clean_db.query(UploadJobs).first()
    assert "extra" in au.metadata_patch["whatever"]["hierarchy"][0]
    assert "extra" in au.metadata_patch["whatever"]["hierarchy"][1]
Пример #30
0
def test_check_auth_smoketest(monkeypatch, cidc_api):
    """Check that authentication succeeds if no errors are thrown"""
    # No authentication errors
    monkeypatch.setattr(auth, "authenticate", lambda: PAYLOAD)

    # No authorization errors
    def fake_role_auth(*args):
        auth._set_current_user(Users(email=EMAIL))
        return True

    monkeypatch.setattr(auth, "authorize", fake_role_auth)
    # No database errors
    monkeypatch.setattr("cidc_api.models.Users.create",
                        lambda: Users(email=EMAIL))
    # Authentication should succeed
    with cidc_api.test_request_context("/"):
        authenticated = auth.check_auth([], RESOURCE, "GET")
        assert authenticated
        assert auth.get_current_user().email == EMAIL