Skip to content

Commit

Permalink
avoid showing unuseful error toast when ds is not yet selected (#1186)
Browse files Browse the repository at this point in the history
Signed-off-by: Amardeepsingh Siglani <[email protected]>
(cherry picked from commit e4fdd25)
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
  • Loading branch information
github-actions[bot] committed Oct 16, 2024
1 parent 27ac0fa commit 2d46fa6
Show file tree
Hide file tree
Showing 7 changed files with 157 additions and 124 deletions.
1 change: 1 addition & 0 deletions public/pages/Main/Main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,7 @@ export default class Main extends Component<MainProps, MainState> {
this.setState({
selectedDataSource: { ...sources[0] },
});
DataStore.logTypes.getLogTypes();
}
dataSourceObservable.next({
id: this.state.selectedDataSource.id,
Expand Down
10 changes: 8 additions & 2 deletions public/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ import { BehaviorSubject } from 'rxjs';

export interface SecurityAnalyticsPluginSetupDeps {
data: DataPublicPluginSetup;
dataSourceManagement: DataSourceManagementPluginSetup;
dataSourceManagement?: DataSourceManagementPluginSetup;
}
export interface SecurityAnalyticsPluginStartDeps {
data: DataPublicPluginStart;
Expand Down Expand Up @@ -232,7 +232,13 @@ export class SecurityAnalyticsPlugin
{ id: THREAT_ALERTS_NAV_ID, showInAllNavGroup: true },
{ id: FINDINGS_NAV_ID, showInAllNavGroup: true },
{ id: CORRELATIONS_NAV_ID, showInAllNavGroup: true },
{ id: PLUGIN_NAME, category: DEFAULT_APP_CATEGORIES.configure, title: 'Threat detection', showInAllNavGroup: true, order: 600 },
{
id: PLUGIN_NAME,
category: DEFAULT_APP_CATEGORIES.configure,
title: 'Threat detection',
showInAllNavGroup: true,
order: 600,
},
{ id: DETECTORS_NAV_ID, parentNavLinkId: PLUGIN_NAME, showInAllNavGroup: true },
{ id: DETECTION_RULE_NAV_ID, parentNavLinkId: PLUGIN_NAME, showInAllNavGroup: true },
{ id: CORRELATIONS_RULE_NAV_ID, showInAllNavGroup: true },
Expand Down
145 changes: 75 additions & 70 deletions public/security_analytics_app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,81 +35,86 @@ export function renderApp(
const services = getBrowserServices();
const metrics = new MetricsContext(services.metricsService);

DataStore.logTypes.getLogTypes().then((logTypes: LogType[]) => {
ReactDOM.render(
<Router>
<Route
render={(props) => {
const originalMethods = {
push: props.history.push,
replace: props.history.replace,
};
const wrapper = (method: 'push' | 'replace') => (
...args: Parameters<History['push']>
) => {
if (typeof args[0] === 'string') {
const url = new URL(args[0], window.location.origin);
const searchParams = url.searchParams;
searchParams.set('dataSourceId', dataSourceInfo.activeDataSource.id);
originalMethods[method](
{
pathname: url.pathname,
search: searchParams.toString(),
},
...args.slice(1)
);
} else if (typeof args[0] === 'object') {
const searchParams = new URLSearchParams(args[0].search);
searchParams.set('dataSourceId', dataSourceInfo.activeDataSource.id);
originalMethods[method](
{
...args[0],
search: searchParams.toString(),
},
...args.slice(1)
);
} else {
originalMethods[method](...args);
}
};
DataStore.logTypes
.getLogTypes()
.then((logTypes: LogType[]) => {
ReactDOM.render(
<Router>
<Route
render={(props) => {
const originalMethods = {
push: props.history.push,
replace: props.history.replace,
};
const wrapper = (method: 'push' | 'replace') => (
...args: Parameters<History['push']>
) => {
if (typeof args[0] === 'string') {
const url = new URL(args[0], window.location.origin);
const searchParams = url.searchParams;
searchParams.set('dataSourceId', dataSourceInfo.activeDataSource.id);
originalMethods[method](
{
pathname: url.pathname,
search: searchParams.toString(),
},
...args.slice(1)
);
} else if (typeof args[0] === 'object') {
const searchParams = new URLSearchParams(args[0].search);
searchParams.set('dataSourceId', dataSourceInfo.activeDataSource.id);
originalMethods[method](
{
...args[0],
search: searchParams.toString(),
},
...args.slice(1)
);
} else {
originalMethods[method](...args);
}
};

props.history = {
...props.history,
push: wrapper('push'),
replace: wrapper('replace'),
};
props.history = {
...props.history,
push: wrapper('push'),
replace: wrapper('replace'),
};

return (
<DarkModeContext.Provider value={isDarkMode}>
<SecurityAnalyticsContext.Provider value={{ services, metrics }}>
<CoreServicesContext.Provider value={coreStart}>
<Main
{...props}
landingPage={landingPage}
multiDataSourceEnabled={!!depsStart.dataSource}
dataSourceManagement={dataSourceManagement}
setActionMenu={params.setHeaderActionMenu}
/>
</CoreServicesContext.Provider>
</SecurityAnalyticsContext.Provider>
</DarkModeContext.Provider>
);
}}
/>
</Router>,
params.element
);
return (
<DarkModeContext.Provider value={isDarkMode}>
<SecurityAnalyticsContext.Provider value={{ services, metrics }}>
<CoreServicesContext.Provider value={coreStart}>
<Main
{...props}
landingPage={landingPage}
multiDataSourceEnabled={!!depsStart.dataSource}
dataSourceManagement={dataSourceManagement}
setActionMenu={params.setHeaderActionMenu}
/>
</CoreServicesContext.Provider>
</SecurityAnalyticsContext.Provider>
</DarkModeContext.Provider>
);
}}
/>
</Router>,
params.element
);

services.notificationsService.getServerFeatures().then((response) => {
if (response.ok) {
CHANNEL_TYPES.splice(0, CHANNEL_TYPES.length, ...response.response);
}
});
services.notificationsService.getServerFeatures().then((response) => {
if (response.ok) {
CHANNEL_TYPES.splice(0, CHANNEL_TYPES.length, ...response.response);
}
});

getPlugins(services.opensearchService).then((plugins): void => {
setIsNotificationPluginInstalled(plugins.includes(OS_NOTIFICATION_PLUGIN));
getPlugins(services.opensearchService).then((plugins): void => {
setIsNotificationPluginInstalled(plugins.includes(OS_NOTIFICATION_PLUGIN));
});
})
.catch((error) => {
console.error(error.message ?? error);
});
});

return () => ReactDOM.unmountComponentAtNode(params.element);
}
6 changes: 2 additions & 4 deletions public/services/utils/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,7 @@ export const [getBreadCrumbsSetter, setBreadCrumbsSetter] = createGetterSetter<
CoreStart['chrome']['setBreadcrumbs']
>('breadCrumbSetter');

export const [getChrome, setChrome] = createGetterSetter<
CoreStart['chrome']
>('chrome');
export const [getChrome, setChrome] = createGetterSetter<CoreStart['chrome']>('chrome');

export const [getContentManagement, setContentManagement] = createGetterSetter<
ContentManagementPluginStart
Expand All @@ -59,4 +57,4 @@ export const [getSavedObjectsClient, setSavedObjectsClient] = createGetterSetter
export const [
getDataSourceManagementPlugin,
setDataSourceManagementPlugin,
] = createNullableGetterSetter<DataSourceManagementPluginSetup>();
] = createNullableGetterSetter<DataSourceManagementPluginSetup | undefined>();
114 changes: 66 additions & 48 deletions public/store/LogTypeStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@ import LogTypeService from '../services/LogTypeService';
import { errorNotificationToast } from '../utils/helpers';
import { DataStore } from './DataStore';
import { ruleTypes } from '../pages/Rules/utils/constants';
import { logTypeCategories, logTypesByCategories } from '../utils/constants';
import {
DATA_SOURCE_NOT_SET_ERROR,
logTypeCategories,
logTypesByCategories,
} from '../utils/constants';
import { getLogTypeLabel } from '../pages/LogTypes/utils/helpers';

export class LogTypeStore {
Expand Down Expand Up @@ -41,58 +45,72 @@ export class LogTypeStore {
}

public async getLogTypes(): Promise<LogType[]> {
const logTypesRes = await this.service.searchLogTypes();
if (logTypesRes.ok) {
const logTypes: LogType[] = logTypesRes.response.hits.hits.map((hit) => {
return {
id: hit._id,
...hit._source,
source: hit._source.source.toLowerCase() === 'sigma' ? 'Standard' : hit._source.source,
};
});
try {
const logTypesRes = await this.service.searchLogTypes();
if (logTypesRes.ok) {
const logTypes: LogType[] = logTypesRes.response.hits.hits.map((hit) => {
return {
id: hit._id,
...hit._source,
source: hit._source.source.toLowerCase() === 'sigma' ? 'Standard' : hit._source.source,
};
});

ruleTypes.splice(
0,
ruleTypes.length,
...logTypes
.map(({ category, id, name, source }) => ({
label: getLogTypeLabel(name),
value: name,
id,
category,
isStandard: source === 'Standard',
}))
.sort((a, b) => {
return a.label < b.label ? -1 : a.label > b.label ? 1 : 0;
ruleTypes.splice(
0,
ruleTypes.length,
...logTypes
.map(({ category, id, name, source }) => ({
label: getLogTypeLabel(name),
value: name,
id,
category,
isStandard: source === 'Standard',
}))
.sort((a, b) => {
return a.label < b.label ? -1 : a.label > b.label ? 1 : 0;
})
);

// Set log category types
for (const key in logTypesByCategories) {
delete logTypesByCategories[key];
}
logTypes.forEach((logType) => {
logTypesByCategories[logType.category] = logTypesByCategories[logType.category] || [];
logTypesByCategories[logType.category].push(logType);
});
logTypeCategories.splice(
0,
logTypeCategories.length,
...Object.keys(logTypesByCategories).sort((a, b) => {
if (a === 'Other') {
return 1;
} else if (b === 'Other') {
return -1;
} else {
return a < b ? -1 : a > b ? 1 : 0;
}
})
);
);

// Set log category types
for (const key in logTypesByCategories) {
delete logTypesByCategories[key];
return logTypes;
}
logTypes.forEach((logType) => {
logTypesByCategories[logType.category] = logTypesByCategories[logType.category] || [];
logTypesByCategories[logType.category].push(logType);
});
logTypeCategories.splice(
0,
logTypeCategories.length,
...Object.keys(logTypesByCategories).sort((a, b) => {
if (a === 'Other') {
return 1;
} else if (b === 'Other') {
return -1;
} else {
return a < b ? -1 : a > b ? 1 : 0;
}
})
);

return logTypes;
}

return [];
return [];
} catch (error: any) {
if (error.message === DATA_SOURCE_NOT_SET_ERROR) {
errorNotificationToast(
this.notifications,
'Fetch',
'Log types',
'Select valid data source.'
);
return [];
}

throw error;
}
}

public async createLogType(logType: LogTypeBase): Promise<boolean> {
Expand Down
2 changes: 2 additions & 0 deletions public/utils/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -317,3 +317,5 @@ const LocalCluster: DataSourceOption = {
};

export const dataSourceObservable = new BehaviorSubject<DataSourceOption>(LocalCluster);

export const DATA_SOURCE_NOT_SET_ERROR = 'Data source is not set';
3 changes: 3 additions & 0 deletions public/utils/helpers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,9 @@ export const errorNotificationToast = (
errorMessage: string = '',
displayTime: number = 5000 // 5 seconds; default is 10 seconds
) => {
if (errorMessage.toLowerCase().includes('no living connections')) {
return;
}
const message = `Failed to ${actionName} ${objectName}:`;
console.error(message, errorMessage);
notifications?.toasts.addDanger({
Expand Down

0 comments on commit 2d46fa6

Please sign in to comment.