Skip to content

Commit

Permalink
Miscellaneous bug fixes (opensearch-project#95)
Browse files Browse the repository at this point in the history
* bug fixes

Signed-off-by: Amardeepsingh Siglani <amardeep7194@gmail.com>

* fixed group by legend for summary vis

Signed-off-by: Amardeepsingh Siglani <amardeep7194@gmail.com>

Signed-off-by: Amardeepsingh Siglani <amardeep7194@gmail.com>
  • Loading branch information
amsiglan authored Nov 9, 2022
1 parent 9b16ac5 commit ce2b172
Show file tree
Hide file tree
Showing 16 changed files with 152 additions and 50 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -271,10 +271,17 @@ export default class AlertConditionPanel extends Component<
label: severity,
});
});
const namesOptions: EuiComboBoxOptionOption<string>[] = rulesOptions.map((option) => ({
label: option.name,
value: option.id,
}));
const uniqueRuleNames = new Set<string>();
const namesOptions: EuiComboBoxOptionOption<string>[] = [];
rulesOptions.forEach((option) => {
if (!uniqueRuleNames.has(option.name)) {
uniqueRuleNames.add(option.name);
namesOptions.push({
label: option.name,
value: option.id,
});
}
});

const channelId = alertCondition.actions[0].destination_id;
const selectedNotificationChannelOption: NotificationChannelOption[] = [];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,8 @@ export default class DetectorDataSource extends Component<
);
this.setState({ errorMessage: indicesResponse.error });
}
} catch (e) {
errorNotificationToast(this.props.notifications, 'retrieve', 'indices', e);
} catch (error: any) {
errorNotificationToast(this.props.notifications, 'retrieve', 'indices', error);
}
this.setState({ loading: false });
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,19 +54,19 @@ export default class DetectorBasicDetailsForm extends Component<
this.props.onDetectorNameChange(event.target.value.trimStart());
};

onDescriptionBlur = (event: React.ChangeEvent<HTMLInputElement>) => {
onDescriptionBlur = (event: React.ChangeEvent<HTMLTextAreaElement>) => {
this.setState({
descriptionFieldTouched: true,
descriptionIsInvalid: !validateDescription(event.target.value),
});
};

onDescriptionChange = (event: React.ChangeEvent<HTMLInputElement>) => {
onDescriptionChange = (event: React.ChangeEvent<HTMLTextAreaElement>) => {
this.props.onDetectorInputDescriptionChange(event.target.value.trimStart());
};

render() {
const { detectorName, detectorDescription, onDetectorInputDescriptionChange } = this.props;
const { detectorName, detectorDescription } = this.props;
const {
descriptionIsInvalid,
descriptionFieldTouched,
Expand All @@ -93,7 +93,6 @@ export default class DetectorBasicDetailsForm extends Component<
</EuiFormRow>
<EuiSpacer size={'m'} />

{/*// TODO: Implement regex pattern validation for description field.*/}
<EuiFormRow
label={<FormFieldHeader headerTitle={'Description'} optionalField={true} />}
isInvalid={descriptionFieldTouched && descriptionIsInvalid}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,14 @@ import {
CreateDetectorRulesState,
DetectionRules,
} from '../components/DetectionRules/DetectionRules';
import { NotificationsStart } from 'opensearch-dashboards/public';

interface DefineDetectorProps extends RouteComponentProps {
detector: Detector;
isEdit: boolean;
indexService: IndexService;
rulesState: CreateDetectorRulesState;
notifications: NotificationsStart;
changeDetector: (detector: Detector) => void;
updateDataValidState: (step: DetectorCreationStep, isValid: boolean) => void;
onPageChange: (page: { index: number; size: number }) => void;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@ import { AlertTriggersView } from '../../../../Detectors/containers/AlertTrigger
import { RouteComponentProps } from 'react-router-dom';
import { Detector, FieldMapping } from '../../../../../../models/interfaces';
import { DetectorCreationStep } from '../../../models/types';
import { NotificationsStart } from 'opensearch-dashboards/public';

export interface ReviewAndCreateProps extends RouteComponentProps {
detector: Detector;
existingMappings: FieldMapping[];
notifications: NotificationsStart;
setDetectorCreationStep: (step: DetectorCreationStep) => void;
}

Expand Down Expand Up @@ -56,6 +58,7 @@ export class ReviewAndCreate extends React.Component<ReviewAndCreateProps, Revie
<EuiSpacer size="l" />
<AlertTriggersView
{...this.props}
notifications={this.props.notifications}
detector={this.props.detector}
editAlertTriggers={this.setConfigureAlertsStep}
/>
Expand Down
9 changes: 5 additions & 4 deletions public/pages/CreateDetector/containers/CreateDetector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,8 @@ export default class CreateDetector extends Component<CreateDetectorProps, Creat
createDetectorRes.error
);
}
} catch (e) {
errorNotificationToast(this.props.notifications, 'create', 'detector', e);
} catch (error: any) {
errorNotificationToast(this.props.notifications, 'create', 'detector', error);
}
this.setState({ creatingDetector: false });
};
Expand Down Expand Up @@ -152,8 +152,8 @@ export default class CreateDetector extends Component<CreateDetectorProps, Creat
};

