-
Notifications
You must be signed in to change notification settings - Fork 8.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Security Solution] Add hook for reading/writing resolver query params #70809
Changes from 1 commit
1206284
6532698
b4c9faf
364ac4c
9d2eeca
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,6 +18,7 @@ import { useKibana } from '../../../../../../src/plugins/kibana_react/public'; | |
export const Resolver = React.memo(function ({ | ||
className, | ||
databaseDocumentID, | ||
documentLocation, | ||
}: { | ||
/** | ||
* Used by `styled-components`. | ||
|
@@ -28,6 +29,11 @@ export const Resolver = React.memo(function ({ | |
* Used as the origin of the Resolver graph. | ||
*/ | ||
databaseDocumentID?: string; | ||
/** | ||
* A string literal describing where in the app resolver is located, | ||
* used to prevent collisions in things like query params | ||
*/ | ||
documentLocation: string; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ❔ defer for now, but something like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ...but maybe also too narrow, carry on actually. |
||
}) { | ||
const context = useKibana<StartServices>(); | ||
const store = useMemo(() => { | ||
|
@@ -40,7 +46,11 @@ export const Resolver = React.memo(function ({ | |
*/ | ||
return ( | ||
<Provider store={store}> | ||
<ResolverMap className={className} databaseDocumentID={databaseDocumentID} /> | ||
<ResolverMap | ||
className={className} | ||
databaseDocumentID={databaseDocumentID} | ||
documentLocation={documentLocation} | ||
/> | ||
</Provider> | ||
); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -29,6 +29,7 @@ import { SideEffectContext } from './side_effect_context'; | |
export const ResolverMap = React.memo(function ({ | ||
className, | ||
databaseDocumentID, | ||
documentLocation, | ||
}: { | ||
/** | ||
* Used by `styled-components`. | ||
|
@@ -39,6 +40,7 @@ export const ResolverMap = React.memo(function ({ | |
* Used as the origin of the Resolver graph. | ||
*/ | ||
databaseDocumentID?: string; | ||
documentLocation: string; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. please add doc comment |
||
}) { | ||
/** | ||
* This is responsible for dispatching actions that include any external data. | ||
|
@@ -111,13 +113,14 @@ export const ResolverMap = React.memo(function ({ | |
relatedEventsStats ? relatedEventsStats.get(entityId(processEvent)) : undefined | ||
} | ||
isProcessTerminated={terminatedProcesses.has(processEntityId)} | ||
documentLocation={documentLocation} | ||
isProcessOrigin={false} | ||
/> | ||
); | ||
})} | ||
</GraphContainer> | ||
)} | ||
<StyledPanel /> | ||
<StyledPanel documentLocation={documentLocation} /> | ||
<GraphControls /> | ||
<SymbolDefinitions /> | ||
</StyledMapContainer> | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -27,8 +27,7 @@ const BetaHeader = styled(`header`)` | |
* The two query parameters we read/write on to control which view the table presents: | ||
*/ | ||
export interface CrumbInfo { | ||
readonly crumbId: string; | ||
readonly crumbEvent: string; | ||
readonly [x: string]: string; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ❔ (defer: do do not this until after merge if you decide to) At this point, you could probably just change it to a |
||
} | ||
|
||
const ThemedBreadcrumbs = styled(EuiBreadcrumbs)<{ background: string; text: string }>` | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,9 +10,6 @@ import React, { useCallback, useMemo } from 'react'; | |
import styled from 'styled-components'; | ||
import { i18n } from '@kbn/i18n'; | ||
import { htmlIdGenerator, EuiButton, EuiI18nNumber, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; | ||
import { useHistory } from 'react-router-dom'; | ||
// eslint-disable-next-line import/no-nodejs-modules | ||
import querystring from 'querystring'; | ||
import { useSelector } from 'react-redux'; | ||
import { NodeSubMenu, subMenuAssets } from './submenu'; | ||
import { applyMatrix3 } from '../models/vector2'; | ||
|
@@ -22,7 +19,7 @@ import { ResolverEvent, ResolverNodeStats } from '../../../common/endpoint/types | |
import { useResolverDispatch } from './use_resolver_dispatch'; | ||
import * as eventModel from '../../../common/endpoint/models/event'; | ||
import * as selectors from '../store/selectors'; | ||
import { CrumbInfo } from './panels/panel_content_utilities'; | ||
import { useResolverQueryParams } from './use_resolver_query_params'; | ||
|
||
/** | ||
* A record of all known event types (in schema format) to translations | ||
|
@@ -244,6 +241,7 @@ const UnstyledProcessEventDot = React.memo( | |
isProcessTerminated, | ||
isProcessOrigin, | ||
relatedEventsStatsForProcess, | ||
documentLocation, | ||
}: { | ||
/** | ||
* A `className` string provided by `styled` | ||
|
@@ -279,6 +277,7 @@ const UnstyledProcessEventDot = React.memo( | |
* Statistics for the number of related events and alerts for this process node | ||
*/ | ||
relatedEventsStatsForProcess?: ResolverNodeStats; | ||
documentLocation: string; | ||
}) => { | ||
/** | ||
* Convert the position, which is in 'world' coordinates, to screen coordinates. | ||
|
@@ -403,35 +402,7 @@ const UnstyledProcessEventDot = React.memo( | |
}); | ||
}, [dispatch, selfId]); | ||
|
||
const history = useHistory(); | ||
const urlSearch = history.location.search; | ||
|
||
/** | ||
* This updates the breadcrumb nav, the table view | ||
*/ | ||
const pushToQueryParams = useCallback( | ||
(newCrumbs: CrumbInfo) => { | ||
// Construct a new set of params from the current set (minus empty params) | ||
// by assigning the new set of params provided in `newCrumbs` | ||
const crumbsToPass = { | ||
...querystring.parse(urlSearch.slice(1)), | ||
...newCrumbs, | ||
}; | ||
|
||
// If either was passed in as empty, remove it from the record | ||
if (crumbsToPass.crumbId === '') { | ||
delete crumbsToPass.crumbId; | ||
} | ||
if (crumbsToPass.crumbEvent === '') { | ||
delete crumbsToPass.crumbEvent; | ||
} | ||
|
||
const relativeURL = { search: querystring.stringify(crumbsToPass) }; | ||
|
||
return history.replace(relativeURL); | ||
}, | ||
[history, urlSearch] | ||
); | ||
const { pushToQueryParams } = useResolverQueryParams(documentLocation); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ℹ️ very niiice |
||
|
||
const handleClick = useCallback(() => { | ||
if (animationTarget.current !== null) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
/* | ||
* 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 { useCallback, useMemo } from 'react'; | ||
// eslint-disable-next-line import/no-nodejs-modules | ||
import querystring from 'querystring'; | ||
import { useHistory, useLocation } from 'react-router-dom'; | ||
import { CrumbInfo } from './panels/panel_content_utilities'; | ||
|
||
export function useResolverQueryParams(documentLocation: string) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. instead of passing this around, put the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are there some cool things you could do by having it passed in as an argument like this, though? Just thinking in the future stuff like "pre-focusing" a Resolver by pushing to query params (I guess if you knew its document location) before you open it? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ❔ My only question here would be if this is "passable" in a URL they way we envisioned. I think we put it in this way now regardless, but maybe we should test that someone on the same Kibana instance can always open the URL and restore/rehydrate context based on this. |
||
/** | ||
* This updates the breadcrumb nav and the panel view. It's supplied to each | ||
* panel content view to allow them to dispatch transitions to each other. | ||
*/ | ||
const history = useHistory(); | ||
const urlSearch = useLocation().search; | ||
const uniqueCrumbIdKey = `${documentLocation}CrumbId`; | ||
const uniqueCrumbEventKey = `${documentLocation}CrumbEvent`; | ||
const pushToQueryParams = useCallback( | ||
(newCrumbs: CrumbInfo) => { | ||
// Construct a new set of params from the current set (minus empty params) | ||
// by assigning the new set of params provided in `newCrumbs` | ||
const crumbsToPass = { | ||
...querystring.parse(urlSearch.slice(1)), | ||
[uniqueCrumbIdKey]: newCrumbs.crumbId, | ||
[uniqueCrumbEventKey]: newCrumbs.crumbEvent, | ||
}; | ||
|
||
// If either was passed in as empty, remove it from the record | ||
if (crumbsToPass.uniqueCrumbIdKey === '') { | ||
delete crumbsToPass.uniqueCrumbIdKey; | ||
} | ||
if (crumbsToPass.uniqueCrumbEventKey === '') { | ||
delete crumbsToPass.uniqueCrumbEventKey; | ||
} | ||
|
||
const relativeURL = { search: querystring.stringify(crumbsToPass) }; | ||
// We probably don't want to nuke the user's history with a huge | ||
// trail of these, thus `.replace` instead of `.push` | ||
return history.replace(relativeURL); | ||
}, | ||
[history, urlSearch, uniqueCrumbIdKey, uniqueCrumbEventKey] | ||
); | ||
const queryParams: CrumbInfo = useMemo(() => { | ||
const newParams = { | ||
[uniqueCrumbIdKey]: '', | ||
[uniqueCrumbEventKey]: '', | ||
...querystring.parse(urlSearch.slice(1)), | ||
}; | ||
newParams.crumbId = newParams[uniqueCrumbIdKey]; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you're setting |
||
newParams.crumbEvent = newParams[uniqueCrumbEventKey]; | ||
return newParams; | ||
}, [urlSearch, uniqueCrumbIdKey, uniqueCrumbEventKey]); | ||
|
||
return { | ||
pushToQueryParams, | ||
queryParams, | ||
}; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please add doc comment