Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Disable action types in UI when license doesn't support it #59819

Merged
Merged
Show file tree
Hide file tree
Changes from 78 commits
Commits
Show all changes
80 commits
Select commit Hold shift + click to select a range
bf35822
Initial work
mikecote Mar 5, 2020
ea73855
Handle errors in update action API
mikecote Mar 5, 2020
2088182
Add unit tests for APIs
mikecote Mar 5, 2020
3215084
Verify action type before scheduling action task
mikecote Mar 5, 2020
6564c8b
Make actions plugin.execute throw error if action type is disabled
mikecote Mar 5, 2020
fe4ea91
Bug fixes
mikecote Mar 5, 2020
a78c999
Make action executor throw when action type isn't enabled
mikecote Mar 5, 2020
c5c7f1b
Add test suite for basic license
mikecote Mar 5, 2020
988ab1f
Merge branch 'actions/ensure-action-type-function' of github.com:mike…
mikecote Mar 5, 2020
b5e28f8
Fix ESLint errors
mikecote Mar 6, 2020
c10d719
Merge branch 'actions/license-checks' of github.com:elastic/kibana in…
mikecote Mar 6, 2020
4dfe082
Merge branch 'actions/ensure-action-type-function' of github.com:mike…
mikecote Mar 6, 2020
4401328
Stop action task from re-running when license check fails
mikecote Mar 6, 2020
dfc787a
Fix failing tests
mikecote Mar 6, 2020
6b54409
Attempt 1 to fix CI
mikecote Mar 6, 2020
bb561f8
Merge with upstream branch
mikecote Mar 6, 2020
4152be8
ESLint fixes
mikecote Mar 6, 2020
9f29e5f
Merge branch 'actions/ensure-action-type-function' of github.com:mike…
mikecote Mar 6, 2020
5c66bf2
Merge branch 'actions/license-checks' of github.com:elastic/kibana in…
mikecote Mar 9, 2020
cfe33cf
Merge branch 'actions/ensure-action-type-function' of github.com:mike…
mikecote Mar 9, 2020
e1def42
Return enabledInConfig and enabledInLicense from actions get types API
mikecote Mar 9, 2020
4d35018
Disable cards that have invalid license in create connector flyout
mikecote Mar 9, 2020
9af1336
Create sendResponse function on ActionTypeDisabledError
mikecote Mar 9, 2020
4c38702
Make disabled action types by config return 403
mikecote Mar 9, 2020
33235e1
Remove switch case
mikecote Mar 9, 2020
da91d38
Fix ESLint
mikecote Mar 9, 2020
d5292e6
Merge branch 'actions/license-checks' of github.com:elastic/kibana in…
mikecote Mar 9, 2020
e443fa0
Merge branch 'actions/license-checks' of github.com:elastic/kibana in…
mikecote Mar 9, 2020
f4c9a33
Merge branch 'actions/ensure-action-type-function' of github.com:mike…
mikecote Mar 9, 2020
06f327b
Merge with upstream
mikecote Mar 9, 2020
86b6cea
Merge branch 'actions/alerting-verify-action-type' of github.com:mike…
mikecote Mar 9, 2020
b8c3fea
Disable when creating alert action
mikecote Mar 10, 2020
ac4cf30
Merge with upstream
mikecote Mar 10, 2020
a2124bc
Return minimumLicenseRequired in /types API
mikecote Mar 10, 2020
bf07236
Disable row in connectors when action type is disabled
mikecote Mar 10, 2020
e7bd542
Fix failing jest test
mikecote Mar 11, 2020
9daf4ae
Some refactoring
mikecote Mar 11, 2020
3c238e3
Card in edit alert flyout
mikecote Mar 11, 2020
92fb600
Merge branch 'actions/license-checks' of github.com:elastic/kibana in…
mikecote Mar 11, 2020
bafd86d
Merge branch 'actions/license-checks' of github.com:elastic/kibana in…
mikecote Mar 12, 2020
00e9971
Sort action types by name
mikecote Mar 12, 2020
adef683
Add tooltips to create connector action type selector
mikecote Mar 12, 2020
d5c5c64
Add tooltips to alert flyout action type selector
mikecote Mar 12, 2020
cd3473c
Add get more actions link in alert flyout
mikecote Mar 12, 2020
9f1d8ef
Add callout when creating a connector
mikecote Mar 12, 2020
80a7b16
Typos
mikecote Mar 12, 2020
4d3380c
remove float right and use flexgroup
andreadelrio Mar 13, 2020
2a4b74c
replace pixels with eui variables
andreadelrio Mar 13, 2020
cfc1306
turn on sass lint for triggers_actions_ui dir
andreadelrio Mar 13, 2020
fa19216
trying to add padding around cards
andreadelrio Mar 13, 2020
53ba44e
Merge pull request #1 from andreadelrio/actions/license-checks-ui-design
mikecote Mar 13, 2020
eab9d5c
Merge branch 'actions/license-checks' of github.com:elastic/kibana in…
mikecote Mar 13, 2020
a381b97
Merge branch 'actions/license-checks-ui' of https://github.com/mikeco…
andreadelrio Mar 13, 2020
0b3fd7a
Add callout in edit alert screen when some actions are disabled
mikecote Mar 13, 2020
81d5878
improve card selection for Add Connector flyout
andreadelrio Mar 13, 2020
72f7e9a
Merge pull request #2 from andreadelrio/actions/license-checks-ui-des…
mikecote Mar 13, 2020
f36ddb8
Fix cards for create connector
mikecote Mar 16, 2020
10f029a
Add tests
mikecote Mar 16, 2020
d65d3ec
Merge branch 'actions/license-checks' of github.com:elastic/kibana in…
mikecote Mar 16, 2020
7423659
ESLint issue
mikecote Mar 16, 2020
5e5838d
Cleanup
mikecote Mar 16, 2020
33a8204
Cleanup pt2
mikecote Mar 16, 2020
e72f45e
Fix type check errors
mikecote Mar 16, 2020
ae5d2a1
moving to 3-columns cards for connector selection
andreadelrio Mar 16, 2020
421dd17
Merge pull request #3 from andreadelrio/license-checks-ui-design-2
mikecote Mar 16, 2020
0d34c9c
Merge branch 'actions/license-checks' of github.com:elastic/kibana in…
mikecote Mar 17, 2020
e1123b4
Merge branch 'actions/license-checks-ui' of github.com:mikecote/kiban…
mikecote Mar 17, 2020
b497dfd
Change re-enable to enable terminology
mikecote Mar 17, 2020
6209871
Revert "Change re-enable to enable terminology"
mikecote Mar 17, 2020
d8c6b47
Add re-enable comment
mikecote Mar 17, 2020
ea2588c
Remove unecessary fragment
mikecote Mar 17, 2020
2ad9a2f
Add type to actionTypeNodes
mikecote Mar 17, 2020
377ae5f
Fix EuiLink to not have opacity of 0.7 when not hovered
mikecote Mar 18, 2020
603a332
design cleanup in progress
andreadelrio Mar 18, 2020
43a602a
updating classNames
andreadelrio Mar 18, 2020
00f091e
Merge branch 'actions/license-checks-ui' of https://github.com/mikeco…
andreadelrio Mar 18, 2020
e6d2b42
using EuiIconTip
andreadelrio Mar 18, 2020
f0ca2a9
Merge pull request #4 from andreadelrio/license-checks-ui-design-3
mikecote Mar 18, 2020
f9aefcf
Remove label on icon tip
mikecote Mar 18, 2020
1650b8a
Fix failing jest test
mikecote Mar 19, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .sass-lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ files:
- 'x-pack/legacy/plugins/rollup/**/*.s+(a|c)ss'
- 'x-pack/legacy/plugins/security/**/*.s+(a|c)ss'
- 'x-pack/legacy/plugins/canvas/**/*.s+(a|c)ss'
- 'x-pack/plugins/triggers_actions_ui/**/*.s+(a|c)ss'
ignore:
- 'x-pack/legacy/plugins/canvas/shareable_runtime/**/*.s+(a|c)ss'
- 'x-pack/legacy/plugins/lens/**/*.s+(a|c)ss'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import * as i18n from './translations';
import {
ActionsConnectorsContextProvider,
ConnectorAddFlyout,
ActionType,
} from '../../../../../../../../plugins/triggers_actions_ui/public';
import { Connector } from '../../../../containers/case/configure/types';
import { useKibana } from '../../../../lib/kibana';
Expand All @@ -41,11 +42,14 @@ interface Props {
refetchConnectors: () => void;
selectedConnector: string;
}
const actionTypes = [
const actionTypes: ActionType[] = [
{
id: '.servicenow',
name: 'ServiceNow',
enabled: true,
enabledInConfig: true,
enabledInLicense: true,
minimumLicenseRequired: 'platinum',
},
];

Expand Down
5 changes: 5 additions & 0 deletions x-pack/plugins/actions/common/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,15 @@
* you may not use this file except in compliance with the Elastic License.
*/

import { LicenseType } from '../../licensing/common/types';

export interface ActionType {
id: string;
name: string;
enabled: boolean;
enabledInConfig: boolean;
enabledInLicense: boolean;
minimumLicenseRequired: LicenseType;
}

export interface ActionResult {
Expand Down
6 changes: 6 additions & 0 deletions x-pack/plugins/actions/server/action_type_registry.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ describe('get()', () => {

describe('list()', () => {
test('returns list of action types', () => {
mockedLicenseState.isLicenseValidForActionType.mockReturnValue({ isValid: true });
const actionTypeRegistry = new ActionTypeRegistry(actionTypeRegistryParams);
actionTypeRegistry.register({
id: 'my-action-type',
Expand All @@ -145,8 +146,13 @@ describe('list()', () => {
id: 'my-action-type',
name: 'My action type',
enabled: true,
enabledInConfig: true,
enabledInLicense: true,
minimumLicenseRequired: 'basic',
},
]);
expect(mockedActionsConfig.isActionTypeEnabled).toHaveBeenCalled();
expect(mockedLicenseState.isLicenseValidForActionType).toHaveBeenCalled();
});
});

Expand Down
5 changes: 4 additions & 1 deletion x-pack/plugins/actions/server/action_type_registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,10 @@ export class ActionTypeRegistry {
return Array.from(this.actionTypes).map(([actionTypeId, actionType]) => ({
id: actionTypeId,
name: actionType.name,
enabled: this.actionsConfigUtils.isActionTypeEnabled(actionTypeId),
minimumLicenseRequired: actionType.minimumLicenseRequired,
enabled: this.isActionTypeEnabled(actionTypeId),
enabledInConfig: this.actionsConfigUtils.isActionTypeEnabled(actionTypeId),
enabledInLicense: this.licenseState.isLicenseValidForActionType(actionType).isValid === true,
}));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ describe('loadActionTypes', () => {
id: 'test',
name: 'Test',
enabled: true,
enabledInConfig: true,
enabledInLicense: true,
minimumLicenseRequired: 'basic',
},
];
http.get.mockResolvedValueOnce(resolvedValue);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import { ActionType } from '../../types';
import { actionTypeCompare } from './action_type_compare';

test('should sort enabled action types first', async () => {
const actionTypes: ActionType[] = [
{
id: '1',
minimumLicenseRequired: 'basic',
name: 'first',
enabled: true,
enabledInConfig: true,
enabledInLicense: true,
},
{
id: '2',
minimumLicenseRequired: 'gold',
name: 'second',
enabled: false,
enabledInConfig: true,
enabledInLicense: false,
},
{
id: '3',
minimumLicenseRequired: 'basic',
name: 'third',
enabled: true,
enabledInConfig: true,
enabledInLicense: true,
},
];
const result = [...actionTypes].sort(actionTypeCompare);
expect(result[0]).toEqual(actionTypes[0]);
expect(result[1]).toEqual(actionTypes[2]);
expect(result[2]).toEqual(actionTypes[1]);
});

test('should sort by name when all enabled', async () => {
const actionTypes: ActionType[] = [
{
id: '1',
minimumLicenseRequired: 'basic',
name: 'third',
enabled: true,
enabledInConfig: true,
enabledInLicense: true,
},
{
id: '2',
minimumLicenseRequired: 'basic',
name: 'first',
enabled: true,
enabledInConfig: true,
enabledInLicense: true,
},
{
id: '3',
minimumLicenseRequired: 'basic',
name: 'second',
enabled: true,
enabledInConfig: true,
enabledInLicense: true,
},
];
const result = [...actionTypes].sort(actionTypeCompare);
expect(result[0]).toEqual(actionTypes[1]);
expect(result[1]).toEqual(actionTypes[2]);
expect(result[2]).toEqual(actionTypes[0]);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import { ActionType } from '../../types';

export function actionTypeCompare(a: ActionType, b: ActionType) {
if (a.enabled === true && b.enabled === false) {
return -1;
}
if (a.enabled === false && b.enabled === true) {
return 1;
}
return a.name.localeCompare(b.name);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.actCheckActionTypeEnabled__disabledActionWarningCard {
background-color: $euiColorLightestShade;
}

.actAccordionActionForm {
.euiCard {
box-shadow: none;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import { ActionType } from '../../types';
import { checkActionTypeEnabled } from './check_action_type_enabled';

test(`returns isEnabled:true when action type isn't provided`, async () => {
expect(checkActionTypeEnabled()).toMatchInlineSnapshot(`
Object {
"isEnabled": true,
}
`);
});

test('returns isEnabled:true when action type is enabled', async () => {
const actionType: ActionType = {
id: '1',
minimumLicenseRequired: 'basic',
name: 'my action',
enabled: true,
enabledInConfig: true,
enabledInLicense: true,
};
expect(checkActionTypeEnabled(actionType)).toMatchInlineSnapshot(`
Object {
"isEnabled": true,
}
`);
});

test('returns isEnabled:false when action type is disabled by license', async () => {
const actionType: ActionType = {
id: '1',
minimumLicenseRequired: 'basic',
name: 'my action',
enabled: false,
enabledInConfig: true,
enabledInLicense: false,
};
expect(checkActionTypeEnabled(actionType)).toMatchInlineSnapshot(`
Object {
"isEnabled": false,
"message": "This connector is disabled because it requires a basic license.",
"messageCard": <EuiCard
className="actCheckActionTypeEnabled__disabledActionWarningCard"
description="To re-enable this action, please upgrade your license."
title="This feature requires a basic license."
>
<ForwardRef
href="https://www.elastic.co/subscriptions"
target="_blank"
>
<FormattedMessage
defaultMessage="View license options"
id="xpack.triggersActionsUI.sections.alertForm.actionTypeDisabledByLicenseLinkTitle"
values={Object {}}
/>
</ForwardRef>
</EuiCard>,
}
`);
});

test('returns isEnabled:false when action type is disabled by config', async () => {
const actionType: ActionType = {
id: '1',
minimumLicenseRequired: 'basic',
name: 'my action',
enabled: false,
enabledInConfig: false,
enabledInLicense: true,
};
expect(checkActionTypeEnabled(actionType)).toMatchInlineSnapshot(`
Object {
"isEnabled": false,
"message": "This connector is disabled by the Kibana configuration.",
"messageCard": <EuiCard
className="actCheckActionTypeEnabled__disabledActionWarningCard"
description=""
title="This feature is disabled by the Kibana configuration."
/>,
}
`);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import React from 'react';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
import { EuiCard, EuiLink } from '@elastic/eui';
import { ActionType } from '../../types';
import { VIEW_LICENSE_OPTIONS_LINK } from '../../common/constants';
import './check_action_type_enabled.scss';

export interface IsEnabledResult {
isEnabled: true;
}
export interface IsDisabledResult {
isEnabled: false;
message: string;
messageCard: JSX.Element;
}

export function checkActionTypeEnabled(
actionType?: ActionType
): IsEnabledResult | IsDisabledResult {
if (actionType?.enabledInLicense === false) {
return {
isEnabled: false,
message: i18n.translate(
'xpack.triggersActionsUI.checkActionTypeEnabled.actionTypeDisabledByLicenseMessage',
{
defaultMessage:
'This connector is disabled because it requires a {minimumLicenseRequired} license.',
values: {
minimumLicenseRequired: actionType.minimumLicenseRequired,
},
}
),
messageCard: (
<EuiCard
titleSize="xs"
title={i18n.translate(
'xpack.triggersActionsUI.sections.alertForm.actionTypeDisabledByLicenseMessageTitle',
{
defaultMessage: 'This feature requires a {minimumLicenseRequired} license.',
values: {
minimumLicenseRequired: actionType.minimumLicenseRequired,
},
}
)}
// The "re-enable" terminology is used here because this message is used when an alert
// action was previously enabled and needs action to be re-enabled.
description={i18n.translate(
'xpack.triggersActionsUI.sections.alertForm.actionTypeDisabledByLicenseMessageDescription',
{ defaultMessage: 'To re-enable this action, please upgrade your license.' }
)}
className="actCheckActionTypeEnabled__disabledActionWarningCard"
children={
<EuiLink href={VIEW_LICENSE_OPTIONS_LINK} target="_blank">
<FormattedMessage
defaultMessage="View license options"
id="xpack.triggersActionsUI.sections.alertForm.actionTypeDisabledByLicenseLinkTitle"
/>
</EuiLink>
}
/>
),
};
}

if (actionType?.enabledInConfig === false) {
return {
isEnabled: false,
message: i18n.translate(
'xpack.triggersActionsUI.checkActionTypeEnabled.actionTypeDisabledByConfigMessage',
{ defaultMessage: 'This connector is disabled by the Kibana configuration.' }
),
messageCard: (
<EuiCard
title={i18n.translate(
'xpack.triggersActionsUI.sections.alertForm.actionTypeDisabledByConfigMessageTitle',
{ defaultMessage: 'This feature is disabled by the Kibana configuration.' }
)}
description=""
className="actCheckActionTypeEnabled__disabledActionWarningCard"
/>
),
};
}

return { isEnabled: true };
}
Loading