Fix MultipleObjectsReturned error on webhook endpoints (#1996)

# What this PR does
Sometimes `CustomButtonView` returns HTTP 500 with the following error:

```
apps.alerts.models.custom_button.CustomButton.MultipleObjectsReturned: get() returned more than one CustomButton -- it returned 3!
```

This PR fixes it by adding `.distinct()` to the `CustomButton` queryset
when retrieving an instance + does the same for `WebhooksView`.

## Which issue(s) this PR fixes
Related to https://github.com/grafana/oncall-private/issues/1828

## Checklist

- [x] Unit, integration, and e2e (if applicable) tests updated
- [x] Documentation added (or `pr:no public docs` PR label added if not
required)
- [x] `CHANGELOG.md` updated (or `pr:no changelog` PR label added if not
required)
This commit is contained in:
Vadim Stepanov 2023-05-23 17:23:06 +01:00 committed by GitHub
parent c921674471
commit 06bd0454f6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 11 additions and 2 deletions

View file

@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed
- Improve plugin authentication by @vadimkerr ([#1995](https://github.com/grafana/oncall/pull/1995))
- Fix MultipleObjectsReturned error on webhook endpoints by @vadimkerr ([#1996](https://github.com/grafana/oncall/pull/1996))
## v1.2.27 (2023-05-23)

View file

@ -64,7 +64,11 @@ class CustomButtonView(TeamFilteringMixin, PublicPrimaryKeyMixin, ModelViewSet):
pk = self.kwargs["pk"]
organization = self.request.auth.organization
try:
obj = organization.custom_buttons.filter(*self.available_teams_lookup_args).get(public_primary_key=pk)
obj = (
organization.custom_buttons.filter(*self.available_teams_lookup_args)
.distinct()
.get(public_primary_key=pk)
)
except ObjectDoesNotExist:
raise NotFound

View file

@ -63,7 +63,7 @@ class WebhooksView(TeamFilteringMixin, PublicPrimaryKeyMixin, ModelViewSet):
pk = self.kwargs["pk"]
organization = self.request.auth.organization
try:
obj = organization.webhooks.filter(*self.available_teams_lookup_args).get(public_primary_key=pk)
obj = organization.webhooks.filter(*self.available_teams_lookup_args).distinct().get(public_primary_key=pk)
except ObjectDoesNotExist:
raise NotFound

View file

@ -197,6 +197,10 @@ class TeamFilteringMixin:
@property
def available_teams_lookup_args(self):
"""
This property returns a list of Q objects that are used to filter instances by teams available to the user.
NOTE: use .distinct() after filtering by available teams as it may return duplicate instances.
"""
available_teams_lookup_args = []
if not self.request.user.role == LegacyAccessControlRole.ADMIN:
available_teams_lookup_args = [