[Endpoint][SIEM] Adjust types related to subplugin's redux (#67768) (#68249)

This commit is contained in:
Robert Austin 2020-06-04 11:55:35 -04:00 committed by GitHub
parent e46beca751
commit 2ca71b1ced
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
59 changed files with 440 additions and 410 deletions

View file

@ -15,28 +15,9 @@ import {
AlertEvent,
KbnConfigSchemaInputTypeOf,
AppLocation,
Immutable,
} from '../endpoint/types';
/**
* A deep readonly type that will make all children of a given object readonly recursively
*/
export type Immutable<T> = T extends undefined | null | boolean | string | number
? T
: unknown extends T
? unknown
: T extends Array<infer U>
? ImmutableArray<U>
: T extends Map<infer K, infer V>
? ImmutableMap<K, V>
: T extends Set<infer M>
? ImmutableSet<M>
: ImmutableObject<T>;
type ImmutableArray<T> = ReadonlyArray<Immutable<T>>;
type ImmutableMap<K, V> = ReadonlyMap<Immutable<K>, Immutable<V>>;
type ImmutableSet<T> = ReadonlySet<Immutable<T>>;
type ImmutableObject<T> = { readonly [K in keyof T]: Immutable<T[K]> };
/**
* Values for the Alert APIs 'order' and 'direction' parameters.
*/

View file

@ -4,17 +4,20 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { Reducer, AnyAction, Middleware, Dispatch } from 'redux';
import {
Reducer,
AnyAction,
Middleware,
Dispatch,
PreloadedState,
StateFromReducersMapObject,
CombinedState,
} from 'redux';
import { NavTab } from '../common/components/navigation/types';
import { HostsState } from '../hosts/store';
import { NetworkState } from '../network/store';
import { TimelineState } from '../timelines/store/timeline/types';
import { ImmutableReducer, State } from '../common/store';
import { State, SubPluginsInitReducer } from '../common/store';
import { Immutable } from '../../common/endpoint/types';
import { AlertListState } from '../../common/endpoint_alerts/types';
import { AppAction } from '../common/store/actions';
import { HostState } from '../endpoint_hosts/types';
import { ManagementState } from '../management/store/types';
export enum SiemPageName {
overview = 'overview',
@ -38,7 +41,7 @@ export type SiemNavTabKey =
export type SiemNavTab = Record<SiemNavTabKey, NavTab>;
export interface SecuritySubPluginStore<K extends SecuritySubPluginKeyStore, T> {
initialState: Record<K, T>;
initialState: Record<K, T | undefined>;
reducer: Record<K, Reducer<T, AnyAction>>;
middleware?: Array<Middleware<{}, State, Dispatch<AppAction | Immutable<AppAction>>>>;
}
@ -54,6 +57,10 @@ type SecuritySubPluginKeyStore =
| 'hostList'
| 'alertList'
| 'management';
/**
* Returned by the various 'SecuritySubPlugin' classes from the `start` method.
*/
export interface SecuritySubPluginWithStore<K extends SecuritySubPluginKeyStore, T>
extends SecuritySubPlugin {
store: SecuritySubPluginStore<K, T>;
@ -61,22 +68,17 @@ export interface SecuritySubPluginWithStore<K extends SecuritySubPluginKeyStore,
export interface SecuritySubPlugins extends SecuritySubPlugin {
store: {
initialState: {
hosts: HostsState;
network: NetworkState;
timeline: TimelineState;
alertList: Immutable<AlertListState>;
hostList: Immutable<HostState>;
management: ManagementState;
};
reducer: {
hosts: Reducer<HostsState, AnyAction>;
network: Reducer<NetworkState, AnyAction>;
timeline: Reducer<TimelineState, AnyAction>;
alertList: ImmutableReducer<AlertListState, AppAction>;
hostList: ImmutableReducer<HostState, AppAction>;
management: ImmutableReducer<ManagementState, AppAction>;
};
initialState: PreloadedState<
CombinedState<
StateFromReducersMapObject<
/** SubPluginsInitReducer, being an interface, will not work in `StateFromReducersMapObject`.
* Picking its keys does the trick.
**/
Pick<SubPluginsInitReducer, keyof SubPluginsInitReducer>
>
>
>;
reducer: SubPluginsInitReducer;
middlewares: Array<Middleware<{}, State, Dispatch<AppAction | Immutable<AppAction>>>>;
};
}

View file

@ -15,7 +15,7 @@ import { BrowserFields } from '../../containers/source';
import { dragAndDropModel, dragAndDropSelectors } from '../../store';
import { timelineSelectors } from '../../../timelines/store/timeline';
import { IdToDataProvider } from '../../store/drag_and_drop/model';
import { State } from '../../store/reducer';
import { State } from '../../store/types';
import { DataProvider } from '../../../timelines/components/timeline/data_providers/data_provider';
import { reArrangeProviders } from '../../../timelines/components/timeline/data_providers/helpers';
import { ACTIVE_TIMELINE_REDUX_ID } from '../top_n';

View file

@ -12,7 +12,7 @@ import { apolloClientObservable, mockGlobalState, SUB_PLUGINS_REDUCER } from '..
import { createStore } from '../../store/store';
import { ErrorToastDispatcher } from '.';
import { State } from '../../store/reducer';
import { State } from '../../store/types';
describe('Error Toast Dispatcher', () => {
const state: State = mockGlobalState;

View file

@ -15,10 +15,10 @@ import { depsStartMock } from './dependencies_start_mock';
import { MiddlewareActionSpyHelper, createSpyMiddleware } from '../../store/test_utils';
import { apolloClientObservable } from '../test_providers';
import { createStore, State, substateMiddlewareFactory } from '../../store';
import { hostMiddlewareFactory } from '../../../endpoint_hosts/store';
import { alertMiddlewareFactory } from '../../../endpoint_alerts/store/middleware';
import { AppRootProvider } from './app_root_provider';
import { managementMiddlewareFactory } from '../../../management/store';
import { managementMiddlewareFactory } from '../../../management/store/middleware';
import { hostMiddlewareFactory } from '../../../endpoint_hosts/store/middleware';
import { SUB_PLUGINS_REDUCER, mockGlobalState } from '..';
type UiRender = (ui: React.ReactElement, options?: RenderOptions) => RenderResult;
@ -56,8 +56,7 @@ export const createAppRootMockRenderer = (): AppContextTestRender => {
const coreStart = coreMock.createStart({ basePath: '/mock' });
const depsStart = depsStartMock();
const middlewareSpy = createSpyMiddleware();
const state: State = mockGlobalState;
const store = createStore(state, SUB_PLUGINS_REDUCER, apolloClientObservable, [
const store = createStore(mockGlobalState, SUB_PLUGINS_REDUCER, apolloClientObservable, [
substateMiddlewareFactory(
(globalState) => globalState.hostList,
hostMiddlewareFactory(coreStart, depsStart)
@ -76,7 +75,6 @@ export const createAppRootMockRenderer = (): AppContextTestRender => {
</AppRootProvider>
);
const render: UiRender = (ui, options) => {
// @ts-ignore
return reactRender(ui, {
wrapper: AppWrapper as React.ComponentType,
...options,

View file

@ -27,11 +27,10 @@ import { networkModel } from '../../network/store';
import { TimelineType, TimelineStatus } from '../../../common/types/timeline';
import { initialAlertListState } from '../../endpoint_alerts/store/reducer';
import { initialHostListState } from '../../endpoint_hosts/store/reducer';
import { getManagementInitialState } from '../../management/store';
const alertList = initialAlertListState();
const hostList = initialHostListState();
const management = getManagementInitialState();
import { mockManagementState } from '../../management/store/reducer';
import { AlertListState } from '../../../common/endpoint_alerts/types';
import { HostState } from '../../endpoint_hosts/types';
import { ManagementState } from '../../management/types';
export const mockGlobalState: State = {
app: {
@ -233,7 +232,11 @@ export const mockGlobalState: State = {
},
},
},
alertList,
hostList,
management,
/**
* These state's are wrapped in `Immutable`, but for compatibility with the overall app architecture,
* they are cast to mutable versions here.
*/
alertList: initialAlertListState as AlertListState,
hostList: initialHostListState as HostState,
management: mockManagementState as ManagementState,
};

View file

@ -7,9 +7,13 @@
import { hostsReducer } from '../../hosts/store';
import { networkReducer } from '../../network/store';
import { timelineReducer } from '../../timelines/store/timeline/reducer';
import { hostListReducer } from '../../endpoint_hosts/store';
import { alertListReducer } from '../../endpoint_alerts/store';
import { managementReducer } from '../../management/store';
import { managementReducer } from '../../management/store/reducer';
import { ManagementPluginReducer } from '../../management';
import { SubPluginsInitReducer } from '../store';
import { EndpointAlertsPluginReducer } from '../../endpoint_alerts';
import { EndpointHostsPluginReducer } from '../../endpoint_hosts';
import { alertListReducer } from '../../endpoint_alerts/store/reducer';
import { hostListReducer } from '../../endpoint_hosts/store/reducer';
interface Global extends NodeJS.Global {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
@ -18,11 +22,15 @@ interface Global extends NodeJS.Global {
export const globalNode: Global = global;
export const SUB_PLUGINS_REDUCER = {
export const SUB_PLUGINS_REDUCER: SubPluginsInitReducer = {
hosts: hostsReducer,
network: networkReducer,
timeline: timelineReducer,
hostList: hostListReducer,
alertList: alertListReducer,
management: managementReducer,
/**
* These state's are wrapped in `Immutable`, but for compatibility with the overall app architecture,
* they are cast to mutable versions here.
*/
hostList: hostListReducer as EndpointHostsPluginReducer['hostList'],
alertList: alertListReducer as EndpointAlertsPluginReducer['alertList'],
management: managementReducer as ManagementPluginReducer['management'],
};

View file

@ -7,11 +7,9 @@
import { keys } from 'lodash/fp';
import memoizeOne from 'memoize-one';
import { createSelector } from 'reselect';
import { Note } from '../../lib/note';
import { State } from '../reducer';
import { ErrorModel, NotesById } from './model';
import { State } from '../types';
const selectNotesById = (state: State): NotesById => state.app.notesById;

View file

@ -5,10 +5,8 @@
*/
import { createSelector } from 'reselect';
import { State } from '../reducer';
import { IdToDataProvider } from './model';
import { State } from '../types';
const selectDataProviders = (state: State): IdToDataProvider => state.dragAndDrop.dataProviders;

View file

@ -8,18 +8,46 @@ export * from './model';
export * from './reducer';
export * from './selectors';
import { Middleware, Dispatch } from 'redux';
import { createStore, getStore } from './store';
import { SubstateMiddlewareFactory } from './types';
import { ImmutableMiddleware, State } from './types';
import { AppAction } from './actions';
import { Immutable } from '../../../common/endpoint/types';
export { createStore, getStore };
export const substateMiddlewareFactory: SubstateMiddlewareFactory = (selector, middleware) => {
/**
* Takes a selector and an `ImmutableMiddleware`. The
* middleware's version of `getState` will receive
* the result of the selector instead of the global state.
*
* This allows middleware to have knowledge of only a subsection of state.
*
* `selector` returns an `Immutable` version of the substate.
* `middleware` must be an `ImmutableMiddleware`.
*
* Returns a regular middleware, meant to be used with `applyMiddleware`.
*/
export const substateMiddlewareFactory = <Substate = never>(
selector: (state: State) => Substate | Immutable<Substate>,
middleware: ImmutableMiddleware<Substate, AppAction>
): Middleware<{}, State, Dispatch<AppAction | Immutable<AppAction>>> => {
return (api) => {
const substateAPI = {
...api,
// Return just the substate instead of global state.
getState() {
return selector(api.getState());
// Return the substate instead of global state.
getState(): Immutable<Substate> {
/**
* The selector will receive the basic (mutable) version of state. This is because
* the top level state shape doesn't use `Immutable`. We cast the return value as `Immutable`
* so that the middleware won't be able to mutate state.
*
* Immutable enforces nothing structural about a type so casting
* a value as `Immutable` is safe as long as nothing else is going to mutate.
* Since the state came from the return value of a reducer, the reducer will (hopefully)
* not be mutating it.
*/
return selector(api.getState()) as Immutable<Substate>;
},
};
return middleware(substateAPI);

View file

@ -6,7 +6,7 @@
import { createSelector } from 'reselect';
import { State } from '../reducer';
import { State } from '../types';
import { InputsModel, InputsRange, GlobalQuery } from './model';

View file

@ -4,47 +4,22 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { combineReducers } from 'redux';
import { combineReducers, PreloadedState, AnyAction, Reducer } from 'redux';
import { appReducer, AppState, initialAppState } from './app';
import { dragAndDropReducer, DragAndDropState, initialDragAndDropState } from './drag_and_drop';
import { createInitialInputsState, initialInputsState, inputsReducer, InputsState } from './inputs';
import { appReducer, initialAppState } from './app';
import { dragAndDropReducer, initialDragAndDropState } from './drag_and_drop';
import { createInitialInputsState, inputsReducer } from './inputs';
import { HostsPluginState, HostsPluginReducer } from '../../hosts/store';
import { NetworkPluginState, NetworkPluginReducer } from '../../network/store';
import { TimelinePluginState, TimelinePluginReducer } from '../../timelines/store/timeline';
import {
EndpointAlertsPluginState,
EndpointAlertsPluginReducer,
} from '../../endpoint_alerts/store';
import { EndpointHostsPluginState, EndpointHostsPluginReducer } from '../../endpoint_hosts/store';
import { HostsPluginReducer } from '../../hosts/store';
import { NetworkPluginReducer } from '../../network/store';
import { TimelinePluginReducer } from '../../timelines/store/timeline';
import { ManagementPluginReducer, ManagementPluginState } from '../../management/store/types';
export interface State
extends HostsPluginState,
NetworkPluginState,
TimelinePluginState,
EndpointAlertsPluginState,
EndpointHostsPluginState,
ManagementPluginState {
app: AppState;
dragAndDrop: DragAndDropState;
inputs: InputsState;
}
export const initialState: Pick<State, 'app' | 'dragAndDrop' | 'inputs'> = {
app: initialAppState,
dragAndDrop: initialDragAndDropState,
inputs: initialInputsState,
};
type SubPluginsInitState = HostsPluginState &
NetworkPluginState &
TimelinePluginState &
EndpointAlertsPluginState &
EndpointHostsPluginState &
ManagementPluginState;
import { SecuritySubPlugins } from '../../app/types';
import { ManagementPluginReducer } from '../../management';
import { EndpointAlertsPluginReducer } from '../../endpoint_alerts';
import { EndpointHostsPluginReducer } from '../../endpoint_hosts';
import { State } from './types';
import { AppAction } from './actions';
export type SubPluginsInitReducer = HostsPluginReducer &
NetworkPluginReducer &
@ -53,14 +28,28 @@ export type SubPluginsInitReducer = HostsPluginReducer &
EndpointHostsPluginReducer &
ManagementPluginReducer;
export const createInitialState = (pluginsInitState: SubPluginsInitState): State => ({
...initialState,
...pluginsInitState,
inputs: createInitialInputsState(),
});
/**
* Factory for the 'initialState' that is used to preload state into the Security App's redux store.
*/
export const createInitialState = (
pluginsInitState: SecuritySubPlugins['store']['initialState']
): PreloadedState<State> => {
const preloadedState: PreloadedState<State> = {
app: initialAppState,
dragAndDrop: initialDragAndDropState,
...pluginsInitState,
inputs: createInitialInputsState(),
};
return preloadedState;
};
export const createReducer = (pluginsReducer: SubPluginsInitReducer) =>
combineReducers<State>({
/**
* Factory for the Security app's redux reducer.
*/
export const createReducer: (
pluginsReducer: SubPluginsInitReducer
) => Reducer<State, AppAction | AnyAction> = (pluginsReducer: SubPluginsInitReducer) =>
combineReducers({
app: appReducer,
dragAndDrop: dragAndDropReducer,
inputs: inputsReducer,

View file

@ -12,6 +12,7 @@ import {
Store,
Middleware,
Dispatch,
PreloadedState,
} from 'redux';
import { createEpicMiddleware } from 'redux-observable';
@ -21,11 +22,12 @@ import { telemetryMiddleware } from '../lib/telemetry';
import { appSelectors } from './app';
import { timelineSelectors } from '../../timelines/store/timeline';
import { inputsSelectors } from './inputs';
import { State, SubPluginsInitReducer, createReducer } from './reducer';
import { SubPluginsInitReducer, createReducer } from './reducer';
import { createRootEpic } from './epic';
import { AppApolloClient } from '../lib/lib';
import { AppAction } from './actions';
import { Immutable } from '../../../common/endpoint/types';
import { State } from './types';
type ComposeType = typeof compose;
declare global {
@ -33,10 +35,17 @@ declare global {
__REDUX_DEVTOOLS_EXTENSION_COMPOSE__: ComposeType;
}
}
/**
* The Redux store type for the Security app.
*/
export type SecurityAppStore = Store<State, Action>;
let store: Store<State, Action> | null = null;
export { SubPluginsInitReducer };
/**
* Factory for Security App's redux store.
*/
export const createStore = (
state: State,
state: PreloadedState<State>,
pluginsReducer: SubPluginsInitReducer,
apolloClient: Observable<AppApolloClient>,
additionalMiddleware?: Array<Middleware<{}, State, Dispatch<AppAction | Immutable<AppAction>>>>

View file

@ -5,9 +5,8 @@
*/
import { Dispatch } from 'redux';
import { State } from './reducer';
import { State, ImmutableMiddlewareFactory } from './types';
import { AppAction } from './actions';
import { ImmutableMiddlewareFactory } from './types';
/**
* Utilities for testing Redux middleware

View file

@ -4,19 +4,40 @@
* you may not use this file except in compliance with the Elastic License.
*/
import {
Dispatch,
Action as ReduxAction,
AnyAction as ReduxAnyAction,
Action,
Middleware,
} from 'redux';
import { Dispatch, Action, Middleware, CombinedState } from 'redux';
import { CoreStart } from '../../../../../../src/core/public';
import { Immutable } from '../../../common/endpoint_alerts/types';
import { State } from './reducer';
import { StartPlugins } from '../../types';
import { AppAction } from './actions';
import { Immutable } from '../../../common/endpoint/types';
import { AppState } from './app/reducer';
import { InputsState } from './inputs/reducer';
import { HostsPluginState } from '../../hosts/store';
import { DragAndDropState } from './drag_and_drop/reducer';
import { TimelinePluginState } from '../../timelines/store/timeline';
import { NetworkPluginState } from '../../network/store';
import { EndpointAlertsPluginState } from '../../endpoint_alerts';
import { EndpointHostsPluginState } from '../../endpoint_hosts';
import { ManagementPluginState } from '../../management';
/**
* The redux `State` type for the Security App.
* We use `CombinedState` to wrap our shape because we create our reducer using `combineReducers`.
* `combineReducers` returns a type wrapped in `CombinedState`.
* `CombinedState` is required for redux to know what keys to make optional when preloaded state into a store.
*/
export type State = CombinedState<
HostsPluginState &
NetworkPluginState &
TimelinePluginState &
EndpointAlertsPluginState &
EndpointHostsPluginState &
ManagementPluginState & {
app: AppState;
dragAndDrop: DragAndDropState;
inputs: InputsState;
}
>;
export type KueryFilterQueryKind = 'kuery' | 'lucene';
@ -67,60 +88,73 @@ export type ImmutableMiddlewareFactory<S = State> = (
* Middleware will be of the `ImmutableMiddleware` variety. Not able to directly
* change actions or state.
*/
export type ImmutableMultipleMiddlewareFactory<S = State> = (
export type SecuritySubPluginMiddlewareFactory = (
coreStart: CoreStart,
depsStart: Pick<StartPlugins, 'data' | 'ingestManager'>
) => Array<ImmutableMiddleware<S, AppAction>>;
/**
* Simple type for a redux selector.
*/
type Selector<S, R> = (state: S) => R;
/**
* Takes a selector and an `ImmutableMiddleware`. The
* middleware's version of `getState` will receive
* the result of the selector instead of the global state.
*
* This allows middleware to have knowledge of only a subsection of state.
*
* `selector` returns an `Immutable` version of the substate.
* `middleware` must be an `ImmutableMiddleware`.
*
* Returns a regular middleware, meant to be used with `applyMiddleware`.
*/
export type SubstateMiddlewareFactory = <Substate>(
selector: Selector<State, Immutable<Substate>>,
middleware: ImmutableMiddleware<Substate, AppAction>
) => Middleware<{}, State, Dispatch<AppAction | Immutable<AppAction>>>;
) => Array<Middleware<{}, State, Dispatch<AppAction | Immutable<AppAction>>>>;
/**
* Like `Reducer` from `redux` but it accepts immutable versions of `state` and `action`.
* Use this type for all Reducers in order to help enforce our pattern of immutable state.
*/
export type ImmutableReducer<State, Action> = (
state: Immutable<State> | undefined,
action: Immutable<Action>
) => State | Immutable<State>;
export type ImmutableReducer<S, A> = (
state: Immutable<S> | undefined,
action: Immutable<A>
) => S | Immutable<S>;
/**
* A alternate interface for `redux`'s `combineReducers`. Will work with the same underlying implementation,
* but will enforce that `Immutable` versions of `state` and `action` are received.
*/
export type ImmutableCombineReducers = <S, A extends ReduxAction = ReduxAnyAction>(
reducers: ImmutableReducersMapObject<S, A>
) => ImmutableReducer<S, A>;
export type ImmutableCombineReducers = <M extends ImmutableReducersMapObject<unknown, never>>(
reducers: M
) => ImmutableReducer<
CombinedState<StateFromImmutableReducersMapObject<M>>,
ActionFromImmutableReducersMapObject<M>
>;
/**
* Helper type for `ImmutableCombineReducers`. Infers the combined state type from an immutable reducer map.
*/
type StateFromImmutableReducersMapObject<M> = M extends ImmutableReducersMapObject<unknown, never>
? { [P in keyof M]: M[P] extends ImmutableReducer<infer S, infer _A> ? S : never }
: never;
/**
* Helper type for `ImmutableCombineReducers`. Infers the combined action type from an immutable reducer map.
*/
type ActionFromImmutableReducersMapObject<M> = M extends ImmutableReducersMapObject<unknown, never>
? ActionFromImmutableReducer<ImmutableReducerFromImmutableReducersMapObject<M>>
: never;
/**
* Helper type for `ImmutableCombineReducers`. Infers the combined reducer type from an immutable reducer map.
*/
type ImmutableReducerFromImmutableReducersMapObject<M> = M extends {
[P in keyof M]: infer R;
}
? R extends ImmutableReducer<infer _S, infer _A>
? R
: never
: never;
/**
* Helper type for `ImmutableCombineReducers`. Infers the action type for an immutable reducer.
*/
type ActionFromImmutableReducer<R> = R extends ImmutableReducer<infer _S, infer A> ? A : never;
/**
* Helper type for `ImmutableCombineReducers`.
* Like `redux`'s `ReducersMapObject` (which is used by `combineReducers`) but enforces that
* the `state` and `action` received are `Immutable` versions.
*/
type ImmutableReducersMapObject<S, A extends ReduxAction = ReduxAction> = {
type ImmutableReducersMapObject<S, A extends Action = Action> = {
[K in keyof S]: ImmutableReducer<S[K], A>;
};
/**
* A better type for createStructuredSelector. This doesn't support the options object.
* https://github.com/reduxjs/reselect/pull/454
*/
export type CreateStructuredSelector = <
SelectorMap extends { [key: string]: (...args: never[]) => unknown }

View file

@ -4,9 +4,8 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { Immutable } from '../../../common/endpoint_alerts/types';
import { HttpFetchQuery } from '../../../../../../src/core/public';
import { Immutable } from '../../../common/endpoint/types';
export function cloneHttpFetchQuery(query: Immutable<HttpFetchQuery>): HttpFetchQuery {
const clone: HttpFetchQuery = {};

View file

@ -4,15 +4,32 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { Reducer } from 'redux';
import { SecuritySubPluginWithStore } from '../app/types';
import { getEndpointAlertsRoutes } from './routes';
import { Immutable } from '../../common/endpoint/types';
import { initialAlertListState, alertListReducer } from './store/reducer';
import { endpointAlertsRoutes } from './routes';
import { alertListReducer } from './store/reducer';
import { AlertListState } from '../../common/endpoint_alerts/types';
import { alertMiddlewareFactory } from './store/middleware';
import { substateMiddlewareFactory } from '../common/store';
import { CoreStart } from '../../../../../src/core/public';
import { StartPlugins } from '../types';
import { AppAction } from '../common/store/actions';
/**
* Internally, our state is sometimes immutable, ignore that in our external
* interface.
*/
export interface EndpointAlertsPluginState {
alertList: AlertListState;
}
/**
* Internally, we use `ImmutableReducer`, but we present a regular reducer
* externally for compatibility w/ regular redux.
*/
export interface EndpointAlertsPluginReducer {
alertList: Reducer<AlertListState, AppAction>;
}
export class EndpointAlerts {
public setup() {}
@ -20,20 +37,24 @@ export class EndpointAlerts {
public start(
core: CoreStart,
plugins: StartPlugins
): SecuritySubPluginWithStore<'alertList', Immutable<AlertListState>> {
): SecuritySubPluginWithStore<'alertList', AlertListState> {
const { data, ingestManager } = plugins;
const middleware = [
substateMiddlewareFactory(
substateMiddlewareFactory<AlertListState>(
(globalState) => globalState.alertList,
alertMiddlewareFactory(core, { data, ingestManager })
),
];
return {
routes: getEndpointAlertsRoutes(),
routes: endpointAlertsRoutes(),
store: {
initialState: { alertList: initialAlertListState() },
reducer: { alertList: alertListReducer },
initialState: { alertList: undefined },
/**
* Cast the ImmutableReducer to a regular reducer for compatibility with
* the subplugin architecture (which expects plain redux reducers.)
*/
reducer: { alertList: alertListReducer } as EndpointAlertsPluginReducer,
middleware,
},
};

View file

@ -6,7 +6,7 @@
import { all } from 'deepmerge';
import { IIndexPattern } from 'src/plugins/data/public';
import { Immutable } from '../../../common/endpoint_alerts/types';
import { Immutable } from '../../../common/endpoint/types';
/**
* Model for the `IIndexPattern` interface exported by the `data` plugin.

View file

@ -9,7 +9,7 @@ import { Route } from 'react-router-dom';
import { AlertIndex } from './view';
export const getEndpointAlertsRoutes = () => [
export const endpointAlertsRoutes = () => [
<Route path="/:pageName(endpoint-alerts)">
<AlertIndex />
</Route>,

View file

@ -5,8 +5,8 @@
*/
import { IIndexPattern } from 'src/plugins/data/public';
// import { Immutable } from '../../../common/types';
import { AlertDetails, AlertListData, Immutable } from '../../../common/endpoint_alerts/types';
import { Immutable } from '../../../common/endpoint/types';
import { AlertDetails, AlertListData } from '../../../common/endpoint_alerts/types';
interface ServerReturnedAlertsData {
readonly type: 'serverReturnedAlertsData';

View file

@ -8,7 +8,7 @@ import { Store, createStore, applyMiddleware } from 'redux';
import { createBrowserHistory, History } from 'history';
import { coreMock } from '../../../../../../src/core/public/mocks';
import { AlertListState, Immutable } from '../../../common/endpoint_alerts/types';
import { AlertListState } from '../../../common/endpoint_alerts/types';
import { depsStartMock, DepsStartMock } from '../../common/mock/endpoint';
import { alertListReducer } from './reducer';
@ -16,6 +16,7 @@ import { alertListReducer } from './reducer';
import { alertMiddlewareFactory } from './middleware';
import { mockAlertResultList } from './mock_alert_result_list';
import { Immutable } from '../../../common/endpoint/types';
describe('alert details tests', () => {
let store: Store;

View file

@ -7,12 +7,13 @@
import { Store, createStore, applyMiddleware } from 'redux';
import { History, createBrowserHistory } from 'history';
import { alertListReducer } from './reducer';
import { AlertListState, AlertResultList, Immutable } from '../../../common/endpoint_alerts/types';
import { AlertListState, AlertResultList } from '../../../common/endpoint_alerts/types';
import { alertMiddlewareFactory } from './middleware';
import { coreMock } from 'src/core/public/mocks';
import { DepsStartMock, depsStartMock } from '../../common/mock/endpoint';
import { isOnAlertPage } from './selectors';
import { mockAlertResultList } from './mock_alert_result_list';
import { Immutable } from '../../../common/endpoint/types';
describe('alert list tests', () => {
let store: Store;

View file

@ -1,20 +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;
* you may not use this file except in compliance with the Elastic License.
*/
import { AlertListState, Immutable } from '../../../common/endpoint_alerts/types';
import { ImmutableReducer } from '../../common/store';
import { AppAction } from '../../common/store/actions';
export { alertListReducer } from './reducer';
export { AlertAction } from './action';
export interface EndpointAlertsPluginState {
alertList: Immutable<AlertListState>;
}
export interface EndpointAlertsPluginReducer {
alertList: ImmutableReducer<AlertListState, AppAction>;
}

View file

@ -20,9 +20,8 @@ import {
uiQueryParams,
isAlertPageTabChange,
} from './selectors';
import { Immutable } from '../../../common/endpoint/types';
export const alertMiddlewareFactory: ImmutableMiddlewareFactory<Immutable<AlertListState>> = (
export const alertMiddlewareFactory: ImmutableMiddlewareFactory<AlertListState> = (
coreStart,
depsStart
) => {

View file

@ -4,26 +4,25 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { Immutable, AlertListState } from '../../../common/endpoint_alerts/types';
import { Immutable } from '../../../common/endpoint/types';
import { AlertListState } from '../../../common/endpoint_alerts/types';
import { ImmutableReducer } from '../../common/store';
import { AppAction } from '../../common/store/actions';
export const initialAlertListState = (): Immutable<AlertListState> => {
return {
alerts: [],
alertDetails: undefined,
pageSize: 10,
pageIndex: 0,
total: 0,
location: undefined,
searchBar: {
patterns: [],
},
};
export const initialAlertListState: Immutable<AlertListState> = {
alerts: [],
alertDetails: undefined,
pageSize: 10,
pageIndex: 0,
total: 0,
location: undefined,
searchBar: {
patterns: [],
},
};
export const alertListReducer: ImmutableReducer<AlertListState, AppAction> = (
state = initialAlertListState(),
state = initialAlertListState,
action
) => {
if (action.type === 'serverReturnedAlertsData') {

View file

@ -12,10 +12,10 @@ import {
} from 'reselect';
import { encode, decode } from 'rison-node';
import { Immutable } from '../../../common/endpoint/types';
import { Query, TimeRange, Filter } from '../../../../../../src/plugins/data/public';
import {
Immutable,
AlertingIndexGetQueryInput,
AlertListState,
AlertingIndexUIQueryParams,

View file

@ -11,7 +11,7 @@ import { Store } from 'redux';
import { mockAlertDetailsResult } from '../store/mock_alert_result_list';
import { alertPageTestRender } from './test_helpers/render_alert_page';
import { AppAction } from '../../common/store/actions';
import { State } from '../../common/store/reducer';
import { State } from '../../common/store/types';
describe('when the alert details flyout is open', () => {
let render: () => reactTestingLibrary.RenderResult;

View file

@ -6,7 +6,8 @@
import React, { memo, useMemo } from 'react';
import { i18n } from '@kbn/i18n';
import { EuiAccordion, EuiDescriptionList } from '@elastic/eui';
import { Immutable, AlertData } from '../../../../../common/endpoint_alerts/types';
import { Immutable } from '../../../../../common/endpoint/types';
import { AlertData } from '../../../../../common/endpoint_alerts/types';
import { FormattedDate } from '../../formatted_date';
export const FileAccordion = memo(({ alertData }: { alertData: Immutable<AlertData> }) => {

View file

@ -6,8 +6,9 @@
import React, { memo, useMemo } from 'react';
import { i18n } from '@kbn/i18n';
import { EuiAccordion, EuiDescriptionList } from '@elastic/eui';
import { Immutable, AlertData } from '../../../../../common/endpoint_alerts/types';
import { AlertData } from '../../../../../common/endpoint_alerts/types';
import { FormattedDate } from '../../formatted_date';
import { Immutable } from '../../../../../common/endpoint/types';
export const GeneralAccordion = memo(({ alertData }: { alertData: Immutable<AlertData> }) => {
const columns = useMemo(() => {

View file

@ -6,7 +6,8 @@
import React, { memo, useMemo } from 'react';
import { i18n } from '@kbn/i18n';
import { EuiAccordion, EuiDescriptionList } from '@elastic/eui';
import { Immutable, AlertData } from '../../../../../common/endpoint_alerts/types';
import { Immutable } from '../../../../../common/endpoint/types';
import { AlertData } from '../../../../../common/endpoint_alerts/types';
export const HashAccordion = memo(({ alertData }: { alertData: Immutable<AlertData> }) => {
const columns = useMemo(() => {

View file

@ -8,7 +8,8 @@ import { i18n } from '@kbn/i18n';
import { EuiAccordion, EuiDescriptionList, EuiHealth } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
import { Immutable, AlertDetails } from '../../../../../common/endpoint_alerts/types';
import { Immutable } from '../../../../../common/endpoint/types';
import { AlertDetails } from '../../../../../common/endpoint_alerts/types';
export const HostAccordion = memo(({ alertData }: { alertData: Immutable<AlertDetails> }) => {
const columns = useMemo(() => {

View file

@ -6,7 +6,8 @@
import React, { memo, useMemo } from 'react';
import { i18n } from '@kbn/i18n';
import { EuiAccordion, EuiDescriptionList } from '@elastic/eui';
import { Immutable, AlertData } from '../../../../../common/endpoint_alerts/types';
import { Immutable } from '../../../../../common/endpoint/types';
import { AlertData } from '../../../../../common/endpoint_alerts/types';
export const SourceProcessAccordion = memo(({ alertData }: { alertData: Immutable<AlertData> }) => {
const columns = useMemo(() => {

View file

@ -6,7 +6,8 @@
import React, { memo, useMemo } from 'react';
import { i18n } from '@kbn/i18n';
import { EuiAccordion, EuiDescriptionList } from '@elastic/eui';
import { Immutable, AlertData } from '../../../../../common/endpoint_alerts/types';
import { Immutable } from '../../../../../common/endpoint/types';
import { AlertData } from '../../../../../common/endpoint_alerts/types';
export const SourceProcessTokenAccordion = memo(
({ alertData }: { alertData: Immutable<AlertData> }) => {

View file

@ -5,8 +5,9 @@
*/
import { useSelector } from 'react-redux';
import { Immutable, AlertListState } from '../../../../common/endpoint_alerts/types';
import { State } from '../../../common/store/reducer';
import { Immutable } from '../../../../common/endpoint/types';
import { AlertListState } from '../../../../common/endpoint_alerts/types';
import { State } from '../../../common/store/types';
export function useAlertListSelector<TSelected>(
selector: (

View file

@ -12,7 +12,7 @@ import { Store } from 'redux';
import { mockAlertResultList } from '../store/mock_alert_result_list';
import { alertPageTestRender } from './test_helpers/render_alert_page';
import { DepsStartMock } from '../../common/mock/endpoint';
import { State } from '../../common/store/reducer';
import { State } from '../../common/store/types';
import { AppAction } from '../../common/store/actions';
describe('when on the alerting page', () => {

View file

@ -4,15 +4,32 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { Reducer } from 'redux';
import { SecuritySubPluginWithStore } from '../app/types';
import { getEndpointHostsRoutes } from './routes';
import { initialHostListState, hostListReducer } from './store/reducer';
import { Immutable } from '../../common/endpoint/types';
import { endpointHostsRoutes } from './routes';
import { hostListReducer } from './store/reducer';
import { HostState } from './types';
import { hostMiddlewareFactory } from './store/middleware';
import { CoreStart } from '../../../../../src/core/public';
import { StartPlugins } from '../types';
import { substateMiddlewareFactory } from '../common/store';
import { AppAction } from '../common/store/actions';
/**
* Internally, our state is sometimes immutable, ignore that in our external
* interface.
*/
export interface EndpointHostsPluginState {
hostList: HostState;
}
/**
* Internally, we use `ImmutableReducer`, but we present a regular reducer
* externally for compatibility w/ regular redux.
*/
export interface EndpointHostsPluginReducer {
hostList: Reducer<HostState, AppAction>;
}
export class EndpointHosts {
public setup() {}
@ -20,7 +37,7 @@ export class EndpointHosts {
public start(
core: CoreStart,
plugins: StartPlugins
): SecuritySubPluginWithStore<'hostList', Immutable<HostState>> {
): SecuritySubPluginWithStore<'hostList', HostState> {
const { data, ingestManager } = plugins;
const middleware = [
substateMiddlewareFactory(
@ -29,10 +46,14 @@ export class EndpointHosts {
),
];
return {
routes: getEndpointHostsRoutes(),
routes: endpointHostsRoutes(),
store: {
initialState: { hostList: initialHostListState() },
reducer: { hostList: hostListReducer },
initialState: { hostList: undefined },
/**
* Cast the ImmutableReducer to a regular reducer for compatibility with
* the subplugin architecture (which expects plain redux reducers.)
*/
reducer: { hostList: hostListReducer } as EndpointHostsPluginReducer,
middleware,
},
};

View file

@ -9,7 +9,7 @@ import { Route } from 'react-router-dom';
import { HostList } from './view';
export const getEndpointHostsRoutes = () => [
export const endpointHostsRoutes = () => [
<Route path="/:pageName(endpoint-hosts)">
<HostList />
</Route>,

View file

@ -5,10 +5,11 @@
*/
import { createStore, Dispatch, Store } from 'redux';
import { HostAction, hostListReducer } from './index';
import { HostState } from '../types';
import { listData } from './selectors';
import { mockHostResultList } from './mock_host_result_list';
import { HostAction } from './action';
import { hostListReducer } from './reducer';
describe('HostList store concerns', () => {
let store: Store<HostState>;

View file

@ -1,22 +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;
* you may not use this file except in compliance with the Elastic License.
*/
import { HostState } from '../types';
import { ImmutableReducer } from '../../common/store';
import { AppAction } from '../../common/store/actions';
import { Immutable } from '../../../common/endpoint/types';
export { hostListReducer } from './reducer';
export { HostAction } from './action';
export { hostMiddlewareFactory } from './middleware';
export interface EndpointHostsPluginState {
hostList: Immutable<HostState>;
}
export interface EndpointHostsPluginReducer {
hostList: ImmutableReducer<HostState, AppAction>;
}

View file

@ -7,7 +7,6 @@ import { CoreStart, HttpSetup } from 'kibana/public';
import { applyMiddleware, createStore, Store } from 'redux';
import { coreMock } from '../../../../../../src/core/public/mocks';
import { History, createBrowserHistory } from 'history';
import { hostListReducer, hostMiddlewareFactory } from './index';
import { DepsStartMock, depsStartMock } from '../../common/mock/endpoint';
@ -17,6 +16,8 @@ import { AppAction } from '../../common/store/actions';
import { mockHostResultList } from './mock_host_result_list';
import { listData } from './selectors';
import { HostState } from '../types';
import { hostListReducer } from './reducer';
import { hostMiddlewareFactory } from './middleware';
describe('host list middleware', () => {
let fakeCoreStart: jest.Mocked<CoreStart>;

View file

@ -4,14 +4,12 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { HostResultList, Immutable } from '../../../common/endpoint/types';
import { HostResultList } from '../../../common/endpoint/types';
import { ImmutableMiddlewareFactory } from '../../common/store';
import { isOnHostPage, hasSelectedHost, uiQueryParams, listData } from './selectors';
import { HostState } from '../types';
export const hostMiddlewareFactory: ImmutableMiddlewareFactory<Immutable<HostState>> = (
coreStart
) => {
export const hostMiddlewareFactory: ImmutableMiddlewareFactory<HostState> = (coreStart) => {
return ({ getState, dispatch }) => (next) => async (action) => {
next(action);
const state = getState();

View file

@ -10,26 +10,24 @@ import { AppAction } from '../../common/store/actions';
import { ImmutableReducer } from '../../common/store';
import { Immutable } from '../../../common/endpoint/types';
export const initialHostListState = (): HostState => {
return {
hosts: [],
pageSize: 10,
pageIndex: 0,
total: 0,
loading: false,
error: undefined,
details: undefined,
detailsLoading: false,
detailsError: undefined,
policyResponse: undefined,
policyResponseLoading: false,
policyResponseError: undefined,
location: undefined,
};
export const initialHostListState: Immutable<HostState> = {
hosts: [],
pageSize: 10,
pageIndex: 0,
total: 0,
loading: false,
error: undefined,
details: undefined,
detailsLoading: false,
detailsError: undefined,
policyResponse: undefined,
policyResponseLoading: false,
policyResponseError: undefined,
location: undefined,
};
export const hostListReducer: ImmutableReducer<HostState, AppAction> = (
state = initialHostListState(),
state = initialHostListState,
action
) => {
if (action.type === 'serverReturnedHostList') {

View file

@ -8,7 +8,7 @@ import { useSelector } from 'react-redux';
import { useMemo } from 'react';
import { HostState } from '../types';
import { useKibana } from '../../../../../../src/plugins/kibana_react/public';
import { State } from '../../common/store/reducer';
import { State } from '../../common/store/types';
export function useHostSelector<TSelected>(selector: (state: HostState) => TSelected) {
return useSelector(function (state: State) {

View file

@ -7,7 +7,7 @@
import { get } from 'lodash/fp';
import { createSelector } from 'reselect';
import { State } from '../../common/store/reducer';
import { State } from '../../common/store/types';
import { GenericHostsModel, HostsType, HostsTableType } from './model';

View file

@ -5,33 +5,53 @@
*/
import { CoreStart } from 'kibana/public';
import { managementReducer, getManagementInitialState, managementMiddlewareFactory } from './store';
import { getManagementRoutes } from './routes';
import { Reducer, CombinedState } from 'redux';
import { managementRoutes } from './routes';
import { StartPlugins } from '../types';
import { MANAGEMENT_STORE_GLOBAL_NAMESPACE } from './common/constants';
import { SecuritySubPluginWithStore } from '../app/types';
import { Immutable } from '../../common/endpoint/types';
import { ManagementStoreGlobalNamespace } from './types';
import { ManagementState } from './store/types';
import { managementReducer } from './store/reducer';
import { AppAction } from '../common/store/actions';
import { managementMiddlewareFactory } from './store/middleware';
import { ManagementState } from './types';
export { getManagementUrl } from './common/routing';
/**
* Internally, our state is sometimes immutable, ignore that in our external
* interface.
*/
export interface ManagementPluginState {
management: ManagementState;
}
/**
* Internally, we use `ImmutableReducer`, but we present a regular reducer
* externally for compatibility w/ regular redux.
*/
export interface ManagementPluginReducer {
management: Reducer<CombinedState<ManagementState>, AppAction>;
}
export class Management {
public setup() {}
public start(
core: CoreStart,
plugins: StartPlugins
): SecuritySubPluginWithStore<ManagementStoreGlobalNamespace, Immutable<ManagementState>> {
): SecuritySubPluginWithStore<'management', ManagementState> {
return {
routes: getManagementRoutes(),
routes: managementRoutes(),
store: {
initialState: {
[MANAGEMENT_STORE_GLOBAL_NAMESPACE]: getManagementInitialState(),
management: undefined,
},
/**
* Cast the ImmutableReducer to a regular reducer for compatibility with
* the subplugin architecture (which expects plain redux reducers.)
*/
reducer: {
[MANAGEMENT_STORE_GLOBAL_NAMESPACE]: managementReducer,
},
management: managementReducer,
} as ManagementPluginReducer,
middleware: managementMiddlewareFactory(core, plugins),
},
};

View file

@ -16,13 +16,13 @@ import {
sendGetFleetAgentStatusForConfig,
sendPutDatasource,
} from '../policy_list/services/ingest';
import { NewPolicyData, PolicyData, Immutable } from '../../../../../../common/endpoint/types';
import { NewPolicyData, PolicyData } from '../../../../../../common/endpoint/types';
import { factory as policyConfigFactory } from '../../../../../../common/endpoint/models/policy_config';
import { ImmutableMiddlewareFactory } from '../../../../../common/store';
export const policyDetailsMiddlewareFactory: ImmutableMiddlewareFactory<Immutable<
PolicyDetailsState
>> = (coreStart) => {
export const policyDetailsMiddlewareFactory: ImmutableMiddlewareFactory<PolicyDetailsState> = (
coreStart
) => {
const http = coreStart.http;
return ({ getState, dispatch }) => (next) => async (action) => {

View file

@ -4,24 +4,25 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { fullPolicy, isOnPolicyDetailsPage } from './selectors';
import { PolicyDetailsState } from '../../types';
import { Immutable, PolicyConfig, UIPolicyConfig } from '../../../../../../common/endpoint/types';
import { ImmutableReducer } from '../../../../../common/store';
import { AppAction } from '../../../../../common/store/actions';
import { PolicyDetailsState } from '../../types';
export const initialPolicyDetailsState = (): PolicyDetailsState => {
return {
policyItem: undefined,
isLoading: false,
agentStatusSummary: {
error: 0,
events: 0,
offline: 0,
online: 0,
total: 0,
},
};
};
/**
* Return a fresh copy of initial state, since we mutate state in the reducer.
*/
export const initialPolicyDetailsState: () => Immutable<PolicyDetailsState> = () => ({
policyItem: undefined,
isLoading: false,
agentStatusSummary: {
error: 0,
events: 0,
offline: 0,
online: 0,
total: 0,
},
});
export const policyDetailsReducer: ImmutableReducer<PolicyDetailsState, AppAction> = (
state = initialPolicyDetailsState(),

View file

@ -10,7 +10,7 @@ import { Store, applyMiddleware, createStore } from 'redux';
import { coreMock } from '../../../../../../../../../src/core/public/mocks';
import { DATASOURCE_SAVED_OBJECT_TYPE } from '../../../../../../../ingest_manager/common';
import { policyListReducer, initialPolicyListState } from './reducer';
import { policyListReducer } from './reducer';
import { policyListMiddlewareFactory } from './middleware';
import { isOnPolicyListPage, selectIsLoading, urlSearchParams } from './selectors';
@ -39,7 +39,7 @@ describe('policy list store concerns', () => {
store = createStore(
policyListReducer,
initialPolicyListState(),
undefined,
applyMiddleware(policyListMiddlewareFactory(fakeCoreStart, depsStart), actionSpyMiddleware)
);
});

View file

@ -8,10 +8,9 @@ import { GetPolicyListResponse, PolicyListState } from '../../types';
import { sendGetEndpointSpecificDatasources } from './services/ingest';
import { isOnPolicyListPage, urlSearchParams } from './selectors';
import { ImmutableMiddlewareFactory } from '../../../../../common/store';
import { Immutable } from '../../../../../../common/endpoint/types';
import { initialPolicyListState } from './reducer';
export const policyListMiddlewareFactory: ImmutableMiddlewareFactory<Immutable<PolicyListState>> = (
export const policyListMiddlewareFactory: ImmutableMiddlewareFactory<PolicyListState> = (
coreStart
) => {
const http = coreStart.http;
@ -20,7 +19,6 @@ export const policyListMiddlewareFactory: ImmutableMiddlewareFactory<Immutable<P
next(action);
const state = getState();
const initialState = initialPolicyListState();
if (action.type === 'userChangedUrl' && isOnPolicyListPage(state)) {
const { page_index: pageIndex, page_size: pageSize } = urlSearchParams(state);
let response: GetPolicyListResponse;
@ -43,10 +41,10 @@ export const policyListMiddlewareFactory: ImmutableMiddlewareFactory<Immutable<P
dispatch({
type: 'serverReturnedPolicyListData',
payload: {
policyItems: response ? response.items : initialState.policyItems,
policyItems: response ? response.items : initialPolicyListState().policyItems,
pageIndex,
pageSize,
total: response ? response.total : initialState.total,
total: response ? response.total : initialPolicyListState().total,
},
});
}

View file

@ -4,23 +4,25 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { PolicyListState } from '../../types';
import { isOnPolicyListPage } from './selectors';
import { ImmutableReducer } from '../../../../../common/store';
import { AppAction } from '../../../../../common/store/actions';
import { Immutable } from '../../../../../../common/endpoint/types';
import { PolicyListState } from '../../types';
export const initialPolicyListState = (): PolicyListState => {
return {
policyItems: [],
isLoading: false,
apiError: undefined,
pageIndex: 0,
pageSize: 10,
total: 0,
location: undefined,
};
};
/**
* Return the initial state.
* In case `state` was mutated, we return a fresh initial state object.
*/
export const initialPolicyListState: () => Immutable<PolicyListState> = () => ({
policyItems: [],
isLoading: false,
apiError: undefined,
pageIndex: 0,
pageSize: 10,
total: 0,
location: undefined,
});
export const policyListReducer: ImmutableReducer<PolicyListState, AppAction> = (
state = initialPolicyListState(),

View file

@ -12,7 +12,7 @@ import { MANAGEMENT_ROUTING_ROOT_PATH } from './common/constants';
/**
* Returns the React Router Routes for the management area
*/
export const getManagementRoutes = () => [
export const managementRoutes = () => [
// Mounts the Management interface on `/management`
<Route path={MANAGEMENT_ROUTING_ROOT_PATH} component={ManagementContainer} />,
];

View file

@ -1,8 +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;
* you may not use this file except in compliance with the Elastic License.
*/
export { managementReducer, getManagementInitialState } from './reducer';
export { managementMiddlewareFactory } from './middleware';

View file

@ -4,30 +4,23 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { ImmutableMultipleMiddlewareFactory, substateMiddlewareFactory } from '../../common/store';
import {
substateMiddlewareFactory,
SecuritySubPluginMiddlewareFactory,
State,
} from '../../common/store';
import { policyListMiddlewareFactory } from '../pages/policy/store/policy_list';
import { policyDetailsMiddlewareFactory } from '../pages/policy/store/policy_details';
import {
MANAGEMENT_STORE_GLOBAL_NAMESPACE,
MANAGEMENT_STORE_POLICY_DETAILS_NAMESPACE,
MANAGEMENT_STORE_POLICY_LIST_NAMESPACE,
} from '../common/constants';
// @ts-ignore
export const managementMiddlewareFactory: ImmutableMultipleMiddlewareFactory = (
export const managementMiddlewareFactory: SecuritySubPluginMiddlewareFactory = (
coreStart,
depsStart
) => {
const listSelector = (state: State) => state.management.policyList;
const detailSelector = (state: State) => state.management.policyDetails;
return [
substateMiddlewareFactory(
(globalState) =>
globalState[MANAGEMENT_STORE_GLOBAL_NAMESPACE][MANAGEMENT_STORE_POLICY_LIST_NAMESPACE],
policyListMiddlewareFactory(coreStart, depsStart)
),
substateMiddlewareFactory(
(globalState) =>
globalState[MANAGEMENT_STORE_GLOBAL_NAMESPACE][MANAGEMENT_STORE_POLICY_DETAILS_NAMESPACE],
policyDetailsMiddlewareFactory(coreStart, depsStart)
),
substateMiddlewareFactory(listSelector, policyListMiddlewareFactory(coreStart, depsStart)),
substateMiddlewareFactory(detailSelector, policyDetailsMiddlewareFactory(coreStart, depsStart)),
];
};

View file

@ -4,42 +4,34 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { combineReducers as reduxCombineReducers } from 'redux';
import { combineReducers } from 'redux';
import {
initialPolicyDetailsState,
policyDetailsReducer,
initialPolicyDetailsState,
} from '../pages/policy/store/policy_details/reducer';
import {
initialPolicyListState,
policyListReducer,
initialPolicyListState,
} from '../pages/policy/store/policy_list/reducer';
import {
MANAGEMENT_STORE_POLICY_DETAILS_NAMESPACE,
MANAGEMENT_STORE_POLICY_LIST_NAMESPACE,
} from '../common/constants';
import { ImmutableCombineReducers } from '../../common/store';
import { AppAction } from '../../common/store/actions';
import { ManagementState } from './types';
import { Immutable } from '../../../common/endpoint/types';
import { ManagementState } from '../types';
// Change the type of `combinerReducers` locally
const combineReducers: ImmutableCombineReducers = reduxCombineReducers;
const immutableCombineReducers: ImmutableCombineReducers = combineReducers;
/**
* Returns the initial state of the store for the SIEM Management section
*/
export const getManagementInitialState = (): ManagementState => {
return {
[MANAGEMENT_STORE_POLICY_LIST_NAMESPACE]: initialPolicyListState(),
[MANAGEMENT_STORE_POLICY_DETAILS_NAMESPACE]: initialPolicyDetailsState(),
};
export const mockManagementState: Immutable<ManagementState> = {
policyList: initialPolicyListState(),
policyDetails: initialPolicyDetailsState(),
};
/**
* Redux store reducer for the SIEM Management section
*/
export const managementReducer = combineReducers<ManagementState, AppAction>({
// @ts-ignore
export const managementReducer = immutableCombineReducers({
[MANAGEMENT_STORE_POLICY_LIST_NAMESPACE]: policyListReducer,
// @ts-ignore
[MANAGEMENT_STORE_POLICY_DETAILS_NAMESPACE]: policyDetailsReducer,
});

View file

@ -1,26 +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;
* you may not use this file except in compliance with the Elastic License.
*/
import { Immutable } from '../../../common/endpoint/types';
import { PolicyDetailsState, PolicyListState } from '../pages/policy/types';
import { ImmutableReducer } from '../../common/store';
import { AppAction } from '../../common/store/actions';
/**
* Redux store state for the Management section
*/
export interface ManagementState {
policyDetails: Immutable<PolicyDetailsState>;
policyList: Immutable<PolicyListState>;
}
export interface ManagementPluginState {
management: ManagementState;
}
export interface ManagementPluginReducer {
management: ImmutableReducer<ManagementState, AppAction>;
}

View file

@ -4,7 +4,9 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { CombinedState } from 'redux';
import { SiemPageName } from '../app/types';
import { PolicyListState, PolicyDetailsState } from './pages/policy/types';
/**
* The type for the management store global namespace. Used mostly internally to reference
@ -12,6 +14,11 @@ import { SiemPageName } from '../app/types';
*/
export type ManagementStoreGlobalNamespace = 'management';
export type ManagementState = CombinedState<{
policyList: PolicyListState;
policyDetails: PolicyDetailsState;
}>;
/**
* The management list of sub-tabs. Changes to these will impact the Router routes.
*/

View file

@ -8,7 +8,7 @@ import { createSelector } from 'reselect';
import { get } from 'lodash/fp';
import { FlowTargetSourceDest } from '../../graphql/types';
import { State } from '../../common/store/reducer';
import { State } from '../../common/store/types';
import { initialNetworkState } from './reducer';
import {
IpDetailsTableType,

View file

@ -14,7 +14,7 @@ import {
TimelineType,
TimelineStatus,
} from '../../../graphql/types';
import { KueryFilterQuery, SerializedFilterQuery } from '../../../common/store/model';
import { KueryFilterQuery, SerializedFilterQuery } from '../../../common/store/types';
export const DEFAULT_PAGE_COUNT = 2; // Eui Pager will not render unless this is a minimum of 2 pages
export type KqlMode = 'filter' | 'search';

View file

@ -7,7 +7,7 @@
import { createSelector } from 'reselect';
import { isFromKueryExpressionValid } from '../../../common/lib/keury';
import { State } from '../../../common/store/reducer';
import { State } from '../../../common/store/types';
import { TimelineModel } from './model';
import { AutoSavedWarningMsg, TimelineById } from './types';