getRulesOptions(): CreateDetectorRulesOptions {
const allRules = this.state.rulesState.allRules;
const options: CreateDetectorRulesOptions = allRules.map((rule) => ({
const enabledRules = this.state.rulesState.allRules.filter((rule) => rule.enabled);
const options: CreateDetectorRulesOptions = enabledRules.map((rule) => ({
id: rule._id,
name: rule._source.title,
severity: rule._source.level,
Expand Down Expand Up @@ -309,6 +309,7 @@ export default class CreateDetector extends Component<CreateDetectorProps, Creat
<ConfigureFieldMapping
{...this.props}
detector={this.state.detector}
loading={false}
filedMappingService={services.fieldMappingService}
fieldMappings={this.state.fieldMappings}
replaceFieldMappings={this.replaceFieldMappings}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { EuiButton, EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiTitle } from '@elas
import ConfigureFieldMapping from '../../../CreateDetector/components/ConfigureFieldMapping';
import { Detector, FieldMapping } from '../../../../../models/interfaces';
import FieldMappingService from '../../../../services/FieldMappingService';
import { DetectorHit, GetDetectorResponse } from '../../../../../server/models/interfaces';
import { DetectorHit, SearchDetectorsResponse } from '../../../../../server/models/interfaces';
import { EMPTY_DEFAULT_DETECTOR, ROUTES } from '../../../../utils/constants';
import { DetectorsService } from '../../../../services';
import { ServerResponse } from '../../../../../server/models/types';
Expand Down Expand Up @@ -57,12 +57,12 @@ export default class UpdateFieldMappings extends Component<
const { detectorService, history } = this.props;
const { detectorId } = this.state;
const response = (await detectorService.getDetectors()) as ServerResponse<
GetDetectorResponse
SearchDetectorsResponse
>;
if (response.ok) {
const detectorHit = response.response.hits.hits.find(
(detectorHit) => detectorHit._id === detectorId
);
) as DetectorHit;
const detector = detectorHit._source;
detector.detector_type = detector.detector_type.toLowerCase();

Expand All @@ -77,8 +77,8 @@ export default class UpdateFieldMappings extends Component<
} else {
errorNotificationToast(this.props.notifications, 'retrieve', 'detector', response.error);
}
} catch (e) {
errorNotificationToast(this.props.notifications, 'retrieve', 'detector', e);
} catch (error: any) {
errorNotificationToast(this.props.notifications, 'retrieve', 'detector', error);
}
this.setState({ loading: false });
};
Expand Down Expand Up @@ -129,8 +129,8 @@ export default class UpdateFieldMappings extends Component<
updateDetectorResponse.error
);
}
} catch (e) {
errorNotificationToast(this.props.notifications, 'update', 'detector', e);
} catch (error: any) {
errorNotificationToast(this.props.notifications, 'update', 'detector', error);
}

this.setState({ submitting: false });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ export class DetectorDetails extends React.Component<DetectorDetailsProps, Detec
this.context.chrome.setBreadcrumbs([
BREADCRUMBS.SECURITY_ANALYTICS,
BREADCRUMBS.DETECTORS,
BREADCRUMBS.DETECTORS_DETAILS(detector._source.name),
BREADCRUMBS.DETECTORS_DETAILS(detector._source.name, detector._id),
]);
} else {
errorNotificationToast(notifications, 'retrieve', 'detector', response.error);
Expand Down
19 changes: 10 additions & 9 deletions public/pages/Findings/components/CreateAlertFlyout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ interface CreateAlertFlyoutProps extends RouteComponentProps {
detectorService: DetectorsService;
finding: Finding;
notificationChannels: NotificationChannelTypeOptions[];
refreshNotificationChannels: () => void;
allRules: object;
rulesOptions: Pick<RulesSharedState, 'rulesOptions'>['rulesOptions'];
}
Expand All @@ -53,7 +54,6 @@ export default class CreateAlertFlyout extends Component<
alertCondition: EMPTY_DEFAULT_ALERT_CONDITION,
loading: false,
detector: this.props.finding.detector._source,
rules: [],
submitting: false,
};
}
Expand All @@ -64,23 +64,24 @@ export default class CreateAlertFlyout extends Component<

