mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
[Security solutions] Adds linter rule to forbid usage of no-non-null-assertion (TypeScript ! bang operator) (#114375)
## Summary Fixes: https://github.com/elastic/kibana/issues/114535 **What this linter rule does:** * Sets the [@typescript-eslint/no-non-null-assertion](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-non-null-assertion.md) linter rule to become an error if seen. If you try to use the `!` operator you get an error and nice helper message that tries to encourage better practices such as this one: <img width="1635" alt="Screen Shot 2021-10-07 at 11 26 14 AM" src="https://user-images.githubusercontent.com/1151048/136474207-f38d3461-0af9-4cdc-885b-632cb49d8a24.png"> **Why are we deciding to set this linter rule?** * Recommended from Kibana [styleguide](https://github.com/elastic/kibana/blob/master/STYLEGUIDE.mdx#avoid-non-null-assertions) for ~2 years now and still recommended. * A lot of TypeScript has evolved and has operators such as `?` which can replace the `!` in most cases. Other cases can use a throw explicitly or other ways to manage this. * Some types can change instead of using this operator and we should just change the types. * TypeScript flows have improved and when we upgrade the linter will cause errors where we can remove the `!` operator which is 👍 better than leaving them when they're not needed anymore. * Newer programmers and team members sometimes mistake it for the `?` when it is not the same thing. * We have had past bugs and bugs recently because of these. * It's easier to use the linter to find bugs than to rely on manual tests. **How did Frank fix all the 403 areas in which the linter goes off?** * Anywhere I could remove the `!` operator without side effects or type script errors I just removed the `!` operator. * Anywhere in test code where I could replace the code with a `?` or a `throw` I went through that route. * Within the code areas (non test code) where I saw what looks like a simple bug that I could fix using a `?? []` or `?` operator or `String(value)` or fixing a simple type I would choose that route first. These areas I marked in the code review with the words `NOTE:` for anyone to look at. * Within all other areas of the code and tests where anything looked more involved I just disabled the linter for that particular line. When in doubt I chose this route. ### Checklist - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios
This commit is contained in:
parent
45f02d3c9b
commit
ed9859ac14
149 changed files with 367 additions and 238 deletions
38
.eslintrc.js
38
.eslintrc.js
|
@ -899,7 +899,12 @@ module.exports = {
|
|||
},
|
||||
|
||||
/**
|
||||
* Security Solution overrides
|
||||
* Security Solution overrides. These rules below are maintained and owned by
|
||||
* the people within the security-solution-platform team. Please see ping them
|
||||
* or check with them if you are encountering issues, have suggestions, or would
|
||||
* like to add, change, or remove any particular rule. Linters, Typescript, and rules
|
||||
* evolve and change over time just like coding styles, so please do not hesitate to
|
||||
* reach out.
|
||||
*/
|
||||
{
|
||||
// front end and common typescript and javascript files only
|
||||
|
@ -922,6 +927,22 @@ module.exports = {
|
|||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
// typescript only for front and back end, but excludes the test files.
|
||||
// We use this section to add rules in which we do not want to apply to test files.
|
||||
// This should be a very small set as most linter rules are useful for tests as well.
|
||||
files: [
|
||||
'x-pack/plugins/security_solution/**/*.{ts,tsx}',
|
||||
'x-pack/plugins/timelines/**/*.{ts,tsx}',
|
||||
],
|
||||
excludedFiles: [
|
||||
'x-pack/plugins/security_solution/**/*.{test,mock,test_helper}.{ts,tsx}',
|
||||
'x-pack/plugins/timelines/**/*.{test,mock,test_helper}.{ts,tsx}',
|
||||
],
|
||||
rules: {
|
||||
'@typescript-eslint/no-non-null-assertion': 'error',
|
||||
},
|
||||
},
|
||||
{
|
||||
// typescript only for front and back end
|
||||
files: [
|
||||
|
@ -1040,7 +1061,12 @@ module.exports = {
|
|||
},
|
||||
|
||||
/**
|
||||
* Lists overrides
|
||||
* Lists overrides. These rules below are maintained and owned by
|
||||
* the people within the security-solution-platform team. Please see ping them
|
||||
* or check with them if you are encountering issues, have suggestions, or would
|
||||
* like to add, change, or remove any particular rule. Linters, Typescript, and rules
|
||||
* evolve and change over time just like coding styles, so please do not hesitate to
|
||||
* reach out.
|
||||
*/
|
||||
{
|
||||
// front end and common typescript and javascript files only
|
||||
|
@ -1215,8 +1241,14 @@ module.exports = {
|
|||
],
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* Metrics entities overrides
|
||||
* Metrics entities overrides. These rules below are maintained and owned by
|
||||
* the people within the security-solution-platform team. Please see ping them
|
||||
* or check with them if you are encountering issues, have suggestions, or would
|
||||
* like to add, change, or remove any particular rule. Linters, Typescript, and rules
|
||||
* evolve and change over time just like coding styles, so please do not hesitate to
|
||||
* reach out.
|
||||
*/
|
||||
{
|
||||
// front end and common typescript and javascript files only
|
||||
|
|
|
@ -51,7 +51,8 @@ export const normalizeThresholdField = (
|
|||
? thresholdField
|
||||
: isEmpty(thresholdField)
|
||||
? []
|
||||
: [thresholdField!];
|
||||
: // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
[thresholdField!];
|
||||
};
|
||||
|
||||
export const normalizeThresholdObject = (threshold: Threshold): ThresholdNormalized => {
|
||||
|
|
|
@ -161,7 +161,7 @@ export async function indexEndpointHostDocs({
|
|||
const indexedAgentResponse = await indexFleetAgentForHost(
|
||||
client,
|
||||
kbnClient,
|
||||
hostMetadata!,
|
||||
hostMetadata,
|
||||
realPolicies[appliedPolicyId].policy_id,
|
||||
kibanaVersion
|
||||
);
|
||||
|
|
|
@ -73,7 +73,7 @@ export const indexFleetAgentForHost = async (
|
|||
.index<FleetServerAgent>({
|
||||
index: agentDoc._index,
|
||||
id: agentDoc._id,
|
||||
body: agentDoc._source!,
|
||||
body: agentDoc._source,
|
||||
op_type: 'create',
|
||||
})
|
||||
.catch(wrapErrorAndRejectPromise);
|
||||
|
|
|
@ -89,11 +89,11 @@ describe('Cases connectors', () => {
|
|||
addServiceNowConnector(snConnector);
|
||||
|
||||
cy.wait('@createConnector').then(({ response }) => {
|
||||
cy.wrap(response!.statusCode).should('eql', 200);
|
||||
cy.wrap(response?.statusCode).should('eql', 200);
|
||||
cy.get(TOASTER).should('have.text', "Created 'New connector'");
|
||||
cy.get(TOASTER).should('not.exist');
|
||||
|
||||
selectLastConnectorCreated(response!.body.id);
|
||||
selectLastConnectorCreated(response?.body.id);
|
||||
|
||||
cy.wait('@saveConnector', { timeout: 10000 }).its('response.statusCode').should('eql', 200);
|
||||
cy.get(SERVICE_NOW_MAPPING).first().should('have.text', 'short_description');
|
||||
|
|
|
@ -351,10 +351,10 @@ describe('Custom detection rules deletion and edition', () => {
|
|||
goToRuleDetails();
|
||||
|
||||
cy.wait('@fetchRuleDetails').then(({ response }) => {
|
||||
cy.wrap(response!.statusCode).should('eql', 200);
|
||||
cy.wrap(response?.statusCode).should('eql', 200);
|
||||
|
||||
cy.wrap(response!.body.max_signals).should('eql', getExistingRule().maxSignals);
|
||||
cy.wrap(response!.body.enabled).should('eql', false);
|
||||
cy.wrap(response?.body.max_signals).should('eql', getExistingRule().maxSignals);
|
||||
cy.wrap(response?.body.enabled).should('eql', false);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -414,9 +414,9 @@ describe('Custom detection rules deletion and edition', () => {
|
|||
saveEditedRule();
|
||||
|
||||
cy.wait('@getRule').then(({ response }) => {
|
||||
cy.wrap(response!.statusCode).should('eql', 200);
|
||||
cy.wrap(response?.statusCode).should('eql', 200);
|
||||
// ensure that editing rule does not modify max_signals
|
||||
cy.wrap(response!.body.max_signals).should('eql', getExistingRule().maxSignals);
|
||||
cy.wrap(response?.body.max_signals).should('eql', getExistingRule().maxSignals);
|
||||
});
|
||||
|
||||
cy.get(RULE_NAME_HEADER).should('contain', `${getEditedRule().name}`);
|
||||
|
|
|
@ -35,7 +35,7 @@ describe('Export rules', () => {
|
|||
goToManageAlertsDetectionRules();
|
||||
exportFirstRule();
|
||||
cy.wait('@export').then(({ response }) => {
|
||||
cy.wrap(response!.body).should('eql', expectedExportedRule(this.ruleResponse));
|
||||
cy.wrap(response?.body).should('eql', expectedExportedRule(this.ruleResponse));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -70,7 +70,7 @@ describe('Timeline Templates', () => {
|
|||
addNameToTimeline(getTimeline().title);
|
||||
|
||||
cy.wait('@timeline').then(({ response }) => {
|
||||
const timelineId = response!.body.data.persistTimeline.timeline.savedObjectId;
|
||||
const timelineId = response?.body.data.persistTimeline.timeline.savedObjectId;
|
||||
|
||||
addDescriptionToTimeline(getTimeline().description);
|
||||
addNotesToTimeline(getTimeline().notes);
|
||||
|
|
|
@ -35,9 +35,9 @@ describe('Export timelines', () => {
|
|||
exportTimeline(this.templateId);
|
||||
|
||||
cy.wait('@export').then(({ response }) => {
|
||||
cy.wrap(response!.statusCode).should('eql', 200);
|
||||
cy.wrap(response?.statusCode).should('eql', 200);
|
||||
|
||||
cy.wrap(response!.body).should(
|
||||
cy.wrap(response?.body).should(
|
||||
'eql',
|
||||
expectedExportedTimelineTemplate(this.templateResponse)
|
||||
);
|
||||
|
|
|
@ -33,9 +33,9 @@ describe('Export timelines', () => {
|
|||
exportTimeline(this.timelineId);
|
||||
|
||||
cy.wait('@export').then(({ response }) => {
|
||||
cy.wrap(response!.statusCode).should('eql', 200);
|
||||
cy.wrap(response?.statusCode).should('eql', 200);
|
||||
|
||||
cy.wrap(response!.body).should('eql', expectedExportedTimeline(this.timelineResponse));
|
||||
cy.wrap(response?.body).should('eql', expectedExportedTimeline(this.timelineResponse));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -54,8 +54,8 @@ describe('Update kqlMode for timeline', () => {
|
|||
it('should be able to update timeline kqlMode with filter', () => {
|
||||
cy.get(TIMELINE_KQLMODE_FILTER).click();
|
||||
cy.wait('@update').then(({ response }) => {
|
||||
cy.wrap(response!.statusCode).should('eql', 200);
|
||||
cy.wrap(response!.body.data.persistTimeline.timeline.kqlMode).should('eql', 'filter');
|
||||
cy.wrap(response?.statusCode).should('eql', 200);
|
||||
cy.wrap(response?.body.data.persistTimeline.timeline.kqlMode).should('eql', 'filter');
|
||||
cy.get(ADD_FILTER).should('exist');
|
||||
});
|
||||
});
|
||||
|
@ -63,8 +63,8 @@ describe('Update kqlMode for timeline', () => {
|
|||
it('should be able to update timeline kqlMode with search', () => {
|
||||
cy.get(TIMELINE_KQLMODE_SEARCH).click();
|
||||
cy.wait('@update').then(({ response }) => {
|
||||
cy.wrap(response!.statusCode).should('eql', 200);
|
||||
cy.wrap(response!.body.data.persistTimeline.timeline.kqlMode).should('eql', 'search');
|
||||
cy.wrap(response?.statusCode).should('eql', 200);
|
||||
cy.wrap(response?.body.data.persistTimeline.timeline.kqlMode).should('eql', 'search');
|
||||
cy.get(ADD_FILTER).should('not.exist');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -250,8 +250,8 @@ describe('url state', () => {
|
|||
|
||||
cy.wait('@timeline').then(({ response }) => {
|
||||
closeTimeline();
|
||||
cy.wrap(response!.statusCode).should('eql', 200);
|
||||
const timelineId = response!.body.data.persistTimeline.timeline.savedObjectId;
|
||||
cy.wrap(response?.statusCode).should('eql', 200);
|
||||
const timelineId = response?.body.data.persistTimeline.timeline.savedObjectId;
|
||||
cy.visit('/app/home');
|
||||
cy.visit(`/app/security/timelines?timeline=(id:'${timelineId}',isOpen:!t)`);
|
||||
cy.get(DATE_PICKER_APPLY_BUTTON_TIMELINE).should('exist');
|
||||
|
|
|
@ -174,8 +174,8 @@ describe('value lists', () => {
|
|||
cy.wait('@exportList').then(({ response }) => {
|
||||
cy.fixture(listName).then((list: string) => {
|
||||
const [lineOne, lineTwo] = list.split('\n');
|
||||
expect(response!.body).to.contain(lineOne);
|
||||
expect(response!.body).to.contain(lineTwo);
|
||||
expect(response?.body).to.contain(lineOne);
|
||||
expect(response?.body).to.contain(lineTwo);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -189,8 +189,8 @@ describe('value lists', () => {
|
|||
cy.wait('@exportList').then(({ response }) => {
|
||||
cy.fixture(listName).then((list: string) => {
|
||||
const [lineOne, lineTwo] = list.split('\n');
|
||||
expect(response!.body).to.contain(lineOne);
|
||||
expect(response!.body).to.contain(lineTwo);
|
||||
expect(response?.body).to.contain(lineOne);
|
||||
expect(response?.body).to.contain(lineTwo);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -204,8 +204,8 @@ describe('value lists', () => {
|
|||
cy.wait('@exportList').then(({ response }) => {
|
||||
cy.fixture(listName).then((list: string) => {
|
||||
const [lineOne, lineTwo] = list.split('\n');
|
||||
expect(response!.body).to.contain(lineOne);
|
||||
expect(response!.body).to.contain(lineTwo);
|
||||
expect(response?.body).to.contain(lineOne);
|
||||
expect(response?.body).to.contain(lineTwo);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -219,7 +219,7 @@ describe('value lists', () => {
|
|||
cy.wait('@exportList').then(({ response }) => {
|
||||
cy.fixture(listName).then((list: string) => {
|
||||
const [lineOne] = list.split('\n');
|
||||
expect(response!.body).to.contain(lineOne);
|
||||
expect(response?.body).to.contain(lineOne);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -9,7 +9,10 @@ export const BULK_ACTIONS = '[data-test-subj="utility-bar-action-button"]';
|
|||
|
||||
export const EXPORT_TIMELINE_ACTION = '[data-test-subj="export-timeline-action"]';
|
||||
|
||||
export const TIMELINE = (id: string) => {
|
||||
export const TIMELINE = (id: string | undefined) => {
|
||||
if (id == null) {
|
||||
throw new TypeError('id should never be null or undefined');
|
||||
}
|
||||
return `[data-test-subj="title-${id}"]`;
|
||||
};
|
||||
|
||||
|
|
|
@ -254,7 +254,7 @@ export const fillDefineCustomRuleWithImportedQueryAndContinue = (
|
|||
rule: CustomRule | OverrideRule
|
||||
) => {
|
||||
cy.get(IMPORT_QUERY_FROM_SAVED_TIMELINE_LINK).click();
|
||||
cy.get(TIMELINE(rule.timeline.id!)).click();
|
||||
cy.get(TIMELINE(rule.timeline.id)).click();
|
||||
cy.get(CUSTOM_QUERY_INPUT).should('have.value', rule.customQuery);
|
||||
cy.get(DEFINE_CONTINUE_BUTTON).should('exist').click({ force: true });
|
||||
|
||||
|
@ -273,7 +273,7 @@ export const fillDefineThresholdRule = (rule: ThresholdRule) => {
|
|||
const threshold = 1;
|
||||
|
||||
cy.get(IMPORT_QUERY_FROM_SAVED_TIMELINE_LINK).click();
|
||||
cy.get(TIMELINE(rule.timeline.id!)).click();
|
||||
cy.get(TIMELINE(rule.timeline.id)).click();
|
||||
cy.get(COMBO_BOX_CLEAR_BTN).first().click();
|
||||
|
||||
rule.index.forEach((index) => {
|
||||
|
@ -298,7 +298,7 @@ export const fillDefineThresholdRuleAndContinue = (rule: ThresholdRule) => {
|
|||
cy.wrap($el).type(rule.thresholdField, { delay: 35 });
|
||||
|
||||
cy.get(IMPORT_QUERY_FROM_SAVED_TIMELINE_LINK).click();
|
||||
cy.get(TIMELINE(rule.timeline.id!)).click();
|
||||
cy.get(TIMELINE(rule.timeline.id)).click();
|
||||
cy.get(CUSTOM_QUERY_INPUT).should('have.value', rule.customQuery);
|
||||
cy.get(THRESHOLD_INPUT_AREA)
|
||||
.find(INPUT)
|
||||
|
@ -314,9 +314,12 @@ export const fillDefineThresholdRuleAndContinue = (rule: ThresholdRule) => {
|
|||
};
|
||||
|
||||
export const fillDefineEqlRuleAndContinue = (rule: CustomRule) => {
|
||||
if (rule.customQuery == null) {
|
||||
throw new TypeError('The rule custom query should never be undefined or null ');
|
||||
}
|
||||
cy.get(RULES_CREATION_FORM).find(EQL_QUERY_INPUT).should('exist');
|
||||
cy.get(RULES_CREATION_FORM).find(EQL_QUERY_INPUT).should('be.visible');
|
||||
cy.get(RULES_CREATION_FORM).find(EQL_QUERY_INPUT).type(rule.customQuery!);
|
||||
cy.get(RULES_CREATION_FORM).find(EQL_QUERY_INPUT).type(rule.customQuery);
|
||||
cy.get(RULES_CREATION_FORM).find(EQL_QUERY_VALIDATION_SPINNER).should('not.exist');
|
||||
cy.get(RULES_CREATION_PREVIEW)
|
||||
.find(QUERY_PREVIEW_BUTTON)
|
||||
|
|
|
@ -57,7 +57,7 @@ const LOGIN_API_ENDPOINT = '/internal/security/login';
|
|||
*/
|
||||
export const getUrlWithRoute = (role: ROLES, route: string) => {
|
||||
const url = Cypress.config().baseUrl;
|
||||
const kibana = new URL(url!);
|
||||
const kibana = new URL(String(url));
|
||||
const theUrl = `${Url.format({
|
||||
auth: `${role}:changeme`,
|
||||
username: role,
|
||||
|
@ -83,7 +83,7 @@ interface User {
|
|||
*/
|
||||
export const constructUrlWithUser = (user: User, route: string) => {
|
||||
const url = Cypress.config().baseUrl;
|
||||
const kibana = new URL(url!);
|
||||
const kibana = new URL(String(url));
|
||||
const hostname = kibana.hostname;
|
||||
const username = user.username;
|
||||
const password = user.password;
|
||||
|
|
|
@ -32,7 +32,7 @@ export const activatesRule = () => {
|
|||
cy.get(RULE_SWITCH).should('be.visible');
|
||||
cy.get(RULE_SWITCH).click();
|
||||
cy.wait('@bulk_update').then(({ response }) => {
|
||||
cy.wrap(response!.statusCode).should('eql', 200);
|
||||
cy.wrap(response?.statusCode).should('eql', 200);
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
@ -94,7 +94,7 @@ export const BarChartBaseComponent = ({
|
|||
yAccessors={yAccessors}
|
||||
timeZone={timeZone}
|
||||
splitSeriesAccessors={splitSeriesAccessors}
|
||||
data={series.value!}
|
||||
data={series.value ?? []}
|
||||
stackAccessors={get('configs.series.stackAccessors', chartConfigs)}
|
||||
color={series.color ? series.color : undefined}
|
||||
/>
|
||||
|
|
|
@ -12,7 +12,7 @@ import { mockBrowserFields } from '../../containers/source/mock';
|
|||
|
||||
const aField = {
|
||||
...mockDetailItemData[4],
|
||||
...mockBrowserFields.base.fields!['@timestamp'],
|
||||
...mockBrowserFields.base.fields?.['@timestamp'],
|
||||
};
|
||||
|
||||
describe('helpers', () => {
|
||||
|
|
|
@ -127,7 +127,7 @@ export const getColumnsWithTimestamp = ({
|
|||
export const getExampleText = (example: string | number | null | undefined): string =>
|
||||
!isEmpty(example) ? `Example: ${example}` : '';
|
||||
|
||||
export const getIconFromType = (type: string | null) => {
|
||||
export const getIconFromType = (type: string | null | undefined) => {
|
||||
switch (type) {
|
||||
case 'string': // fall through
|
||||
case 'keyword':
|
||||
|
|
|
@ -236,7 +236,7 @@ const EventsViewerComponent: React.FC<Props> = ({
|
|||
useTimelineEvents({
|
||||
docValueFields,
|
||||
fields,
|
||||
filterQuery: combinedQueries!.filterQuery,
|
||||
filterQuery: combinedQueries?.filterQuery,
|
||||
id,
|
||||
indexNames,
|
||||
limit: itemsPerPage,
|
||||
|
@ -300,7 +300,7 @@ const EventsViewerComponent: React.FC<Props> = ({
|
|||
height={headerFilterGroup ? COMPACT_HEADER_HEIGHT : EVENTS_VIEWER_HEADER_HEIGHT}
|
||||
subtitle={utilityBar ? undefined : subtitle}
|
||||
title={globalFullScreen ? titleWithExitFullScreen : justTitle}
|
||||
isInspectDisabled={combinedQueries!.filterQuery === undefined}
|
||||
isInspectDisabled={combinedQueries?.filterQuery === undefined}
|
||||
>
|
||||
{HeaderSectionContent}
|
||||
</HeaderSection>
|
||||
|
|
|
@ -181,7 +181,7 @@ const StatefulEventsViewerComponent: React.FC<Props> = ({
|
|||
browserFields,
|
||||
bulkActions,
|
||||
columns,
|
||||
dataProviders: dataProviders!,
|
||||
dataProviders,
|
||||
defaultCellActions,
|
||||
deletedEventIds,
|
||||
docValueFields,
|
||||
|
@ -199,7 +199,7 @@ const StatefulEventsViewerComponent: React.FC<Props> = ({
|
|||
isLive,
|
||||
isLoadingIndexPattern,
|
||||
itemsPerPage,
|
||||
itemsPerPageOptions: itemsPerPageOptions!,
|
||||
itemsPerPageOptions,
|
||||
kqlMode,
|
||||
leadingControlColumns,
|
||||
onRuleChange,
|
||||
|
@ -220,7 +220,7 @@ const StatefulEventsViewerComponent: React.FC<Props> = ({
|
|||
columns={columns}
|
||||
docValueFields={docValueFields}
|
||||
id={id}
|
||||
dataProviders={dataProviders!}
|
||||
dataProviders={dataProviders}
|
||||
deletedEventIds={deletedEventIds}
|
||||
end={end}
|
||||
isLoadingIndexPattern={isLoadingIndexPattern}
|
||||
|
@ -228,8 +228,8 @@ const StatefulEventsViewerComponent: React.FC<Props> = ({
|
|||
indexNames={selectedPatterns}
|
||||
indexPattern={indexPattern}
|
||||
isLive={isLive}
|
||||
itemsPerPage={itemsPerPage!}
|
||||
itemsPerPageOptions={itemsPerPageOptions!}
|
||||
itemsPerPage={itemsPerPage}
|
||||
itemsPerPageOptions={itemsPerPageOptions}
|
||||
kqlMode={kqlMode}
|
||||
query={query}
|
||||
onRuleChange={onRuleChange}
|
||||
|
|
|
@ -54,6 +54,7 @@ export const useSetBreadcrumbs = () => {
|
|||
|
||||
dispatch(timelineActions.showTimeline({ id: TimelineId.active, show: false }));
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
navigateToUrl(breadcrumb.href!);
|
||||
},
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ export const getDaysDiff = (minDate: moment.Moment, maxDate: moment.Moment) => {
|
|||
};
|
||||
|
||||
export const histogramDateTimeFormatter = (domain: [string, string] | null, fixedDiff?: number) => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
const diff = fixedDiff ?? getDaysDiff(moment(domain![0]), moment(domain![1]));
|
||||
const format = niceTimeFormatByDay(diff);
|
||||
return timeFormatter(format);
|
||||
|
|
|
@ -78,7 +78,7 @@ const experimentalFeaturesReducer: Reducer<State['app'], UpdateExperimentalFeatu
|
|||
return {
|
||||
...state,
|
||||
enableExperimental: {
|
||||
...state.enableExperimental!,
|
||||
...state.enableExperimental,
|
||||
...action.payload,
|
||||
},
|
||||
};
|
||||
|
|
|
@ -290,7 +290,7 @@ describe('alert actions', () => {
|
|||
...mockEcsDataWithAlert,
|
||||
signal: {
|
||||
rule: {
|
||||
...mockEcsDataWithAlert.signal?.rule!,
|
||||
...mockEcsDataWithAlert.signal?.rule,
|
||||
// @ts-expect-error
|
||||
timeline_id: null,
|
||||
},
|
||||
|
@ -317,7 +317,7 @@ describe('alert actions', () => {
|
|||
...mockEcsDataWithAlert,
|
||||
signal: {
|
||||
rule: {
|
||||
...mockEcsDataWithAlert.signal?.rule!,
|
||||
...mockEcsDataWithAlert.signal?.rule,
|
||||
timeline_id: [''],
|
||||
},
|
||||
},
|
||||
|
@ -343,7 +343,7 @@ describe('alert actions', () => {
|
|||
...mockEcsDataWithAlert,
|
||||
signal: {
|
||||
rule: {
|
||||
...mockEcsDataWithAlert.signal?.rule!,
|
||||
...mockEcsDataWithAlert.signal?.rule,
|
||||
type: ['eql'],
|
||||
timeline_id: [''],
|
||||
},
|
||||
|
@ -387,7 +387,7 @@ describe('alert actions', () => {
|
|||
...mockEcsDataWithAlert,
|
||||
signal: {
|
||||
rule: {
|
||||
...mockEcsDataWithAlert.signal?.rule!,
|
||||
...mockEcsDataWithAlert.signal?.rule,
|
||||
type: ['eql'],
|
||||
timeline_id: [''],
|
||||
},
|
||||
|
|
|
@ -192,8 +192,10 @@ export const getThresholdAggregationData = (
|
|||
};
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
const originalTime = moment(thresholdData.signal?.original_time![0]);
|
||||
const now = moment();
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
const ruleFrom = dateMath.parse(thresholdData.signal?.rule?.from![0]!);
|
||||
const ruleInterval = moment.duration(now.diff(ruleFrom));
|
||||
const fromOriginalTime = originalTime.clone().subtract(ruleInterval); // This is the default... can overshoot
|
||||
|
|
|
@ -142,14 +142,14 @@ export const AlertsTableComponent: React.FC<AlertsTableComponentProps> = ({
|
|||
|
||||
const setEventsLoadingCallback = useCallback(
|
||||
({ eventIds, isLoading }: SetEventsLoadingProps) => {
|
||||
setEventsLoading!({ id: timelineId, eventIds, isLoading });
|
||||
setEventsLoading({ id: timelineId, eventIds, isLoading });
|
||||
},
|
||||
[setEventsLoading, timelineId]
|
||||
);
|
||||
|
||||
const setEventsDeletedCallback = useCallback(
|
||||
({ eventIds, isDeleted }: SetEventsDeletedProps) => {
|
||||
setEventsDeleted!({ id: timelineId, eventIds, isDeleted });
|
||||
setEventsDeleted({ id: timelineId, eventIds, isDeleted });
|
||||
},
|
||||
[setEventsDeleted, timelineId]
|
||||
);
|
||||
|
@ -216,7 +216,7 @@ export const AlertsTableComponent: React.FC<AlertsTableComponentProps> = ({
|
|||
|
||||
// Callback for clearing entire selection from utility bar
|
||||
const clearSelectionCallback = useCallback(() => {
|
||||
clearSelected!({ id: timelineId });
|
||||
clearSelected({ id: timelineId });
|
||||
dispatch(
|
||||
timelineActions.setTGridSelectAll({
|
||||
id: timelineId,
|
||||
|
|
|
@ -59,6 +59,7 @@ interface MlJobSelectProps {
|
|||
}
|
||||
|
||||
const renderJobOption = (option: MlJobOption) => (
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
<JobDisplay id={option.value!.id} description={option.value!.description} />
|
||||
);
|
||||
|
||||
|
@ -69,6 +70,7 @@ export const MlJobSelect: React.FC<MlJobSelectProps> = ({ describedByIds = [], f
|
|||
const mlUrl = useKibana().services.application.getUrlForApp('ml');
|
||||
const handleJobSelect = useCallback(
|
||||
(selectedJobOptions: MlJobOption[]): void => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
const selectedJobIds = selectedJobOptions.map((option) => option.value!.id);
|
||||
field.setValue(selectedJobIds);
|
||||
},
|
||||
|
|
|
@ -61,9 +61,9 @@ export const RuleSwitchComponent = ({
|
|||
async (event: EuiSwitchEvent) => {
|
||||
setMyIsLoading(true);
|
||||
if (dispatch != null) {
|
||||
await enableRulesAction([id], event.target.checked!, dispatch, dispatchToaster);
|
||||
await enableRulesAction([id], event.target.checked, dispatch, dispatchToaster);
|
||||
} else {
|
||||
const enabling = event.target.checked!;
|
||||
const enabling = event.target.checked;
|
||||
const title = enabling
|
||||
? i18n.BATCH_ACTION_ACTIVATE_SELECTED_ERROR(1)
|
||||
: i18n.BATCH_ACTION_DEACTIVATE_SELECTED_ERROR(1);
|
||||
|
|
|
@ -176,8 +176,8 @@ const DetectionEnginePageComponent: React.FC<DetectionEngineComponentProps> = ({
|
|||
const onFilterGroupChangedCallback = useCallback(
|
||||
(newFilterGroup: Status) => {
|
||||
const timelineId = TimelineId.detectionsPage;
|
||||
clearEventsLoading!({ id: timelineId });
|
||||
clearEventsDeleted!({ id: timelineId });
|
||||
clearEventsLoading({ id: timelineId });
|
||||
clearEventsDeleted({ id: timelineId });
|
||||
setFilterGroup(newFilterGroup);
|
||||
},
|
||||
[clearEventsLoading, clearEventsDeleted, setFilterGroup]
|
||||
|
|
|
@ -302,6 +302,7 @@ const RuleDetailsPageComponent: React.FC<DetectionEngineComponentProps> = ({
|
|||
const getLegacyUrlConflictCallout = useMemo(() => {
|
||||
const outcome = rule?.outcome;
|
||||
if (rule != null && spacesApi && outcome === 'conflict') {
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
const aliasTargetId = rule?.alias_target_id!; // This is always defined if outcome === 'conflict'
|
||||
// We have resolved to one rule, but there is another one with a legacy URL associated with this page. Display a
|
||||
// callout with a warning for the user, and provide a way for them to navigate to the other rule.
|
||||
|
@ -401,9 +402,9 @@ const RuleDetailsPageComponent: React.FC<DetectionEngineComponentProps> = ({
|
|||
const onFilterGroupChangedCallback = useCallback(
|
||||
(newFilterGroup: Status) => {
|
||||
const timelineId = TimelineId.detectionsRulesDetailsPage;
|
||||
clearEventsLoading!({ id: timelineId });
|
||||
clearEventsDeleted!({ id: timelineId });
|
||||
clearSelected!({ id: timelineId });
|
||||
clearEventsLoading({ id: timelineId });
|
||||
clearEventsDeleted({ id: timelineId });
|
||||
clearSelected({ id: timelineId });
|
||||
setFilterGroup(newFilterGroup);
|
||||
},
|
||||
[clearEventsLoading, clearEventsDeleted, clearSelected, setFilterGroup]
|
||||
|
|
|
@ -174,6 +174,7 @@ export const getAboutStepsData = (rule: Rule, detailsView: boolean): AboutStepRu
|
|||
timestampOverride: timestampOverride ?? '',
|
||||
name,
|
||||
description,
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
note: note!,
|
||||
references,
|
||||
severity: {
|
||||
|
|
|
@ -229,8 +229,8 @@ const getAuthenticationColumns = (): AuthTableColumns => [
|
|||
truncateText: false,
|
||||
hideForMobile: false,
|
||||
render: ({ node }) =>
|
||||
has('lastSuccess.timestamp', node) && node.lastSuccess!.timestamp != null ? (
|
||||
<FormattedRelativePreferenceDate value={node.lastSuccess!.timestamp} />
|
||||
has('lastSuccess.timestamp', node) && node.lastSuccess?.timestamp != null ? (
|
||||
<FormattedRelativePreferenceDate value={node.lastSuccess?.timestamp} />
|
||||
) : (
|
||||
getEmptyTagValue()
|
||||
),
|
||||
|
@ -264,8 +264,8 @@ const getAuthenticationColumns = (): AuthTableColumns => [
|
|||
truncateText: false,
|
||||
hideForMobile: false,
|
||||
render: ({ node }) =>
|
||||
has('lastFailure.timestamp', node) && node.lastFailure!.timestamp != null ? (
|
||||
<FormattedRelativePreferenceDate value={node.lastFailure!.timestamp} />
|
||||
has('lastFailure.timestamp', node) && node.lastFailure?.timestamp != null ? (
|
||||
<FormattedRelativePreferenceDate value={node.lastFailure?.timestamp} />
|
||||
) : (
|
||||
getEmptyTagValue()
|
||||
),
|
||||
|
|
|
@ -119,6 +119,7 @@ export const ArtifactCardGrid = memo<ArtifactCardGridProps>(
|
|||
|
||||
const handleItemComponentProps = useCallback(
|
||||
(item: AnyArtifact): ArtifactEntryCollapsibleCardProps => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
return fullCardProps.get(item)!;
|
||||
},
|
||||
[fullCardProps]
|
||||
|
|
|
@ -31,7 +31,7 @@ const EuiButtonEmptyStyled = styled(EuiButtonEmpty)`
|
|||
export type BackToExternalAppButtonProps = CommonProps & ListPageRouteState;
|
||||
export const BackToExternalAppButton = memo<BackToExternalAppButtonProps>(
|
||||
({ backButtonLabel, backButtonUrl, onBackButtonNavigateTo, ...commonProps }) => {
|
||||
const handleBackOnClick = useNavigateToAppEventHandler(...onBackButtonNavigateTo!);
|
||||
const handleBackOnClick = useNavigateToAppEventHandler(...onBackButtonNavigateTo);
|
||||
|
||||
return (
|
||||
<EuiButtonEmptyStyled
|
||||
|
@ -40,7 +40,7 @@ export const BackToExternalAppButton = memo<BackToExternalAppButtonProps>(
|
|||
flush="left"
|
||||
size="xs"
|
||||
iconType="arrowLeft"
|
||||
href={backButtonUrl!}
|
||||
href={backButtonUrl}
|
||||
onClick={handleBackOnClick}
|
||||
textProps={{ className: 'text' }}
|
||||
>
|
||||
|
|
|
@ -75,6 +75,7 @@ export const ContextMenuWithRouterSupport = memo<ContextMenuWithRouterSupportPro
|
|||
};
|
||||
|
||||
if (maxWidth) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
newAdditionalProps.style!.maxWidth = maxWidth;
|
||||
}
|
||||
|
||||
|
|
|
@ -203,6 +203,7 @@ export const PaginatedContent = memo(
|
|||
key = item[itemId] as unknown as Key;
|
||||
} else {
|
||||
if (itemKeys.has(item)) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
key = itemKeys.get(item)!;
|
||||
} else {
|
||||
key = generateUUI();
|
||||
|
|
|
@ -50,9 +50,9 @@ const handleEndpointDetailsActivityLogChanged: CaseReducer<EndpointDetailsActivi
|
|||
}
|
||||
: { ...state.endpointDetails.activityLog };
|
||||
return {
|
||||
...state!,
|
||||
...state,
|
||||
endpointDetails: {
|
||||
...state.endpointDetails!,
|
||||
...state.endpointDetails,
|
||||
activityLog: {
|
||||
...updatedActivityLog,
|
||||
logData: action.payload,
|
||||
|
@ -181,7 +181,7 @@ export const endpointListReducer: StateReducer = (state = initialEndpointPageSta
|
|||
return {
|
||||
...state,
|
||||
endpointDetails: {
|
||||
...state.endpointDetails!,
|
||||
...state.endpointDetails,
|
||||
activityLog: {
|
||||
...state.endpointDetails.activityLog,
|
||||
paging: {
|
||||
|
@ -195,7 +195,7 @@ export const endpointListReducer: StateReducer = (state = initialEndpointPageSta
|
|||
return {
|
||||
...state,
|
||||
endpointDetails: {
|
||||
...state.endpointDetails!,
|
||||
...state.endpointDetails,
|
||||
activityLog: {
|
||||
...state.endpointDetails.activityLog,
|
||||
paging: {
|
||||
|
@ -458,6 +458,7 @@ const handleEndpointIsolationRequestStateChanged: ImmutableReducer<
|
|||
AppAction & { type: 'endpointIsolationRequestStateChange' }
|
||||
> = (state, action) => {
|
||||
return {
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
...state!,
|
||||
isolationRequestState: action.payload,
|
||||
};
|
||||
|
|
|
@ -30,12 +30,12 @@ describe('When event filters delete modal is shown', () => {
|
|||
const getConfirmButton = () =>
|
||||
renderResult.baseElement.querySelector(
|
||||
'[data-test-subj="eventFilterDeleteModalConfirmButton"]'
|
||||
)! as HTMLButtonElement;
|
||||
) as HTMLButtonElement;
|
||||
|
||||
const getCancelButton = () =>
|
||||
renderResult.baseElement.querySelector(
|
||||
'[data-test-subj="eventFilterDeleteModalCancelButton"]'
|
||||
)! as HTMLButtonElement;
|
||||
) as HTMLButtonElement;
|
||||
|
||||
const getCurrentState = () => store.getState().management.eventFilters;
|
||||
|
||||
|
|
|
@ -80,7 +80,7 @@ describe('Event filter flyout', () => {
|
|||
});
|
||||
|
||||
expect(getFormEntryState(getState())).not.toBeUndefined();
|
||||
expect(getFormEntryState(getState())!.entries[0].field).toBe('');
|
||||
expect(getFormEntryState(getState())?.entries[0].field).toBe('');
|
||||
});
|
||||
|
||||
it('should confirm form when button is disabled', () => {
|
||||
|
@ -98,7 +98,7 @@ describe('Event filter flyout', () => {
|
|||
type: 'eventFiltersChangeForm',
|
||||
payload: {
|
||||
entry: {
|
||||
...(getState().form!.entry as CreateExceptionListItemSchema),
|
||||
...(getState().form?.entry as CreateExceptionListItemSchema),
|
||||
name: 'test',
|
||||
os_types: ['windows'],
|
||||
},
|
||||
|
@ -125,7 +125,7 @@ describe('Event filter flyout', () => {
|
|||
type: 'eventFiltersFormStateChanged',
|
||||
payload: {
|
||||
type: 'LoadedResourceState',
|
||||
data: getState().form!.entry as ExceptionListItemSchema,
|
||||
data: getState().form?.entry as ExceptionListItemSchema,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
@ -193,6 +193,6 @@ describe('Event filter flyout', () => {
|
|||
});
|
||||
|
||||
expect(getFormEntryState(getState())).not.toBeUndefined();
|
||||
expect(getFormEntryState(getState())!.item_id).toBe(createdEventFilterEntryMock().item_id);
|
||||
expect(getFormEntryState(getState())?.item_id).toBe(createdEventFilterEntryMock().item_id);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -99,7 +99,7 @@ describe('Event filter form', () => {
|
|||
});
|
||||
});
|
||||
|
||||
expect(getState().form.entry!.name).toBe('Exception name');
|
||||
expect(getState().form.entry?.name).toBe('Exception name');
|
||||
expect(getState().form.hasNameError).toBeFalsy();
|
||||
});
|
||||
|
||||
|
@ -116,7 +116,7 @@ describe('Event filter form', () => {
|
|||
});
|
||||
});
|
||||
|
||||
expect(getState().form.entry!.name).toBe('');
|
||||
expect(getState().form.entry?.name).toBe('');
|
||||
expect(getState().form.hasNameError).toBeTruthy();
|
||||
});
|
||||
|
||||
|
|
|
@ -81,7 +81,7 @@ describe('Event filter modal', () => {
|
|||
await waitForAction('eventFiltersInitForm');
|
||||
});
|
||||
|
||||
expect(getState().form!.entry).not.toBeUndefined();
|
||||
expect(getState().form?.entry).not.toBeUndefined();
|
||||
});
|
||||
|
||||
it('should set OS with the enriched data', async () => {
|
||||
|
@ -90,7 +90,7 @@ describe('Event filter modal', () => {
|
|||
await waitForAction('eventFiltersInitForm');
|
||||
});
|
||||
|
||||
expect(getState().form!.entry?.os_types).toContain('linux');
|
||||
expect(getState().form?.entry?.os_types).toContain('linux');
|
||||
});
|
||||
|
||||
it('should confirm form when button is disabled', async () => {
|
||||
|
@ -103,7 +103,7 @@ describe('Event filter modal', () => {
|
|||
act(() => {
|
||||
fireEvent.click(confirmButton);
|
||||
});
|
||||
expect(getState().form!.submissionResourceState.type).toBe('UninitialisedResourceState');
|
||||
expect(getState().form?.submissionResourceState.type).toBe('UninitialisedResourceState');
|
||||
});
|
||||
|
||||
it('should confirm form when button is enabled', async () => {
|
||||
|
@ -116,7 +116,7 @@ describe('Event filter modal', () => {
|
|||
type: 'eventFiltersChangeForm',
|
||||
payload: {
|
||||
entry: {
|
||||
...(getState().form!.entry as CreateExceptionListItemSchema),
|
||||
...(getState().form?.entry as CreateExceptionListItemSchema),
|
||||
name: 'test',
|
||||
},
|
||||
hasNameError: false,
|
||||
|
@ -126,7 +126,7 @@ describe('Event filter modal', () => {
|
|||
act(() => {
|
||||
fireEvent.click(confirmButton);
|
||||
});
|
||||
expect(getState().form!.submissionResourceState.type).toBe('LoadingResourceState');
|
||||
expect(getState().form?.submissionResourceState.type).toBe('LoadingResourceState');
|
||||
expect(confirmButton.hasAttribute('disabled')).toBeTruthy();
|
||||
});
|
||||
|
||||
|
@ -143,7 +143,7 @@ describe('Event filter modal', () => {
|
|||
type: 'eventFiltersFormStateChanged',
|
||||
payload: {
|
||||
type: 'LoadedResourceState',
|
||||
data: getState().form!.entry as ExceptionListItemSchema,
|
||||
data: getState().form?.entry as ExceptionListItemSchema,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
|
|
@ -79,14 +79,14 @@ describe('EventFiltersNotification', () => {
|
|||
type: 'eventFiltersFormStateChanged',
|
||||
payload: {
|
||||
type: 'LoadedResourceState',
|
||||
data: store.getState()!.management!.eventFilters!.form!.entry as ExceptionListItemSchema,
|
||||
data: store.getState().management.eventFilters.form.entry as ExceptionListItemSchema,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
expect(notifications.toasts.addSuccess).toBeCalledWith(
|
||||
getCreationSuccessMessage(
|
||||
store.getState()!.management!.eventFilters!.form!.entry as CreateExceptionListItemSchema
|
||||
store.getState().management.eventFilters.form.entry as CreateExceptionListItemSchema
|
||||
)
|
||||
);
|
||||
expect(notifications.toasts.addDanger).not.toBeCalled();
|
||||
|
@ -110,14 +110,14 @@ describe('EventFiltersNotification', () => {
|
|||
type: 'eventFiltersFormStateChanged',
|
||||
payload: {
|
||||
type: 'LoadedResourceState',
|
||||
data: store.getState()!.management!.eventFilters!.form!.entry as ExceptionListItemSchema,
|
||||
data: store.getState().management.eventFilters.form.entry as ExceptionListItemSchema,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
expect(notifications.toasts.addSuccess).toBeCalledWith(
|
||||
getUpdateSuccessMessage(
|
||||
store.getState()!.management!.eventFilters!.form!.entry as CreateExceptionListItemSchema
|
||||
store.getState().management.eventFilters.form.entry as CreateExceptionListItemSchema
|
||||
)
|
||||
);
|
||||
expect(notifications.toasts.addDanger).not.toBeCalled();
|
||||
|
@ -144,7 +144,7 @@ describe('EventFiltersNotification', () => {
|
|||
type: 'FailedResourceState',
|
||||
error: { message: 'error message', statusCode: 500, error: 'error' },
|
||||
lastLoadedState: getLastLoadedResourceState(
|
||||
store.getState()!.management!.eventFilters!.form!.submissionResourceState
|
||||
store.getState().management.eventFilters.form.submissionResourceState
|
||||
),
|
||||
},
|
||||
});
|
||||
|
@ -154,7 +154,7 @@ describe('EventFiltersNotification', () => {
|
|||
expect(notifications.toasts.addDanger).toBeCalledWith(
|
||||
getCreationErrorMessage(
|
||||
(
|
||||
store.getState()!.management!.eventFilters!.form!
|
||||
store.getState().management.eventFilters.form
|
||||
.submissionResourceState as FailedResourceState
|
||||
).error
|
||||
)
|
||||
|
@ -181,7 +181,7 @@ describe('EventFiltersNotification', () => {
|
|||
type: 'FailedResourceState',
|
||||
error: { message: 'error message', statusCode: 500, error: 'error' },
|
||||
lastLoadedState: getLastLoadedResourceState(
|
||||
store.getState()!.management!.eventFilters!.form!.submissionResourceState
|
||||
store.getState().management.eventFilters.form.submissionResourceState
|
||||
),
|
||||
},
|
||||
});
|
||||
|
@ -191,7 +191,7 @@ describe('EventFiltersNotification', () => {
|
|||
expect(notifications.toasts.addDanger).toBeCalledWith(
|
||||
getUpdateErrorMessage(
|
||||
(
|
||||
store.getState()!.management!.eventFilters!.form!
|
||||
store.getState().management.eventFilters.form
|
||||
.submissionResourceState as FailedResourceState
|
||||
).error
|
||||
)
|
||||
|
@ -211,7 +211,7 @@ describe('EventFiltersNotification', () => {
|
|||
type: 'FailedResourceState',
|
||||
error: { message: 'error message', statusCode: 500, error: 'error' },
|
||||
lastLoadedState: getLastLoadedResourceState(
|
||||
store.getState()!.management!.eventFilters!.form!.submissionResourceState
|
||||
store.getState().management.eventFilters.form.submissionResourceState
|
||||
),
|
||||
},
|
||||
});
|
||||
|
@ -221,7 +221,7 @@ describe('EventFiltersNotification', () => {
|
|||
expect(notifications.toasts.addWarning).toBeCalledWith(
|
||||
getGetErrorMessage(
|
||||
(
|
||||
store.getState()!.management!.eventFilters!.form!
|
||||
store.getState().management.eventFilters.form
|
||||
.submissionResourceState as FailedResourceState
|
||||
).error
|
||||
)
|
||||
|
|
|
@ -53,11 +53,11 @@ describe('When on the host isolation exceptions delete modal', () => {
|
|||
|
||||
const submitButton = renderResult.baseElement.querySelector(
|
||||
'[data-test-subj="hostIsolationExceptionsDeleteModalConfirmButton"]'
|
||||
)! as HTMLButtonElement;
|
||||
) as HTMLButtonElement;
|
||||
|
||||
const cancelButton = renderResult.baseElement.querySelector(
|
||||
'[data-test-subj="hostIsolationExceptionsDeleteModalConfirmButton"]'
|
||||
)! as HTMLButtonElement;
|
||||
) as HTMLButtonElement;
|
||||
|
||||
act(() => {
|
||||
fireEvent.click(submitButton);
|
||||
|
@ -72,7 +72,7 @@ describe('When on the host isolation exceptions delete modal', () => {
|
|||
render();
|
||||
const cancelButton = renderResult.baseElement.querySelector(
|
||||
'[data-test-subj="hostIsolationExceptionsDeleteModalConfirmButton"]'
|
||||
)! as HTMLButtonElement;
|
||||
) as HTMLButtonElement;
|
||||
|
||||
const waiter = waitForAction('hostIsolationExceptionsMarkToDelete', {
|
||||
validate: ({ payload }) => {
|
||||
|
@ -96,7 +96,7 @@ describe('When on the host isolation exceptions delete modal', () => {
|
|||
|
||||
const submitButton = renderResult.baseElement.querySelector(
|
||||
'[data-test-subj="hostIsolationExceptionsDeleteModalConfirmButton"]'
|
||||
)! as HTMLButtonElement;
|
||||
) as HTMLButtonElement;
|
||||
|
||||
await act(async () => {
|
||||
fireEvent.click(submitButton);
|
||||
|
@ -121,7 +121,7 @@ describe('When on the host isolation exceptions delete modal', () => {
|
|||
|
||||
const submitButton = renderResult.baseElement.querySelector(
|
||||
'[data-test-subj="hostIsolationExceptionsDeleteModalConfirmButton"]'
|
||||
)! as HTMLButtonElement;
|
||||
) as HTMLButtonElement;
|
||||
|
||||
await act(async () => {
|
||||
fireEvent.click(submitButton);
|
||||
|
|
|
@ -97,7 +97,7 @@ export const HostIsolationExceptionsFormFlyout: React.FC<{}> = memo(() => {
|
|||
if (!exceptionToEdit || location.id !== exceptionToEdit.id) {
|
||||
dispatch({
|
||||
type: 'hostIsolationExceptionsMarkToEdit',
|
||||
payload: { id: location.id! },
|
||||
payload: { id: location.id },
|
||||
});
|
||||
} else {
|
||||
setException(exceptionToEdit);
|
||||
|
|
|
@ -75,6 +75,7 @@ export const trustedAppPutHttpMocks = httpHandlerMockFactory<TrustedAppPutHttpMo
|
|||
const response: PutTrustedAppUpdateResponse = {
|
||||
data: {
|
||||
...(body as unknown as PutTrustedAppUpdateRequest),
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
id: path.split('/').pop()!,
|
||||
created_at: '2021-10-12T16:02:55.856Z',
|
||||
created_by: 'elastic',
|
||||
|
|
|
@ -106,7 +106,7 @@ describe('policy details: ', () => {
|
|||
|
||||
it('windows process events is enabled', () => {
|
||||
const config = policyConfig(getState());
|
||||
expect(config!.windows.events.process).toEqual(true);
|
||||
expect(config.windows.events.process).toEqual(true);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -128,7 +128,7 @@ describe('policy details: ', () => {
|
|||
|
||||
it('mac file events is enabled', () => {
|
||||
const config = policyConfig(getState());
|
||||
expect(config!.mac.events.file).toEqual(true);
|
||||
expect(config.mac.events.file).toEqual(true);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -150,7 +150,7 @@ describe('policy details: ', () => {
|
|||
|
||||
it('linux file events is enabled', () => {
|
||||
const config = policyConfig(getState());
|
||||
expect(config!.linux.events.file).toEqual(true);
|
||||
expect(config.linux.events.file).toEqual(true);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ const mockTheme = getMockTheme({
|
|||
});
|
||||
|
||||
const getStatValue = (el: reactTestingLibrary.RenderResult, stat: string) => {
|
||||
return el.getByText(stat)!.nextSibling?.lastChild?.textContent;
|
||||
return el.getByText(stat).nextSibling?.lastChild?.textContent;
|
||||
};
|
||||
|
||||
describe('Fleet event filters card', () => {
|
||||
|
|
|
@ -101,6 +101,7 @@ export const PolicyFormLayout = React.memo(() => {
|
|||
title: i18n.translate('xpack.securitySolution.endpoint.policy.details.updateErrorTitle', {
|
||||
defaultMessage: 'Failed!',
|
||||
}),
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
text: policyUpdateStatus.error!.message,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -93,7 +93,7 @@ export const usePolicyTrustedAppsNotification = () => {
|
|||
'xpack.securitySolution.endpoint.policy.trustedApps.layout.flyout.toastSuccess.textSingle',
|
||||
{
|
||||
defaultMessage: '"{name}" has been added to your trusted applications list.',
|
||||
values: { name: updatedArtifacts[0]!.data.name },
|
||||
values: { name: updatedArtifacts[0].data.name },
|
||||
}
|
||||
),
|
||||
});
|
||||
|
|
|
@ -91,6 +91,7 @@ export const PolicyTrustedAppsFlyout = React.memo(() => {
|
|||
payload: {
|
||||
action: 'assign',
|
||||
artifacts: selectedArtifactIds.map<MaybeImmutable<TrustedApp>>((selectedId) => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
return assignableArtifactsList?.data?.find((trustedApp) => trustedApp.id === selectedId)!;
|
||||
}),
|
||||
},
|
||||
|
|
|
@ -181,6 +181,7 @@ export const PolicyTrustedAppsList = memo(() => {
|
|||
|
||||
const provideCardProps = useCallback<Required<ArtifactCardGridProps>['cardComponentProps']>(
|
||||
(item) => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
return cardProps.get(item as Immutable<TrustedApp>)!;
|
||||
},
|
||||
[cardProps]
|
||||
|
|
|
@ -191,6 +191,7 @@ const submitCreationIfNeeded = async (
|
|||
if (editMode) {
|
||||
responseTrustedApp = (
|
||||
await trustedAppsService.updateTrustedApp(
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
{ id: editItemId(currentState)! },
|
||||
// TODO: try to remove the cast
|
||||
entry as PostTrustedAppCreateRequest
|
||||
|
@ -414,6 +415,7 @@ const fetchEditTrustedAppIfNeeded = async (
|
|||
payload: {
|
||||
// @ts-expect-error-next-line will be fixed with when AsyncResourceState is refactored (#830)
|
||||
type: 'LoadingResourceState',
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
previousState: editItemState(currentState)!,
|
||||
},
|
||||
});
|
||||
|
|
|
@ -86,7 +86,9 @@ const addResultToValidation = (
|
|||
};
|
||||
}
|
||||
const errorMarkup: React.ReactNode = type === 'warnings' ? <div>{resultValue}</div> : resultValue;
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
validation.result[field]![type].push(errorMarkup);
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
validation.result[field]!.isInvalid = true;
|
||||
};
|
||||
|
||||
|
|
|
@ -143,7 +143,7 @@ export const EffectedPolicySelect = memo<EffectedPolicySelectProps>(
|
|||
});
|
||||
},
|
||||
[isGlobal, onChange]
|
||||
)!;
|
||||
);
|
||||
|
||||
const handleGlobalButtonChange = useCallback(
|
||||
(selectedId) => {
|
||||
|
|
|
@ -71,7 +71,7 @@ export const IpOverview = React.memo<IpOverviewProps>(
|
|||
const capabilities = useMlCapabilities();
|
||||
const userPermissions = hasMlUserPermissions(capabilities);
|
||||
const [darkMode] = useUiSetting$<boolean>(DEFAULT_DARK_MODE);
|
||||
const typeData = data[flowTarget]!;
|
||||
const typeData = data[flowTarget];
|
||||
const column: DescriptionList[] = [
|
||||
{
|
||||
title: i18n.LOCATION,
|
||||
|
|
|
@ -78,7 +78,7 @@ describe('NetworkTopNFlow Table Component', () => {
|
|||
</TestProviders>
|
||||
);
|
||||
|
||||
expect(store.getState().network.page.queries!.dns.sort).toEqual({
|
||||
expect(store.getState().network.page.queries?.dns.sort).toEqual({
|
||||
direction: 'desc',
|
||||
field: 'queryCount',
|
||||
});
|
||||
|
@ -87,7 +87,7 @@ describe('NetworkTopNFlow Table Component', () => {
|
|||
|
||||
wrapper.update();
|
||||
|
||||
expect(store.getState().network.page.queries!.dns.sort).toEqual({
|
||||
expect(store.getState().network.page.queries?.dns.sort).toEqual({
|
||||
direction: 'asc',
|
||||
field: 'dnsName',
|
||||
});
|
||||
|
|
|
@ -80,7 +80,7 @@ describe('NetworkHttp Table Component', () => {
|
|||
</TestProviders>
|
||||
);
|
||||
|
||||
expect(store.getState().network.page.queries!.http.sort).toEqual({
|
||||
expect(store.getState().network.page.queries?.http.sort).toEqual({
|
||||
direction: 'desc',
|
||||
});
|
||||
|
||||
|
@ -88,7 +88,7 @@ describe('NetworkHttp Table Component', () => {
|
|||
|
||||
wrapper.update();
|
||||
|
||||
expect(store.getState().network.page.queries!.http.sort).toEqual({
|
||||
expect(store.getState().network.page.queries?.http.sort).toEqual({
|
||||
direction: 'asc',
|
||||
});
|
||||
expect(wrapper.find('.euiTable thead tr th button').first().find('svg')).toBeTruthy();
|
||||
|
|
|
@ -77,7 +77,7 @@ describe('Tls Table Component', () => {
|
|||
/>
|
||||
</TestProviders>
|
||||
);
|
||||
expect(store.getState().network.details.queries!.tls.sort).toEqual({
|
||||
expect(store.getState().network.details.queries?.tls.sort).toEqual({
|
||||
direction: 'desc',
|
||||
field: '_id',
|
||||
});
|
||||
|
@ -86,7 +86,7 @@ describe('Tls Table Component', () => {
|
|||
|
||||
wrapper.update();
|
||||
|
||||
expect(store.getState().network.details.queries!.tls.sort).toEqual({
|
||||
expect(store.getState().network.details.queries?.tls.sort).toEqual({
|
||||
direction: 'asc',
|
||||
field: '_id',
|
||||
});
|
||||
|
|
|
@ -81,7 +81,7 @@ describe('Users Table Component', () => {
|
|||
/>
|
||||
</TestProviders>
|
||||
);
|
||||
expect(store.getState().network.details.queries!.users.sort).toEqual({
|
||||
expect(store.getState().network.details.queries?.users.sort).toEqual({
|
||||
direction: 'asc',
|
||||
field: 'name',
|
||||
});
|
||||
|
@ -90,7 +90,7 @@ describe('Users Table Component', () => {
|
|||
|
||||
wrapper.update();
|
||||
|
||||
expect(store.getState().network.details.queries!.users.sort).toEqual({
|
||||
expect(store.getState().network.details.queries?.users.sort).toEqual({
|
||||
direction: 'desc',
|
||||
field: 'name',
|
||||
});
|
||||
|
|
|
@ -371,16 +371,23 @@ export class Plugin implements IPlugin<PluginSetup, PluginStart, SetupPlugins, S
|
|||
|
||||
const timelineInitialState = {
|
||||
timeline: {
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
...subPlugins.timelines.store.initialState.timeline!,
|
||||
timelineById: {
|
||||
...subPlugins.timelines.store.initialState.timeline.timelineById,
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
...subPlugins.alerts.storageTimelines!.timelineById,
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
...subPlugins.rules.storageTimelines!.timelineById,
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
...subPlugins.exceptions.storageTimelines!.timelineById,
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
...subPlugins.hosts.storageTimelines!.timelineById,
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
...subPlugins.network.storageTimelines!.timelineById,
|
||||
...(this.experimentalFeatures.uebaEnabled && subPlugins.ueba != null
|
||||
? subPlugins.ueba.storageTimelines!.timelineById
|
||||
? // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
subPlugins.ueba.storageTimelines!.timelineById
|
||||
: {}),
|
||||
},
|
||||
},
|
||||
|
|
|
@ -314,6 +314,7 @@ export function mockTreeWithNoAncestorsAndTwoChildrenAndRelatedEventsOnOrigin({
|
|||
secondChildID,
|
||||
});
|
||||
const parentEntityID = nodeModel.parentId(
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
resolverTree.nodes.find((node) => node.id === originID)!
|
||||
);
|
||||
const relatedEvents = [
|
||||
|
|
|
@ -162,6 +162,7 @@ export function root(tree: IndexedProcessTree) {
|
|||
|
||||
// iteratively swap current w/ its parent
|
||||
while (parent(tree, current) !== undefined) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
current = parent(tree, current)!;
|
||||
}
|
||||
return current;
|
||||
|
|
|
@ -145,7 +145,7 @@ describe('resolver selectors', () => {
|
|||
});
|
||||
});
|
||||
it('the origin should be in view', () => {
|
||||
const origin = selectors.graphNodeForID(state())(originID)!;
|
||||
const origin = selectors.graphNodeForID(state())(originID);
|
||||
expect(
|
||||
selectors
|
||||
.visibleNodesAndEdgeLines(state())(0)
|
||||
|
@ -153,7 +153,7 @@ describe('resolver selectors', () => {
|
|||
).toBe(true);
|
||||
});
|
||||
it('the first child should be in view', () => {
|
||||
const firstChild = selectors.graphNodeForID(state())(firstChildID)!;
|
||||
const firstChild = selectors.graphNodeForID(state())(firstChildID);
|
||||
expect(
|
||||
selectors
|
||||
.visibleNodesAndEdgeLines(state())(0)
|
||||
|
@ -161,7 +161,7 @@ describe('resolver selectors', () => {
|
|||
).toBe(true);
|
||||
});
|
||||
it('the second child should not be in view', () => {
|
||||
const secondChild = selectors.graphNodeForID(state())(secondChildID)!;
|
||||
const secondChild = selectors.graphNodeForID(state())(secondChildID);
|
||||
expect(
|
||||
selectors
|
||||
.visibleNodesAndEdgeLines(state())(0)
|
||||
|
|
|
@ -67,7 +67,7 @@ expect.extend({
|
|||
? () =>
|
||||
`${this.utils.matcherHint(matcherName, undefined, undefined, options)}\n\n` +
|
||||
`Expected: not ${this.utils.printExpected(expected)}\n${
|
||||
this.utils.stringify(expected) !== this.utils.stringify(received[received.length - 1]!)
|
||||
this.utils.stringify(expected) !== this.utils.stringify(received[received.length - 1])
|
||||
? `Received: ${this.utils.printReceived(received[received.length - 1])}`
|
||||
: ''
|
||||
}`
|
||||
|
@ -131,7 +131,7 @@ expect.extend({
|
|||
? () =>
|
||||
`${this.utils.matcherHint(matcherName, undefined, undefined, options)}\n\n` +
|
||||
`Expected: not ${this.utils.printExpected(expected)}\n${
|
||||
this.utils.stringify(expected) !== this.utils.stringify(received[received.length - 1]!)
|
||||
this.utils.stringify(expected) !== this.utils.stringify(received[received.length - 1])
|
||||
? `Received: ${this.utils.printReceived(received[received.length - 1])}`
|
||||
: ''
|
||||
}`
|
||||
|
|
|
@ -104,7 +104,7 @@ describe('graph controls: when relsover is loaded with an origin node', () => {
|
|||
|
||||
describe('when the user clicks the west panning button', () => {
|
||||
beforeEach(async () => {
|
||||
(await simulator.resolve('resolver:graph-controls:west-button'))!.simulate('click');
|
||||
(await simulator.resolve('resolver:graph-controls:west-button'))?.simulate('click');
|
||||
simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration);
|
||||
});
|
||||
|
||||
|
@ -118,7 +118,7 @@ describe('graph controls: when relsover is loaded with an origin node', () => {
|
|||
|
||||
describe('when the user clicks the south panning button', () => {
|
||||
beforeEach(async () => {
|
||||
(await simulator.resolve('resolver:graph-controls:south-button'))!.simulate('click');
|
||||
(await simulator.resolve('resolver:graph-controls:south-button'))?.simulate('click');
|
||||
simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration);
|
||||
});
|
||||
|
||||
|
@ -132,7 +132,7 @@ describe('graph controls: when relsover is loaded with an origin node', () => {
|
|||
|
||||
describe('when the user clicks the east panning button', () => {
|
||||
beforeEach(async () => {
|
||||
(await simulator.resolve('resolver:graph-controls:east-button'))!.simulate('click');
|
||||
(await simulator.resolve('resolver:graph-controls:east-button'))?.simulate('click');
|
||||
simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration);
|
||||
});
|
||||
|
||||
|
@ -146,7 +146,7 @@ describe('graph controls: when relsover is loaded with an origin node', () => {
|
|||
|
||||
describe('when the user clicks the north panning button', () => {
|
||||
beforeEach(async () => {
|
||||
(await simulator.resolve('resolver:graph-controls:north-button'))!.simulate('click');
|
||||
(await simulator.resolve('resolver:graph-controls:north-button'))?.simulate('click');
|
||||
simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration);
|
||||
});
|
||||
|
||||
|
@ -160,9 +160,9 @@ describe('graph controls: when relsover is loaded with an origin node', () => {
|
|||
|
||||
describe('when the user clicks the center panning button', () => {
|
||||
beforeEach(async () => {
|
||||
(await simulator.resolve('resolver:graph-controls:north-button'))!.simulate('click');
|
||||
(await simulator.resolve('resolver:graph-controls:north-button'))?.simulate('click');
|
||||
simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration);
|
||||
(await simulator.resolve('resolver:graph-controls:center-button'))!.simulate('click');
|
||||
(await simulator.resolve('resolver:graph-controls:center-button'))?.simulate('click');
|
||||
simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration);
|
||||
});
|
||||
|
||||
|
@ -177,7 +177,7 @@ describe('graph controls: when relsover is loaded with an origin node', () => {
|
|||
|
||||
describe('when the zoom in button is clicked', () => {
|
||||
beforeEach(async () => {
|
||||
(await simulator.resolve('resolver:graph-controls:zoom-in'))!.simulate('click');
|
||||
(await simulator.resolve('resolver:graph-controls:zoom-in'))?.simulate('click');
|
||||
simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration);
|
||||
});
|
||||
|
||||
|
@ -191,7 +191,7 @@ describe('graph controls: when relsover is loaded with an origin node', () => {
|
|||
|
||||
describe('when the zoom out button is clicked', () => {
|
||||
beforeEach(async () => {
|
||||
(await simulator.resolve('resolver:graph-controls:zoom-out'))!.simulate('click');
|
||||
(await simulator.resolve('resolver:graph-controls:zoom-out'))?.simulate('click');
|
||||
simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration);
|
||||
});
|
||||
|
||||
|
@ -207,7 +207,7 @@ describe('graph controls: when relsover is loaded with an origin node', () => {
|
|||
beforeEach(async () => {
|
||||
await expect(originNodeStyle()).toYieldObjectEqualTo(originalSizeStyle);
|
||||
|
||||
(await simulator.resolve('resolver:graph-controls:zoom-slider'))!.simulate('change', {
|
||||
(await simulator.resolve('resolver:graph-controls:zoom-slider'))?.simulate('change', {
|
||||
target: { value: 0.8 },
|
||||
});
|
||||
simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration);
|
||||
|
@ -223,7 +223,7 @@ describe('graph controls: when relsover is loaded with an origin node', () => {
|
|||
|
||||
describe('when the slider is moved downwards', () => {
|
||||
beforeEach(async () => {
|
||||
(await simulator.resolve('resolver:graph-controls:zoom-slider'))!.simulate('change', {
|
||||
(await simulator.resolve('resolver:graph-controls:zoom-slider'))?.simulate('change', {
|
||||
target: { value: 0.2 },
|
||||
});
|
||||
simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration);
|
||||
|
@ -239,7 +239,7 @@ describe('graph controls: when relsover is loaded with an origin node', () => {
|
|||
|
||||
describe('when the schema information button is clicked', () => {
|
||||
beforeEach(async () => {
|
||||
(await simulator.resolve('resolver:graph-controls:schema-info-button'))!.simulate('click', {
|
||||
(await simulator.resolve('resolver:graph-controls:schema-info-button'))?.simulate('click', {
|
||||
button: 0,
|
||||
});
|
||||
});
|
||||
|
@ -257,7 +257,7 @@ describe('graph controls: when relsover is loaded with an origin node', () => {
|
|||
|
||||
describe('when the node legend button is clicked', () => {
|
||||
beforeEach(async () => {
|
||||
(await simulator.resolve('resolver:graph-controls:node-legend-button'))!.simulate('click', {
|
||||
(await simulator.resolve('resolver:graph-controls:node-legend-button'))?.simulate('click', {
|
||||
button: 0,
|
||||
});
|
||||
});
|
||||
|
@ -275,7 +275,7 @@ describe('graph controls: when relsover is loaded with an origin node', () => {
|
|||
|
||||
describe('when the node legend button is clicked while the schema info button is open', () => {
|
||||
beforeEach(async () => {
|
||||
(await simulator.resolve('resolver:graph-controls:schema-info-button'))!.simulate('click', {
|
||||
(await simulator.resolve('resolver:graph-controls:schema-info-button'))?.simulate('click', {
|
||||
button: 0,
|
||||
});
|
||||
});
|
||||
|
@ -284,8 +284,8 @@ describe('graph controls: when relsover is loaded with an origin node', () => {
|
|||
expect(simulator.testSubject('resolver:graph-controls:schema-info').length).toBe(1);
|
||||
|
||||
await simulator
|
||||
.testSubject('resolver:graph-controls:node-legend-button')!
|
||||
.simulate('click', { button: 0 });
|
||||
.testSubject('resolver:graph-controls:node-legend-button')
|
||||
?.simulate('click', { button: 0 });
|
||||
|
||||
await expect(
|
||||
simulator.map(() => ({
|
||||
|
|
|
@ -150,13 +150,13 @@ describe(`Resolver: when analyzing a tree with no ancestors and two children and
|
|||
.filterWhere(Simulator.isDOM);
|
||||
|
||||
expect(copyableFieldHoverArea).toHaveLength(1);
|
||||
copyableFieldHoverArea!.simulate('mouseenter');
|
||||
copyableFieldHoverArea?.simulate('mouseenter');
|
||||
});
|
||||
describe('and when they click the copy-to-clipboard button', () => {
|
||||
beforeEach(async () => {
|
||||
const copyButton = await simulator().resolve('resolver:panel:clipboard');
|
||||
expect(copyButton).toHaveLength(1);
|
||||
copyButton!.simulate('click');
|
||||
copyButton?.simulate('click');
|
||||
simulator().confirmTextWrittenToClipboard();
|
||||
});
|
||||
it(`should write ${value} to the clipboard`, async () => {
|
||||
|
@ -232,11 +232,11 @@ describe(`Resolver: when analyzing a tree with no ancestors and two children and
|
|||
.filterWhere(Simulator.isDOM)
|
||||
);
|
||||
});
|
||||
cExtHoverArea!.simulate('mouseenter');
|
||||
cExtHoverArea?.simulate('mouseenter');
|
||||
});
|
||||
describe('and when the user clicks the copy-to-clipboard button', () => {
|
||||
beforeEach(async () => {
|
||||
(await simulator().resolve('resolver:panel:clipboard'))!.simulate('click');
|
||||
(await simulator().resolve('resolver:panel:clipboard'))?.simulate('click');
|
||||
simulator().confirmTextWrittenToClipboard();
|
||||
});
|
||||
const expected = 'Sep 23, 2020 @ 08:25:32.316';
|
||||
|
@ -369,7 +369,7 @@ describe(`Resolver: when analyzing a tree with no ancestors and two children and
|
|||
beforeEach(async () => {
|
||||
const button = await simulator().resolve('resolver:panel:clipboard');
|
||||
expect(button).toBeTruthy();
|
||||
button!.simulate('click');
|
||||
button?.simulate('click');
|
||||
simulator().confirmTextWrittenToClipboard();
|
||||
});
|
||||
it(`should write ${expectedValue} to the clipboard`, async () => {
|
||||
|
|
|
@ -41,6 +41,7 @@ export const sideEffectSimulatorFactory: () => SideEffectSimulator = () => {
|
|||
*/
|
||||
const getBoundingClientRect: (target: Element) => DOMRect = (target) => {
|
||||
if (contentRects.has(target)) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
return contentRects.get(target)!;
|
||||
}
|
||||
const domRect: DOMRect = {
|
||||
|
|
|
@ -70,7 +70,7 @@ describe('Field Renderers', () => {
|
|||
|
||||
describe('#dateRenderer', () => {
|
||||
test('it renders correctly against snapshot', () => {
|
||||
const wrapper = shallow(dateRenderer(mockData.complete.source!.firstSeen));
|
||||
const wrapper = shallow(dateRenderer(mockData.complete.source?.firstSeen));
|
||||
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
@ -307,7 +307,7 @@ describe('Field Renderers', () => {
|
|||
);
|
||||
|
||||
expect(
|
||||
wrapper.find('[data-test-subj="more-container"]').first().props().style!.overflow
|
||||
wrapper.find('[data-test-subj="more-container"]').first().props().style?.overflow
|
||||
).toEqual('auto');
|
||||
});
|
||||
|
||||
|
@ -322,7 +322,7 @@ describe('Field Renderers', () => {
|
|||
);
|
||||
|
||||
expect(
|
||||
wrapper.find('[data-test-subj="more-container"]').first().props().style!.maxHeight
|
||||
wrapper.find('[data-test-subj="more-container"]').first().props().style?.maxHeight
|
||||
).toEqual(DEFAULT_MORE_MAX_HEIGHT);
|
||||
});
|
||||
|
||||
|
|
|
@ -77,6 +77,7 @@ const ActiveTimelinesComponent: React.FC<ActiveTimelinesProps> = ({
|
|||
<FormattedRelative
|
||||
data-test-subj="timeline-status"
|
||||
key="timeline-status-autosaved"
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
value={new Date(updated!)}
|
||||
/>
|
||||
</>
|
||||
|
|
|
@ -113,6 +113,7 @@ const FlyoutHeaderPanelComponent: React.FC<FlyoutHeaderPanelProps> = ({ timeline
|
|||
[dataProviders, kqlQuery]
|
||||
);
|
||||
const getKqlQueryTimeline = useMemo(() => timelineSelectors.getKqlFilterQuerySelector(), []);
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
const kqlQueryTimeline = useSelector((state: State) => getKqlQueryTimeline(state, timelineId)!);
|
||||
|
||||
const kqlQueryExpression =
|
||||
|
@ -333,6 +334,7 @@ const TimelineStatusInfoComponent: React.FC<FlyoutHeaderProps> = ({ timelineId }
|
|||
<FormattedRelative
|
||||
data-test-subj="timeline-status"
|
||||
key="timeline-status-autosaved"
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
value={new Date(updated!)}
|
||||
/>
|
||||
</EuiTextColor>
|
||||
|
@ -372,6 +374,7 @@ const FlyoutHeaderComponent: React.FC<FlyoutHeaderProps> = ({ timelineId }) => {
|
|||
);
|
||||
const { dataProviders, filters, timelineType, kqlMode, activeTab } = timeline;
|
||||
const getKqlQueryTimeline = useMemo(() => timelineSelectors.getKqlFilterQuerySelector(), []);
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
const kqlQueryTimeline = useSelector((state: State) => getKqlQueryTimeline(state, timelineId)!);
|
||||
|
||||
const kqlQueryExpression =
|
||||
|
|
|
@ -205,9 +205,11 @@ const convertToDefaultField = ({ and, ...dataProvider }: DataProviderResult) =>
|
|||
if (dataProvider.type === DataProviderType.template) {
|
||||
return deepMerge(dataProvider, {
|
||||
type: DataProviderType.default,
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
enabled: dataProvider.queryMatch!.operator !== IS_OPERATOR,
|
||||
queryMatch: {
|
||||
value:
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
dataProvider.queryMatch!.operator === IS_OPERATOR ? '' : dataProvider.queryMatch!.value,
|
||||
},
|
||||
});
|
||||
|
|
|
@ -318,7 +318,7 @@ describe('StatefulOpenTimeline', () => {
|
|||
await waitFor(() => {
|
||||
expect(
|
||||
wrapper.find(`.${OPEN_TIMELINE_CLASS_NAME} input`).first().getDOMNode().id ===
|
||||
document.activeElement!.id
|
||||
document.activeElement?.id
|
||||
).toBe(true);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -44,7 +44,7 @@ describe('NotePreviews', () => {
|
|||
|
||||
const wrapper = mountWithIntl(<NotePreviews notes={hasNotes[0].notes} />);
|
||||
|
||||
hasNotes[0].notes!.forEach(({ savedObjectId }) => {
|
||||
hasNotes[0].notes?.forEach(({ savedObjectId }) => {
|
||||
expect(wrapper.find(`[data-test-subj="note-preview-${savedObjectId}"]`).exists()).toBe(true);
|
||||
});
|
||||
});
|
||||
|
@ -54,7 +54,7 @@ describe('NotePreviews', () => {
|
|||
|
||||
const wrapper = mountWithIntl(<NotePreviews notes={hasNotes[0].notes} />);
|
||||
|
||||
hasNotes[0].notes!.forEach(({ savedObjectId }) => {
|
||||
hasNotes[0].notes?.forEach(({ savedObjectId }) => {
|
||||
expect(wrapper.find(`[data-test-subj="note-preview-${savedObjectId}"]`).exists()).toBe(true);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -40,6 +40,7 @@ export const getActionsColumns = ({
|
|||
onOpenTimeline({
|
||||
duplicate: true,
|
||||
timelineType: TimelineType.default,
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
timelineId: savedObjectId!,
|
||||
});
|
||||
},
|
||||
|
@ -58,6 +59,7 @@ export const getActionsColumns = ({
|
|||
onOpenTimeline({
|
||||
duplicate: true,
|
||||
timelineType: TimelineType.template,
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
timelineId: savedObjectId!,
|
||||
});
|
||||
},
|
||||
|
|
|
@ -108,7 +108,7 @@ export const ExpandableEvent = React.memo<Props>(
|
|||
<EventDetails
|
||||
browserFields={browserFields}
|
||||
data={detailsData ?? []}
|
||||
id={event.eventId!}
|
||||
id={event.eventId}
|
||||
isAlert={isAlert}
|
||||
isDraggable={isDraggable}
|
||||
timelineId={timelineId}
|
||||
|
|
|
@ -61,7 +61,7 @@ export const HeaderToolTipContent = React.memo<{ header: ColumnHeaderOptions }>(
|
|||
{':'}
|
||||
</ToolTipTableMetadata>
|
||||
<ToolTipTableValue>
|
||||
<IconType data-test-subj="type-icon" type={getIconFromType(header.type!)} />
|
||||
<IconType data-test-subj="type-icon" type={getIconFromType(header.type)} />
|
||||
<span data-test-subj="type-value">{header.type}</span>
|
||||
</ToolTipTableValue>
|
||||
</P>
|
||||
|
|
|
@ -185,6 +185,7 @@ const StatefulEventComponent: React.FC<Props> = ({
|
|||
|
||||
const handleOnEventDetailPanelOpened = useCallback(() => {
|
||||
const eventId = event._id;
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
const indexName = event._index!;
|
||||
|
||||
const updatedExpandedDetail: TimelineExpandedDetailType = {
|
||||
|
|
|
@ -111,7 +111,7 @@ export const BodyComponent = React.memo<StatefulBodyProps>(
|
|||
|
||||
const onRowSelected: OnRowSelected = useCallback(
|
||||
({ eventIds, isSelected }: { eventIds: string[]; isSelected: boolean }) => {
|
||||
setSelected!({
|
||||
setSelected({
|
||||
id,
|
||||
eventIds: getEventIdToDataMapping(data, eventIds, queryFields),
|
||||
isSelected,
|
||||
|
@ -125,7 +125,7 @@ export const BodyComponent = React.memo<StatefulBodyProps>(
|
|||
const onSelectAll: OnSelectAll = useCallback(
|
||||
({ isSelected }: { isSelected: boolean }) =>
|
||||
isSelected
|
||||
? setSelected!({
|
||||
? setSelected({
|
||||
id,
|
||||
eventIds: getEventIdToDataMapping(
|
||||
data,
|
||||
|
@ -135,7 +135,7 @@ export const BodyComponent = React.memo<StatefulBodyProps>(
|
|||
isSelected,
|
||||
isSelectAllChecked: isSelected,
|
||||
})
|
||||
: clearSelected!({ id }),
|
||||
: clearSelected({ id }),
|
||||
[setSelected, clearSelected, id, data, queryFields]
|
||||
);
|
||||
|
||||
|
|
|
@ -78,7 +78,7 @@ describe('suricata_row_renderer', () => {
|
|||
});
|
||||
|
||||
test('should render a suricata row even if it does not have a suricata signature', () => {
|
||||
delete suricata!.suricata!.eve!.alert!.signature;
|
||||
delete suricata?.suricata?.eve?.alert?.signature;
|
||||
const children = suricataRowRenderer.renderRow({
|
||||
browserFields: mockBrowserFields,
|
||||
data: suricata,
|
||||
|
|
|
@ -76,12 +76,12 @@ export const DraggableZeekElement = React.memo<{
|
|||
and: [],
|
||||
enabled: true,
|
||||
id: escapeDataProviderId(`draggable-zeek-element-draggable-wrapper-${id}-${field}-${value}`),
|
||||
name: value!,
|
||||
name: String(value),
|
||||
excluded: false,
|
||||
kqlQuery: '',
|
||||
queryMatch: {
|
||||
field,
|
||||
value: value!,
|
||||
value: String(value),
|
||||
operator: IS_OPERATOR as QueryOperator,
|
||||
},
|
||||
}),
|
||||
|
@ -97,7 +97,7 @@ export const DraggableZeekElement = React.memo<{
|
|||
) : (
|
||||
<EuiToolTip data-test-subj="badge-tooltip" content={field}>
|
||||
<Badge iconType="tag" color="hollow" title="">
|
||||
{stringRenderer(value!)}
|
||||
{stringRenderer(String(value))}
|
||||
</Badge>
|
||||
</EuiToolTip>
|
||||
),
|
||||
|
|
|
@ -113,7 +113,7 @@ const AddDataProviderPopoverComponent: React.FC<AddDataProviderPopoverProps> = (
|
|||
width: 400,
|
||||
content: (
|
||||
<StatefulEditDataProvider
|
||||
browserFields={browserFields!}
|
||||
browserFields={browserFields}
|
||||
field=""
|
||||
isExcluded={false}
|
||||
onDataProviderEdited={handleDataProviderEdited}
|
||||
|
@ -131,7 +131,7 @@ const AddDataProviderPopoverComponent: React.FC<AddDataProviderPopoverProps> = (
|
|||
width: 400,
|
||||
content: (
|
||||
<StatefulEditDataProvider
|
||||
browserFields={browserFields!}
|
||||
browserFields={browserFields}
|
||||
field=""
|
||||
isExcluded={false}
|
||||
onDataProviderEdited={handleDataProviderEdited}
|
||||
|
@ -182,7 +182,7 @@ const AddDataProviderPopoverComponent: React.FC<AddDataProviderPopoverProps> = (
|
|||
|
||||
return (
|
||||
<StatefulEditDataProvider
|
||||
browserFields={browserFields!}
|
||||
browserFields={browserFields}
|
||||
field=""
|
||||
isExcluded={false}
|
||||
onDataProviderEdited={handleDataProviderEdited}
|
||||
|
|
|
@ -95,8 +95,11 @@ const ParticipantsComponent: React.FC<ParticipantsProps> = ({ users }) => {
|
|||
const List = useMemo(
|
||||
() =>
|
||||
users.map((user) => (
|
||||
<Fragment key={user.updatedBy!}>
|
||||
<UsernameWithAvatar key={user.updatedBy!} username={user.updatedBy!} />
|
||||
<Fragment key={user.updatedBy === null ? undefined : user.updatedBy}>
|
||||
<UsernameWithAvatar
|
||||
key={user.updatedBy === null ? undefined : user.updatedBy}
|
||||
username={String(user.updatedBy)}
|
||||
/>
|
||||
<EuiSpacer size="s" />
|
||||
</Fragment>
|
||||
)),
|
||||
|
|
|
@ -463,7 +463,7 @@ const makeMapStateToProps = () => {
|
|||
status,
|
||||
timelineType,
|
||||
} = timeline;
|
||||
const kqlQueryTimeline = getKqlQueryTimeline(state, timelineId)!;
|
||||
const kqlQueryTimeline = getKqlQueryTimeline(state, timelineId);
|
||||
const timelineFilter = kqlMode === 'filter' ? filters || [] : [];
|
||||
|
||||
// return events on empty search
|
||||
|
|
|
@ -74,7 +74,7 @@ const StatefulSearchOrFilterComponent = React.memo<Props>(
|
|||
from={from}
|
||||
fromStr={fromStr}
|
||||
isRefreshPaused={isRefreshPaused}
|
||||
kqlMode={kqlMode!}
|
||||
kqlMode={kqlMode}
|
||||
refreshInterval={refreshInterval}
|
||||
savedQueryId={savedQueryId}
|
||||
setFilters={setFiltersInTimeline}
|
||||
|
@ -82,7 +82,7 @@ const StatefulSearchOrFilterComponent = React.memo<Props>(
|
|||
timelineId={timelineId}
|
||||
to={to}
|
||||
toStr={toStr}
|
||||
updateKqlMode={updateKqlMode!}
|
||||
updateKqlMode={updateKqlMode}
|
||||
updateReduxTime={updateReduxTime}
|
||||
/>
|
||||
);
|
||||
|
@ -119,15 +119,19 @@ const makeMapStateToProps = () => {
|
|||
const policy: inputsModel.Policy = getInputsPolicy(state);
|
||||
return {
|
||||
dataProviders: timeline.dataProviders,
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
filterQuery: getKqlFilterQuery(state, timelineId)!,
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
filters: timeline.filters!,
|
||||
from: input.timerange.from,
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
fromStr: input.timerange.fromStr!,
|
||||
isRefreshPaused: policy.kind === 'manual',
|
||||
kqlMode: getOr('filter', 'kqlMode', timeline),
|
||||
refreshInterval: policy.duration,
|
||||
savedQueryId: getOr(null, 'savedQueryId', timeline),
|
||||
to: input.timerange.to,
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
toStr: input.timerange.toStr!,
|
||||
};
|
||||
};
|
||||
|
|
|
@ -47,7 +47,7 @@ describe('SelectableTimeline', () => {
|
|||
const searchProps: EuiSelectableProps['searchProps'] = wrapper
|
||||
.find('[data-test-subj="selectable-input"]')
|
||||
.prop('searchProps');
|
||||
expect(searchProps!.placeholder).toEqual('e.g. Timeline name or description');
|
||||
expect(searchProps?.placeholder).toEqual('e.g. Timeline name or description');
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -65,7 +65,7 @@ describe('SelectableTimeline', () => {
|
|||
const searchProps: EuiSelectableProps['searchProps'] = wrapper
|
||||
.find('[data-test-subj="selectable-input"]')
|
||||
.prop('searchProps');
|
||||
expect(searchProps!.placeholder).toEqual('e.g. Timeline template name or description');
|
||||
expect(searchProps?.placeholder).toEqual('e.g. Timeline template name or description');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -110,8 +110,8 @@ const SelectableTimelineComponent: React.FC<SelectableTimelineProps> = ({
|
|||
selectableListOuterRef.current &&
|
||||
selectableListInnerRef.current
|
||||
) {
|
||||
const clientHeight = selectableListOuterRef.current!.clientHeight;
|
||||
const scrollHeight = selectableListInnerRef.current!.clientHeight;
|
||||
const clientHeight = selectableListOuterRef.current.clientHeight;
|
||||
const scrollHeight = selectableListInnerRef.current.clientHeight;
|
||||
const clientHeightTrigger = clientHeight * 1.2;
|
||||
if (
|
||||
scrollOffset > 10 &&
|
||||
|
|
|
@ -271,13 +271,13 @@ export const EventsTrData = styled.div.attrs(({ className = '' }) => ({
|
|||
const TIMELINE_EVENT_DETAILS_OFFSET = 40;
|
||||
|
||||
interface WidthProp {
|
||||
width?: number;
|
||||
width: number;
|
||||
}
|
||||
|
||||
export const EventsTrSupplementContainer = styled.div.attrs<WidthProp>(({ width }) => ({
|
||||
role: 'dialog',
|
||||
style: {
|
||||
width: `${width! - TIMELINE_EVENT_DETAILS_OFFSET}px`,
|
||||
width: `${width - TIMELINE_EVENT_DETAILS_OFFSET}px`,
|
||||
},
|
||||
}))<WidthProp>``;
|
||||
|
||||
|
|
|
@ -156,6 +156,7 @@ export const persistTimeline = async ({
|
|||
try {
|
||||
if (isEmpty(timelineId) && timeline.status === TimelineStatus.draft && timeline) {
|
||||
const temp: TimelineResponse | TimelineErrorResponse = await cleanDraftTimeline({
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
timelineType: timeline.timelineType!,
|
||||
templateTimelineId: timeline.templateTimelineId ?? undefined,
|
||||
templateTimelineVersion: timeline.templateTimelineVersion ?? undefined,
|
||||
|
@ -163,7 +164,7 @@ export const persistTimeline = async ({
|
|||
|
||||
const draftTimeline = decodeTimelineResponse(temp);
|
||||
const templateTimelineInfo =
|
||||
timeline.timelineType! === TimelineType.template
|
||||
timeline.timelineType === TimelineType.template
|
||||
? {
|
||||
templateTimelineId:
|
||||
draftTimeline.data.persistTimeline.timeline.templateTimelineId ??
|
||||
|
|
|
@ -235,7 +235,7 @@ export const createTimelineEpic =
|
|||
mergeMap(([result, recentTimeline, allTimelineQuery, kibana]) => {
|
||||
const error = result as TimelineErrorResponse;
|
||||
if (error.status_code != null && error.status_code === 405) {
|
||||
kibana.notifications!.toasts.addDanger({
|
||||
kibana.notifications.toasts.addDanger({
|
||||
title: i18n.UPDATE_TIMELINE_ERROR_TITLE,
|
||||
text: error.message ?? i18n.UPDATE_TIMELINE_ERROR_TEXT,
|
||||
});
|
||||
|
|
|
@ -1126,8 +1126,8 @@ describe('Timeline', () => {
|
|||
const newAndProvider = update.foo.dataProviders[indexProvider].and.find(
|
||||
(i) => i.id === '456'
|
||||
);
|
||||
expect(oldAndProvider!.enabled).toEqual(false);
|
||||
expect(newAndProvider!.enabled).toEqual(true);
|
||||
expect(oldAndProvider?.enabled).toEqual(false);
|
||||
expect(newAndProvider?.enabled).toEqual(true);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -1386,8 +1386,8 @@ describe('Timeline', () => {
|
|||
const newAndProvider = update.foo.dataProviders[indexProvider].and.find(
|
||||
(i) => i.id === '456'
|
||||
);
|
||||
expect(oldAndProvider!.excluded).toEqual(true);
|
||||
expect(newAndProvider!.excluded).toEqual(false);
|
||||
expect(oldAndProvider?.excluded).toEqual(true);
|
||||
expect(newAndProvider?.excluded).toEqual(false);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -135,6 +135,7 @@ export class ManifestTask {
|
|||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
if (oldManifest! == null) {
|
||||
this.logger.debug('Last computed manifest not available yet');
|
||||
return;
|
||||
|
|
|
@ -130,7 +130,7 @@ describe('Policy-Changing license watcher', () => {
|
|||
|
||||
expect(packagePolicySvcMock.update).toHaveBeenCalled();
|
||||
expect(
|
||||
packagePolicySvcMock.update.mock.calls[0][3].inputs[0].config!.policy.value.windows.popup
|
||||
packagePolicySvcMock.update.mock.calls[0][3].inputs[0].config?.policy.value.windows.popup
|
||||
.malware.message
|
||||
).not.toEqual(CustomMessage);
|
||||
});
|
||||
|
|
|
@ -189,6 +189,7 @@ export const isolationRequestHandler = function (
|
|||
},
|
||||
} as Omit<EndpointAction, 'agents' | 'user_id'>,
|
||||
user: {
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
id: user!.username,
|
||||
},
|
||||
};
|
||||
|
|
|
@ -114,8 +114,8 @@ describe('test document enrichment', () => {
|
|||
|
||||
const enrichedHostList = await enrichHostMetadata(docGen.generateHostMetadata(), metaReqCtx);
|
||||
expect(enrichedHostList.policy_info).toBeDefined();
|
||||
expect(enrichedHostList.policy_info!.agent.applied.id).toEqual(policyID);
|
||||
expect(enrichedHostList.policy_info!.agent.applied.revision).toEqual(policyRev);
|
||||
expect(enrichedHostList.policy_info?.agent.applied.id).toEqual(policyID);
|
||||
expect(enrichedHostList.policy_info?.agent.applied.revision).toEqual(policyRev);
|
||||
});
|
||||
|
||||
it('reflects current fleet agent info', async () => {
|
||||
|
@ -130,8 +130,8 @@ describe('test document enrichment', () => {
|
|||
|
||||
const enrichedHostList = await enrichHostMetadata(docGen.generateHostMetadata(), metaReqCtx);
|
||||
expect(enrichedHostList.policy_info).toBeDefined();
|
||||
expect(enrichedHostList.policy_info!.agent.configured.id).toEqual(policyID);
|
||||
expect(enrichedHostList.policy_info!.agent.configured.revision).toEqual(policyRev);
|
||||
expect(enrichedHostList.policy_info?.agent.configured.id).toEqual(policyID);
|
||||
expect(enrichedHostList.policy_info?.agent.configured.revision).toEqual(policyRev);
|
||||
});
|
||||
|
||||
it('reflects current endpoint policy info', async () => {
|
||||
|
@ -151,8 +151,8 @@ describe('test document enrichment', () => {
|
|||
|
||||
const enrichedHostList = await enrichHostMetadata(docGen.generateHostMetadata(), metaReqCtx);
|
||||
expect(enrichedHostList.policy_info).toBeDefined();
|
||||
expect(enrichedHostList.policy_info!.endpoint.id).toEqual(policyID);
|
||||
expect(enrichedHostList.policy_info!.endpoint.revision).toEqual(policyRev);
|
||||
expect(enrichedHostList.policy_info?.endpoint.id).toEqual(policyID);
|
||||
expect(enrichedHostList.policy_info?.endpoint.revision).toEqual(policyRev);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -114,6 +114,7 @@ export const getMetadataListRequestHandler = function (
|
|||
}
|
||||
|
||||
const endpointPolicies = await getAllEndpointPackagePolicies(
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
endpointAppContext.service.getPackagePolicyService()!,
|
||||
context.core.savedObjects.client
|
||||
);
|
||||
|
@ -344,6 +345,7 @@ export async function enrichHostMetadata(
|
|||
const status = await metadataRequestContext.endpointAppContextService
|
||||
?.getAgentService()
|
||||
?.getAgentStatusById(esClient.asCurrentUser, elasticAgentId);
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
hostStatus = fleetAgentStatusToEndpointHostStatus(status!);
|
||||
} catch (e) {
|
||||
if (e instanceof AgentNotFoundError) {
|
||||
|
@ -361,6 +363,7 @@ export async function enrichHostMetadata(
|
|||
?.getAgent(esClient.asCurrentUser, elasticAgentId);
|
||||
const agentPolicy = await metadataRequestContext.endpointAppContextService
|
||||
.getAgentPolicyService()
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
?.get(esSavedObjectClient, agent?.policy_id!, true);
|
||||
const endpointPolicy = ((agentPolicy?.package_policies || []) as PackagePolicy[]).find(
|
||||
(policy: PackagePolicy) => policy.package?.name === 'endpoint'
|
||||
|
@ -404,6 +407,7 @@ async function legacyListMetadataQuery(
|
|||
logger: Logger,
|
||||
endpointPolicies: PackagePolicy[]
|
||||
): Promise<HostResultList> {
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
const agentService = endpointAppContext.service.getAgentService()!;
|
||||
|
||||
const metadataRequestContext: MetadataRequestContext = {
|
||||
|
@ -512,11 +516,15 @@ async function queryUnitedIndex(
|
|||
return metadata && agent;
|
||||
})
|
||||
.map((doc) => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
const { endpoint: metadata, agent } = doc!._source!.united!;
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
const agentPolicy = agentPoliciesMap[agent.policy_id!];
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
const endpointPolicy = endpointPoliciesMap[agent.policy_id!];
|
||||
return {
|
||||
metadata,
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
host_status: fleetAgentStatusToEndpointHostStatus(agent.last_checkin_status!),
|
||||
policy_info: {
|
||||
agent: {
|
||||
|
|
|
@ -171,8 +171,8 @@ describe('test endpoint route', () => {
|
|||
const esSearchMock = mockScopedClient.asCurrentUser.search;
|
||||
// should be called twice, united index first, then legacy index
|
||||
expect(esSearchMock).toHaveBeenCalledTimes(2);
|
||||
expect(esSearchMock.mock.calls[0][0]!.index).toEqual(METADATA_UNITED_INDEX);
|
||||
expect(esSearchMock.mock.calls[1][0]!.index).toEqual(metadataCurrentIndexPattern);
|
||||
expect(esSearchMock.mock.calls[0][0]?.index).toEqual(METADATA_UNITED_INDEX);
|
||||
expect(esSearchMock.mock.calls[1][0]?.index).toEqual(metadataCurrentIndexPattern);
|
||||
expect(routeConfig.options).toEqual({
|
||||
authRequired: true,
|
||||
tags: ['access:securitySolution'],
|
||||
|
@ -224,7 +224,7 @@ describe('test endpoint route', () => {
|
|||
);
|
||||
|
||||
expect(esSearchMock).toHaveBeenCalledTimes(1);
|
||||
expect(esSearchMock.mock.calls[0][0]!.index).toEqual(METADATA_UNITED_INDEX);
|
||||
expect(esSearchMock.mock.calls[0][0]?.index).toEqual(METADATA_UNITED_INDEX);
|
||||
expect(esSearchMock.mock.calls[0][0]?.body?.query).toEqual({
|
||||
bool: {
|
||||
must: [
|
||||
|
|
|
@ -53,8 +53,8 @@ export async function kibanaRequestToMetadataListESQuery(
|
|||
body: {
|
||||
query: buildQueryBody(
|
||||
request,
|
||||
queryBuilderOptions?.unenrolledAgentIds!,
|
||||
queryBuilderOptions?.statusAgentIds!
|
||||
queryBuilderOptions?.unenrolledAgentIds,
|
||||
queryBuilderOptions?.statusAgentIds
|
||||
),
|
||||
track_total_hits: true,
|
||||
sort: MetadataSortMethod,
|
||||
|
|
|
@ -120,12 +120,14 @@ export async function agentVersionsMap(
|
|||
const result: Map<string, number> = new Map<string, number>();
|
||||
let hasMore = true;
|
||||
while (hasMore) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
const queryResult = await endpointAppContext.service
|
||||
.getAgentService()!
|
||||
.listAgents(esClient, searchOptions(page++));
|
||||
queryResult.agents.forEach((agent: Agent) => {
|
||||
const agentVersion = agent.local_metadata?.elastic?.agent?.version;
|
||||
if (result.has(agentVersion)) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
result.set(agentVersion, result.get(agentVersion)! + 1);
|
||||
} else {
|
||||
result.set(agentVersion, 1);
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue