Ejemplo n.º 1
0
class GitHubOAuthTests(TestCase):

    fixtures = ['eric', 'test_data']

    def setUp(self):
        self.client.login(username='******', password='******')
        self.user = User.objects.get(pk=1)
        self.project = Project.objects.get(slug='pip')
        self.org = RemoteOrganization.objects.create(slug='rtfd', json='')
        self.privacy = self.project.version_privacy_level
        self.service = GitHubService(user=self.user, account=None)
        self.external_version = get(Version,
                                    project=self.project,
                                    type=EXTERNAL)
        self.external_build = get(Build,
                                  project=self.project,
                                  version=self.external_version)
        self.integration = get(GitHubWebhook,
                               project=self.project,
                               provider_data={'url': 'https://github.com/'})
        self.provider_data = [{
            "config": {
                "url": "https://example.com/webhook"
            },
            "url":
            "https://api.github.com/repos/test/Hello-World/hooks/12345678",
        }]

    def test_make_project_pass(self):
        repo_json = {
            'name': 'testrepo',
            'full_name': 'testuser/testrepo',
            'description': 'Test Repo',
            'git_url': 'git://github.com/testuser/testrepo.git',
            'private': False,
            'ssh_url': 'ssh://[email protected]:testuser/testrepo.git',
            'html_url': 'https://github.com/testuser/testrepo',
            'clone_url': 'https://github.com/testuser/testrepo.git',
        }
        repo = self.service.create_repository(
            repo_json,
            organization=self.org,
            privacy=self.privacy,
        )
        self.assertIsInstance(repo, RemoteRepository)
        self.assertEqual(repo.name, 'testrepo')
        self.assertEqual(repo.full_name, 'testuser/testrepo')
        self.assertEqual(repo.description, 'Test Repo')
        self.assertEqual(
            repo.avatar_url,
            settings.OAUTH_AVATAR_USER_DEFAULT_URL,
        )
        self.assertIn(self.user, repo.users.all())
        self.assertEqual(repo.organization, self.org)
        self.assertEqual(
            repo.clone_url,
            'https://github.com/testuser/testrepo.git',
        )
        self.assertEqual(
            repo.ssh_url,
            'ssh://[email protected]:testuser/testrepo.git',
        )
        self.assertEqual(repo.html_url, 'https://github.com/testuser/testrepo')

    def test_make_project_fail(self):
        repo_json = {
            'name': '',
            'full_name': '',
            'description': '',
            'git_url': '',
            'private': True,
            'ssh_url': '',
            'html_url': '',
            'clone_url': '',
        }
        github_project = self.service.create_repository(
            repo_json,
            organization=self.org,
            privacy=self.privacy,
        )
        self.assertIsNone(github_project)

    def test_make_organization(self):
        org_json = {
            'html_url': 'https://github.com/testorg',
            'name': 'Test Org',
            'email': '*****@*****.**',
            'login': '******',
            'avatar_url': 'https://images.github.com/foobar',
        }
        org = self.service.create_organization(org_json)
        self.assertIsInstance(org, RemoteOrganization)
        self.assertEqual(org.slug, 'testorg')
        self.assertEqual(org.name, 'Test Org')
        self.assertEqual(org.email, '*****@*****.**')
        self.assertEqual(org.avatar_url, 'https://images.github.com/foobar')
        self.assertEqual(org.url, 'https://github.com/testorg')

    def test_import_with_no_token(self):
        """User without a GitHub SocialToken does not return a service."""
        services = GitHubService.for_user(self.user)
        self.assertEqual(services, [])

    def test_multiple_users_same_repo(self):
        repo_json = {
            'name': '',
            'full_name': 'testrepo/multiple',
            'description': '',
            'git_url': '',
            'private': False,
            'ssh_url': '',
            'html_url': '',
            'clone_url': '',
        }

        github_project = self.service.create_repository(
            repo_json,
            organization=self.org,
            privacy=self.privacy,
        )

        user2 = User.objects.get(pk=2)
        service = GitHubService(user=user2, account=None)
        github_project_2 = service.create_repository(
            repo_json,
            organization=self.org,
            privacy=self.privacy,
        )
        self.assertIsInstance(github_project, RemoteRepository)
        self.assertIsInstance(github_project_2, RemoteRepository)
        self.assertNotEqual(github_project_2, github_project)

        github_project_3 = self.service.create_repository(
            repo_json,
            organization=self.org,
            privacy=self.privacy,
        )
        github_project_4 = service.create_repository(
            repo_json,
            organization=self.org,
            privacy=self.privacy,
        )
        self.assertIsInstance(github_project_3, RemoteRepository)
        self.assertIsInstance(github_project_4, RemoteRepository)
        self.assertEqual(github_project, github_project_3)
        self.assertEqual(github_project_2, github_project_4)

        github_project_5 = self.service.create_repository(
            repo_json,
            organization=self.org,
            privacy=self.privacy,
        )
        github_project_6 = service.create_repository(
            repo_json,
            organization=self.org,
            privacy=self.privacy,
        )

        self.assertEqual(github_project, github_project_5)
        self.assertEqual(github_project_2, github_project_6)

    @mock.patch('readthedocs.oauth.services.github.log')
    @mock.patch('readthedocs.oauth.services.github.GitHubService.get_session')
    def test_send_build_status_successful(self, session, mock_logger):
        session().post.return_value.status_code = 201
        success = self.service.send_build_status(self.external_build,
                                                 self.external_build.commit,
                                                 BUILD_STATUS_SUCCESS)

        self.assertTrue(success)
        mock_logger.info.assert_called_with(
            "GitHub commit status created for project: %s, commit status: %s",
            self.project, BUILD_STATUS_SUCCESS)

    @mock.patch('readthedocs.oauth.services.github.log')
    @mock.patch('readthedocs.oauth.services.github.GitHubService.get_session')
    def test_send_build_status_404_error(self, session, mock_logger):
        session().post.return_value.status_code = 404
        success = self.service.send_build_status(self.external_build,
                                                 self.external_build.commit,
                                                 BUILD_STATUS_SUCCESS)

        self.assertFalse(success)
        mock_logger.info.assert_called_with(
            'GitHub project does not exist or user does not have '
            'permissions: project=%s, user=%s, status=%s, url=%s',
            self.project, self.user, 404,
            'https://api.github.com/repos/pypa/pip/statuses/297')

    @mock.patch('readthedocs.oauth.services.github.log')
    @mock.patch('readthedocs.oauth.services.github.GitHubService.get_session')
    def test_send_build_status_value_error(self, session, mock_logger):
        session().post.side_effect = ValueError
        success = self.service.send_build_status(self.external_build,
                                                 self.external_build.commit,
                                                 BUILD_STATUS_SUCCESS)

        self.assertFalse(success)
        mock_logger.exception.assert_called_with(
            'GitHub commit status creation failed for project: %s',
            self.project,
        )

    @override_settings(DEFAULT_PRIVACY_LEVEL='private')
    def test_make_private_project(self):
        """
        Test ability to import ``public`` repositories under ``private`` level.
        """
        repo_json = {
            'name': 'testrepo',
            'full_name': 'testuser/testrepo',
            'description': 'Test Repo',
            'git_url': 'git://github.com/testuser/testrepo.git',
            'private': False,
            'ssh_url': 'ssh://[email protected]:testuser/testrepo.git',
            'html_url': 'https://github.com/testuser/testrepo',
            'clone_url': 'https://github.com/testuser/testrepo.git',
        }
        repo = self.service.create_repository(repo_json, organization=self.org)
        self.assertIsNotNone(repo)

    @mock.patch('readthedocs.oauth.services.github.log')
    @mock.patch('readthedocs.oauth.services.github.GitHubService.get_session')
    def test_setup_webhook_successful(self, session, mock_logger):
        session().post.return_value.status_code = 201
        session().post.return_value.json.return_value = {}
        success, _ = self.service.setup_webhook(self.project, self.integration)

        self.integration.refresh_from_db()

        self.assertTrue(success)
        self.assertIsNotNone(self.integration.secret)
        mock_logger.info.assert_called_with(
            "GitHub webhook creation successful for project: %s",
            self.project,
        )

    @mock.patch('readthedocs.oauth.services.github.log')
    @mock.patch('readthedocs.oauth.services.github.GitHubService.get_session')
    def test_setup_webhook_404_error(self, session, mock_logger):
        session().post.return_value.status_code = 404
        success, _ = self.service.setup_webhook(self.project, self.integration)
        self.integration.refresh_from_db()

        self.assertFalse(success)
        self.assertIsNone(self.integration.secret)
        mock_logger.info.assert_called_with(
            'GitHub project does not exist or user does not have '
            'permissions: project=%s',
            self.project,
        )

    @mock.patch('readthedocs.oauth.services.github.log')
    @mock.patch('readthedocs.oauth.services.github.GitHubService.get_session')
    def test_setup_webhook_value_error(self, session, mock_logger):
        session().post.side_effect = ValueError
        success = self.service.setup_webhook(self.project, self.integration)

        self.integration.refresh_from_db()

        self.assertIsNone(self.integration.secret)
        mock_logger.exception.assert_called_with(
            'GitHub webhook creation failed for project: %s',
            self.project,
        )

    @mock.patch('readthedocs.oauth.services.github.log')
    @mock.patch('readthedocs.oauth.services.github.GitHubService.get_session')
    def test_update_webhook_successful(self, session, mock_logger):
        session().patch.return_value.status_code = 201
        session().patch.return_value.json.return_value = {}
        success, _ = self.service.update_webhook(self.project,
                                                 self.integration)

        self.integration.refresh_from_db()

        self.assertTrue(success)
        self.assertIsNotNone(self.integration.secret)
        mock_logger.info.assert_called_with(
            "GitHub webhook update successful for project: %s",
            self.project,
        )

    @mock.patch('readthedocs.oauth.services.github.GitHubService.get_session')
    @mock.patch('readthedocs.oauth.services.github.GitHubService.setup_webhook'
                )
    def test_update_webhook_404_error(self, setup_webhook, session):
        session().patch.return_value.status_code = 404
        self.service.update_webhook(self.project, self.integration)

        setup_webhook.assert_called_once_with(self.project, self.integration)

    @mock.patch('readthedocs.oauth.services.github.GitHubService.get_session')
    @mock.patch('readthedocs.oauth.services.github.GitHubService.setup_webhook'
                )
    def test_update_webhook_no_provider_data(self, setup_webhook, session):
        self.integration.provider_data = None
        self.integration.save()

        session().patch.side_effect = AttributeError
        self.service.update_webhook(self.project, self.integration)

        setup_webhook.assert_called_once_with(self.project, self.integration)

    @mock.patch('readthedocs.oauth.services.github.log')
    @mock.patch('readthedocs.oauth.services.github.GitHubService.get_session')
    def test_update_webhook_value_error(self, session, mock_logger):
        session().patch.side_effect = ValueError
        self.service.update_webhook(self.project, self.integration)

        self.integration.refresh_from_db()

        self.assertIsNone(self.integration.secret)
        mock_logger.exception.assert_called_with(
            'GitHub webhook update failed for project: %s',
            self.project,
        )

    @mock.patch('readthedocs.oauth.services.github.log')
    @mock.patch('readthedocs.oauth.services.github.GitHubService.get_session')
    def test_get_provider_data_successful(self, session, mock_logger):
        self.integration.provider_data = {}
        self.integration.save()

        webhook_data = self.provider_data
        rtd_webhook_url = 'https://{domain}{path}'.format(
            domain=settings.PRODUCTION_DOMAIN,
            path=reverse(
                'api_webhook',
                kwargs={
                    'project_slug': self.project.slug,
                    'integration_pk': self.integration.pk,
                },
            ))
        webhook_data[0]["config"]["url"] = rtd_webhook_url

        session().get.return_value.status_code = 200
        session().get.return_value.json.return_value = webhook_data

        self.service.get_provider_data(self.project, self.integration)

        self.integration.refresh_from_db()

        self.assertEqual(self.integration.provider_data, webhook_data[0])
        mock_logger.info.assert_called_with(
            'GitHub integration updated with provider data for project: %s',
            self.project,
        )

    @mock.patch('readthedocs.oauth.services.github.log')
    @mock.patch('readthedocs.oauth.services.github.GitHubService.get_session')
    def test_get_provider_data_404_error(self, session, mock_logger):
        self.integration.provider_data = {}
        self.integration.save()

        session().get.return_value.status_code = 404

        self.service.get_provider_data(self.project, self.integration)

        self.integration.refresh_from_db()

        self.assertEqual(self.integration.provider_data, {})
        mock_logger.info.assert_called_with(
            'GitHub project does not exist or user does not have '
            'permissions: project=%s',
            self.project,
        )

    @mock.patch('readthedocs.oauth.services.github.log')
    @mock.patch('readthedocs.oauth.services.github.GitHubService.get_session')
    def test_get_provider_data_attribute_error(self, session, mock_logger):
        self.integration.provider_data = {}
        self.integration.save()

        session().get.side_effect = AttributeError

        self.service.get_provider_data(self.project, self.integration)

        self.integration.refresh_from_db()

        self.assertEqual(self.integration.provider_data, {})
        mock_logger.exception.assert_called_with(
            'GitHub webhook Listing failed for project: %s',
            self.project,
        )
