Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
26b9f4f
feat(14047): New Sigma Event Definition import options plugin
zeeklop May 8, 2026
793986e
Merge branch 'master' of github.com:Graylog2/graylog2-server into fea…
zeeklop May 8, 2026
d9b0069
Merge branch 'master' of github.com:Graylog2/graylog2-server into fea…
zeeklop May 11, 2026
2379ebe
feat(14047): Updates to EventDefinitionFormContainer
zeeklop May 12, 2026
6284bc2
Merge branch 'master' of github.com:Graylog2/graylog2-server into fea…
zeeklop May 12, 2026
8cb5df3
Merge branch 'master' of github.com:Graylog2/graylog2-server into fea…
zeeklop May 13, 2026
3c2dcb3
feat(14047): Moved requests to a reusable hook
zeeklop May 14, 2026
86b5d64
Merge branch 'master' of github.com:Graylog2/graylog2-server into fea…
zeeklop May 14, 2026
13a48df
feat(14047): Have the new sigma page working
zeeklop May 15, 2026
a0eb55f
Merge branch 'master' of github.com:Graylog2/graylog2-server into fea…
zeeklop May 15, 2026
98fea32
Merge branch 'master' of github.com:Graylog2/graylog2-server into fea…
zeeklop May 18, 2026
0770f4e
feat(14047): Updated event definitions form buttons
zeeklop May 20, 2026
19bf1ae
Merge branch 'master' of github.com:Graylog2/graylog2-server into fea…
zeeklop May 20, 2026
0c7f09a
Merge branch 'master' of github.com:Graylog2/graylog2-server into fea…
zeeklop May 21, 2026
2f68227
Merge branch 'master' of github.com:Graylog2/graylog2-server into fea…
zeeklop May 22, 2026
85097c9
feat(14047): Now it shows the list of available notifications
zeeklop May 22, 2026
ff4ce17
feat(14047): Fixed some lint issues
zeeklop May 26, 2026
d53e0e0
Merge branch 'master' of github.com:Graylog2/graylog2-server into fea…
zeeklop May 26, 2026
cfe0383
feat(14047): Fixed failing test
zeeklop May 26, 2026
ddb951d
Merge branch 'master' of github.com:Graylog2/graylog2-server into fea…
zeeklop May 27, 2026
0f38239
Merge branch 'master' of github.com:Graylog2/graylog2-server into fea…
zeeklop May 28, 2026
db69022
Merge branch 'master' of github.com:Graylog2/graylog2-server into fea…
zeeklop May 28, 2026
2092502
Merge branch 'master' of github.com:Graylog2/graylog2-server into fea…
zeeklop May 29, 2026
7a29abd
Merge branch 'master' of github.com:Graylog2/graylog2-server into fea…
zeeklop May 29, 2026
2e5302f
Merge branch 'master' into feat/14047-sigma-rules-to-event-definition…
zeeklop Jun 1, 2026
f62ba05
feat(14047): Added new alert routes to point to new sigma import page
zeeklop Jun 1, 2026
5886004
Merge branch 'feat/14047-sigma-rules-to-event-definition-wizard-ui' o…
zeeklop Jun 1, 2026
432f199
Merge branch 'master' of github.com:Graylog2/graylog2-server into fea…
zeeklop Jun 2, 2026
2fd6af5
Merge branch 'master' of github.com:Graylog2/graylog2-server into fea…
zeeklop Jun 3, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 13 additions & 10 deletions graylog2-web-interface/src/components/common/CreateButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,22 @@
* along with this program. If not, see
* <http://www.mongodb.com/licensing/server-side-public-license>.
*/
import * as React from 'react';
import { useCallback, useMemo } from 'react';
import React, { useCallback, useMemo } from 'react';
import type { Permissions } from 'graylog-web-plugin/plugin';

