Example #1
0
def test_invite_without_email(client):
    """The email is required."""
    user_no_email = first_new_user.copy()
    user_no_email.pop("email")

    for inviter in ["superadmin", "unitadmin", "unituser"]:
        # Attempt invite
        response = client.post(
            tests.DDSEndpoint.USER_ADD,
            headers=tests.UserAuth(
                tests.USER_CREDENTIALS[inviter]).token(client),
            json=user_no_email,
            # query_string={"project": existing_project},
        )

        # There should be an error message
        assert response.status_code == http.HTTPStatus.BAD_REQUEST
        assert "Email address required to add or invite." in response.json[
            "message"]
Example #2
0
def test_del_request_others_unprivileged(client):
    """Unprivileged deletion request"""

    email_to_delete = "*****@*****.**"

    # with pytest.raises(ddserr.AccessDeniedError):
    response = client.delete(
        tests.DDSEndpoint.USER_DELETE,
        headers=tests.UserAuth(
            tests.USER_CREDENTIALS["delete_me_unituser"]).token(client),
        json={"email": email_to_delete},
    )
    assert response.status_code == http.HTTPStatus.FORBIDDEN

    # verify that user was not deleted
    exists = user_from_email(email_to_delete)
    assert exists is not None
    assert type(exists).__name__ == "UnitUser"
    assert exists.primary_email == email_to_delete
Example #3
0
def test_del_request_others_self(client):
    """Unit Admin tries to instantly self-delete via this endpoint"""

    email_to_delete = "*****@*****.**"

    # with pytest.raises(ddserr.UserDeletionError):
    response = client.delete(
        tests.DDSEndpoint.USER_DELETE,
        headers=tests.UserAuth(
            tests.USER_CREDENTIALS["delete_me_unitadmin"]).token(client),
        json={"email": email_to_delete},
    )
    assert response.status_code == http.HTTPStatus.BAD_REQUEST

    # verify that user was not deleted
    exists = user_from_email(email_to_delete)
    assert exists is not None
    assert type(exists).__name__ == "UnitUser"
    assert exists.primary_email == email_to_delete
Example #4
0
def test_new_file_sizeprocessed_bigint(client):
    """Add huge file."""

    project_1 = project_row(project_id="file_testing_project")
    assert project_1

    file_sizeprocessed_bigint = FIRST_NEW_FILE.copy()
    file_sizeprocessed_bigint[
        "size_processed"] = 9223372036854775807  # 9223 petabytes (big int sql definition)
    response = client.post(
        tests.DDSEndpoint.FILE_NEW,
        headers=tests.UserAuth(
            tests.USER_CREDENTIALS["unitadmin"]).token(client),
        query_string={"project": "file_testing_project"},
        json=file_sizeprocessed_bigint,
    )
    assert response.status_code == http.HTTPStatus.OK
    assert file_in_db(test_dict=file_sizeprocessed_bigint,
                      project=project_1.id)
Example #5
0
def test_set_project_to_available_no_mail(module_client, boto3_session):
    """Set status to Available for test project, but skip sending mails"""
    current_unit_admins = models.UnitUser.query.filter_by(
        unit_id=1, is_admin=True).count()
    assert current_unit_admins == 3

    token = tests.UserAuth(
        tests.USER_CREDENTIALS["unituser"]).token(module_client)

    response = module_client.post(
        tests.DDSEndpoint.PROJECT_CREATE,
        headers=token,
        json=proj_data_with_existing_users,
    )
    assert response.status_code == http.HTTPStatus.OK
    assert response.json and response.json.get("user_addition_statuses")
    for x in response.json.get("user_addition_statuses"):
        assert "given access to the Project" in x

    public_project_id = response.json.get("project_id")

    with unittest.mock.patch.object(flask_mail.Mail, "send") as mock_mail_send:
        with unittest.mock.patch.object(
                dds_web.api.user.AddUser,
                "compose_and_send_email_to_user") as mock_mail_func:
            response = module_client.post(
                tests.DDSEndpoint.PROJECT_STATUS,
                headers=token,
                query_string={"project": public_project_id},
                json={
                    "new_status": "Available",
                    "deadline": 10,
                    "send_email": False
                },
            )
            # assert that no mail is being sent.
            assert mock_mail_func.called == False
        assert mock_mail_send.call_count == 0

    assert response.status_code == http.HTTPStatus.OK
    assert "An e-mail notification has not been sent." in response.json[
        "message"]
Example #6
0
def test_create_project_unknown_field(client):
    """Make request with unknown field passed."""
    # Make sure there's 3 unit admins for unit
    create_unit_admins(num_admins=2)

    current_unit_admins = models.UnitUser.query.filter_by(
        unit_id=1, is_admin=True).count()
    assert current_unit_admins == 3

    # Attempt creating project
    response = client.post(
        tests.DDSEndpoint.PROJECT_CREATE,
        headers=tests.UserAuth(
            tests.USER_CREDENTIALS["unitadmin"]).token(client),
        json={"test": "test"},
    )
    assert response.status_code == http.HTTPStatus.BAD_REQUEST
    response_json = response.json
    assert (response_json and "title" in response_json
            and response_json["title"].get("message") == "Title is required.")