prepareAlertCondition = async () => {
const { rulesOptions } = this.props;
const { alertCondition, detector } = this.state;
const { alertCondition } = this.state;
const newAlertCondition = { ...alertCondition };

const selectedRuleNames = new Set();
const selectedRuleSeverities = new Set();
const selectedTags = new Set();
const selectedRuleNames = new Set<string>();
const selectedRuleSeverities = new Set<string>();
const selectedTags = new Set<string>();

rulesOptions.forEach((rule) => {
selectedRuleNames.add(rule.id);
selectedRuleSeverities.add(rule.severity);
rule.tags.forEach((tag) => selectedTags.add(tag));
});

alertCondition.ids = Array.from(selectedRuleNames);
alertCondition.sev_levels = Array.from(selectedRuleSeverities);
alertCondition.tags = Array.from(selectedTags);
newAlertCondition.ids = Array.from(selectedRuleNames);
newAlertCondition.sev_levels = Array.from(selectedRuleSeverities);
newAlertCondition.tags = Array.from(selectedTags);

this.setState({ alertCondition: { ...alertCondition } });
this.setState({ alertCondition: newAlertCondition });
};

onAlertConditionChange = (newDetector: Detector): void => {
Expand Down
34 changes: 34 additions & 0 deletions public/pages/Main/Main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,14 @@ interface MainState {
selectedNavItemIndex: number;
}

const navItemIndexByRoute: { [route: string]: number } = {
[ROUTES.OVERVIEW]: 1,
[ROUTES.FINDINGS]: 2,
[ROUTES.ALERTS]: 3,
[ROUTES.DETECTORS]: 4,
[ROUTES.RULES]: 5,
};

export default class Main extends Component<MainProps, MainState> {
constructor(props: MainProps) {
super(props);
Expand All @@ -78,6 +86,32 @@ export default class Main extends Component<MainProps, MainState> {
};
}

componentDidMount(): void {
this.updateSelectedNavItem();
}

componentDidUpdate(
prevProps: Readonly<MainProps>,
prevState: Readonly<MainState>,
snapshot?: any
): void {
if (this.props.location.pathname === prevProps.location.pathname) {
return;
}

this.updateSelectedNavItem();
}

updateSelectedNavItem() {
if (navItemIndexByRoute[this.props.location.pathname] !== undefined) {
this.setState({ selectedNavItemIndex: navItemIndexByRoute[this.props.location.pathname] });
}

if (this.props.location.pathname.includes('detector-details')) {
this.setState({ selectedNavItemIndex: navItemIndexByRoute[ROUTES.DETECTORS] });
}
}

setGetStartedDismissedOnce = () => {
this.setState({ getStartedDismissedOnce: true });
};
Expand Down
1 change: 1 addition & 0 deletions public/pages/Overview/components/Widgets/Summary.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ export const Summary: React.FC<SummaryProps> = ({ alerts, findings }) => {
time: getTimeWithMinPrecision(alert.time),
alert: 1,
finding: 0,
logType: alert.logType,
});
});

