Skip to content

Commit

Permalink
Remove include_system_actions query from get_all
Browse files Browse the repository at this point in the history
  • Loading branch information
Zacqary committed Jan 29, 2024
1 parent 51bc88b commit 372e6a3
Show file tree
Hide file tree
Showing 12 changed files with 192 additions and 56 deletions.

This file was deleted.

This file was deleted.

14 changes: 2 additions & 12 deletions x-pack/plugins/actions/server/routes/connector/get_all/get_all.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,6 @@

import { IRouter } from '@kbn/core/server';
import { AllConnectorsResponseV1 } from '../../../../common/routes/connector/response';
import {
connectorsQuerySchemaV1,
ConnectorsRequestQueryV1,
} from '../../../../common/routes/connector/apis/connectors';
import { transformGetAllConnectorsResponseV1 } from './transforms';
import { ActionsRequestHandlerContext } from '../../../types';
import { BASE_ACTION_API_PATH } from '../../../../common';
Expand All @@ -24,18 +20,12 @@ export const getAllConnectorsRoute = (
router.get(
{
path: `${BASE_ACTION_API_PATH}/connectors`,
validate: {
query: connectorsQuerySchemaV1,
},
validate: {},
},
router.handleLegacyErrors(
verifyAccessAndContext(licenseState, async function (context, req, res) {
const query: ConnectorsRequestQueryV1 = req.query;

const actionsClient = (await context.actions).getActionsClient();
const result = await actionsClient.getAll({
includeSystemActions: query?.include_system_actions,
});
const result = await actionsClient.getAll();

const responseBody: AllConnectorsResponseV1[] = transformGetAllConnectorsResponseV1(result);
return res.ok({ body: responseBody });
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import { getAllConnectorsRoute } from './get_all';
import { httpServiceMock } from '@kbn/core/server/mocks';
import { licenseStateMock } from '../../../lib/license_state.mock';
import { mockHandlerArguments } from '../../legacy/_mock_handler_arguments';
import { verifyAccessAndContext } from '../../verify_access_and_context';
import { actionsClientMock } from '../../../actions_client/actions_client.mock';

jest.mock('../../verify_access_and_context', () => ({
verifyAccessAndContext: jest.fn(),
}));

beforeEach(() => {
jest.resetAllMocks();
(verifyAccessAndContext as jest.Mock).mockImplementation((license, handler) => handler);
});

describe('getAllConnectorsRoute', () => {
it('get all connectors with proper parameters', async () => {
const licenseState = licenseStateMock.create();
const router = httpServiceMock.createRouter();

getAllConnectorsRoute(router, licenseState);

const [config, handler] = router.get.mock.calls[0];

expect(config.path).toMatchInlineSnapshot(`"/api/actions/connectors"`);

const actionsClient = actionsClientMock.create();
actionsClient.getAll.mockResolvedValueOnce([]);

const [context, req, res] = mockHandlerArguments({ actionsClient }, {}, ['ok']);

expect(await handler(context, req, res)).toMatchInlineSnapshot(`
Object {
"body": Array [],
}
`);

expect(actionsClient.getAll).toHaveBeenCalledTimes(1);

expect(res.ok).toHaveBeenCalledWith({
body: [],
});
});

it('ensures the license allows getting all connectors', async () => {
const licenseState = licenseStateMock.create();
const router = httpServiceMock.createRouter();

getAllConnectorsRoute(router, licenseState);

const [config, handler] = router.get.mock.calls[0];

expect(config.path).toMatchInlineSnapshot(`"/api/actions/connectors"`);

const actionsClient = actionsClientMock.create();
actionsClient.getAll.mockResolvedValueOnce([]);

const [context, req, res] = mockHandlerArguments({ actionsClient }, {}, ['ok']);

await handler(context, req, res);

expect(verifyAccessAndContext).toHaveBeenCalledWith(licenseState, expect.any(Function));
});

it('ensures the license check prevents getting all connectors', async () => {
const licenseState = licenseStateMock.create();
const router = httpServiceMock.createRouter();

(verifyAccessAndContext as jest.Mock).mockImplementation(() => async () => {
throw new Error('OMG');
});

getAllConnectorsRoute(router, licenseState);

const [config, handler] = router.get.mock.calls[0];

expect(config.path).toMatchInlineSnapshot(`"/api/actions/connectors"`);

const actionsClient = actionsClientMock.create();
actionsClient.getAll.mockResolvedValueOnce([]);

const [context, req, res] = mockHandlerArguments({ actionsClient }, {}, ['ok']);

expect(handler(context, req, res)).rejects.toMatchInlineSnapshot(`[Error: OMG]`);

expect(verifyAccessAndContext).toHaveBeenCalledWith(licenseState, expect.any(Function));
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import { IRouter } from '@kbn/core/server';
import { AllConnectorsResponseV1 } from '../../../../common/routes/connector/response';
import { transformGetAllConnectorsResponseV1 } from './transforms';
import { ActionsRequestHandlerContext } from '../../../types';
import { INTERNAL_BASE_ACTION_API_PATH } from '../../../../common';
import { ILicenseState } from '../../../lib';
import { verifyAccessAndContext } from '../../verify_access_and_context';

export const getAllSystemConnectorsRoute = (
router: IRouter<ActionsRequestHandlerContext>,
licenseState: ILicenseState
) => {
router.get(
{
path: `${INTERNAL_BASE_ACTION_API_PATH}/connectors/system`,
validate: {},
},
router.handleLegacyErrors(
verifyAccessAndContext(licenseState, async function (context, req, res) {
const actionsClient = (await context.actions).getActionsClient();
const result = await actionsClient.getAll({
includeSystemActions: true,
});

const responseBody: AllConnectorsResponseV1[] = transformGetAllConnectorsResponseV1(result);
return res.ok({ body: responseBody });
})
)
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@
* 2.0.
*/

export * from './v1';
export { getAllSystemConnectorsRoute } from './get_all_system';
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
* 2.0.
*/

import type { TypeOf } from '@kbn/config-schema';
import { connectorsQuerySchemaV1 } from '..';
export { transformGetAllConnectorsResponse } from './transform_connectors_response/latest';

export type ConnectorsRequestQuery = TypeOf<typeof connectorsQuerySchemaV1>;
export { transformGetAllConnectorsResponse as transformGetAllConnectorsResponseV1 } from './transform_connectors_response/v1';
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@
* 2.0.
*/

export * from './v1';
export { transformGetAllConnectorsResponse } from './v1';
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import { ConnectorWithExtraFindData } from '../../../../../application/connector/types';
import { AllConnectorsResponseV1 } from '../../../../../../common/routes/connector/response';

export const transformGetAllConnectorsResponse = (
results: ConnectorWithExtraFindData[]
): AllConnectorsResponseV1[] => {
return results.map(
({
id,
name,
config,
actionTypeId,
isPreconfigured,
isDeprecated,
referencedByCount,
isMissingSecrets,
isSystemAction,
}) => ({
id,
name,
config,
connector_type_id: actionTypeId,
is_preconfigured: isPreconfigured,
is_deprecated: isDeprecated,
referenced_by_count: referencedByCount,
is_missing_secrets: isMissingSecrets,
is_system_action: isSystemAction,
})
);
};
2 changes: 2 additions & 0 deletions x-pack/plugins/actions/server/routes/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import { IRouter } from '@kbn/core/server';
import { UsageCounter } from '@kbn/usage-collection-plugin/server';
import { getAllConnectorsRoute } from './connector/get_all';
import { getAllSystemConnectorsRoute } from './connector/get_all_system';
import { listTypesRoute } from './connector/list_types';
import { ILicenseState } from '../lib';
import { ActionsRequestHandlerContext } from '../types';
Expand Down Expand Up @@ -45,4 +46,5 @@ export function defineRoutes(opts: RouteOptions) {
getGlobalExecutionKPIRoute(router, licenseState);

getOAuthAccessToken(router, licenseState, actionsConfigUtils);
getAllSystemConnectorsRoute(router, licenseState);
}
5 changes: 0 additions & 5 deletions x-pack/plugins/alerting/common/rule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,11 +142,6 @@ export interface RuleSystemAction {
params: RuleActionParams;
type: typeof RuleActionTypes.SYSTEM;
useAlertDataForTemplate?: boolean;
// Workaround for typescript issues where boolean types are only defined in one of the union type members
// Allow frequency and alertsFilter to be deemed present in a system action, but require them to be undefined
// This prevents code like action.frequency?.someProperty from throwing an error
frequency?: undefined;
alertsFilter?: undefined;
}

export type RuleAction = RuleDefaultAction | RuleSystemAction;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {
EuiLoadingSpinner,
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { RuleNotifyWhenType } from '@kbn/alerting-plugin/common';
import { isSystemAction, RuleDefaultAction, RuleNotifyWhenType } from '@kbn/alerting-plugin/common';
import { ActionTypeRegistryContract, RuleAction, suspendedComponentWithProps } from '../../../..';
import { useFetchRuleActionConnectors } from '../../../hooks/use_fetch_rule_action_connectors';
import { NOTIFY_WHEN_OPTIONS } from '../../rule_form/rule_notify_when';
Expand Down Expand Up @@ -51,7 +51,7 @@ export function RuleActions({
);
}

const getNotifyText = (action: RuleAction) =>
const getNotifyText = (action: RuleDefaultAction) =>
(NOTIFY_WHEN_OPTIONS.find((options) => options.value === action.frequency?.notifyWhen)
?.inputDisplay ||
action.frequency?.notifyWhen) ??
Expand Down Expand Up @@ -93,14 +93,18 @@ export function RuleActions({
<EuiFlexItem grow={false}>
<EuiIcon size="s" type="bell" />
</EuiFlexItem>
<EuiFlexItem>
<EuiText
data-test-subj={`actionConnectorName-${index}-${actionName || actionTypeId}`}
size="xs"
>
{String(getNotifyText(action))}
</EuiText>
</EuiFlexItem>
{!isSystemAction(action) && (
<EuiFlexItem>
<EuiText
data-test-subj={`actionConnectorName-${index}-${
actionName || actionTypeId
}`}
size="xs"
>
{String(getNotifyText(action))}
</EuiText>
</EuiFlexItem>
)}
</EuiFlexGroup>
</EuiFlexItem>
</EuiFlexGroup>
Expand Down

0 comments on commit 372e6a3

Please sign in to comment.