Example #7
0
def test_auth_second_factor_expired_hotp_statuscode_401_unauthorized(client):
    """Test that the second_factor endpoint with expired hotp returns 401/UNAUTHORIZED"""
    user_auth = tests.UserAuth(tests.USER_CREDENTIALS["researcher"])
    hotp_token = user_auth.fetch_hotp()
    user = dds_web.database.models.User.query.filter_by(
        username=user_auth.username).first()
    user.hotp_issue_time = datetime.datetime.now() - datetime.timedelta(
        minutes=15, seconds=1)
    db.session.commit()

    response = client.get(
        tests.DDSEndpoint.SECOND_FACTOR,
        headers=user_auth.partial_token(client),
        json={"HOTP": hotp_token.decode()},
    )
    assert response.status_code == http.HTTPStatus.UNAUTHORIZED
    response_json = response.json
    assert response_json.get("message")
    assert "Invalid one-time authentication code." == response_json.get(
        "message")
Example #8
0
def test_invite_unituser_with_valid_unit_as_superadmin(client):
    """A unit user should be invited if the super admin provides a valid unit."""
    for invitee in [new_unit_admin, new_unit_user]:
        valid_unit = models.Unit.query.filter_by(name="Unit 1").one_or_none()
        assert valid_unit

        invite_with_valid_unit = invitee.copy()
        invite_with_valid_unit["unit"] = valid_unit.public_id

        # Attempt invite
        response = client.post(
            tests.DDSEndpoint.USER_ADD,
            headers=tests.UserAuth(
                tests.USER_CREDENTIALS["superadmin"]).token(client),
            json=invite_with_valid_unit,
        )

        new_invite = models.Invite.query.filter_by(
            email=invite_with_valid_unit["email"]).one_or_none()
        assert new_invite
Example #9
0
def test_create_project_no_title(client):
    """Create project without a title specified."""
    create_unit_admins(num_admins=2)

    current_unit_admins = models.UnitUser.query.filter_by(
        unit_id=1, is_admin=True).count()
    assert current_unit_admins == 3

    response = client.post(
        tests.DDSEndpoint.PROJECT_CREATE,
        headers=tests.UserAuth(
            tests.USER_CREDENTIALS["unituser"]).token(client),
        json={"pi": "piName"},
    )
    assert response.status_code == http.HTTPStatus.BAD_REQUEST

    created_proj = models.Project.query.filter_by(
        created_by="unituser",
        pi=proj_data["pi"],
    ).one_or_none()
    assert created_proj is None
Example #10
0
def test_create_project_none_pi(client):
    """Make request with missing title."""
    create_unit_admins(num_admins=2)

    current_unit_admins = models.UnitUser.query.filter_by(
        unit_id=1, is_admin=True).count()
    assert current_unit_admins == 3

    proj_data_none_pi = proj_data.copy()
    proj_data_none_pi["pi"] = None

    response = client.post(
        tests.DDSEndpoint.PROJECT_CREATE,
        headers=tests.UserAuth(
            tests.USER_CREDENTIALS["unitadmin"]).token(client),
        json=proj_data_none_pi,
    )
    assert response.status_code == http.HTTPStatus.BAD_REQUEST
    response_json = response.json
    assert ("pi" in response_json and response_json["pi"].get("message")
            == "A principal investigator is required.")
def perform_invite(client, inviting_user, email, role=None, project=None):
    json_data = {"email": email, "role": role}
    query_string = {}
    if project:
        if not role:
            raise ValueError(
                "Role must be specified when inviting to a project")
        query_string = {"project": project.public_id}

    # get the auth token here to avoid interfering with the invite token fetching
    auth_token = tests.UserAuth(
        tests.USER_CREDENTIALS[inviting_user.username]).token(client)

    # Need to get hold of the actual invite token
    invite_token = None
    with unittest.mock.patch.object(dds_web.api.user,
                                    "encrypted_jwt_token",
                                    return_value="token") as mock_token_method:
        response = client.post(
            tests.DDSEndpoint.USER_ADD,
            headers=auth_token,
            query_string=query_string,
            json=json_data,
            content_type="application/json",
        )
        if DEBUG:
            print(response.data)
        # New invite token is not generated if invite is already sent
        assert mock_token_method.call_count <= 1
        if mock_token_method.call_args is not None:
            call_args = mock_token_method.call_args
            invite_token = encrypted_jwt_token(*call_args.args,
                                               **call_args.kwargs)

    if response.status != "200 OK":
        if DEBUG:
            print(response.status_code)
        raise ValueError(f"Invitation failed: {response.data}")

    return invite_token
Example #12
0
def test_add_existing_user_to_existing_project_no_mail_flag(client):
    "Test that an e-mail notification is not send when the --no-mail flag is used"

    user_copy = existing_research_user_to_existing_project.copy()
    project_id = user_copy.pop("project")
    new_status = {"new_status": "Available"}
    user_copy["send_email"] = False
    token = tests.UserAuth(tests.USER_CREDENTIALS["unituser"]).token(client)

    # make project available prior to test, otherwise an e-mail is never sent.
    response = client.post(
        tests.DDSEndpoint.PROJECT_STATUS,
        headers=token,
        query_string={"project": project_id},
        data=json.dumps(new_status),
        content_type="application/json",
    )

    # Test mail sending is suppressed

    with unittest.mock.patch.object(flask_mail.Mail, "send") as mock_mail_send:
        with unittest.mock.patch.object(
                dds_web.api.user.AddUser,
                "compose_and_send_email_to_user") as mock_mail_func:
            print(user_copy)
            response = client.post(
                tests.DDSEndpoint.USER_ADD,
                headers=token,
                query_string={"project": project_id},
                data=json.dumps(user_copy),
                content_type="application/json",
            )
            # assert that no mail is being sent.
            assert mock_mail_func.called == False
    assert mock_mail_send.call_count == 0

    assert response.status_code == http.HTTPStatus.OK
    assert "An e-mail notification has not been sent." in response.json[
        "message"]
Example #13
0
def test_create_project_with_malformed_json(client):
    """Create a project with malformed project info."""
    create_unit_admins(num_admins=2)

    current_unit_admins = models.UnitUser.query.filter_by(
        unit_id=1, is_admin=True).count()
    assert current_unit_admins == 3

    response = client.post(
        tests.DDSEndpoint.PROJECT_CREATE,
        headers=tests.UserAuth(
            tests.USER_CREDENTIALS["unituser"]).token(client),
        json="",
    )
    assert response.status_code == http.HTTPStatus.BAD_REQUEST
    created_proj = models.Project.query.filter_by(
        created_by="unituser",
        title="",
        pi="",
        description="",
    ).one_or_none()
    assert created_proj is None
Example #14
0
def test_create_project_without_credentials(client):
    """Create project without valid user credentials."""
    create_unit_admins(num_admins=2)

    current_unit_admins = models.UnitUser.query.filter_by(
        unit_id=1, is_admin=True).count()
    assert current_unit_admins == 3

    response = client.post(
        tests.DDSEndpoint.PROJECT_CREATE,
        headers=tests.UserAuth(
            tests.USER_CREDENTIALS["researchuser"]).token(client),
        json=proj_data,
    )
    assert response.status_code == http.HTTPStatus.FORBIDDEN
    created_proj = models.Project.query.filter_by(
        created_by="researchuser",
        title=proj_data["title"],
        pi=proj_data["pi"],
        description=proj_data["description"],
    ).one_or_none()
    assert created_proj is None
Example #15
0
def test_auth_second_factor_correctauth_reused_hotp_401_unauthorized(client):
    """Test that the token endpoint called with an already used hotp returns 401/UNAUTHORIZED"""
    user_auth = tests.UserAuth(tests.USER_CREDENTIALS["researcher"])
    hotp_token = user_auth.fetch_hotp()
    response = client.get(
        tests.DDSEndpoint.SECOND_FACTOR,
        headers=user_auth.partial_token(client),
        json={"HOTP": hotp_token.decode()},
    )
    assert response.status_code == http.HTTPStatus.OK

    # Reuse the same hotp token
    response = client.get(
        tests.DDSEndpoint.SECOND_FACTOR,
        headers=user_auth.partial_token(client),
        json={"HOTP": hotp_token.decode()},
    )

    assert response.status_code == http.HTTPStatus.UNAUTHORIZED
    response_json = response.json
    assert response_json.get("message")
    assert "Invalid one-time authentication code." == response_json.get(
        "message")
Example #16
0
def test_fix_access_projectowner_valid_email_invalid_otheruser(client):
    """Project owner giving access to another user - no permissions."""
    token = tests.UserAuth(
        tests.USER_CREDENTIALS["projectowner"]).token(client)
    response = client.post(
        tests.DDSEndpoint.PROJECT_ACCESS,
        headers=token,
        query_string=proj_query,
        json={"email": "*****@*****.**"},
    )
    assert response.status_code == http.HTTPStatus.FORBIDDEN
    assert "You do not have the necessary permissions" in response.json.get(
        "message")

    response = client.post(
        tests.DDSEndpoint.PROJECT_ACCESS,
        headers=token,
        query_string=proj_query,
        json={"email": "*****@*****.**"},
    )
    assert response.status_code == http.HTTPStatus.FORBIDDEN
    assert "You do not have the necessary permissions" in response.json.get(
        "message")
