diff --git a/x-pack/plugins/actions/server/builtin_action_types/jira/service.ts b/x-pack/plugins/actions/server/builtin_action_types/jira/service.ts index 1deb19e9d52ea..a3262a526e2f4 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/jira/service.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/jira/service.ts @@ -27,7 +27,7 @@ import { } from './types'; import * as i18n from './translations'; -import { request, getErrorMessage, throwIfRequestIsNotValid } from '../lib/axios_utils'; +import { request, getErrorMessage, throwIfResponseIsNotValid } from '../lib/axios_utils'; import { ActionsConfigurationUtilities } from '../../actions_config'; const VERSION = '2'; @@ -181,7 +181,7 @@ export const createExternalService = ( configurationUtilities, }); - throwIfRequestIsNotValid({ + throwIfResponseIsNotValid({ res, requiredAttributesToBeInTheResponse: ['id', 'key'], }); @@ -235,7 +235,7 @@ export const createExternalService = ( configurationUtilities, }); - throwIfRequestIsNotValid({ + throwIfResponseIsNotValid({ res, requiredAttributesToBeInTheResponse: ['id'], }); @@ -281,7 +281,7 @@ export const createExternalService = ( configurationUtilities, }); - throwIfRequestIsNotValid({ + throwIfResponseIsNotValid({ res, }); @@ -319,7 +319,7 @@ export const createExternalService = ( configurationUtilities, }); - throwIfRequestIsNotValid({ + throwIfResponseIsNotValid({ res, requiredAttributesToBeInTheResponse: ['id', 'created'], }); @@ -351,7 +351,7 @@ export const createExternalService = ( configurationUtilities, }); - throwIfRequestIsNotValid({ + throwIfResponseIsNotValid({ res, requiredAttributesToBeInTheResponse: ['capabilities'], }); @@ -382,7 +382,7 @@ export const createExternalService = ( configurationUtilities, }); - throwIfRequestIsNotValid({ + throwIfResponseIsNotValid({ res, }); @@ -397,7 +397,7 @@ export const createExternalService = ( configurationUtilities, }); - throwIfRequestIsNotValid({ + throwIfResponseIsNotValid({ res, }); @@ -429,7 +429,7 @@ export const createExternalService = ( configurationUtilities, }); - throwIfRequestIsNotValid({ + throwIfResponseIsNotValid({ res, }); @@ -444,7 +444,7 @@ export const createExternalService = ( configurationUtilities, }); - throwIfRequestIsNotValid({ + throwIfResponseIsNotValid({ res, }); @@ -507,7 +507,7 @@ export const createExternalService = ( configurationUtilities, }); - throwIfRequestIsNotValid({ + throwIfResponseIsNotValid({ res, }); @@ -535,7 +535,7 @@ export const createExternalService = ( configurationUtilities, }); - throwIfRequestIsNotValid({ + throwIfResponseIsNotValid({ res, }); diff --git a/x-pack/plugins/actions/server/builtin_action_types/lib/axios_utils.test.ts b/x-pack/plugins/actions/server/builtin_action_types/lib/axios_utils.test.ts index 1953f99bba21b..d0177e0e5a8a2 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/lib/axios_utils.test.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/lib/axios_utils.test.ts @@ -15,7 +15,7 @@ import { request, patch, getErrorMessage, - throwIfRequestIsNotValid, + throwIfResponseIsNotValid, createAxiosResponse, } from './axios_utils'; import { loggingSystemMock } from '../../../../../../src/core/server/mocks'; @@ -300,19 +300,19 @@ describe('getErrorMessage', () => { }); }); -describe('throwIfRequestIsNotValid', () => { +describe('throwIfResponseIsNotValid', () => { const res = createAxiosResponse({ headers: { ['content-type']: 'application/json' }, data: { incident: { id: '1' } }, }); test('it does NOT throw if the request is valid', () => { - expect(() => throwIfRequestIsNotValid({ res })).not.toThrow(); + expect(() => throwIfResponseIsNotValid({ res })).not.toThrow(); }); test('it does throw if the content-type is not json', () => { expect(() => - throwIfRequestIsNotValid({ + throwIfResponseIsNotValid({ res: { ...res, headers: { ['content-type']: 'text/html' } }, }) ).toThrow( @@ -320,9 +320,9 @@ describe('throwIfRequestIsNotValid', () => { ); }); - test('it does throw if the content-type is defined', () => { + test('it does throw if the content-type is undefined', () => { expect(() => - throwIfRequestIsNotValid({ + throwIfResponseIsNotValid({ res: { ...res, headers: {} }, }) ).toThrow( @@ -332,7 +332,7 @@ describe('throwIfRequestIsNotValid', () => { test('it does throw if the data is not an object or array', () => { expect(() => - throwIfRequestIsNotValid({ + throwIfResponseIsNotValid({ res: { ...res, data: 'string' }, }) ).toThrow('Response is not a valid JSON'); @@ -340,7 +340,7 @@ describe('throwIfRequestIsNotValid', () => { test('it does NOT throw if the data is an array', () => { expect(() => - throwIfRequestIsNotValid({ + throwIfResponseIsNotValid({ res: { ...res, data: ['test'] }, }) ).not.toThrow(); @@ -348,7 +348,7 @@ describe('throwIfRequestIsNotValid', () => { test.each(['', [], {}])('it does NOT throw if the data is %p', (data) => { expect(() => - throwIfRequestIsNotValid({ + throwIfResponseIsNotValid({ res: { ...res, data }, }) ).not.toThrow(); @@ -356,22 +356,22 @@ describe('throwIfRequestIsNotValid', () => { test('it does throw if the required attribute is not in the response', () => { expect(() => - throwIfRequestIsNotValid({ res, requiredAttributesToBeInTheResponse: ['not-exist'] }) + throwIfResponseIsNotValid({ res, requiredAttributesToBeInTheResponse: ['not-exist'] }) ).toThrow('Response is missing at least one of the expected fields: not-exist'); }); - test('it does NOT throw if the required attribute is not in the response and the data are an array', () => { + test('it does throw if the required attribute are defined and the data is an array', () => { expect(() => - throwIfRequestIsNotValid({ + throwIfResponseIsNotValid({ res: { ...res, data: ['test'] }, requiredAttributesToBeInTheResponse: ['not-exist'], }) - ).not.toThrow(); + ).toThrow('Response is missing at least one of the expected fields: not-exist'); }); test('it does NOT throw if the value of the required attribute is null', () => { expect(() => - throwIfRequestIsNotValid({ + throwIfResponseIsNotValid({ res: { ...res, data: { id: null } }, requiredAttributesToBeInTheResponse: ['id'], }) diff --git a/x-pack/plugins/actions/server/builtin_action_types/lib/axios_utils.ts b/x-pack/plugins/actions/server/builtin_action_types/lib/axios_utils.ts index 13c5732b73b3d..43c9d276e6574 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/lib/axios_utils.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/lib/axios_utils.ts @@ -78,7 +78,7 @@ export const getErrorMessage = (connector: string, msg: string) => { return `[Action][${connector}]: ${msg}`; }; -export const throwIfRequestIsNotValid = ({ +export const throwIfResponseIsNotValid = ({ res, requiredAttributesToBeInTheResponse = [], }: { @@ -110,19 +110,27 @@ export const throwIfRequestIsNotValid = ({ throw new Error('Response is not a valid JSON'); } - /** - * Check for required attributes only if provided and - * data is an object and not an array - */ - if (requiredAttributesToBeInTheResponse.length > 0 && !Array.isArray(data)) { + if (requiredAttributesToBeInTheResponse.length > 0) { + const requiredAttributesError = new Error( + `Response is missing at least one of the expected fields: ${requiredAttributesToBeInTheResponse.join( + ',' + )}` + ); + + /** + * If the response is an array and requiredAttributesToBeInTheResponse + * are not empty then we thrown an error assuming that the consumer + * expects an object response and not an array. + */ + + if (Array.isArray(data)) { + throw requiredAttributesError; + } + requiredAttributesToBeInTheResponse.forEach((attr) => { // Check only for undefined as null is a valid value if (data[attr] === undefined) { - throw new Error( - `Response is missing at least one of the expected fields: ${requiredAttributesToBeInTheResponse.join( - ',' - )}` - ); + throw requiredAttributesError; } }); } diff --git a/x-pack/plugins/actions/server/builtin_action_types/resilient/service.ts b/x-pack/plugins/actions/server/builtin_action_types/resilient/service.ts index b3d1eaf18dcef..a469c631fac37 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/resilient/service.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/resilient/service.ts @@ -24,7 +24,7 @@ import { } from './types'; import * as i18n from './translations'; -import { getErrorMessage, request, throwIfRequestIsNotValid } from '../lib/axios_utils'; +import { getErrorMessage, request, throwIfResponseIsNotValid } from '../lib/axios_utils'; import { ActionsConfigurationUtilities } from '../../actions_config'; const VIEW_INCIDENT_URL = `#incidents`; @@ -134,7 +134,7 @@ export const createExternalService = ( configurationUtilities, }); - throwIfRequestIsNotValid({ + throwIfResponseIsNotValid({ res, }); @@ -186,7 +186,7 @@ export const createExternalService = ( configurationUtilities, }); - throwIfRequestIsNotValid({ + throwIfResponseIsNotValid({ res, requiredAttributesToBeInTheResponse: ['id', 'create_date'], }); @@ -221,7 +221,7 @@ export const createExternalService = ( configurationUtilities, }); - throwIfRequestIsNotValid({ + throwIfResponseIsNotValid({ res, }); @@ -258,7 +258,7 @@ export const createExternalService = ( configurationUtilities, }); - throwIfRequestIsNotValid({ + throwIfResponseIsNotValid({ res, }); @@ -287,7 +287,7 @@ export const createExternalService = ( configurationUtilities, }); - throwIfRequestIsNotValid({ + throwIfResponseIsNotValid({ res, }); @@ -313,7 +313,7 @@ export const createExternalService = ( configurationUtilities, }); - throwIfRequestIsNotValid({ + throwIfResponseIsNotValid({ res, }); @@ -338,7 +338,7 @@ export const createExternalService = ( configurationUtilities, }); - throwIfRequestIsNotValid({ + throwIfResponseIsNotValid({ res, }); diff --git a/x-pack/plugins/actions/server/builtin_action_types/swimlane/service.ts b/x-pack/plugins/actions/server/builtin_action_types/swimlane/service.ts index 7f7d57c73a84c..d917d7f5677bb 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/swimlane/service.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/swimlane/service.ts @@ -9,7 +9,7 @@ import { Logger } from '@kbn/logging'; import axios from 'axios'; import { ActionsConfigurationUtilities } from '../../actions_config'; -import { getErrorMessage, request, throwIfRequestIsNotValid } from '../lib/axios_utils'; +import { getErrorMessage, request, throwIfResponseIsNotValid } from '../lib/axios_utils'; import { getBodyForEventAction } from './helpers'; import { CreateCommentParams, @@ -90,7 +90,7 @@ export const createExternalService = ( url: getPostRecordUrl(appId), }); - throwIfRequestIsNotValid({ + throwIfResponseIsNotValid({ res, requiredAttributesToBeInTheResponse: ['id', 'name', 'createdDate'], }); @@ -130,7 +130,7 @@ export const createExternalService = ( url: getPostRecordIdUrl(appId, params.incidentId), }); - throwIfRequestIsNotValid({ + throwIfResponseIsNotValid({ res, requiredAttributesToBeInTheResponse: ['id', 'name', 'modifiedDate'], });