[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:
Frank Hassanabad 2021-10-14 20:24:01 -06:00 committed by GitHub
parent 45f02d3c9b
commit ed9859ac14
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
149 changed files with 367 additions and 238 deletions

View file

@ -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

View file

@ -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 => {

View file

@ -161,7 +161,7 @@ export async function indexEndpointHostDocs({
const indexedAgentResponse = await indexFleetAgentForHost(
client,
kbnClient,
hostMetadata!,
hostMetadata,
realPolicies[appliedPolicyId].policy_id,
kibanaVersion
);

View file

@ -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);

View file

@ -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');

View file

@ -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}`);

View file

@ -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));
});
});
});

View file

@ -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);

View file

@ -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)
);

View file

@ -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));
});
});
});

View file

@ -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');
});
});

View file

@ -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');

View file

@ -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);
});
});
});

View file

@ -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}"]`;
};

View file

@ -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)

View file

@ -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;

View file

@ -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);
});
};

View file

@ -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}
/>

View file

@ -12,7 +12,7 @@ import { mockBrowserFields } from '../../containers/source/mock';
const aField = {
...mockDetailItemData[4],
...mockBrowserFields.base.fields!['@timestamp'],
...mockBrowserFields.base.fields?.['@timestamp'],
};
describe('helpers', () => {

View file

@ -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':

View file

@ -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>

View file

@ -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}

View file

@ -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!);
},
}

View file

@ -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);

View file

@ -78,7 +78,7 @@ const experimentalFeaturesReducer: Reducer<State['app'], UpdateExperimentalFeatu
return {
...state,
enableExperimental: {
...state.enableExperimental!,
...state.enableExperimental,
...action.payload,
},
};

View file

@ -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: [''],
},

View file

@ -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

View file

@ -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,

View file

@ -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);
},

View file

@ -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);

View file

@ -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]

View file

@ -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]

View file

@ -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: {

View file

@ -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()
),

View file

@ -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]

View file

@ -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' }}
>

View file

@ -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;
}

View file

@ -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();

View file

@ -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,
};

View file

@ -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;

View file

@ -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);
});
});

View file

@ -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();
});

View file

@ -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,
},
});
});

View file

@ -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
)

View file

@ -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);

View file

@ -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);

View file

@ -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',

View file

@ -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);
});
});

View file

@ -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', () => {

View file

@ -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,
});
}

View file

@ -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 },
}
),
});

View file

@ -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)!;
}),
},

View file

@ -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]

View file

@ -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)!,
},
});

View file

@ -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;
};

View file

@ -143,7 +143,7 @@ export const EffectedPolicySelect = memo<EffectedPolicySelectProps>(
});
},
[isGlobal, onChange]
)!;
);
const handleGlobalButtonChange = useCallback(
(selectedId) => {

View file

@ -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,

View file

@ -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',
});

View file

@ -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();

View file

@ -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',
});

View file

@ -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',
});

View file

@ -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
: {}),
},
},

View file

@ -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 = [

View file

@ -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;

View file

@ -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)

View file

@ -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])}`
: ''
}`

View file

@ -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(() => ({

View file

@ -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 () => {

View file

@ -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 = {

View file

@ -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);
});

View file

@ -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!)}
/>
</>

View file

@ -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 =

View file

@ -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,
},
});

View file

@ -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);
});
});

View file

@ -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);
});
});

View file

@ -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!,
});
},

View file

@ -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}

View file

@ -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>

View file

@ -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 = {

View file

@ -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]
);

View file

@ -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,

View file

@ -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>
),

View file

@ -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}

View file

@ -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>
)),

View file

@ -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

View file

@ -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!,
};
};

View file

@ -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');
});
});
});

View file

@ -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 &&

View file

@ -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>``;

View file

@ -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 ??

View file

@ -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,
});

View file

@ -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);
});
});

View file

@ -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;

View file

@ -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);
});

View file

@ -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,
},
};

View file

@ -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);
});
});
});

View file

@ -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: {

View file

@ -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: [

View file

@ -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,

View file

@ -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