"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.FormattedIp = void 0; var _fp = require("lodash/fp"); var _react = _interopRequireWildcard(require("react")); var _reactRedux = require("react-redux"); var _fastDeepEqual = _interopRequireDefault(require("fast-deep-equal")); var _stateful_event_context = require("../../../common/components/events_viewer/stateful_event_context"); var _helpers = require("../../../helpers"); var _network = require("../../../../common/search_strategy/security_solution/network"); var _draggable_wrapper = require("../../../common/components/drag_and_drop/draggable_wrapper"); var _helpers2 = require("../../../common/components/drag_and_drop/helpers"); var _draggables = require("../../../common/components/draggables"); var _empty_value = require("../../../common/components/empty_value"); var _parse_query_value = require("../timeline/body/renderers/parse_query_value"); var _data_provider = require("../timeline/data_providers/data_provider"); var _provider = require("../timeline/data_providers/provider"); var _timeline = require("../../../../common/types/timeline"); var _active_timeline_context = require("../../containers/active_timeline_context"); var _links = require("../../../common/components/links"); function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ const getUniqueId = ({ contextId, eventId, fieldName, address }) => `formatted-ip-data-provider-${contextId}-${fieldName}-${address}-${eventId}`; const tryStringify = value => { try { return JSON.stringify(value); } catch (_) { return `${value}`; } }; const getDataProvider = ({ contextId, eventId, fieldName, address }) => ({ enabled: true, id: (0, _helpers2.escapeDataProviderId)(getUniqueId({ contextId, eventId, fieldName, address })), name: `${fieldName}: ${(0, _parse_query_value.parseQueryValue)(address)}`, queryMatch: { field: fieldName, value: (0, _parse_query_value.parseQueryValue)(address), operator: _data_provider.IS_OPERATOR }, excluded: false, kqlQuery: '', and: [] }); const NonDecoratedIpComponent = ({ contextId, eventId, fieldName, fieldType, isAggregatable, isDraggable, truncate, value }) => { const key = (0, _react.useMemo)(() => `non-decorated-ip-draggable-wrapper-${getUniqueId({ contextId, eventId, fieldName, address: value })}`, [contextId, eventId, fieldName, value]); const dataProviderProp = (0, _react.useMemo)(() => getDataProvider({ contextId, eventId, fieldName, address: value }), [contextId, eventId, fieldName, value]); const content = (0, _react.useMemo)(() => typeof value !== 'object' ? (0, _empty_value.getOrEmptyTagFromValue)(value) : (0, _empty_value.getOrEmptyTagFromValue)(tryStringify(value)), [value]); const render = (0, _react.useCallback)((dataProvider, _, snapshot) => snapshot.isDragging ? /*#__PURE__*/_react.default.createElement(_draggable_wrapper.DragEffects, null, /*#__PURE__*/_react.default.createElement(_provider.Provider, { dataProvider: dataProvider })) : content, [content]); if (!isDraggable) { return content; } return /*#__PURE__*/_react.default.createElement(_draggable_wrapper.DraggableWrapper, { dataProvider: dataProviderProp, fieldType: fieldType, isAggregatable: isAggregatable, isDraggable: isDraggable, key: key, render: render, truncate: truncate }); }; const NonDecoratedIp = /*#__PURE__*/_react.default.memo(NonDecoratedIpComponent); const AddressLinksItemComponent = ({ address, Component, contextId, eventId, fieldName, fieldType, isAggregatable, isButton, isDraggable, onClick, truncate, title }) => { const key = `address-links-draggable-wrapper-${getUniqueId({ contextId, eventId, fieldName, address })}`; const dataProviderProp = (0, _react.useMemo)(() => getDataProvider({ contextId, eventId, fieldName, address }), [address, contextId, eventId, fieldName]); const dispatch = (0, _reactRedux.useDispatch)(); const eventContext = (0, _react.useContext)(_stateful_event_context.StatefulEventContext); const isInTimelineContext = address && (eventContext === null || eventContext === void 0 ? void 0 : eventContext.enableIpDetailsFlyout) && (eventContext === null || eventContext === void 0 ? void 0 : eventContext.timelineID); const openNetworkDetailsSidePanel = (0, _react.useCallback)(e => { e.preventDefault(); if (onClick) { onClick(); } if (eventContext && isInTimelineContext) { const { tabType, timelineID } = eventContext; const updatedExpandedDetail = { panelView: 'networkDetail', params: { ip: address, flowTarget: fieldName.includes(_network.FlowTargetSourceDest.destination) ? _network.FlowTargetSourceDest.destination : _network.FlowTargetSourceDest.source } }; const scopedActions = (0, _helpers.getScopedActions)(timelineID); if (scopedActions) { dispatch(scopedActions.toggleDetailPanel({ ...updatedExpandedDetail, id: timelineID, tabType: tabType })); } if (timelineID === _timeline.TimelineId.active && tabType === _timeline.TimelineTabs.query) { _active_timeline_context.activeTimeline.toggleExpandedDetail({ ...updatedExpandedDetail }); } } }, [onClick, eventContext, isInTimelineContext, address, fieldName, dispatch]); // The below is explicitly defined this way as the onClick takes precedence when it and the href are both defined // When this component is used outside of timeline/alerts table (i.e. in the flyout) we would still like it to link to the IP Overview page const content = (0, _react.useMemo)(() => Component ? /*#__PURE__*/_react.default.createElement(_links.NetworkDetailsLink, { Component: Component, ip: address, isButton: isButton, onClick: isInTimelineContext ? openNetworkDetailsSidePanel : undefined, title: title }) : /*#__PURE__*/_react.default.createElement(_draggables.Content, { field: fieldName, tooltipContent: fieldName }, /*#__PURE__*/_react.default.createElement(_links.NetworkDetailsLink, { Component: Component, ip: address, isButton: isButton, onClick: isInTimelineContext ? openNetworkDetailsSidePanel : undefined, title: title })), [Component, address, fieldName, isButton, isInTimelineContext, openNetworkDetailsSidePanel, title]); const render = (0, _react.useCallback)((_props, _provided, snapshot) => snapshot.isDragging ? /*#__PURE__*/_react.default.createElement(_draggable_wrapper.DragEffects, null, /*#__PURE__*/_react.default.createElement(_provider.Provider, { dataProvider: dataProviderProp })) : content, [dataProviderProp, content]); if (!isDraggable) { return content; } return /*#__PURE__*/_react.default.createElement(_draggable_wrapper.DraggableWrapper, { dataProvider: dataProviderProp, isDraggable: isDraggable, fieldType: fieldType, isAggregatable: isAggregatable, key: key, render: render, truncate: truncate }); }; const AddressLinksItem = /*#__PURE__*/_react.default.memo(AddressLinksItemComponent); const AddressLinksComponent = ({ addresses, Component, contextId, eventId, fieldName, fieldType, isAggregatable, isButton, isDraggable, onClick, truncate, title }) => { const uniqAddresses = (0, _react.useMemo)(() => (0, _fp.uniq)(addresses), [addresses]); const content = (0, _react.useMemo)(() => uniqAddresses.map(address => /*#__PURE__*/_react.default.createElement(AddressLinksItem, { key: address, address: address, Component: Component, contextId: contextId, eventId: eventId, fieldName: fieldName, fieldType: fieldType, isAggregatable: isAggregatable, isButton: isButton, isDraggable: isDraggable, onClick: onClick, truncate: truncate, title: title })), [Component, contextId, eventId, fieldName, fieldType, isAggregatable, isButton, isDraggable, onClick, title, truncate, uniqAddresses]); return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, content); }; const AddressLinks = /*#__PURE__*/_react.default.memo(AddressLinksComponent, (prevProps, nextProps) => prevProps.contextId === nextProps.contextId && prevProps.eventId === nextProps.eventId && prevProps.fieldName === nextProps.fieldName && prevProps.isAggregatable === nextProps.isAggregatable && prevProps.fieldType === nextProps.fieldType && prevProps.isDraggable === nextProps.isDraggable && prevProps.truncate === nextProps.truncate && (0, _fastDeepEqual.default)(prevProps.addresses, nextProps.addresses)); const FormattedIpComponent = ({ Component, contextId, eventId, fieldName, fieldType, isAggregatable, isDraggable, isButton, onClick, title, truncate, value }) => { if ((0, _fp.isString)(value) && !(0, _fp.isEmpty)(value)) { try { const addresses = JSON.parse(value); if ((0, _fp.isArray)(addresses)) { return /*#__PURE__*/_react.default.createElement(AddressLinks, { addresses: addresses, Component: Component, contextId: contextId, eventId: eventId, fieldName: fieldName, fieldType: fieldType, isAggregatable: isAggregatable, isButton: isButton, isDraggable: isDraggable, onClick: onClick, title: title, truncate: truncate }); } } catch (_) { // fall back to formatting it as a single link } // return a single draggable link return /*#__PURE__*/_react.default.createElement(AddressLinks, { addresses: [value], Component: Component, contextId: contextId, eventId: eventId, isButton: isButton, isDraggable: isDraggable, onClick: onClick, fieldName: fieldName, fieldType: fieldType, isAggregatable: isAggregatable, truncate: truncate, title: title }); } else { return /*#__PURE__*/_react.default.createElement(NonDecoratedIp, { contextId: contextId, eventId: eventId, fieldName: fieldName, fieldType: fieldType, isAggregatable: isAggregatable, isDraggable: isDraggable, truncate: truncate, value: value }); } }; const FormattedIp = /*#__PURE__*/_react.default.memo(FormattedIpComponent, (prevProps, nextProps) => prevProps.contextId === nextProps.contextId && prevProps.eventId === nextProps.eventId && prevProps.fieldName === nextProps.fieldName && prevProps.isAggregatable === nextProps.isAggregatable && prevProps.fieldType === nextProps.fieldType && prevProps.isDraggable === nextProps.isDraggable && prevProps.truncate === nextProps.truncate && (0, _fastDeepEqual.default)(prevProps.value, nextProps.value)); exports.FormattedIp = FormattedIp;