|
@@ -1,4 +1,4 @@
|
|
|
-from typing import Any, MutableMapping
|
|
|
+from typing import Any, MutableMapping, Optional
|
|
|
|
|
|
from django.db import IntegrityError
|
|
|
from django.http import Http404
|
|
@@ -9,7 +9,7 @@ from rest_framework.request import Request
|
|
|
from sentry import features
|
|
|
from sentry.api.serializers.rest_framework.base import CamelSnakeModelSerializer
|
|
|
from sentry.api.validators.integrations import validate_provider
|
|
|
-from sentry.models import ExternalActor, Organization, Team, User
|
|
|
+from sentry.models import ExternalActor, Organization, OrganizationIntegration, Team, User
|
|
|
from sentry.types.integrations import ExternalProviders, get_provider_choices
|
|
|
|
|
|
AVAILABLE_PROVIDERS = {
|
|
@@ -23,27 +23,35 @@ class ExternalActorSerializerBase(CamelSnakeModelSerializer): # type: ignore
|
|
|
external_id = serializers.CharField()
|
|
|
external_name = serializers.CharField(required=True)
|
|
|
provider = serializers.ChoiceField(choices=get_provider_choices(AVAILABLE_PROVIDERS))
|
|
|
+ integration_id = serializers.IntegerField(required=False, allow_null=True)
|
|
|
|
|
|
@property
|
|
|
def organization(self) -> Organization:
|
|
|
return self.context["organization"]
|
|
|
|
|
|
- def get_actor_id(self, validated_data: MutableMapping[str, Any]) -> int:
|
|
|
- return int(validated_data.pop(self._actor_key).actor_id)
|
|
|
+ def validate_integration_id(self, integration_id: str) -> Optional[str]:
|
|
|
+ if not integration_id:
|
|
|
+ return None
|
|
|
|
|
|
- def get_provider_id(self, validated_data: MutableMapping[str, Any]) -> int:
|
|
|
- provider_name_option = validated_data.pop("provider", None)
|
|
|
+ integration_query = OrganizationIntegration.objects.filter(
|
|
|
+ organization=self.organization, integration_id=integration_id
|
|
|
+ )
|
|
|
+ if not integration_query.exists():
|
|
|
+ raise serializers.ValidationError("Integration does not exist for this organization")
|
|
|
+ return integration_id
|
|
|
+
|
|
|
+ def validate_provider(self, provider_name_option: str) -> int:
|
|
|
provider = validate_provider(provider_name_option, available_providers=AVAILABLE_PROVIDERS)
|
|
|
return int(provider.value)
|
|
|
|
|
|
+ def get_actor_id(self, validated_data: MutableMapping[str, Any]) -> int:
|
|
|
+ return int(validated_data.pop(self._actor_key).actor_id)
|
|
|
+
|
|
|
def create(self, validated_data: MutableMapping[str, Any]) -> ExternalActor:
|
|
|
actor_id = self.get_actor_id(validated_data)
|
|
|
- provider = self.get_provider_id(validated_data)
|
|
|
-
|
|
|
return ExternalActor.objects.get_or_create(
|
|
|
**validated_data,
|
|
|
actor_id=actor_id,
|
|
|
- provider=provider,
|
|
|
organization=self.organization,
|
|
|
)
|
|
|
|
|
@@ -53,8 +61,7 @@ class ExternalActorSerializerBase(CamelSnakeModelSerializer): # type: ignore
|
|
|
# Discard the object ID passed by the API.
|
|
|
if "id" in validated_data:
|
|
|
validated_data.pop("id")
|
|
|
- if "provider" in validated_data:
|
|
|
- validated_data["provider"] = self.get_provider_id({**validated_data})
|
|
|
+
|
|
|
if self._actor_key in validated_data:
|
|
|
validated_data["actor_id"] = self.get_actor_id({**validated_data})
|
|
|
|
|
@@ -86,7 +93,7 @@ class ExternalUserSerializer(ExternalActorSerializerBase):
|
|
|
|
|
|
class Meta:
|
|
|
model = ExternalActor
|
|
|
- fields = ["user_id", "external_name", "provider"]
|
|
|
+ fields = ["user_id", "external_name", "provider", "integration_id"]
|
|
|
|
|
|
|
|
|
class ExternalTeamSerializer(ExternalActorSerializerBase):
|
|
@@ -103,7 +110,7 @@ class ExternalTeamSerializer(ExternalActorSerializerBase):
|
|
|
|
|
|
class Meta:
|
|
|
model = ExternalActor
|
|
|
- fields = ["team_id", "external_name", "provider"]
|
|
|
+ fields = ["team_id", "external_name", "provider", "integration_id"]
|
|
|
|
|
|
|
|
|
class ExternalActorEndpointMixin:
|