diff --git a/x-pack/platform/plugins/private/translations/translations/fr-FR.json b/x-pack/platform/plugins/private/translations/translations/fr-FR.json index 985a8120d1721..81298783701e2 100644 --- a/x-pack/platform/plugins/private/translations/translations/fr-FR.json +++ b/x-pack/platform/plugins/private/translations/translations/fr-FR.json @@ -42544,6 +42544,7 @@ "xpack.securitySolution.uiSettings.enableCcsWarningDescription": "

Active les avertissements de vérification des privilèges dans les règles relatives aux index CCS

", "xpack.securitySolution.uiSettings.enableNewsFeedDescription": "

Active le fil d'actualités

", "xpack.securitySolution.uiSettings.enableNewsFeedLabel": "Fil d'actualités", + "xpack.securitySolution.uiSettings.enableVisualizationsInFlyoutDescription": "[version d'évaluation technique] Activez les visualisations (analyseur et visualiseur de session) dans le menu volant.", "xpack.securitySolution.uiSettings.enableVisualizationsInFlyoutLabel": "Activer les visualisations dans le menu volant", "xpack.securitySolution.uiSettings.excludeColdAndFrozenTiersInAnalyzer": "Exclure les niveaux froids de l'analyseur", "xpack.securitySolution.uiSettings.excludeColdAndFrozenTiersInAnalyzerDescription": "

Lorsque cette option est activée, les niveaux \"cold\" et \"frozen\" sont ignorés dans les requêtes de l'analyseur

", diff --git a/x-pack/platform/plugins/private/translations/translations/ja-JP.json b/x-pack/platform/plugins/private/translations/translations/ja-JP.json index 9b31292d397e4..ca80aaa127e32 100644 --- a/x-pack/platform/plugins/private/translations/translations/ja-JP.json +++ b/x-pack/platform/plugins/private/translations/translations/ja-JP.json @@ -42402,6 +42402,7 @@ "xpack.securitySolution.uiSettings.enableCcsWarningDescription": "

CCSインデックスのルールで権限チェック警告を有効にします

", "xpack.securitySolution.uiSettings.enableNewsFeedDescription": "

ニュースフィードを有効にします

", "xpack.securitySolution.uiSettings.enableNewsFeedLabel": "ニュースフィード", + "xpack.securitySolution.uiSettings.enableVisualizationsInFlyoutDescription": "[テクニカルプレビュー]フライアウトで視覚化(アナライザーとセッションビューアー)を有効にします。", "xpack.securitySolution.uiSettings.enableVisualizationsInFlyoutLabel": "フライアウトでビジュアライゼーションを有効化", "xpack.securitySolution.uiSettings.excludeColdAndFrozenTiersInAnalyzer": "アナライザーでコールドティアとフローズンティアを除外", "xpack.securitySolution.uiSettings.excludeColdAndFrozenTiersInAnalyzerDescription": "

有効にすると、アナライザークエリーでコールドティアとフローズンティアがスキップされます

", diff --git a/x-pack/platform/plugins/private/translations/translations/zh-CN.json b/x-pack/platform/plugins/private/translations/translations/zh-CN.json index b89f4978302c0..31eb102ba6780 100644 --- a/x-pack/platform/plugins/private/translations/translations/zh-CN.json +++ b/x-pack/platform/plugins/private/translations/translations/zh-CN.json @@ -41786,6 +41786,7 @@ "xpack.securitySolution.uiSettings.enableCcsWarningDescription": "

在规则中为 CCS 索引启用权限检查警告

", "xpack.securitySolution.uiSettings.enableNewsFeedDescription": "

启用新闻源

", "xpack.securitySolution.uiSettings.enableNewsFeedLabel": "新闻源", + "xpack.securitySolution.uiSettings.enableVisualizationsInFlyoutDescription": "[技术预览] 在浮出控件中启用可视化(分析器和会话查看器)。", "xpack.securitySolution.uiSettings.enableVisualizationsInFlyoutLabel": "在浮出控件中启用可视化", "xpack.securitySolution.uiSettings.excludeColdAndFrozenTiersInAnalyzer": "在分析器中排除冷层和冻结层", "xpack.securitySolution.uiSettings.excludeColdAndFrozenTiersInAnalyzerDescription": "

启用后,将在分析器查询中跳过冷层和冻结层

", diff --git a/x-pack/plugins/cloud_security_posture/server/routes/graph/route.ts b/x-pack/plugins/cloud_security_posture/server/routes/graph/route.ts index fd42061472044..181f5c3912b14 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/graph/route.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/graph/route.ts @@ -44,15 +44,6 @@ export const defineGraphRoute = (router: CspRouter) => }, async (context: CspRequestHandlerContext, request, response) => { const cspContext = await context.csp; - const isGraphEnabled = await ( - await context.core - ).uiSettings.client.get(ENABLE_VISUALIZATIONS_IN_FLYOUT_SETTING); - - cspContext.logger.debug(`isGraphEnabled: ${isGraphEnabled}`); - - if (!isGraphEnabled) { - return response.notFound(); - } const { nodesLimit, showUnknownTarget = false } = request.body; const { eventIds, start, end, esQuery } = request.body.query as GraphRequest['query']; diff --git a/x-pack/plugins/security_solution/common/experimental_features.ts b/x-pack/plugins/security_solution/common/experimental_features.ts index 156c4c6dc0f49..def958c07bd2d 100644 --- a/x-pack/plugins/security_solution/common/experimental_features.ts +++ b/x-pack/plugins/security_solution/common/experimental_features.ts @@ -196,6 +196,11 @@ export const allowedExperimentalValues = Object.freeze({ */ analyzerDatePickersAndSourcererDisabled: false, + /** + * Enables graph visualization in alerts flyout + */ + graphVisualizationInFlyoutEnabled: false, + /** * Enables an ability to customize Elastic prebuilt rules. * diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/left/tabs/visualize_tab.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/left/tabs/visualize_tab.tsx index 6bd30d9061d65..5018e6ea1411a 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/left/tabs/visualize_tab.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/left/tabs/visualize_tab.tsx @@ -11,6 +11,7 @@ import type { EuiButtonGroupOptionProps } from '@elastic/eui/src/components/butt import { useExpandableFlyoutApi, useExpandableFlyoutState } from '@kbn/expandable-flyout'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; +import { useIsExperimentalFeatureEnabled } from '../../../../common/hooks/use_experimental_features'; import { useDocumentDetailsContext } from '../../shared/context'; import { useWhichFlyout } from '../../shared/hooks/use_which_flyout'; import { @@ -33,6 +34,7 @@ import { ALERTS_ACTIONS } from '../../../../common/lib/apm/user_actions'; import { useStartTransaction } from '../../../../common/lib/apm/use_start_transaction'; import { GraphVisualization } from '../components/graph_visualization'; import { useGraphPreview } from '../../shared/hooks/use_graph_preview'; +import { GRAPH_VISUALIZATION_IN_FLYOUT_ENABLED_EXPERIMENTAL_FEATURE } from '../../shared/constants/experimental_features'; const visualizeButtons: EuiButtonGroupOptionProps[] = [ { @@ -121,14 +123,18 @@ export const VisualizeTab = memo(() => { }, [panels.left?.path?.subTab]); // Decide whether to show the graph preview or not - const { isAuditLog: isGraphPreviewEnabled } = useGraphPreview({ + const { isAuditLog } = useGraphPreview({ getFieldsData, ecsData: dataAsNestedObject, }); + const isGraphFeatureEnabled = useIsExperimentalFeatureEnabled( + GRAPH_VISUALIZATION_IN_FLYOUT_ENABLED_EXPERIMENTAL_FEATURE + ); + const options = [...visualizeButtons]; - if (isGraphPreviewEnabled) { + if (isAuditLog && isGraphFeatureEnabled) { options.push(graphVisualizationButton); } diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/graph_preview_container.test.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/graph_preview_container.test.tsx index 6567f2b8412b6..bc0b0b9426c8d 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/graph_preview_container.test.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/graph_preview_container.test.tsx @@ -21,6 +21,7 @@ import { EXPANDABLE_PANEL_HEADER_TITLE_TEXT_TEST_ID, EXPANDABLE_PANEL_TOGGLE_ICON_TEST_ID, } from '../../../shared/components/test_ids'; +import { useIsExperimentalFeatureEnabled } from '../../../../common/hooks/use_experimental_features'; const mockUseUiSetting = jest.fn().mockReturnValue([true]); jest.mock('@kbn/kibana-react-plugin/public', () => { @@ -31,6 +32,12 @@ jest.mock('@kbn/kibana-react-plugin/public', () => { }; }); +jest.mock('../../../../common/hooks/use_experimental_features', () => ({ + useIsExperimentalFeatureEnabled: jest.fn(), +})); + +const useIsExperimentalFeatureEnabledMock = useIsExperimentalFeatureEnabled as jest.Mock; + jest.mock('../../shared/hooks/use_graph_preview'); jest.mock('@kbn/cloud-security-posture-graph/src/hooks', () => ({ useFetchGraphData: jest.fn(), @@ -58,6 +65,7 @@ describe('', () => { }); it('should render component and link in header', async () => { + useIsExperimentalFeatureEnabledMock.mockReturnValue(true); mockUseFetchGraphData.mockReturnValue({ isLoading: false, isError: false, @@ -108,6 +116,7 @@ describe('', () => { }); it('should render component and without link in header in preview panel', async () => { + useIsExperimentalFeatureEnabledMock.mockReturnValue(true); mockUseFetchGraphData.mockReturnValue({ isLoading: false, isError: false, @@ -161,6 +170,7 @@ describe('', () => { }); it('should render component and without link in header in rule preview', async () => { + useIsExperimentalFeatureEnabledMock.mockReturnValue(true); mockUseFetchGraphData.mockReturnValue({ isLoading: false, isError: false, @@ -213,7 +223,8 @@ describe('', () => { }); }); - it('should not render when feature is not enabled', () => { + it('should not render when flyout feature is not enabled', () => { + useIsExperimentalFeatureEnabledMock.mockReturnValue(true); mockUseUiSetting.mockReturnValue([false]); mockUseFetchGraphData.mockReturnValue({ @@ -233,7 +244,29 @@ describe('', () => { ).not.toBeInTheDocument(); }); + it('should not render when experimental feature is not enabled', () => { + useIsExperimentalFeatureEnabledMock.mockReturnValue(false); + mockUseUiSetting.mockReturnValue([true]); + + mockUseFetchGraphData.mockReturnValue({ + isLoading: false, + isError: false, + data: undefined, + }); + + (useGraphPreview as jest.Mock).mockReturnValue({ + isAuditLog: true, + }); + + const { queryByTestId } = renderGraphPreview(); + + expect( + queryByTestId(EXPANDABLE_PANEL_HEADER_TITLE_LINK_TEST_ID(GRAPH_PREVIEW_TEST_ID)) + ).not.toBeInTheDocument(); + }); + it('should not render when graph data is not available', () => { + useIsExperimentalFeatureEnabledMock.mockReturnValue(true); mockUseFetchGraphData.mockReturnValue({ isLoading: false, isError: false, diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/graph_preview_container.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/graph_preview_container.tsx index 82888d56edc79..cde99e88e9039 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/graph_preview_container.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/graph_preview_container.tsx @@ -11,6 +11,7 @@ import { useUiSetting$ } from '@kbn/kibana-react-plugin/public'; import { EuiBetaBadge } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { useFetchGraphData } from '@kbn/cloud-security-posture-graph/src/hooks'; +import { useIsExperimentalFeatureEnabled } from '../../../../common/hooks/use_experimental_features'; import { ENABLE_VISUALIZATIONS_IN_FLYOUT_SETTING } from '../../../../../common/constants'; import { useDocumentDetailsContext } from '../../shared/context'; import { GRAPH_PREVIEW_TEST_ID } from './test_ids'; @@ -18,6 +19,7 @@ import { GraphPreview } from './graph_preview'; import { useGraphPreview } from '../../shared/hooks/use_graph_preview'; import { useNavigateToGraphVisualization } from '../../shared/hooks/use_navigate_to_graph_visualization'; import { ExpandablePanel } from '../../../shared/components/expandable_panel'; +import { GRAPH_VISUALIZATION_IN_FLYOUT_ENABLED_EXPERIMENTAL_FEATURE } from '../../shared/constants/experimental_features'; /** * Graph preview under Overview, Visualizations. It shows a graph representation of entities. @@ -36,6 +38,9 @@ export const GraphPreviewContainer: React.FC = () => { const [visualizationInFlyoutEnabled] = useUiSetting$( ENABLE_VISUALIZATIONS_IN_FLYOUT_SETTING ); + const isGraphFeatureEnabled = useIsExperimentalFeatureEnabled( + GRAPH_VISUALIZATION_IN_FLYOUT_ENABLED_EXPERIMENTAL_FEATURE + ); const allowFlyoutExpansion = !isPreviewMode && !isPreview; @@ -55,6 +60,9 @@ export const GraphPreviewContainer: React.FC = () => { ecsData: dataAsNestedObject, }); + const shouldShowGraphPreview = + visualizationInFlyoutEnabled && isGraphFeatureEnabled && isAuditLog; + // TODO: default start and end might not capture the original event const { isLoading, isError, data } = useFetchGraphData({ req: { @@ -71,8 +79,7 @@ export const GraphPreviewContainer: React.FC = () => { }); return ( - isAuditLog && - visualizationInFlyoutEnabled && ( + shouldShowGraphPreview && ( ({ @@ -53,6 +54,12 @@ jest.mock( '../../../../detections/components/alerts_table/timeline_actions/investigate_in_resolver' ); +jest.mock('../../../../common/hooks/use_experimental_features', () => ({ + useIsExperimentalFeatureEnabled: jest.fn(), +})); + +const useIsExperimentalFeatureEnabledMock = useIsExperimentalFeatureEnabled as jest.Mock; + const mockUseUiSetting = jest.fn().mockReturnValue([false]); jest.mock('@kbn/kibana-react-plugin/public', () => { const original = jest.requireActual('@kbn/kibana-react-plugin/public'); @@ -132,6 +139,7 @@ describe('', () => { (useIsInvestigateInResolverActionEnabled as jest.Mock).mockReturnValue(true); (useExpandSection as jest.Mock).mockReturnValue(true); mockUseUiSetting.mockReturnValue([false]); + useIsExperimentalFeatureEnabledMock.mockReturnValue(false); const { getByTestId, queryByTestId } = renderVisualizationsSection(); expect(getByTestId(VISUALIZATIONS_SECTION_CONTENT_TEST_ID)).toBeVisible(); @@ -144,9 +152,30 @@ describe('', () => { it('should render the graph preview component if the feature is enabled', () => { (useExpandSection as jest.Mock).mockReturnValue(true); mockUseUiSetting.mockReturnValue([true]); + useIsExperimentalFeatureEnabledMock.mockReturnValue(true); const { getByTestId } = renderVisualizationsSection(); expect(getByTestId(`${GRAPH_PREVIEW_TEST_ID}LeftSection`)).toBeInTheDocument(); }); + + it('should not render the graph preview component if the experimental feature is disabled', () => { + (useExpandSection as jest.Mock).mockReturnValue(true); + mockUseUiSetting.mockReturnValue([true]); + useIsExperimentalFeatureEnabledMock.mockReturnValue(false); + + const { queryByTestId } = renderVisualizationsSection(); + + expect(queryByTestId(`${GRAPH_PREVIEW_TEST_ID}LeftSection`)).not.toBeInTheDocument(); + }); + + it('should not render the graph preview component if the flyout feature is disabled', () => { + (useExpandSection as jest.Mock).mockReturnValue(true); + mockUseUiSetting.mockReturnValue([false]); + useIsExperimentalFeatureEnabledMock.mockReturnValue(true); + + const { queryByTestId } = renderVisualizationsSection(); + + expect(queryByTestId(`${GRAPH_PREVIEW_TEST_ID}LeftSection`)).not.toBeInTheDocument(); + }); }); diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/visualizations_section.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/visualizations_section.tsx index 12ed787ae9c80..f0af9ba8bb80e 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/visualizations_section.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/visualizations_section.tsx @@ -17,7 +17,9 @@ import { VISUALIZATIONS_TEST_ID } from './test_ids'; import { GraphPreviewContainer } from './graph_preview_container'; import { useDocumentDetailsContext } from '../../shared/context'; import { useGraphPreview } from '../../shared/hooks/use_graph_preview'; +import { useIsExperimentalFeatureEnabled } from '../../../../common/hooks/use_experimental_features'; import { ENABLE_VISUALIZATIONS_IN_FLYOUT_SETTING } from '../../../../../common/constants'; +import { GRAPH_VISUALIZATION_IN_FLYOUT_ENABLED_EXPERIMENTAL_FEATURE } from '../../shared/constants/experimental_features'; const KEY = 'visualizations'; @@ -32,12 +34,19 @@ export const VisualizationsSection = memo(() => { ENABLE_VISUALIZATIONS_IN_FLYOUT_SETTING ); + const isGraphFeatureEnabled = useIsExperimentalFeatureEnabled( + GRAPH_VISUALIZATION_IN_FLYOUT_ENABLED_EXPERIMENTAL_FEATURE + ); + // Decide whether to show the graph preview or not - const { isAuditLog: isGraphPreviewEnabled } = useGraphPreview({ + const { isAuditLog } = useGraphPreview({ getFieldsData, ecsData: dataAsNestedObject, }); + const shouldShowGraphPreview = + visualizationInFlyoutEnabled && isGraphFeatureEnabled && isAuditLog; + return ( { - {visualizationInFlyoutEnabled && isGraphPreviewEnabled && ( + {shouldShowGraphPreview && ( <> diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/shared/constants/experimental_features.ts b/x-pack/plugins/security_solution/public/flyout/document_details/shared/constants/experimental_features.ts new file mode 100644 index 0000000000000..aeb8b899ef6ea --- /dev/null +++ b/x-pack/plugins/security_solution/public/flyout/document_details/shared/constants/experimental_features.ts @@ -0,0 +1,10 @@ +/* + * 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. + */ + +/** This security solution experimental feature allows user to enable/disable the graph visualization in Flyout feature (depends on securitySolution:enableVisualizationsInFlyout) */ +export const GRAPH_VISUALIZATION_IN_FLYOUT_ENABLED_EXPERIMENTAL_FEATURE = + 'graphVisualizationInFlyoutEnabled' as const; diff --git a/x-pack/plugins/security_solution/server/ui_settings.ts b/x-pack/plugins/security_solution/server/ui_settings.ts index 592c648792090..6aeb86750be7a 100644 --- a/x-pack/plugins/security_solution/server/ui_settings.ts +++ b/x-pack/plugins/security_solution/server/ui_settings.ts @@ -209,7 +209,7 @@ export const initUiSettings = ( 'xpack.securitySolution.uiSettings.enableVisualizationsInFlyoutDescription', { defaultMessage: - '[technical preview] Enable visualizations (analyzer, session viewer, and graph view) in flyout.', + '[technical preview] Enable visualizations (analyzer and session viewer) in flyout.', values: { em: (chunks) => `${chunks}` }, } ), diff --git a/x-pack/test/api_integration/apis/cloud_security_posture/config.ts b/x-pack/test/api_integration/apis/cloud_security_posture/config.ts index 81a2cd0df2fd5..28ac1f643041b 100644 --- a/x-pack/test/api_integration/apis/cloud_security_posture/config.ts +++ b/x-pack/test/api_integration/apis/cloud_security_posture/config.ts @@ -17,7 +17,6 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { ...baseConfig.get('kbnTestServer'), serverArgs: [ ...baseConfig.get('kbnTestServer.serverArgs'), - `--uiSettings.overrides.securitySolution:enableVisualizationsInFlyout=false`, // Disables /graph API `--logging.loggers=${JSON.stringify([ ...getKibanaCliLoggers(baseConfig.get('kbnTestServer.serverArgs')), { diff --git a/x-pack/test/api_integration/apis/cloud_security_posture/graph.ts b/x-pack/test/api_integration/apis/cloud_security_posture/graph.ts index bcf8ef10f483c..4ff483bff343d 100644 --- a/x-pack/test/api_integration/apis/cloud_security_posture/graph.ts +++ b/x-pack/test/api_integration/apis/cloud_security_posture/graph.ts @@ -35,7 +35,8 @@ export default function (providerContext: FtrProviderContext) { }; describe('POST /internal/cloud_security_posture/graph', () => { - describe('Feature flag', () => { + // TODO: fix once feature flag is enabled for the API + describe.skip('Feature flag', () => { it('should return 404 when feature flag is not toggled', async () => { await postGraph(supertest, { query: { diff --git a/x-pack/test/cloud_security_posture_api/config.ts b/x-pack/test/cloud_security_posture_api/config.ts index 0dac59b47c52c..4e0ecd1f26e43 100644 --- a/x-pack/test/cloud_security_posture_api/config.ts +++ b/x-pack/test/cloud_security_posture_api/config.ts @@ -34,7 +34,6 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { * 1. release a new package to EPR * 2. merge the updated version number change to kibana */ - `--uiSettings.overrides.securitySolution:enableVisualizationsInFlyout=true`, // Enables /graph API `--xpack.fleet.packages.0.name=cloud_security_posture`, `--xpack.fleet.packages.0.version=${CLOUD_SECURITY_PLUGIN_VERSION}`, // `--xpack.fleet.registryUrl=https://localhost:8080`, diff --git a/x-pack/test/cloud_security_posture_functional/config.ts b/x-pack/test/cloud_security_posture_functional/config.ts index db560992e4fad..bea81dd38dc15 100644 --- a/x-pack/test/cloud_security_posture_functional/config.ts +++ b/x-pack/test/cloud_security_posture_functional/config.ts @@ -39,6 +39,9 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { * 2. merge the updated version number change to kibana */ `--uiSettings.overrides.securitySolution:enableVisualizationsInFlyout=true`, + `--xpack.securitySolution.enableExperimental=${JSON.stringify([ + 'graphVisualizationInFlyoutEnabled', + ])}`, `--xpack.fleet.packages.0.name=cloud_security_posture`, `--xpack.fleet.packages.0.version=${CLOUD_SECURITY_PLUGIN_VERSION}`, // `--xpack.fleet.registryUrl=https://localhost:8080`, diff --git a/x-pack/test_serverless/api_integration/test_suites/security/config.ts b/x-pack/test_serverless/api_integration/test_suites/security/config.ts index a75c3e4186a02..d5d816dfcdf17 100644 --- a/x-pack/test_serverless/api_integration/test_suites/security/config.ts +++ b/x-pack/test_serverless/api_integration/test_suites/security/config.ts @@ -33,7 +33,5 @@ export default createTestConfig({ '--xpack.dataUsage.autoops.api.url=http://localhost:9000', `--xpack.dataUsage.autoops.api.tls.certificate=${KBN_CERT_PATH}`, `--xpack.dataUsage.autoops.api.tls.key=${KBN_KEY_PATH}`, - - `--uiSettings.overrides.securitySolution:enableVisualizationsInFlyout=true`, // Enables /graph API ], });