mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
This commit is contained in:
parent
d59d0c92ca
commit
1581512816
9 changed files with 91 additions and 16 deletions
|
@ -10,7 +10,7 @@ import { map, last } from 'lodash';
|
|||
|
||||
import { IndexPattern } from './data_view';
|
||||
|
||||
import { DuplicateField } from '../../../kibana_utils/common';
|
||||
import { CharacterNotAllowedInField, DuplicateField } from '../../../kibana_utils/common';
|
||||
|
||||
import { IndexPatternField } from '../fields';
|
||||
|
||||
|
@ -207,6 +207,14 @@ describe('IndexPattern', () => {
|
|||
expect(e).toBeInstanceOf(DuplicateField);
|
||||
}
|
||||
});
|
||||
|
||||
test('should not allow scripted field with * in name', async () => {
|
||||
try {
|
||||
await indexPattern.addScriptedField('test*123', "'new script'", 'string');
|
||||
} catch (e) {
|
||||
expect(e).toBeInstanceOf(CharacterNotAllowedInField);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('setFieldFormat and deleteFieldFormaat', () => {
|
||||
|
@ -267,6 +275,14 @@ describe('IndexPattern', () => {
|
|||
});
|
||||
expect(indexPattern.toSpec()!.fields!.new_field).toBeUndefined();
|
||||
});
|
||||
|
||||
test('should not allow runtime field with * in name', async () => {
|
||||
try {
|
||||
await indexPattern.addRuntimeField('test*123', runtime);
|
||||
} catch (e) {
|
||||
expect(e).toBeInstanceOf(CharacterNotAllowedInField);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('getFormatterForField', () => {
|
||||
|
|
|
@ -13,7 +13,7 @@ import { castEsToKbnFieldTypeName, ES_FIELD_TYPES, KBN_FIELD_TYPES } from '@kbn/
|
|||
import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
|
||||
import { FieldAttrs, FieldAttrSet, DataViewAttributes } from '..';
|
||||
import type { RuntimeField } from '../types';
|
||||
import { DuplicateField } from '../../../kibana_utils/common';
|
||||
import { CharacterNotAllowedInField, DuplicateField } from '../../../kibana_utils/common';
|
||||
|
||||
import { IIndexPattern, IFieldType } from '../../common';
|
||||
import { DataViewField, IIndexPatternFieldList, fieldList } from '../fields';
|
||||
|
@ -237,6 +237,10 @@ export class DataView implements IIndexPattern {
|
|||
const scriptedFields = this.getScriptedFields();
|
||||
const names = _.map(scriptedFields, 'name');
|
||||
|
||||
if (name.includes('*')) {
|
||||
throw new CharacterNotAllowedInField('*', name);
|
||||
}
|
||||
|
||||
if (_.includes(names, name)) {
|
||||
throw new DuplicateField(name);
|
||||
}
|
||||
|
@ -358,6 +362,11 @@ export class DataView implements IIndexPattern {
|
|||
*/
|
||||
addRuntimeField(name: string, runtimeField: RuntimeField) {
|
||||
const existingField = this.getFieldByName(name);
|
||||
|
||||
if (name.includes('*')) {
|
||||
throw new CharacterNotAllowedInField('*', name);
|
||||
}
|
||||
|
||||
if (existingField) {
|
||||
existingField.runtimeField = runtimeField;
|
||||
} else {
|
||||
|
|
|
@ -11,7 +11,7 @@ import { fieldValidators } from '../../shared_imports';
|
|||
|
||||
import { RUNTIME_FIELD_OPTIONS } from './constants';
|
||||
|
||||
const { emptyField, numberGreaterThanField } = fieldValidators;
|
||||
const { containsCharsField, emptyField, numberGreaterThanField } = fieldValidators;
|
||||
|
||||
export const schema = {
|
||||
name: {
|
||||
|
@ -29,6 +29,17 @@ export const schema = {
|
|||
)
|
||||
),
|
||||
},
|
||||
{
|
||||
validator: containsCharsField({
|
||||
message: i18n.translate(
|
||||
'indexPatternFieldEditor.editor.form.validations.starCharacterNotAllowedValidationErrorMessage',
|
||||
{
|
||||
defaultMessage: 'The field cannot have * in the name.',
|
||||
}
|
||||
),
|
||||
chars: '*',
|
||||
}),
|
||||
},
|
||||
],
|
||||
},
|
||||
type: {
|
||||
|
|
|
@ -546,7 +546,7 @@ exports[`FieldEditor should show conflict field warning 1`] = `
|
|||
onClose={[Function]}
|
||||
/>
|
||||
<eui-form-row
|
||||
error={null}
|
||||
error={false}
|
||||
helpText={
|
||||
<span>
|
||||
<eui-icon
|
||||
|
@ -1175,7 +1175,7 @@ exports[`FieldEditor should show multiple type field warning with a table contai
|
|||
onClose={[Function]}
|
||||
/>
|
||||
<eui-form-row
|
||||
error={null}
|
||||
error={false}
|
||||
helpText={
|
||||
<span>
|
||||
<eui-icon
|
||||
|
|
|
@ -292,4 +292,25 @@ describe('FieldEditor', () => {
|
|||
component.update();
|
||||
expect(component).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should not allow field to have * in the name', async () => {
|
||||
const testField = {
|
||||
...field,
|
||||
name: 'test-field',
|
||||
};
|
||||
const component = createComponentWithContext<FieldEdiorProps>(
|
||||
FieldEditor,
|
||||
{
|
||||
indexPattern,
|
||||
spec: testField as unknown as IndexPatternField,
|
||||
services,
|
||||
},
|
||||
mockContext
|
||||
);
|
||||
|
||||
await new Promise((resolve) => process.nextTick(resolve));
|
||||
(component.instance() as FieldEditor).onFieldChange('name', 'test*123');
|
||||
component.update();
|
||||
expect(component.html().includes('The field cannot have * in the name.')).toBe(true);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -267,7 +267,8 @@ export class FieldEditor extends PureComponent<FieldEdiorProps, FieldEditorState
|
|||
|
||||
renderName() {
|
||||
const { isCreating, spec } = this.state;
|
||||
const isInvalid = !spec.name || !spec.name.trim();
|
||||
const starCheck = spec?.name?.includes('*');
|
||||
const isInvalid = !spec.name || !spec.name.trim() || starCheck;
|
||||
|
||||
return isCreating ? (
|
||||
<EuiFormRow
|
||||
|
@ -298,11 +299,17 @@ export class FieldEditor extends PureComponent<FieldEdiorProps, FieldEditorState
|
|||
}
|
||||
isInvalid={isInvalid}
|
||||
error={
|
||||
isInvalid
|
||||
? i18n.translate('indexPatternManagement.nameErrorMessage', {
|
||||
isInvalid &&
|
||||
(starCheck
|
||||
? i18n.translate(
|
||||
'indexPatternManagement.starCharacterNotAllowedValidationErrorMessage',
|
||||
{
|
||||
defaultMessage: 'The field cannot have * in the name.',
|
||||
}
|
||||
)
|
||||
: i18n.translate('indexPatternManagement.nameErrorMessage', {
|
||||
defaultMessage: 'Name is required',
|
||||
})
|
||||
: null
|
||||
}))
|
||||
}
|
||||
>
|
||||
<EuiFieldText
|
||||
|
|
|
@ -26,6 +26,17 @@ export class DuplicateField extends KbnError {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* when a user is attempting to create a field with disallowed character in the name, like *
|
||||
* @param {String} character - the character not allowed in name
|
||||
* @param {String} name - the field name
|
||||
*/
|
||||
export class CharacterNotAllowedInField extends KbnError {
|
||||
constructor(character: string, name: string) {
|
||||
super(`The field "${name}" cannot have "${character}" in the name`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A saved object was not found
|
||||
*/
|
||||
|
|
|
@ -132,7 +132,7 @@ describe('Runtime field editor', () => {
|
|||
const defaultValue: RuntimeField = {
|
||||
name: 'myRuntimeField',
|
||||
type: 'boolean',
|
||||
script: { source: 'emit("hello"' },
|
||||
script: { source: 'emit("hello")' },
|
||||
};
|
||||
|
||||
testBed = setup({
|
||||
|
|
|
@ -98,7 +98,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
await PageObjects.lens.goToTimeRange();
|
||||
await PageObjects.lens.switchToVisualization('lnsDatatable');
|
||||
await PageObjects.lens.clickAddField();
|
||||
await fieldEditor.setName(`*' "'`);
|
||||
await fieldEditor.setName(`ab' "'`);
|
||||
await fieldEditor.enableValue();
|
||||
await fieldEditor.typeScript("emit('abc')");
|
||||
await fieldEditor.save();
|
||||
|
@ -106,21 +106,21 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
await PageObjects.lens.configureDimension({
|
||||
dimension: 'lnsDatatable_metrics > lns-empty-dimension',
|
||||
operation: 'unique_count',
|
||||
field: `*`,
|
||||
field: `ab`,
|
||||
keepOpen: true,
|
||||
});
|
||||
|
||||
await PageObjects.lens.switchToFormula();
|
||||
await PageObjects.lens.expectFormulaText(`unique_count('*\\' "\\'')`);
|
||||
await PageObjects.lens.expectFormulaText(`unique_count('ab\\' "\\'')`);
|
||||
|
||||
await PageObjects.lens.typeFormula('unique_count(');
|
||||
const input = await find.activeElement();
|
||||
await input.type('*');
|
||||
await input.type('ab');
|
||||
await input.pressKeys(browser.keys.ENTER);
|
||||
|
||||
await PageObjects.common.sleep(100);
|
||||
|
||||
await PageObjects.lens.expectFormulaText(`unique_count('*\\' "\\'')`);
|
||||
await PageObjects.lens.expectFormulaText(`unique_count('ab\\' "\\'')`);
|
||||
});
|
||||
|
||||
it('should persist a broken formula on close', async () => {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue