[data views] fix capabilities check (#122503)

* fix permissions check

* typescript fix

* update jest test

* Update workspace_panel.tsx

* Update workspace_panel.test.tsx

* first swing at functional test

* refactor permissions code

* type improvement

* make client side specific service

* cleanup

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Matthew Kime 2022-01-20 06:59:10 -06:00 committed by GitHub
parent ab5741ff78
commit 946be82994
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 64 additions and 35 deletions

View file

@ -98,7 +98,7 @@ export const EmptyPrompts: FC<Props> = ({ allSources, onCancel, children, loadSo
<EmptyIndexPatternPrompt
goToCreate={() => setGoToForm(true)}
indexPatternsIntroUrl={docLinks.links.indexPatterns.introduction}
canSaveIndexPattern={application.capabilities.indexPatterns.save as boolean}
canSaveIndexPattern={dataViews.getCanSaveSync()}
/>
<PromptFooter onCancel={onCancel} />
</>

View file

@ -60,9 +60,7 @@ export class DataViewEditorPlugin
* @returns boolean
*/
userPermissions: {
editDataView: () => {
return application.capabilities.management.kibana.indexPatterns;
},
editDataView: () => dataViews.getCanSaveSync(),
},
};
}

View file

@ -30,10 +30,7 @@ export class IndexPatternFieldEditorPlugin
public start(core: CoreStart, plugins: StartPlugins) {
const { fieldFormatEditors } = this.formatEditorService.start();
const {
application: { capabilities },
http,
} = core;
const { http } = core;
const { data, usageCollection, dataViews, fieldFormats } = plugins;
const openDeleteModal = getFieldDeleteModalOpener({
core,
@ -53,9 +50,7 @@ export class IndexPatternFieldEditorPlugin
}),
openDeleteModal,
userPermissions: {
editIndexPattern: () => {
return capabilities.management.kibana.indexPatterns;
},
editIndexPattern: () => dataViews.getCanSaveSync(),
},
DeleteRuntimeFieldProvider: getDeleteFieldProvider(openDeleteModal),
};

View file

@ -6,7 +6,7 @@
* Side Public License, v 1.
*/
import { DataView, DataViewField, DataViewsService } from 'src/plugins/data_views/public';
import { DataView, DataViewField, DataViewsContract } from 'src/plugins/data_views/public';
import { FieldFormatInstanceType } from 'src/plugins/field_formats/common';
import { findTestSubject } from '@elastic/eui/lib/test';
@ -95,7 +95,7 @@ const field = {
const services = {
redirectAway: () => {},
saveIndexPattern: async () => {},
indexPatternService: {} as DataViewsService,
indexPatternService: {} as DataViewsContract,
};
describe('FieldEditor', () => {
@ -202,7 +202,7 @@ describe('FieldEditor', () => {
redirectAway: () => {},
indexPatternService: {
updateSavedObject: jest.fn(() => Promise.resolve()),
} as unknown as DataViewsService,
} as unknown as DataViewsContract,
},
},
mockContext

View file

@ -43,7 +43,7 @@ export async function mountManagementSection(
{ data, dataViewFieldEditor, dataViewEditor, dataViews, fieldFormats },
indexPatternManagementStart,
] = await getStartServices();
const canSave = Boolean(application.capabilities.indexPatterns.save);
const canSave = dataViews.getCanSaveSync();
if (!canSave) {
chrome.setBadge(readOnlyBadge);

View file

@ -59,7 +59,7 @@ export interface DataViewListItem {
export type IndexPatternListItem = DataViewListItem;
interface IndexPatternsServiceDeps {
export interface DataViewsServiceDeps {
uiSettings: UiSettingsCommon;
savedObjectsClient: SavedObjectsClientCommon;
apiClient: IDataViewsApiClient;
@ -79,7 +79,7 @@ export class DataViewsService {
private onNotification: OnNotification;
private onError: OnError;
private dataViewCache: ReturnType<typeof createDataViewCache>;
private getCanSave: () => Promise<boolean>;
public getCanSave: () => Promise<boolean>;
/**
* @deprecated Use `getDefaultDataView` instead (when loading data view) and handle
@ -96,7 +96,7 @@ export class DataViewsService {
onError,
onRedirectNoIndexPattern = () => {},
getCanSave = () => Promise.resolve(false),
}: IndexPatternsServiceDeps) {
}: DataViewsServiceDeps) {
this.apiClient = apiClient;
this.config = uiSettings;
this.savedObjectsClient = savedObjectsClient;

View file

@ -0,0 +1,24 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import { DataViewsService } from '.';
import { DataViewsServiceDeps } from '../common/data_views/data_views';
interface DataViewsServicePublicDeps extends DataViewsServiceDeps {
getCanSaveSync: () => boolean;
}
export class DataViewsServicePublic extends DataViewsService {
public getCanSaveSync: () => boolean;
constructor(deps: DataViewsServicePublicDeps) {
super(deps);
this.getCanSaveSync = deps.getCanSaveSync;
}
}

View file

@ -18,7 +18,7 @@ export { onRedirectNoIndexPattern } from './data_views';
export type { IIndexPatternFieldList, TypeMeta } from '../common';
export { IndexPatternField, DataViewField, DataViewType, META_FIELDS } from '../common';
export type { IndexPatternsContract, DataViewsContract } from './data_views';
export type { IndexPatternsContract } from './data_views';
export type { DataViewListItem } from './data_views';
export {
IndexPatternsService,
@ -40,7 +40,11 @@ export function plugin() {
return new DataViewsPublicPlugin();
}
export type { DataViewsPublicPluginSetup, DataViewsPublicPluginStart } from './types';
export type {
DataViewsPublicPluginSetup,
DataViewsPublicPluginStart,
DataViewsContract,
} from './types';
// Export plugin after all other imports
export type { DataViewsPublicPlugin as DataViewsPlugin };

View file

@ -16,13 +16,14 @@ import {
} from './types';
import {
DataViewsService,
onRedirectNoIndexPattern,
DataViewsApiClient,
UiSettingsPublicToCommon,
SavedObjectsClientPublicToCommon,
} from '.';
import { DataViewsServicePublic } from './data_views_service_public';
export class DataViewsPublicPlugin
implements
Plugin<
@ -47,7 +48,7 @@ export class DataViewsPublicPlugin
): DataViewsPublicPluginStart {
const { uiSettings, http, notifications, savedObjects, theme, overlays, application } = core;
return new DataViewsService({
return new DataViewsServicePublic({
uiSettings: new UiSettingsPublicToCommon(uiSettings),
savedObjectsClient: new SavedObjectsClientPublicToCommon(savedObjects.client),
apiClient: new DataViewsApiClient(http),
@ -63,6 +64,7 @@ export class DataViewsPublicPlugin
theme
),
getCanSave: () => Promise.resolve(application.capabilities.indexPatterns.save === true),
getCanSaveSync: () => application.capabilities.indexPatterns.save === true,
});
}

View file

@ -26,7 +26,13 @@ export interface DataViewsPublicStartDependencies {
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface DataViewsPublicPluginSetup {}
export interface DataViewsServicePublic extends DataViewsService {
getCanSaveSync: () => boolean;
}
export type DataViewsContract = PublicMethodsOf<DataViewsServicePublic>;
/**
* Data plugin public Start contract
* Data views plugin public Start contract
*/
export type DataViewsPublicPluginStart = PublicMethodsOf<DataViewsService>;
export type DataViewsPublicPluginStart = PublicMethodsOf<DataViewsServicePublic>;

View file

@ -8,7 +8,7 @@
import { UsageCollectionSetup } from 'src/plugins/usage_collection/server';
import { StartServicesAccessor } from 'src/core/server';
import { DataViewsService } from '../common';
import { DataViewsContract } from '../common';
import { SavedObjectsClient } from '../../../core/server';
import { DataViewsServerPluginStartDependencies, DataViewsServerPluginStart } from './types';
@ -57,7 +57,7 @@ export const updateMax = (currentMax: number | undefined, newVal: number): numbe
}
};
export async function getIndexPatternTelemetry(indexPatterns: DataViewsService) {
export async function getIndexPatternTelemetry(indexPatterns: DataViewsContract) {
const ids = await indexPatterns.getIds();
const countSummaryDefaults: CountSummary = {

View file

@ -6,7 +6,7 @@
* Side Public License, v 1.
*/
import { DataViewsService } from '../../../data/common';
import { DataViewsContract } from '../../../data_views/public';
import { indexPatternMock } from './index_pattern';
export const indexPatternsMock = {
@ -21,4 +21,4 @@ export const indexPatternsMock = {
}
},
updateSavedObject: jest.fn(),
} as unknown as jest.Mocked<DataViewsService>;
} as unknown as jest.Mocked<DataViewsContract>;

View file

@ -7,7 +7,7 @@
*/
import { Capabilities } from 'kibana/public';
import { DataView, DataViewsService } from '../../../data/common';
import { DataView, DataViewsContract } from '../../../data_views/public';
import { popularizeField } from './popularize_field';
const capabilities = {
@ -20,7 +20,7 @@ describe('Popularize field', () => {
test('returns undefined if index pattern lacks id', async () => {
const indexPattern = {} as unknown as DataView;
const fieldName = '@timestamp';
const dataViewsService = {} as unknown as DataViewsService;
const dataViewsService = {} as unknown as DataViewsContract;
const result = await popularizeField(indexPattern, fieldName, dataViewsService, capabilities);
expect(result).toBeUndefined();
});
@ -32,7 +32,7 @@ describe('Popularize field', () => {
},
} as unknown as DataView;
const fieldName = '@timestamp';
const dataViewsService = {} as unknown as DataViewsService;
const dataViewsService = {} as unknown as DataViewsContract;
const result = await popularizeField(indexPattern, fieldName, dataViewsService, capabilities);
expect(result).toBeUndefined();
});
@ -50,7 +50,7 @@ describe('Popularize field', () => {
const fieldName = '@timestamp';
const dataViewsService = {
updateSavedObject: async () => {},
} as unknown as DataViewsService;
} as unknown as DataViewsContract;
const result = await popularizeField(indexPattern, fieldName, dataViewsService, capabilities);
expect(result).toBeUndefined();
expect(field.count).toEqual(1);
@ -71,7 +71,7 @@ describe('Popularize field', () => {
updateSavedObject: async () => {
throw new Error('unknown error');
},
} as unknown as DataViewsService;
} as unknown as DataViewsContract;
const result = await popularizeField(indexPattern, fieldName, dataViewsService, capabilities);
expect(result).toBeUndefined();
});
@ -89,7 +89,7 @@ describe('Popularize field', () => {
const fieldName = '@timestamp';
const dataViewsService = {
updateSavedObject: jest.fn(),
} as unknown as DataViewsService;
} as unknown as DataViewsContract;
const result = await popularizeField(indexPattern, fieldName, dataViewsService, {
indexPatterns: { save: false },
} as unknown as Capabilities);

View file

@ -7,7 +7,7 @@
*/
import { useMemo } from 'react';
import type { DataView, DataViewsContract } from 'src/plugins/data/common';
import type { DataView, DataViewsContract } from 'src/plugins/data_views/public';
import { Capabilities, IUiSettingsClient } from 'kibana/public';
import {