Skip to content

Commit

Permalink
[8.15] [Tines connector] Improve error handling and fallback (#191263) (
Browse files Browse the repository at this point in the history
#191491)

# Backport

This will backport the following commits from `main` to `8.15`:
- [[Tines connector] Improve error handling and fallback
(#191263)](#191263)

<!--- Backport version: 9.4.3 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sqren/backport)

<!--BACKPORT [{"author":{"name":"Sergi
Massaneda","email":"sergi.massaneda@elastic.co"},"sourceCommit":{"committedDate":"2024-08-27T12:10:48Z","message":"[Tines
connector] Improve error handling and fallback (#191263)\n\n##
Summary\r\n\r\nFrom:
https://github.com/elastic/kibana/issues/188115\r\n\r\nImprovements of
the Tines connector:\r\n\r\n- Original Axios error passed back from
`getResponseErrorMessage` to the\r\nsub-actions framework, instead of
returning `Unknown API error` string.\r\nThe error appears in the error
toast so the user has more information\r\nabout the
problem:\r\n\r\nBefore:\r\n<img width=\"975\"
alt=\"before\"\r\nsrc=\"https://github.com/user-attachments/assets/0fdfd085-a4d6-4ebe-b1ae-0f62332b4f5c\">\r\n\r\nAfter:\r\n<img
width=\"975\"
alt=\"after\"\r\nsrc=\"https://github.com/user-attachments/assets/1019c8ce-c97c-4564-8ec0-eca303706cfa\">\r\n\r\n\r\n-
Fallback input (direct webhook URL) now appears when there's
some\r\nerror. Before this change, the fallback input only appeared when
the\r\nTines API response was incomplete. Proper callout message
added:\r\n\r\n<img width=\"975\" alt=\"Error
fallback\"\r\nsrc=\"https://github.com/user-attachments/assets/b8f46df5-5dfe-42cb-88cc-f10e12a07e25\">\r\n\r\nCo-authored-by:
Elastic Machine
<elasticmachine@users.noreply.github.com>","sha":"ffd4076538cdd41c41651a09e11fb3eef8144b85","branchLabelMapping":{"^v8.16.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:enhancement","Team:
SecuritySolution","backport:prev-minor","v8.16.0"],"title":"[Tines
connector] Improve error handling and
fallback","number":191263,"url":"https://github.com/elastic/kibana/pull/191263","mergeCommit":{"message":"[Tines
connector] Improve error handling and fallback (#191263)\n\n##
Summary\r\n\r\nFrom:
https://github.com/elastic/kibana/issues/188115\r\n\r\nImprovements of
the Tines connector:\r\n\r\n- Original Axios error passed back from
`getResponseErrorMessage` to the\r\nsub-actions framework, instead of
returning `Unknown API error` string.\r\nThe error appears in the error
toast so the user has more information\r\nabout the
problem:\r\n\r\nBefore:\r\n<img width=\"975\"
alt=\"before\"\r\nsrc=\"https://github.com/user-attachments/assets/0fdfd085-a4d6-4ebe-b1ae-0f62332b4f5c\">\r\n\r\nAfter:\r\n<img
width=\"975\"
alt=\"after\"\r\nsrc=\"https://github.com/user-attachments/assets/1019c8ce-c97c-4564-8ec0-eca303706cfa\">\r\n\r\n\r\n-
Fallback input (direct webhook URL) now appears when there's
some\r\nerror. Before this change, the fallback input only appeared when
the\r\nTines API response was incomplete. Proper callout message
added:\r\n\r\n<img width=\"975\" alt=\"Error
fallback\"\r\nsrc=\"https://github.com/user-attachments/assets/b8f46df5-5dfe-42cb-88cc-f10e12a07e25\">\r\n\r\nCo-authored-by:
Elastic Machine
<elasticmachine@users.noreply.github.com>","sha":"ffd4076538cdd41c41651a09e11fb3eef8144b85"}},"sourceBranch":"main","suggestedTargetBranches":[],"targetPullRequestStates":[{"branch":"main","label":"v8.16.0","branchLabelMappingKey":"^v8.16.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/191263","number":191263,"mergeCommit":{"message":"[Tines
connector] Improve error handling and fallback (#191263)\n\n##
Summary\r\n\r\nFrom:
https://github.com/elastic/kibana/issues/188115\r\n\r\nImprovements of
the Tines connector:\r\n\r\n- Original Axios error passed back from
`getResponseErrorMessage` to the\r\nsub-actions framework, instead of
returning `Unknown API error` string.\r\nThe error appears in the error
toast so the user has more information\r\nabout the
problem:\r\n\r\nBefore:\r\n<img width=\"975\"
alt=\"before\"\r\nsrc=\"https://github.com/user-attachments/assets/0fdfd085-a4d6-4ebe-b1ae-0f62332b4f5c\">\r\n\r\nAfter:\r\n<img
width=\"975\"
alt=\"after\"\r\nsrc=\"https://github.com/user-attachments/assets/1019c8ce-c97c-4564-8ec0-eca303706cfa\">\r\n\r\n\r\n-
Fallback input (direct webhook URL) now appears when there's
some\r\nerror. Before this change, the fallback input only appeared when
the\r\nTines API response was incomplete. Proper callout message
added:\r\n\r\n<img width=\"975\" alt=\"Error
fallback\"\r\nsrc=\"https://github.com/user-attachments/assets/b8f46df5-5dfe-42cb-88cc-f10e12a07e25\">\r\n\r\nCo-authored-by:
Elastic Machine
<elasticmachine@users.noreply.github.com>","sha":"ffd4076538cdd41c41651a09e11fb3eef8144b85"}}]}]
BACKPORT-->

Co-authored-by: Sergi Massaneda <sergi.massaneda@elastic.co>
  • Loading branch information
kibanamachine and semd authored Aug 27, 2024
1 parent ee067b6 commit 4f2a101
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -467,6 +467,50 @@ describe('TinesParamsFields renders', () => {
webhookUrl
);
});

it('should render webhook url fallback when stories request has error', () => {
const errorMessage = 'something broke';
mockUseSubActionStories.mockReturnValueOnce({
isLoading: false,
response: { stories: [story] },
error: new Error(errorMessage),
});

const wrapper = mountWithIntl(
<TinesParamsFields
actionParams={{}}
errors={emptyErrors}
editAction={mockEditAction}
index={index}
executionMode={ActionConnectorMode.ActionForm}
/>
);

expect(wrapper.find('[data-test-subj="tines-fallbackCallout"]').exists()).toBe(true);
expect(wrapper.find('[data-test-subj="tines-webhookUrlInput"]').exists()).toBe(true);
});

it('should render webhook url fallback when webhooks request has error', () => {
const errorMessage = 'something broke';
mockUseSubActionWebhooks.mockReturnValueOnce({
isLoading: false,
response: { webhooks: [webhook] },
error: new Error(errorMessage),
});

const wrapper = mountWithIntl(
<TinesParamsFields
actionParams={{}}
errors={emptyErrors}
editAction={mockEditAction}
index={index}
executionMode={ActionConnectorMode.ActionForm}
/>
);

expect(wrapper.find('[data-test-subj="tines-fallbackCallout"]').exists()).toBe(true);
expect(wrapper.find('[data-test-subj="tines-webhookUrlInput"]').exists()).toBe(true);
});
});

describe('subActions error', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,10 @@ const TinesParamsFields: React.FunctionComponent<ActionParamsProps<TinesExecuteA
}
}, [toasts, storiesError, webhooksError]);

const showFallbackFrom = useMemo<'Story' | 'Webhook' | 'any' | null>(() => {
const showFallbackFrom = useMemo<'Story' | 'Webhook' | 'any' | 'error' | null>(() => {
if (storiesError || webhooksError) {
return 'error';
}
if (incompleteStories && !selectedStoryOption) {
return 'Story';
}
Expand All @@ -150,7 +153,9 @@ const TinesParamsFields: React.FunctionComponent<ActionParamsProps<TinesExecuteA
return null;
}, [
webhookUrl,
storiesError,
incompleteStories,
webhooksError,
incompleteWebhooks,
selectedStoryOption,
selectedWebhookOption,
Expand Down Expand Up @@ -276,7 +281,19 @@ const TinesParamsFields: React.FunctionComponent<ActionParamsProps<TinesExecuteA

{showFallbackFrom != null && (
<EuiFlexItem>
{showFallbackFrom !== 'any' && (
{showFallbackFrom === 'error' && (
<>
<EuiCallOut
title={i18n.WEBHOOK_URL_ERROR_FALLBACK_TITLE}
color="primary"
data-test-subj="tines-fallbackCallout"
>
{i18n.WEBHOOK_URL_ERROR_FALLBACK}
</EuiCallOut>
<EuiSpacer size="s" />
</>
)}
{(showFallbackFrom === 'Story' || showFallbackFrom === 'Webhook') && (
<>
<EuiCallOut
title={i18n.WEBHOOK_URL_FALLBACK_TITLE}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,20 @@ export const WEBHOOK_URL_FALLBACK_TEXT = (entity: 'Story' | 'Webhook') =>
values: { entity, limit: API_MAX_RESULTS },
defaultMessage: `Not possible to retrieve more than {limit} results from the Tines {entity} API. If your {entity} does not appear in the list, please fill the Webhook URL below`,
});

export const WEBHOOK_URL_ERROR_FALLBACK_TITLE = i18n.translate(
'xpack.stackConnectors.security.tines.params.webhookUrlErrorFallbackTitle',
{
defaultMessage: 'Error using Tines API',
}
);
export const WEBHOOK_URL_ERROR_FALLBACK = i18n.translate(
'xpack.stackConnectors.security.tines.params.webhookUrlErrorFallback',
{
defaultMessage:
'There seems to be an issue retrieving Stories or Webhooks using the Tines API. Alternatively, you can set the Tines Webhook URL in the input below',
}
);
export const WEBHOOK_URL_HELP = i18n.translate(
'xpack.stackConnectors.security.tines.params.webhookUrlHelp',
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* 2.0.
*/

import axios, { AxiosInstance } from 'axios';
import axios, { AxiosError, AxiosInstance, AxiosResponse } from 'axios';
import { actionsConfigMock } from '@kbn/actions-plugin/server/actions_config.mock';
import { actionsMock } from '@kbn/actions-plugin/server/mocks';
import { loggingSystemMock } from '@kbn/core-logging-server-mocks';
Expand Down Expand Up @@ -140,6 +140,28 @@ describe('TinesConnector', () => {
});
});

describe('Error handling', () => {
let error: AxiosError;

beforeEach(() => {
error = new AxiosError();
});

it('should return status text api error', () => {
error.response = { status: 401, statusText: 'Unauthorized' } as AxiosResponse;
// @ts-expect-error protected method
const errorMessage = connector.getResponseErrorMessage(error);
expect(errorMessage).toEqual('API Error: Unauthorized');
});

it('should return original error', () => {
error.toString = () => 'Network Error';
// @ts-expect-error protected method
const errorMessage = connector.getResponseErrorMessage(error);
expect(errorMessage).toEqual('Network Error');
});
});

describe('getWebhooks', () => {
beforeAll(() => {
mockRequest.mockReturnValue({ data: { agents: [webhookAgent], meta: { pages: 1 } } });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,13 +121,10 @@ export class TinesConnector extends SubActionConnector<TinesConfig, TinesSecrets
}

protected getResponseErrorMessage(error: AxiosError): string {
if (!error.response?.status) {
return 'Unknown API Error';
if (error.response?.statusText) {
return `API Error: ${error.response?.statusText}`;
}
if (error.response.status === 401) {
return 'Unauthorized API Error';
}
return `API Error: ${error.response?.statusText}`;
return error.toString();
}

public async getStories(): Promise<TinesStoriesActionResponse> {
Expand Down

0 comments on commit 4f2a101

Please sign in to comment.