From f3e4ababb8b22da6cc722fff8ca2a8b973385e40 Mon Sep 17 00:00:00 2001 From: Georgii Gorbachev Date: Fri, 12 Feb 2021 17:56:23 +0100 Subject: [PATCH] Switch back to the server-side implementation --- .../rules_table/projections/filtering.ts | 54 ----------------- .../rules_table/projections/pagination.ts | 37 ------------ .../rules/rules_table/projections/sorting.ts | 24 -------- .../rules/rules_table/use_rules_table.ts | 60 ++++++------------- 4 files changed, 18 insertions(+), 157 deletions(-) delete mode 100644 x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/rules_table/projections/filtering.ts delete mode 100644 x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/rules_table/projections/pagination.ts delete mode 100644 x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/rules_table/projections/sorting.ts diff --git a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/rules_table/projections/filtering.ts b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/rules_table/projections/filtering.ts deleted file mode 100644 index 09bc58d6fb51e..0000000000000 --- a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/rules_table/projections/filtering.ts +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { useMemo } from 'react'; -import { pipe } from 'fp-ts/lib/function'; -import { every } from 'lodash/fp'; -import { Rule, FilterOptions } from '../../types'; - -export const useFilteredRules = (rules: Rule[], options: FilterOptions): Rule[] => { - const filterTags = options.tags.sort().join(); - return useMemo( - () => pipe(rules, filterRules(options)), - // eslint-disable-next-line react-hooks/exhaustive-deps - [rules, options.filter, options.showCustomRules, options.showElasticRules, filterTags] - ); -}; - -const filterRules = (options: FilterOptions) => (rules: Rule[]): Rule[] => { - const { filter, showCustomRules, showElasticRules, tags } = options; - return rules.filter((rule) => { - if (filter != null) { - const filterValue = filter.toLowerCase(); - const nameValue = String(rule.name).toLowerCase(); - if (!nameValue.includes(filterValue)) { - return false; - } - } - - if (showCustomRules !== showElasticRules) { - // If both are true or both are false, filtering is off by this criteria. - // If one of them is true, we turn this filter on. - // "Immutable" means the rule is "pre-packaged", or created by Elastic. - if (showCustomRules && rule.immutable) { - return false; - } - if (showElasticRules && !rule.immutable) { - return false; - } - } - - if (tags.length > 0) { - const includesAllTags = every((tag) => rule.tags.includes(tag), tags); - if (!includesAllTags) { - return false; - } - } - - return true; - }); -}; diff --git a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/rules_table/projections/pagination.ts b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/rules_table/projections/pagination.ts deleted file mode 100644 index 6177675435fbe..0000000000000 --- a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/rules_table/projections/pagination.ts +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { useMemo } from 'react'; -import { pipe } from 'fp-ts/lib/function'; -import { drop, take } from 'lodash/fp'; -import { Rule, PaginationOptions } from '../../types'; - -export const useDisplayedPaginationOptions = ( - filteredRules: Rule[], - options: PaginationOptions -): PaginationOptions => { - return useMemo(() => { - return { - page: options.page, - perPage: options.perPage, - total: filteredRules.length, - }; - }, [filteredRules, options.page, options.perPage]); -}; - -export const usePaginatedRules = (rules: Rule[], options: PaginationOptions): Rule[] => { - return useMemo( - () => pipe(rules, paginateRules(options)), - // eslint-disable-next-line react-hooks/exhaustive-deps - [rules, options.page, options.perPage] - ); -}; - -const paginateRules = (options: PaginationOptions) => (rules: Rule[]): Rule[] => { - const { page, perPage } = options; - return pipe(rules, drop(perPage * (page - 1)), take(perPage)); -}; diff --git a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/rules_table/projections/sorting.ts b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/rules_table/projections/sorting.ts deleted file mode 100644 index c104eba001cf5..0000000000000 --- a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/rules_table/projections/sorting.ts +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { useMemo } from 'react'; -import { pipe } from 'fp-ts/lib/function'; -import { orderBy } from 'lodash/fp'; -import { Rule, FilterOptions } from '../../types'; - -export const useSortedRules = (rules: Rule[], options: FilterOptions): Rule[] => { - return useMemo( - () => pipe(rules, sortRules(options)), - // eslint-disable-next-line react-hooks/exhaustive-deps - [rules, options.sortField, options.sortOrder] - ); -}; - -const sortRules = (options: FilterOptions) => (rules: Rule[]): Rule[] => { - const { sortField, sortOrder } = options; - return orderBy([sortField], [sortOrder], rules); -}; diff --git a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/rules_table/use_rules_table.ts b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/rules_table/use_rules_table.ts index ebf559884bbfe..f31b2894301ba 100644 --- a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/rules_table/use_rules_table.ts +++ b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/rules_table/use_rules_table.ts @@ -14,22 +14,6 @@ import * as i18n from '../translations'; import { fetchRules } from '../api'; import { createRulesTableReducer, RulesTableState, RulesTableAction } from './rules_table_reducer'; import { createRulesTableFacade, RulesTableFacade } from './rules_table_facade'; -import { useFilteredRules } from './projections/filtering'; -import { useSortedRules } from './projections/sorting'; -import { usePaginatedRules, useDisplayedPaginationOptions } from './projections/pagination'; - -// Why these values? -// If we request more rules than 10000, we'll get an error from Elasticsearch (most likely). -// https://www.elastic.co/guide/en/elasticsearch/reference/current/paginate-search-results.html -// https://www.elastic.co/guide/en/elasticsearch/reference/current/index-modules.html#dynamic-index-settings -// see `index.max_result_window`, default value is 10000. -// Example: -// In requests like `GET my-index/_search?from=40&size=20` it's not about items per page, -// but overall from+size count (requested page + all previous pages). -// If max_result_window=10000 this will fail: `GET my-index/_search?from=9990&size=20`. -// We load "all" rules in memory at once. So, because we always request page=1: -const MAX_RULES_TO_LOAD = 10000; // must not be increased -const NUM_RULES_TO_LOAD = MAX_RULES_TO_LOAD / 2; // must be < MAX_RULES_TO_LOAD const INITIAL_SORT_FIELD = 'enabled'; @@ -84,8 +68,9 @@ export const useRulesTable = (params: UseRulesTableParams): UseRulesTableReturn const reFetchRules = useRef<() => Promise>(() => Promise.resolve()); const [, dispatchToaster] = useStateToaster(); - // Fetch all rules at once (and only once) after mount. Filtering, sorting, - // searching and pagination are implemented in memory on the client side. + const { pagination, filterOptions } = state; + const filterTags = filterOptions.tags.sort().join(); + useEffect(() => { let isSubscribed = true; const abortCtrl = new AbortController(); @@ -95,17 +80,15 @@ export const useRulesTable = (params: UseRulesTableParams): UseRulesTableReturn facade.current.actionStarted('load', []); const fetchRulesResult = await fetchRules({ - filterOptions: initialStateDefaults.filterOptions, - pagination: { - page: 1, - perPage: NUM_RULES_TO_LOAD, - total: -1, - }, + filterOptions, + pagination, signal: abortCtrl.signal, }); if (isSubscribed) { facade.current.setRules(fetchRulesResult.data, { + page: fetchRulesResult.page, + perPage: fetchRulesResult.perPage, total: fetchRulesResult.total, }); } @@ -128,28 +111,21 @@ export const useRulesTable = (params: UseRulesTableParams): UseRulesTableReturn abortCtrl.abort(); }; // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); - - const projections = useProjectedState(state); + }, [ + pagination.page, + pagination.perPage, + filterOptions.filter, + filterOptions.sortField, + filterOptions.sortOrder, + filterTags, + filterOptions.showCustomRules, + filterOptions.showElasticRules, + ]); return { - state: { ...state, ...projections }, + state, dispatch, ...facade.current, reFetchRules: reFetchRules.current, }; }; - -const useProjectedState = (state: RulesTableState): Partial => { - const { rules, filterOptions, pagination } = state; - - const filteredRules = useFilteredRules(rules, filterOptions); - const sortedRules = useSortedRules(filteredRules, filterOptions); - const displayedPagination = useDisplayedPaginationOptions(sortedRules, pagination); - const displayedRules = usePaginatedRules(sortedRules, displayedPagination); - - return { - rules: displayedRules, - pagination: displayedPagination, - }; -};