Example #17
0
def test_add_user_with_unitadmin(client):
    with unittest.mock.patch.object(flask_mail.Mail, "send") as mock_mail_send:
        token = tests.UserAuth(
            tests.USER_CREDENTIALS["unitadmin"]).token(client)
        response = client.post(
            tests.DDSEndpoint.USER_ADD,
            headers=token,
            json=first_new_user,
        )
        # One mail sent for partial token and one for the invite
        assert mock_mail_send.call_count == 2

    assert response.status_code == http.HTTPStatus.OK

    invited_user = models.Invite.query.filter_by(
        email=first_new_user["email"]).one_or_none()
    assert invited_user
    assert invited_user.email == first_new_user["email"]
    assert invited_user.role == first_new_user["role"]

    assert invited_user.nonce is not None
    assert invited_user.public_key is not None
    assert invited_user.private_key is not None
    assert invited_user.project_invite_keys == []

    # Repeating the invite should not send a new invite:
    with unittest.mock.patch.object(flask_mail.Mail, "send") as mock_mail_send:
        response = client.post(
            tests.DDSEndpoint.USER_ADD,
            headers=token,
            json=first_new_user,
        )
        # No new mail should be sent for the token and neither for an invite
        assert mock_mail_send.call_count == 0
    assert response.status_code == http.HTTPStatus.BAD_REQUEST
    message = response.json.get("message")
    assert "user was already added to the system" in message
Example #18
0
def test_set_project_to_archived(module_client, test_project, boto3_session):
    """Archive an expired project"""

    new_status = {"new_status": "Archived"}
    project_id = test_project
    project = project_row(project_id=project_id)

    assert file_in_db(test_dict=FIRST_NEW_FILE, project=project.id)
    assert project.project_user_keys

    response = module_client.post(
        tests.DDSEndpoint.PROJECT_STATUS,
        headers=tests.UserAuth(
            tests.USER_CREDENTIALS["unitadmin"]).token(module_client),
        query_string={"project": project_id},
        json=new_status,
    )

    assert response.status_code == http.HTTPStatus.OK
    assert project.current_status == "Archived"
    assert not max(project.project_statuses,
                   key=lambda x: x.date_created).is_aborted
    assert not file_in_db(test_dict=FIRST_NEW_FILE, project=project.id)
    assert not project.project_user_keys
Example #19
0
def test_create_project_sensitive(client, boto3_session):
    """Create a sensitive project."""
    create_unit_admins(num_admins=2)

    current_unit_admins = models.UnitUser.query.filter_by(
        unit_id=1, is_admin=True).count()
    assert current_unit_admins == 3

    p_data = proj_data
    p_data["non_sensitive"] = False
    response = client.post(
        tests.DDSEndpoint.PROJECT_CREATE,
        headers=tests.UserAuth(
            tests.USER_CREDENTIALS["unituser"]).token(client),
        json=p_data,
    )
    assert response.status_code == http.HTTPStatus.OK
    created_proj = models.Project.query.filter_by(
        created_by="unituser",
        title=proj_data["title"],
        pi=proj_data["pi"],
        description=proj_data["description"],
    ).one_or_none()
    assert created_proj and not created_proj.non_sensitive
Example #20
0
def test_cancel_2fa(client):
    user_auth = tests.UserAuth(tests.USER_CREDENTIALS["researcher"])

    response = client.get(tests.DDSEndpoint.LOGIN)
    assert response.status == "200 OK"

    form_token = flask.g.csrf_token

    form_data = {
        "csrf_token": form_token,
        "username": user_auth.as_tuple()[0],
        "password": user_auth.as_tuple()[1],
        "submit": "Login",
    }

    response = client.post(
        tests.DDSEndpoint.LOGIN,
        json=form_data,
        follow_redirects=True,
    )
    assert response.status == "200 OK"
    assert flask.request.path == tests.DDSEndpoint.CONFIRM_2FA

    second_factor_token = flask.session.get("2fa_initiated_token")
    assert second_factor_token is not None

    response = client.post(
        tests.DDSEndpoint.CANCEL_2FA,
        follow_redirects=True,
    )

    assert response.status == "200 OK"
    assert flask.request.path == tests.DDSEndpoint.LOGIN

    second_factor_token = flask.session.get("2fa_initiated_token")
    assert second_factor_token is None
Example #21
0
def test_fix_access_projectowner_valid_email(client):
    """Project Owner giving access to users - ok."""
    project = models.Project.query.filter_by(
        public_id="public_project_id").one_or_none()
    assert project

    user_project_row = models.ProjectUsers.query.filter_by(
        project_id=project.id, user_id="researchuser").first()
    assert user_project_row

    po_project_row = models.ProjectUsers.query.filter_by(
        project_id=project.id, user_id="projectowner").first()
    assert po_project_row and po_project_row.owner

    user_project_key_row = models.ProjectUserKeys.query.filter_by(
        project_id=project.id, user_id="researchuser").first()
    if user_project_key_row:
        db.session.delete(user_project_key_row)
        db.session.commit()
    user_project_key_row = models.ProjectUserKeys.query.filter_by(
        project_id=project.id, user_id="researchuser").first()
    assert not user_project_key_row

    token = tests.UserAuth(
        tests.USER_CREDENTIALS["projectowner"]).token(client)
    response = client.post(
        tests.DDSEndpoint.PROJECT_ACCESS,
        headers=token,
        query_string=proj_query,
        json={"email": "*****@*****.**"},
    )
    assert response.status_code == http.HTTPStatus.OK

    user_project_key_row = models.ProjectUserKeys.query.filter_by(
        project_id=project.id, user_id="researchuser").first()
    assert user_project_key_row
