Skip to content

Commit

Permalink
[ResponseOps][Connectors] Allow to use POST method for get case infor…
Browse files Browse the repository at this point in the history
…mation in case management webhook (elastic#197437)

## Summary

Resolves elastic#178074

This PR allows to use POST method and JSON payload for body for get case
information in case management webhook.

<img width="1279" alt="Screenshot 2024-10-24 at 15 02 33"
src="https://github.com/user-attachments/assets/aaabc5b8-cd9e-46d6-aab8-85a27731bd88">

### How to test
- Create a case management webhook connector [as per
documentation](https://www.elastic.co/guide/en/kibana/master/cases-webhook-action-type.html)
- Use any public API which supports GET and POST methods 
- Use POST method for Get case information
- Verify that it validates the URL and JSON payload correctly 
- Test the connector using Test tab
- Create a rule with action using case management webhook connector
- Verify alerts are generated and action executed without any errors

### Checklist

Delete any items that are not applicable to this PR.

- [x] Any text added follows [EUI's writing
guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses
sentence case text and includes [i18n
support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md)
- [x] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios
- [x] Any UI touched in this PR is usable by keyboard only (learn more
about [keyboard accessibility](https://webaim.org/techniques/keyboard/))
  • Loading branch information
js-jankisalvi authored Nov 7, 2024
1 parent 08cf1ee commit d81d071
Show file tree
Hide file tree
Showing 13 changed files with 775 additions and 94 deletions.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions x-pack/plugins/stack_connectors/common/auth/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,5 @@ export enum WebhookMethods {
PATCH = 'patch',
POST = 'post',
PUT = 'put',
GET = 'get',
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,103 +6,183 @@
*/

import React, { FunctionComponent } from 'react';
import { css } from '@emotion/react';
import { EuiFlexGroup, EuiFlexItem, EuiText } from '@elastic/eui';
import { UseField } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib';
import {
FIELD_TYPES,
UseField,
useFormData,
} from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib';
import { Field } from '@kbn/es-ui-shared-plugin/static/forms/components';
import { fieldValidators } from '@kbn/es-ui-shared-plugin/static/forms/helpers';
import { MustacheTextFieldWrapper } from '@kbn/triggers-actions-ui-plugin/public';
import { containsExternalId, containsExternalIdOrTitle } from '../validator';
import { JsonFieldWrapper, MustacheTextFieldWrapper } from '@kbn/triggers-actions-ui-plugin/public';
import { WebhookMethods } from '../../../../common/auth/constants';
import {
containsExternalIdForGet,
containsExternalIdOrTitle,
requiredJsonForPost,
} from '../validator';
import { urlVars, urlVarsExt } from '../action_variables';
import * as i18n from '../translations';

const { emptyField, urlField } = fieldValidators;

interface Props {
display: boolean;
readOnly: boolean;
}

export const GetStep: FunctionComponent<Props> = ({ display, readOnly }) => (
<span data-test-subj="getStep" style={{ display: display ? 'block' : 'none' }}>
<EuiText>
<h3>{i18n.STEP_3}</h3>
<small>
<p>{i18n.STEP_3_DESCRIPTION}</p>
</small>
</EuiText>
<EuiFlexGroup direction="column">
<EuiFlexItem>
<UseField
path="config.getIncidentUrl"
config={{
label: i18n.GET_INCIDENT_URL,
validations: [
{
validator: urlField(i18n.GET_INCIDENT_URL_REQUIRED),
},
{ validator: containsExternalId() },
],
helpText: i18n.GET_INCIDENT_URL_HELP,
}}
component={MustacheTextFieldWrapper}
componentProps={{
euiFieldProps: {
readOnly,
'data-test-subj': 'webhookGetUrlText',
messageVariables: urlVars,
paramsProperty: 'getIncidentUrl',
buttonTitle: i18n.ADD_CASES_VARIABLE,
showButtonTitle: true,
},
}}
/>
</EuiFlexItem>
<EuiFlexItem>
<UseField
path="config.getIncidentResponseExternalTitleKey"
config={{
label: i18n.GET_INCIDENT_TITLE_KEY,
validations: [
{
validator: emptyField(i18n.GET_RESPONSE_EXTERNAL_TITLE_KEY_REQUIRED),
export const GetStep: FunctionComponent<Props> = ({ display, readOnly }) => {
const [{ config }] = useFormData({
watch: ['config.getIncidentMethod'],
});
const { getIncidentMethod = WebhookMethods.GET } = config ?? {};

return (
<span data-test-subj="getStep" style={{ display: display ? 'block' : 'none' }}>
<EuiText>
<h3>{i18n.STEP_3}</h3>
<small>
<p>{i18n.STEP_3_DESCRIPTION}</p>
</small>
</EuiText>
<EuiFlexGroup direction="column">
<EuiFlexGroup justifyContent="spaceBetween">
<EuiFlexItem grow={false}>
<UseField
path="config.getIncidentMethod"
component={Field}
config={{
label: i18n.GET_INCIDENT_METHOD,
defaultValue: WebhookMethods.GET,
type: FIELD_TYPES.SELECT,
validations: [
{
validator: emptyField(i18n.GET_METHOD_REQUIRED),
},
],
}}
css={css`
.euiFormRow__labelWrapper {
margin-bottom: 9px;
}
`}
componentProps={{
euiFieldProps: {
'data-test-subj': 'webhookGetIncidentMethodSelect',
options: [WebhookMethods.GET, WebhookMethods.POST].map((verb) => ({
text: verb.toUpperCase(),
value: verb,
})),
readOnly,
},
}}
/>
</EuiFlexItem>
<EuiFlexItem>
<UseField
path="config.getIncidentUrl"
config={{
label: i18n.GET_INCIDENT_URL,
validations: [
{
validator: urlField(i18n.GET_INCIDENT_URL_REQUIRED),
},
{ validator: containsExternalIdForGet(getIncidentMethod) },
],
helpText: i18n.GET_INCIDENT_URL_HELP,
}}
component={MustacheTextFieldWrapper}
componentProps={{
euiFieldProps: {
readOnly,
'data-test-subj': 'webhookGetUrlText',
messageVariables: urlVars,
paramsProperty: 'getIncidentUrl',
buttonTitle: i18n.ADD_CASES_VARIABLE,
showButtonTitle: true,
},
}}
/>
</EuiFlexItem>
</EuiFlexGroup>
{getIncidentMethod === WebhookMethods.POST ? (
<EuiFlexItem>
<UseField
path="config.getIncidentJson"
config={{
helpText: i18n.GET_INCIDENT_JSON_HELP,
label: i18n.GET_INCIDENT_JSON,
validations: [
{
validator: requiredJsonForPost(getIncidentMethod),
},
],
}}
component={JsonFieldWrapper}
componentProps={{
euiCodeEditorProps: {
height: '200px',
isReadOnly: readOnly,
['aria-label']: i18n.CODE_EDITOR,
},
dataTestSubj: 'webhookGetIncidentJson',
messageVariables: urlVars,
paramsProperty: 'getIncidentJson',
buttonTitle: i18n.ADD_CASES_VARIABLE,
showButtonTitle: true,
}}
/>
</EuiFlexItem>
) : null}
<EuiFlexItem>
<UseField
path="config.getIncidentResponseExternalTitleKey"
config={{
label: i18n.GET_INCIDENT_TITLE_KEY,
validations: [
{
validator: emptyField(i18n.GET_RESPONSE_EXTERNAL_TITLE_KEY_REQUIRED),
},
],
helpText: i18n.GET_INCIDENT_TITLE_KEY_HELP,
}}
component={Field}
componentProps={{
euiFieldProps: {
readOnly,
'data-test-subj': 'getIncidentResponseExternalTitleKeyText',
},
],
helpText: i18n.GET_INCIDENT_TITLE_KEY_HELP,
}}
component={Field}
componentProps={{
euiFieldProps: {
readOnly,
'data-test-subj': 'getIncidentResponseExternalTitleKeyText',
},
}}
/>
</EuiFlexItem>
<EuiFlexItem>
<UseField
path="config.viewIncidentUrl"
config={{
label: i18n.EXTERNAL_INCIDENT_VIEW_URL,
validations: [
{
validator: urlField(i18n.GET_INCIDENT_VIEW_URL_REQUIRED),
}}
/>
</EuiFlexItem>
<EuiFlexItem>
<UseField
path="config.viewIncidentUrl"
config={{
label: i18n.EXTERNAL_INCIDENT_VIEW_URL,
validations: [
{
validator: urlField(i18n.GET_INCIDENT_VIEW_URL_REQUIRED),
},
{ validator: containsExternalIdOrTitle() },
],
helpText: i18n.EXTERNAL_INCIDENT_VIEW_URL_HELP,
}}
component={MustacheTextFieldWrapper}
componentProps={{
euiFieldProps: {
readOnly,
'data-test-subj': 'viewIncidentUrlText',
messageVariables: urlVarsExt,
paramsProperty: 'viewIncidentUrl',
buttonTitle: i18n.ADD_CASES_VARIABLE,
showButtonTitle: true,
},
{ validator: containsExternalIdOrTitle() },
],
helpText: i18n.EXTERNAL_INCIDENT_VIEW_URL_HELP,
}}
component={MustacheTextFieldWrapper}
componentProps={{
euiFieldProps: {
readOnly,
'data-test-subj': 'viewIncidentUrlText',
messageVariables: urlVarsExt,
paramsProperty: 'viewIncidentUrl',
buttonTitle: i18n.ADD_CASES_VARIABLE,
showButtonTitle: true,
},
}}
/>
</EuiFlexItem>
</EuiFlexGroup>
</span>
);
}}
/>
</EuiFlexItem>
</EuiFlexGroup>
</span>
);
};
Loading

0 comments on commit d81d071

Please sign in to comment.