import IfPermitted from 'components/common/IfPermitted';
import { LinkContainer } from 'components/common';
import Button from 'components/bootstrap/Button';
import { Button } from 'components/bootstrap';
import usePluginEntities from 'hooks/usePluginEntities';
import useSendTelemetry from 'logic/telemetry/useSendTelemetry';
import useLocation from 'routing/useLocation';
import { getPathnameWithoutId } from 'util/URLUtils';

type Props = {
disabled?: boolean;
entityKey: string;
disabled?: boolean;
};

const useEntityCreator = (entityKey: string) => {
const entityCreators = usePluginEntities('entityCreators');

Expand All @@ -42,10 +43,18 @@ const useEntityCreator = (entityKey: string) => {

return entityCreator;
};

const PermissionWrapper = ({
permissions = undefined,
children = undefined,
}: React.PropsWithChildren<{ permissions?: Permissions }>) =>
permissions ? <IfPermitted permissions={permissions}>{children}</IfPermitted> : <>{children}</>;

const CreateButton = ({ disabled = false, entityKey }: Props) => {
const entityCreator = useEntityCreator(entityKey);
const sendTelemetry = useSendTelemetry();
const { pathname } = useLocation();

const _onClick = useCallback(() => {
const { telemetryEvent } = entityCreator;
if (telemetryEvent) {
Expand All @@ -57,12 +66,6 @@ const CreateButton = ({ disabled = false, entityKey }: Props) => {
}
}, [entityCreator, pathname, sendTelemetry]);

const PermissionWrapper = entityCreator?.permissions
? ({ children }: React.PropsWithChildren<{}>) => (
<IfPermitted permissions={entityCreator.permissions}>{children}</IfPermitted>
)
: React.Fragment;

return (
<PermissionWrapper>
<LinkContainer to={entityCreator.path}>
Expand Down
1 change: 1 addition & 0 deletions graylog2-web-interface/src/components/common/Wizard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,7 @@ export type StepType<StepKey extends string> = {
title: React.ReactNode;
component: React.ReactElement;
disabled?: boolean;
hidden?: boolean;
};

export type StepsType<StepKey extends string> = Array<StepType<StepKey>>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,37 +14,24 @@
* along with this program. If not, see
* <http://www.mongodb.com/licensing/server-side-public-license>.
*/
import React from 'react';
import type { SyntheticEvent } from 'react';
import * as React from 'react';
import { useMemo } from 'react';
import { PluginStore } from 'graylog-web-plugin/plugin';
import styled from 'styled-components';

import { getPathnameWithoutId } from 'util/URLUtils';
import { Col, Row } from 'components/bootstrap';
import { Wizard } from 'components/common';
import type { EventNotification } from 'stores/event-notifications/EventNotificationsStore';
import type {
EventDefinition,
EventDefinitionFormControlsProps,
} from 'components/event-definitions/event-definitions-types';
import type User from 'logic/users/User';
import type { StepType } from 'components/common/Wizard';
import type { EventDefinitionFormControlsProps } from 'components/event-definitions/event-definitions-types';
import useSendTelemetry from 'logic/telemetry/useSendTelemetry';
import useLocation from 'routing/useLocation';
import { TELEMETRY_EVENT_TYPE } from 'logic/telemetry/Constants';
import EventDefinitionFormControls from 'components/event-definitions/event-definition-form/EventDefinitionFormControls';
import type { EntitySharePayload } from 'actions/permissions/EntityShareActions';

import EventDetailsForm from './EventDetailsForm';
import EventConditionForm from './EventConditionForm';
import FieldsForm from './FieldsForm';
import NotificationsForm from './NotificationsForm';
import EventDefinitionSummary from './EventDefinitionSummary';
import ShareForm from './ShareForm';

const WizardContainer = styled.div`
margin-bottom: 10px;
`;

const STEP_KEYS = {
EVENT_DETAILS: 'event-details',
CONDITION: 'condition',
Expand All @@ -71,55 +58,24 @@ const STEP_TELEMETRY_KEYS = [
TELEMETRY_EVENT_TYPE.EVENTDEFINITION_SUMMARY.STEP_CLICKED,
];

const getConditionPlugin = (type: string | undefined) => {
if (type === undefined) {
return { displayName: null };
}

return PluginStore.exports('eventDefinitionTypes').find((edt) => edt.type === type) || {};
};

type Props = {
steps: Array<StepType<string>>;
activeStep: string;
action?: 'edit' | 'create';
eventDefinition: EventDefinition & {
share_request?: EntitySharePayload;
};
currentUser: User;
validation: {
errors: {
config?: unknown;
title?: string;
};
};
entityTypes: {};
notifications: Array<EventNotification>;
defaults: { default_backlog_size: number };
onChange: (key: string, value: unknown) => void;
onChangeStep: (step: string) => void;
onCancel: () => void;
onSubmit: () => void;
canEdit: boolean;
formControls?: React.ComponentType<EventDefinitionFormControlsProps>;
hideFieldsStep?: boolean;
};

const EventDefinitionForm = ({
steps,
action = 'edit',
activeStep,
canEdit,
currentUser,
defaults,
entityTypes,
eventDefinition,
formControls: FormControls = EventDefinitionFormControls,
notifications,
onCancel,
onChange,
onChangeStep,
onSubmit,
validation,
hideFieldsStep = false,
}: Props) => {
const { pathname } = useLocation();
const sendTelemetry = useSendTelemetry();
Expand All @@ -132,75 +88,6 @@ const EventDefinitionForm = ({
onSubmit();
};

const defaultStepProps = {
key: eventDefinition.id, // Recreate components if ID changed
action,
entityTypes,
eventDefinition,
onChange,
validation,
currentUser,
};

const canEditCondition = useMemo(
() => canEdit || eventDefinition._scope.toUpperCase() === 'ILLUMINATE',
[canEdit, eventDefinition._scope],
);

const eventProcedureId = eventDefinition?.event_procedure || undefined;

const eventDefinitionType = getConditionPlugin(eventDefinition.config.type);
const isNew = action === 'create';

const allSteps = [
{
key: STEP_KEYS.EVENT_DETAILS,
title: 'Event Details',
component: (
<EventDetailsForm {...defaultStepProps} eventDefinitionEventProcedure={eventProcedureId} canEdit={canEdit} />
),
},
{
key: STEP_KEYS.CONDITION,
title: eventDefinitionType?.displayName ?? 'Condition',
component: <EventConditionForm {...defaultStepProps} canEdit={canEditCondition} />,
},
{
key: STEP_KEYS.FIELDS,
title: 'Fields',
component: <FieldsForm {...defaultStepProps} canEdit={canEdit} />,
},
{
key: STEP_KEYS.NOTIFICATIONS,
title: 'Notifications',
component: <NotificationsForm {...defaultStepProps} notifications={notifications} defaults={defaults} />,
},
{
key: STEP_KEYS.SHARE,
title: 'Share',
component: <ShareForm {...defaultStepProps} />,
},
{
key: STEP_KEYS.SUMMARY,
title: 'Summary',
component: (
<EventDefinitionSummary
eventDefinition={eventDefinition}
currentUser={currentUser}
notifications={notifications}
validation={validation}
/>
),
},
];

const steps = allSteps.filter((step) => {
if (step.key === STEP_KEYS.FIELDS && hideFieldsStep) return false;
if (step.key === STEP_KEYS.SHARE && !isNew) return false;

return true;
});

const currentStepKeys = steps.map((step) => step.key);
const activeStepIndex = currentStepKeys.indexOf(activeStep);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ jest.mock('stores/event-notifications/EventNotificationsStore', () => ({
EventNotificationsActions: { listAll: jest.fn() },
EventNotificationsStore: {
listen: () => jest.fn(),
listAll: jest.fn(() => Promise.resolve({ notifications: mockEventNotifications })),
getInitialState: () => ({
all: mockEventNotifications,
allLegacyTypes: [],
Expand Down
Loading
Loading