def test_anvil_workspace_page(self, mock_logger):
        # Requesting to load data from a workspace without an existing project
        url = reverse(
            anvil_workspace_page,
            args=[TEST_WORKSPACE_NAMESPACE, TEST_NO_PROJECT_WORKSPACE_NAME])
        collaborator_response = self._check_login_permissions(url, mock_logger)
        self.assertEqual(collaborator_response.get('Content-Type'),
                         'text/html')
        initial_json = self.get_initial_page_json(collaborator_response)
        self.assertEqual(initial_json['user']['username'],
                         'test_user_collaborator')

        response = self.client.post(url)
        self.assertEqual(response.status_code, 302)
        self.assertEqual(
            response.url, '/create_project_from_workspace/{}/{}'.format(
                TEST_WORKSPACE_NAMESPACE, TEST_NO_PROJECT_WORKSPACE_NAME))
        self.mock_get_ws_access_level.assert_called_with(
            self.manager_user, TEST_WORKSPACE_NAMESPACE,
            TEST_NO_PROJECT_WORKSPACE_NAME)

        # Test error handling when token refresh fails
        self.mock_get_ws_access_level.side_effect = TerraRefreshTokenFailedException(
            'Failed to refresh token')
        response = self.client.post(url)
        self.assertEqual(response.status_code, 302)
        self.assertEqual(
            response.url, '/login/google-oauth2?next=/workspace/{}/{}'.format(
                TEST_WORKSPACE_NAMESPACE, TEST_NO_PROJECT_WORKSPACE_NAME))
        self.mock_get_ws_access_level.assert_called_with(
            self.manager_user, TEST_WORKSPACE_NAMESPACE,
            TEST_NO_PROJECT_WORKSPACE_NAME)

        # Requesting to load data for an existing project
        self.mock_get_ws_access_level.reset_mock()
        url = reverse(anvil_workspace_page,
                      args=[TEST_WORKSPACE_NAMESPACE, TEST_WORKSPACE_NAME])
        response = self.client.post(url)
        self.assertEqual(response.status_code, 302)
        self.assertEqual(response.url, '/project/R0001_1kg/project_page')
        self.mock_get_ws_access_level.assert_not_called()

        # Test login locally
        remove_token(
            self.manager_user
        )  # The user will be same as logging in locally after the access token is removed
        response = self.client.post(url)
        self.assertEqual(response.status_code, 302)
        self.assertEqual(
            response.url,
            '/login/google-oauth2?next=/workspace/my-seqr-billing/anvil-1kg%2520project%2520n%25C3%25A5me%2520with%2520uni%25C3%25A7%25C3%25B8de'
        )
        self.mock_get_ws_access_level.assert_not_called()
Esempio n. 2
0
    def test_is_google_authenticated(self, mock_social_auth_key):
        user = User.objects.get(username='******')
        r = is_google_authenticated(user)
        self.assertTrue(r)

        remove_token(user)
        r = is_google_authenticated(user)
        self.assertTrue(r)

        local_user = User.objects.get(username='******')
        r = is_google_authenticated(local_user)
        self.assertFalse(r)

        mock_social_auth_key.__bool__.return_value = False
        r = is_google_authenticated(user)
        self.assertFalse(r)
Esempio n. 3
0
    def test_is_anvil_authenticated(self, mock_social_auth_key,
                                    mock_terra_url):
        mock_social_auth_key.__bool__.return_value = False
        mock_terra_url.__bool__.return_value = True
        user = User.objects.get(username='******')
        r = is_anvil_authenticated(user)
        self.assertFalse(r)

        mock_social_auth_key.__bool__.return_value = True
        mock_terra_url.__bool__.return_value = False
        r = is_anvil_authenticated(user)
        self.assertFalse(r)

        mock_terra_url.__bool__.return_value = True
        r = is_anvil_authenticated(user)
        self.assertTrue(r)

        remove_token(user)
        r = is_anvil_authenticated(user)
        self.assertFalse(r)
Esempio n. 4
0
def logout_view(request):
    user = request.user
    remove_token(user)
    logout(request)
    logger.info('Logged out {}'.format(user.email), extra={'user': user})
    return redirect('/login')
