[Runtime field editor] Fix preview error when not enough privileges (#115070)

This commit is contained in:
Sébastien Loix 2021-10-15 16:06:59 +01:00 committed by GitHub
parent 8b70071623
commit d009e54199
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 48 additions and 17 deletions

View file

@ -366,6 +366,7 @@ describe('Field editor Preview panel', () => {
subTitle: 'First doc - subTitle',
title: 'First doc - title',
},
documentId: '001',
index: 'testIndex',
script: {
source: 'echo("hello")',

View file

@ -335,6 +335,7 @@ export const FieldPreviewProvider: FunctionComponent = ({ children }) => {
document: params.document!,
context: `${params.type!}_field` as FieldPreviewContext,
script: params.script!,
documentId: currentDocId,
});
if (currentApiCall !== previewCount.current) {

View file

@ -16,11 +16,13 @@ export const initApi = (httpClient: HttpSetup) => {
context,
script,
document,
documentId,
}: {
index: string;
context: FieldPreviewContext;
script: { source: string } | null;
document: Record<string, any>;
documentId: string;
}) => {
return sendRequest<FieldPreviewResponse>(httpClient, {
path: `${API_BASE_PATH}/field_preview`,
@ -30,6 +32,7 @@ export const initApi = (httpClient: HttpSetup) => {
context,
script,
document,
documentId,
},
});
};

View file

@ -6,8 +6,8 @@
* Side Public License, v 1.
*/
import { estypes } from '@elastic/elasticsearch';
import { schema } from '@kbn/config-schema';
import { HttpResponsePayload } from 'kibana/server';
import { API_BASE_PATH } from '../../common/constants';
import { RouteDependencies } from '../types';
@ -26,6 +26,7 @@ const bodySchema = schema.object({
schema.literal('long_field'),
]),
document: schema.object({}, { unknowns: 'allow' }),
documentId: schema.string(),
});
export const registerFieldPreviewRoute = ({ router }: RouteDependencies): void => {
@ -39,30 +40,41 @@ export const registerFieldPreviewRoute = ({ router }: RouteDependencies): void =
async (ctx, req, res) => {
const { client } = ctx.core.elasticsearch;
const body = JSON.stringify({
script: req.body.script,
context: req.body.context,
context_setup: {
document: req.body.document,
index: req.body.index,
} as any,
});
const type = req.body.context.split('_field')[0] as estypes.MappingRuntimeFieldType;
const body = {
runtime_mappings: {
my_runtime_field: {
type,
script: req.body.script,
},
},
size: 1,
query: {
term: {
_id: req.body.documentId,
},
},
fields: ['my_runtime_field'],
};
try {
const response = await client.asCurrentUser.scriptsPainlessExecute({
// @ts-expect-error `ExecutePainlessScriptRequest.body` does not allow `string`
const response = await client.asCurrentUser.search({
index: req.body.index,
body,
});
const fieldValue = response.body.result as any[] as HttpResponsePayload;
const fieldValue = response.body.hits.hits[0]?.fields?.my_runtime_field ?? '';
return res.ok({ body: { values: fieldValue } });
} catch (error) {
} catch (error: any) {
// Assume invalid painless script was submitted
// Return 200 with error object
const handleCustomError = () => {
return res.ok({
body: { values: [], ...error.body },
body: {
values: [],
error: error.body.error.failed_shards[0]?.reason ?? {},
},
});
};

View file

@ -12,11 +12,14 @@ import { FtrProviderContext } from '../../ftr_provider_context';
import { API_BASE_PATH } from './constants';
const INDEX_NAME = 'api-integration-test-field-preview';
const DOC_ID = '1';
export default function ({ getService }: FtrProviderContext) {
const supertest = getService('supertest');
const es = getService('es');
const document = { foo: 1, bar: 'hello' };
const createIndex = async () => {
await es.indices.create({
index: INDEX_NAME,
@ -35,6 +38,15 @@ export default function ({ getService }: FtrProviderContext) {
});
};
const addDoc = async () => {
await es.index({
index: INDEX_NAME,
id: DOC_ID,
body: document,
refresh: 'wait_for',
});
};
const deleteIndex = async () => {
await es.indices.delete({
index: INDEX_NAME,
@ -42,12 +54,13 @@ export default function ({ getService }: FtrProviderContext) {
};
describe('Field preview', function () {
before(async () => await createIndex());
before(async () => {
await createIndex();
await addDoc();
});
after(async () => await deleteIndex());
describe('should return the script value', () => {
const document = { foo: 1, bar: 'hello' };
const tests = [
{
context: 'keyword_field',
@ -77,6 +90,7 @@ export default function ({ getService }: FtrProviderContext) {
const payload = {
script: test.script,
document,
documentId: DOC_ID,
context: test.context,
index: INDEX_NAME,
};