mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[SIEM][Lists] Removes plugin dependencies, adds more unit tests, fixes more TypeScript types
* Removes plugin dependencies for better integration outside of Requests such as alerting * Adds more unit tests * Fixes more TypeScript types to be more normalized * Makes this work with the user 'elastic' if security is turned off - [x] [Unit or functional tests](https://github.com/elastic/kibana/blob/master/CONTRIBUTING.md#cross-browser-compatibility) were updated or added to match the most common scenarios
This commit is contained in:
parent
fba5128bd8
commit
bcda1096e1
59 changed files with 649 additions and 397 deletions
46
x-pack/plugins/lists/server/get_space_id.test.ts
Normal file
46
x-pack/plugins/lists/server/get_space_id.test.ts
Normal file
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* 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 { httpServerMock } from 'src/core/server/mocks';
|
||||
import { KibanaRequest } from 'src/core/server';
|
||||
|
||||
import { spacesServiceMock } from '../../spaces/server/spaces_service/spaces_service.mock';
|
||||
|
||||
import { getSpaceId } from './get_space_id';
|
||||
|
||||
describe('get_space_id', () => {
|
||||
let request = KibanaRequest.from(httpServerMock.createRawRequest({}));
|
||||
beforeEach(() => {
|
||||
request = KibanaRequest.from(httpServerMock.createRawRequest({}));
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
test('it returns "default" as the space id given a space id of "default"', () => {
|
||||
const spaces = spacesServiceMock.createSetupContract();
|
||||
const space = getSpaceId({ request, spaces });
|
||||
expect(space).toEqual('default');
|
||||
});
|
||||
|
||||
test('it returns "another-space" as the space id given a space id of "another-space"', () => {
|
||||
const spaces = spacesServiceMock.createSetupContract('another-space');
|
||||
const space = getSpaceId({ request, spaces });
|
||||
expect(space).toEqual('another-space');
|
||||
});
|
||||
|
||||
test('it returns "default" as the space id given a space id of undefined', () => {
|
||||
const space = getSpaceId({ request, spaces: undefined });
|
||||
expect(space).toEqual('default');
|
||||
});
|
||||
|
||||
test('it returns "default" as the space id given a space id of null', () => {
|
||||
const space = getSpaceId({ request, spaces: null });
|
||||
expect(space).toEqual('default');
|
||||
});
|
||||
});
|
|
@ -6,9 +6,9 @@
|
|||
|
||||
import { KibanaRequest } from 'kibana/server';
|
||||
|
||||
import { SpacesServiceSetup } from '../../../../spaces/server';
|
||||
import { SpacesServiceSetup } from '../../spaces/server';
|
||||
|
||||
export const getSpace = ({
|
||||
export const getSpaceId = ({
|
||||
spaces,
|
||||
request,
|
||||
}: {
|
67
x-pack/plugins/lists/server/get_user.test.ts
Normal file
67
x-pack/plugins/lists/server/get_user.test.ts
Normal file
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* 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 { httpServerMock } from 'src/core/server/mocks';
|
||||
import { KibanaRequest } from 'src/core/server';
|
||||
|
||||
import { securityMock } from '../../security/server/mocks';
|
||||
import { SecurityPluginSetup } from '../../security/server';
|
||||
|
||||
import { getUser } from './get_user';
|
||||
|
||||
describe('get_user', () => {
|
||||
let request = KibanaRequest.from(httpServerMock.createRawRequest({}));
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
request = KibanaRequest.from(httpServerMock.createRawRequest({}));
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
test('it returns "bob" as the user given a security request with "bob"', () => {
|
||||
const security: SecurityPluginSetup = securityMock.createSetup();
|
||||
security.authc.getCurrentUser = jest.fn().mockReturnValue({ username: 'bob' });
|
||||
const user = getUser({ request, security });
|
||||
expect(user).toEqual('bob');
|
||||
});
|
||||
|
||||
test('it returns "alice" as the user given a security request with "alice"', () => {
|
||||
const security: SecurityPluginSetup = securityMock.createSetup();
|
||||
security.authc.getCurrentUser = jest.fn().mockReturnValue({ username: 'alice' });
|
||||
const user = getUser({ request, security });
|
||||
expect(user).toEqual('alice');
|
||||
});
|
||||
|
||||
test('it returns "elastic" as the user given null as the current user', () => {
|
||||
const security: SecurityPluginSetup = securityMock.createSetup();
|
||||
security.authc.getCurrentUser = jest.fn().mockReturnValue(null);
|
||||
const user = getUser({ request, security });
|
||||
expect(user).toEqual('elastic');
|
||||
});
|
||||
|
||||
test('it returns "elastic" as the user given undefined as the current user', () => {
|
||||
const security: SecurityPluginSetup = securityMock.createSetup();
|
||||
security.authc.getCurrentUser = jest.fn().mockReturnValue(undefined);
|
||||
const user = getUser({ request, security });
|
||||
expect(user).toEqual('elastic');
|
||||
});
|
||||
|
||||
test('it returns "elastic" as the user given undefined as the plugin', () => {
|
||||
const security: SecurityPluginSetup = securityMock.createSetup();
|
||||
security.authc.getCurrentUser = jest.fn().mockReturnValue(undefined);
|
||||
const user = getUser({ request, security: undefined });
|
||||
expect(user).toEqual('elastic');
|
||||
});
|
||||
|
||||
test('it returns "elastic" as the user given null as the plugin', () => {
|
||||
const security: SecurityPluginSetup = securityMock.createSetup();
|
||||
security.authc.getCurrentUser = jest.fn().mockReturnValue(undefined);
|
||||
const user = getUser({ request, security: null });
|
||||
expect(user).toEqual('elastic');
|
||||
});
|
||||
});
|
|
@ -6,17 +6,21 @@
|
|||
|
||||
import { KibanaRequest } from 'kibana/server';
|
||||
|
||||
import { SecurityPluginSetup } from '../../../../security/server';
|
||||
import { SecurityPluginSetup } from '../../security/server';
|
||||
|
||||
interface GetUserOptions {
|
||||
security: SecurityPluginSetup;
|
||||
export interface GetUserOptions {
|
||||
security: SecurityPluginSetup | null | undefined;
|
||||
request: KibanaRequest;
|
||||
}
|
||||
|
||||
export const getUser = ({ security, request }: GetUserOptions): string => {
|
||||
const authenticatedUser = security.authc.getCurrentUser(request);
|
||||
if (authenticatedUser != null) {
|
||||
return authenticatedUser.username;
|
||||
if (security != null) {
|
||||
const authenticatedUser = security.authc.getCurrentUser(request);
|
||||
if (authenticatedUser != null) {
|
||||
return authenticatedUser.username;
|
||||
} else {
|
||||
return 'elastic';
|
||||
}
|
||||
} else {
|
||||
return 'elastic';
|
||||
}
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
|
||||
import { first } from 'rxjs/operators';
|
||||
import { ElasticsearchServiceSetup, Logger, PluginInitializerContext } from 'kibana/server';
|
||||
import { Logger, PluginInitializerContext } from 'kibana/server';
|
||||
import { CoreSetup } from 'src/core/server';
|
||||
|
||||
import { SecurityPluginSetup } from '../../security/server';
|
||||
|
@ -16,12 +16,13 @@ import { initRoutes } from './routes/init_routes';
|
|||
import { ListClient } from './services/lists/client';
|
||||
import { ContextProvider, ContextProviderReturn, PluginsSetup } from './types';
|
||||
import { createConfig$ } from './create_config';
|
||||
import { getSpaceId } from './get_space_id';
|
||||
import { getUser } from './get_user';
|
||||
|
||||
export class ListPlugin {
|
||||
private readonly logger: Logger;
|
||||
private spaces: SpacesServiceSetup | undefined | null;
|
||||
private config: ConfigType | undefined | null;
|
||||
private elasticsearch: ElasticsearchServiceSetup | undefined | null;
|
||||
private security: SecurityPluginSetup | undefined | null;
|
||||
|
||||
constructor(private readonly initializerContext: PluginInitializerContext) {
|
||||
|
@ -38,7 +39,6 @@ export class ListPlugin {
|
|||
);
|
||||
this.spaces = plugins.spaces?.spacesService;
|
||||
this.config = config;
|
||||
this.elasticsearch = core.elasticsearch;
|
||||
this.security = plugins.security;
|
||||
|
||||
core.http.registerRouteHandlerContext('lists', this.createRouteHandlerContext());
|
||||
|
@ -56,28 +56,28 @@ export class ListPlugin {
|
|||
|
||||
private createRouteHandlerContext = (): ContextProvider => {
|
||||
return async (context, request): ContextProviderReturn => {
|
||||
const { spaces, config, security, elasticsearch } = this;
|
||||
const { spaces, config, security } = this;
|
||||
const {
|
||||
core: {
|
||||
elasticsearch: { dataClient },
|
||||
elasticsearch: {
|
||||
dataClient: { callAsCurrentUser },
|
||||
},
|
||||
},
|
||||
} = context;
|
||||
if (config == null) {
|
||||
throw new TypeError('Configuration is required for this plugin to operate');
|
||||
} else if (elasticsearch == null) {
|
||||
throw new TypeError('Elastic Search is required for this plugin to operate');
|
||||
} else if (security == null) {
|
||||
// TODO: This might be null, test authentication being turned off.
|
||||
throw new TypeError('Security plugin is required for this plugin to operate');
|
||||
} else {
|
||||
const spaceId = getSpaceId({ request, spaces });
|
||||
const user = getUser({ request, security });
|
||||
return {
|
||||
getListClient: (): ListClient =>
|
||||
new ListClient({
|
||||
callCluster: callAsCurrentUser,
|
||||
config,
|
||||
dataClient,
|
||||
request,
|
||||
security,
|
||||
spaces,
|
||||
spaceId,
|
||||
user,
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { TestReadable } from '../mocks/test_readable';
|
||||
import { TestReadable } from '../mocks';
|
||||
|
||||
import { BufferLines } from './buffer_lines';
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ describe('crete_list_item', () => {
|
|||
expect(listItem).toEqual(expected);
|
||||
});
|
||||
|
||||
test('It calls "callAsCurrentUser" with body, index, and listIndex', async () => {
|
||||
test('It calls "callCluster" with body, index, and listIndex', async () => {
|
||||
const options = getCreateListItemOptionsMock();
|
||||
await createListItem(options);
|
||||
const body = getIndexESListItemMock();
|
||||
|
@ -40,7 +40,7 @@ describe('crete_list_item', () => {
|
|||
id: LIST_ITEM_ID,
|
||||
index: LIST_ITEM_INDEX,
|
||||
};
|
||||
expect(options.dataClient.callAsCurrentUser).toBeCalledWith('index', expected);
|
||||
expect(options.callCluster).toBeCalledWith('index', expected);
|
||||
});
|
||||
|
||||
test('It returns an auto-generated id if id is sent in undefined', async () => {
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
import uuid from 'uuid';
|
||||
import { CreateDocumentResponse } from 'elasticsearch';
|
||||
import { APICaller } from 'kibana/server';
|
||||
|
||||
import {
|
||||
IdOrUndefined,
|
||||
|
@ -14,7 +15,6 @@ import {
|
|||
MetaOrUndefined,
|
||||
Type,
|
||||
} from '../../../common/schemas';
|
||||
import { DataClient } from '../../types';
|
||||
import { transformListItemToElasticQuery } from '../utils';
|
||||
|
||||
export interface CreateListItemOptions {
|
||||
|
@ -22,7 +22,7 @@ export interface CreateListItemOptions {
|
|||
listId: string;
|
||||
type: Type;
|
||||
value: string;
|
||||
dataClient: DataClient;
|
||||
callCluster: APICaller;
|
||||
listItemIndex: string;
|
||||
user: string;
|
||||
meta: MetaOrUndefined;
|
||||
|
@ -35,7 +35,7 @@ export const createListItem = async ({
|
|||
listId,
|
||||
type,
|
||||
value,
|
||||
dataClient,
|
||||
callCluster,
|
||||
listItemIndex,
|
||||
user,
|
||||
meta,
|
||||
|
@ -58,7 +58,7 @@ export const createListItem = async ({
|
|||
...transformListItemToElasticQuery({ type, value }),
|
||||
};
|
||||
|
||||
const response: CreateDocumentResponse = await dataClient.callAsCurrentUser('index', {
|
||||
const response: CreateDocumentResponse = await callCluster('index', {
|
||||
body,
|
||||
id,
|
||||
index: listItemIndex,
|
||||
|
|
|
@ -24,13 +24,13 @@ describe('crete_list_item_bulk', () => {
|
|||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
test('It calls "callAsCurrentUser" with body, index, and the bulk items', async () => {
|
||||
test('It calls "callCluster" with body, index, and the bulk items', async () => {
|
||||
const options = getCreateListItemBulkOptionsMock();
|
||||
await createListItemsBulk(options);
|
||||
const firstRecord: IndexEsListItemSchema = getIndexESListItemMock();
|
||||
const secondRecord: IndexEsListItemSchema = getIndexESListItemMock(VALUE_2);
|
||||
[firstRecord.tie_breaker_id, secondRecord.tie_breaker_id] = TIE_BREAKERS;
|
||||
expect(options.dataClient.callAsCurrentUser).toBeCalledWith('bulk', {
|
||||
expect(options.callCluster).toBeCalledWith('bulk', {
|
||||
body: [
|
||||
{ create: { _index: LIST_ITEM_INDEX } },
|
||||
firstRecord,
|
||||
|
@ -44,6 +44,6 @@ describe('crete_list_item_bulk', () => {
|
|||
test('It should not call the dataClient when the values are empty', async () => {
|
||||
const options = getCreateListItemBulkOptionsMock();
|
||||
options.value = [];
|
||||
expect(options.dataClient.callAsCurrentUser).not.toBeCalled();
|
||||
expect(options.callCluster).not.toBeCalled();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -5,9 +5,9 @@
|
|||
*/
|
||||
|
||||
import uuid from 'uuid';
|
||||
import { APICaller } from 'kibana/server';
|
||||
|
||||
import { transformListItemToElasticQuery } from '../utils';
|
||||
import { DataClient } from '../../types';
|
||||
import {
|
||||
CreateEsBulkTypeSchema,
|
||||
IndexEsListItemSchema,
|
||||
|
@ -19,7 +19,7 @@ export interface CreateListItemsBulkOptions {
|
|||
listId: string;
|
||||
type: Type;
|
||||
value: string[];
|
||||
dataClient: DataClient;
|
||||
callCluster: APICaller;
|
||||
listItemIndex: string;
|
||||
user: string;
|
||||
meta: MetaOrUndefined;
|
||||
|
@ -31,7 +31,7 @@ export const createListItemsBulk = async ({
|
|||
listId,
|
||||
type,
|
||||
value,
|
||||
dataClient,
|
||||
callCluster,
|
||||
listItemIndex,
|
||||
user,
|
||||
meta,
|
||||
|
@ -63,7 +63,7 @@ export const createListItemsBulk = async ({
|
|||
[]
|
||||
);
|
||||
|
||||
await dataClient.callAsCurrentUser('bulk', {
|
||||
await callCluster('bulk', {
|
||||
body,
|
||||
index: listItemIndex,
|
||||
});
|
||||
|
|
|
@ -4,8 +4,12 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { LIST_ITEM_ID, LIST_ITEM_INDEX, getListItemResponseMock } from '../mocks';
|
||||
import { getDeleteListItemOptionsMock } from '../mocks/get_delete_list_item_options_mock';
|
||||
import {
|
||||
LIST_ITEM_ID,
|
||||
LIST_ITEM_INDEX,
|
||||
getDeleteListItemOptionsMock,
|
||||
getListItemResponseMock,
|
||||
} from '../mocks';
|
||||
|
||||
import { getListItem } from './get_list_item';
|
||||
import { deleteListItem } from './delete_list_item';
|
||||
|
@ -37,6 +41,7 @@ describe('delete_list_item', () => {
|
|||
const deletedListItem = await deleteListItem(options);
|
||||
expect(deletedListItem).toEqual(listItem);
|
||||
});
|
||||
|
||||
test('Delete calls "delete" if a list item is returned from "getListItem"', async () => {
|
||||
const listItem = getListItemResponseMock();
|
||||
((getListItem as unknown) as jest.Mock).mockResolvedValueOnce(listItem);
|
||||
|
@ -46,6 +51,6 @@ describe('delete_list_item', () => {
|
|||
id: LIST_ITEM_ID,
|
||||
index: LIST_ITEM_INDEX,
|
||||
};
|
||||
expect(options.dataClient.callAsCurrentUser).toBeCalledWith('delete', deleteQuery);
|
||||
expect(options.callCluster).toBeCalledWith('delete', deleteQuery);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -4,27 +4,28 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { APICaller } from 'kibana/server';
|
||||
|
||||
import { Id, ListItemSchema } from '../../../common/schemas';
|
||||
import { DataClient } from '../../types';
|
||||
|
||||
import { getListItem } from '.';
|
||||
|
||||
export interface DeleteListItemOptions {
|
||||
id: Id;
|
||||
dataClient: DataClient;
|
||||
callCluster: APICaller;
|
||||
listItemIndex: string;
|
||||
}
|
||||
|
||||
export const deleteListItem = async ({
|
||||
id,
|
||||
dataClient,
|
||||
callCluster,
|
||||
listItemIndex,
|
||||
}: DeleteListItemOptions): Promise<ListItemSchema | null> => {
|
||||
const listItem = await getListItem({ dataClient, id, listItemIndex });
|
||||
const listItem = await getListItem({ callCluster, id, listItemIndex });
|
||||
if (listItem == null) {
|
||||
return null;
|
||||
} else {
|
||||
await dataClient.callAsCurrentUser('delete', {
|
||||
await callCluster('delete', {
|
||||
id,
|
||||
index: listItemIndex,
|
||||
});
|
||||
|
|
|
@ -52,6 +52,6 @@ describe('delete_list_item_by_value', () => {
|
|||
},
|
||||
index: '.items',
|
||||
};
|
||||
expect(options.dataClient.callAsCurrentUser).toBeCalledWith('deleteByQuery', deleteByQuery);
|
||||
expect(options.callCluster).toBeCalledWith('deleteByQuery', deleteByQuery);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -4,9 +4,10 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { APICaller } from 'kibana/server';
|
||||
|
||||
import { ListItemArraySchema, Type } from '../../../common/schemas';
|
||||
import { getQueryFilterFromTypeValue } from '../utils';
|
||||
import { DataClient } from '../../types';
|
||||
|
||||
import { getListItemByValues } from './get_list_item_by_values';
|
||||
|
||||
|
@ -14,7 +15,7 @@ export interface DeleteListItemByValueOptions {
|
|||
listId: string;
|
||||
type: Type;
|
||||
value: string;
|
||||
dataClient: DataClient;
|
||||
callCluster: APICaller;
|
||||
listItemIndex: string;
|
||||
}
|
||||
|
||||
|
@ -22,11 +23,11 @@ export const deleteListItemByValue = async ({
|
|||
listId,
|
||||
value,
|
||||
type,
|
||||
dataClient,
|
||||
callCluster,
|
||||
listItemIndex,
|
||||
}: DeleteListItemByValueOptions): Promise<ListItemArraySchema> => {
|
||||
const listItems = await getListItemByValues({
|
||||
dataClient,
|
||||
callCluster,
|
||||
listId,
|
||||
listItemIndex,
|
||||
type,
|
||||
|
@ -38,7 +39,7 @@ export const deleteListItemByValue = async ({
|
|||
type,
|
||||
value: values,
|
||||
});
|
||||
await dataClient.callAsCurrentUser('deleteByQuery', {
|
||||
await callCluster('deleteByQuery', {
|
||||
body: {
|
||||
query: {
|
||||
bool: {
|
||||
|
|
|
@ -4,8 +4,13 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { LIST_ID, LIST_INDEX, getDataClientMock, getListItemResponseMock } from '../mocks';
|
||||
import { getSearchListItemMock } from '../mocks/get_search_list_item_mock';
|
||||
import {
|
||||
LIST_ID,
|
||||
LIST_INDEX,
|
||||
getCallClusterMock,
|
||||
getListItemResponseMock,
|
||||
getSearchListItemMock,
|
||||
} from '../mocks';
|
||||
|
||||
import { getListItem } from './get_list_item';
|
||||
|
||||
|
@ -20,8 +25,8 @@ describe('get_list_item', () => {
|
|||
|
||||
test('it returns a list item as expected if the list item is found', async () => {
|
||||
const data = getSearchListItemMock();
|
||||
const dataClient = getDataClientMock(data);
|
||||
const list = await getListItem({ dataClient, id: LIST_ID, listItemIndex: LIST_INDEX });
|
||||
const callCluster = getCallClusterMock(data);
|
||||
const list = await getListItem({ callCluster, id: LIST_ID, listItemIndex: LIST_INDEX });
|
||||
const expected = getListItemResponseMock();
|
||||
expect(list).toEqual(expected);
|
||||
});
|
||||
|
@ -29,8 +34,8 @@ describe('get_list_item', () => {
|
|||
test('it returns null if the search is empty', async () => {
|
||||
const data = getSearchListItemMock();
|
||||
data.hits.hits = [];
|
||||
const dataClient = getDataClientMock(data);
|
||||
const list = await getListItem({ dataClient, id: LIST_ID, listItemIndex: LIST_INDEX });
|
||||
const callCluster = getCallClusterMock(data);
|
||||
const list = await getListItem({ callCluster, id: LIST_ID, listItemIndex: LIST_INDEX });
|
||||
expect(list).toEqual(null);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -5,36 +5,33 @@
|
|||
*/
|
||||
|
||||
import { SearchResponse } from 'elasticsearch';
|
||||
import { APICaller } from 'kibana/server';
|
||||
|
||||
import { Id, ListItemSchema, SearchEsListItemSchema } from '../../../common/schemas';
|
||||
import { DataClient } from '../../types';
|
||||
import { deriveTypeFromItem, transformElasticToListItem } from '../utils';
|
||||
|
||||
interface GetListItemOptions {
|
||||
id: Id;
|
||||
dataClient: DataClient;
|
||||
callCluster: APICaller;
|
||||
listItemIndex: string;
|
||||
}
|
||||
|
||||
export const getListItem = async ({
|
||||
id,
|
||||
dataClient,
|
||||
callCluster,
|
||||
listItemIndex,
|
||||
}: GetListItemOptions): Promise<ListItemSchema | null> => {
|
||||
const listItemES: SearchResponse<SearchEsListItemSchema> = await dataClient.callAsCurrentUser(
|
||||
'search',
|
||||
{
|
||||
body: {
|
||||
query: {
|
||||
term: {
|
||||
_id: id,
|
||||
},
|
||||
const listItemES: SearchResponse<SearchEsListItemSchema> = await callCluster('search', {
|
||||
body: {
|
||||
query: {
|
||||
term: {
|
||||
_id: id,
|
||||
},
|
||||
},
|
||||
ignoreUnavailable: true,
|
||||
index: listItemIndex,
|
||||
}
|
||||
);
|
||||
},
|
||||
ignoreUnavailable: true,
|
||||
index: listItemIndex,
|
||||
});
|
||||
|
||||
if (listItemES.hits.hits.length) {
|
||||
const type = deriveTypeFromItem({ item: listItemES.hits.hits[0]._source });
|
||||
|
|
|
@ -4,14 +4,15 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { APICaller } from 'kibana/server';
|
||||
|
||||
import { ListItemArraySchema, Type } from '../../../common/schemas';
|
||||
import { DataClient } from '../../types';
|
||||
|
||||
import { getListItemByValues } from '.';
|
||||
|
||||
export interface GetListItemByValueOptions {
|
||||
listId: string;
|
||||
dataClient: DataClient;
|
||||
callCluster: APICaller;
|
||||
listItemIndex: string;
|
||||
type: Type;
|
||||
value: string;
|
||||
|
@ -19,13 +20,13 @@ export interface GetListItemByValueOptions {
|
|||
|
||||
export const getListItemByValue = async ({
|
||||
listId,
|
||||
dataClient,
|
||||
callCluster,
|
||||
listItemIndex,
|
||||
type,
|
||||
value,
|
||||
}: GetListItemByValueOptions): Promise<ListItemArraySchema> =>
|
||||
getListItemByValues({
|
||||
dataClient,
|
||||
callCluster,
|
||||
listId,
|
||||
listItemIndex,
|
||||
type,
|
||||
|
|
|
@ -4,8 +4,15 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { LIST_ID, LIST_ITEM_INDEX, TYPE, VALUE, VALUE_2, getDataClientMock } from '../mocks';
|
||||
import { getSearchListItemMock } from '../mocks/get_search_list_item_mock';
|
||||
import {
|
||||
LIST_ID,
|
||||
LIST_ITEM_INDEX,
|
||||
TYPE,
|
||||
VALUE,
|
||||
VALUE_2,
|
||||
getCallClusterMock,
|
||||
getSearchListItemMock,
|
||||
} from '../mocks';
|
||||
|
||||
import { getListItemByValues } from './get_list_item_by_values';
|
||||
|
||||
|
@ -21,27 +28,29 @@ describe('get_list_item_by_values', () => {
|
|||
test('Returns a an empty array if the ES query is also empty', async () => {
|
||||
const data = getSearchListItemMock();
|
||||
data.hits.hits = [];
|
||||
const dataClient = getDataClientMock(data);
|
||||
const callCluster = getCallClusterMock(data);
|
||||
const listItem = await getListItemByValues({
|
||||
dataClient,
|
||||
callCluster,
|
||||
listId: LIST_ID,
|
||||
listItemIndex: LIST_ITEM_INDEX,
|
||||
type: TYPE,
|
||||
value: [VALUE, VALUE_2],
|
||||
});
|
||||
|
||||
expect(listItem).toEqual([]);
|
||||
});
|
||||
|
||||
test('Returns transformed list item if the data exists within ES', async () => {
|
||||
const data = getSearchListItemMock();
|
||||
const dataClient = getDataClientMock(data);
|
||||
const callCluster = getCallClusterMock(data);
|
||||
const listItem = await getListItemByValues({
|
||||
dataClient,
|
||||
callCluster,
|
||||
listId: LIST_ID,
|
||||
listItemIndex: LIST_ITEM_INDEX,
|
||||
type: TYPE,
|
||||
value: [VALUE, VALUE_2],
|
||||
});
|
||||
|
||||
expect(listItem).toEqual([
|
||||
{
|
||||
created_at: '2020-04-20T15:25:31.830Z',
|
||||
|
|
|
@ -5,14 +5,14 @@
|
|||
*/
|
||||
|
||||
import { SearchResponse } from 'elasticsearch';
|
||||
import { APICaller } from 'kibana/server';
|
||||
|
||||
import { ListItemArraySchema, SearchEsListItemSchema, Type } from '../../../common/schemas';
|
||||
import { DataClient } from '../../types';
|
||||
import { getQueryFilterFromTypeValue, transformElasticToListItem } from '../utils';
|
||||
|
||||
export interface GetListItemByValuesOptions {
|
||||
listId: string;
|
||||
dataClient: DataClient;
|
||||
callCluster: APICaller;
|
||||
listItemIndex: string;
|
||||
type: Type;
|
||||
value: string[];
|
||||
|
@ -20,25 +20,22 @@ export interface GetListItemByValuesOptions {
|
|||
|
||||
export const getListItemByValues = async ({
|
||||
listId,
|
||||
dataClient,
|
||||
callCluster,
|
||||
listItemIndex,
|
||||
type,
|
||||
value,
|
||||
}: GetListItemByValuesOptions): Promise<ListItemArraySchema> => {
|
||||
const response: SearchResponse<SearchEsListItemSchema> = await dataClient.callAsCurrentUser(
|
||||
'search',
|
||||
{
|
||||
body: {
|
||||
query: {
|
||||
bool: {
|
||||
filter: getQueryFilterFromTypeValue({ listId, type, value }),
|
||||
},
|
||||
const response: SearchResponse<SearchEsListItemSchema> = await callCluster('search', {
|
||||
body: {
|
||||
query: {
|
||||
bool: {
|
||||
filter: getQueryFilterFromTypeValue({ listId, type, value }),
|
||||
},
|
||||
},
|
||||
ignoreUnavailable: true,
|
||||
index: listItemIndex,
|
||||
size: value.length, // This has a limit on the number which is 10k
|
||||
}
|
||||
);
|
||||
},
|
||||
ignoreUnavailable: true,
|
||||
index: listItemIndex,
|
||||
size: value.length, // This has a limit on the number which is 10k
|
||||
});
|
||||
return transformElasticToListItem({ response, type });
|
||||
};
|
||||
|
|
|
@ -4,17 +4,8 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { httpServerMock } from 'src/core/server/mocks';
|
||||
import { KibanaRequest } from 'src/core/server';
|
||||
|
||||
import { getSpace } from '../utils';
|
||||
|
||||
import { getListItemIndex } from './get_list_item_index';
|
||||
|
||||
jest.mock('../utils', () => ({
|
||||
getSpace: jest.fn(),
|
||||
}));
|
||||
|
||||
describe('get_list_item_index', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
|
@ -25,13 +16,9 @@ describe('get_list_item_index', () => {
|
|||
});
|
||||
|
||||
test('Returns the list item index when there is a space', async () => {
|
||||
((getSpace as unknown) as jest.Mock).mockReturnValueOnce('test-space');
|
||||
const rawRequest = httpServerMock.createRawRequest({});
|
||||
const request = KibanaRequest.from(rawRequest);
|
||||
const listIndex = getListItemIndex({
|
||||
listsItemsIndexName: 'lists-items-index',
|
||||
request,
|
||||
spaces: undefined,
|
||||
spaceId: 'test-space',
|
||||
});
|
||||
expect(listIndex).toEqual('lists-items-index-test-space');
|
||||
});
|
||||
|
|
|
@ -4,19 +4,12 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { KibanaRequest } from 'kibana/server';
|
||||
|
||||
import { SpacesServiceSetup } from '../../../../spaces/server';
|
||||
import { getSpace } from '../utils';
|
||||
|
||||
interface GetListItemIndexOptions {
|
||||
spaces: SpacesServiceSetup | undefined | null;
|
||||
request: KibanaRequest;
|
||||
export interface GetListItemIndexOptions {
|
||||
spaceId: string;
|
||||
listsItemsIndexName: string;
|
||||
}
|
||||
|
||||
export const getListItemIndex = ({
|
||||
spaces,
|
||||
request,
|
||||
spaceId,
|
||||
listsItemsIndexName,
|
||||
}: GetListItemIndexOptions): string => `${listsItemsIndexName}-${getSpace({ request, spaces })}`;
|
||||
}: GetListItemIndexOptions): string => `${listsItemsIndexName}-${spaceId}`;
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
|
||||
import { CreateDocumentResponse } from 'elasticsearch';
|
||||
import { APICaller } from 'kibana/server';
|
||||
|
||||
import {
|
||||
Id,
|
||||
|
@ -13,14 +14,13 @@ import {
|
|||
UpdateEsListItemSchema,
|
||||
} from '../../../common/schemas';
|
||||
import { transformListItemToElasticQuery } from '../utils';
|
||||
import { DataClient } from '../../types';
|
||||
|
||||
import { getListItem } from './get_list_item';
|
||||
|
||||
export interface UpdateListItemOptions {
|
||||
id: Id;
|
||||
value: string | null | undefined;
|
||||
dataClient: DataClient;
|
||||
callCluster: APICaller;
|
||||
listItemIndex: string;
|
||||
user: string;
|
||||
meta: MetaOrUndefined;
|
||||
|
@ -30,14 +30,14 @@ export interface UpdateListItemOptions {
|
|||
export const updateListItem = async ({
|
||||
id,
|
||||
value,
|
||||
dataClient,
|
||||
callCluster,
|
||||
listItemIndex,
|
||||
user,
|
||||
meta,
|
||||
dateNow,
|
||||
}: UpdateListItemOptions): Promise<ListItemSchema | null> => {
|
||||
const updatedAt = dateNow ?? new Date().toISOString();
|
||||
const listItem = await getListItem({ dataClient, id, listItemIndex });
|
||||
const listItem = await getListItem({ callCluster, id, listItemIndex });
|
||||
if (listItem == null) {
|
||||
return null;
|
||||
} else {
|
||||
|
@ -48,7 +48,7 @@ export const updateListItem = async ({
|
|||
...transformListItemToElasticQuery({ type: listItem.type, value: value ?? listItem.value }),
|
||||
};
|
||||
|
||||
const response: CreateDocumentResponse = await dataClient.callAsCurrentUser('update', {
|
||||
const response: CreateDocumentResponse = await callCluster('update', {
|
||||
body: {
|
||||
doc,
|
||||
},
|
||||
|
|
|
@ -6,8 +6,9 @@
|
|||
|
||||
import { Readable } from 'stream';
|
||||
|
||||
import { APICaller } from 'kibana/server';
|
||||
|
||||
import { MetaOrUndefined, Type } from '../../../common/schemas';
|
||||
import { DataClient } from '../../types';
|
||||
|
||||
import { BufferLines } from './buffer_lines';
|
||||
import { getListItemByValues } from './get_list_item_by_values';
|
||||
|
@ -16,7 +17,7 @@ import { createListItemsBulk } from './create_list_items_bulk';
|
|||
export interface ImportListItemsToStreamOptions {
|
||||
listId: string;
|
||||
stream: Readable;
|
||||
dataClient: DataClient;
|
||||
callCluster: APICaller;
|
||||
listItemIndex: string;
|
||||
type: Type;
|
||||
user: string;
|
||||
|
@ -26,7 +27,7 @@ export interface ImportListItemsToStreamOptions {
|
|||
export const importListItemsToStream = ({
|
||||
listId,
|
||||
stream,
|
||||
dataClient,
|
||||
callCluster,
|
||||
listItemIndex,
|
||||
type,
|
||||
user,
|
||||
|
@ -37,7 +38,7 @@ export const importListItemsToStream = ({
|
|||
readBuffer.on('lines', async (lines: string[]) => {
|
||||
await writeBufferToItems({
|
||||
buffer: lines,
|
||||
dataClient,
|
||||
callCluster,
|
||||
listId,
|
||||
listItemIndex,
|
||||
meta,
|
||||
|
@ -54,7 +55,7 @@ export const importListItemsToStream = ({
|
|||
|
||||
export interface WriteBufferToItemsOptions {
|
||||
listId: string;
|
||||
dataClient: DataClient;
|
||||
callCluster: APICaller;
|
||||
listItemIndex: string;
|
||||
buffer: string[];
|
||||
type: Type;
|
||||
|
@ -69,7 +70,7 @@ export interface LinesResult {
|
|||
|
||||
export const writeBufferToItems = async ({
|
||||
listId,
|
||||
dataClient,
|
||||
callCluster,
|
||||
listItemIndex,
|
||||
buffer,
|
||||
type,
|
||||
|
@ -77,7 +78,7 @@ export const writeBufferToItems = async ({
|
|||
meta,
|
||||
}: WriteBufferToItemsOptions): Promise<LinesResult> => {
|
||||
const items = await getListItemByValues({
|
||||
dataClient,
|
||||
callCluster,
|
||||
listId,
|
||||
listItemIndex,
|
||||
type,
|
||||
|
@ -89,7 +90,7 @@ export const writeBufferToItems = async ({
|
|||
const linesProcessed = duplicatesRemoved.length;
|
||||
const duplicatesFound = buffer.length - duplicatesRemoved.length;
|
||||
await createListItemsBulk({
|
||||
dataClient,
|
||||
callCluster,
|
||||
listId,
|
||||
listItemIndex,
|
||||
meta,
|
||||
|
|
|
@ -7,13 +7,13 @@
|
|||
import {
|
||||
LIST_ID,
|
||||
LIST_ITEM_INDEX,
|
||||
getDataClientMock,
|
||||
getCallClusterMock,
|
||||
getExportListItemsToStreamOptionsMock,
|
||||
getResponseOptionsMock,
|
||||
getSearchListItemMock,
|
||||
getWriteNextResponseOptions,
|
||||
getWriteResponseHitsToStreamOptionsMock,
|
||||
} from '../mocks';
|
||||
import { getSearchListItemMock } from '../mocks/get_search_list_item_mock';
|
||||
|
||||
import {
|
||||
exportListItemsToStream,
|
||||
|
@ -37,7 +37,7 @@ describe('write_list_items_to_stream', () => {
|
|||
const options = getExportListItemsToStreamOptionsMock();
|
||||
const firstResponse = getSearchListItemMock();
|
||||
firstResponse.hits.hits = [];
|
||||
options.dataClient = getDataClientMock(firstResponse);
|
||||
options.callCluster = getCallClusterMock(firstResponse);
|
||||
exportListItemsToStream(options);
|
||||
|
||||
let chunks: string[] = [];
|
||||
|
@ -71,7 +71,7 @@ describe('write_list_items_to_stream', () => {
|
|||
const firstResponse = getSearchListItemMock();
|
||||
const secondResponse = getSearchListItemMock();
|
||||
firstResponse.hits.hits = [...firstResponse.hits.hits, ...secondResponse.hits.hits];
|
||||
options.dataClient = getDataClientMock(firstResponse);
|
||||
options.callCluster = getCallClusterMock(firstResponse);
|
||||
exportListItemsToStream(options);
|
||||
|
||||
let chunks: string[] = [];
|
||||
|
@ -90,15 +90,14 @@ describe('write_list_items_to_stream', () => {
|
|||
|
||||
const firstResponse = getSearchListItemMock();
|
||||
firstResponse.hits.hits[0].sort = ['some-sort-value'];
|
||||
|
||||
const secondResponse = getSearchListItemMock();
|
||||
secondResponse.hits.hits[0]._source.ip = '255.255.255.255';
|
||||
|
||||
const jestCalls = jest.fn().mockResolvedValueOnce(firstResponse);
|
||||
jestCalls.mockResolvedValueOnce(secondResponse);
|
||||
|
||||
const dataClient = getDataClientMock(firstResponse);
|
||||
dataClient.callAsCurrentUser = jestCalls;
|
||||
options.dataClient = dataClient;
|
||||
options.callCluster = jest
|
||||
.fn()
|
||||
.mockResolvedValueOnce(firstResponse)
|
||||
.mockResolvedValueOnce(secondResponse);
|
||||
|
||||
exportListItemsToStream(options);
|
||||
|
||||
|
@ -125,7 +124,7 @@ describe('write_list_items_to_stream', () => {
|
|||
const listItem = getSearchListItemMock();
|
||||
listItem.hits.hits[0].sort = ['sort-value-1'];
|
||||
const options = getWriteNextResponseOptions();
|
||||
options.dataClient = getDataClientMock(listItem);
|
||||
options.callCluster = getCallClusterMock(listItem);
|
||||
const searchAfter = await writeNextResponse(options);
|
||||
expect(searchAfter).toEqual(['sort-value-1']);
|
||||
});
|
||||
|
@ -134,7 +133,7 @@ describe('write_list_items_to_stream', () => {
|
|||
const listItem = getSearchListItemMock();
|
||||
listItem.hits.hits = [];
|
||||
const options = getWriteNextResponseOptions();
|
||||
options.dataClient = getDataClientMock(listItem);
|
||||
options.callCluster = getCallClusterMock(listItem);
|
||||
const searchAfter = await writeNextResponse(options);
|
||||
expect(searchAfter).toEqual(undefined);
|
||||
});
|
||||
|
@ -187,7 +186,7 @@ describe('write_list_items_to_stream', () => {
|
|||
index: LIST_ITEM_INDEX,
|
||||
size: 100,
|
||||
};
|
||||
expect(options.dataClient.callAsCurrentUser).toBeCalledWith('search', expected);
|
||||
expect(options.callCluster).toBeCalledWith('search', expected);
|
||||
});
|
||||
|
||||
test('It returns a simple response with expected values and size changed', async () => {
|
||||
|
@ -205,7 +204,7 @@ describe('write_list_items_to_stream', () => {
|
|||
index: LIST_ITEM_INDEX,
|
||||
size: 33,
|
||||
};
|
||||
expect(options.dataClient.callAsCurrentUser).toBeCalledWith('search', expected);
|
||||
expect(options.callCluster).toBeCalledWith('search', expected);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -7,9 +7,9 @@
|
|||
import { PassThrough } from 'stream';
|
||||
|
||||
import { SearchResponse } from 'elasticsearch';
|
||||
import { APICaller } from 'kibana/server';
|
||||
|
||||
import { SearchEsListItemSchema } from '../../../common/schemas';
|
||||
import { DataClient } from '../../types';
|
||||
import { ErrorWithStatusCode } from '../../error_with_status_code';
|
||||
|
||||
/**
|
||||
|
@ -20,7 +20,7 @@ export const SIZE = 100;
|
|||
|
||||
export interface ExportListItemsToStreamOptions {
|
||||
listId: string;
|
||||
dataClient: DataClient;
|
||||
callCluster: APICaller;
|
||||
listItemIndex: string;
|
||||
stream: PassThrough;
|
||||
stringToAppend: string | null | undefined;
|
||||
|
@ -28,7 +28,7 @@ export interface ExportListItemsToStreamOptions {
|
|||
|
||||
export const exportListItemsToStream = ({
|
||||
listId,
|
||||
dataClient,
|
||||
callCluster,
|
||||
stream,
|
||||
listItemIndex,
|
||||
stringToAppend,
|
||||
|
@ -37,7 +37,7 @@ export const exportListItemsToStream = ({
|
|||
// and prevent the async await from bubbling up to the caller
|
||||
setTimeout(async () => {
|
||||
let searchAfter = await writeNextResponse({
|
||||
dataClient,
|
||||
callCluster,
|
||||
listId,
|
||||
listItemIndex,
|
||||
searchAfter: undefined,
|
||||
|
@ -46,7 +46,7 @@ export const exportListItemsToStream = ({
|
|||
});
|
||||
while (searchAfter != null) {
|
||||
searchAfter = await writeNextResponse({
|
||||
dataClient,
|
||||
callCluster,
|
||||
listId,
|
||||
listItemIndex,
|
||||
searchAfter,
|
||||
|
@ -60,7 +60,7 @@ export const exportListItemsToStream = ({
|
|||
|
||||
export interface WriteNextResponseOptions {
|
||||
listId: string;
|
||||
dataClient: DataClient;
|
||||
callCluster: APICaller;
|
||||
listItemIndex: string;
|
||||
stream: PassThrough;
|
||||
searchAfter: string[] | undefined;
|
||||
|
@ -69,14 +69,14 @@ export interface WriteNextResponseOptions {
|
|||
|
||||
export const writeNextResponse = async ({
|
||||
listId,
|
||||
dataClient,
|
||||
callCluster,
|
||||
stream,
|
||||
listItemIndex,
|
||||
searchAfter,
|
||||
stringToAppend,
|
||||
}: WriteNextResponseOptions): Promise<string[] | undefined> => {
|
||||
const response = await getResponse({
|
||||
dataClient,
|
||||
callCluster,
|
||||
listId,
|
||||
listItemIndex,
|
||||
searchAfter,
|
||||
|
@ -100,7 +100,7 @@ export const getSearchAfterFromResponse = <T>({
|
|||
: undefined;
|
||||
|
||||
export interface GetResponseOptions {
|
||||
dataClient: DataClient;
|
||||
callCluster: APICaller;
|
||||
listId: string;
|
||||
searchAfter: undefined | string[];
|
||||
listItemIndex: string;
|
||||
|
@ -108,13 +108,13 @@ export interface GetResponseOptions {
|
|||
}
|
||||
|
||||
export const getResponse = async ({
|
||||
dataClient,
|
||||
callCluster,
|
||||
searchAfter,
|
||||
listId,
|
||||
listItemIndex,
|
||||
size = SIZE,
|
||||
}: GetResponseOptions): Promise<SearchResponse<SearchEsListItemSchema>> => {
|
||||
return dataClient.callAsCurrentUser('search', {
|
||||
return callCluster('search', {
|
||||
body: {
|
||||
query: {
|
||||
term: {
|
||||
|
|
|
@ -4,10 +4,8 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { KibanaRequest, ScopedClusterClient } from 'src/core/server';
|
||||
import { APICaller } from 'kibana/server';
|
||||
|
||||
import { SecurityPluginSetup } from '../../../../security/server';
|
||||
import { SpacesServiceSetup } from '../../../../spaces/server';
|
||||
import { ListItemArraySchema, ListItemSchema, ListSchema } from '../../../common/schemas';
|
||||
import { ConfigType } from '../../config';
|
||||
import {
|
||||
|
@ -31,7 +29,6 @@ import {
|
|||
importListItemsToStream,
|
||||
updateListItem,
|
||||
} from '../../services/items';
|
||||
import { getUser } from '../../services/utils';
|
||||
import {
|
||||
createBootstrapIndex,
|
||||
deleteAllIndex,
|
||||
|
@ -64,47 +61,39 @@ import {
|
|||
UpdateListOptions,
|
||||
} from './client_types';
|
||||
|
||||
// TODO: Consider an interface and a factory
|
||||
export class ListClient {
|
||||
private readonly spaces: SpacesServiceSetup | undefined | null;
|
||||
private readonly spaceId: string;
|
||||
private readonly user: string;
|
||||
private readonly config: ConfigType;
|
||||
private readonly dataClient: Pick<
|
||||
ScopedClusterClient,
|
||||
'callAsCurrentUser' | 'callAsInternalUser'
|
||||
>;
|
||||
private readonly request: KibanaRequest;
|
||||
private readonly security: SecurityPluginSetup;
|
||||
private readonly callCluster: APICaller;
|
||||
|
||||
constructor({ request, spaces, config, dataClient, security }: ConstructorOptions) {
|
||||
this.request = request;
|
||||
this.spaces = spaces;
|
||||
constructor({ spaceId, user, config, callCluster }: ConstructorOptions) {
|
||||
this.spaceId = spaceId;
|
||||
this.user = user;
|
||||
this.config = config;
|
||||
this.dataClient = dataClient;
|
||||
this.security = security;
|
||||
this.callCluster = callCluster;
|
||||
}
|
||||
|
||||
public getListIndex = (): string => {
|
||||
const {
|
||||
spaces,
|
||||
request,
|
||||
spaceId,
|
||||
config: { listIndex: listsIndexName },
|
||||
} = this;
|
||||
return getListIndex({ listsIndexName, request, spaces });
|
||||
return getListIndex({ listsIndexName, spaceId });
|
||||
};
|
||||
|
||||
public getListItemIndex = (): string => {
|
||||
const {
|
||||
spaces,
|
||||
request,
|
||||
spaceId,
|
||||
config: { listItemIndex: listsItemsIndexName },
|
||||
} = this;
|
||||
return getListItemIndex({ listsItemsIndexName, request, spaces });
|
||||
return getListItemIndex({ listsItemsIndexName, spaceId });
|
||||
};
|
||||
|
||||
public getList = async ({ id }: GetListOptions): Promise<ListSchema | null> => {
|
||||
const { dataClient } = this;
|
||||
const { callCluster } = this;
|
||||
const listIndex = this.getListIndex();
|
||||
return getList({ dataClient, id, listIndex });
|
||||
return getList({ callCluster, id, listIndex });
|
||||
};
|
||||
|
||||
public createList = async ({
|
||||
|
@ -114,10 +103,9 @@ export class ListClient {
|
|||
type,
|
||||
meta,
|
||||
}: CreateListOptions): Promise<ListSchema> => {
|
||||
const { dataClient, security, request } = this;
|
||||
const { callCluster, user } = this;
|
||||
const listIndex = this.getListIndex();
|
||||
const user = getUser({ request, security });
|
||||
return createList({ dataClient, description, id, listIndex, meta, name, type, user });
|
||||
return createList({ callCluster, description, id, listIndex, meta, name, type, user });
|
||||
};
|
||||
|
||||
public createListIfItDoesNotExist = async ({
|
||||
|
@ -136,67 +124,51 @@ export class ListClient {
|
|||
};
|
||||
|
||||
public getListIndexExists = async (): Promise<boolean> => {
|
||||
const {
|
||||
dataClient: { callAsCurrentUser },
|
||||
} = this;
|
||||
const { callCluster } = this;
|
||||
const listIndex = this.getListIndex();
|
||||
return getIndexExists(callAsCurrentUser, listIndex);
|
||||
return getIndexExists(callCluster, listIndex);
|
||||
};
|
||||
|
||||
public getListItemIndexExists = async (): Promise<boolean> => {
|
||||
const {
|
||||
dataClient: { callAsCurrentUser },
|
||||
} = this;
|
||||
const { callCluster } = this;
|
||||
const listItemIndex = this.getListItemIndex();
|
||||
return getIndexExists(callAsCurrentUser, listItemIndex);
|
||||
return getIndexExists(callCluster, listItemIndex);
|
||||
};
|
||||
|
||||
public createListBootStrapIndex = async (): Promise<unknown> => {
|
||||
const {
|
||||
dataClient: { callAsCurrentUser },
|
||||
} = this;
|
||||
const { callCluster } = this;
|
||||
const listIndex = this.getListIndex();
|
||||
return createBootstrapIndex(callAsCurrentUser, listIndex);
|
||||
return createBootstrapIndex(callCluster, listIndex);
|
||||
};
|
||||
|
||||
public createListItemBootStrapIndex = async (): Promise<unknown> => {
|
||||
const {
|
||||
dataClient: { callAsCurrentUser },
|
||||
} = this;
|
||||
const { callCluster } = this;
|
||||
const listItemIndex = this.getListItemIndex();
|
||||
return createBootstrapIndex(callAsCurrentUser, listItemIndex);
|
||||
return createBootstrapIndex(callCluster, listItemIndex);
|
||||
};
|
||||
|
||||
public getListPolicyExists = async (): Promise<boolean> => {
|
||||
const {
|
||||
dataClient: { callAsCurrentUser },
|
||||
} = this;
|
||||
const { callCluster } = this;
|
||||
const listIndex = this.getListIndex();
|
||||
return getPolicyExists(callAsCurrentUser, listIndex);
|
||||
return getPolicyExists(callCluster, listIndex);
|
||||
};
|
||||
|
||||
public getListItemPolicyExists = async (): Promise<boolean> => {
|
||||
const {
|
||||
dataClient: { callAsCurrentUser },
|
||||
} = this;
|
||||
const { callCluster } = this;
|
||||
const listsItemIndex = this.getListItemIndex();
|
||||
return getPolicyExists(callAsCurrentUser, listsItemIndex);
|
||||
return getPolicyExists(callCluster, listsItemIndex);
|
||||
};
|
||||
|
||||
public getListTemplateExists = async (): Promise<boolean> => {
|
||||
const {
|
||||
dataClient: { callAsCurrentUser },
|
||||
} = this;
|
||||
const { callCluster } = this;
|
||||
const listIndex = this.getListIndex();
|
||||
return getTemplateExists(callAsCurrentUser, listIndex);
|
||||
return getTemplateExists(callCluster, listIndex);
|
||||
};
|
||||
|
||||
public getListItemTemplateExists = async (): Promise<boolean> => {
|
||||
const {
|
||||
dataClient: { callAsCurrentUser },
|
||||
} = this;
|
||||
const { callCluster } = this;
|
||||
const listItemIndex = this.getListItemIndex();
|
||||
return getTemplateExists(callAsCurrentUser, listItemIndex);
|
||||
return getTemplateExists(callCluster, listItemIndex);
|
||||
};
|
||||
|
||||
public getListTemplate = (): Record<string, unknown> => {
|
||||
|
@ -210,91 +182,71 @@ export class ListClient {
|
|||
};
|
||||
|
||||
public setListTemplate = async (): Promise<unknown> => {
|
||||
const {
|
||||
dataClient: { callAsCurrentUser },
|
||||
} = this;
|
||||
const { callCluster } = this;
|
||||
const template = this.getListTemplate();
|
||||
const listIndex = this.getListIndex();
|
||||
return setTemplate(callAsCurrentUser, listIndex, template);
|
||||
return setTemplate(callCluster, listIndex, template);
|
||||
};
|
||||
|
||||
public setListItemTemplate = async (): Promise<unknown> => {
|
||||
const {
|
||||
dataClient: { callAsCurrentUser },
|
||||
} = this;
|
||||
const { callCluster } = this;
|
||||
const template = this.getListItemTemplate();
|
||||
const listItemIndex = this.getListItemIndex();
|
||||
return setTemplate(callAsCurrentUser, listItemIndex, template);
|
||||
return setTemplate(callCluster, listItemIndex, template);
|
||||
};
|
||||
|
||||
public setListPolicy = async (): Promise<unknown> => {
|
||||
const {
|
||||
dataClient: { callAsCurrentUser },
|
||||
} = this;
|
||||
const { callCluster } = this;
|
||||
const listIndex = this.getListIndex();
|
||||
return setPolicy(callAsCurrentUser, listIndex, listPolicy);
|
||||
return setPolicy(callCluster, listIndex, listPolicy);
|
||||
};
|
||||
|
||||
public setListItemPolicy = async (): Promise<unknown> => {
|
||||
const {
|
||||
dataClient: { callAsCurrentUser },
|
||||
} = this;
|
||||
const { callCluster } = this;
|
||||
const listItemIndex = this.getListItemIndex();
|
||||
return setPolicy(callAsCurrentUser, listItemIndex, listsItemsPolicy);
|
||||
return setPolicy(callCluster, listItemIndex, listsItemsPolicy);
|
||||
};
|
||||
|
||||
public deleteListIndex = async (): Promise<boolean> => {
|
||||
const {
|
||||
dataClient: { callAsCurrentUser },
|
||||
} = this;
|
||||
const { callCluster } = this;
|
||||
const listIndex = this.getListIndex();
|
||||
return deleteAllIndex(callAsCurrentUser, `${listIndex}-*`);
|
||||
return deleteAllIndex(callCluster, `${listIndex}-*`);
|
||||
};
|
||||
|
||||
public deleteListItemIndex = async (): Promise<boolean> => {
|
||||
const {
|
||||
dataClient: { callAsCurrentUser },
|
||||
} = this;
|
||||
const { callCluster } = this;
|
||||
const listItemIndex = this.getListItemIndex();
|
||||
return deleteAllIndex(callAsCurrentUser, `${listItemIndex}-*`);
|
||||
return deleteAllIndex(callCluster, `${listItemIndex}-*`);
|
||||
};
|
||||
|
||||
public deleteListPolicy = async (): Promise<unknown> => {
|
||||
const {
|
||||
dataClient: { callAsCurrentUser },
|
||||
} = this;
|
||||
const { callCluster } = this;
|
||||
const listIndex = this.getListIndex();
|
||||
return deletePolicy(callAsCurrentUser, listIndex);
|
||||
return deletePolicy(callCluster, listIndex);
|
||||
};
|
||||
|
||||
public deleteListItemPolicy = async (): Promise<unknown> => {
|
||||
const {
|
||||
dataClient: { callAsCurrentUser },
|
||||
} = this;
|
||||
const { callCluster } = this;
|
||||
const listItemIndex = this.getListItemIndex();
|
||||
return deletePolicy(callAsCurrentUser, listItemIndex);
|
||||
return deletePolicy(callCluster, listItemIndex);
|
||||
};
|
||||
|
||||
public deleteListTemplate = async (): Promise<unknown> => {
|
||||
const {
|
||||
dataClient: { callAsCurrentUser },
|
||||
} = this;
|
||||
const { callCluster } = this;
|
||||
const listIndex = this.getListIndex();
|
||||
return deleteTemplate(callAsCurrentUser, listIndex);
|
||||
return deleteTemplate(callCluster, listIndex);
|
||||
};
|
||||
|
||||
public deleteListItemTemplate = async (): Promise<unknown> => {
|
||||
const {
|
||||
dataClient: { callAsCurrentUser },
|
||||
} = this;
|
||||
const { callCluster } = this;
|
||||
const listItemIndex = this.getListItemIndex();
|
||||
return deleteTemplate(callAsCurrentUser, listItemIndex);
|
||||
return deleteTemplate(callCluster, listItemIndex);
|
||||
};
|
||||
|
||||
public deleteListItem = async ({ id }: DeleteListItemOptions): Promise<ListItemSchema | null> => {
|
||||
const { dataClient } = this;
|
||||
const { callCluster } = this;
|
||||
const listItemIndex = this.getListItemIndex();
|
||||
return deleteListItem({ dataClient, id, listItemIndex });
|
||||
return deleteListItem({ callCluster, id, listItemIndex });
|
||||
};
|
||||
|
||||
public deleteListItemByValue = async ({
|
||||
|
@ -302,10 +254,10 @@ export class ListClient {
|
|||
value,
|
||||
type,
|
||||
}: DeleteListItemByValueOptions): Promise<ListItemArraySchema> => {
|
||||
const { dataClient } = this;
|
||||
const { callCluster } = this;
|
||||
const listItemIndex = this.getListItemIndex();
|
||||
return deleteListItemByValue({
|
||||
dataClient,
|
||||
callCluster,
|
||||
listId,
|
||||
listItemIndex,
|
||||
type,
|
||||
|
@ -314,11 +266,11 @@ export class ListClient {
|
|||
};
|
||||
|
||||
public deleteList = async ({ id }: DeleteListOptions): Promise<ListSchema | null> => {
|
||||
const { dataClient } = this;
|
||||
const { callCluster } = this;
|
||||
const listIndex = this.getListIndex();
|
||||
const listItemIndex = this.getListItemIndex();
|
||||
return deleteList({
|
||||
dataClient,
|
||||
callCluster,
|
||||
id,
|
||||
listIndex,
|
||||
listItemIndex,
|
||||
|
@ -330,10 +282,10 @@ export class ListClient {
|
|||
listId,
|
||||
stream,
|
||||
}: ExportListItemsToStreamOptions): void => {
|
||||
const { dataClient } = this;
|
||||
const { callCluster } = this;
|
||||
const listItemIndex = this.getListItemIndex();
|
||||
exportListItemsToStream({
|
||||
dataClient,
|
||||
callCluster,
|
||||
listId,
|
||||
listItemIndex,
|
||||
stream,
|
||||
|
@ -347,11 +299,10 @@ export class ListClient {
|
|||
stream,
|
||||
meta,
|
||||
}: ImportListItemsToStreamOptions): Promise<void> => {
|
||||
const { dataClient, security, request } = this;
|
||||
const { callCluster, user } = this;
|
||||
const listItemIndex = this.getListItemIndex();
|
||||
const user = getUser({ request, security });
|
||||
return importListItemsToStream({
|
||||
dataClient,
|
||||
callCluster,
|
||||
listId,
|
||||
listItemIndex,
|
||||
meta,
|
||||
|
@ -366,10 +317,10 @@ export class ListClient {
|
|||
value,
|
||||
type,
|
||||
}: GetListItemByValueOptions): Promise<ListItemArraySchema> => {
|
||||
const { dataClient } = this;
|
||||
const { callCluster } = this;
|
||||
const listItemIndex = this.getListItemIndex();
|
||||
return getListItemByValue({
|
||||
dataClient,
|
||||
callCluster,
|
||||
listId,
|
||||
listItemIndex,
|
||||
type,
|
||||
|
@ -384,11 +335,10 @@ export class ListClient {
|
|||
type,
|
||||
meta,
|
||||
}: CreateListItemOptions): Promise<ListItemSchema> => {
|
||||
const { dataClient, security, request } = this;
|
||||
const { callCluster, user } = this;
|
||||
const listItemIndex = this.getListItemIndex();
|
||||
const user = getUser({ request, security });
|
||||
return createListItem({
|
||||
dataClient,
|
||||
callCluster,
|
||||
id,
|
||||
listId,
|
||||
listItemIndex,
|
||||
|
@ -404,11 +354,10 @@ export class ListClient {
|
|||
value,
|
||||
meta,
|
||||
}: UpdateListItemOptions): Promise<ListItemSchema | null> => {
|
||||
const { dataClient, security, request } = this;
|
||||
const user = getUser({ request, security });
|
||||
const { callCluster, user } = this;
|
||||
const listItemIndex = this.getListItemIndex();
|
||||
return updateListItem({
|
||||
dataClient,
|
||||
callCluster,
|
||||
id,
|
||||
listItemIndex,
|
||||
meta,
|
||||
|
@ -423,11 +372,10 @@ export class ListClient {
|
|||
description,
|
||||
meta,
|
||||
}: UpdateListOptions): Promise<ListSchema | null> => {
|
||||
const { dataClient, security, request } = this;
|
||||
const user = getUser({ request, security });
|
||||
const { callCluster, user } = this;
|
||||
const listIndex = this.getListIndex();
|
||||
return updateList({
|
||||
dataClient,
|
||||
callCluster,
|
||||
description,
|
||||
id,
|
||||
listIndex,
|
||||
|
@ -438,10 +386,10 @@ export class ListClient {
|
|||
};
|
||||
|
||||
public getListItem = async ({ id }: GetListItemOptions): Promise<ListItemSchema | null> => {
|
||||
const { dataClient } = this;
|
||||
const { callCluster } = this;
|
||||
const listItemIndex = this.getListItemIndex();
|
||||
return getListItem({
|
||||
dataClient,
|
||||
callCluster,
|
||||
id,
|
||||
listItemIndex,
|
||||
});
|
||||
|
@ -452,10 +400,10 @@ export class ListClient {
|
|||
listId,
|
||||
value,
|
||||
}: GetListItemsByValueOptions): Promise<ListItemArraySchema> => {
|
||||
const { dataClient } = this;
|
||||
const { callCluster } = this;
|
||||
const listItemIndex = this.getListItemIndex();
|
||||
return getListItemByValues({
|
||||
dataClient,
|
||||
callCluster,
|
||||
listId,
|
||||
listItemIndex,
|
||||
type,
|
||||
|
|
|
@ -6,10 +6,9 @@
|
|||
|
||||
import { PassThrough, Readable } from 'stream';
|
||||
|
||||
import { KibanaRequest } from 'kibana/server';
|
||||
import { APICaller, KibanaRequest } from 'kibana/server';
|
||||
|
||||
import { SecurityPluginSetup } from '../../../../security/server';
|
||||
import { SpacesServiceSetup } from '../../../../spaces/server';
|
||||
import {
|
||||
Description,
|
||||
DescriptionOrUndefined,
|
||||
|
@ -21,14 +20,14 @@ import {
|
|||
Type,
|
||||
} from '../../../common/schemas';
|
||||
import { ConfigType } from '../../config';
|
||||
import { DataClient } from '../../types';
|
||||
|
||||
export interface ConstructorOptions {
|
||||
callCluster: APICaller;
|
||||
config: ConfigType;
|
||||
dataClient: DataClient;
|
||||
request: KibanaRequest;
|
||||
spaces: SpacesServiceSetup | undefined | null;
|
||||
security: SecurityPluginSetup;
|
||||
spaceId: string;
|
||||
user: string;
|
||||
security: SecurityPluginSetup | undefined | null;
|
||||
}
|
||||
|
||||
export interface GetListOptions {
|
||||
|
|
|
@ -31,7 +31,7 @@ describe('crete_list', () => {
|
|||
expect(list).toEqual(expected);
|
||||
});
|
||||
|
||||
test('It calls "callAsCurrentUser" with body, index, and listIndex', async () => {
|
||||
test('It calls "callCluster" with body, index, and listIndex', async () => {
|
||||
const options = getCreateListOptionsMock();
|
||||
await createList(options);
|
||||
const body = getIndexESListMock();
|
||||
|
@ -40,7 +40,7 @@ describe('crete_list', () => {
|
|||
id: LIST_ID,
|
||||
index: LIST_INDEX,
|
||||
};
|
||||
expect(options.dataClient.callAsCurrentUser).toBeCalledWith('index', expected);
|
||||
expect(options.callCluster).toBeCalledWith('index', expected);
|
||||
});
|
||||
|
||||
test('It returns an auto-generated id if id is sent in undefined', async () => {
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
|
||||
import uuid from 'uuid';
|
||||
import { CreateDocumentResponse } from 'elasticsearch';
|
||||
import { APICaller } from 'kibana/server';
|
||||
|
||||
import { DataClient } from '../../types';
|
||||
import {
|
||||
Description,
|
||||
IdOrUndefined,
|
||||
|
@ -23,7 +23,7 @@ export interface CreateListOptions {
|
|||
type: Type;
|
||||
name: Name;
|
||||
description: Description;
|
||||
dataClient: DataClient;
|
||||
callCluster: APICaller;
|
||||
listIndex: string;
|
||||
user: string;
|
||||
meta: MetaOrUndefined;
|
||||
|
@ -36,7 +36,7 @@ export const createList = async ({
|
|||
name,
|
||||
type,
|
||||
description,
|
||||
dataClient,
|
||||
callCluster,
|
||||
listIndex,
|
||||
user,
|
||||
meta,
|
||||
|
@ -55,7 +55,7 @@ export const createList = async ({
|
|||
updated_at: createdAt,
|
||||
updated_by: user,
|
||||
};
|
||||
const response: CreateDocumentResponse = await dataClient.callAsCurrentUser('index', {
|
||||
const response: CreateDocumentResponse = await callCluster('index', {
|
||||
body,
|
||||
id,
|
||||
index: listIndex,
|
||||
|
|
|
@ -52,7 +52,7 @@ describe('delete_list', () => {
|
|||
body: { query: { term: { list_id: LIST_ID } } },
|
||||
index: LIST_ITEM_INDEX,
|
||||
};
|
||||
expect(options.dataClient.callAsCurrentUser).toBeCalledWith('deleteByQuery', deleteByQuery);
|
||||
expect(options.callCluster).toBeCalledWith('deleteByQuery', deleteByQuery);
|
||||
});
|
||||
|
||||
test('Delete calls "delete" second if a list is returned from getList', async () => {
|
||||
|
@ -64,13 +64,13 @@ describe('delete_list', () => {
|
|||
id: LIST_ID,
|
||||
index: LIST_INDEX,
|
||||
};
|
||||
expect(options.dataClient.callAsCurrentUser).toHaveBeenNthCalledWith(2, 'delete', deleteQuery);
|
||||
expect(options.callCluster).toHaveBeenNthCalledWith(2, 'delete', deleteQuery);
|
||||
});
|
||||
|
||||
test('Delete does not call data client if the list returns null', async () => {
|
||||
((getList as unknown) as jest.Mock).mockResolvedValueOnce(null);
|
||||
const options = getDeleteListOptionsMock();
|
||||
await deleteList(options);
|
||||
expect(options.dataClient.callAsCurrentUser).not.toHaveBeenCalled();
|
||||
expect(options.callCluster).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -4,29 +4,30 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { APICaller } from 'kibana/server';
|
||||
|
||||
import { Id, ListSchema } from '../../../common/schemas';
|
||||
import { DataClient } from '../../types';
|
||||
|
||||
import { getList } from './get_list';
|
||||
|
||||
export interface DeleteListOptions {
|
||||
id: Id;
|
||||
dataClient: DataClient;
|
||||
callCluster: APICaller;
|
||||
listIndex: string;
|
||||
listItemIndex: string;
|
||||
}
|
||||
|
||||
export const deleteList = async ({
|
||||
id,
|
||||
dataClient,
|
||||
callCluster,
|
||||
listIndex,
|
||||
listItemIndex,
|
||||
}: DeleteListOptions): Promise<ListSchema | null> => {
|
||||
const list = await getList({ dataClient, id, listIndex });
|
||||
const list = await getList({ callCluster, id, listIndex });
|
||||
if (list == null) {
|
||||
return null;
|
||||
} else {
|
||||
await dataClient.callAsCurrentUser('deleteByQuery', {
|
||||
await callCluster('deleteByQuery', {
|
||||
body: {
|
||||
query: {
|
||||
term: {
|
||||
|
@ -37,7 +38,7 @@ export const deleteList = async ({
|
|||
index: listItemIndex,
|
||||
});
|
||||
|
||||
await dataClient.callAsCurrentUser('delete', {
|
||||
await callCluster('delete', {
|
||||
id,
|
||||
index: listIndex,
|
||||
});
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
import {
|
||||
LIST_ID,
|
||||
LIST_INDEX,
|
||||
getDataClientMock,
|
||||
getCallClusterMock,
|
||||
getListResponseMock,
|
||||
getSearchListMock,
|
||||
} from '../mocks';
|
||||
|
@ -25,8 +25,8 @@ describe('get_list', () => {
|
|||
|
||||
test('it returns a list as expected if the list is found', async () => {
|
||||
const data = getSearchListMock();
|
||||
const dataClient = getDataClientMock(data);
|
||||
const list = await getList({ dataClient, id: LIST_ID, listIndex: LIST_INDEX });
|
||||
const callCluster = getCallClusterMock(data);
|
||||
const list = await getList({ callCluster, id: LIST_ID, listIndex: LIST_INDEX });
|
||||
const expected = getListResponseMock();
|
||||
expect(list).toEqual(expected);
|
||||
});
|
||||
|
@ -34,8 +34,8 @@ describe('get_list', () => {
|
|||
test('it returns null if the search is empty', async () => {
|
||||
const data = getSearchListMock();
|
||||
data.hits.hits = [];
|
||||
const dataClient = getDataClientMock(data);
|
||||
const list = await getList({ dataClient, id: LIST_ID, listIndex: LIST_INDEX });
|
||||
const callCluster = getCallClusterMock(data);
|
||||
const list = await getList({ callCluster, id: LIST_ID, listIndex: LIST_INDEX });
|
||||
expect(list).toEqual(null);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -5,22 +5,22 @@
|
|||
*/
|
||||
|
||||
import { SearchResponse } from 'elasticsearch';
|
||||
import { APICaller } from 'kibana/server';
|
||||
|
||||
import { Id, ListSchema, SearchEsListSchema } from '../../../common/schemas';
|
||||
import { DataClient } from '../../types';
|
||||
|
||||
interface GetListOptions {
|
||||
id: Id;
|
||||
dataClient: DataClient;
|
||||
callCluster: APICaller;
|
||||
listIndex: string;
|
||||
}
|
||||
|
||||
export const getList = async ({
|
||||
id,
|
||||
dataClient,
|
||||
callCluster,
|
||||
listIndex,
|
||||
}: GetListOptions): Promise<ListSchema | null> => {
|
||||
const result: SearchResponse<SearchEsListSchema> = await dataClient.callAsCurrentUser('search', {
|
||||
const result: SearchResponse<SearchEsListSchema> = await callCluster('search', {
|
||||
body: {
|
||||
query: {
|
||||
term: {
|
||||
|
|
|
@ -4,17 +4,8 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { httpServerMock } from 'src/core/server/mocks';
|
||||
import { KibanaRequest } from 'src/core/server';
|
||||
|
||||
import { getSpace } from '../utils';
|
||||
|
||||
import { getListIndex } from './get_list_index';
|
||||
|
||||
jest.mock('../utils', () => ({
|
||||
getSpace: jest.fn(),
|
||||
}));
|
||||
|
||||
describe('get_list_index', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
|
@ -25,13 +16,9 @@ describe('get_list_index', () => {
|
|||
});
|
||||
|
||||
test('Returns the list index when there is a space', async () => {
|
||||
((getSpace as unknown) as jest.Mock).mockReturnValueOnce('test-space');
|
||||
const rawRequest = httpServerMock.createRawRequest({});
|
||||
const request = KibanaRequest.from(rawRequest);
|
||||
const listIndex = getListIndex({
|
||||
listsIndexName: 'lists-index',
|
||||
request,
|
||||
spaces: undefined,
|
||||
spaceId: 'test-space',
|
||||
});
|
||||
expect(listIndex).toEqual('lists-index-test-space');
|
||||
});
|
||||
|
|
|
@ -4,16 +4,10 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { KibanaRequest } from 'kibana/server';
|
||||
|
||||
import { SpacesServiceSetup } from '../../../../spaces/server';
|
||||
import { getSpace } from '../utils';
|
||||
|
||||
interface GetListIndexOptions {
|
||||
spaces: SpacesServiceSetup | undefined | null;
|
||||
request: KibanaRequest;
|
||||
spaceId: string;
|
||||
listsIndexName: string;
|
||||
}
|
||||
|
||||
export const getListIndex = ({ spaces, request, listsIndexName }: GetListIndexOptions): string =>
|
||||
`${listsIndexName}-${getSpace({ request, spaces })}`;
|
||||
export const getListIndex = ({ spaceId, listsIndexName }: GetListIndexOptions): string =>
|
||||
`${listsIndexName}-${spaceId}`;
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
|
||||
import { CreateDocumentResponse } from 'elasticsearch';
|
||||
import { APICaller } from 'kibana/server';
|
||||
|
||||
import {
|
||||
DescriptionOrUndefined,
|
||||
|
@ -14,13 +15,12 @@ import {
|
|||
NameOrUndefined,
|
||||
UpdateEsListSchema,
|
||||
} from '../../../common/schemas';
|
||||
import { DataClient } from '../../types';
|
||||
|
||||
import { getList } from '.';
|
||||
|
||||
export interface UpdateListOptions {
|
||||
id: Id;
|
||||
dataClient: DataClient;
|
||||
callCluster: APICaller;
|
||||
listIndex: string;
|
||||
user: string;
|
||||
name: NameOrUndefined;
|
||||
|
@ -33,14 +33,14 @@ export const updateList = async ({
|
|||
id,
|
||||
name,
|
||||
description,
|
||||
dataClient,
|
||||
callCluster,
|
||||
listIndex,
|
||||
user,
|
||||
meta,
|
||||
dateNow,
|
||||
}: UpdateListOptions): Promise<ListSchema | null> => {
|
||||
const updatedAt = dateNow ?? new Date().toISOString();
|
||||
const list = await getList({ dataClient, id, listIndex });
|
||||
const list = await getList({ callCluster, id, listIndex });
|
||||
if (list == null) {
|
||||
return null;
|
||||
} else {
|
||||
|
@ -51,7 +51,7 @@ export const updateList = async ({
|
|||
updated_at: updatedAt,
|
||||
updated_by: user,
|
||||
};
|
||||
const response: CreateDocumentResponse = await dataClient.callAsCurrentUser('update', {
|
||||
const response: CreateDocumentResponse = await callCluster('update', {
|
||||
body: { doc },
|
||||
id,
|
||||
index: listIndex,
|
||||
|
|
|
@ -5,15 +5,11 @@
|
|||
*/
|
||||
|
||||
import { CreateDocumentResponse } from 'elasticsearch';
|
||||
import { APICaller } from 'kibana/server';
|
||||
|
||||
import { LIST_INDEX } from './lists_services_mock_constants';
|
||||
import { getShardMock } from './get_shard_mock';
|
||||
|
||||
interface DataClientReturn {
|
||||
callAsCurrentUser: () => Promise<unknown>;
|
||||
callAsInternalUser: () => Promise<never>;
|
||||
}
|
||||
|
||||
export const getEmptyCreateDocumentResponseMock = (): CreateDocumentResponse => ({
|
||||
_id: 'elastic-id-123',
|
||||
_index: LIST_INDEX,
|
||||
|
@ -24,11 +20,6 @@ export const getEmptyCreateDocumentResponseMock = (): CreateDocumentResponse =>
|
|||
result: '',
|
||||
});
|
||||
|
||||
export const getDataClientMock = (
|
||||
callAsCurrentUserData: unknown = getEmptyCreateDocumentResponseMock()
|
||||
): DataClientReturn => ({
|
||||
callAsCurrentUser: jest.fn().mockResolvedValue(callAsCurrentUserData),
|
||||
callAsInternalUser: (): Promise<never> => {
|
||||
throw new Error('This function should not be calling "callAsInternalUser"');
|
||||
},
|
||||
});
|
||||
export const getCallClusterMock = (
|
||||
callCluster: unknown = getEmptyCreateDocumentResponseMock()
|
||||
): APICaller => jest.fn().mockResolvedValue(callCluster);
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
import { CreateListItemsBulkOptions } from '../items';
|
||||
|
||||
import { getDataClientMock } from './get_data_client_mock';
|
||||
import { getCallClusterMock } from './get_call_cluster_mock';
|
||||
import {
|
||||
DATE_NOW,
|
||||
LIST_ID,
|
||||
|
@ -20,7 +20,7 @@ import {
|
|||
} from './lists_services_mock_constants';
|
||||
|
||||
export const getCreateListItemBulkOptionsMock = (): CreateListItemsBulkOptions => ({
|
||||
dataClient: getDataClientMock(),
|
||||
callCluster: getCallClusterMock(),
|
||||
dateNow: DATE_NOW,
|
||||
listId: LIST_ID,
|
||||
listItemIndex: LIST_ITEM_INDEX,
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
import { CreateListItemOptions } from '../items';
|
||||
|
||||
import { getDataClientMock } from './get_data_client_mock';
|
||||
import { getCallClusterMock } from './get_call_cluster_mock';
|
||||
import {
|
||||
DATE_NOW,
|
||||
LIST_ID,
|
||||
|
@ -19,7 +19,7 @@ import {
|
|||
} from './lists_services_mock_constants';
|
||||
|
||||
export const getCreateListItemOptionsMock = (): CreateListItemOptions => ({
|
||||
dataClient: getDataClientMock(),
|
||||
callCluster: getCallClusterMock(),
|
||||
dateNow: DATE_NOW,
|
||||
id: LIST_ITEM_ID,
|
||||
listId: LIST_ID,
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
import { CreateListOptions } from '../lists';
|
||||
|
||||
import { getDataClientMock } from './get_data_client_mock';
|
||||
import { getCallClusterMock } from './get_call_cluster_mock';
|
||||
import {
|
||||
DATE_NOW,
|
||||
DESCRIPTION,
|
||||
|
@ -20,7 +20,7 @@ import {
|
|||
} from './lists_services_mock_constants';
|
||||
|
||||
export const getCreateListOptionsMock = (): CreateListOptions => ({
|
||||
dataClient: getDataClientMock(),
|
||||
callCluster: getCallClusterMock(),
|
||||
dateNow: DATE_NOW,
|
||||
description: DESCRIPTION,
|
||||
id: LIST_ID,
|
||||
|
|
|
@ -6,11 +6,11 @@
|
|||
|
||||
import { DeleteListItemByValueOptions } from '../items';
|
||||
|
||||
import { getDataClientMock } from './get_data_client_mock';
|
||||
import { getCallClusterMock } from './get_call_cluster_mock';
|
||||
import { LIST_ID, LIST_ITEM_INDEX, TYPE, VALUE } from './lists_services_mock_constants';
|
||||
|
||||
export const getDeleteListItemByValueOptionsMock = (): DeleteListItemByValueOptions => ({
|
||||
dataClient: getDataClientMock(),
|
||||
callCluster: getCallClusterMock(),
|
||||
listId: LIST_ID,
|
||||
listItemIndex: LIST_ITEM_INDEX,
|
||||
type: TYPE,
|
||||
|
|
|
@ -6,11 +6,11 @@
|
|||
|
||||
import { DeleteListItemOptions } from '../items';
|
||||
|
||||
import { getDataClientMock } from './get_data_client_mock';
|
||||
import { getCallClusterMock } from './get_call_cluster_mock';
|
||||
import { LIST_ITEM_ID, LIST_ITEM_INDEX } from './lists_services_mock_constants';
|
||||
|
||||
export const getDeleteListItemOptionsMock = (): DeleteListItemOptions => ({
|
||||
dataClient: getDataClientMock(),
|
||||
callCluster: getCallClusterMock(),
|
||||
id: LIST_ITEM_ID,
|
||||
listItemIndex: LIST_ITEM_INDEX,
|
||||
});
|
||||
|
|
|
@ -6,11 +6,11 @@
|
|||
|
||||
import { DeleteListOptions } from '../lists';
|
||||
|
||||
import { getDataClientMock } from './get_data_client_mock';
|
||||
import { getCallClusterMock } from './get_call_cluster_mock';
|
||||
import { LIST_ID, LIST_INDEX, LIST_ITEM_INDEX } from './lists_services_mock_constants';
|
||||
|
||||
export const getDeleteListOptionsMock = (): DeleteListOptions => ({
|
||||
dataClient: getDataClientMock(),
|
||||
callCluster: getCallClusterMock(),
|
||||
id: LIST_ID,
|
||||
listIndex: LIST_INDEX,
|
||||
listItemIndex: LIST_ITEM_INDEX,
|
||||
|
|
|
@ -5,12 +5,12 @@
|
|||
*/
|
||||
import { ImportListItemsToStreamOptions } from '../items';
|
||||
|
||||
import { getDataClientMock } from './get_data_client_mock';
|
||||
import { getCallClusterMock } from './get_call_cluster_mock';
|
||||
import { LIST_ID, LIST_ITEM_INDEX, META, TYPE, USER } from './lists_services_mock_constants';
|
||||
import { TestReadable } from './test_readable';
|
||||
|
||||
export const getImportListItemsToStreamOptionsMock = (): ImportListItemsToStreamOptions => ({
|
||||
dataClient: getDataClientMock(),
|
||||
callCluster: getCallClusterMock(),
|
||||
listId: LIST_ID,
|
||||
listItemIndex: LIST_ITEM_INDEX,
|
||||
meta: META,
|
||||
|
|
|
@ -6,11 +6,11 @@
|
|||
|
||||
import { GetListItemByValueOptions } from '../items';
|
||||
|
||||
import { getDataClientMock } from './get_data_client_mock';
|
||||
import { getCallClusterMock } from './get_call_cluster_mock';
|
||||
import { LIST_ID, LIST_ITEM_INDEX, TYPE, VALUE } from './lists_services_mock_constants';
|
||||
|
||||
export const getListItemByValueOptionsMocks = (): GetListItemByValueOptions => ({
|
||||
dataClient: getDataClientMock(),
|
||||
callCluster: getCallClusterMock(),
|
||||
listId: LIST_ID,
|
||||
listItemIndex: LIST_ITEM_INDEX,
|
||||
type: TYPE,
|
||||
|
|
|
@ -6,11 +6,11 @@
|
|||
|
||||
import { GetListItemByValuesOptions } from '../items';
|
||||
|
||||
import { getDataClientMock } from './get_data_client_mock';
|
||||
import { getCallClusterMock } from './get_call_cluster_mock';
|
||||
import { LIST_ID, LIST_ITEM_INDEX, TYPE, VALUE, VALUE_2 } from './lists_services_mock_constants';
|
||||
|
||||
export const getListItemByValuesOptionsMocks = (): GetListItemByValuesOptions => ({
|
||||
dataClient: getDataClientMock(),
|
||||
callCluster: getCallClusterMock(),
|
||||
listId: LIST_ID,
|
||||
listItemIndex: LIST_ITEM_INDEX,
|
||||
type: TYPE,
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
import { UpdateListItemOptions } from '../items';
|
||||
|
||||
import { getDataClientMock } from './get_data_client_mock';
|
||||
import { getCallClusterMock } from './get_call_cluster_mock';
|
||||
import {
|
||||
DATE_NOW,
|
||||
LIST_ITEM_ID,
|
||||
|
@ -16,7 +16,7 @@ import {
|
|||
} from './lists_services_mock_constants';
|
||||
|
||||
export const getUpdateListItemOptionsMock = (): UpdateListItemOptions => ({
|
||||
dataClient: getDataClientMock(),
|
||||
callCluster: getCallClusterMock(),
|
||||
dateNow: DATE_NOW,
|
||||
id: LIST_ITEM_ID,
|
||||
listItemIndex: LIST_ITEM_INDEX,
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
import { UpdateListOptions } from '../lists';
|
||||
|
||||
import { getDataClientMock } from './get_data_client_mock';
|
||||
import { getCallClusterMock } from './get_call_cluster_mock';
|
||||
import {
|
||||
DATE_NOW,
|
||||
DESCRIPTION,
|
||||
|
@ -17,7 +17,7 @@ import {
|
|||
} from './lists_services_mock_constants';
|
||||
|
||||
export const getUpdateListOptionsMock = (): UpdateListOptions => ({
|
||||
dataClient: getDataClientMock(),
|
||||
callCluster: getCallClusterMock(),
|
||||
dateNow: DATE_NOW,
|
||||
description: DESCRIPTION,
|
||||
id: LIST_ID,
|
||||
|
|
|
@ -5,12 +5,12 @@
|
|||
*/
|
||||
import { WriteBufferToItemsOptions } from '../items';
|
||||
|
||||
import { getDataClientMock } from './get_data_client_mock';
|
||||
import { getCallClusterMock } from './get_call_cluster_mock';
|
||||
import { LIST_ID, LIST_ITEM_INDEX, META, TYPE, USER } from './lists_services_mock_constants';
|
||||
|
||||
export const getWriteBufferToItemsOptionsMock = (): WriteBufferToItemsOptions => ({
|
||||
buffer: [],
|
||||
dataClient: getDataClientMock(),
|
||||
callCluster: getCallClusterMock(),
|
||||
listId: LIST_ID,
|
||||
listItemIndex: LIST_ITEM_INDEX,
|
||||
meta: META,
|
||||
|
|
|
@ -13,12 +13,12 @@ import {
|
|||
WriteResponseHitsToStreamOptions,
|
||||
} from '../items';
|
||||
|
||||
import { getDataClientMock } from './get_data_client_mock';
|
||||
import { LIST_ID, LIST_ITEM_INDEX } from './lists_services_mock_constants';
|
||||
import { getSearchListItemMock } from './get_search_list_item_mock';
|
||||
import { getCallClusterMock } from './get_call_cluster_mock';
|
||||
|
||||
export const getExportListItemsToStreamOptionsMock = (): ExportListItemsToStreamOptions => ({
|
||||
dataClient: getDataClientMock(getSearchListItemMock()),
|
||||
callCluster: getCallClusterMock(getSearchListItemMock()),
|
||||
listId: LIST_ID,
|
||||
listItemIndex: LIST_ITEM_INDEX,
|
||||
stream: new Stream.PassThrough(),
|
||||
|
@ -26,7 +26,7 @@ export const getExportListItemsToStreamOptionsMock = (): ExportListItemsToStream
|
|||
});
|
||||
|
||||
export const getWriteNextResponseOptions = (): WriteNextResponseOptions => ({
|
||||
dataClient: getDataClientMock(getSearchListItemMock()),
|
||||
callCluster: getCallClusterMock(getSearchListItemMock()),
|
||||
listId: LIST_ID,
|
||||
listItemIndex: LIST_ITEM_INDEX,
|
||||
searchAfter: [],
|
||||
|
@ -35,7 +35,7 @@ export const getWriteNextResponseOptions = (): WriteNextResponseOptions => ({
|
|||
});
|
||||
|
||||
export const getResponseOptionsMock = (): GetResponseOptions => ({
|
||||
dataClient: getDataClientMock(),
|
||||
callCluster: getCallClusterMock(),
|
||||
listId: LIST_ID,
|
||||
listItemIndex: LIST_ITEM_INDEX,
|
||||
searchAfter: [],
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
export * from './get_data_client_mock';
|
||||
export * from './get_call_cluster_mock';
|
||||
export * from './get_delete_list_options_mock';
|
||||
export * from './get_create_list_options_mock';
|
||||
export * from './get_list_response_mock';
|
||||
|
@ -27,3 +27,5 @@ export * from './get_update_list_item_options_mock';
|
|||
export * from './get_write_buffer_to_items_options_mock';
|
||||
export * from './get_import_list_items_to_stream_options_mock';
|
||||
export * from './get_write_list_items_to_stream_options_mock';
|
||||
export * from './get_search_list_item_mock';
|
||||
export * from './test_readable';
|
||||
|
|
|
@ -10,6 +10,14 @@ import { Type } from '../../../common/schemas';
|
|||
import { deriveTypeFromItem } from './derive_type_from_es_type';
|
||||
|
||||
describe('derive_type_from_es_type', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
test('it returns the item ip if it exists', () => {
|
||||
const item = getSearchEsListItemMock();
|
||||
const derivedType = deriveTypeFromItem({ item });
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* 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 { QueryFilterType, getQueryFilterFromTypeValue } from './get_query_filter_from_type_value';
|
||||
|
||||
describe('get_query_filter_from_type_value', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
test('it returns an ip if given an ip', () => {
|
||||
const queryFilter = getQueryFilterFromTypeValue({
|
||||
listId: 'list-123',
|
||||
type: 'ip',
|
||||
value: ['127.0.0.1'],
|
||||
});
|
||||
const expected: QueryFilterType = [
|
||||
{ term: { list_id: 'list-123' } },
|
||||
{ terms: { ip: ['127.0.0.1'] } },
|
||||
];
|
||||
expect(queryFilter).toEqual(expected);
|
||||
});
|
||||
|
||||
test('it returns two ip if given two ip', () => {
|
||||
const queryFilter = getQueryFilterFromTypeValue({
|
||||
listId: 'list-123',
|
||||
type: 'ip',
|
||||
value: ['127.0.0.1', '127.0.0.2'],
|
||||
});
|
||||
const expected: QueryFilterType = [
|
||||
{ term: { list_id: 'list-123' } },
|
||||
{ terms: { ip: ['127.0.0.1', '127.0.0.2'] } },
|
||||
];
|
||||
expect(queryFilter).toEqual(expected);
|
||||
});
|
||||
|
||||
test('it returns a keyword if given a keyword', () => {
|
||||
const queryFilter = getQueryFilterFromTypeValue({
|
||||
listId: 'list-123',
|
||||
type: 'keyword',
|
||||
value: ['host-name-1'],
|
||||
});
|
||||
const expected: QueryFilterType = [
|
||||
{ term: { list_id: 'list-123' } },
|
||||
{ terms: { keyword: ['host-name-1'] } },
|
||||
];
|
||||
expect(queryFilter).toEqual(expected);
|
||||
});
|
||||
|
||||
test('it returns two keywords if given two values', () => {
|
||||
const queryFilter = getQueryFilterFromTypeValue({
|
||||
listId: 'list-123',
|
||||
type: 'keyword',
|
||||
value: ['host-name-1', 'host-name-2'],
|
||||
});
|
||||
const expected: QueryFilterType = [
|
||||
{ term: { list_id: 'list-123' } },
|
||||
{ terms: { keyword: ['host-name-1', 'host-name-2'] } },
|
||||
];
|
||||
expect(queryFilter).toEqual(expected);
|
||||
});
|
||||
|
||||
test('it returns an empty keyword given an empty value', () => {
|
||||
const queryFilter = getQueryFilterFromTypeValue({
|
||||
listId: 'list-123',
|
||||
type: 'keyword',
|
||||
value: [],
|
||||
});
|
||||
const expected: QueryFilterType = [
|
||||
{ term: { list_id: 'list-123' } },
|
||||
{ terms: { keyword: [] } },
|
||||
];
|
||||
expect(queryFilter).toEqual(expected);
|
||||
});
|
||||
|
||||
test('it returns an empty ip given an empty value', () => {
|
||||
const queryFilter = getQueryFilterFromTypeValue({
|
||||
listId: 'list-123',
|
||||
type: 'ip',
|
||||
value: [],
|
||||
});
|
||||
const expected: QueryFilterType = [{ term: { list_id: 'list-123' } }, { terms: { ip: [] } }];
|
||||
expect(queryFilter).toEqual(expected);
|
||||
});
|
||||
});
|
|
@ -7,6 +7,4 @@
|
|||
export * from './get_query_filter_from_type_value';
|
||||
export * from './transform_elastic_to_list_item';
|
||||
export * from './transform_list_item_to_elastic_query';
|
||||
export * from './get_user';
|
||||
export * from './derive_type_from_es_type';
|
||||
export * from './get_space';
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* 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 { ListItemArraySchema } from '../../../common/schemas';
|
||||
import { getListItemResponseMock, getSearchListItemMock } from '../mocks';
|
||||
|
||||
import { transformElasticToListItem } from './transform_elastic_to_list_item';
|
||||
|
||||
describe('transform_elastic_to_list_item', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
test('it transforms an elastic type to a list item type', () => {
|
||||
const response = getSearchListItemMock();
|
||||
const queryFilter = transformElasticToListItem({
|
||||
response,
|
||||
type: 'ip',
|
||||
});
|
||||
const expected: ListItemArraySchema = [getListItemResponseMock()];
|
||||
expect(queryFilter).toEqual(expected);
|
||||
});
|
||||
|
||||
test('it transforms an elastic keyword type to a list item type', () => {
|
||||
const response = getSearchListItemMock();
|
||||
response.hits.hits[0]._source.ip = undefined;
|
||||
response.hits.hits[0]._source.keyword = 'host-name-example';
|
||||
const queryFilter = transformElasticToListItem({
|
||||
response,
|
||||
type: 'keyword',
|
||||
});
|
||||
const listItemResponse = getListItemResponseMock();
|
||||
listItemResponse.type = 'keyword';
|
||||
listItemResponse.value = 'host-name-example';
|
||||
const expected: ListItemArraySchema = [listItemResponse];
|
||||
expect(queryFilter).toEqual(expected);
|
||||
});
|
||||
|
||||
test('it does a throw if it cannot determine the list item type from "ip"', () => {
|
||||
const response = getSearchListItemMock();
|
||||
response.hits.hits[0]._source.ip = undefined;
|
||||
response.hits.hits[0]._source.keyword = 'host-name-example';
|
||||
expect(() =>
|
||||
transformElasticToListItem({
|
||||
response,
|
||||
type: 'ip',
|
||||
})
|
||||
).toThrow('Was expecting ip to not be null/undefined');
|
||||
});
|
||||
|
||||
test('it does a throw if it cannot determine the list item type from "keyword"', () => {
|
||||
const response = getSearchListItemMock();
|
||||
response.hits.hits[0]._source.ip = '127.0.0.1';
|
||||
response.hits.hits[0]._source.keyword = undefined;
|
||||
expect(() =>
|
||||
transformElasticToListItem({
|
||||
response,
|
||||
type: 'keyword',
|
||||
})
|
||||
).toThrow('Was expecting keyword to not be null/undefined');
|
||||
});
|
||||
});
|
|
@ -9,13 +9,15 @@ import { SearchResponse } from 'elasticsearch';
|
|||
import { ListItemArraySchema, SearchEsListItemSchema, Type } from '../../../common/schemas';
|
||||
import { ErrorWithStatusCode } from '../../error_with_status_code';
|
||||
|
||||
export interface TransformElasticToListItemOptions {
|
||||
response: SearchResponse<SearchEsListItemSchema>;
|
||||
type: Type;
|
||||
}
|
||||
|
||||
export const transformElasticToListItem = ({
|
||||
response,
|
||||
type,
|
||||
}: {
|
||||
response: SearchResponse<SearchEsListItemSchema>;
|
||||
type: Type;
|
||||
}): ListItemArraySchema => {
|
||||
}: TransformElasticToListItemOptions): ListItemArraySchema => {
|
||||
return response.hits.hits.map(hit => {
|
||||
const {
|
||||
_id,
|
||||
|
@ -64,11 +66,10 @@ export const transformElasticToListItem = ({
|
|||
};
|
||||
}
|
||||
}
|
||||
// TypeScript is not happy unless I have this line here
|
||||
return assertUnreachable();
|
||||
});
|
||||
};
|
||||
|
||||
export const assertUnreachable = (): never => {
|
||||
const assertUnreachable = (): never => {
|
||||
throw new Error('Unknown type in elastic_to_list_items');
|
||||
};
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* 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 { EsDataTypeUnion, Type } from '../../../common/schemas';
|
||||
|
||||
import { transformListItemToElasticQuery } from './transform_list_item_to_elastic_query';
|
||||
|
||||
describe('transform_elastic_to_elastic_query', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
test('it transforms a ip type and value to a union', () => {
|
||||
const elasticQuery = transformListItemToElasticQuery({
|
||||
type: 'ip',
|
||||
value: '127.0.0.1',
|
||||
});
|
||||
const expected: EsDataTypeUnion = { ip: '127.0.0.1' };
|
||||
expect(elasticQuery).toEqual(expected);
|
||||
});
|
||||
|
||||
test('it transforms a keyword type and value to a union', () => {
|
||||
const elasticQuery = transformListItemToElasticQuery({
|
||||
type: 'keyword',
|
||||
value: 'host-name',
|
||||
});
|
||||
const expected: EsDataTypeUnion = { keyword: 'host-name' };
|
||||
expect(elasticQuery).toEqual(expected);
|
||||
});
|
||||
|
||||
test('it throws if the type is not known', () => {
|
||||
const type: Type = 'made-up' as Type;
|
||||
expect(() =>
|
||||
transformListItemToElasticQuery({
|
||||
type,
|
||||
value: 'some-value',
|
||||
})
|
||||
).toThrow('Unknown type: "made-up" in transformListItemToElasticQuery');
|
||||
});
|
||||
});
|
|
@ -12,8 +12,6 @@ export const transformListItemToElasticQuery = ({
|
|||
}: {
|
||||
type: Type;
|
||||
value: string;
|
||||
// We disable the consistent return since we want to use typescript for exhaustive type checks
|
||||
// eslint-disable-next-line consistent-return
|
||||
}): EsDataTypeUnion => {
|
||||
switch (type) {
|
||||
case 'ip': {
|
||||
|
@ -27,4 +25,9 @@ export const transformListItemToElasticQuery = ({
|
|||
};
|
||||
}
|
||||
}
|
||||
return assertUnreachable(type);
|
||||
};
|
||||
|
||||
const assertUnreachable = (type: string): never => {
|
||||
throw new Error(`Unknown type: "${type}" in transformListItemToElasticQuery`);
|
||||
};
|
||||
|
|
|
@ -4,18 +4,17 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { IContextProvider, RequestHandler, ScopedClusterClient } from 'kibana/server';
|
||||
import { IContextProvider, RequestHandler } from 'kibana/server';
|
||||
|
||||
import { SecurityPluginSetup } from '../../security/server';
|
||||
import { SpacesPluginSetup } from '../../spaces/server';
|
||||
|
||||
import { ListClient } from './services/lists/client';
|
||||
|
||||
export type DataClient = Pick<ScopedClusterClient, 'callAsCurrentUser' | 'callAsInternalUser'>;
|
||||
export type ContextProvider = IContextProvider<RequestHandler<unknown, unknown, unknown>, 'lists'>;
|
||||
|
||||
export interface PluginsSetup {
|
||||
security: SecurityPluginSetup;
|
||||
security: SecurityPluginSetup | undefined | null;
|
||||
spaces: SpacesPluginSetup | undefined | null;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue