Feature Controls - Simplify Saved Objects Management UI Capabilities (#38461)
* start simplifying saved objects management UI Capabilities * update tests * simplify UI * address PR feedback * remove savedObjectsManagement UI Capabilities tests
This commit is contained in:
parent
9c36f5e343
commit
ee27bc4083
|
@ -240,9 +240,7 @@ export default function (kibana) {
|
|||
migrations,
|
||||
},
|
||||
|
||||
uiCapabilities: async function (server) {
|
||||
const { savedObjects } = server;
|
||||
|
||||
uiCapabilities: async function () {
|
||||
return {
|
||||
discover: {
|
||||
show: true,
|
||||
|
@ -275,14 +273,11 @@ export default function (kibana) {
|
|||
indexPatterns: {
|
||||
save: true,
|
||||
},
|
||||
savedObjectsManagement: savedObjects.types.reduce((acc, type) => ({
|
||||
...acc,
|
||||
[type]: {
|
||||
delete: true,
|
||||
edit: true,
|
||||
read: true,
|
||||
}
|
||||
}), {}),
|
||||
savedObjectsManagement: {
|
||||
delete: true,
|
||||
edit: true,
|
||||
read: true,
|
||||
},
|
||||
management: {
|
||||
/*
|
||||
* Management settings correspond to management section/link ids, and should not be changed
|
||||
|
|
|
@ -139,7 +139,7 @@ uiModules.get('apps/management', ['monospaced.elastic'])
|
|||
}
|
||||
};
|
||||
|
||||
const { edit: canEdit, delete: canDelete } = uiCapabilities.savedObjectsManagement[service.type];
|
||||
const { edit: canEdit, delete: canDelete } = uiCapabilities.savedObjectsManagement;
|
||||
$scope.canEdit = canEdit;
|
||||
$scope.canDelete = canDelete;
|
||||
$scope.canViewInApp = canViewInApp(uiCapabilities, service.type);
|
||||
|
|
|
@ -257,7 +257,7 @@ exports[`ObjectsTable should render normally 1`] = `
|
|||
size="xs"
|
||||
/>
|
||||
<InjectIntl(TableUI)
|
||||
canDeleteSavedObjectTypes={Array []}
|
||||
canDelete={false}
|
||||
filterOptions={
|
||||
Array [
|
||||
Object {
|
||||
|
|
|
@ -134,26 +134,12 @@ const defaultProps = {
|
|||
services: [],
|
||||
uiCapabilities: {
|
||||
savedObjectsManagement: {
|
||||
'index-pattern': {
|
||||
read: true
|
||||
},
|
||||
visualization: {
|
||||
read: true
|
||||
},
|
||||
dashboard: {
|
||||
read: true
|
||||
},
|
||||
search: {
|
||||
read: true
|
||||
}
|
||||
read: true,
|
||||
edit: false,
|
||||
delete: false,
|
||||
}
|
||||
},
|
||||
canDeleteSavedObjectTypes: [
|
||||
'index-pattern',
|
||||
'visualization',
|
||||
'dashboard',
|
||||
'search'
|
||||
]
|
||||
canDelete: true,
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
|
@ -272,41 +258,6 @@ describe('ObjectsTable', () => {
|
|||
expect(addDangerMock).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should filter find operation based on the uiCapabilities', async () => {
|
||||
const uiCapabilities = {
|
||||
savedObjectsManagement: {
|
||||
'index-pattern': {
|
||||
read: false,
|
||||
},
|
||||
visualization: {
|
||||
read: false,
|
||||
},
|
||||
dashboard: {
|
||||
read: false,
|
||||
},
|
||||
search: {
|
||||
read: true,
|
||||
}
|
||||
}
|
||||
};
|
||||
const customizedProps = { ...defaultProps, uiCapabilities };
|
||||
const component = shallowWithIntl(
|
||||
<ObjectsTable.WrappedComponent
|
||||
{...customizedProps}
|
||||
perPageConfig={15}
|
||||
/>
|
||||
);
|
||||
|
||||
// Ensure all promises resolve
|
||||
await new Promise(resolve => process.nextTick(resolve));
|
||||
// Ensure the state changes are reflected
|
||||
component.update();
|
||||
|
||||
expect(findObjects).toHaveBeenCalledWith(expect.objectContaining({
|
||||
type: ['search']
|
||||
}));
|
||||
});
|
||||
|
||||
describe('export', () => {
|
||||
it('should export selected objects', async () => {
|
||||
const mockSelectedSavedObjects = [
|
||||
|
@ -452,42 +403,6 @@ describe('ObjectsTable', () => {
|
|||
expect(getRelationships).toHaveBeenCalledWith('search', '1', savedObjectTypes, defaultProps.$http, defaultProps.basePath);
|
||||
});
|
||||
|
||||
it('should fetch relationships filtered based on the uiCapabilities', async () => {
|
||||
const { getRelationships } = require('../../../lib/get_relationships');
|
||||
|
||||
const uiCapabilities = {
|
||||
savedObjectsManagement: {
|
||||
'index-pattern': {
|
||||
read: false,
|
||||
},
|
||||
visualization: {
|
||||
read: false,
|
||||
},
|
||||
dashboard: {
|
||||
read: false,
|
||||
},
|
||||
search: {
|
||||
read: true,
|
||||
}
|
||||
}
|
||||
};
|
||||
const customizedProps = { ...defaultProps, uiCapabilities };
|
||||
const component = shallowWithIntl(
|
||||
<ObjectsTable.WrappedComponent
|
||||
{...customizedProps}
|
||||
/>
|
||||
);
|
||||
|
||||
// Ensure all promises resolve
|
||||
await new Promise(resolve => process.nextTick(resolve));
|
||||
// Ensure the state changes are reflected
|
||||
component.update();
|
||||
|
||||
await component.instance().getRelationships('search', '1');
|
||||
const savedObjectTypes = ['search'];
|
||||
expect(getRelationships).toHaveBeenCalledWith('search', '1', savedObjectTypes, defaultProps.$http, defaultProps.basePath);
|
||||
});
|
||||
|
||||
it('should show the flyout', async () => {
|
||||
const component = shallowWithIntl(
|
||||
<ObjectsTable.WrappedComponent
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Table restricts which saved objects can be deleted based on type 1`] = `
|
||||
exports[`Table prevents saved objects from being deleted 1`] = `
|
||||
<Fragment>
|
||||
<EuiSearchBar
|
||||
box={
|
||||
|
@ -35,7 +35,7 @@ exports[`Table restricts which saved objects can be deleted based on type 1`] =
|
|||
isDisabled={true}
|
||||
onClick={[Function]}
|
||||
size="m"
|
||||
title="Unable to delete search, index-pattern"
|
||||
title="Unable to delete saved objects"
|
||||
type="button"
|
||||
>
|
||||
<FormattedMessage
|
||||
|
@ -247,10 +247,9 @@ exports[`Table should render normally 1`] = `
|
|||
fill={false}
|
||||
iconSide="left"
|
||||
iconType="trash"
|
||||
isDisabled={true}
|
||||
isDisabled={false}
|
||||
onClick={[Function]}
|
||||
size="m"
|
||||
title="Unable to delete index-pattern"
|
||||
type="button"
|
||||
>
|
||||
<FormattedMessage
|
||||
|
|
|
@ -86,7 +86,7 @@ const defaultProps = {
|
|||
onTableChange: () => {},
|
||||
isSearching: false,
|
||||
onShowRelationships: () => {},
|
||||
canDeleteSavedObjectTypes: ['visualization']
|
||||
canDelete: true
|
||||
};
|
||||
|
||||
describe('Table', () => {
|
||||
|
@ -127,9 +127,9 @@ describe('Table', () => {
|
|||
expect(component.state().isSearchTextValid).toBe(true);
|
||||
});
|
||||
|
||||
it(`restricts which saved objects can be deleted based on type`, () => {
|
||||
it(`prevents saved objects from being deleted`, () => {
|
||||
const selectedSavedObjects = [{ type: 'visualization' }, { type: 'search' }, { type: 'index-pattern' }];
|
||||
const customizedProps = { ...defaultProps, selectedSavedObjects, canDeleteSavedObjectTypes: ['visualization'] };
|
||||
const customizedProps = { ...defaultProps, selectedSavedObjects, canDelete: false };
|
||||
const component = shallowWithIntl(
|
||||
<Table.WrappedComponent
|
||||
{...customizedProps}
|
||||
|
|
|
@ -36,6 +36,7 @@ import {
|
|||
EuiText
|
||||
} from '@elastic/eui';
|
||||
import { getDefaultTitle, getSavedObjectLabel } from '../../../../lib';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { FormattedMessage, injectI18n } from '@kbn/i18n/react';
|
||||
|
||||
class TableUI extends PureComponent {
|
||||
|
@ -47,7 +48,7 @@ class TableUI extends PureComponent {
|
|||
onSelectionChange: PropTypes.func.isRequired,
|
||||
}).isRequired,
|
||||
filterOptions: PropTypes.array.isRequired,
|
||||
canDeleteSavedObjectTypes: PropTypes.array.isRequired,
|
||||
canDelete: PropTypes.bool.isRequired,
|
||||
onDelete: PropTypes.func.isRequired,
|
||||
onExport: PropTypes.func.isRequired,
|
||||
goInspectObject: PropTypes.func.isRequired,
|
||||
|
@ -254,10 +255,6 @@ class TableUI extends PureComponent {
|
|||
);
|
||||
}
|
||||
|
||||
const unableToDeleteSavedObjectTypes = selectedSavedObjects
|
||||
.map(({ type }) => type)
|
||||
.filter(type => !this.props.canDeleteSavedObjectTypes.includes(type));
|
||||
|
||||
const button = (
|
||||
<EuiButton
|
||||
iconType="arrowDown"
|
||||
|
@ -286,10 +283,15 @@ class TableUI extends PureComponent {
|
|||
onClick={onDelete}
|
||||
isDisabled={
|
||||
selectedSavedObjects.length === 0 ||
|
||||
unableToDeleteSavedObjectTypes.length > 0
|
||||
!this.props.canDelete
|
||||
}
|
||||
title={
|
||||
unableToDeleteSavedObjectTypes.length > 0 ? `Unable to delete ${unableToDeleteSavedObjectTypes.join(', ')}` : undefined
|
||||
this.props.canDelete
|
||||
? undefined
|
||||
: i18n.translate(
|
||||
'kbn.management.objects.objectsTable.table.deleteButtonTitle',
|
||||
{ defaultMessage: 'Unable to delete saved objects' }
|
||||
)
|
||||
}
|
||||
data-test-subj="savedObjectsManagementDelete"
|
||||
>
|
||||
|
|
|
@ -82,9 +82,7 @@ class ObjectsTableUI extends Component {
|
|||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.savedObjectTypes = POSSIBLE_TYPES.filter(type => {
|
||||
return this.props.uiCapabilities.savedObjectsManagement[type].read;
|
||||
});
|
||||
this.savedObjectTypes = POSSIBLE_TYPES;
|
||||
|
||||
this.state = {
|
||||
totalCount: 0,
|
||||
|
@ -677,10 +675,6 @@ class ObjectsTableUI extends Component {
|
|||
view: `${type} (${savedObjectCounts[type] || 0})`,
|
||||
}));
|
||||
|
||||
const canDeleteSavedObjectTypes = POSSIBLE_TYPES.filter(type => {
|
||||
return this.props.uiCapabilities.savedObjectsManagement[type].delete;
|
||||
});
|
||||
|
||||
return (
|
||||
<EuiPageContent
|
||||
horizontalPosition="center"
|
||||
|
@ -706,7 +700,7 @@ class ObjectsTableUI extends Component {
|
|||
onTableChange={this.onTableChange}
|
||||
filterOptions={filterOptions}
|
||||
onExport={this.onExport}
|
||||
canDeleteSavedObjectTypes={canDeleteSavedObjectTypes}
|
||||
canDelete={this.props.uiCapabilities.savedObjectsManagement.delete}
|
||||
onDelete={this.onDelete}
|
||||
goInspectObject={this.props.goInspectObject}
|
||||
pageIndex={page}
|
||||
|
|
|
@ -14,7 +14,6 @@ import { FeaturePrivilegeBuilder } from './feature_privilege_builder';
|
|||
import { FeaturePrivilegeManagementBuilder } from './management';
|
||||
import { FeaturePrivilegeNavlinkBuilder } from './navlink';
|
||||
import { FeaturePrivilegeSavedObjectBuilder } from './saved_object';
|
||||
import { FeaturePrivilegeSavedObjectsManagementBuilder } from './saved_objects_management';
|
||||
import { FeaturePrivilegeUIBuilder } from './ui';
|
||||
export { FeaturePrivilegeBuilder };
|
||||
|
||||
|
@ -26,7 +25,6 @@ export const featurePrivilegeBuilderFactory = (actions: Actions): FeaturePrivile
|
|||
new FeaturePrivilegeManagementBuilder(actions),
|
||||
new FeaturePrivilegeNavlinkBuilder(actions),
|
||||
new FeaturePrivilegeSavedObjectBuilder(actions),
|
||||
new FeaturePrivilegeSavedObjectsManagementBuilder(actions),
|
||||
new FeaturePrivilegeUIBuilder(actions),
|
||||
];
|
||||
|
||||
|
|
|
@ -1,33 +0,0 @@
|
|||
/*
|
||||
* 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 { flatten, uniq } from 'lodash';
|
||||
import {
|
||||
Feature,
|
||||
FeatureKibanaPrivileges,
|
||||
} from '../../../../../../xpack_main/server/lib/feature_registry/feature_registry';
|
||||
import { BaseFeaturePrivilegeBuilder } from './feature_privilege_builder';
|
||||
|
||||
export class FeaturePrivilegeSavedObjectsManagementBuilder extends BaseFeaturePrivilegeBuilder {
|
||||
public getActions(privilegeDefinition: FeatureKibanaPrivileges, feature: Feature): string[] {
|
||||
// TODO: Revisit if/when savedObjectsManagement UI Capabilities are refactored
|
||||
if (feature.id !== 'savedObjectsManagement') {
|
||||
return [];
|
||||
}
|
||||
return uniq([
|
||||
...flatten(
|
||||
privilegeDefinition.savedObject.all.map(type => [
|
||||
this.actions.ui.get('savedObjectsManagement', type, 'delete'),
|
||||
this.actions.ui.get('savedObjectsManagement', type, 'edit'),
|
||||
this.actions.ui.get('savedObjectsManagement', type, 'read'),
|
||||
])
|
||||
),
|
||||
...privilegeDefinition.savedObject.read.map(type =>
|
||||
this.actions.ui.get('savedObjectsManagement', type, 'read')
|
||||
),
|
||||
]);
|
||||
}
|
||||
}
|
|
@ -622,90 +622,6 @@ describe('features', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('savedObjectsManagement feature', () => {
|
||||
test(`saved objects privileges create 'savedObjectsManagement' actions`, () => {
|
||||
const features: Feature[] = [
|
||||
{
|
||||
id: 'savedObjectsManagement',
|
||||
name: 'Saved Objects Management',
|
||||
icon: 'arrowDown',
|
||||
app: [],
|
||||
catalogue: [],
|
||||
management: {},
|
||||
privileges: {
|
||||
all: {
|
||||
ui: [],
|
||||
savedObject: {
|
||||
all: ['all-savedObject-all-1'],
|
||||
read: ['all-savedObject-read-1'],
|
||||
},
|
||||
},
|
||||
read: {
|
||||
ui: [],
|
||||
savedObject: {
|
||||
all: ['read-savedObject-all-1'],
|
||||
read: ['read-savedObject-read-1'],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const mockXPackMainPlugin = {
|
||||
getFeatures: jest.fn().mockReturnValue(features),
|
||||
};
|
||||
|
||||
const privileges = privilegesFactory(actions, mockXPackMainPlugin as any);
|
||||
|
||||
const actual = privileges.get();
|
||||
expect(actual).toHaveProperty('features.savedObjectsManagement.all', [
|
||||
actions.login,
|
||||
actions.version,
|
||||
actions.savedObject.get('all-savedObject-all-1', 'bulk_get'),
|
||||
actions.savedObject.get('all-savedObject-all-1', 'get'),
|
||||
actions.savedObject.get('all-savedObject-all-1', 'find'),
|
||||
actions.savedObject.get('all-savedObject-all-1', 'create'),
|
||||
actions.savedObject.get('all-savedObject-all-1', 'bulk_create'),
|
||||
actions.savedObject.get('all-savedObject-all-1', 'update'),
|
||||
actions.savedObject.get('all-savedObject-all-1', 'delete'),
|
||||
|
||||
actions.savedObject.get('all-savedObject-read-1', 'bulk_get'),
|
||||
actions.savedObject.get('all-savedObject-read-1', 'get'),
|
||||
actions.savedObject.get('all-savedObject-read-1', 'find'),
|
||||
|
||||
actions.ui.get('savedObjectsManagement', 'all-savedObject-all-1', 'delete'),
|
||||
actions.ui.get('savedObjectsManagement', 'all-savedObject-all-1', 'edit'),
|
||||
actions.ui.get('savedObjectsManagement', 'all-savedObject-all-1', 'read'),
|
||||
|
||||
actions.ui.get('savedObjectsManagement', 'all-savedObject-read-1', 'read'),
|
||||
|
||||
actions.allHack,
|
||||
]);
|
||||
|
||||
expect(actual).toHaveProperty('features.savedObjectsManagement.read', [
|
||||
actions.login,
|
||||
actions.version,
|
||||
actions.savedObject.get('read-savedObject-all-1', 'bulk_get'),
|
||||
actions.savedObject.get('read-savedObject-all-1', 'get'),
|
||||
actions.savedObject.get('read-savedObject-all-1', 'find'),
|
||||
actions.savedObject.get('read-savedObject-all-1', 'create'),
|
||||
actions.savedObject.get('read-savedObject-all-1', 'bulk_create'),
|
||||
actions.savedObject.get('read-savedObject-all-1', 'update'),
|
||||
actions.savedObject.get('read-savedObject-all-1', 'delete'),
|
||||
|
||||
actions.savedObject.get('read-savedObject-read-1', 'bulk_get'),
|
||||
actions.savedObject.get('read-savedObject-read-1', 'get'),
|
||||
actions.savedObject.get('read-savedObject-read-1', 'find'),
|
||||
|
||||
actions.ui.get('savedObjectsManagement', 'read-savedObject-all-1', 'delete'),
|
||||
actions.ui.get('savedObjectsManagement', 'read-savedObject-all-1', 'edit'),
|
||||
actions.ui.get('savedObjectsManagement', 'read-savedObject-all-1', 'read'),
|
||||
|
||||
actions.ui.get('savedObjectsManagement', 'read-savedObject-read-1', 'read'),
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('reserved', () => {
|
||||
test('actions defined at the feature cascade to the privileges', () => {
|
||||
const features: Feature[] = [
|
||||
|
|
|
@ -60,21 +60,6 @@ function toggleDisabledFeatures(
|
|||
});
|
||||
});
|
||||
|
||||
// TODO: Revisit if/when savedObjectsManagement UI Capabilities are refactored
|
||||
if (feature.id === 'savedObjectsManagement') {
|
||||
const capability: Record<string, Record<string, boolean>> = uiCapabilities[
|
||||
feature.id
|
||||
] as Record<string, Record<string, boolean>>;
|
||||
|
||||
Object.keys(capability).forEach(savedObjectType => {
|
||||
Object.keys(capability[savedObjectType]).forEach(typeCapability => {
|
||||
capability[savedObjectType][typeCapability] = false;
|
||||
});
|
||||
});
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Disable "sub features" that match the disabled feature
|
||||
if (uiCapabilities.hasOwnProperty(feature.id)) {
|
||||
const capability = uiCapabilities[feature.id];
|
||||
|
|
|
@ -206,14 +206,14 @@ const buildKibanaFeatures = (savedObjectTypes: string[]) => {
|
|||
all: [...savedObjectTypes],
|
||||
read: [],
|
||||
},
|
||||
ui: [],
|
||||
ui: ['read', 'edit', 'delete'],
|
||||
},
|
||||
read: {
|
||||
savedObject: {
|
||||
all: [],
|
||||
read: [...savedObjectTypes],
|
||||
},
|
||||
ui: [],
|
||||
ui: ['read'],
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
@ -1,93 +0,0 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* eslint-disable max-classes-per-file */
|
||||
class SavedObjectsTypeUICapabilitiesGroup {
|
||||
public all = ['delete', 'edit', 'read'];
|
||||
public read = ['read'];
|
||||
public none = [] as string[];
|
||||
}
|
||||
const savedObjectsTypeUICapabilitiesGroup = new SavedObjectsTypeUICapabilitiesGroup();
|
||||
|
||||
interface OnlyParameters {
|
||||
all?: string | string[];
|
||||
read?: string | string[];
|
||||
}
|
||||
|
||||
const coerceToArray = <T>(itemOrItemsOrNil: T | T[] | undefined): T[] => {
|
||||
if (itemOrItemsOrNil == null) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return Array.isArray(itemOrItemsOrNil) ? itemOrItemsOrNil : [itemOrItemsOrNil];
|
||||
};
|
||||
|
||||
export class SavedObjectsManagementBuilder {
|
||||
private allSavedObjectTypes: string[];
|
||||
|
||||
constructor(spacesEnabled: boolean) {
|
||||
this.allSavedObjectTypes = [
|
||||
...(spacesEnabled ? ['space'] : []),
|
||||
'config',
|
||||
'telemetry',
|
||||
'graph-workspace',
|
||||
'ml-telemetry',
|
||||
'apm-telemetry',
|
||||
'map',
|
||||
'maps-telemetry',
|
||||
'canvas-workpad',
|
||||
'canvas-element',
|
||||
'infrastructure-ui-source',
|
||||
'upgrade-assistant-reindex-operation',
|
||||
'upgrade-assistant-telemetry',
|
||||
'index-pattern',
|
||||
'visualization',
|
||||
'search',
|
||||
'dashboard',
|
||||
'url',
|
||||
'server',
|
||||
'kql-telemetry',
|
||||
'timelion-sheet',
|
||||
'ui-metric',
|
||||
'sample-data-telemetry',
|
||||
'siem-ui-timeline',
|
||||
'siem-ui-timeline-note',
|
||||
'siem-ui-timeline-pinned-event',
|
||||
];
|
||||
}
|
||||
|
||||
public uiCapabilities(group: keyof SavedObjectsTypeUICapabilitiesGroup) {
|
||||
return savedObjectsTypeUICapabilitiesGroup.all.reduce(
|
||||
(acc2, uiCapability) => ({
|
||||
...acc2,
|
||||
[uiCapability]: savedObjectsTypeUICapabilitiesGroup[group].includes(uiCapability),
|
||||
}),
|
||||
{}
|
||||
);
|
||||
}
|
||||
|
||||
public build(parameters: OnlyParameters): Record<string, boolean> {
|
||||
const readTypes = coerceToArray(parameters.read);
|
||||
const allTypes = coerceToArray(parameters.all);
|
||||
return this.allSavedObjectTypes.reduce(
|
||||
(acc, savedObjectType) => ({
|
||||
...acc,
|
||||
[savedObjectType]: savedObjectsTypeUICapabilitiesGroup.all.reduce(
|
||||
(acc2, uiCapability) => ({
|
||||
...acc2,
|
||||
[uiCapability]:
|
||||
(readTypes.includes(savedObjectType) &&
|
||||
savedObjectsTypeUICapabilitiesGroup.read.includes(uiCapability)) ||
|
||||
(allTypes.includes(savedObjectType) &&
|
||||
savedObjectsTypeUICapabilitiesGroup.all.includes(uiCapability)),
|
||||
}),
|
||||
{}
|
||||
),
|
||||
}),
|
||||
{}
|
||||
);
|
||||
}
|
||||
}
|
|
@ -73,6 +73,5 @@ export default function uiCapabilitiesTests({
|
|||
loadTestFile(require.resolve('./catalogue'));
|
||||
loadTestFile(require.resolve('./foo'));
|
||||
loadTestFile(require.resolve('./nav_links'));
|
||||
loadTestFile(require.resolve('./saved_objects_management'));
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,91 +0,0 @@
|
|||
/*
|
||||
* 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 '@kbn/expect';
|
||||
import { mapValues } from 'lodash';
|
||||
import { KibanaFunctionalTestDefaultProviders } from '../../../types/providers';
|
||||
import { SavedObjectsManagementBuilder } from '../../common/saved_objects_management_builder';
|
||||
import {
|
||||
UICapabilitiesService,
|
||||
GetUICapabilitiesFailureReason,
|
||||
} from '../../common/services/ui_capabilities';
|
||||
import { UserAtSpaceScenarios } from '../scenarios';
|
||||
|
||||
const savedObjectsManagementBuilder = new SavedObjectsManagementBuilder(true);
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default function savedObjectsManagementTests({
|
||||
getService,
|
||||
}: KibanaFunctionalTestDefaultProviders) {
|
||||
const uiCapabilitiesService: UICapabilitiesService = getService('uiCapabilities');
|
||||
|
||||
describe('savedObjectsManagement', () => {
|
||||
UserAtSpaceScenarios.forEach(scenario => {
|
||||
it(`${scenario.id}`, async () => {
|
||||
const { user, space } = scenario;
|
||||
|
||||
const uiCapabilities = await uiCapabilitiesService.get({
|
||||
credentials: { username: user.username, password: user.password },
|
||||
spaceId: space.id,
|
||||
});
|
||||
switch (scenario.id) {
|
||||
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('savedObjectsManagement');
|
||||
const expected = mapValues(uiCapabilities.value!.savedObjectsManagement, () =>
|
||||
savedObjectsManagementBuilder.uiCapabilities('all')
|
||||
);
|
||||
expect(uiCapabilities.value!.savedObjectsManagement).to.eql(expected);
|
||||
break;
|
||||
|
||||
case 'dual_privileges_read at everything_space':
|
||||
case 'global_read at everything_space':
|
||||
case 'everything_space_read at everything_space':
|
||||
expect(uiCapabilities.success).to.be(true);
|
||||
expect(uiCapabilities.value).to.have.property('savedObjectsManagement');
|
||||
const readExpected = mapValues(uiCapabilities.value!.savedObjectsManagement, () =>
|
||||
savedObjectsManagementBuilder.uiCapabilities('read')
|
||||
);
|
||||
expect(uiCapabilities.value!.savedObjectsManagement).to.eql(readExpected);
|
||||
break;
|
||||
|
||||
case 'superuser at nothing_space':
|
||||
case 'nothing_space_all at nothing_space':
|
||||
case 'nothing_space_read 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':
|
||||
expect(uiCapabilities.success).to.be(true);
|
||||
expect(uiCapabilities.value).to.have.property('savedObjectsManagement');
|
||||
const noneExpected = mapValues(uiCapabilities.value!.savedObjectsManagement, () =>
|
||||
savedObjectsManagementBuilder.uiCapabilities('none')
|
||||
);
|
||||
expect(uiCapabilities.value!.savedObjectsManagement).to.eql(noneExpected);
|
||||
break;
|
||||
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);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
|
@ -55,6 +55,5 @@ export default function uiCapabilitesTests({
|
|||
loadTestFile(require.resolve('./catalogue'));
|
||||
loadTestFile(require.resolve('./foo'));
|
||||
loadTestFile(require.resolve('./nav_links'));
|
||||
loadTestFile(require.resolve('./saved_objects_management'));
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,78 +0,0 @@
|
|||
/*
|
||||
* 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 '@kbn/expect';
|
||||
import { mapValues } from 'lodash';
|
||||
import { KibanaFunctionalTestDefaultProviders } from '../../../types/providers';
|
||||
import { SavedObjectsManagementBuilder } from '../../common/saved_objects_management_builder';
|
||||
import {
|
||||
UICapabilitiesService,
|
||||
GetUICapabilitiesFailureReason,
|
||||
} from '../../common/services/ui_capabilities';
|
||||
import { UserScenarios } from '../scenarios';
|
||||
|
||||
const savedObjectsManagementBuilder = new SavedObjectsManagementBuilder(false);
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default function savedObjectsManagementTests({
|
||||
getService,
|
||||
}: KibanaFunctionalTestDefaultProviders) {
|
||||
const uiCapabilitiesService: UICapabilitiesService = getService('uiCapabilities');
|
||||
|
||||
describe('savedObjectsManagement', () => {
|
||||
UserScenarios.forEach(scenario => {
|
||||
it(`${scenario.fullName}`, async () => {
|
||||
const uiCapabilities = await uiCapabilitiesService.get({
|
||||
credentials: {
|
||||
username: scenario.username,
|
||||
password: scenario.password,
|
||||
},
|
||||
});
|
||||
switch (scenario.username) {
|
||||
case 'superuser':
|
||||
case 'all':
|
||||
case 'dual_privileges_all':
|
||||
expect(uiCapabilities.success).to.be(true);
|
||||
expect(uiCapabilities.value).to.have.property('savedObjectsManagement');
|
||||
const expected = mapValues(uiCapabilities.value!.savedObjectsManagement, () =>
|
||||
savedObjectsManagementBuilder.uiCapabilities('all')
|
||||
);
|
||||
expect(uiCapabilities.value!.savedObjectsManagement).to.eql(expected);
|
||||
break;
|
||||
case 'read':
|
||||
case 'dual_privileges_read':
|
||||
expect(uiCapabilities.success).to.be(true);
|
||||
expect(uiCapabilities.value).to.have.property('savedObjectsManagement');
|
||||
const expectedRead = mapValues(uiCapabilities.value!.savedObjectsManagement, () =>
|
||||
savedObjectsManagementBuilder.uiCapabilities('read')
|
||||
);
|
||||
expect(uiCapabilities.value!.savedObjectsManagement).to.eql(expectedRead);
|
||||
break;
|
||||
case 'foo_all':
|
||||
case 'foo_read':
|
||||
expect(uiCapabilities.success).to.be(true);
|
||||
expect(uiCapabilities.value).to.have.property('savedObjectsManagement');
|
||||
expect(uiCapabilities.value!.savedObjectsManagement).to.eql(
|
||||
savedObjectsManagementBuilder.build({
|
||||
all: [],
|
||||
read: [],
|
||||
})
|
||||
);
|
||||
break;
|
||||
case 'no_kibana_privileges':
|
||||
// these users have no access to any ui capabilities
|
||||
case 'legacy_all':
|
||||
case 'no_kibana_privileges':
|
||||
expect(uiCapabilities.success).to.be(false);
|
||||
expect(uiCapabilities.failureReason).to.be(GetUICapabilitiesFailureReason.NotFound);
|
||||
break;
|
||||
default:
|
||||
throw new UnreachableError(scenario);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
|
@ -41,6 +41,5 @@ export default function uiCapabilitesTests({
|
|||
loadTestFile(require.resolve('./catalogue'));
|
||||
loadTestFile(require.resolve('./foo'));
|
||||
loadTestFile(require.resolve('./nav_links'));
|
||||
loadTestFile(require.resolve('./saved_objects_management'));
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,54 +0,0 @@
|
|||
/*
|
||||
* 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 '@kbn/expect';
|
||||
import { mapValues } from 'lodash';
|
||||
import { KibanaFunctionalTestDefaultProviders } from '../../../types/providers';
|
||||
import { SavedObjectsManagementBuilder } from '../../common/saved_objects_management_builder';
|
||||
import { UICapabilitiesService } from '../../common/services/ui_capabilities';
|
||||
import { SpaceScenarios } from '../scenarios';
|
||||
|
||||
const savedObjectsManagementBuilder = new SavedObjectsManagementBuilder(true);
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default function savedObjectsManagementTests({
|
||||
getService,
|
||||
}: KibanaFunctionalTestDefaultProviders) {
|
||||
const uiCapabilitiesService: UICapabilitiesService = getService('uiCapabilities');
|
||||
|
||||
describe('savedObjectsManagement', () => {
|
||||
SpaceScenarios.forEach(scenario => {
|
||||
it(`${scenario.name}`, async () => {
|
||||
switch (scenario.id) {
|
||||
case 'nothing_space':
|
||||
// Saved Objects Managment is not available when everything is disabled.
|
||||
const nothingSpaceCapabilities = await uiCapabilitiesService.get({
|
||||
spaceId: scenario.id,
|
||||
});
|
||||
expect(nothingSpaceCapabilities.success).to.be(true);
|
||||
expect(nothingSpaceCapabilities.value).to.have.property('savedObjectsManagement');
|
||||
const nothingSpaceExpected = mapValues(
|
||||
nothingSpaceCapabilities.value!.savedObjectsManagement,
|
||||
() => savedObjectsManagementBuilder.uiCapabilities('none')
|
||||
);
|
||||
expect(nothingSpaceCapabilities.value!.savedObjectsManagement).to.eql(
|
||||
nothingSpaceExpected
|
||||
);
|
||||
break;
|
||||
default:
|
||||
// Otherwise it's available without restriction
|
||||
const uiCapabilities = await uiCapabilitiesService.get({ spaceId: scenario.id });
|
||||
expect(uiCapabilities.success).to.be(true);
|
||||
expect(uiCapabilities.value).to.have.property('savedObjectsManagement');
|
||||
const expected = mapValues(uiCapabilities.value!.savedObjectsManagement, () =>
|
||||
savedObjectsManagementBuilder.uiCapabilities('all')
|
||||
);
|
||||
expect(uiCapabilities.value!.savedObjectsManagement).to.eql(expected);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
Loading…
Reference in a new issue