Example #22
0
def test_invite_to_register_unituser_by_unitadmin(client):
    "Test that a unit user can be created with project access"
    unitadmin = models.User.query.filter_by(username="******").one_or_none()
    unituser_to_be = "*****@*****.**"

    projects = set(unitadmin.projects)
    assert len(projects) > 1

    user = invite_confirm_register_and_get_private(
        client,
        inviting_user=unitadmin,
        email=unituser_to_be,
        projects=None,
        role_per_project=["Unit Personnel"],
    )
    assert user.role == "Unit Personnel"
    assert user.is_active
    assert set(user.projects) == projects
    assert len(user.project_user_keys) == len(projects)

    auth_token = tests.UserAuth(f"{user.username}:{REGISTRATION_DATA['password']}").token(client)

    for project in projects:
        get_private(client, project, auth_token)
Example #23
0
def test_list_files_auth(client):
    """Confirm that the correct files/folders are listed."""
    response = client.post(
        tests.DDSEndpoint.PROJECT_STATUS,
        headers=tests.UserAuth(
            tests.USER_CREDENTIALS["unituser"]).token(client),
        query_string={"project": "public_project_id"},
        json={"new_status": "Available"},
    )
    assert response.status_code == http.HTTPStatus.OK

    response = client.get(
        tests.DDSEndpoint.LIST_FILES,
        headers=tests.UserAuth(
            tests.USER_CREDENTIALS["researchuser"]).token(client),
        query_string={"project": "public_project_id"},
        json={"show_size": True},
    )
    expected = {
        "files_folders": [
            {
                "folder": True,
                "name": "filename1",
                "size": "15 KB"
            },
            {
                "folder": True,
                "name": "filename2",
                "size": "82.5 KB"
            },
            {
                "folder": True,
                "name": "sub",
                "size": "15 KB"
            },
        ]
    }
    assert "files_folders" in response.json
    assert len(response.json["files_folders"]) == len(
        expected["files_folders"])
    for entry in response.json["files_folders"]:
        assert len(entry) == 3
        assert entry["folder"] is True
    assert set(entry["name"]
               for entry in response.json["files_folders"]) == set(
                   entry["name"] for entry in expected["files_folders"])

    response = client.get(
        tests.DDSEndpoint.LIST_FILES,
        headers=tests.UserAuth(
            tests.USER_CREDENTIALS["researchuser"]).token(client),
        query_string={"project": "public_project_id"},
        json={"subpath": ""},
    )
    expected = {
        "files_folders": [
            {
                "folder": True,
                "name": "filename1"
            },
            {
                "folder": True,
                "name": "filename2"
            },
            {
                "folder": True,
                "name": "sub"
            },
        ]
    }
    assert "files_folders" in response.json
    assert len(response.json["files_folders"]) == len(
        expected["files_folders"])
    for entry in response.json["files_folders"]:
        assert len(entry) == 2
        assert entry["folder"] is True
    assert set(entry["name"]
               for entry in response.json["files_folders"]) == set(
                   entry["name"] for entry in expected["files_folders"])

    response = client.get(
        tests.DDSEndpoint.LIST_FILES,
        headers=tests.UserAuth(
            tests.USER_CREDENTIALS["researchuser"]).token(client),
        query_string={"project": "public_project_id"},
        json={"subpath": "sub/path"},
    )
    assert response.json == {"files_folders": [{"folder": True, "name": "to"}]}

    response = client.get(
        tests.DDSEndpoint.LIST_FILES,
        headers=tests.UserAuth(
            tests.USER_CREDENTIALS["researchuser"]).token(client),
        query_string={"project": "public_project_id"},
        json={"subpath": "sub/path/to"},
    )
    # compare in multiple steps as the order of the returned entries is not guaranteed
    expected = {
        "files_folders": [
            {
                "folder": True,
                "name": "folder1"
            },
            {
                "folder": True,
                "name": "folder2"
            },
            {
                "folder": True,
                "name": "folder3"
            },
            {
                "folder": True,
                "name": "folder4"
            },
            {
                "folder": True,
                "name": "folder5"
            },
            {
                "folder": True,
                "name": "files"
            },
        ]
    }
    assert "files_folders" in response.json
    assert len(response.json["files_folders"]) == len(
        expected["files_folders"])
    for entry in response.json["files_folders"]:
        assert len(entry) == 2
        assert entry["folder"] is True
    assert set(entry["name"]
               for entry in response.json["files_folders"]) == set(
                   entry["name"] for entry in expected["files_folders"])

    response = client.get(
        tests.DDSEndpoint.LIST_FILES,
        headers=tests.UserAuth(
            tests.USER_CREDENTIALS["researchuser"]).token(client),
        query_string={"project": "public_project_id"},
        json={"subpath": "sub/path/to/folder1"},
    )
    assert response.json == {
        "files_folders": [{
            "folder": False,
            "name": "filename_a1"
        }]
    }

    response = client.get(
        tests.DDSEndpoint.LIST_FILES,
        headers=tests.UserAuth(
            tests.USER_CREDENTIALS["researchuser"]).token(client),
        query_string={"project": "public_project_id"},
        json={"subpath": "sub/path/to/files"},
    )
    # compare in multiple steps as the order of the returned entries is not guaranteed
    expected = {
        "files_folders": [
            {
                "folder": False,
                "name": "filename_b1"
            },
            {
                "folder": False,
                "name": "filename_b2"
            },
            {
                "folder": False,
                "name": "filename_b3"
            },
            {
                "folder": False,
                "name": "filename_b4"
            },
            {
                "folder": False,
                "name": "filename_b5"
            },
        ]
    }
    assert "files_folders" in response.json
    assert len(response.json["files_folders"]) == len(
        expected["files_folders"])
    for entry in response.json["files_folders"]:
        assert len(entry) == 2
        assert entry["folder"] is False
    assert set(entry["name"]
               for entry in response.json["files_folders"]) == set(
                   entry["name"] for entry in expected["files_folders"])
Example #24
0
def test_load_login_page(client):
    user_auth = tests.UserAuth(tests.USER_CREDENTIALS["researcher"])

    response = client.get(tests.DDSEndpoint.LOGIN)
    assert response.status == "200 OK"
Example #25
0
def get_token(username, client):
    return tests.UserAuth(tests.USER_CREDENTIALS[username]).token(client)
Example #26
0
def test_abort_from_in_progress_once_made_available(module_client,
                                                    boto3_session):
    """Create project and abort it from In Progress after it has been made available"""
    current_unit_admins = models.UnitUser.query.filter_by(
        unit_id=1, is_admin=True).count()
    assert current_unit_admins == 3

    response = module_client.post(
        tests.DDSEndpoint.PROJECT_CREATE,
        headers=tests.UserAuth(
            tests.USER_CREDENTIALS["unituser"]).token(module_client),
        json=proj_data,
    )
    assert response.status_code == http.HTTPStatus.OK

    project_id = response.json.get("project_id")

    # add a file
    response = module_client.post(
        tests.DDSEndpoint.FILE_NEW,
        headers=tests.UserAuth(
            tests.USER_CREDENTIALS["unitadmin"]).token(module_client),
        query_string={"project": project_id},
        json=FIRST_NEW_FILE,
    )

    project = project_row(project_id=project_id)

    assert file_in_db(test_dict=FIRST_NEW_FILE, project=project.id)

    new_status = {"new_status": "Available"}
    time.sleep(1)

    response = module_client.post(
        tests.DDSEndpoint.PROJECT_STATUS,
        headers=tests.UserAuth(
            tests.USER_CREDENTIALS["unitadmin"]).token(module_client),
        query_string={"project": project_id},
        json=new_status,
    )

    assert response.status_code == http.HTTPStatus.OK
    assert project.current_status == "Available"

    new_status["new_status"] = "In Progress"
    time.sleep(1)

    response = module_client.post(
        tests.DDSEndpoint.PROJECT_STATUS,
        headers=tests.UserAuth(
            tests.USER_CREDENTIALS["unitadmin"]).token(module_client),
        query_string={"project": project_id},
        json=new_status,
    )

    assert response.status_code == http.HTTPStatus.OK
    assert project.current_status == "In Progress"
    assert project.project_user_keys

    response = module_client.get(
        tests.DDSEndpoint.PROJECT_STATUS,
        headers=tests.UserAuth(
            tests.USER_CREDENTIALS["unitadmin"]).token(module_client),
        query_string={"project": project_id},
        json={"history": True},
    )

    assert response.status_code == http.HTTPStatus.OK
    assert response.json["current_status"] == project.current_status
    assert response.json["current_deadline"]
    assert response.json["history"]

    time.sleep(1)
    new_status["new_status"] = "Archived"
    new_status["is_aborted"] = True
    response = module_client.post(
        tests.DDSEndpoint.PROJECT_STATUS,
        headers=tests.UserAuth(
            tests.USER_CREDENTIALS["unitadmin"]).token(module_client),
        query_string={"project": project_id},
        json=new_status,
    )

    assert response.status_code == http.HTTPStatus.OK
    assert project.current_status == "Archived"
    assert max(project.project_statuses,
               key=lambda x: x.date_created).is_aborted
    assert not file_in_db(test_dict=FIRST_NEW_FILE, project=project.id)

    for field, value in vars(project).items():
        if field in fields_set_to_null:
            assert not value
    assert len(project.researchusers) == 0
    assert not project.project_user_keys
Example #27
0
def test_project_availability_after_set_to_expired_more_than_twice(
        module_client, test_project):
    """Try to set status to Available for test project after being in Expired 3 times"""

    new_status = {"new_status": "Available", "deadline": 5}

    project_id = test_project
    project = project_row(project_id=project_id)
    time.sleep(1)

    response = module_client.post(
        tests.DDSEndpoint.PROJECT_STATUS,
        headers=tests.UserAuth(
            tests.USER_CREDENTIALS["unitadmin"]).token(module_client),
        query_string={"project": project_id},
        json=new_status,
    )

    assert response.status_code == http.HTTPStatus.OK
    assert project.current_status == "Available"

    new_status["new_status"] = "Expired"
    time.sleep(1)

    response = module_client.post(
        tests.DDSEndpoint.PROJECT_STATUS,
        headers=tests.UserAuth(
            tests.USER_CREDENTIALS["unitadmin"]).token(module_client),
        query_string={"project": project_id},
        json=new_status,
    )

    assert response.status_code == http.HTTPStatus.OK
    assert project.current_status == "Expired"

    new_status["new_status"] = "Available"
    time.sleep(1)

    response = module_client.post(
        tests.DDSEndpoint.PROJECT_STATUS,
        headers=tests.UserAuth(
            tests.USER_CREDENTIALS["unitadmin"]).token(module_client),
        query_string={"project": project_id},
        json=new_status,
    )

    assert response.status_code == http.HTTPStatus.OK
    assert project.current_status == "Available"

    new_status["new_status"] = "Expired"
    time.sleep(1)

    response = module_client.post(
        tests.DDSEndpoint.PROJECT_STATUS,
        headers=tests.UserAuth(
            tests.USER_CREDENTIALS["unitadmin"]).token(module_client),
        query_string={"project": project_id},
        json=new_status,
    )

    assert response.status_code == http.HTTPStatus.OK
    assert project.current_status == "Expired"

    new_status["new_status"] = "Available"
    time.sleep(1)

    response = module_client.post(
        tests.DDSEndpoint.PROJECT_STATUS,
        headers=tests.UserAuth(
            tests.USER_CREDENTIALS["unitadmin"]).token(module_client),
        query_string={"project": project_id},
        json=new_status,
    )

    assert response.status_code == http.HTTPStatus.BAD_REQUEST
    assert project.current_status == "Expired"

    assert "Project cannot be made Available any more times" in response.json[
        "message"]
Example #28
0
def test_files_find_all_for_download(client, boto3_session):
    """Check if correct file info for all files is returned for download"""
    # Set status to available
    response = client.post(
        tests.DDSEndpoint.PROJECT_STATUS,
        headers=tests.UserAuth(
            tests.USER_CREDENTIALS["unituser"]).token(client),
        query_string={"project": "public_project_id"},
        json={"new_status": "Available"},
    )
    assert response.status_code == http.HTTPStatus.OK

    with unittest.mock.patch(
            "dds_web.api.api_s3_connector.ApiS3Connector.generate_get_url"
    ) as mock_url:
        mock_url.return_value = "url"
        response = client.get(
            tests.DDSEndpoint.FILE_INFO_ALL,
            headers=tests.UserAuth(
                tests.USER_CREDENTIALS["researchuser"]).token(client),
            query_string={"project": "public_project_id"},
        )
        assert response.status_code == http.HTTPStatus.OK
        # filenames in conftest
        expected_output = {
            "filename1": {
                "subpath": "filename1/subpath",
                "size_original": 15000,
                "size_stored": 10000,
                "compressed": True,
                "salt": "A" * 32,
                "public_key": "B" * 64,
                "checksum": "C" * 64,
                "url": "url",
            },
            "filename2": {
                "subpath": "filename2/subpath",
                "size_original": 15000,
                "size_stored": 10000,
                "compressed": True,
                "salt": "D" * 32,
                "public_key": "E" * 64,
                "checksum": "F" * 64,
                "url": "url",
            },
        }
        for i in range(5):
            expected_output[f"filename_a{i+1}"] = {
                "subpath": f"sub/path/to/folder{i+1}",
                "size_original": 5000 * (i + 1),
                "size_stored": 3000 * (i + 1),
                "compressed": True,
                "salt": chr(ord("A") + 3 * i) * 32,
                "public_key": chr(ord("B") + 3 * i) * 64,
                "checksum": chr(ord("C") + 3 * i) * 64,
                "url": "url",
            }
            expected_output[f"filename_b{i+1}"] = {
                "subpath": f"sub/path/to/files",
                "size_original": 500 * (i + 1),
                "size_stored": 300 * (i + 1),
                "compressed": True,
                "salt": chr(ord("Z") - 3 * i) * 32,
                "public_key": chr(ord("Y") - 3 * i) * 64,
                "checksum": chr(ord("X") - 3 * i) * 64,
                "url": "url",
            }

        files = response.json["files"]
        for file in files:
            files[file].pop("name_in_bucket")

        assert "filename1" in files
        assert "filename2" in files
        for i in range(5):
            assert f"filename_a{i+1}" in files
            assert f"filename_b{i+1}" in files
        unittest.TestCase().assertDictEqual(expected_output, files)
