mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
Merge remote-tracking branch 'upstream/granular-app-privileges' into fc/enable-saved-object-management
This commit is contained in:
commit
68447ca556
41 changed files with 1548 additions and 128 deletions
|
@ -143,7 +143,12 @@ export default function (kibana) {
|
|||
),
|
||||
{ auth: false }
|
||||
)
|
||||
)
|
||||
),
|
||||
uiCapabilities: {
|
||||
dev_tools: {
|
||||
show: true
|
||||
},
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ require('ui-bootstrap-custom');
|
|||
require('ui/modules').get('kibana', ['sense.ui.bootstrap']);
|
||||
require('ui/tooltip');
|
||||
require('ui/autoload/styles');
|
||||
require('ui/capabilities/route_setup');
|
||||
|
||||
require('./src/controllers/sense_controller');
|
||||
require('./src/directives/sense_history');
|
||||
|
@ -35,6 +36,7 @@ require('./src/directives/sense_welcome');
|
|||
|
||||
|
||||
uiRoutes.when('/dev_tools/console', {
|
||||
requireUICapability: 'dev_tools.show',
|
||||
controller: 'SenseController',
|
||||
template,
|
||||
});
|
||||
|
|
|
@ -34,6 +34,7 @@ import {
|
|||
TimelionPageProvider,
|
||||
SharePageProvider,
|
||||
TimePickerPageProvider,
|
||||
ErrorPageProvider,
|
||||
} from './page_objects';
|
||||
|
||||
import {
|
||||
|
@ -96,6 +97,7 @@ export default async function ({ readConfigFile }) {
|
|||
timelion: TimelionPageProvider,
|
||||
share: SharePageProvider,
|
||||
timePicker: TimePickerPageProvider,
|
||||
error: ErrorPageProvider
|
||||
},
|
||||
services: {
|
||||
es: commonConfig.get('services.es'),
|
||||
|
|
39
test/functional/page_objects/error_page.js
Normal file
39
test/functional/page_objects/error_page.js
Normal file
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import expect from 'expect.js';
|
||||
|
||||
export function ErrorPageProvider({ getService }) {
|
||||
const find = getService('find');
|
||||
|
||||
class ErrorPage {
|
||||
async expectNotFound() {
|
||||
const el = await find.byCssSelector('body>pre');
|
||||
const messageText = await el.getVisibleText();
|
||||
expect(messageText).to.eql(
|
||||
JSON.stringify({
|
||||
statusCode: 404,
|
||||
error: 'Not Found',
|
||||
message: 'Not Found',
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return new ErrorPage();
|
||||
}
|
|
@ -33,3 +33,4 @@ export { VisualBuilderPageProvider } from './visual_builder_page';
|
|||
export { TimelionPageProvider } from './timelion_page';
|
||||
export { SharePageProvider } from './share_page';
|
||||
export { TimePickerPageProvider } from './time_picker';
|
||||
export { ErrorPageProvider } from './error_page';
|
||||
|
|
|
@ -67,7 +67,7 @@ export function graph(kibana) {
|
|||
all: ['graph-workspace'],
|
||||
read: ['config', 'index-pattern'],
|
||||
},
|
||||
ui: [],
|
||||
ui: ['save', 'delete'],
|
||||
},
|
||||
read: {
|
||||
savedObject: {
|
||||
|
|
|
@ -43,6 +43,7 @@ import {
|
|||
import {
|
||||
getOutlinkEncoders,
|
||||
} from './services/outlink_encoders';
|
||||
import { uiCapabilities } from 'ui/capabilities';
|
||||
|
||||
const app = uiModules.get('app/graph');
|
||||
|
||||
|
@ -792,35 +793,43 @@ app.controller('graphuiPlugin', function ($scope, $route, $http, kbnUrl, Private
|
|||
}),
|
||||
run: function () {canWipeWorkspace(function () {kbnUrl.change('/home', {}); }); },
|
||||
});
|
||||
if (!$scope.allSavingDisabled) {
|
||||
$scope.topNavMenu.push({
|
||||
key: 'save',
|
||||
label: i18n('xpack.graph.topNavMenu.saveWorkspace.enabledLabel', {
|
||||
defaultMessage: 'Save',
|
||||
}),
|
||||
description: i18n('xpack.graph.topNavMenu.saveWorkspace.enabledAriaLabel', {
|
||||
defaultMessage: 'Save Workspace',
|
||||
}),
|
||||
tooltip: i18n('xpack.graph.topNavMenu.saveWorkspace.enabledTooltip', {
|
||||
defaultMessage: 'Save this workspace',
|
||||
}),
|
||||
disableButton: function () {return $scope.selectedFields.length === 0;},
|
||||
template: require('./templates/save_workspace.html')
|
||||
});
|
||||
}else {
|
||||
$scope.topNavMenu.push({
|
||||
key: 'save',
|
||||
label: i18n('xpack.graph.topNavMenu.saveWorkspace.disabledLabel', {
|
||||
defaultMessage: 'Save',
|
||||
}),
|
||||
description: i18n('xpack.graph.topNavMenu.saveWorkspace.disabledAriaLabel', {
|
||||
defaultMessage: 'Save Workspace',
|
||||
}),
|
||||
tooltip: i18n('xpack.graph.topNavMenu.saveWorkspace.disabledTooltip', {
|
||||
defaultMessage: 'No changes to saved workspaces are permitted by the current save policy',
|
||||
}),
|
||||
disableButton: true
|
||||
});
|
||||
|
||||
// if saving is disabled using uiCapabilities, we don't want to render the save
|
||||
// button so it's consistent with all of the other applications
|
||||
if (uiCapabilities.graph.save) {
|
||||
// allSavingDisabled is based on the xpack.graph.savePolicy, we'll maintain this functionality
|
||||
if (!$scope.allSavingDisabled) {
|
||||
$scope.topNavMenu.push({
|
||||
key: 'save',
|
||||
label: i18n('xpack.graph.topNavMenu.saveWorkspace.enabledLabel', {
|
||||
defaultMessage: 'Save',
|
||||
}),
|
||||
description: i18n('xpack.graph.topNavMenu.saveWorkspace.enabledAriaLabel', {
|
||||
defaultMessage: 'Save Workspace',
|
||||
}),
|
||||
tooltip: i18n('xpack.graph.topNavMenu.saveWorkspace.enabledTooltip', {
|
||||
defaultMessage: 'Save this workspace',
|
||||
}),
|
||||
disableButton: function () {return $scope.selectedFields.length === 0;},
|
||||
template: require('./templates/save_workspace.html'),
|
||||
testId: 'graphSaveButton',
|
||||
});
|
||||
} else {
|
||||
$scope.topNavMenu.push({
|
||||
key: 'save',
|
||||
label: i18n('xpack.graph.topNavMenu.saveWorkspace.disabledLabel', {
|
||||
defaultMessage: 'Save',
|
||||
}),
|
||||
description: i18n('xpack.graph.topNavMenu.saveWorkspace.disabledAriaLabel', {
|
||||
defaultMessage: 'Save Workspace',
|
||||
}),
|
||||
tooltip: i18n('xpack.graph.topNavMenu.saveWorkspace.disabledTooltip', {
|
||||
defaultMessage: 'No changes to saved workspaces are permitted by the current save policy',
|
||||
}),
|
||||
disableButton: true,
|
||||
testId: 'graphSaveButton',
|
||||
});
|
||||
}
|
||||
}
|
||||
$scope.topNavMenu.push({
|
||||
key: 'open',
|
||||
|
@ -833,65 +842,74 @@ app.controller('graphuiPlugin', function ($scope, $route, $http, kbnUrl, Private
|
|||
tooltip: i18n('xpack.graph.topNavMenu.loadWorkspaceTooltip', {
|
||||
defaultMessage: 'Load a saved workspace',
|
||||
}),
|
||||
template: require('./templates/load_workspace.html')
|
||||
template: require('./templates/load_workspace.html'),
|
||||
testId: 'graphOpenButton',
|
||||
});
|
||||
if (!$scope.allSavingDisabled) {
|
||||
$scope.topNavMenu.push({
|
||||
key: 'delete',
|
||||
disableButton: function () {
|
||||
return $route.current.locals === undefined || $route.current.locals.savedWorkspace === undefined;
|
||||
},
|
||||
label: i18n('xpack.graph.topNavMenu.deleteWorkspace.enabledLabel', {
|
||||
defaultMessage: 'Delete',
|
||||
}),
|
||||
description: i18n('xpack.graph.topNavMenu.deleteWorkspace.enabledAriaLabel', {
|
||||
defaultMessage: 'Delete Saved Workspace',
|
||||
}),
|
||||
tooltip: i18n('xpack.graph.topNavMenu.deleteWorkspace.enabledAriaTooltip', {
|
||||
defaultMessage: 'Delete this workspace',
|
||||
}),
|
||||
run: function () {
|
||||
const title = $route.current.locals.savedWorkspace.title;
|
||||
function doDelete() {
|
||||
$route.current.locals.SavedWorkspacesProvider.delete($route.current.locals.savedWorkspace.id);
|
||||
kbnUrl.change('/home', {});
|
||||
// if deleting is disabled using uiCapabilities, we don't want to render the delete
|
||||
// button so it's consistent with all of the other applications
|
||||
if (uiCapabilities.graph.delete) {
|
||||
|
||||
toastNotifications.addSuccess(
|
||||
i18n('xpack.graph.topNavMenu.deleteWorkspaceNotification', {
|
||||
defaultMessage: `Deleted '{workspaceTitle}'`,
|
||||
values: { workspaceTitle: title },
|
||||
})
|
||||
// allSavingDisabled is based on the xpack.graph.savePolicy, we'll maintain this functionality
|
||||
if (!$scope.allSavingDisabled) {
|
||||
$scope.topNavMenu.push({
|
||||
key: 'delete',
|
||||
disableButton: function () {
|
||||
return $route.current.locals === undefined || $route.current.locals.savedWorkspace === undefined;
|
||||
},
|
||||
label: i18n('xpack.graph.topNavMenu.deleteWorkspace.enabledLabel', {
|
||||
defaultMessage: 'Delete',
|
||||
}),
|
||||
description: i18n('xpack.graph.topNavMenu.deleteWorkspace.enabledAriaLabel', {
|
||||
defaultMessage: 'Delete Saved Workspace',
|
||||
}),
|
||||
tooltip: i18n('xpack.graph.topNavMenu.deleteWorkspace.enabledAriaTooltip', {
|
||||
defaultMessage: 'Delete this workspace',
|
||||
}),
|
||||
testId: 'graphDeleteButton',
|
||||
run: function () {
|
||||
const title = $route.current.locals.savedWorkspace.title;
|
||||
function doDelete() {
|
||||
$route.current.locals.SavedWorkspacesProvider.delete($route.current.locals.savedWorkspace.id);
|
||||
kbnUrl.change('/home', {});
|
||||
|
||||
toastNotifications.addSuccess(
|
||||
i18n('xpack.graph.topNavMenu.deleteWorkspaceNotification', {
|
||||
defaultMessage: `Deleted '{workspaceTitle}'`,
|
||||
values: { workspaceTitle: title },
|
||||
})
|
||||
);
|
||||
}
|
||||
const confirmModalOptions = {
|
||||
onConfirm: doDelete,
|
||||
confirmButtonText: i18n('xpack.graph.topNavMenu.deleteWorkspace.confirmButtonLabel', {
|
||||
defaultMessage: 'Delete workspace',
|
||||
}),
|
||||
};
|
||||
confirmModal(
|
||||
i18n('xpack.graph.topNavMenu.deleteWorkspace.confirmText', {
|
||||
defaultMessage: 'Are you sure you want to delete the workspace {title} ?',
|
||||
values: { title },
|
||||
}),
|
||||
confirmModalOptions
|
||||
);
|
||||
}
|
||||
const confirmModalOptions = {
|
||||
onConfirm: doDelete,
|
||||
confirmButtonText: i18n('xpack.graph.topNavMenu.deleteWorkspace.confirmButtonLabel', {
|
||||
defaultMessage: 'Delete workspace',
|
||||
}),
|
||||
};
|
||||
confirmModal(
|
||||
i18n('xpack.graph.topNavMenu.deleteWorkspace.confirmText', {
|
||||
defaultMessage: 'Are you sure you want to delete the workspace {title} ?',
|
||||
values: { title },
|
||||
}),
|
||||
confirmModalOptions
|
||||
);
|
||||
}
|
||||
});
|
||||
}else {
|
||||
$scope.topNavMenu.push({
|
||||
key: 'delete',
|
||||
disableButton: true,
|
||||
label: i18n('xpack.graph.topNavMenu.deleteWorkspace.disabledLabel', {
|
||||
defaultMessage: 'Delete',
|
||||
}),
|
||||
description: i18n('xpack.graph.topNavMenu.deleteWorkspace.disabledAriaLabel', {
|
||||
defaultMessage: 'Delete Saved Workspace',
|
||||
}),
|
||||
tooltip: i18n('xpack.graph.topNavMenu.deleteWorkspace.disabledTooltip', {
|
||||
defaultMessage: 'No changes to saved workspaces are permitted by the current save policy',
|
||||
}),
|
||||
});
|
||||
});
|
||||
}else {
|
||||
$scope.topNavMenu.push({
|
||||
key: 'delete',
|
||||
disableButton: true,
|
||||
label: i18n('xpack.graph.topNavMenu.deleteWorkspace.disabledLabel', {
|
||||
defaultMessage: 'Delete',
|
||||
}),
|
||||
description: i18n('xpack.graph.topNavMenu.deleteWorkspace.disabledAriaLabel', {
|
||||
defaultMessage: 'Delete Saved Workspace',
|
||||
}),
|
||||
tooltip: i18n('xpack.graph.topNavMenu.deleteWorkspace.disabledTooltip', {
|
||||
defaultMessage: 'No changes to saved workspaces are permitted by the current save policy',
|
||||
}),
|
||||
testId: 'graphDeleteButton',
|
||||
});
|
||||
}
|
||||
}
|
||||
$scope.topNavMenu.push({
|
||||
key: 'settings',
|
||||
|
|
|
@ -5,14 +5,17 @@
|
|||
*/
|
||||
|
||||
import routes from 'ui/routes';
|
||||
import 'ui/capabilities/route_setup';
|
||||
import { toastNotifications } from 'ui/notify';
|
||||
import { XPackInfoProvider } from 'plugins/xpack_main/services/xpack_info';
|
||||
import template from './grokdebugger_route.html';
|
||||
import './directives/grokdebugger';
|
||||
|
||||
|
||||
routes
|
||||
.when('/dev_tools/grokdebugger', {
|
||||
template: template,
|
||||
requireUICapability: 'dev_tools.show',
|
||||
resolve: {
|
||||
licenseCheckResults(Private) {
|
||||
const xpackInfo = Private(XPackInfoProvider);
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
// K5 imports
|
||||
import { uiModules } from 'ui/modules';
|
||||
import uiRoutes from 'ui/routes';
|
||||
import 'ui/capabilities/route_setup';
|
||||
import { notify } from 'ui/notify';
|
||||
|
||||
// License
|
||||
|
@ -30,6 +31,7 @@ import { defaultQuery } from './templates/default_query';
|
|||
|
||||
uiRoutes.when('/dev_tools/searchprofiler', {
|
||||
template: template,
|
||||
requireUICapability: 'dev_tools.show',
|
||||
controller: ($scope, i18n) => {
|
||||
$scope.registerLicenseLinkLabel = i18n('xpack.searchProfiler.registerLicenseLinkLabel',
|
||||
{ defaultMessage: 'register a license' });
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<kbn-dev-tools-app class="prfDevTool">
|
||||
<kbn-dev-tools-app class="prfDevTool" data-test-subj="searchProfiler">
|
||||
<div class="prfDevTool__container kuiViewContent kuiViewContentItem" ng-controller="profileViz">
|
||||
<div class="prfDevTool__wrapper">
|
||||
<div class="prfDevTool__main">
|
||||
|
|
|
@ -1,2 +1 @@
|
|||
@import './manage_spaces';
|
||||
@import './components/confirm_delete_modal';
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
.spcManagePage__content {
|
||||
max-width: 640px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
flex-grow: 0;
|
||||
}
|
||||
.spcGridPage {
|
||||
max-width: map-get($euiBreakpoints, 'xl');
|
||||
}
|
|
@ -4,8 +4,9 @@ exports[`SecureSpaceMessage doesn't render if UI Capabilities does not allow sec
|
|||
|
||||
exports[`SecureSpaceMessage renders if user profile allows security to be managed 1`] = `
|
||||
<Fragment>
|
||||
<EuiSpacer
|
||||
size="l"
|
||||
<EuiHorizontalRule
|
||||
margin="l"
|
||||
size="full"
|
||||
/>
|
||||
<EuiText
|
||||
className="eui-textCenter"
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { EuiLink, EuiSpacer, EuiText } from '@elastic/eui';
|
||||
import { EuiHorizontalRule, EuiLink, EuiText } from '@elastic/eui';
|
||||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
import React, { Fragment } from 'react';
|
||||
import { uiCapabilities } from 'ui/capabilities';
|
||||
|
@ -13,7 +13,7 @@ export const SecureSpaceMessage = ({}) => {
|
|||
if (uiCapabilities.spaces.manage) {
|
||||
return (
|
||||
<Fragment>
|
||||
<EuiSpacer />
|
||||
<EuiHorizontalRule />
|
||||
<EuiText className="eui-textCenter">
|
||||
<p>
|
||||
<FormattedMessage
|
||||
|
|
|
@ -14,7 +14,6 @@ import {
|
|||
EuiPopover,
|
||||
EuiPopoverProps,
|
||||
EuiSpacer,
|
||||
EuiText,
|
||||
EuiTextArea,
|
||||
EuiTitle,
|
||||
} from '@elastic/eui';
|
||||
|
@ -186,24 +185,20 @@ export class CustomizeSpace extends Component<Props, State> {
|
|||
};
|
||||
|
||||
public getPanelDescription = () => {
|
||||
return (
|
||||
<EuiText>
|
||||
{this.props.editingExistingSpace ? (
|
||||
<p>
|
||||
<FormattedMessage
|
||||
id="xpack.spaces.management.manageSpacePage.customizeSpacePanelUrlIdentifierNotEditable"
|
||||
defaultMessage="The url identifier cannot be changed."
|
||||
/>
|
||||
</p>
|
||||
) : (
|
||||
<p>
|
||||
<FormattedMessage
|
||||
id="xpack.spaces.management.manageSpacePage.customizeSpacePanelUrlIdentifierEditable"
|
||||
defaultMessage="Note the URL identifier. You cannot change it after you create the space."
|
||||
/>
|
||||
</p>
|
||||
)}
|
||||
</EuiText>
|
||||
return this.props.editingExistingSpace ? (
|
||||
<p>
|
||||
<FormattedMessage
|
||||
id="xpack.spaces.management.manageSpacePage.customizeSpacePanelUrlIdentifierNotEditable"
|
||||
defaultMessage="The url identifier cannot be changed."
|
||||
/>
|
||||
</p>
|
||||
) : (
|
||||
<p>
|
||||
<FormattedMessage
|
||||
id="xpack.spaces.management.manageSpacePage.customizeSpacePanelUrlIdentifierEditable"
|
||||
defaultMessage="Note the URL identifier. You cannot change it after you create the space."
|
||||
/>
|
||||
</p>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -9,7 +9,6 @@ import {
|
|||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiLoadingSpinner,
|
||||
EuiPageContent,
|
||||
EuiPageContentBody,
|
||||
EuiSpacer,
|
||||
EuiText,
|
||||
|
@ -114,12 +113,10 @@ class ManageSpacePageUI extends Component<Props, State> {
|
|||
const content = this.state.isLoading ? this.getLoadingIndicator() : this.getForm();
|
||||
|
||||
return (
|
||||
<div className="spcManagePage">
|
||||
<EuiPageContent className="spcManagePage__content">
|
||||
<EuiPageContentBody>{content}</EuiPageContentBody>
|
||||
</EuiPageContent>
|
||||
<Fragment>
|
||||
<EuiPageContentBody>{content}</EuiPageContentBody>
|
||||
{this.maybeGetSecureSpacesMessage()}
|
||||
</div>
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -116,7 +116,7 @@ const kibanaFeatures: Feature[] = [
|
|||
all: [],
|
||||
read: ['config'],
|
||||
},
|
||||
ui: [],
|
||||
ui: ['show'],
|
||||
},
|
||||
read: {
|
||||
api: ['console/execute'],
|
||||
|
@ -124,7 +124,7 @@ const kibanaFeatures: Feature[] = [
|
|||
all: [],
|
||||
read: ['config'],
|
||||
},
|
||||
ui: [],
|
||||
ui: ['show'],
|
||||
},
|
||||
},
|
||||
privilegesTooltip: i18n.translate('xpack.main.featureRegistry.devToolsPrivilegesTooltip', {
|
||||
|
|
218
x-pack/test/api_integration/apis/console/feature_controls.ts
Normal file
218
x-pack/test/api_integration/apis/console/feature_controls.ts
Normal file
|
@ -0,0 +1,218 @@
|
|||
/*
|
||||
* 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 { SecurityService, SpacesService } from 'x-pack/test/common/services';
|
||||
import { KibanaFunctionalTestDefaultProviders } from '../../../types/providers';
|
||||
|
||||
// tslint:disable:no-default-export
|
||||
export default function securityTests({ getService }: KibanaFunctionalTestDefaultProviders) {
|
||||
const supertest = getService('supertestWithoutAuth');
|
||||
const security: SecurityService = getService('security');
|
||||
const spaces: SpacesService = getService('spaces');
|
||||
|
||||
describe('/api/console/proxy', () => {
|
||||
it('cannot be accessed by an anonymous user', async () => {
|
||||
await supertest
|
||||
.post(`/api/console/proxy?method=GET&path=${encodeURIComponent('/_cat')}`)
|
||||
.set('kbn-xsrf', 'xxx')
|
||||
.send()
|
||||
.expect(401);
|
||||
});
|
||||
|
||||
it('can be accessed by kibana_user role', async () => {
|
||||
const username = 'kibana_user';
|
||||
const roleName = 'kibana_user';
|
||||
try {
|
||||
const password = `${username}-password`;
|
||||
|
||||
await security.user.create(username, {
|
||||
password,
|
||||
roles: [roleName],
|
||||
full_name: 'a kibana user',
|
||||
});
|
||||
|
||||
await supertest
|
||||
.post(`/api/console/proxy?method=GET&path=${encodeURIComponent('/_cat')}`)
|
||||
.auth(username, password)
|
||||
.set('kbn-xsrf', 'xxx')
|
||||
.send()
|
||||
.expect(200);
|
||||
} finally {
|
||||
await security.user.delete(username);
|
||||
}
|
||||
});
|
||||
|
||||
it('can be accessed by global all role', async () => {
|
||||
const username = 'global_all';
|
||||
const roleName = 'global_all';
|
||||
try {
|
||||
const password = `${username}-password`;
|
||||
|
||||
await security.role.create(roleName, {
|
||||
kibana: [
|
||||
{
|
||||
base: ['all'],
|
||||
spaces: ['*'],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
await security.user.create(username, {
|
||||
password,
|
||||
roles: [roleName],
|
||||
});
|
||||
|
||||
await supertest
|
||||
.post(`/api/console/proxy?method=GET&path=${encodeURIComponent('/_cat')}`)
|
||||
.auth(username, password)
|
||||
.set('kbn-xsrf', 'xxx')
|
||||
.send()
|
||||
.expect(200);
|
||||
} finally {
|
||||
await security.role.delete(roleName);
|
||||
await security.user.delete(username);
|
||||
}
|
||||
});
|
||||
|
||||
it('can be accessed by global read role', async () => {
|
||||
const username = 'global_read';
|
||||
const roleName = 'global_read';
|
||||
try {
|
||||
const password = `${username}-password`;
|
||||
|
||||
await security.role.create(roleName, {
|
||||
kibana: [
|
||||
{
|
||||
base: ['read'],
|
||||
spaces: ['*'],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
await security.user.create(username, {
|
||||
password,
|
||||
roles: [roleName],
|
||||
});
|
||||
|
||||
await supertest
|
||||
.post(`/api/console/proxy?method=GET&path=${encodeURIComponent('/_cat')}`)
|
||||
.auth(username, password)
|
||||
.set('kbn-xsrf', 'xxx')
|
||||
.send()
|
||||
.expect(200);
|
||||
} finally {
|
||||
await security.role.delete(roleName);
|
||||
await security.user.delete(username);
|
||||
}
|
||||
});
|
||||
|
||||
// this could be any role which doesn't have access to the dev_tools feature
|
||||
it(`can't be accessed by a user with dashboard all access`, async () => {
|
||||
const username = 'dashboard_all';
|
||||
const roleName = 'dashboard_all';
|
||||
try {
|
||||
const password = `${username}-password`;
|
||||
|
||||
await security.role.create(roleName, {
|
||||
kibana: [
|
||||
{
|
||||
feature: {
|
||||
dashboard: ['all'],
|
||||
},
|
||||
spaces: ['*'],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
await security.user.create(username, {
|
||||
password,
|
||||
roles: [roleName],
|
||||
});
|
||||
|
||||
await supertest
|
||||
.post(`/api/console/proxy?method=GET&path=${encodeURIComponent('/_cat')}`)
|
||||
.auth(username, password)
|
||||
.set('kbn-xsrf', 'xxx')
|
||||
.send()
|
||||
.expect(404);
|
||||
} finally {
|
||||
await security.role.delete(roleName);
|
||||
await security.user.delete(username);
|
||||
}
|
||||
});
|
||||
|
||||
describe('spaces', () => {
|
||||
// the following tests create a user_1 which has dev_tools all access to space_1 and dashboard access to space_2
|
||||
const space1Id = 'space_1';
|
||||
const user1 = {
|
||||
username: 'user_1',
|
||||
roleName: 'user_1',
|
||||
password: 'user_1-password',
|
||||
};
|
||||
|
||||
const space2Id = 'space_2';
|
||||
|
||||
before(async () => {
|
||||
await spaces.create({
|
||||
id: space1Id,
|
||||
name: space1Id,
|
||||
disabledFeatures: [],
|
||||
});
|
||||
await security.role.create(user1.roleName, {
|
||||
kibana: [
|
||||
{
|
||||
feature: {
|
||||
dev_tools: ['all'],
|
||||
},
|
||||
spaces: [space1Id],
|
||||
},
|
||||
{
|
||||
feature: {
|
||||
dashboard: ['all'],
|
||||
},
|
||||
spaces: [space2Id],
|
||||
},
|
||||
],
|
||||
});
|
||||
await security.user.create(user1.username, {
|
||||
password: user1.password,
|
||||
roles: [user1.roleName],
|
||||
});
|
||||
|
||||
await spaces.create({
|
||||
id: space2Id,
|
||||
name: space2Id,
|
||||
disabledFeatures: [],
|
||||
});
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await spaces.delete(space1Id);
|
||||
await spaces.delete(space2Id);
|
||||
await security.role.delete(user1.roleName);
|
||||
await security.user.delete(user1.username);
|
||||
});
|
||||
|
||||
it('user_1 can access dev_tools in space_1', async () => {
|
||||
await supertest
|
||||
.post(`/s/${space1Id}/api/console/proxy?method=GET&path=${encodeURIComponent('/_cat')}`)
|
||||
.auth(user1.username, user1.password)
|
||||
.set('kbn-xsrf', 'xxx')
|
||||
.send()
|
||||
.expect(200);
|
||||
});
|
||||
|
||||
it(`user_1 can't access dev_tools in space_2`, async () => {
|
||||
await supertest
|
||||
.post(`/s/${space2Id}/api/console/proxy?method=GET&path=${encodeURIComponent('/_cat')}`)
|
||||
.auth(user1.username, user1.password)
|
||||
.set('kbn-xsrf', 'xxx')
|
||||
.send()
|
||||
.expect(404);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
16
x-pack/test/api_integration/apis/console/index.ts
Normal file
16
x-pack/test/api_integration/apis/console/index.ts
Normal file
|
@ -0,0 +1,16 @@
|
|||
/*
|
||||
* 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 { KibanaFunctionalTestDefaultProviders } from '../../../types/providers';
|
||||
|
||||
// tslint:disable:no-default-export
|
||||
export default function consoleApiIntegrationTests({
|
||||
loadTestFile,
|
||||
}: KibanaFunctionalTestDefaultProviders) {
|
||||
describe('console', () => {
|
||||
loadTestFile(require.resolve('./feature_controls'));
|
||||
});
|
||||
}
|
|
@ -16,6 +16,7 @@ export default function ({ loadTestFile }) {
|
|||
loadTestFile(require.resolve('./kibana'));
|
||||
loadTestFile(require.resolve('./infra'));
|
||||
loadTestFile(require.resolve('./beats'));
|
||||
loadTestFile(require.resolve('./console'));
|
||||
loadTestFile(require.resolve('./management'));
|
||||
loadTestFile(require.resolve('./uptime'));
|
||||
});
|
||||
|
|
|
@ -195,6 +195,7 @@ export default function({ getService }: KibanaFunctionalTestDefaultProviders) {
|
|||
'saved_object:config/bulk_get',
|
||||
'saved_object:config/get',
|
||||
'saved_object:config/find',
|
||||
'ui:dev_tools/show',
|
||||
],
|
||||
read: [
|
||||
'login:',
|
||||
|
@ -208,6 +209,7 @@ export default function({ getService }: KibanaFunctionalTestDefaultProviders) {
|
|||
'saved_object:config/bulk_get',
|
||||
'saved_object:config/get',
|
||||
'saved_object:config/find',
|
||||
'ui:dev_tools/show',
|
||||
],
|
||||
},
|
||||
advancedSettings: {
|
||||
|
@ -331,6 +333,8 @@ export default function({ getService }: KibanaFunctionalTestDefaultProviders) {
|
|||
'saved_object:index-pattern/bulk_get',
|
||||
'saved_object:index-pattern/get',
|
||||
'saved_object:index-pattern/find',
|
||||
'ui:graph/save',
|
||||
'ui:graph/delete',
|
||||
],
|
||||
read: [
|
||||
'login:',
|
||||
|
@ -602,6 +606,7 @@ export default function({ getService }: KibanaFunctionalTestDefaultProviders) {
|
|||
'ui:catalogue/searchprofiler',
|
||||
'ui:catalogue/grokdebugger',
|
||||
'ui:navLinks/kibana:dev_tools',
|
||||
'ui:dev_tools/show',
|
||||
'ui:catalogue/advanced_settings',
|
||||
'ui:management/kibana/settings',
|
||||
'saved_object:config/create',
|
||||
|
@ -633,6 +638,8 @@ export default function({ getService }: KibanaFunctionalTestDefaultProviders) {
|
|||
'saved_object:graph-workspace/bulk_create',
|
||||
'saved_object:graph-workspace/update',
|
||||
'saved_object:graph-workspace/delete',
|
||||
'ui:graph/save',
|
||||
'ui:graph/delete',
|
||||
'app:monitoring',
|
||||
'ui:catalogue/monitoring',
|
||||
'ui:navLinks/monitoring',
|
||||
|
@ -709,6 +716,7 @@ export default function({ getService }: KibanaFunctionalTestDefaultProviders) {
|
|||
'ui:catalogue/searchprofiler',
|
||||
'ui:catalogue/grokdebugger',
|
||||
'ui:navLinks/kibana:dev_tools',
|
||||
'ui:dev_tools/show',
|
||||
'ui:catalogue/advanced_settings',
|
||||
'ui:management/kibana/settings',
|
||||
'ui:catalogue/index_patterns',
|
||||
|
@ -806,6 +814,7 @@ export default function({ getService }: KibanaFunctionalTestDefaultProviders) {
|
|||
'ui:catalogue/searchprofiler',
|
||||
'ui:catalogue/grokdebugger',
|
||||
'ui:navLinks/kibana:dev_tools',
|
||||
'ui:dev_tools/show',
|
||||
'ui:catalogue/advanced_settings',
|
||||
'ui:management/kibana/settings',
|
||||
'saved_object:config/create',
|
||||
|
@ -837,6 +846,8 @@ export default function({ getService }: KibanaFunctionalTestDefaultProviders) {
|
|||
'saved_object:graph-workspace/bulk_create',
|
||||
'saved_object:graph-workspace/update',
|
||||
'saved_object:graph-workspace/delete',
|
||||
'ui:graph/save',
|
||||
'ui:graph/delete',
|
||||
'app:monitoring',
|
||||
'ui:catalogue/monitoring',
|
||||
'ui:navLinks/monitoring',
|
||||
|
@ -913,6 +924,7 @@ export default function({ getService }: KibanaFunctionalTestDefaultProviders) {
|
|||
'ui:catalogue/searchprofiler',
|
||||
'ui:catalogue/grokdebugger',
|
||||
'ui:navLinks/kibana:dev_tools',
|
||||
'ui:dev_tools/show',
|
||||
'ui:catalogue/advanced_settings',
|
||||
'ui:management/kibana/settings',
|
||||
'ui:catalogue/index_patterns',
|
||||
|
|
|
@ -12,6 +12,11 @@ import {
|
|||
InfraOpsGraphQLProvider
|
||||
} from './services';
|
||||
|
||||
import {
|
||||
SecurityServiceProvider,
|
||||
SpacesServiceProvider,
|
||||
} from '../common/services';
|
||||
|
||||
export default async function ({ readConfigFile }) {
|
||||
|
||||
const kibanaAPITestsConfig = await readConfigFile(require.resolve('../../../test/api_integration/config.js'));
|
||||
|
@ -32,6 +37,8 @@ export default async function ({ readConfigFile }) {
|
|||
usageAPI: UsageAPIProvider,
|
||||
kibanaServer: kibanaCommonConfig.get('services.kibanaServer'),
|
||||
chance: kibanaAPITestsConfig.get('services.chance'),
|
||||
security: SecurityServiceProvider,
|
||||
spaces: SpacesServiceProvider,
|
||||
},
|
||||
esArchiver: xPackFunctionalTestsConfig.get('esArchiver'),
|
||||
junit: {
|
||||
|
|
|
@ -0,0 +1,205 @@
|
|||
/*
|
||||
* 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 expect from 'expect.js';
|
||||
import { SecurityService } from 'x-pack/test/common/services';
|
||||
import { KibanaFunctionalTestDefaultProviders } from '../../../../types/providers';
|
||||
|
||||
// tslint:disable:no-default-export
|
||||
export default function({ getPageObjects, getService }: KibanaFunctionalTestDefaultProviders) {
|
||||
const esArchiver = getService('esArchiver');
|
||||
const security: SecurityService = getService('security');
|
||||
const PageObjects = getPageObjects(['common', 'console', 'security']);
|
||||
const appsMenu = getService('appsMenu');
|
||||
const testSubjects = getService('testSubjects');
|
||||
const grokDebugger = getService('grokDebugger');
|
||||
|
||||
describe('security', () => {
|
||||
before(async () => {
|
||||
await esArchiver.load('empty_kibana');
|
||||
|
||||
// ensure we're logged out so we can login as the appropriate users
|
||||
await PageObjects.security.forceLogout();
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
// logout, so the other tests don't accidentally run as the custom users we're testing below
|
||||
await PageObjects.security.forceLogout();
|
||||
});
|
||||
|
||||
describe('global dev_tools all privileges', () => {
|
||||
before(async () => {
|
||||
await security.role.create('global_dev_tools_all_role', {
|
||||
kibana: [
|
||||
{
|
||||
feature: {
|
||||
dev_tools: ['all'],
|
||||
},
|
||||
spaces: ['*'],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
await security.user.create('global_dev_tools_all_user', {
|
||||
password: 'global_dev_tools_all_user-password',
|
||||
roles: ['global_dev_tools_all_role'],
|
||||
full_name: 'test user',
|
||||
});
|
||||
|
||||
await PageObjects.security.login(
|
||||
'global_dev_tools_all_user',
|
||||
'global_dev_tools_all_user-password',
|
||||
{
|
||||
expectSpaceSelector: false,
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await security.role.delete('global_dev_tools_all_role');
|
||||
await security.user.delete('global_dev_tools_all_user');
|
||||
});
|
||||
|
||||
it('shows Dev Tools navlink', async () => {
|
||||
const navLinks = await appsMenu.readLinks();
|
||||
expect(navLinks.map((link: Record<string, string>) => link.text)).to.eql([
|
||||
'Dev Tools',
|
||||
'Management',
|
||||
]);
|
||||
});
|
||||
|
||||
it(`can navigate to console`, async () => {
|
||||
await PageObjects.common.navigateToApp('console');
|
||||
await testSubjects.existOrFail('console');
|
||||
});
|
||||
|
||||
it(`can navigate to search profiler`, async () => {
|
||||
await PageObjects.common.navigateToApp('searchProfiler');
|
||||
await testSubjects.existOrFail('searchProfiler');
|
||||
});
|
||||
|
||||
it(`can navigate to grok debugger`, async () => {
|
||||
await PageObjects.common.navigateToApp('grokDebugger');
|
||||
await grokDebugger.assertExists();
|
||||
});
|
||||
});
|
||||
|
||||
describe('global dev_tools read-only privileges', () => {
|
||||
before(async () => {
|
||||
await security.role.create('global_dev_tools_read_role', {
|
||||
kibana: [
|
||||
{
|
||||
feature: {
|
||||
dev_tools: ['read'],
|
||||
},
|
||||
spaces: ['*'],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
await security.user.create('global_dev_tools_read_user', {
|
||||
password: 'global_dev_tools_read_user-password',
|
||||
roles: ['global_dev_tools_read_role'],
|
||||
full_name: 'test user',
|
||||
});
|
||||
|
||||
await PageObjects.security.login(
|
||||
'global_dev_tools_read_user',
|
||||
'global_dev_tools_read_user-password',
|
||||
{
|
||||
expectSpaceSelector: false,
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await security.role.delete('global_dev_tools_read_role');
|
||||
await security.user.delete('global_dev_tools_read_user');
|
||||
});
|
||||
|
||||
it(`shows 'Dev Tools' navlink`, async () => {
|
||||
const navLinks = (await appsMenu.readLinks()).map(
|
||||
(link: Record<string, string>) => link.text
|
||||
);
|
||||
expect(navLinks).to.eql(['Dev Tools', 'Management']);
|
||||
});
|
||||
|
||||
it(`can navigate to console`, async () => {
|
||||
await PageObjects.common.navigateToApp('console');
|
||||
await testSubjects.existOrFail('console');
|
||||
});
|
||||
|
||||
it(`can navigate to search profiler`, async () => {
|
||||
await PageObjects.common.navigateToApp('searchProfiler');
|
||||
await testSubjects.existOrFail('searchProfiler');
|
||||
});
|
||||
|
||||
it(`can navigate to grok debugger`, async () => {
|
||||
await PageObjects.common.navigateToApp('grokDebugger');
|
||||
await grokDebugger.assertExists();
|
||||
});
|
||||
});
|
||||
|
||||
describe('no dev_tools privileges', () => {
|
||||
before(async () => {
|
||||
await security.role.create('no_dev_tools_privileges_role', {
|
||||
kibana: [
|
||||
{
|
||||
feature: {
|
||||
discover: ['all'],
|
||||
},
|
||||
spaces: ['*'],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
await security.user.create('no_dev_tools_privileges_user', {
|
||||
password: 'no_dev_tools_privileges_user-password',
|
||||
roles: ['no_dev_tools_privileges_role'],
|
||||
full_name: 'test user',
|
||||
});
|
||||
|
||||
await PageObjects.security.login(
|
||||
'no_dev_tools_privileges_user',
|
||||
'no_dev_tools_privileges_user-password',
|
||||
{
|
||||
expectSpaceSelector: false,
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await security.role.delete('no_dev_tools_privileges_role');
|
||||
await security.user.delete('no_dev_tools_privileges_user');
|
||||
});
|
||||
|
||||
it(`doesn't show 'Dev Tools' navLink`, async () => {
|
||||
const navLinks = await appsMenu.readLinks();
|
||||
expect(navLinks.map((navLink: any) => navLink.text)).to.not.contain(['Dev Tools']);
|
||||
});
|
||||
|
||||
it(`navigating to console redirect to homepage`, async () => {
|
||||
await PageObjects.common.navigateToUrl('console', '', {
|
||||
ensureCurrentUrl: false,
|
||||
});
|
||||
await testSubjects.existOrFail('homeApp', 10000);
|
||||
});
|
||||
|
||||
it(`navigating to search profiler redirect to homepage`, async () => {
|
||||
await PageObjects.common.navigateToUrl('searchProfiler', '', {
|
||||
ensureCurrentUrl: false,
|
||||
});
|
||||
await testSubjects.existOrFail('homeApp', 10000);
|
||||
});
|
||||
|
||||
it(`navigating to grok debugger redirect to homepage`, async () => {
|
||||
await PageObjects.common.navigateToUrl('grokDebugger', '', {
|
||||
ensureCurrentUrl: false,
|
||||
});
|
||||
await testSubjects.existOrFail('homeApp', 10000);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
* 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 expect from 'expect.js';
|
||||
import { SpacesService } from 'x-pack/test/common/services';
|
||||
import { KibanaFunctionalTestDefaultProviders } from '../../../../types/providers';
|
||||
|
||||
// tslint:disable:no-default-export
|
||||
export default function({ getPageObjects, getService }: KibanaFunctionalTestDefaultProviders) {
|
||||
const esArchiver = getService('esArchiver');
|
||||
const spacesService: SpacesService = getService('spaces');
|
||||
const PageObjects = getPageObjects(['common', 'dashboard', 'security', 'spaceSelector']);
|
||||
const appsMenu = getService('appsMenu');
|
||||
const testSubjects = getService('testSubjects');
|
||||
const grokDebugger = getService('grokDebugger');
|
||||
|
||||
describe('spaces', () => {
|
||||
before(async () => {
|
||||
await esArchiver.load('empty_kibana');
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await esArchiver.unload('empty_kibana');
|
||||
});
|
||||
|
||||
describe('space with no features disabled', () => {
|
||||
before(async () => {
|
||||
await spacesService.create({
|
||||
id: 'custom_space',
|
||||
name: 'custom_space',
|
||||
disabledFeatures: [],
|
||||
});
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await spacesService.delete('custom_space');
|
||||
});
|
||||
|
||||
it(`shows 'Dev Tools' navlink`, async () => {
|
||||
await PageObjects.common.navigateToApp('home', {
|
||||
basePath: '/s/custom_space',
|
||||
});
|
||||
const navLinks = (await appsMenu.readLinks()).map(
|
||||
(link: Record<string, string>) => link.text
|
||||
);
|
||||
expect(navLinks).to.contain('Dev Tools');
|
||||
});
|
||||
|
||||
it(`can navigate to console`, async () => {
|
||||
await PageObjects.common.navigateToApp('console');
|
||||
await testSubjects.existOrFail('console');
|
||||
});
|
||||
|
||||
it(`can navigate to search profiler`, async () => {
|
||||
await PageObjects.common.navigateToApp('searchProfiler');
|
||||
await testSubjects.existOrFail('searchProfiler');
|
||||
});
|
||||
|
||||
it(`can navigate to grok debugger`, async () => {
|
||||
await PageObjects.common.navigateToApp('grokDebugger');
|
||||
await grokDebugger.assertExists();
|
||||
});
|
||||
});
|
||||
|
||||
describe('space with dev_tools disabled', () => {
|
||||
before(async () => {
|
||||
await spacesService.create({
|
||||
id: 'custom_space',
|
||||
name: 'custom_space',
|
||||
disabledFeatures: ['dev_tools'],
|
||||
});
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await spacesService.delete('custom_space');
|
||||
});
|
||||
|
||||
it(`doesn't show 'Dev Tools' navlink`, async () => {
|
||||
await PageObjects.common.navigateToApp('home', {
|
||||
basePath: '/s/custom_space',
|
||||
});
|
||||
const navLinks = (await appsMenu.readLinks()).map(
|
||||
(link: Record<string, string>) => link.text
|
||||
);
|
||||
expect(navLinks).not.to.contain('Dev Tools');
|
||||
});
|
||||
|
||||
it(`navigating to console redirect to homepage`, async () => {
|
||||
await PageObjects.common.navigateToUrl('console', '', {
|
||||
ensureCurrentUrl: false,
|
||||
});
|
||||
await testSubjects.existOrFail('homeApp', 10000);
|
||||
});
|
||||
|
||||
it(`navigating to search profiler redirect to homepage`, async () => {
|
||||
await PageObjects.common.navigateToUrl('searchProfiler', '', {
|
||||
ensureCurrentUrl: false,
|
||||
});
|
||||
await testSubjects.existOrFail('homeApp', 10000);
|
||||
});
|
||||
|
||||
it(`navigating to grok debugger redirect to homepage`, async () => {
|
||||
await PageObjects.common.navigateToUrl('grokDebugger', '', {
|
||||
ensureCurrentUrl: false,
|
||||
});
|
||||
await testSubjects.existOrFail('homeApp', 10000);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
/*
|
||||
* 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 { KibanaFunctionalTestDefaultProviders } from '../../../../types/providers';
|
||||
|
||||
// tslint:disable:no-default-export
|
||||
export default function({ loadTestFile }: KibanaFunctionalTestDefaultProviders) {
|
||||
describe('feature controls', () => {
|
||||
loadTestFile(require.resolve('./dev_tools_security'));
|
||||
loadTestFile(require.resolve('./dev_tools_spaces'));
|
||||
});
|
||||
}
|
15
x-pack/test/functional/apps/dev_tools/index.ts
Normal file
15
x-pack/test/functional/apps/dev_tools/index.ts
Normal file
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
* 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 { KibanaFunctionalTestDefaultProviders } from '../../../types/providers';
|
||||
|
||||
// tslint:disable:no-default-export
|
||||
export default function({ loadTestFile }: KibanaFunctionalTestDefaultProviders) {
|
||||
describe('console', function() {
|
||||
this.tags('ciGroup3');
|
||||
|
||||
loadTestFile(require.resolve('./feature_controls'));
|
||||
});
|
||||
}
|
|
@ -0,0 +1,194 @@
|
|||
/*
|
||||
* 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 expect from 'expect.js';
|
||||
import { SecurityService } from 'x-pack/test/common/services';
|
||||
import { KibanaFunctionalTestDefaultProviders } from '../../../../types/providers';
|
||||
|
||||
// tslint:disable:no-default-export
|
||||
export default function({ getPageObjects, getService }: KibanaFunctionalTestDefaultProviders) {
|
||||
const esArchiver = getService('esArchiver');
|
||||
const security: SecurityService = getService('security');
|
||||
const PageObjects = getPageObjects(['common', 'graph', 'security', 'error']);
|
||||
const testSubjects = getService('testSubjects');
|
||||
const appsMenu = getService('appsMenu');
|
||||
|
||||
describe('security', () => {
|
||||
before(async () => {
|
||||
esArchiver.load('empty_kibana');
|
||||
// ensure we're logged out so we can login as the appropriate users
|
||||
await PageObjects.security.logout();
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
// logout, so the other tests don't accidentally run as the custom users we're testing below
|
||||
await PageObjects.security.logout();
|
||||
});
|
||||
|
||||
describe('global graph all privileges', () => {
|
||||
before(async () => {
|
||||
await security.role.create('global_graph_all_role', {
|
||||
elasticsearch: {
|
||||
indices: [{ names: ['logstash-*'], privileges: ['read', 'view_index_metadata'] }],
|
||||
},
|
||||
kibana: [
|
||||
{
|
||||
feature: {
|
||||
graph: ['all'],
|
||||
},
|
||||
spaces: ['*'],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
await security.user.create('global_graph_all_user', {
|
||||
password: 'global_graph_all_user-password',
|
||||
roles: ['global_graph_all_role'],
|
||||
full_name: 'test user',
|
||||
});
|
||||
|
||||
await PageObjects.security.login(
|
||||
'global_graph_all_user',
|
||||
'global_graph_all_user-password',
|
||||
{
|
||||
expectSpaceSelector: false,
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await security.role.delete('global_graph_all_role');
|
||||
await security.user.delete('global_graph_all_user');
|
||||
});
|
||||
|
||||
it('shows graph navlink', async () => {
|
||||
const navLinks = await appsMenu.readLinks();
|
||||
expect(navLinks.map((link: Record<string, string>) => link.text)).to.eql([
|
||||
'Graph',
|
||||
'Management',
|
||||
]);
|
||||
});
|
||||
|
||||
it('shows save button', async () => {
|
||||
await PageObjects.common.navigateToApp('graph');
|
||||
await testSubjects.existOrFail('graphSaveButton');
|
||||
});
|
||||
|
||||
it('shows delete button', async () => {
|
||||
await PageObjects.common.navigateToApp('graph');
|
||||
await testSubjects.existOrFail('graphDeleteButton');
|
||||
});
|
||||
});
|
||||
|
||||
describe('global graph read-only privileges', () => {
|
||||
before(async () => {
|
||||
await security.role.create('global_graph_read_role', {
|
||||
elasticsearch: {
|
||||
indices: [{ names: ['logstash-*'], privileges: ['read', 'view_index_metadata'] }],
|
||||
},
|
||||
kibana: [
|
||||
{
|
||||
feature: {
|
||||
graph: ['read'],
|
||||
},
|
||||
spaces: ['*'],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
await security.user.create('global_graph_read_user', {
|
||||
password: 'global_graph_read_user-password',
|
||||
roles: ['global_graph_read_role'],
|
||||
full_name: 'test user',
|
||||
});
|
||||
|
||||
await PageObjects.security.login(
|
||||
'global_graph_read_user',
|
||||
'global_graph_read_user-password',
|
||||
{
|
||||
expectSpaceSelector: false,
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await security.role.delete('global_graph_read_role');
|
||||
await security.user.delete('global_graph_read_user');
|
||||
});
|
||||
|
||||
it('shows graph navlink', async () => {
|
||||
const navLinks = (await appsMenu.readLinks()).map(
|
||||
(link: Record<string, string>) => link.text
|
||||
);
|
||||
expect(navLinks).to.eql(['Graph', 'Management']);
|
||||
});
|
||||
|
||||
it(`doesn't show save button`, async () => {
|
||||
await PageObjects.common.navigateToApp('graph');
|
||||
await testSubjects.existOrFail('graphOpenButton');
|
||||
await testSubjects.missingOrFail('graphSaveButton');
|
||||
});
|
||||
|
||||
it(`doesn't show delete button`, async () => {
|
||||
await PageObjects.common.navigateToApp('graph');
|
||||
await testSubjects.existOrFail('graphOpenButton');
|
||||
await testSubjects.missingOrFail('graphSaveButton');
|
||||
});
|
||||
});
|
||||
|
||||
describe('no graph privileges', () => {
|
||||
before(async () => {
|
||||
await security.role.create('no_graph_privileges_role', {
|
||||
elasticsearch: {
|
||||
indices: [{ names: ['logstash-*'], privileges: ['read', 'view_index_metadata'] }],
|
||||
},
|
||||
kibana: [
|
||||
{
|
||||
feature: {
|
||||
dashboard: ['all'],
|
||||
},
|
||||
spaces: ['*'],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
await security.user.create('no_graph_privileges_user', {
|
||||
password: 'no_graph_privileges_user-password',
|
||||
roles: ['no_graph_privileges_role'],
|
||||
full_name: 'test user',
|
||||
});
|
||||
|
||||
await PageObjects.security.login(
|
||||
'no_graph_privileges_user',
|
||||
'no_graph_privileges_user-password',
|
||||
{
|
||||
expectSpaceSelector: false,
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await security.role.delete('no_graph_privileges_role');
|
||||
await security.user.delete('no_graph_privileges_user');
|
||||
});
|
||||
|
||||
it(`doesn't show graph navlink`, async () => {
|
||||
const navLinks = (await appsMenu.readLinks()).map(
|
||||
(link: Record<string, string>) => link.text
|
||||
);
|
||||
expect(navLinks).not.to.contain('Graph');
|
||||
});
|
||||
|
||||
it(`navigating to app displays a 404`, async () => {
|
||||
await PageObjects.common.navigateToUrl('graph', '', {
|
||||
ensureCurrentUrl: false,
|
||||
shouldLoginIfPrompted: false,
|
||||
});
|
||||
|
||||
await PageObjects.error.expectNotFound();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
|
@ -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 expect from 'expect.js';
|
||||
import { SpacesService } from 'x-pack/test/common/services';
|
||||
import { KibanaFunctionalTestDefaultProviders } from '../../../../types/providers';
|
||||
|
||||
// tslint:disable:no-default-export
|
||||
export default function({ getPageObjects, getService }: KibanaFunctionalTestDefaultProviders) {
|
||||
const esArchiver = getService('esArchiver');
|
||||
const spacesService: SpacesService = getService('spaces');
|
||||
const PageObjects = getPageObjects(['common', 'graph', 'security', 'error']);
|
||||
const testSubjects = getService('testSubjects');
|
||||
const appsMenu = getService('appsMenu');
|
||||
|
||||
describe('spaces', () => {
|
||||
before(async () => {
|
||||
await esArchiver.load('empty_kibana');
|
||||
});
|
||||
describe('space with no features disabled', () => {
|
||||
before(async () => {
|
||||
await spacesService.create({
|
||||
id: 'custom_space',
|
||||
name: 'custom_space',
|
||||
disabledFeatures: [],
|
||||
});
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await spacesService.delete('custom_space');
|
||||
});
|
||||
|
||||
it('shows graph navlink', async () => {
|
||||
await PageObjects.common.navigateToApp('home', {
|
||||
basePath: '/s/custom_space',
|
||||
});
|
||||
const navLinks = (await appsMenu.readLinks()).map(
|
||||
(link: Record<string, string>) => link.text
|
||||
);
|
||||
expect(navLinks).to.contain('Graph');
|
||||
});
|
||||
|
||||
it('shows save button', async () => {
|
||||
await PageObjects.common.navigateToApp('graph', {
|
||||
basePath: '/s/custom_space',
|
||||
});
|
||||
await testSubjects.existOrFail('graphSaveButton');
|
||||
});
|
||||
|
||||
it('shows delete button', async () => {
|
||||
await PageObjects.common.navigateToApp('graph', {
|
||||
basePath: '/s/custom_space',
|
||||
});
|
||||
await testSubjects.existOrFail('graphDeleteButton');
|
||||
});
|
||||
});
|
||||
|
||||
describe('space with Graph disabled', () => {
|
||||
before(async () => {
|
||||
await spacesService.create({
|
||||
id: 'custom_space',
|
||||
name: 'custom_space',
|
||||
disabledFeatures: ['graph'],
|
||||
});
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await spacesService.delete('custom_space');
|
||||
});
|
||||
|
||||
it(`doesn't show graph navlink`, async () => {
|
||||
await PageObjects.common.navigateToApp('home', {
|
||||
basePath: '/s/custom_space',
|
||||
});
|
||||
const navLinks = (await appsMenu.readLinks()).map(
|
||||
(link: Record<string, string>) => link.text
|
||||
);
|
||||
expect(navLinks).not.to.contain('Graph');
|
||||
});
|
||||
|
||||
it(`navigating to app shows 404`, async () => {
|
||||
await PageObjects.common.navigateToUrl('graph', '', {
|
||||
basePath: '/s/custom_space',
|
||||
shouldLoginIfPrompted: false,
|
||||
ensureCurrentUrl: false,
|
||||
});
|
||||
await PageObjects.error.expectNotFound();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
14
x-pack/test/functional/apps/graph/feature_controls/index.ts
Normal file
14
x-pack/test/functional/apps/graph/feature_controls/index.ts
Normal file
|
@ -0,0 +1,14 @@
|
|||
/*
|
||||
* 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 { KibanaFunctionalTestDefaultProviders } from '../../../../types/providers';
|
||||
|
||||
// tslint:disable:no-default-export
|
||||
export default function({ loadTestFile }: KibanaFunctionalTestDefaultProviders) {
|
||||
describe('feature controls', () => {
|
||||
loadTestFile(require.resolve('./graph_security'));
|
||||
loadTestFile(require.resolve('./graph_spaces'));
|
||||
});
|
||||
}
|
|
@ -8,6 +8,7 @@ export default function ({ loadTestFile }) {
|
|||
describe('graph app', function () {
|
||||
this.tags('ciGroup1');
|
||||
|
||||
loadTestFile(require.resolve('./feature_controls'));
|
||||
loadTestFile(require.resolve('./graph'));
|
||||
});
|
||||
}
|
||||
|
|
|
@ -102,6 +102,7 @@ export default async function ({ readConfigFile }) {
|
|||
resolve(__dirname, './apps/visualize'),
|
||||
resolve(__dirname, './apps/uptime'),
|
||||
resolve(__dirname, './apps/saved_objects_management'),
|
||||
resolve(__dirname, './apps/dev_tools')
|
||||
],
|
||||
|
||||
// define the name and providers for services that should be
|
||||
|
@ -215,6 +216,10 @@ export default async function ({ readConfigFile }) {
|
|||
pathname: '/app/kibana',
|
||||
hash: '/dev_tools/grokdebugger',
|
||||
},
|
||||
searchProfiler: {
|
||||
pathname: '/app/kibana',
|
||||
hash: '/dev_tools/searchprofiler',
|
||||
},
|
||||
spaceSelector: {
|
||||
pathname: '/',
|
||||
},
|
||||
|
|
|
@ -97,6 +97,22 @@ export function SecurityPageProvider({ getService, getPageObjects }) {
|
|||
));
|
||||
}
|
||||
|
||||
async forceLogout() {
|
||||
log.debug('SecurityPage.forceLogout');
|
||||
if (await find.existsByDisplayedByCssSelector('.login-form', 100)) {
|
||||
log.debug('Already on the login page, not forcing anything');
|
||||
return;
|
||||
}
|
||||
|
||||
log.debug('Redirecting to /logout to force the logout');
|
||||
const url = PageObjects.common.getHostPort() + '/logout';
|
||||
await browser.get(url);
|
||||
log.debug('Waiting on the login form to appear');
|
||||
await retry.waitForWithTimeout('login form', config.get('timeouts.waitFor') * 5, async () => (
|
||||
await find.existsByDisplayedByCssSelector('.login-form')
|
||||
));
|
||||
}
|
||||
|
||||
async clickRolesSection() {
|
||||
await testSubjects.click('roles');
|
||||
}
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* 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 expect from 'expect.js';
|
||||
import { KibanaFunctionalTestDefaultProviders } from '../../../types/providers';
|
||||
import {
|
||||
GetUICapabilitiesFailureReason,
|
||||
UICapabilitiesService,
|
||||
} from '../../common/services/ui_capabilities';
|
||||
import { UserAtSpaceScenarios } from '../scenarios';
|
||||
|
||||
// tslint:disable:no-default-export
|
||||
export default function devToolsTests({ getService }: KibanaFunctionalTestDefaultProviders) {
|
||||
const uiCapabilitiesService: UICapabilitiesService = getService('uiCapabilities');
|
||||
|
||||
describe('dev_tools', () => {
|
||||
UserAtSpaceScenarios.forEach(scenario => {
|
||||
it(`${scenario.id}`, async () => {
|
||||
const { user, space } = scenario;
|
||||
|
||||
const uiCapabilities = await uiCapabilitiesService.get(
|
||||
{ username: user.username, password: user.password },
|
||||
space.id
|
||||
);
|
||||
switch (scenario.id) {
|
||||
// these users have a read/write view of Dev Tools
|
||||
case 'superuser at everything_space':
|
||||
case 'global_all at everything_space':
|
||||
case 'dual_privileges_all at everything_space':
|
||||
case 'everything_space_all at everything_space':
|
||||
expect(uiCapabilities.success).to.be(true);
|
||||
expect(uiCapabilities.value).to.have.property('dev_tools');
|
||||
expect(uiCapabilities.value!.dev_tools).to.eql({
|
||||
show: true,
|
||||
});
|
||||
break;
|
||||
// these users have a read only view of Dev Tools
|
||||
// for the time being, this is functionally equivalent to the read/write view
|
||||
case 'global_read at everything_space':
|
||||
case 'dual_privileges_read at everything_space':
|
||||
case 'everything_space_read at everything_space':
|
||||
expect(uiCapabilities.success).to.be(true);
|
||||
expect(uiCapabilities.value).to.have.property('dev_tools');
|
||||
expect(uiCapabilities.value!.dev_tools).to.eql({
|
||||
show: true,
|
||||
});
|
||||
break;
|
||||
// the nothing_space has no features enabled, so even if we have
|
||||
// privileges to perform these actions, we won't be able to
|
||||
case 'superuser at nothing_space':
|
||||
case 'global_all at nothing_space':
|
||||
case 'global_read at nothing_space':
|
||||
case 'dual_privileges_all at nothing_space':
|
||||
case 'dual_privileges_read at nothing_space':
|
||||
case 'nothing_space_all at nothing_space':
|
||||
case 'nothing_space_read at nothing_space':
|
||||
expect(uiCapabilities.success).to.be(true);
|
||||
expect(uiCapabilities.value).to.have.property('dev_tools');
|
||||
expect(uiCapabilities.value!.dev_tools).to.eql({
|
||||
show: false,
|
||||
});
|
||||
break;
|
||||
// if we don't have access at the space itself, we're
|
||||
// redirected to the space selector and the ui capabilities
|
||||
// are lagely irrelevant because they won't be consumed
|
||||
case 'no_kibana_privileges at everything_space':
|
||||
case 'no_kibana_privileges at nothing_space':
|
||||
case 'legacy_all at everything_space':
|
||||
case 'legacy_all at nothing_space':
|
||||
case 'everything_space_all at nothing_space':
|
||||
case 'everything_space_read at nothing_space':
|
||||
case 'nothing_space_all at everything_space':
|
||||
case 'nothing_space_read at everything_space':
|
||||
expect(uiCapabilities.success).to.be(false);
|
||||
expect(uiCapabilities.failureReason).to.be(
|
||||
GetUICapabilitiesFailureReason.RedirectedToRoot
|
||||
);
|
||||
break;
|
||||
default:
|
||||
throw new UnreachableError(scenario);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* 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 expect from 'expect.js';
|
||||
import { UICapabilities } from 'ui/capabilities';
|
||||
import { KibanaFunctionalTestDefaultProviders } from '../../../types/providers';
|
||||
import {
|
||||
GetUICapabilitiesFailureReason,
|
||||
UICapabilitiesService,
|
||||
} from '../../common/services/ui_capabilities';
|
||||
import { UserAtSpaceScenarios } from '../scenarios';
|
||||
|
||||
// tslint:disable:no-default-export
|
||||
export default function graphTests({ getService }: KibanaFunctionalTestDefaultProviders) {
|
||||
const uiCapabilitiesService: UICapabilitiesService = getService('uiCapabilities');
|
||||
|
||||
describe('graph', () => {
|
||||
UserAtSpaceScenarios.forEach(scenario => {
|
||||
it(`${scenario.id}`, async () => {
|
||||
const { user, space } = scenario;
|
||||
|
||||
const uiCapabilities = await uiCapabilitiesService.get(
|
||||
{ username: user.username, password: user.password },
|
||||
space.id
|
||||
);
|
||||
const capabilities: UICapabilities = uiCapabilities.value as UICapabilities;
|
||||
switch (scenario.id) {
|
||||
// these users have a read/write view of Graph
|
||||
case 'superuser at everything_space':
|
||||
case 'global_all at everything_space':
|
||||
case 'dual_privileges_all at everything_space':
|
||||
case 'everything_space_all at everything_space':
|
||||
expect(uiCapabilities.success).to.be(true);
|
||||
expect(capabilities).to.have.property('graph');
|
||||
expect(capabilities.graph).to.eql({
|
||||
save: true,
|
||||
delete: true,
|
||||
});
|
||||
expect(capabilities.catalogue.graph).to.eql(true);
|
||||
break;
|
||||
// these users have a read only view of Graph
|
||||
case 'global_read at everything_space':
|
||||
case 'dual_privileges_read at everything_space':
|
||||
case 'everything_space_read at everything_space':
|
||||
expect(uiCapabilities.success).to.be(true);
|
||||
expect(capabilities).to.have.property('graph');
|
||||
expect(capabilities.graph).to.eql({
|
||||
save: false,
|
||||
delete: false,
|
||||
});
|
||||
expect(capabilities.catalogue.graph).to.eql(true);
|
||||
break;
|
||||
// the nothing_space has no features enabled, so even if we have
|
||||
// privileges to perform these actions, we won't be able to
|
||||
case 'superuser at nothing_space':
|
||||
case 'global_all at nothing_space':
|
||||
case 'global_read at nothing_space':
|
||||
case 'dual_privileges_all at nothing_space':
|
||||
case 'dual_privileges_read at nothing_space':
|
||||
case 'nothing_space_all at nothing_space':
|
||||
case 'nothing_space_read at nothing_space':
|
||||
expect(uiCapabilities.success).to.be(true);
|
||||
expect(capabilities).to.have.property('graph');
|
||||
expect(capabilities.graph).to.eql({
|
||||
save: false,
|
||||
delete: false,
|
||||
});
|
||||
expect(capabilities.catalogue.graph).to.eql(false);
|
||||
break;
|
||||
// if we don't have access at the space itself, we're
|
||||
// redirected to the space selector and the ui capabilities
|
||||
// are lagely irrelevant because they won't be consumed
|
||||
case 'no_kibana_privileges at everything_space':
|
||||
case 'no_kibana_privileges at nothing_space':
|
||||
case 'legacy_all at everything_space':
|
||||
case 'legacy_all at nothing_space':
|
||||
case 'everything_space_all at nothing_space':
|
||||
case 'everything_space_read at nothing_space':
|
||||
case 'nothing_space_all at everything_space':
|
||||
case 'nothing_space_read at everything_space':
|
||||
expect(uiCapabilities.success).to.be(false);
|
||||
expect(uiCapabilities.failureReason).to.be(
|
||||
GetUICapabilitiesFailureReason.RedirectedToRoot
|
||||
);
|
||||
break;
|
||||
default:
|
||||
throw new UnreachableError(scenario);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
|
@ -57,7 +57,9 @@ export default function uiCapabilitesTests({
|
|||
loadTestFile(require.resolve('./advanced_settings'));
|
||||
loadTestFile(require.resolve('./canvas'));
|
||||
loadTestFile(require.resolve('./dashboard'));
|
||||
loadTestFile(require.resolve('./dev_tools'));
|
||||
loadTestFile(require.resolve('./discover'));
|
||||
loadTestFile(require.resolve('./graph'));
|
||||
loadTestFile(require.resolve('./maps'));
|
||||
loadTestFile(require.resolve('./nav_links'));
|
||||
loadTestFile(require.resolve('./saved_objects_management'));
|
||||
|
|
66
x-pack/test/ui_capabilities/security_only/tests/dev_tools.ts
Normal file
66
x-pack/test/ui_capabilities/security_only/tests/dev_tools.ts
Normal file
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* 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 expect from 'expect.js';
|
||||
import { KibanaFunctionalTestDefaultProviders } from '../../../types/providers';
|
||||
import {
|
||||
GetUICapabilitiesFailureReason,
|
||||
UICapabilitiesService,
|
||||
} from '../../common/services/ui_capabilities';
|
||||
import { UserScenarios } from '../scenarios';
|
||||
|
||||
// tslint:disable:no-default-export
|
||||
export default function devToolsTests({ getService }: KibanaFunctionalTestDefaultProviders) {
|
||||
const uiCapabilitiesService: UICapabilitiesService = getService('uiCapabilities');
|
||||
|
||||
describe('dev_tools', () => {
|
||||
UserScenarios.forEach(scenario => {
|
||||
it(`${scenario.fullName}`, async () => {
|
||||
const uiCapabilities = await uiCapabilitiesService.get({
|
||||
username: scenario.username,
|
||||
password: scenario.password,
|
||||
});
|
||||
switch (scenario.username) {
|
||||
// these users have a read/write view of Dev Tools
|
||||
case 'superuser':
|
||||
case 'all':
|
||||
case 'dual_privileges_all':
|
||||
case 'dev_tools_all':
|
||||
expect(uiCapabilities.success).to.be(true);
|
||||
expect(uiCapabilities.value).to.have.property('dev_tools');
|
||||
expect(uiCapabilities.value!.dev_tools).to.eql({
|
||||
show: true,
|
||||
});
|
||||
break;
|
||||
// these users have a read-only view of Dev Tools
|
||||
// for the time being, this is functionally equivalent to the read/write view
|
||||
case 'dual_privileges_read':
|
||||
case 'dev_tools_all':
|
||||
case 'dev_tools_read':
|
||||
expect(uiCapabilities.success).to.be(true);
|
||||
expect(uiCapabilities.value).to.have.property('dev_tools');
|
||||
expect(uiCapabilities.value!.dev_tools).to.eql({
|
||||
show: true,
|
||||
});
|
||||
break;
|
||||
// these users have no access to even get the ui capabilities
|
||||
case 'legacy_all':
|
||||
case 'no_kibana_privileges':
|
||||
expect(uiCapabilities.success).to.be(false);
|
||||
expect(uiCapabilities.failureReason).to.be(GetUICapabilitiesFailureReason.NotFound);
|
||||
break;
|
||||
// all other users can't do anything with Dashboard
|
||||
default:
|
||||
expect(uiCapabilities.success).to.be(true);
|
||||
expect(uiCapabilities.value).to.have.property('dev_tools');
|
||||
expect(uiCapabilities.value!.dev_tools).to.eql({
|
||||
show: false,
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
71
x-pack/test/ui_capabilities/security_only/tests/graph.ts
Normal file
71
x-pack/test/ui_capabilities/security_only/tests/graph.ts
Normal file
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* 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 expect from 'expect.js';
|
||||
import { UICapabilities } from 'ui/capabilities';
|
||||
import { KibanaFunctionalTestDefaultProviders } from '../../../types/providers';
|
||||
import {
|
||||
GetUICapabilitiesFailureReason,
|
||||
UICapabilitiesService,
|
||||
} from '../../common/services/ui_capabilities';
|
||||
import { UserScenarios } from '../scenarios';
|
||||
|
||||
// tslint:disable:no-default-export
|
||||
export default function graphTests({ getService }: KibanaFunctionalTestDefaultProviders) {
|
||||
const uiCapabilitiesService: UICapabilitiesService = getService('uiCapabilities');
|
||||
|
||||
describe('graph', () => {
|
||||
UserScenarios.forEach(scenario => {
|
||||
it(`${scenario.fullName}`, async () => {
|
||||
const uiCapabilities = await uiCapabilitiesService.get({
|
||||
username: scenario.username,
|
||||
password: scenario.password,
|
||||
});
|
||||
|
||||
const capabilities: UICapabilities = uiCapabilities.value as UICapabilities;
|
||||
|
||||
switch (scenario.username) {
|
||||
// these users have a read/write view of Graph
|
||||
case 'superuser':
|
||||
case 'all':
|
||||
case 'dual_privileges_all':
|
||||
case 'graph_all':
|
||||
expect(uiCapabilities.success).to.be(true);
|
||||
expect(capabilities).to.have.property('graph');
|
||||
expect(capabilities!.graph).to.eql({
|
||||
save: true,
|
||||
delete: true,
|
||||
});
|
||||
break;
|
||||
// these users have a read-only view of Graph
|
||||
case 'dual_privileges_read':
|
||||
case 'graph_read':
|
||||
expect(uiCapabilities.success).to.be(true);
|
||||
expect(capabilities).to.have.property('graph');
|
||||
expect(capabilities!.graph).to.eql({
|
||||
save: false,
|
||||
delete: false,
|
||||
});
|
||||
break;
|
||||
// these users have no access to even get the ui capabilities
|
||||
case 'no_kibana_privileges':
|
||||
case 'legacy_all':
|
||||
expect(uiCapabilities.success).to.be(false);
|
||||
expect(uiCapabilities.failureReason).to.be(GetUICapabilitiesFailureReason.NotFound);
|
||||
break;
|
||||
// all other users can't do anything with Graph
|
||||
default:
|
||||
expect(uiCapabilities.success).to.be(true);
|
||||
expect(capabilities).to.have.property('graph');
|
||||
expect(capabilities!.graph).to.eql({
|
||||
save: false,
|
||||
delete: false,
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
|
@ -46,7 +46,9 @@ export default function uiCapabilitesTests({
|
|||
loadTestFile(require.resolve('./advanced_settings'));
|
||||
loadTestFile(require.resolve('./canvas'));
|
||||
loadTestFile(require.resolve('./dashboard'));
|
||||
loadTestFile(require.resolve('./dev_tools'));
|
||||
loadTestFile(require.resolve('./discover'));
|
||||
loadTestFile(require.resolve('./graph'));
|
||||
loadTestFile(require.resolve('./maps'));
|
||||
loadTestFile(require.resolve('./nav_links'));
|
||||
loadTestFile(require.resolve('./saved_objects_management'));
|
||||
|
|
56
x-pack/test/ui_capabilities/spaces_only/tests/dev_tools.ts
Normal file
56
x-pack/test/ui_capabilities/spaces_only/tests/dev_tools.ts
Normal file
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* 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 expect from 'expect.js';
|
||||
import { KibanaFunctionalTestDefaultProviders } from '../../../types/providers';
|
||||
import { UICapabilitiesService } from '../../common/services/ui_capabilities';
|
||||
import { SpaceScenarios } from '../scenarios';
|
||||
|
||||
// tslint:disable:no-default-export
|
||||
export default function devToolsTests({ getService }: KibanaFunctionalTestDefaultProviders) {
|
||||
const uiCapabilitiesService: UICapabilitiesService = getService('uiCapabilities');
|
||||
|
||||
describe('dev_tools', () => {
|
||||
SpaceScenarios.forEach(scenario => {
|
||||
it(`${scenario.name}`, async () => {
|
||||
const uiCapabilities = await uiCapabilitiesService.get(null, scenario.id);
|
||||
switch (scenario.id) {
|
||||
case 'everything_space':
|
||||
case 'apm_disabled_space':
|
||||
case 'advanced_settings_disabled_space':
|
||||
case 'canvas_disabled_space':
|
||||
case 'dashboard_disabled_space':
|
||||
case 'discover_disabled_space':
|
||||
case 'graph_disabled_space':
|
||||
case 'maps_disabled_space':
|
||||
case 'infrastructure_disabled_space':
|
||||
case 'logs_disabled_space':
|
||||
case 'ml_disabled_space':
|
||||
case 'monitoring_disabled_space':
|
||||
case 'timelion_disabled_space':
|
||||
case 'uptime_disabled_space':
|
||||
case 'visualize_disabled_space':
|
||||
expect(uiCapabilities.success).to.be(true);
|
||||
expect(uiCapabilities.value).to.have.property('dev_tools');
|
||||
expect(uiCapabilities.value!.dev_tools).to.eql({
|
||||
show: true,
|
||||
});
|
||||
break;
|
||||
case 'nothing_space':
|
||||
case 'dev_tools_disabled_space':
|
||||
expect(uiCapabilities.success).to.be(true);
|
||||
expect(uiCapabilities.value).to.have.property('dev_tools');
|
||||
expect(uiCapabilities.value!.dev_tools).to.eql({
|
||||
show: false,
|
||||
});
|
||||
break;
|
||||
default:
|
||||
throw new UnreachableError(scenario);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
60
x-pack/test/ui_capabilities/spaces_only/tests/graph.ts
Normal file
60
x-pack/test/ui_capabilities/spaces_only/tests/graph.ts
Normal file
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* 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 expect from 'expect.js';
|
||||
import { UICapabilities } from 'ui/capabilities';
|
||||
import { KibanaFunctionalTestDefaultProviders } from '../../../types/providers';
|
||||
import { UICapabilitiesService } from '../../common/services/ui_capabilities';
|
||||
import { SpaceScenarios } from '../scenarios';
|
||||
|
||||
// tslint:disable:no-default-export
|
||||
export default function graphTests({ getService }: KibanaFunctionalTestDefaultProviders) {
|
||||
const uiCapabilitiesService: UICapabilitiesService = getService('uiCapabilities');
|
||||
|
||||
describe('graph', () => {
|
||||
SpaceScenarios.forEach(scenario => {
|
||||
it(`${scenario.name}`, async () => {
|
||||
const uiCapabilities = await uiCapabilitiesService.get(null, scenario.id);
|
||||
const capabilities: UICapabilities = uiCapabilities.value as UICapabilities;
|
||||
switch (scenario.id) {
|
||||
case 'everything_space':
|
||||
case 'apm_disabled_space':
|
||||
case 'advanced_settings_disabled_space':
|
||||
case 'canvas_disabled_space':
|
||||
case 'dashboard_disabled_space':
|
||||
case 'dev_tools_disabled_space':
|
||||
case 'discover_disabled_space':
|
||||
case 'maps_disabled_space':
|
||||
case 'infrastructure_disabled_space':
|
||||
case 'logs_disabled_space':
|
||||
case 'ml_disabled_space':
|
||||
case 'monitoring_disabled_space':
|
||||
case 'timelion_disabled_space':
|
||||
case 'uptime_disabled_space':
|
||||
case 'visualize_disabled_space':
|
||||
expect(uiCapabilities.success).to.be(true);
|
||||
expect(capabilities).to.have.property('graph');
|
||||
expect(capabilities!.graph).to.eql({
|
||||
save: true,
|
||||
delete: true,
|
||||
});
|
||||
break;
|
||||
case 'nothing_space':
|
||||
case 'graph_disabled_space':
|
||||
expect(uiCapabilities.success).to.be(true);
|
||||
expect(capabilities).to.have.property('graph');
|
||||
expect(capabilities!.graph).to.eql({
|
||||
delete: false,
|
||||
save: false,
|
||||
});
|
||||
break;
|
||||
default:
|
||||
throw new UnreachableError(scenario);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
|
@ -33,7 +33,9 @@ export default function uiCapabilitesTests({
|
|||
loadTestFile(require.resolve('./advanced_settings'));
|
||||
loadTestFile(require.resolve('./canvas'));
|
||||
loadTestFile(require.resolve('./dashboard'));
|
||||
loadTestFile(require.resolve('./dev_tools'));
|
||||
loadTestFile(require.resolve('./discover'));
|
||||
loadTestFile(require.resolve('./graph'));
|
||||
loadTestFile(require.resolve('./maps'));
|
||||
loadTestFile(require.resolve('./nav_links'));
|
||||
loadTestFile(require.resolve('./saved_objects_management'));
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue