Add filters to outgoing webhooks 2 (#1598)
# What this PR does ## Which issue(s) this PR fixes ## Checklist - [ ] Tests updated - [ ] Documentation added - [ ] `CHANGELOG.md` updated
This commit is contained in:
parent
1cd906ceab
commit
cfcfa0336e
4 changed files with 96 additions and 5 deletions
|
|
@ -1,22 +1,32 @@
|
|||
from django.apps import apps
|
||||
from django.core.exceptions import ObjectDoesNotExist, PermissionDenied
|
||||
from django_filters import rest_framework as filters
|
||||
from rest_framework.decorators import action
|
||||
from rest_framework.exceptions import NotFound
|
||||
from rest_framework.filters import SearchFilter
|
||||
from rest_framework.permissions import IsAuthenticated
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.viewsets import ModelViewSet
|
||||
|
||||
from apps.api.permissions import RBACPermission
|
||||
from apps.api.serializers.webhook import WebhookSerializer
|
||||
from apps.auth_token.auth import PluginAuthentication
|
||||
from apps.webhooks.models import Webhook
|
||||
from common.api_helpers.filters import ByTeamModelFieldFilterMixin, ModelFieldFilterMixin, TeamModelMultipleChoiceFilter
|
||||
from common.api_helpers.mixins import PublicPrimaryKeyMixin, TeamFilteringMixin
|
||||
|
||||
|
||||
class WebhooksFilter(ByTeamModelFieldFilterMixin, ModelFieldFilterMixin, filters.FilterSet):
|
||||
team = TeamModelMultipleChoiceFilter()
|
||||
|
||||
|
||||
class WebhooksView(TeamFilteringMixin, PublicPrimaryKeyMixin, ModelViewSet):
|
||||
authentication_classes = (PluginAuthentication,)
|
||||
permission_classes = (IsAuthenticated, RBACPermission)
|
||||
|
||||
rbac_permissions = {
|
||||
"metadata": [RBACPermission.Permissions.OUTGOING_WEBHOOKS_READ],
|
||||
"filters": [RBACPermission.Permissions.OUTGOING_WEBHOOKS_READ],
|
||||
"list": [RBACPermission.Permissions.OUTGOING_WEBHOOKS_READ],
|
||||
"retrieve": [RBACPermission.Permissions.OUTGOING_WEBHOOKS_READ],
|
||||
"create": [RBACPermission.Permissions.OUTGOING_WEBHOOKS_WRITE],
|
||||
|
|
@ -28,6 +38,10 @@ class WebhooksView(TeamFilteringMixin, PublicPrimaryKeyMixin, ModelViewSet):
|
|||
model = Webhook
|
||||
serializer_class = WebhookSerializer
|
||||
|
||||
filter_backends = [SearchFilter, filters.DjangoFilterBackend]
|
||||
search_fields = ["public_primary_key", "name"]
|
||||
filterset_class = WebhooksFilter
|
||||
|
||||
def get_queryset(self, ignore_filtering_by_available_teams=False):
|
||||
queryset = Webhook.objects.filter(
|
||||
organization=self.request.auth.organization,
|
||||
|
|
@ -48,9 +62,8 @@ class WebhooksView(TeamFilteringMixin, PublicPrimaryKeyMixin, ModelViewSet):
|
|||
# use this method to get the object from the whole organization instead of the current team
|
||||
pk = self.kwargs["pk"]
|
||||
organization = self.request.auth.organization
|
||||
|
||||
try:
|
||||
obj = organization.webhooks.get(public_primary_key=pk)
|
||||
obj = organization.webhooks.filter(*self.available_teams_lookup_args).get(public_primary_key=pk)
|
||||
except ObjectDoesNotExist:
|
||||
raise NotFound
|
||||
|
||||
|
|
@ -83,3 +96,22 @@ class WebhooksView(TeamFilteringMixin, PublicPrimaryKeyMixin, ModelViewSet):
|
|||
)[0]
|
||||
if self.request.auth.organization.pk not in enabled_webhooks_2_orgs.json_value["org_ids"]:
|
||||
raise PermissionDenied("Webhooks 2 not enabled for organization. Permission denied.")
|
||||
|
||||
@action(methods=["get"], detail=False)
|
||||
def filters(self, request):
|
||||
filter_name = request.query_params.get("search", None)
|
||||
api_root = "/api/internal/v1/"
|
||||
|
||||
filter_options = [
|
||||
{
|
||||
"name": "team",
|
||||
"type": "team_select",
|
||||
"href": api_root + "teams/",
|
||||
"global": True,
|
||||
},
|
||||
]
|
||||
|
||||
if filter_name is not None:
|
||||
filter_options = list(filter(lambda f: filter_name in f["name"], filter_options))
|
||||
|
||||
return Response(filter_options)
|
||||
|
|
|
|||
|
|
@ -8,6 +8,20 @@ export const form: { name: string; fields: FormItem[] } = {
|
|||
type: FormItemType.Input,
|
||||
validation: { required: true },
|
||||
},
|
||||
{
|
||||
name: 'team',
|
||||
label: 'Assign to team',
|
||||
description:
|
||||
'Assigning to the teams allows you to filter Outgoing Webhooks and configure their visibility. Go to OnCall -> Settings -> Team and Access Settings for more details',
|
||||
type: FormItemType.GSelect,
|
||||
extra: {
|
||||
modelName: 'grafanaTeamStore',
|
||||
displayField: 'name',
|
||||
valueField: 'id',
|
||||
showSearch: true,
|
||||
allowClear: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'trigger_type',
|
||||
label: 'Trigger type',
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { action, observable } from 'mobx';
|
||||
|
||||
import BaseStore from 'models/base_store';
|
||||
import { OutgoingWebhook } from 'models/outgoing_webhook/outgoing_webhook.types';
|
||||
import { makeRequest } from 'network';
|
||||
import { RootStore } from 'state';
|
||||
|
||||
|
|
@ -52,9 +53,11 @@ export class OutgoingWebhook2Store extends BaseStore {
|
|||
}
|
||||
|
||||
@action
|
||||
async updateItems(query = '') {
|
||||
async updateItems(query: any = '') {
|
||||
const params = typeof query === 'string' ? { search: query } : query;
|
||||
|
||||
const results = await makeRequest(`${this.path}`, {
|
||||
params: { search: query },
|
||||
params,
|
||||
});
|
||||
|
||||
this.items = {
|
||||
|
|
@ -68,9 +71,11 @@ export class OutgoingWebhook2Store extends BaseStore {
|
|||
),
|
||||
};
|
||||
|
||||
const key = typeof query === 'string' ? query : '';
|
||||
|
||||
this.searchResult = {
|
||||
...this.searchResult,
|
||||
[query]: results.map((item: OutgoingWebhook2) => item.id),
|
||||
[key]: results.map((item: OutgoingWebhook) => item.id),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,8 +17,12 @@ import Text from 'components/Text/Text';
|
|||
import WithConfirm from 'components/WithConfirm/WithConfirm';
|
||||
import OutgoingWebhook2Form from 'containers/OutgoingWebhook2Form/OutgoingWebhook2Form';
|
||||
import OutgoingWebhook2Status from 'containers/OutgoingWebhook2Status/OutgoingWebhook2Status';
|
||||
import RemoteFilters from 'containers/RemoteFilters/RemoteFilters';
|
||||
import TeamName from 'containers/TeamName/TeamName';
|
||||
import { WithPermissionControlTooltip } from 'containers/WithPermissionControl/WithPermissionControlTooltip';
|
||||
import { ActionDTO } from 'models/action';
|
||||
import { FiltersValues } from 'models/filters/filters.types';
|
||||
import { OutgoingWebhook } from 'models/outgoing_webhook/outgoing_webhook.types';
|
||||
import { OutgoingWebhook2 } from 'models/outgoing_webhook_2/outgoing_webhook_2.types';
|
||||
import { makeRequest } from 'network';
|
||||
import { PageProps, WithStoreProps } from 'state/types';
|
||||
|
|
@ -122,6 +126,11 @@ class OutgoingWebhooks2 extends React.Component<OutgoingWebhooks2Props, Outgoing
|
|||
title: 'Last run',
|
||||
dataIndex: 'last_run',
|
||||
},
|
||||
{
|
||||
width: '15%',
|
||||
title: 'Team',
|
||||
render: (item: OutgoingWebhook) => this.renderTeam(item, store.grafanaTeamStore.items),
|
||||
},
|
||||
{
|
||||
width: '20%',
|
||||
key: 'action',
|
||||
|
|
@ -139,6 +148,7 @@ class OutgoingWebhooks2 extends React.Component<OutgoingWebhooks2Props, Outgoing
|
|||
{() => (
|
||||
<>
|
||||
<div className={cx('root')}>
|
||||
{this.renderOutgoingWebhooksFilters()}
|
||||
<GTable
|
||||
emptyText={webhooks ? 'No outgoing webhooks found' : 'Loading...'}
|
||||
title={() => (
|
||||
|
|
@ -191,6 +201,36 @@ class OutgoingWebhooks2 extends React.Component<OutgoingWebhooks2Props, Outgoing
|
|||
);
|
||||
}
|
||||
|
||||
renderOutgoingWebhooksFilters() {
|
||||
const { query, store } = this.props;
|
||||
return (
|
||||
<div className={cx('filters')}>
|
||||
<RemoteFilters
|
||||
query={query}
|
||||
page="webhooks"
|
||||
grafanaTeamStore={store.grafanaTeamStore}
|
||||
onChange={this.handleFiltersChange}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
handleFiltersChange = (filters: FiltersValues, isOnMount) => {
|
||||
const { store } = this.props;
|
||||
|
||||
const { outgoingWebhook2Store } = store;
|
||||
|
||||
outgoingWebhook2Store.updateItems(filters).then(() => {
|
||||
if (isOnMount) {
|
||||
this.parseQueryParams();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
renderTeam(record: OutgoingWebhook, teams: any) {
|
||||
return <TeamName team={teams[record.team]} />;
|
||||
}
|
||||
|
||||
renderActionButtons = (record: ActionDTO) => {
|
||||
return (
|
||||
<HorizontalGroup justify="flex-end">
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue