def test_with_valid_signature_header(self): payload = """ { "action": "will-be-saved-in-db", "sender": { "login": "******", "id": 1002300 } } """.strip() signature = github.calculate_signature( settings.KIWI_GITHUB_APP_SECRET, json.dumps(json.loads(payload)).encode()) initial_db_count = WebhookPayload.objects.count() response = self.client.post(self.url, json.loads(payload), content_type='application/json', HTTP_X_HUB_SIGNATURE=signature, HTTP_X_GITHUB_EVENT='some-event') self.assertContains(response, 'ok') # the hook handler saves to DB self.assertEqual(initial_db_count + 1, WebhookPayload.objects.count())
def test_with_valid_signature_header_without_event_header(self): payload = """ { "action": "will-be-saved-in-db", "sender": { "login": "******", "id": 1002300 } } """.strip() signature = github.calculate_signature( settings.KIWI_GITHUB_APP_SECRET, json.dumps(json.loads(payload)).encode()) # X-GitHub-Event header is missing !!! response = self.client.post(self.url, json.loads(payload), content_type='application/json', HTTP_X_HUB_SIGNATURE=signature) self.assertIsInstance(response, HttpResponseForbidden) self.assertContains(response, 'Missing event', status_code=HTTPStatus.FORBIDDEN)
def test_valid_signature_header(self): request = self.factory.post(self.url) request.META["HTTP_X_HUB_SIGNATURE"] = github.calculate_signature( b"secret", request.body) result = github.verify_signature(request, b"secret") self.assertIsInstance(result, bool) self.assertTrue(result)
def test_installation_unconfigured_then_nothing(self): for schema_name in ['public', self.tenant.schema_name]: with schema_context(schema_name): self.assertFalse( Product.objects.filter(name='kiwitcms-bot/test').exists()) self.assertFalse( BugSystem.objects.filter( name='GitHub Issues for kiwitcms-bot/test').exists()) # simulate unconfigured installation owned by the same user # who owns the GitHub repository app_inst = AppInstallationFactory(sender=self.social_user.uid, ) payload = """ { "action": "created", "repository": { "id": 225221463, "full_name": "kiwitcms-bot/test", "private": false, "owner": { }, "html_url": "https://github.com/kiwitcms-bot/test", "description": "A test repository", "fork": false }, "sender": { "login": "******", "id": %d }, "installation": { "id": %d, "node_id": "MDIzOkludGVncmF0aW9uSW5zdGFsbGF0aW9uNTQ5ODkwOA==" } }""".strip() % (self.social_user.user.username, self.social_user.uid, app_inst.installation) signature = github.calculate_signature( settings.KIWI_GITHUB_APP_SECRET, json.dumps(json.loads(payload)).encode()) response = self.client.post(self.url, json.loads(payload), content_type='application/json', HTTP_X_HUB_SIGNATURE=signature, HTTP_X_GITHUB_EVENT='repository') self.assertContains(response, 'ok') # assert no new products have been created for schema_name in ['public', self.tenant.schema_name]: with schema_context(schema_name): self.assertFalse( Product.objects.filter(name='kiwitcms-bot/test').exists()) self.assertFalse( BugSystem.objects.filter( name='GitHub Issues for kiwitcms-bot/test').exists())
def test_installation_unconfigured_then_nothing(self): for schema_name in ['public', self.tenant.schema_name]: with schema_context(schema_name): self.assertFalse(Version.objects.filter(value='v2.0').exists()) # simulate unconfigured installation owned by the same user # who owns the GitHub repository app_inst = AppInstallationFactory(sender=self.social_user.uid, ) payload = """ { "ref": "v2.0", "ref_type": "tag", "master_branch": "master", "description": "an empty repository", "pusher_type": "user", "repository": { "full_name": "kiwitcms-bot/example", "private": false, "owner": { "login": "******", "site_admin": false }, "description": "an empty repository", "fork": true, "default_branch": "master" }, "sender": { "login": "******", "id": %d, "type": "User", "site_admin": false }, "installation": { "id": %d, "node_id": "MDIzOkludGVncmF0aW9uSW5zdGFsbGF0aW9uNTY1MTMwNQ==" } }""".strip() % (self.social_user.user.username, self.social_user.uid, app_inst.installation) signature = github.calculate_signature( settings.KIWI_GITHUB_APP_SECRET, json.dumps(json.loads(payload)).encode()) response = self.client.post(self.url, json.loads(payload), content_type='application/json', HTTP_X_HUB_SIGNATURE=signature, HTTP_X_GITHUB_EVENT='create') self.assertContains(response, 'ok') # assert no new version have been created for schema_name in ['public', self.tenant.schema_name]: with schema_context(schema_name): self.assertFalse(Version.objects.filter(value='v2.0').exists())
def test_hook_ping(self): payload = """ { "zen": "Mind your words, they are important.", "sender": { "login": "******", "id": 1002300 } } """.strip() signature = github.calculate_signature( settings.KIWI_GITHUB_APP_SECRET, json.dumps(json.loads(payload)).encode()) response = self.client.post(self.url, json.loads(payload), content_type='application/json', HTTP_X_HUB_SIGNATURE=signature, HTTP_X_GITHUB_EVENT='ping') # initial ping responds with a pong self.assertContains(response, 'pong')
def test_return_format(self): self.assertEqual(github.calculate_signature(b'secret', b'content'), 'sha1=0bd98d1a7514a85bbb8377bb8d750b6e01494056')
def test_should_not_crash_when_version_already_exists(self, github_rpc): example_repo = unittest.mock.MagicMock() example_repo.fork = False example_repo.full_name = 'kiwitcms-bot/example' example_repo.description = 'Example description' example_repo.html_url = 'https://github.com/%s' % example_repo.full_name github_rpc.return_value.get_repo = unittest.mock.MagicMock( side_effect=[example_repo]) # make sure version already exists for schema_name in ['public', self.tenant.schema_name]: with schema_context(schema_name): classification, _ = Classification.objects.get_or_create( name='test-products', ) product, _ = Product.objects.get_or_create( name=example_repo.full_name, description=example_repo.description, classification=classification, ) Version.objects.get_or_create(product=product, value='v2.0') self.assertTrue(Version.objects.filter(value='v2.0').exists()) # simulate already configured installation owned by the same user # who owns the GitHub repository app_inst = AppInstallationFactory( sender=self.social_user.uid, tenant_pk=self.tenant.pk, ) payload = """ { "ref": "v2.0", "ref_type": "tag", "master_branch": "master", "description": "an empty repository", "pusher_type": "user", "repository": { "full_name": "kiwitcms-bot/example", "private": false, "owner": { "login": "******", "site_admin": false }, "description": "an empty repository", "fork": false, "default_branch": "master" }, "sender": { "login": "******", "id": %d, "type": "User", "site_admin": false }, "installation": { "id": %d, "node_id": "MDIzOkludGVncmF0aW9uSW5zdGFsbGF0aW9uNTY1MTMwNQ==" } }""".strip() % (self.social_user.user.username, self.social_user.uid, app_inst.installation) signature = github.calculate_signature( settings.KIWI_GITHUB_APP_SECRET, json.dumps(json.loads(payload)).encode()) response = self.client.post(self.url, json.loads(payload), content_type='application/json', HTTP_X_HUB_SIGNATURE=signature, HTTP_X_GITHUB_EVENT='create') self.assertContains(response, 'ok') with tenant_context(self.tenant): self.assertTrue(Version.objects.filter(value='v2.0').exists())
def test_sender_has_access_to_multiple_tenants(self): with schema_context('public'): self.private_tenant.authorized_users.add(self.social_user.user) self.tenant.authorized_users.add(self.social_user.user) # assert products don't exist initially for tenant in [self.public_tenant, self.tenant, self.private_tenant]: with tenant_context(tenant): self.assertFalse( Product.objects.filter( name='kiwitcms-bot/example').exists()) self.assertFalse( Product.objects.filter(name='kiwitcms-bot/test').exists()) self.assertFalse( BugSystem.objects.filter( name='GitHub Issues for kiwitcms-bot/example').exists( )) self.assertFalse( BugSystem.objects.filter( name='GitHub Issues for kiwitcms-bot/test').exists()) payload = """ { "action": "created", "installation": { "id": 5651399, "account": { "login": "******", "id": 44892260, "site_admin": false }, "repository_selection": "all", "html_url": "https://github.com/settings/installations/5651399", "single_file_name": null }, "repositories": [ { "id": 224524413, "node_id": "MDEwOlJlcG9zaXRvcnkyMjQ1MjQ0MTM=", "name": "example", "full_name": "kiwitcms-bot/example", "private": false }, { "id": 225221463, "node_id": "MDEwOlJlcG9zaXRvcnkyMjUyMjE0NjM=", "name": "test", "full_name": "kiwitcms-bot/test", "private": false } ], "requester": null, "sender": { "login": "******", "id": %d, "site_admin": false } }""".strip() % (self.social_user.user.username, self.social_user.uid) signature = github.calculate_signature( settings.KIWI_GITHUB_APP_SECRET, json.dumps(json.loads(payload)).encode()) response = self.client.post(self.url, json.loads(payload), content_type='application/json', HTTP_X_HUB_SIGNATURE=signature, HTTP_X_GITHUB_EVENT='installation') self.assertContains(response, 'ok') with schema_context('public'): self.assertTrue( AppInstallation.objects.filter(installation=5651399, sender=self.social_user.uid, tenant_pk=None).exists()) # assert products have *NOT* been imported anywhere for tenant in [self.public_tenant, self.tenant, self.private_tenant]: with tenant_context(tenant): self.assertFalse( Product.objects.filter( name='kiwitcms-bot/example').exists()) self.assertFalse( Product.objects.filter(name='kiwitcms-bot/test').exists()) self.assertFalse( BugSystem.objects.filter( name='GitHub Issues for kiwitcms-bot/example').exists( )) self.assertFalse( BugSystem.objects.filter( name='GitHub Issues for kiwitcms-bot/test').exists())
def test_sender_only_has_access_to_private_tenant(self, github_rpc): example_repo = unittest.mock.MagicMock() example_repo.fork = False example_repo.full_name = 'kiwitcms-bot/example' example_repo.description = 'Example description' example_repo.html_url = 'https://github.com/%s' % example_repo.full_name test_repo = unittest.mock.MagicMock() test_repo.fork = False test_repo.full_name = 'kiwitcms-bot/test' test_repo.description = 'Test description' test_repo.html_url = 'https://github.com/%s' % test_repo.full_name github_rpc.return_value.get_repo = unittest.mock.MagicMock( side_effect=[example_repo, test_repo]) with schema_context('public'): # make sure social_user can access private_tenant self.private_tenant.authorized_users.add(self.social_user.user) # assert products don't exist initially for tenant in [self.public_tenant, self.tenant, self.private_tenant]: with tenant_context(tenant): self.assertFalse( Product.objects.filter( name='kiwitcms-bot/example').exists()) self.assertFalse( Product.objects.filter(name='kiwitcms-bot/test').exists()) self.assertFalse( BugSystem.objects.filter( name='GitHub Issues for kiwitcms-bot/example').exists( )) self.assertFalse( BugSystem.objects.filter( name='GitHub Issues for kiwitcms-bot/test').exists()) payload = """ { "action": "created", "installation": { "id": 5651305, "account": { "login": "******", "id": 44892260, "site_admin": false }, "repository_selection": "all", "html_url": "https://github.com/settings/installations/5651305", "single_file_name": null }, "repositories": [ { "id": 224524413, "node_id": "MDEwOlJlcG9zaXRvcnkyMjQ1MjQ0MTM=", "name": "example", "full_name": "kiwitcms-bot/example", "private": false }, { "id": 225221463, "node_id": "MDEwOlJlcG9zaXRvcnkyMjUyMjE0NjM=", "name": "test", "full_name": "kiwitcms-bot/test", "private": false } ], "requester": null, "sender": { "login": "******", "id": %d, "site_admin": false } }""".strip() % (self.social_user.user.username, self.social_user.uid) signature = github.calculate_signature( settings.KIWI_GITHUB_APP_SECRET, json.dumps(json.loads(payload)).encode()) response = self.client.post(self.url, json.loads(payload), content_type='application/json', HTTP_X_HUB_SIGNATURE=signature, HTTP_X_GITHUB_EVENT='installation') self.assertContains(response, 'ok') with schema_context('public'): self.assertTrue( AppInstallation.objects.filter( installation=5651305, sender=self.social_user.uid, tenant_pk=self.private_tenant.pk).exists()) # assert products have been imported *ONLY* on private.tenant for tenant in [self.public_tenant, self.tenant]: with tenant_context(tenant): self.assertFalse( Product.objects.filter( name='kiwitcms-bot/example').exists()) self.assertFalse( Product.objects.filter(name='kiwitcms-bot/test').exists()) self.assertFalse( BugSystem.objects.filter( name='GitHub Issues for kiwitcms-bot/example').exists( )) self.assertFalse( BugSystem.objects.filter( name='GitHub Issues for kiwitcms-bot/test').exists()) with tenant_context(self.private_tenant): self.assertTrue( Product.objects.filter(name='kiwitcms-bot/example').exists()) self.assertTrue( Product.objects.filter(name='kiwitcms-bot/test').exists()) self.assertTrue( BugSystem.objects.filter( name='GitHub Issues for kiwitcms-bot/example').exists()) self.assertTrue( BugSystem.objects.filter( name='GitHub Issues for kiwitcms-bot/test').exists())
def test_sender_not_in_db(self): with schema_context('public'): initial_installation_count = AppInstallation.objects.count() payload = """ { "action": "created", "installation": { "id": 5651305, "account": { "login": "******", "id": 44892260, "site_admin": false }, "repository_selection": "all", "html_url": "https://github.com/settings/installation/5651305", "single_file_name": null }, "repositories": [ { "id": 224524413, "node_id": "MDEwOlJlcG9zaXRvcnkyMjQ1MjQ0MTM=", "name": "example", "full_name": "kiwitcms-bot/example", "private": false }, { "id": 225221463, "node_id": "MDEwOlJlcG9zaXRvcnkyMjUyMjE0NjM=", "name": "test", "full_name": "kiwitcms-bot/test", "private": false } ], "requester": null, "sender": { "login": "******", "id": 99999999, "site_admin": false } }""".strip() signature = github.calculate_signature( settings.KIWI_GITHUB_APP_SECRET, json.dumps(json.loads(payload)).encode()) response = self.client.post(self.url, json.loads(payload), content_type='application/json', HTTP_X_HUB_SIGNATURE=signature, HTTP_X_GITHUB_EVENT='installation') self.assertContains(response, 'ok') with schema_context('public'): self.assertEqual(initial_installation_count + 1, AppInstallation.objects.count()) self.assertTrue( AppInstallation.objects.filter(installation=5651305, sender=99999999, tenant_pk=None).exists())
def test_installation_configured_then_creates_new_product_and_bugsystem( self, github_rpc): test_repo = unittest.mock.MagicMock() test_repo.fork = False test_repo.full_name = 'kiwitcms-bot/test' test_repo.description = 'A test repository' test_repo.html_url = 'https://github.com/%s' % test_repo.full_name github_rpc.return_value.get_repo = unittest.mock.MagicMock( side_effect=[test_repo]) for schema_name in ['public', self.tenant.schema_name]: with schema_context(schema_name): self.assertFalse( Product.objects.filter(name='kiwitcms-bot/test').exists()) self.assertFalse( BugSystem.objects.filter( name='GitHub Issues for kiwitcms-bot/test').exists()) # simulate already configured installation owned by the same user # who owns the GitHub repository app_inst = AppInstallationFactory( sender=self.social_user.uid, tenant_pk=self.tenant.pk, ) # NOTE: testing with private repository b/c these are still added as products payload = """ { "action": "created", "repository": { "id": 225221463, "full_name": "kiwitcms-bot/test", "private": true, "owner": { }, "html_url": "https://github.com/kiwitcms-bot/test", "description": "A test repository", "fork": false }, "sender": { "login": "******", "id": %d }, "installation": { "id": %d, "node_id": "MDIzOkludGVncmF0aW9uSW5zdGFsbGF0aW9uNTQ5ODkwOA==" } }""".strip() % (self.social_user.user.username, self.social_user.uid, app_inst.installation) signature = github.calculate_signature( settings.KIWI_GITHUB_APP_SECRET, json.dumps(json.loads(payload)).encode()) response = self.client.post(self.url, json.loads(payload), content_type='application/json', HTTP_X_HUB_SIGNATURE=signature, HTTP_X_GITHUB_EVENT='repository') self.assertContains(response, 'ok') with tenant_context(self.tenant): new_product = Product.objects.get(name='kiwitcms-bot/test') self.assertEqual(new_product.description, 'A test repository') new_bugsystem = BugSystem.objects.get( name='GitHub Issues for kiwitcms-bot/test') self.assertEqual(new_bugsystem.tracker_type, 'tcms_github_app.issues.Integration') self.assertEqual(new_bugsystem.base_url, 'https://github.com/kiwitcms-bot/test')
def test_return_format(self): self.assertEqual( github.calculate_signature(b"secret", b"content"), "sha1=0bd98d1a7514a85bbb8377bb8d750b6e01494056", )
def test_adds_new_data_when_it_doesnt_exist(self, github_rpc): mock_repo = unittest.mock.MagicMock() mock_repo.fork = False mock_repo.full_name = 'kiwitcms-bot/IT-CPE' mock_repo.description = '' mock_repo.html_url = 'https://github.com/%s' % mock_repo.full_name github_rpc.return_value.get_repo = unittest.mock.MagicMock(side_effect=[mock_repo]) # assert products don't exist initially for schema_name in ['public', self.tenant.schema_name]: with schema_context(schema_name): self.assertFalse(Product.objects.filter(name='kiwitcms-bot/IT-CPE').exists()) self.assertFalse( BugSystem.objects.filter( name='GitHub Issues for kiwitcms-bot/IT-CPE').exists()) # simulate already configured installation owned by the same user # who owns the GitHub repository app_inst = AppInstallationFactory( sender=self.social_user.uid, tenant_pk=self.tenant.pk, ) payload = """ { "action": "added", "installation": { "id": %d, "account": { }, "repository_selection": "all", "single_file_name": null }, "repository_selection": "all", "repositories_added": [ { "id": 281502467, "node_id": "MDEwOlJlcG9zaXRvcnkyODE1MDI0Njc=", "name": "IT-CPE", "full_name": "kiwitcms-bot/IT-CPE", "private": false } ], "repositories_removed": [ ], "requester": null, "sender": { "login": "******", "id": %d } }""".strip() % (app_inst.installation, self.social_user.user.username, self.social_user.uid) signature = github.calculate_signature( settings.KIWI_GITHUB_APP_SECRET, json.dumps(json.loads(payload)).encode()) response = self.client.post(self.url, json.loads(payload), content_type='application/json', HTTP_X_HUB_SIGNATURE=signature, HTTP_X_GITHUB_EVENT='installation_repositories') self.assertContains(response, 'ok') # assert products have been imported *ONLY* on public with tenant_context(self.tenant): new_product = Product.objects.get(name='kiwitcms-bot/IT-CPE') self.assertEqual(new_product.description, 'GitHub repository') new_bugsystem = BugSystem.objects.get(name='GitHub Issues for kiwitcms-bot/IT-CPE') self.assertEqual(new_bugsystem.tracker_type, 'tcms_github_app.issues.Integration') self.assertEqual(new_bugsystem.base_url, 'https://github.com/kiwitcms-bot/IT-CPE')