[Alerting] Fixing broken Alerts view when no Global All Kibana privilege (#88727)

* Making kibanaFeatures an optional parameter and catching error on plugin start

* Gracefully handle 404 errors when no access to features endpoint

* Adding functional test
This commit is contained in:
ymao1 2021-01-19 18:14:56 -05:00 committed by GitHub
parent e3063f6934
commit 6d1c010607
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 108 additions and 63 deletions

View file

@ -9,6 +9,7 @@ import { CoreSetup, CoreStart, Plugin as CorePlugin } from 'src/core/public';
import { i18n } from '@kbn/i18n';
import { ReactElement } from 'react';
import { FeaturesPluginStart } from '../../features/public';
import { KibanaFeature } from '../../features/common';
import { registerBuiltInActionTypes } from './application/components/builtin_action_types';
import { ActionTypeModel, AlertTypeModel } from './types';
import { TypeRegistry } from './application/type_registry';
@ -122,7 +123,17 @@ export class Plugin
];
const { renderApp } = await import('./application/app');
const kibanaFeatures = await pluginsStart.features.getFeatures();
// The `/api/features` endpoint requires the "Global All" Kibana privilege. Users with a
// subset of this privilege are not authorized to access this endpoint and will receive a 404
// error that causes the Alerting view to fail to load.
let kibanaFeatures: KibanaFeature[];
try {
kibanaFeatures = await pluginsStart.features.getFeatures();
} catch (err) {
kibanaFeatures = [];
}
return renderApp({
...coreStart,
data: pluginsStart.data,

View file

@ -11,6 +11,7 @@ import { getTestAlertData, getTestActionData } from '../../lib/get_test_data';
export default ({ getPageObjects, getService }: FtrProviderContext) => {
const testSubjects = getService('testSubjects');
const security = getService('security');
const pageObjects = getPageObjects(['common', 'triggersActionsUI', 'header']);
const log = getService('log');
const browser = getService('browser');
@ -18,80 +19,97 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
const objectRemover = new ObjectRemover(supertest);
describe('Home page', function () {
before(async () => {
await pageObjects.common.navigateToApp('triggersActions');
});
describe('Loads the app with limited privileges', () => {
before(async () => {
await security.testUser.setRoles(['alerts_and_actions_role'], true);
});
after(async () => {
await security.testUser.restoreDefaults();
});
after(async () => {
await objectRemover.removeAll();
});
it('Loads the app', async () => {
await log.debug('Checking for section heading to say Triggers and Actions.');
const headingText = await pageObjects.triggersActionsUI.getSectionHeadingText();
expect(headingText).to.be('Alerts and Actions');
});
describe('Connectors tab', () => {
it('renders the connectors tab', async () => {
// Navigate to the connectors tab
await pageObjects.triggersActionsUI.changeTabs('connectorsTab');
await pageObjects.header.waitUntilLoadingHasFinished();
// Verify url
const url = await browser.getCurrentUrl();
expect(url).to.contain(`/connectors`);
// Verify content
await testSubjects.existOrFail('actionsList');
it('Loads the Alerts page', async () => {
await pageObjects.common.navigateToApp('triggersActions');
const headingText = await pageObjects.triggersActionsUI.getSectionHeadingText();
expect(headingText).to.be('Alerts and Actions');
});
});
describe('Alerts tab', () => {
it('renders the alerts tab', async () => {
// Navigate to the alerts tab
await pageObjects.triggersActionsUI.changeTabs('alertsTab');
await pageObjects.header.waitUntilLoadingHasFinished();
// Verify url
const url = await browser.getCurrentUrl();
expect(url).to.contain(`/alerts`);
// Verify content
await testSubjects.existOrFail('alertsList');
describe('Loads the app', () => {
before(async () => {
await pageObjects.common.navigateToApp('triggersActions');
});
it('navigates to an alert details page', async () => {
const { body: createdAction } = await supertest
.post(`/api/actions/action`)
.set('kbn-xsrf', 'foo')
.send(getTestActionData())
.expect(200);
objectRemover.add(createdAction.id, 'action', 'actions');
after(async () => {
await objectRemover.removeAll();
});
const { body: createdAlert } = await supertest
.post(`/api/alerts/alert`)
.set('kbn-xsrf', 'foo')
.send(getTestAlertData())
.expect(200);
objectRemover.add(createdAlert.id, 'alert', 'alerts');
it('Loads the Alerts page', async () => {
await log.debug('Checking for section heading to say Triggers and Actions.');
// refresh to see alert
await browser.refresh();
const headingText = await pageObjects.triggersActionsUI.getSectionHeadingText();
expect(headingText).to.be('Alerts and Actions');
});
await pageObjects.header.waitUntilLoadingHasFinished();
describe('Connectors tab', () => {
it('renders the connectors tab', async () => {
// Navigate to the connectors tab
await pageObjects.triggersActionsUI.changeTabs('connectorsTab');
// Verify content
await testSubjects.existOrFail('alertsList');
await pageObjects.header.waitUntilLoadingHasFinished();
// click on first alert
await pageObjects.triggersActionsUI.clickOnAlertInAlertsList(createdAlert.name);
// Verify url
const url = await browser.getCurrentUrl();
expect(url).to.contain(`/connectors`);
// Verify url
expect(await browser.getCurrentUrl()).to.contain(`/alert/${createdAlert.id}`);
// Verify content
await testSubjects.existOrFail('actionsList');
});
});
describe('Alerts tab', () => {
it('renders the alerts tab', async () => {
// Navigate to the alerts tab
await pageObjects.triggersActionsUI.changeTabs('alertsTab');
await pageObjects.header.waitUntilLoadingHasFinished();
// Verify url
const url = await browser.getCurrentUrl();
expect(url).to.contain(`/alerts`);
// Verify content
await testSubjects.existOrFail('alertsList');
});
it('navigates to an alert details page', async () => {
const { body: createdAction } = await supertest
.post(`/api/actions/action`)
.set('kbn-xsrf', 'foo')
.send(getTestActionData())
.expect(200);
objectRemover.add(createdAction.id, 'action', 'actions');
const { body: createdAlert } = await supertest
.post(`/api/alerts/alert`)
.set('kbn-xsrf', 'foo')
.send(getTestAlertData())
.expect(200);
objectRemover.add(createdAlert.id, 'alert', 'alerts');
// refresh to see alert
await browser.refresh();
await pageObjects.header.waitUntilLoadingHasFinished();
// Verify content
await testSubjects.existOrFail('alertsList');
// click on first alert
await pageObjects.triggersActionsUI.clickOnAlertInAlertsList(createdAlert.name);
// Verify url
expect(await browser.getCurrentUrl()).to.contain(`/alert/${createdAlert.id}`);
});
});
});
});

View file

@ -86,6 +86,22 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) {
})}`,
],
},
security: {
roles: {
alerts_and_actions_role: {
kibana: [
{
feature: {
actions: ['all'],
stackAlerts: ['all'],
},
spaces: ['*'],
},
],
},
},
defaultRoles: ['superuser'],
},
};
return returnedObject;