Expand Down
47 changes: 44 additions & 3 deletions public/pages/Rules/components/RuleEditor/RuleEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,14 @@ import {
import { Rule } from '../../../../../models/interfaces';
import { FieldTextArray } from './FieldTextArray';
import { ruleStatus, ruleTypes } from '../../utils/constants';
import {
authorErrorString,
AUTHOR_REGEX,
descriptionErrorString,
nameErrorString,
validateDescription,
validateName,
} from '../../../../utils/validation';

export interface RuleEditorProps {
services: BrowserServices;
Expand All @@ -34,6 +42,14 @@ export const RuleEditor: React.FC<RuleEditorProps> = ({ title, rule, FooterActio
const onNameChange = (e: ChangeEvent<HTMLInputElement>) => {
setName(e.target.value);
};
const [nameError, setNameError] = useState('');
const onNameBlur = (e: ChangeEvent<HTMLInputElement>) => {
if (!validateName(e.target.value)) {
setNameError(nameErrorString);
} else {
setNameError('');
}
};

const [logType, setLogType] = useState(rule?.category || '');
const onLogTypeChange = (e: ChangeEvent<HTMLSelectElement>) => {
Expand All @@ -44,6 +60,14 @@ export const RuleEditor: React.FC<RuleEditorProps> = ({ title, rule, FooterActio
const onDescriptionChange = (e: ChangeEvent<HTMLTextAreaElement>) => {
setDescription(e.target.value);
};
const [descriptionError, setDescriptionError] = useState('');
const onDescriptionBlur = (e: ChangeEvent<HTMLTextAreaElement>) => {
if (!validateDescription(e.target.value)) {
setDescriptionError(descriptionErrorString);
} else {
setDescriptionError('');
}
};

const [level, setLevel] = useState(rule?.level || '');
const onLevelChange = (e: ChangeEvent<HTMLSelectElement>) => {
Expand All @@ -62,6 +86,14 @@ export const RuleEditor: React.FC<RuleEditorProps> = ({ title, rule, FooterActio
const onAuthorChange = (e: ChangeEvent<HTMLInputElement>) => {
setAuthor(e.target.value);
};
const [authorError, setAuthorError] = useState('');
const onAuthorBlur = (e: ChangeEvent<HTMLInputElement>) => {
if (!validateName(e.target.value, AUTHOR_REGEX)) {
setAuthorError(authorErrorString);
} else {
setAuthorError('');
}
};

const [status, setRuleStatus] = useState(rule?.status || '');
const onStatusChange = (e: ChangeEvent<HTMLSelectElement>) => {
Expand Down Expand Up @@ -129,11 +161,13 @@ export const RuleEditor: React.FC<RuleEditorProps> = ({ title, rule, FooterActio
<ContentPanel title={title}>
<EuiFlexGroup component="span">
<EuiFlexItem grow={false} style={{ minWidth: 400 }}>
<EuiFormRow label="Rule name">
<EuiFormRow label="Rule name" isInvalid={!!nameError} error={nameError}>
<EuiFieldText
placeholder="Enter rule name"
value={name}
onChange={onNameChange}
onBlur={onNameBlur}
required
data-test-subj={'rule_name_field'}
/>
</EuiFormRow>
Expand All @@ -154,10 +188,16 @@ export const RuleEditor: React.FC<RuleEditorProps> = ({ title, rule, FooterActio

<EuiSpacer />

<EuiFormRow label="Description" fullWidth>
<EuiFormRow
label="Description"
fullWidth
isInvalid={!!descriptionError}
error={descriptionError}
>
<EuiTextArea
value={description}
onChange={onDescriptionChange}
onBlur={onDescriptionBlur}
data-test-subj={'rule_description_field'}
/>
</EuiFormRow>
Expand Down Expand Up @@ -224,11 +264,12 @@ export const RuleEditor: React.FC<RuleEditorProps> = ({ title, rule, FooterActio
onFieldRemove={onFalsePositiveRemove}
/>

<EuiFormRow label="Author">
<EuiFormRow label="Author" isInvalid={!!authorError} error={authorError}>
<EuiFieldText
placeholder="Enter author name"
value={author}
onChange={onAuthorChange}
onBlur={onAuthorBlur}
required
data-test-subj={'rule_author_field'}
/>
Expand Down
Loading

0 comments on commit ce2b172

Please sign in to comment.