Esempio n. 5
0
    def test_create_project_from_workspace(self, mock_file_exist, mock_email,
                                           mock_add_service_account,
                                           mock_has_service_account,
                                           mock_load_file, mock_api_logger,
                                           mock_sleep, mock_utils_logger):
        # Requesting to load data from a workspace without an existing project
        url = reverse(
            create_project_from_workspace,
            args=[TEST_WORKSPACE_NAMESPACE, TEST_NO_PROJECT_WORKSPACE_NAME])

        # Test user doesn't login
        response = self.client.post(url)
        self.assertEqual(response.status_code, 302)
        self.assertEqual(
            response.url,
            '/login/google-oauth2?next=/api/create_project_from_workspace/submit/{}/{}'
            .format(TEST_WORKSPACE_NAMESPACE, TEST_NO_PROJECT_WORKSPACE_NAME))

        # Test the user needs sufficient workspace permissions
        self.check_manager_login(url)
        mock_utils_logger.warning.assert_called_with(
            'User does not have sufficient permissions for workspace {}/{}'.
            format(TEST_WORKSPACE_NAMESPACE, TEST_NO_PROJECT_WORKSPACE_NAME))

        # Test missing required fields in the request body
        response = self.client.post(url,
                                    content_type='application/json',
                                    data=json.dumps({}))
        self.assertEqual(response.status_code, 400)
        self.assertEqual(
            response.reason_phrase,
            'Field(s) "genomeVersion, uploadedFileId, dataPath" are required')
        self.mock_get_ws_access_level.assert_called_with(
            self.manager_user,
            TEST_WORKSPACE_NAMESPACE,
            TEST_NO_PROJECT_WORKSPACE_NAME,
            meta_fields=['workspace.bucketName'])

        data = {
            'genomeVersion': '38',
            'uploadedFileId': 'test_temp_file_id',
            'dataPath': '/test_path',
        }
        response = self.client.post(url,
                                    content_type='application/json',
                                    data=json.dumps(data))
        self.assertEqual(response.status_code, 400)
        self.assertEqual(
            response.reason_phrase,
            'Must agree to grant seqr access to the data in the associated workspace.'
        )

        # Test parsing sample data error
        mock_load_file.return_value = LOAD_SAMPLE_DATA + BAD_SAMPLE_DATA
        response = self.client.post(url,
                                    content_type='application/json',
                                    data=json.dumps(REQUEST_BODY))
        self.assertEqual(response.status_code, 400)
        response_json = response.json()
        self.assertListEqual(response_json['errors'], [
            'NA19679 is the mother of NA19674 but doesn\'t have a separate record in the table'
        ])

        # Test adding service account exception
        mock_load_file.return_value = LOAD_SAMPLE_DATA
        mock_add_service_account.side_effect = TerraAPIException(
            'Failed to grant seqr service account access to the workspace {}/{}'
            .format(TEST_WORKSPACE_NAMESPACE,
                    TEST_NO_PROJECT_WORKSPACE_NAME), 400)
        response = self.client.post(url,
                                    content_type='application/json',
                                    data=json.dumps(REQUEST_BODY))
        self.assertEqual(response.status_code, 400)
        self.assertEqual(
            response.json()['error'],
            'Failed to grant seqr service account access to the workspace {}/{}'
            .format(TEST_WORKSPACE_NAMESPACE, TEST_NO_PROJECT_WORKSPACE_NAME))

        # Test adding service account never processes
        mock_add_service_account.reset_mock(side_effect=True)
        mock_add_service_account.return_value = True
        mock_has_service_account.return_value = False
        response = self.client.post(url,
                                    content_type='application/json',
                                    data=json.dumps(REQUEST_BODY))
        self.assertEqual(response.status_code, 400)
        self.assertEqual(
            response.json()['error'],
            'Failed to grant seqr service account access to the workspace')
        mock_has_service_account.assert_called_with(
            self.manager_user, TEST_WORKSPACE_NAMESPACE,
            TEST_NO_PROJECT_WORKSPACE_NAME)
        self.assertEqual(mock_has_service_account.call_count, 3)
        self.assertEqual(mock_sleep.call_count, 3)

        # Test bad data path
        mock_sleep.reset_mock()
        mock_has_service_account.reset_mock()
        mock_has_service_account.return_value = True
        mock_file_exist.return_value = False
        response = self.client.post(
            url,
            content_type='application/json',
            data=json.dumps(REQUEST_BODY_NO_SLASH_DATA_PATH))
        self.assertEqual(response.status_code, 400)
        self.assertEqual(response.json()['error'],
                         'Data file or path test_no_slash_path is not found.')
        mock_file_exist.assert_called_with(
            'gs://test_bucket/test_no_slash_path')
        mock_has_service_account.assert_called_with(
            self.manager_user, TEST_WORKSPACE_NAMESPACE,
            TEST_NO_PROJECT_WORKSPACE_NAME)
        self.assertEqual(mock_has_service_account.call_count, 1)
        self.assertEqual(mock_sleep.call_count, 1)

        # Test valid operation
        mock_sleep.reset_mock()
        mock_has_service_account.reset_mock()
        mock_add_service_account.return_value = False
        mock_file_exist.return_value = True
        response = self.client.post(url,
                                    content_type='application/json',
                                    data=json.dumps(REQUEST_BODY))
        self.assertEqual(response.status_code, 200)
        project = Project.objects.get(
            workspace_namespace=TEST_WORKSPACE_NAMESPACE,
            workspace_name=TEST_NO_PROJECT_WORKSPACE_NAME)
        response_json = response.json()
        self.assertEqual(project.guid, response_json['projectGuid'])
        self.assertListEqual([
            project.genome_version, project.description,
            project.workspace_namespace, project.workspace_name
        ], [
            '38', 'A test project', TEST_WORKSPACE_NAMESPACE,
            TEST_NO_PROJECT_WORKSPACE_NAME
        ])
        mock_add_service_account.assert_called_with(
            self.manager_user, TEST_WORKSPACE_NAMESPACE,
            TEST_NO_PROJECT_WORKSPACE_NAME)
        mock_has_service_account.assert_not_called()
        mock_sleep.assert_not_called()
        mock_file_exist.assert_called_with('gs://test_bucket/test_path')

        email_body = """
        [email protected] requested to load data from AnVIL workspace "{namespace}/{name}" at "gs://test_bucket/test_path" to seqr project
        {{project_name}} (guid: {guid})

        The sample IDs to load are attached.    
        """.format(namespace=TEST_WORKSPACE_NAMESPACE,
                   name=TEST_NO_PROJECT_WORKSPACE_NAME,
                   guid=project.guid)
        mock_email.assert_called_with(
            subject='AnVIL data loading request',
            body=email_body.format(
                project_name=TEST_NO_PROJECT_WORKSPACE_NAME),
            to=['*****@*****.**', '*****@*****.**'],
            attachments=[('{}_sample_ids.tsv'.format(project.guid),
                          'NA19675\nNA19678\nHG00735')])
        html_project_name = '<a href="http://testserver/project/{guid}/project_page">{name}</a>'.format(
            name=TEST_NO_PROJECT_WORKSPACE_NAME, guid=project.guid)
        mock_email.return_value.attach_alternative.assert_called_with(
            email_body.format(project_name=html_project_name), 'text/html')
        mock_email.return_value.send.assert_called()

        # Test project exist
        url = reverse(
            create_project_from_workspace,
            args=[TEST_WORKSPACE_NAMESPACE, TEST_NO_PROJECT_WORKSPACE_NAME])
        response = self.client.post(url)
        self.assertEqual(response.status_code, 400)
        self.assertEqual(
            response.reason_phrase,
            'Project "{name}" for workspace "{namespace}/{name}" exists.'.
            format(namespace=TEST_WORKSPACE_NAMESPACE,
                   name=TEST_NO_PROJECT_WORKSPACE_NAME))

        # Test sending email exception
        url = reverse(
            create_project_from_workspace,
            args=[TEST_WORKSPACE_NAMESPACE, TEST_NO_PROJECT_WORKSPACE_NAME2])
        mock_email.side_effect = Exception(
            'Something wrong while sending email.')
        response = self.client.post(url,
                                    content_type='application/json',
                                    data=json.dumps(REQUEST_BODY))
        self.assertEqual(response.status_code, 200)
        mock_api_logger.error.assert_called_with(
            'Exception while sending email to user test_user_manager. Something wrong while sending email.'
        )

        # Test logged in locally
        remove_token(
            self.manager_user
        )  # The user will look like having logged in locally after the access token is removed
        response = self.client.post(url)
        self.assertEqual(response.status_code, 302)
        self.assertEqual(
            response.url,
            '/login/google-oauth2?next=/api/create_project_from_workspace/submit/my-seqr-billing/anvil-no-project-workspace2'
        )
Esempio n. 6
0
def logout_view(request):
    user = request.user
    remove_token(user)
    logout(request)
    logger.info('Logged out {}'.format(user.email), user)
    return redirect('/')