mirror of
https://github.com/hanzoai/sentinel.git
synced 2026-09-29 22:34:33 +00:00
228 lines
9.1 KiB
Python
228 lines
9.1 KiB
Python
from __future__ import annotations
|
|
|
|
from typing import Any
|
|
|
|
import responses
|
|
|
|
from sentry.integrations.bitbucket.installed import BitbucketInstalledEndpoint
|
|
from sentry.integrations.bitbucket.integration import BitbucketIntegrationProvider, scopes
|
|
from sentry.models.integrations.integration import Integration
|
|
from sentry.models.project import Project
|
|
from sentry.models.repository import Repository
|
|
from sentry.plugins.base import plugins
|
|
from sentry.plugins.bases.issue2 import IssueTrackingPlugin2
|
|
from sentry.services.hybrid_cloud.organization.serial import serialize_rpc_organization
|
|
from sentry.silo.base import SiloMode
|
|
from sentry.testutils.cases import APITestCase
|
|
from sentry.testutils.silo import assume_test_silo_mode, control_silo_test
|
|
|
|
|
|
class BitbucketPlugin(IssueTrackingPlugin2):
|
|
slug = "bitbucket"
|
|
name = "Bitbucket Mock Plugin"
|
|
conf_key = slug
|
|
|
|
|
|
@control_silo_test
|
|
class BitbucketInstalledEndpointTest(APITestCase):
|
|
def setUp(self):
|
|
self.provider = "bitbucket"
|
|
self.path = "/extensions/bitbucket/installed/"
|
|
self.username = "sentryuser"
|
|
self.client_key = "connection:123"
|
|
self.public_key = "123abcDEFg"
|
|
self.shared_secret = "G12332434SDfsjkdfgsd"
|
|
self.base_api_url = "https://api.bitbucket.org"
|
|
self.base_url = "https://bitbucket.org"
|
|
self.domain_name = "bitbucket.org/sentryuser"
|
|
self.user_display_name = "Sentry User"
|
|
self.team_display_name = self.username
|
|
self.icon = "https://bitbucket.org/account/sentryuser/avatar/32/"
|
|
|
|
self.team_data = {
|
|
"username": self.username,
|
|
"display_name": self.team_display_name,
|
|
"account_id": "123456t256371u",
|
|
"links": {
|
|
"self": {"href": "https://api.bitbucket.org/2.0/users/sentryuser/"},
|
|
"html": {
|
|
"href": "https://bitbucket.org/%8Cde3c29fa-c919-4b59-8c43-59febd16a8e7%7D/"
|
|
},
|
|
"avatar": {"href": "https://bitbucket.org/account/sentryuser/avatar/32/"},
|
|
},
|
|
"created_on": "2018-04-18T00:46:37.374621+00:00",
|
|
"type": "team",
|
|
"uuid": "{e123-f456-g78910}",
|
|
}
|
|
self.user_data = self.team_data.copy()
|
|
self.user_data["type"] = "user"
|
|
|
|
self.user_data["display_name"] = self.user_display_name
|
|
|
|
self.metadata = {
|
|
"public_key": self.public_key,
|
|
"shared_secret": self.shared_secret,
|
|
"base_url": self.base_api_url,
|
|
"domain_name": self.domain_name,
|
|
"icon": self.icon,
|
|
"scopes": list(scopes),
|
|
"type": self.team_data["type"],
|
|
"uuid": self.team_data["uuid"],
|
|
}
|
|
|
|
self.user_metadata = self.metadata.copy()
|
|
self.user_metadata["type"] = self.user_data["type"]
|
|
self.user_metadata["domain_name"] = self.user_display_name
|
|
|
|
self.team_data_from_bitbucket: dict[str, Any] = {
|
|
"key": "sentry-bitbucket",
|
|
"eventType": "installed",
|
|
"baseUrl": self.base_url,
|
|
"sharedSecret": self.shared_secret,
|
|
"publicKey": self.public_key,
|
|
"user": self.team_data,
|
|
"productType": "bitbucket",
|
|
"baseApiUrl": self.base_api_url,
|
|
"clientKey": self.client_key,
|
|
"principal": self.team_data,
|
|
}
|
|
self.user_data_from_bitbucket = self.team_data_from_bitbucket.copy()
|
|
self.user_data_from_bitbucket["principal"] = self.user_data
|
|
|
|
self.data_without_public_key = {"identity": {"bitbucket_client_id": self.client_key}}
|
|
|
|
plugins.register(BitbucketPlugin)
|
|
|
|
def tearDown(self):
|
|
plugins.unregister(BitbucketPlugin)
|
|
super().tearDown()
|
|
|
|
def test_default_permissions(self):
|
|
# Permissions must be empty so that it will be accessible to bitbucket.
|
|
assert BitbucketInstalledEndpoint.authentication_classes == ()
|
|
assert BitbucketInstalledEndpoint.permission_classes == ()
|
|
|
|
def test_installed_with_public_key(self):
|
|
response = self.client.post(self.path, data=self.team_data_from_bitbucket)
|
|
assert response.status_code == 200
|
|
integration = Integration.objects.get(provider=self.provider, external_id=self.client_key)
|
|
assert integration.name == self.username
|
|
assert integration.metadata == self.metadata
|
|
|
|
def test_installed_without_public_key(self):
|
|
integration, created = Integration.objects.get_or_create(
|
|
provider=self.provider,
|
|
external_id=self.client_key,
|
|
defaults={"name": self.user_display_name, "metadata": self.user_metadata},
|
|
)
|
|
del self.user_data_from_bitbucket["principal"]["username"]
|
|
response = self.client.post(self.path, data=self.user_data_from_bitbucket)
|
|
assert response.status_code == 200
|
|
|
|
# assert no changes have been made to the integration
|
|
integration_after = Integration.objects.get(
|
|
provider=self.provider, external_id=self.client_key
|
|
)
|
|
assert integration.name == integration_after.name
|
|
assert integration.metadata == integration_after.metadata
|
|
|
|
def test_installed_without_username(self):
|
|
"""Test a user (not team) installation where the user has hidden their username from public view"""
|
|
|
|
# Remove username to simulate privacy mode
|
|
del self.user_data_from_bitbucket["principal"]["username"]
|
|
|
|
response = self.client.post(self.path, data=self.user_data_from_bitbucket)
|
|
assert response.status_code == 200
|
|
integration = Integration.objects.get(provider=self.provider, external_id=self.client_key)
|
|
assert integration.name == self.user_display_name
|
|
assert integration.metadata == self.user_metadata
|
|
|
|
@responses.activate
|
|
def test_plugin_migration(self):
|
|
with assume_test_silo_mode(SiloMode.REGION):
|
|
accessible_repo = Repository.objects.create(
|
|
organization_id=self.organization.id,
|
|
name="sentryuser/repo",
|
|
url="https://bitbucket.org/sentryuser/repo",
|
|
provider="bitbucket",
|
|
external_id="123456",
|
|
config={"name": "sentryuser/repo"},
|
|
)
|
|
|
|
inaccessible_repo = Repository.objects.create(
|
|
organization_id=self.organization.id,
|
|
name="otheruser/otherrepo",
|
|
url="https://bitbucket.org/otheruser/otherrepo",
|
|
provider="bitbucket",
|
|
external_id="654321",
|
|
config={"name": "otheruser/otherrepo"},
|
|
)
|
|
|
|
self.client.post(self.path, data=self.team_data_from_bitbucket)
|
|
|
|
integration = Integration.objects.get(provider=self.provider, external_id=self.client_key)
|
|
|
|
responses.add(
|
|
responses.GET,
|
|
f"https://api.bitbucket.org/2.0/repositories/{accessible_repo.name}/hooks",
|
|
json={"values": [{"description": "sentry-bitbucket-repo-hook"}]},
|
|
)
|
|
|
|
with self.tasks():
|
|
with assume_test_silo_mode(SiloMode.REGION):
|
|
org = serialize_rpc_organization(self.organization)
|
|
BitbucketIntegrationProvider().post_install(
|
|
integration=integration,
|
|
organization=org,
|
|
)
|
|
|
|
with assume_test_silo_mode(SiloMode.REGION):
|
|
assert (
|
|
Repository.objects.get(id=accessible_repo.id).integration_id == integration.id
|
|
)
|
|
|
|
assert (
|
|
Repository.objects.get(id=accessible_repo.id).provider
|
|
== "integrations:bitbucket"
|
|
)
|
|
|
|
assert Repository.objects.get(id=inaccessible_repo.id).integration_id is None
|
|
|
|
@responses.activate
|
|
def test_disable_plugin_when_fully_migrated(self):
|
|
with assume_test_silo_mode(SiloMode.REGION):
|
|
project = Project.objects.create(organization_id=self.organization.id)
|
|
|
|
plugin = plugins.get("bitbucket")
|
|
plugin.enable(project)
|
|
|
|
# Accessible to new Integration
|
|
Repository.objects.create(
|
|
organization_id=self.organization.id,
|
|
name="sentryuser/repo",
|
|
url="https://bitbucket.org/sentryuser/repo",
|
|
provider="bitbucket",
|
|
external_id="123456",
|
|
config={"name": "sentryuser/repo"},
|
|
)
|
|
|
|
self.client.post(self.path, data=self.team_data_from_bitbucket)
|
|
|
|
integration = Integration.objects.get(provider=self.provider, external_id=self.client_key)
|
|
|
|
responses.add(
|
|
responses.GET,
|
|
"https://api.bitbucket.org/2.0/repositories/sentryuser/repo/hooks",
|
|
json={"values": [{"description": "sentry-bitbucket-repo-hook"}]},
|
|
)
|
|
|
|
assert "bitbucket" in [p.slug for p in plugins.for_project(project)]
|
|
|
|
with self.tasks():
|
|
with assume_test_silo_mode(SiloMode.REGION):
|
|
org = serialize_rpc_organization(self.organization)
|
|
BitbucketIntegrationProvider().post_install(integration=integration, organization=org)
|
|
|
|
assert "bitbucket" not in [p.slug for p in plugins.for_project(project)]
|