From 525b3614d2f123fac83a556c6e3c80fc261d8059 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20=C3=81ngel?= Date: Mon, 2 Sep 2019 17:48:56 +0200 Subject: [PATCH] Added missing copyright header --- .../agent/components/export-configuration.js | 11 + .../agent/components/register-agent.js | 11 + public/controllers/agent/components/stats.js | 13 ++ .../controllers/agent/components/welcome.js | 13 ++ public/controllers/agent/index.js | 2 +- public/controllers/dev-tools/index.js | 2 +- public/controllers/index.js | 2 +- .../management/components/reporting-table.js | 12 ++ .../management/components/welcome.js | 12 ++ public/controllers/management/index.js | 2 +- public/controllers/misc/index.js | 2 +- .../overview/components/alerts-stats.js | 12 ++ .../overview/components/requirement-card.js | 12 ++ .../controllers/overview/components/stats.js | 12 ++ .../overview/components/welcome.js | 12 ++ public/controllers/overview/index.js | 2 +- .../settings/components/add-api.js | 12 ++ .../settings/components/api-table.js | 12 ++ public/controllers/settings/index.js | 2 +- public/directives/index.js | 2 +- .../wz-table-eui/components/table.js | 11 + .../directives/wz-tabs-eui/components/tabs.js | 11 + public/factories/index.js | 2 +- public/kibana-integrations/debounce.js | 73 +++++++ .../kibana-integrations/get_painless_error.ts | 46 ++++ .../loader/embedded_visualize_handler.ts | 2 +- .../search-bar/filter-generator.tsx | 93 ++++++++ .../search-bar/filter-manager.tsx | 200 ++++++++++++++++++ .../search-bar/filter-state-manager.tsx | 94 ++++++++ .../search-bar/only_disabled.tsx | 31 +++ .../search-bar/query-filter.ts | 44 ++++ .../kibana-integrations/search-bar/setup.tsx | 99 +++++++++ public/services/index.js | 2 +- public/services/region-maps.js | 2 +- public/services/resolves/index.js | 2 +- 35 files changed, 859 insertions(+), 13 deletions(-) create mode 100644 public/kibana-integrations/debounce.js create mode 100644 public/kibana-integrations/get_painless_error.ts create mode 100644 public/kibana-integrations/search-bar/filter-generator.tsx create mode 100644 public/kibana-integrations/search-bar/filter-manager.tsx create mode 100644 public/kibana-integrations/search-bar/filter-state-manager.tsx create mode 100644 public/kibana-integrations/search-bar/only_disabled.tsx create mode 100644 public/kibana-integrations/search-bar/query-filter.ts create mode 100644 public/kibana-integrations/search-bar/setup.tsx diff --git a/public/controllers/agent/components/export-configuration.js b/public/controllers/agent/components/export-configuration.js index d3ccbab53..a850f77ae 100644 --- a/public/controllers/agent/components/export-configuration.js +++ b/public/controllers/agent/components/export-configuration.js @@ -1,3 +1,14 @@ +/* + * Wazuh app - React component for exporting the configuration of a group. + * Copyright (C) 2015-2019 Wazuh, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Find more information about this on the LICENSE file. + */ import React, { Component } from 'react'; import { diff --git a/public/controllers/agent/components/register-agent.js b/public/controllers/agent/components/register-agent.js index f3b90f27d..d102c1834 100644 --- a/public/controllers/agent/components/register-agent.js +++ b/public/controllers/agent/components/register-agent.js @@ -1,3 +1,14 @@ +/* + * Wazuh app - React component for registering agents. + * Copyright (C) 2015-2019 Wazuh, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Find more information about this on the LICENSE file. + */ import React, { Component, Fragment } from 'react'; import { diff --git a/public/controllers/agent/components/stats.js b/public/controllers/agent/components/stats.js index c2a43bcf7..3f9015751 100644 --- a/public/controllers/agent/components/stats.js +++ b/public/controllers/agent/components/stats.js @@ -1,3 +1,16 @@ +/* + * Wazuh app - React component for showing agent fields such as IP, ID, name, + * version, OS, registration date, last keep alive. + * + * Copyright (C) 2015-2019 Wazuh, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Find more information about this on the LICENSE file. + */ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import { EuiStat, EuiFlexItem, EuiFlexGroup, EuiPanel } from '@elastic/eui'; diff --git a/public/controllers/agent/components/welcome.js b/public/controllers/agent/components/welcome.js index fd2eef9cb..d25fc6bcd 100644 --- a/public/controllers/agent/components/welcome.js +++ b/public/controllers/agent/components/welcome.js @@ -1,3 +1,16 @@ +/* + * Wazuh app - React component building the welcome screen of an agent. + * version, OS, registration date, last keep alive. + * + * Copyright (C) 2015-2019 Wazuh, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Find more information about this on the LICENSE file. + */ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import { diff --git a/public/controllers/agent/index.js b/public/controllers/agent/index.js index 1e771065d..c7d23f8bb 100644 --- a/public/controllers/agent/index.js +++ b/public/controllers/agent/index.js @@ -1,5 +1,5 @@ /* - * Wazuh app - File for app requirements and set up + * Wazuh app - Load the Agent controllers and React components. * Copyright (C) 2015-2019 Wazuh, Inc. * * This program is free software; you can redistribute it and/or modify diff --git a/public/controllers/dev-tools/index.js b/public/controllers/dev-tools/index.js index 2d0665656..f36a98e60 100644 --- a/public/controllers/dev-tools/index.js +++ b/public/controllers/dev-tools/index.js @@ -1,5 +1,5 @@ /* - * Wazuh app - File for app requirements and set up + * Wazuh app - Load the Dev Tools controller. * Copyright (C) 2015-2019 Wazuh, Inc. * * This program is free software; you can redistribute it and/or modify diff --git a/public/controllers/index.js b/public/controllers/index.js index 097565a8b..9ae2620fa 100644 --- a/public/controllers/index.js +++ b/public/controllers/index.js @@ -1,5 +1,5 @@ /* - * Wazuh app - File for app requirements and set up + * Wazuh app - Load all the controllers. * Copyright (C) 2015-2019 Wazuh, Inc. * * This program is free software; you can redistribute it and/or modify diff --git a/public/controllers/management/components/reporting-table.js b/public/controllers/management/components/reporting-table.js index 4a7da59e9..137dde72e 100644 --- a/public/controllers/management/components/reporting-table.js +++ b/public/controllers/management/components/reporting-table.js @@ -1,3 +1,15 @@ +/* + * Wazuh app - React component for building the reports table. + * + * Copyright (C) 2015-2019 Wazuh, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Find more information about this on the LICENSE file. + */ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import { EuiBasicTable, EuiButtonIcon } from '@elastic/eui'; diff --git a/public/controllers/management/components/welcome.js b/public/controllers/management/components/welcome.js index 66b432963..83b7806d9 100644 --- a/public/controllers/management/components/welcome.js +++ b/public/controllers/management/components/welcome.js @@ -1,3 +1,15 @@ +/* + * Wazuh app - React component for building the management welcome screen. + * + * Copyright (C) 2015-2019 Wazuh, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Find more information about this on the LICENSE file. + */ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import { diff --git a/public/controllers/management/index.js b/public/controllers/management/index.js index e2662d9ed..647b19f18 100644 --- a/public/controllers/management/index.js +++ b/public/controllers/management/index.js @@ -1,5 +1,5 @@ /* - * Wazuh app - File for app requirements and set up + * Wazuh app - Load all the Management controllers and related React components. * Copyright (C) 2015-2019 Wazuh, Inc. * * This program is free software; you can redistribute it and/or modify diff --git a/public/controllers/misc/index.js b/public/controllers/misc/index.js index e3139c0cb..7c56d59c2 100644 --- a/public/controllers/misc/index.js +++ b/public/controllers/misc/index.js @@ -1,5 +1,5 @@ /* - * Wazuh app - File for app requirements and set up + * Wazuh app - Load all the Misc controllers. * Copyright (C) 2015-2019 Wazuh, Inc. * * This program is free software; you can redistribute it and/or modify diff --git a/public/controllers/overview/components/alerts-stats.js b/public/controllers/overview/components/alerts-stats.js index b91953c54..dc041c112 100644 --- a/public/controllers/overview/components/alerts-stats.js +++ b/public/controllers/overview/components/alerts-stats.js @@ -1,3 +1,15 @@ +/* + * Wazuh app - React component for alerts stats. + * + * Copyright (C) 2015-2019 Wazuh, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Find more information about this on the LICENSE file. + */ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import { EuiStat, EuiFlexItem, EuiFlexGroup } from '@elastic/eui'; diff --git a/public/controllers/overview/components/requirement-card.js b/public/controllers/overview/components/requirement-card.js index 98374731b..237917eba 100644 --- a/public/controllers/overview/components/requirement-card.js +++ b/public/controllers/overview/components/requirement-card.js @@ -1,3 +1,15 @@ +/* + * Wazuh app - React component for building a card to be used for showing compliance requirements. + * + * Copyright (C) 2015-2019 Wazuh, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Find more information about this on the LICENSE file. + */ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import { diff --git a/public/controllers/overview/components/stats.js b/public/controllers/overview/components/stats.js index da0ea176c..29337ae2e 100644 --- a/public/controllers/overview/components/stats.js +++ b/public/controllers/overview/components/stats.js @@ -1,3 +1,15 @@ +/* + * Wazuh app - React component for showing stats about agents. + * + * Copyright (C) 2015-2019 Wazuh, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Find more information about this on the LICENSE file. + */ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import { EuiStat, EuiFlexItem, EuiFlexGroup } from '@elastic/eui'; diff --git a/public/controllers/overview/components/welcome.js b/public/controllers/overview/components/welcome.js index 36b571f5c..88f62e17c 100644 --- a/public/controllers/overview/components/welcome.js +++ b/public/controllers/overview/components/welcome.js @@ -1,3 +1,15 @@ +/* + * Wazuh app - React component for building the Overview welcome screen. + * + * Copyright (C) 2015-2019 Wazuh, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Find more information about this on the LICENSE file. + */ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import { diff --git a/public/controllers/overview/index.js b/public/controllers/overview/index.js index ac9a51adf..e5c22f7a9 100644 --- a/public/controllers/overview/index.js +++ b/public/controllers/overview/index.js @@ -1,5 +1,5 @@ /* - * Wazuh app - File for app requirements and set up + * Wazuh app - Load all the Overview controllers and related React components. * Copyright (C) 2015-2019 Wazuh, Inc. * * This program is free software; you can redistribute it and/or modify diff --git a/public/controllers/settings/components/add-api.js b/public/controllers/settings/components/add-api.js index 663afdf21..04db6d647 100644 --- a/public/controllers/settings/components/add-api.js +++ b/public/controllers/settings/components/add-api.js @@ -1,3 +1,15 @@ +/* + * Wazuh app - React component for the adding an API entry form. + * + * Copyright (C) 2015-2019 Wazuh, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Find more information about this on the LICENSE file. + */ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import { diff --git a/public/controllers/settings/components/api-table.js b/public/controllers/settings/components/api-table.js index 9cc40182c..a6411db94 100644 --- a/public/controllers/settings/components/api-table.js +++ b/public/controllers/settings/components/api-table.js @@ -1,3 +1,15 @@ +/* + * Wazuh app - React component building the API entries table. + * + * Copyright (C) 2015-2019 Wazuh, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Find more information about this on the LICENSE file. + */ import PropTypes from 'prop-types'; import React, { Component } from 'react'; import { RIGHT_ALIGNMENT } from '@elastic/eui/lib/services'; diff --git a/public/controllers/settings/index.js b/public/controllers/settings/index.js index aa313c943..eb193c6b4 100644 --- a/public/controllers/settings/index.js +++ b/public/controllers/settings/index.js @@ -1,5 +1,5 @@ /* - * Wazuh app - File for app requirements and set up + * Wazuh app - Load the Settings React components. * Copyright (C) 2015-2019 Wazuh, Inc. * * This program is free software; you can redistribute it and/or modify diff --git a/public/directives/index.js b/public/directives/index.js index ef15a29aa..f1b9b3057 100644 --- a/public/directives/index.js +++ b/public/directives/index.js @@ -1,5 +1,5 @@ /* - * Wazuh app - File for app requirements and set up + * Wazuh app - Load all the directives. * Copyright (C) 2015-2019 Wazuh, Inc. * * This program is free software; you can redistribute it and/or modify diff --git a/public/directives/wz-table-eui/components/table.js b/public/directives/wz-table-eui/components/table.js index 2fe8a198c..db94482ac 100644 --- a/public/directives/wz-table-eui/components/table.js +++ b/public/directives/wz-table-eui/components/table.js @@ -1,3 +1,14 @@ +/* + * Wazuh app - React base component for building tables. + * Copyright (C) 2015-2019 Wazuh, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Find more information about this on the LICENSE file. + */ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import { EuiBasicTable } from '@elastic/eui'; diff --git a/public/directives/wz-tabs-eui/components/tabs.js b/public/directives/wz-tabs-eui/components/tabs.js index 3e13bdc45..22bcb39fd 100644 --- a/public/directives/wz-tabs-eui/components/tabs.js +++ b/public/directives/wz-tabs-eui/components/tabs.js @@ -1,3 +1,14 @@ +/* + * Wazuh app - React component for section tabs. + * Copyright (C) 2015-2019 Wazuh, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Find more information about this on the LICENSE file. + */ import React, { Component, Fragment } from 'react'; import PropTypes from 'prop-types'; import { EuiTabs, EuiTab } from '@elastic/eui'; diff --git a/public/factories/index.js b/public/factories/index.js index 31918b3dd..cfdcc640b 100644 --- a/public/factories/index.js +++ b/public/factories/index.js @@ -1,5 +1,5 @@ /* - * Wazuh app - File for app requirements and set up + * Wazuh app - Load all the Angular.js factories. * Copyright (C) 2015-2019 Wazuh, Inc. * * This program is free software; you can redistribute it and/or modify diff --git a/public/kibana-integrations/debounce.js b/public/kibana-integrations/debounce.js new file mode 100644 index 000000000..d8e3b0233 --- /dev/null +++ b/public/kibana-integrations/debounce.js @@ -0,0 +1,73 @@ +/* + * Author: Elasticsearch B.V. + * Updated by Wazuh, Inc. + * + * Copyright (C) 2015-2019 Wazuh, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Find more information about this on the LICENSE file. + */ + +import _ from 'lodash'; +import { uiModules } from 'ui/modules'; +// Debounce service, angularized version of lodash debounce +// borrowed heavily from https://github.com/shahata/angular-debounce + +const module = uiModules.get('app/wazuh'); + +module.service('debounce', [ + '$timeout', + function($timeout) { + return function(func, wait, options) { + let timeout; + let args; + let self; + let result; + options = _.defaults(options || {}, { + leading: false, + trailing: true, + invokeApply: true + }); + + function debounce() { + self = this; + args = arguments; + + const later = function() { + timeout = null; + if (!options.leading || options.trailing) { + result = func.apply(self, args); + } + }; + + const callNow = options.leading && !timeout; + + if (timeout) { + $timeout.cancel(timeout); + } + timeout = $timeout(later, wait, options.invokeApply); + + if (callNow) { + result = func.apply(self, args); + } + + return result; + } + + debounce.cancel = function() { + $timeout.cancel(timeout); + timeout = null; + }; + + return debounce; + }; + } +]); + +export function DebounceProvider(debounce) { + return debounce; +} diff --git a/public/kibana-integrations/get_painless_error.ts b/public/kibana-integrations/get_painless_error.ts new file mode 100644 index 000000000..97900bdeb --- /dev/null +++ b/public/kibana-integrations/get_painless_error.ts @@ -0,0 +1,46 @@ +/* + * Author: Elasticsearch B.V. + * Updated by Wazuh, Inc. + * + * Copyright (C) 2015-2019 Wazuh, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Find more information about this on the LICENSE file. + */ + +import { i18n } from '@kbn/i18n'; +import { get } from 'lodash'; + +export function getPainlessError(error: Error) { + const rootCause: Array<{ lang: string; script: string }> | undefined = get( + error, + 'resp.error.root_cause' + ); + + if (!rootCause) { + return; + } + + const [{ lang, script }] = rootCause; + + if (lang !== 'painless') { + return; + } + + return { + lang, + script, + message: i18n.translate( + 'kbn.discover.painlessError.painlessScriptedFieldErrorMessage', + { + defaultMessage: "Error with Painless scripted field '{script}'.", + values: { script } + } + ), + error: error.message + }; +} diff --git a/public/kibana-integrations/loader/embedded_visualize_handler.ts b/public/kibana-integrations/loader/embedded_visualize_handler.ts index f117d9b1a..155c47803 100644 --- a/public/kibana-integrations/loader/embedded_visualize_handler.ts +++ b/public/kibana-integrations/loader/embedded_visualize_handler.ts @@ -159,7 +159,7 @@ export class EmbeddedVisualizeHandler { timefilter.on('autoRefreshFetch', this.reload); } - // This is a hack to give maps visualizations access to data in the + // This is a workaround to give maps visualizations access to data in the // globalState, since they can no longer access it via searchSource. // TODO: Remove this as a part of elastic/kibana#30593 this.vis.API.getGeohashBounds = () => { diff --git a/public/kibana-integrations/search-bar/filter-generator.tsx b/public/kibana-integrations/search-bar/filter-generator.tsx new file mode 100644 index 000000000..d754d21d9 --- /dev/null +++ b/public/kibana-integrations/search-bar/filter-generator.tsx @@ -0,0 +1,93 @@ +/* + * Author: Elasticsearch B.V. + * Updated by Wazuh, Inc. + * + * Copyright (C) 2015-2019 Wazuh, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Find more information about this on the LICENSE file. + */ + +import _ from 'lodash'; +import { getPhraseScript } from '@kbn/es-query'; + +// Adds a filter to a passed state +export function getFilterGenerator(queryFilter) { + const filterGen = {}; + + filterGen.generate = (field, values, operation, index) => { + values = Array.isArray(values) ? values : [values]; + const fieldName = _.isObject(field) ? field.name : field; + const filters = _.flatten([queryFilter.getAppFilters()]); + const newFilters = []; + + const negate = (operation === '-'); + + // TODO: On array fields, negating does not negate the combination, rather all terms + _.each(values, function (value) { + let filter; + const existing = _.find(filters, function (filter) { + if (!filter) return; + + if (fieldName === '_exists_' && filter.exists) { + return filter.exists.field === value; + } + + if (_.has(filter, 'query.match')) { + return filter.query.match[fieldName] && filter.query.match[fieldName].query === value; + } + + if (filter.script) { + return filter.meta.field === fieldName && filter.script.script.params.value === value; + } + }); + + if (existing) { + existing.meta.disabled = false; + if (existing.meta.negate !== negate) { + existing.meta.negate = !existing.meta.negate; + } + newFilters.push(existing); + return; + } + + switch (fieldName) { + case '_exists_': + filter = { + meta: { negate, index }, + exists: { + field: value + } + }; + break; + default: + if (field.scripted) { + filter = { + meta: { negate, index, field: fieldName }, + script: getPhraseScript(field, value) + }; + } else { + filter = { meta: { negate, index }, query: { match: {} } }; + filter.query.match[fieldName] = { query: value, type: 'phrase' }; + } + + break; + } + + newFilters.push(filter); + }); + + return newFilters; + }; + + filterGen.add = function (field, values, operation, index) { + const newFilters = this.generate(field, values, operation, index); + return queryFilter.addFilters(newFilters); + }; + + return filterGen; +} \ No newline at end of file diff --git a/public/kibana-integrations/search-bar/filter-manager.tsx b/public/kibana-integrations/search-bar/filter-manager.tsx new file mode 100644 index 000000000..60090cfb1 --- /dev/null +++ b/public/kibana-integrations/search-bar/filter-manager.tsx @@ -0,0 +1,200 @@ +/* + * Author: Elasticsearch B.V. + * Updated by Wazuh, Inc. + * + * Copyright (C) 2015-2019 Wazuh, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Find more information about this on the LICENSE file. + */ +import { Filter, isFilterPinned, FilterStateStore } from '@kbn/es-query'; + +import _ from 'lodash'; +import { Subject } from 'rxjs'; + +import { npSetup } from 'ui/new_platform'; + +// @ts-ignore +import { compareFilters } from 'plugins/data/filter/filter_manager/lib/compare_filters'; +// @ts-ignore +import { mapAndFlattenFilters } from 'plugins/data/filter/filter_manager/lib/map_and_flatten_filters'; +// @ts-ignore +import { uniqFilters } from 'plugins/data/filter/filter_manager/lib/uniq_filters'; +// @ts-ignore +import { extractTimeFilter } from 'plugins/data/filter/filter_manager/lib/extract_time_filter'; +// @ts-ignore +import { changeTimeFilter } from 'plugins/data/filter/filter_manager/lib/change_time_filter'; + +import { onlyDisabledFiltersChanged } from './only_disabled'; + +import { PartitionedFilters } from 'plugins/data/filter/filter_manager/partitioned_filters'; + +import { IndexPatterns } from 'plugins/data/index_patterns'; + +export class FilterManager { + private indexPatterns: IndexPatterns; + private filters: Filter[] = []; + private updated$: Subject = new Subject(); + private fetch$: Subject = new Subject(); + + constructor(indexPatterns: IndexPatterns) { + this.indexPatterns = indexPatterns; + } + + private mergeIncomingFilters(partitionedFilters: PartitionedFilters): Filter[] { + const globalFilters = partitionedFilters.globalFilters; + const appFilters = partitionedFilters.appFilters; + + // existing globalFilters should be mutated by appFilters + _.each(appFilters, function (filter, i) { + const match = _.find(globalFilters, function (globalFilter) { + return compareFilters(globalFilter, filter); + }); + + // no match, do nothing + if (!match) return; + + // matching filter in globalState, update global and remove from appState + _.assign(match.meta, filter.meta); + appFilters.splice(i, 1); + }); + + return FilterManager.mergeFilters(appFilters, globalFilters); + } + + private static mergeFilters(appFilters: Filter[], globalFilters: Filter[]): Filter[] { + return uniqFilters(appFilters.reverse().concat(globalFilters.reverse())).reverse(); + } + + private static partitionFilters(filters: Filter[]): PartitionedFilters { + const [globalFilters, appFilters] = _.partition(filters, isFilterPinned); + return { + globalFilters, + appFilters, + }; + } + + private handleStateUpdate(newFilters: Filter[]) { + // global filters should always be first + newFilters.sort(({ $state: a }: Filter, { $state: b }: Filter): number => { + return a!.store === FilterStateStore.GLOBAL_STATE && + b!.store !== FilterStateStore.GLOBAL_STATE + ? -1 + : 1; + }); + + const filtersUpdated = !_.isEqual(this.filters, newFilters); + const updatedOnlyDisabledFilters = onlyDisabledFiltersChanged(newFilters, this.filters); + + this.filters = newFilters; + if (filtersUpdated) { + this.updated$.next(); + if (!updatedOnlyDisabledFilters) { + this.fetch$.next(); + } + } + } + + /* Getters */ + + public getFilters() { + return _.cloneDeep(this.filters); + } + + public getAppFilters() { + const { appFilters } = this.getPartitionedFilters(); + return appFilters; + } + + public getGlobalFilters() { + const { globalFilters } = this.getPartitionedFilters(); + return globalFilters; + } + + public getPartitionedFilters(): PartitionedFilters { + return FilterManager.partitionFilters(this.getFilters()); + } + + public getUpdates$() { + return this.updated$.asObservable(); + } + + public getFetches$() { + return this.fetch$.asObservable(); + } + + /* Setters */ + + public async addFilters(filters: Filter[] | Filter, pinFilterStatus?: boolean) { + if (!Array.isArray(filters)) { + filters = [filters]; + } + + if (filters.length === 0) { + return; + } + + const { uiSettings } = npSetup.core; + if (pinFilterStatus === undefined) { + pinFilterStatus = uiSettings.get('filters:pinnedByDefault'); + } + + // Set the store of all filters. For now. + // In the future, all filters should come in with filter state store already set. + const store = pinFilterStatus ? FilterStateStore.GLOBAL_STATE : FilterStateStore.APP_STATE; + FilterManager.setFiltersStore(filters, store); + + const mappedFilters = await mapAndFlattenFilters(this.indexPatterns, filters); + + // This is where we add new filters to the correct place (app \ global) + const newPartitionedFilters = FilterManager.partitionFilters(mappedFilters); + const currentFilters = this.getPartitionedFilters(); + currentFilters.appFilters.push(...newPartitionedFilters.appFilters); + currentFilters.globalFilters.push(...newPartitionedFilters.globalFilters); + + const newFilters = this.mergeIncomingFilters(currentFilters); + this.handleStateUpdate(newFilters); + } + + public async setFilters(newFilters: Filter[]) { + const mappedFilters = await mapAndFlattenFilters(this.indexPatterns, newFilters); + const newPartitionedFilters = FilterManager.partitionFilters(mappedFilters); + const mergedFilters = this.mergeIncomingFilters(newPartitionedFilters); + this.handleStateUpdate(mergedFilters); + } + + public removeFilter(filter: Filter) { + const filterIndex = _.findIndex(this.filters, item => { + return _.isEqual(item.meta, filter.meta) && _.isEqual(item.query, filter.query); + }); + + if (filterIndex >= 0) { + const newFilters = _.cloneDeep(this.filters); + newFilters.splice(filterIndex, 1); + this.handleStateUpdate(newFilters); + } + } + + public async removeAll() { + await this.setFilters([]); + } + + public async addFiltersAndChangeTimeFilter(filters: Filter[]) { + const timeFilter = await extractTimeFilter(this.indexPatterns, filters); + if (timeFilter) changeTimeFilter(timeFilter); + return this.addFilters(filters.filter(filter => filter !== timeFilter)); + } + + public static setFiltersStore(filters: Filter[], store: FilterStateStore) { + _.map(filters, (filter: Filter) => { + // Override status only for filters that didn't have state in the first place. + if (filter.$state === undefined) { + filter.$state = { store }; + } + }); + } +} \ No newline at end of file diff --git a/public/kibana-integrations/search-bar/filter-state-manager.tsx b/public/kibana-integrations/search-bar/filter-state-manager.tsx new file mode 100644 index 000000000..31c27f289 --- /dev/null +++ b/public/kibana-integrations/search-bar/filter-state-manager.tsx @@ -0,0 +1,94 @@ +/* + * Author: Elasticsearch B.V. + * Updated by Wazuh, Inc. + * + * Copyright (C) 2015-2019 Wazuh, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Find more information about this on the LICENSE file. + */ + +import { FilterStateStore } from '@kbn/es-query'; + +import _ from 'lodash'; +import { State } from 'ui/state_management/state'; +import { FilterManager } from './filter-manager'; + +type GetAppStateFunc = () => State | undefined | null; + +/** + * FilterStateManager is responsible for watching for filter changes + * and syncing with FilterManager, as well as syncing FilterManager changes + * back to the URL. + **/ +export class FilterStateManager { + filterManager: FilterManager; + globalState: State; + getAppState: GetAppStateFunc; + interval: NodeJS.Timeout | undefined; + + constructor(globalState: State, getAppState: GetAppStateFunc, filterManager: FilterManager) { + this.getAppState = getAppState; + this.globalState = globalState; + this.filterManager = filterManager; + + this.watchFilterState(); + + this.filterManager.getUpdates$().subscribe(() => { + this.updateAppState(); + }); + } + + destroy() { + if (this.interval) { + clearInterval(this.interval); + } + } + + private watchFilterState() { + // This is a temporary solution to remove rootscope. + // Moving forward, state should provide observable subscriptions. + this.interval = setInterval(() => { + const appState = this.getAppState(); + const stateUndefined = !appState || !this.globalState; + if (stateUndefined) return; + + const globalFilters = this.globalState.filters || []; + const appFilters = (appState && appState.filters) || []; + + const globalFilterChanged = !_.isEqual(this.filterManager.getGlobalFilters(), globalFilters); + const appFilterChanged = !_.isEqual(this.filterManager.getAppFilters(), appFilters); + const filterStateChanged = globalFilterChanged || appFilterChanged; + + if (!filterStateChanged) return; + + const newGlobalFilters = _.cloneDeep(globalFilters); + const newAppFilters = _.cloneDeep(appFilters); + FilterManager.setFiltersStore(newAppFilters, FilterStateStore.APP_STATE); + FilterManager.setFiltersStore(newGlobalFilters, FilterStateStore.GLOBAL_STATE); + + this.filterManager.setFilters(newGlobalFilters.concat(newAppFilters)); + }, 10); + } + + private saveState() { + const appState = this.getAppState(); + if (appState) appState.save(); + this.globalState.save(); + } + + private updateAppState() { + // Update Angular state before saving State objects (which save it to URL) + const partitionedFilters = this.filterManager.getPartitionedFilters(); + const appState = this.getAppState(); + if (appState) { + appState.filters = partitionedFilters.appFilters; + } + this.globalState.filters = partitionedFilters.globalFilters; + this.saveState(); + } +} \ No newline at end of file diff --git a/public/kibana-integrations/search-bar/only_disabled.tsx b/public/kibana-integrations/search-bar/only_disabled.tsx new file mode 100644 index 000000000..4e4186bfa --- /dev/null +++ b/public/kibana-integrations/search-bar/only_disabled.tsx @@ -0,0 +1,31 @@ +/* + * Author: Elasticsearch B.V. + * Updated by Wazuh, Inc. + * + * Copyright (C) 2015-2019 Wazuh, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Find more information about this on the LICENSE file. + */ + +import _ from 'lodash'; +import { Filter } from '@kbn/es-query'; + +const isEnabled = function(filter: Filter) { + return filter && filter.meta && !filter.meta.disabled; +}; +/** + * Checks to see if only disabled filters have been changed + * @returns {bool} Only disabled filters + */ +export function onlyDisabledFiltersChanged(newFilters: Filter[], oldFilters: Filter[]) { + // If it's the same - compare only enabled filters + const newEnabledFilters = _.filter(newFilters, isEnabled); + const oldEnabledFilters = _.filter(oldFilters, isEnabled); + + return _.isEqual(oldEnabledFilters, newEnabledFilters); +} \ No newline at end of file diff --git a/public/kibana-integrations/search-bar/query-filter.ts b/public/kibana-integrations/search-bar/query-filter.ts new file mode 100644 index 000000000..795a73840 --- /dev/null +++ b/public/kibana-integrations/search-bar/query-filter.ts @@ -0,0 +1,44 @@ +/* + * Author: Elasticsearch B.V. + * Updated by Wazuh, Inc. + * + * Copyright (C) 2015-2019 Wazuh, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Find more information about this on the LICENSE file. + */ + +import { FilterStateManager } from './filter-state-manager'; +import { DataPlugin } from './setup'; + +export function FilterBarQueryFilterProvider(getAppState, globalState) { + // TODO: this is imported here to avoid circular imports. + // eslint-disable-next-line @typescript-eslint/no-var-requires + + const data = new DataPlugin().setup(); + const filterManager = data.filter.filterManager; + const filterStateManager = new FilterStateManager(globalState, getAppState, filterManager); + + const queryFilter = {}; + queryFilter.getUpdates$ = filterManager.getUpdates$.bind(filterManager); + queryFilter.getFetches$ = filterManager.getFetches$.bind(filterManager); + queryFilter.getFilters = filterManager.getFilters.bind(filterManager); + queryFilter.getAppFilters = filterManager.getAppFilters.bind(filterManager); + queryFilter.getGlobalFilters = filterManager.getGlobalFilters.bind(filterManager); + queryFilter.removeFilter = filterManager.removeFilter.bind(filterManager); + queryFilter.addFilters = filterManager.addFilters.bind(filterManager); + queryFilter.setFilters = filterManager.setFilters.bind(filterManager); + queryFilter.addFiltersAndChangeTimeFilter = filterManager.addFiltersAndChangeTimeFilter.bind(filterManager); + queryFilter.removeAll = filterManager.removeAll.bind(filterManager); + + queryFilter.destroy = () => { + filterManager.destroy(); + filterStateManager.destroy(); + }; + + return queryFilter; +} \ No newline at end of file diff --git a/public/kibana-integrations/search-bar/setup.tsx b/public/kibana-integrations/search-bar/setup.tsx new file mode 100644 index 000000000..b402ec690 --- /dev/null +++ b/public/kibana-integrations/search-bar/setup.tsx @@ -0,0 +1,99 @@ +/* + * Author: Elasticsearch B.V. + * Updated by Wazuh, Inc. + * + * Copyright (C) 2015-2019 Wazuh, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Find more information about this on the LICENSE file. + */ + +// TODO these are imports from the old plugin world. +// Once the new platform is ready, they can get removed +// and handled by the platform itself in the setup method +// of the ExpressionExectorService +// @ts-ignore +import { renderersRegistry } from 'plugins/interpreter/registries'; +import { ExpressionsService, ExpressionsSetup } from 'plugins/data/expressions'; +import { QueryService, QuerySetup } from 'plugins/data/query'; +import { FilterService, FilterSetup } from 'plugins/data/filter'; +import { IndexPatternsService, IndexPatternsSetup } from 'plugins/data/index_patterns'; + +export class DataPlugin { + // Exposed services, sorted alphabetically + private readonly expressions: ExpressionsService; + private readonly filter: FilterService; + private readonly indexPatterns: IndexPatternsService; + private readonly query: QueryService; + + constructor() { + this.indexPatterns = new IndexPatternsService(); + this.filter = new FilterService(); + this.query = new QueryService(); + this.expressions = new ExpressionsService(); + } + + public setup(): DataSetup { + // TODO: this is imported here to avoid circular imports. + // eslint-disable-next-line @typescript-eslint/no-var-requires + const { getInterpreter } = require('plugins/interpreter/interpreter'); + const indexPatternsService = this.indexPatterns.setup(); + return { + expressions: this.expressions.setup({ + interpreter: { + getInterpreter, + renderersRegistry, + }, + }), + indexPatterns: indexPatternsService, + filter: this.filter.setup({ + indexPatterns: indexPatternsService.indexPatterns, + }), + query: this.query.setup(), + }; + } + + public stop() { + this.expressions.stop(); + this.indexPatterns.stop(); + this.filter.stop(); + this.query.stop(); + } +} + +/** @public */ +export interface DataSetup { + expressions: ExpressionsSetup; + indexPatterns: IndexPatternsSetup; + filter: FilterSetup; + query: QuerySetup; +} + +/** @public types */ +export { ExpressionRenderer, ExpressionRendererProps, ExpressionRunner } from 'plugins/data/expressions'; + +/** @public types */ +export { IndexPattern, StaticIndexPattern, StaticIndexPatternField, Field } from 'plugins/data/index_patterns'; +export { Query, QueryBar } from 'plugins/data/query'; +export { FilterBar } from 'plugins/data/filter'; +export { + FilterManager, + FilterStateManager, + uniqFilters, + onlyDisabledFiltersChanged, +} from './filter-manager'; + +/** @public static code */ +export { dateHistogramInterval } from 'plugins/data/filter/../../common/date_histogram_interval'; +/** @public static code */ +export { + isValidEsInterval, + InvalidEsCalendarIntervalError, + InvalidEsIntervalFormatError, + parseEsInterval, + ParsedInterval, +} from 'plugins/data/filter/../../common/parse_es_interval'; \ No newline at end of file diff --git a/public/services/index.js b/public/services/index.js index f8ea4ca1e..defd1f467 100644 --- a/public/services/index.js +++ b/public/services/index.js @@ -1,5 +1,5 @@ /* - * Wazuh app - File for app requirements and set up + * Wazuh app - Load all the Angular.js services. * Copyright (C) 2015-2019 Wazuh, Inc. * * This program is free software; you can redistribute it and/or modify diff --git a/public/services/region-maps.js b/public/services/region-maps.js index 5065d17f2..23117aee4 100644 --- a/public/services/region-maps.js +++ b/public/services/region-maps.js @@ -1,5 +1,5 @@ /* - * Wazuh app - Makes null the region maps (temporary hack in order to make it work) + * Wazuh app - Makes null the region maps (temporary fix in order to make it work) * Copyright (C) 2015-2019 Wazuh, Inc. * * This program is free software; you can redistribute it and/or modify diff --git a/public/services/resolves/index.js b/public/services/resolves/index.js index 8180a7204..c6e7d72e1 100644 --- a/public/services/resolves/index.js +++ b/public/services/resolves/index.js @@ -1,5 +1,5 @@ /* - * Wazuh app - File for app requirements and set up + * Wazuh app - Load all the "resolve" functions. * Copyright (C) 2015-2019 Wazuh, Inc. * * This program is free software; you can redistribute it and/or modify