Ejemplo n.º 2
0
class GitHubOAuthTests(TestCase):

    fixtures = ['eric', 'test_data']

    def setUp(self):
        self.client.login(username='******', password='******')
        self.user = User.objects.get(pk=1)
        self.project = Project.objects.get(slug='pip')
        self.org = RemoteOrganization.objects.create(slug='rtfd', json='')
        self.privacy = self.project.version_privacy_level
        self.service = GitHubService(user=self.user, account=None)
        self.external_version = get(Version, project=self.project, type=EXTERNAL)
        self.external_build = get(
            Build, project=self.project, version=self.external_version
        )

    def test_make_project_pass(self):
        repo_json = {
            'name': 'testrepo',
            'full_name': 'testuser/testrepo',
            'description': 'Test Repo',
            'git_url': 'git://github.com/testuser/testrepo.git',
            'private': False,
            'ssh_url': 'ssh://[email protected]:testuser/testrepo.git',
            'html_url': 'https://github.com/testuser/testrepo',
            'clone_url': 'https://github.com/testuser/testrepo.git',
        }
        repo = self.service.create_repository(
            repo_json, organization=self.org, privacy=self.privacy,
        )
        self.assertIsInstance(repo, RemoteRepository)
        self.assertEqual(repo.name, 'testrepo')
        self.assertEqual(repo.full_name, 'testuser/testrepo')
        self.assertEqual(repo.description, 'Test Repo')
        self.assertEqual(
            repo.avatar_url,
            settings.OAUTH_AVATAR_USER_DEFAULT_URL,
        )
        self.assertIn(self.user, repo.users.all())
        self.assertEqual(repo.organization, self.org)
        self.assertEqual(
            repo.clone_url, 'https://github.com/testuser/testrepo.git',
        )
        self.assertEqual(
            repo.ssh_url, 'ssh://[email protected]:testuser/testrepo.git',
        )
        self.assertEqual(repo.html_url, 'https://github.com/testuser/testrepo')

    def test_make_project_fail(self):
        repo_json = {
            'name': '',
            'full_name': '',
            'description': '',
            'git_url': '',
            'private': True,
            'ssh_url': '',
            'html_url': '',
            'clone_url': '',
        }
        github_project = self.service.create_repository(
            repo_json, organization=self.org, privacy=self.privacy,
        )
        self.assertIsNone(github_project)

    def test_make_organization(self):
        org_json = {
            'html_url': 'https://github.com/testorg',
            'name': 'Test Org',
            'email': '*****@*****.**',
            'login': '******',
            'avatar_url': 'https://images.github.com/foobar',
        }
        org = self.service.create_organization(org_json)
        self.assertIsInstance(org, RemoteOrganization)
        self.assertEqual(org.slug, 'testorg')
        self.assertEqual(org.name, 'Test Org')
        self.assertEqual(org.email, '*****@*****.**')
        self.assertEqual(org.avatar_url, 'https://images.github.com/foobar')
        self.assertEqual(org.url, 'https://github.com/testorg')

    def test_import_with_no_token(self):
        """User without a GitHub SocialToken does not return a service."""
        services = GitHubService.for_user(self.user)
        self.assertEqual(services, [])

    def test_multiple_users_same_repo(self):
        repo_json = {
            'name': '',
            'full_name': 'testrepo/multiple',
            'description': '',
            'git_url': '',
            'private': False,
            'ssh_url': '',
            'html_url': '',
            'clone_url': '',
        }

        github_project = self.service.create_repository(
            repo_json, organization=self.org, privacy=self.privacy,
        )

        user2 = User.objects.get(pk=2)
        service = GitHubService(user=user2, account=None)
        github_project_2 = service.create_repository(
            repo_json, organization=self.org, privacy=self.privacy,
        )
        self.assertIsInstance(github_project, RemoteRepository)
        self.assertIsInstance(github_project_2, RemoteRepository)
        self.assertNotEqual(github_project_2, github_project)

        github_project_3 = self.service.create_repository(
            repo_json, organization=self.org, privacy=self.privacy,
        )
        github_project_4 = service.create_repository(
            repo_json, organization=self.org, privacy=self.privacy,
        )
        self.assertIsInstance(github_project_3, RemoteRepository)
        self.assertIsInstance(github_project_4, RemoteRepository)
        self.assertEqual(github_project, github_project_3)
        self.assertEqual(github_project_2, github_project_4)

        github_project_5 = self.service.create_repository(
            repo_json, organization=self.org, privacy=self.privacy,
        )
        github_project_6 = service.create_repository(
            repo_json, organization=self.org, privacy=self.privacy,
        )

        self.assertEqual(github_project, github_project_5)
        self.assertEqual(github_project_2, github_project_6)

    @mock.patch('readthedocs.oauth.services.github.log')
    @mock.patch('readthedocs.oauth.services.github.GitHubService.get_session')
    def test_send_build_status_successful(self, session, mock_logger):
        session().post.return_value.status_code = 201
        success = self.service.send_build_status(
            self.external_build,
            BUILD_STATUS_SUCCESS
        )

        self.assertTrue(success)
        mock_logger.info.assert_called_with(
            "GitHub commit status created for project: %s, commit status: %s",
            self.project,
            BUILD_STATUS_SUCCESS
        )

    @mock.patch('readthedocs.oauth.services.github.log')
    @mock.patch('readthedocs.oauth.services.github.GitHubService.get_session')
    def test_send_build_status_404_error(self, session, mock_logger):
        session().post.return_value.status_code = 404
        success = self.service.send_build_status(
            self.external_build,
            BUILD_STATUS_SUCCESS
        )

        self.assertFalse(success)
        mock_logger.info.assert_called_with(
            'GitHub project does not exist or user does not have '
            'permissions: project=%s',
            self.project
        )

    @mock.patch('readthedocs.oauth.services.github.log')
    @mock.patch('readthedocs.oauth.services.github.GitHubService.get_session')
    def test_send_build_status_value_error(self, session, mock_logger):
        session().post.side_effect = ValueError
        success = self.service.send_build_status(
            self.external_build, BUILD_STATUS_SUCCESS
        )

        self.assertFalse(success)
        mock_logger.exception.assert_called_with(
            'GitHub commit status creation failed for project: %s',
            self.project,
        )

    @override_settings(DEFAULT_PRIVACY_LEVEL='private')
    def test_make_private_project(self):
        """
        Test ability to import ``public`` repositories under ``private`` level.
        """
        repo_json = {
            'name': 'testrepo',
            'full_name': 'testuser/testrepo',
            'description': 'Test Repo',
            'git_url': 'git://github.com/testuser/testrepo.git',
            'private': False,
            'ssh_url': 'ssh://[email protected]:testuser/testrepo.git',
            'html_url': 'https://github.com/testuser/testrepo',
            'clone_url': 'https://github.com/testuser/testrepo.git',
        }
        repo = self.service.create_repository(repo_json, organization=self.org)
        self.assertIsNotNone(repo)