def setUp(self): super().setUp() self.url = reverse("sentry-api-0-organization-key-transactions-list", args=[self.org.slug]) self.team1 = self.create_team(organization=self.org, name="Team A") self.team2 = self.create_team(organization=self.org, name="Team B") self.team3 = self.create_team(organization=self.org, name="Team C") self.team4 = self.create_team(organization=self.org, name="Team D") self.team5 = self.create_team(organization=self.org, name="Team E") for team in [ self.team1, self.team2, self.team3, self.team4, self.team5 ]: self.project.add_team(team) # only join teams 1,2,3 for team in [self.team1, self.team2, self.team3]: self.create_team_membership(team, user=self.user) TeamKeyTransaction.objects.bulk_create([ TeamKeyTransaction( organization=self.org, project_team=project_team, transaction=self.event_data["transaction"], ) for project_team in ProjectTeam.objects.filter( project=self.project, team__in=[self.team2, self.team3]) ] + [ TeamKeyTransaction( organization=self.org, project_team=project_team, transaction="other-transaction", ) for project_team in ProjectTeam.objects.filter( project=self.project, team__in=[self.team3, self.team4]) ])
def test_get_key_transaction_my_teams(self): team1 = self.create_team(organization=self.org, name="Team A") team2 = self.create_team(organization=self.org, name="Team B") team3 = self.create_team(organization=self.org, name="Team C") # should not be in response because we never joined this team self.create_team(organization=self.org, name="Team D") # only join teams 1,2,3 for team in [team1, team2, team3]: self.create_team_membership(team, user=self.user) self.project.add_team(team) TeamKeyTransaction.objects.bulk_create( [ TeamKeyTransaction( organization=self.org, project_team=project_team, transaction=self.event_data["transaction"], ) for project_team in ProjectTeam.objects.filter( project=self.project, team__in=[team1, team2] ) ] + [ TeamKeyTransaction( organization=self.org, project_team=project_team, transaction="other-transaction", ) for project_team in ProjectTeam.objects.filter( project=self.project, team__in=[team2, team3] ) ] ) with self.feature(self.features): response = self.client.get( self.url, data={ "project": [self.project.id], "transaction": self.event_data["transaction"], "team": "myteams", }, format="json", ) assert response.status_code == 200, response.content assert response.data == [ { "team": str(team1.id), }, { "team": str(team2.id), }, ]
def test_post_key_transaction_limit_is_per_team(self): team1 = self.create_team(organization=self.org, name="Team Foo") self.create_team_membership(team1, user=self.user) self.project.add_team(team1) team2 = self.create_team(organization=self.org, name="Team Bar") self.create_team_membership(team2, user=self.user) self.project.add_team(team2) TeamKeyTransaction.objects.bulk_create([ TeamKeyTransaction( team=team, organization=self.org, transaction=f"{self.event_data['transaction']}-{i}", project=self.project, ) for team in [team1, team2] for i in range(MAX_TEAM_KEY_TRANSACTIONS - 1) ]) with self.feature(self.features): response = self.client.post( self.url, data={ "project": [self.project.id], "transaction": self.event_data["transaction"], "team": [team1.id, team2.id], }, format="json", ) assert response.status_code == 201 key_transactions = TeamKeyTransaction.objects.filter( team__in=[team1, team2]) assert len(key_transactions) == 2 * MAX_TEAM_KEY_TRANSACTIONS
def test_post_key_transactions_exceed_limit(self): team = self.create_team(organization=self.org, name="Team Foo") self.create_team_membership(team, user=self.user) self.project.add_team(team) TeamKeyTransaction.objects.bulk_create([ TeamKeyTransaction( team=team, organization=self.org, transaction=f"{self.event_data['transaction']}-{i}", project=self.project, ) for i in range(MAX_TEAM_KEY_TRANSACTIONS) ]) with self.feature(self.features): response = self.client.post( self.url, data={ "project": [self.project.id], "transaction": self.event_data["transaction"], "team": [team.id], }, format="json", ) assert response.status_code == 400 assert response.data == { "non_field_errors": [ f"At most {MAX_TEAM_KEY_TRANSACTIONS} Key Transactions can be added for a team" ] }
def post(self, request: Request, organization) -> Response: """Create a Key Transaction""" if not self.has_feature(organization, request): return Response(status=404) project = self.get_project(request, organization) with transaction.atomic(): serializer = serializers.TeamKeyTransactionSerializer( data=request.data, context={ "mode": "create", "request": request, "organization": organization, }, ) if serializer.is_valid(): data = serializer.validated_data base_filter = { "organization": organization, "transaction": data["transaction"], } project_teams = ProjectTeam.objects.filter( project=project, team__in=data["team"]) if len(project_teams) < len(data["team"]): # some teams do not have access to the specified project return Response( {"detail": "Team does not have access to project"}, status=400) keyed_transaction_team_ids = set( TeamKeyTransaction.objects.values_list( "project_team__team_id", flat=True).filter(**base_filter, project_team__in=project_teams)) if len(keyed_transaction_team_ids) == len(data["team"]): # all teams already have the specified transaction marked as key return Response(status=204) try: unkeyed_project_teams = project_teams.exclude( team_id__in=keyed_transaction_team_ids) TeamKeyTransaction.objects.bulk_create([ TeamKeyTransaction(**base_filter, project_team=project_team) for project_team in unkeyed_project_teams ]) return Response(status=201) # Even though we tried to avoid it, the TeamKeyTransaction was created already except IntegrityError: return Response(status=409) return Response(serializer.errors, status=400)
def post(self, request, organization): """ Create a Key Transaction """ if not self.has_feature(request, organization): return Response(status=404) project = self.get_project(request, organization) if not self.has_team_feature(request, organization): base_filter = {"organization": organization, "owner": request.user} with transaction.atomic(): serializer = serializers.KeyTransactionSerializer( data=request.data, context=base_filter) if serializer.is_valid(): data = serializer.validated_data base_filter["transaction"] = data["transaction"] base_filter["project"] = project if KeyTransaction.objects.filter(**base_filter).exists(): return Response(status=204) try: KeyTransaction.objects.create(**base_filter) return Response(status=201) # Even though we tried to avoid it, this KeyTransaction was created already except IntegrityError: return Response(status=204) return Response(serializer.errors, status=400) with transaction.atomic(): serializer = serializers.TeamKeyTransactionSerializer( data=request.data, context={ "mode": "create", "request": request, "organization": organization, }, ) if serializer.is_valid(): data = serializer.validated_data base_filter = { "organization": organization, "project": project, "transaction": data["transaction"], } keyed_transaction_team_ids = set( TeamKeyTransaction.objects.values_list( "team_id", flat=True).filter(**base_filter, team__in=data["team"])) if len(keyed_transaction_team_ids) == len(data["team"]): return Response(status=204) try: # TeamKeyTransaction.objects.create(**base_filter) TeamKeyTransaction.objects.bulk_create([ TeamKeyTransaction(**base_filter, team=team) for team in data["team"] if team.id not in keyed_transaction_team_ids ]) return Response(status=201) # Even though we tried to avoid it, the TeamKeyTransaction was created already except IntegrityError: return Response(status=409) return Response(serializer.errors, status=400)