Example #29
0
def test_upload_move_available_delete_file(client, boto3_session):
    """Test delete a file once project has been made available"""

    project_1 = project_row(project_id="file_testing_project")
    assert project_1
    assert project_1.current_status == "In Progress"
    response = client.post(
        tests.DDSEndpoint.FILE_NEW,
        headers=tests.UserAuth(
            tests.USER_CREDENTIALS["unitadmin"]).token(client),
        query_string={"project": "file_testing_project"},
        json=FIRST_NEW_FILE,
    )
    assert response.status_code == http.HTTPStatus.OK
    assert file_in_db(test_dict=FIRST_NEW_FILE, project=project_1.id)

    # Make project Available
    new_status = {"new_status": "Available"}
    response = client.post(
        tests.DDSEndpoint.PROJECT_STATUS,
        headers=tests.UserAuth(
            tests.USER_CREDENTIALS["unitadmin"]).token(client),
        query_string={"project": "file_testing_project"},
        json=new_status,
    )
    assert response.status_code == http.HTTPStatus.OK
    assert project_1.current_status == "Available"
    # Try deleting the uploaded file
    response = client.delete(
        tests.DDSEndpoint.REMOVE_FILE,
        headers=tests.UserAuth(
            tests.USER_CREDENTIALS["unitadmin"]).token(client),
        query_string={"project": "file_testing_project"},
        json=[FIRST_NEW_FILE["name"]],
    )
    assert response.status_code == http.HTTPStatus.BAD_REQUEST
    assert "Project Status prevents files from being deleted." in response.json[
        "message"]

    # Move project back to In Progress
    time.sleep(1)
    new_status["new_status"] = "In Progress"
    response = client.post(
        tests.DDSEndpoint.PROJECT_STATUS,
        headers=tests.UserAuth(
            tests.USER_CREDENTIALS["unitadmin"]).token(client),
        query_string={"project": "file_testing_project"},
        json=new_status,
    )
    assert response.status_code == http.HTTPStatus.OK
    assert project_1.current_status == "In Progress"

    # Try deleting uploaded file again
    response = client.delete(
        tests.DDSEndpoint.REMOVE_FILE,
        headers=tests.UserAuth(
            tests.USER_CREDENTIALS["unitadmin"]).token(client),
        query_string={"project": "file_testing_project"},
        json=[FIRST_NEW_FILE["name"]],
    )
    assert response.status_code == http.HTTPStatus.BAD_REQUEST
    assert (
        "Existing project contents cannot be deleted since the project has been previously made available to recipients."
        in response.json["message"])
def invite_confirm_register_and_get_private(client,
                                            inviting_user,
                                            email,
                                            projects,
                                            role_per_project=None,
                                            no_checkbox=False):
    # Invite
    if projects is None or projects == []:
        assert len(role_per_project) == 1
        invite_token = perform_invite(client,
                                      inviting_user,
                                      email,
                                      role=role_per_project[0])
    else:
        for project, role in zip(projects, role_per_project):
            most_recent_invite_token = perform_invite(client,
                                                      inviting_user,
                                                      email,
                                                      role=role,
                                                      project=project)
            # only the first invite returns a token
            if most_recent_invite_token is not None:
                invite_token = most_recent_invite_token

    if DEBUG:
        print([(invite.email, invite.role)
               for invite in models.Invite.query.all()])
        print([(pik.project.public_id, pik.invite.email, pik.owner)
               for pik in models.ProjectInviteKeys.query.all()])

    # Confirm invite
    response = client.get(tests.DDSEndpoint.USER_CONFIRM + invite_token,
                          content_type="application/json")
    assert response.status == "200 OK"

    # Complete registration
    form_token = flask.g.csrf_token

    if no_checkbox:
        NO_CHECKBOX_REGISTRATION_DATA = REGISTRATION_DATA.copy()
        NO_CHECKBOX_REGISTRATION_DATA.pop("policy_checkbox")

        form_data = {
            **NO_CHECKBOX_REGISTRATION_DATA, "csrf_token": form_token,
            "email": email
        }

        response = client.post(
            tests.DDSEndpoint.USER_NEW,
            json=form_data,
            follow_redirects=True,
        )

        assert response.status == "200 OK"

        user = models.User.query.filter_by(
            username=form_data["username"]).one_or_none()

    else:
        form_data = {
            **REGISTRATION_DATA, "csrf_token": form_token,
            "email": email
        }

        response = client.post(
            tests.DDSEndpoint.USER_NEW,
            json=form_data,
            follow_redirects=True,
        )
        assert response.status == "200 OK"

        user = models.User.query.filter_by(
            username=form_data["username"]).one_or_none()

        auth_token = tests.UserAuth(
            f"{form_data['username']}:{form_data['password']}").token(client)

        if projects is not None:
            for project in projects:
                # Request decrypted project private key for user just created
                # to somewhat test that the decryption works
                get_private(client, project, auth_token)

    return user