Skip to content

Commit

Permalink
[Security Solution] [Onboarding] t1_analyst role blocked from interac…
Browse files Browse the repository at this point in the history
…ting with cards due to missing integration privileges (elastic#202413)

## Summary

This PR temporarily fixes the elastic#201799 issue for Serverless.



https://github.com/user-attachments/assets/604128cb-49b0-4a93-9a15-2a5a0c511883



### Checklist

Check the PR satisfies following conditions. 

Reviewers should verify this PR satisfies this list as well.

- [ ] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios
  • Loading branch information
agusruidiazgd authored Dec 2, 2024
1 parent 97dab10 commit 3daaaa5
Show file tree
Hide file tree
Showing 11 changed files with 149 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const props = {
checkComplete: jest.fn(),
isCardComplete: jest.fn(),
setExpandedCardId: jest.fn(),
isCardAvailable: jest.fn(),
};

describe('AlertsCard', () => {
Expand All @@ -31,7 +32,8 @@ describe('AlertsCard', () => {
expect(getByTestId('alertsCardDescription')).toBeInTheDocument();
});

it('card callout should be rendered if integrations cards is not complete', () => {
it('card callout should be rendered if integrations card is available but not complete', () => {
props.isCardAvailable.mockReturnValueOnce(true);
props.isCardComplete.mockReturnValueOnce(false);

const { getByText } = render(
Expand All @@ -43,7 +45,20 @@ describe('AlertsCard', () => {
expect(getByText('To view alerts add integrations first.')).toBeInTheDocument();
});

it('card button should be disabled if integrations cards is not complete', () => {
it('card callout should not be rendered if integrations card is not available', () => {
props.isCardAvailable.mockReturnValueOnce(false);

const { queryByText } = render(
<TestProviders>
<AlertsCard {...props} />
</TestProviders>
);

expect(queryByText('To view alerts add integrations first.')).not.toBeInTheDocument();
});

it('card button should be disabled if integrations card is available but not complete', () => {
props.isCardAvailable.mockReturnValueOnce(true);
props.isCardComplete.mockReturnValueOnce(false);

const { getByTestId } = render(
Expand All @@ -54,4 +69,17 @@ describe('AlertsCard', () => {

expect(getByTestId('alertsCardButton').querySelector('button')).toBeDisabled();
});

it('card button should be enabled if integrations card is complete', () => {
props.isCardAvailable.mockReturnValueOnce(true);
props.isCardComplete.mockReturnValueOnce(true);

const { getByTestId } = render(
<TestProviders>
<AlertsCard {...props} />
</TestProviders>
);

expect(getByTestId('alertsCardButton').querySelector('button')).not.toBeDisabled();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,18 @@ export const AlertsCard: OnboardingCardComponent = ({
isCardComplete,
setExpandedCardId,
setComplete,
isCardAvailable,
}) => {
const isIntegrationsCardComplete = useMemo(
() => isCardComplete(OnboardingCardId.integrations),
[isCardComplete]
);

const isIntegrationsCardAvailable = useMemo(
() => isCardAvailable(OnboardingCardId.integrations),
[isCardAvailable]
);

const expandIntegrationsCard = useCallback(() => {
setExpandedCardId(OnboardingCardId.integrations, { scroll: true });
}, [setExpandedCardId]);
Expand All @@ -43,7 +49,7 @@ export const AlertsCard: OnboardingCardComponent = ({
<CardSubduedText data-test-subj="alertsCardDescription" size="s">
{i18n.ALERTS_CARD_DESCRIPTION}
</CardSubduedText>
{!isIntegrationsCardComplete && (
{isIntegrationsCardAvailable && !isIntegrationsCardComplete && (
<>
<EuiSpacer size="m" />
<CardCallOut
Expand All @@ -69,7 +75,7 @@ export const AlertsCard: OnboardingCardComponent = ({
onClick={() => setComplete(true)}
deepLinkId={SecurityPageName.alerts}
fill
isDisabled={!isIntegrationsCardComplete}
isDisabled={isIntegrationsCardAvailable && !isIntegrationsCardComplete}
>
{i18n.ALERTS_CARD_VIEW_ALERTS_BUTTON}
</SecuritySolutionLinkButton>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,18 @@ export const AssistantCard: OnboardingCardComponent<AssistantCardMetadata> = ({
setExpandedCardId,
checkCompleteMetadata,
checkComplete,
isCardAvailable,
}) => {
const isIntegrationsCardComplete = useMemo(
() => isCardComplete(OnboardingCardId.integrations),
[isCardComplete]
);

const isIntegrationsCardAvailable = useMemo(
() => isCardAvailable(OnboardingCardId.integrations),
[isCardAvailable]
);

const expandIntegrationsCard = useCallback(() => {
setExpandedCardId(OnboardingCardId.integrations, { scroll: true });
}, [setExpandedCardId]);
Expand All @@ -45,13 +51,7 @@ export const AssistantCard: OnboardingCardComponent<AssistantCardMetadata> = ({
<CardSubduedText size="s">{i18n.ASSISTANT_CARD_DESCRIPTION}</CardSubduedText>
</EuiFlexItem>
<EuiFlexItem>
{isIntegrationsCardComplete ? (
<ConnectorCards
canCreateConnectors={canCreateConnectors}
connectors={connectors}
onConnectorSaved={checkComplete}
/>
) : (
{isIntegrationsCardAvailable && !isIntegrationsCardComplete ? (
<EuiFlexItem
className={css`
width: 45%;
Expand All @@ -73,6 +73,12 @@ export const AssistantCard: OnboardingCardComponent<AssistantCardMetadata> = ({
}
/>
</EuiFlexItem>
) : (
<ConnectorCards
canCreateConnectors={canCreateConnectors}
connectors={connectors}
onConnectorSaved={checkComplete}
/>
)}
</EuiFlexItem>
</EuiFlexGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const props = {
checkComplete: jest.fn(),
isCardComplete: jest.fn(),
setExpandedCardId: jest.fn(),
isCardAvailable: jest.fn(),
};

describe('RulesCard', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@ const props = {
checkComplete: jest.fn(),
isCardComplete: jest.fn(),
setExpandedCardId: jest.fn(),
isCardAvailable: jest.fn(),
};

describe('RulesCard', () => {
describe('DashboardsCard', () => {
beforeEach(() => {
jest.clearAllMocks();
});
Expand All @@ -34,7 +35,8 @@ describe('RulesCard', () => {
expect(getByTestId('dashboardsDescription')).toBeInTheDocument();
});

it('card callout should be rendered if integrations cards is not complete', () => {
it('card callout should be rendered if integrations card is available but not complete', () => {
props.isCardAvailable.mockReturnValueOnce(true);
props.isCardComplete.mockReturnValueOnce(false);

const { getByText } = render(
Expand All @@ -46,7 +48,20 @@ describe('RulesCard', () => {
expect(getByText('To view dashboards add integrations first.')).toBeInTheDocument();
});

it('card button should be disabled if integrations cards is not complete', () => {
it('card callout should not be rendered if integrations card is not available', () => {
props.isCardAvailable.mockReturnValueOnce(false);

const { queryByText } = render(
<TestProviders>
<DashboardsCard {...props} />
</TestProviders>
);

expect(queryByText('To view dashboards add integrations first.')).not.toBeInTheDocument();
});

it('card button should be disabled if integrations card is available but not complete', () => {
props.isCardAvailable.mockReturnValueOnce(true);
props.isCardComplete.mockReturnValueOnce(false);

const { getByTestId } = render(
Expand All @@ -57,7 +72,22 @@ describe('RulesCard', () => {

expect(getByTestId('dashboardsCardButton').querySelector('button')).toBeDisabled();
});

it('card button should be enabled if integrations card is complete', () => {
props.isCardAvailable.mockReturnValueOnce(true);
props.isCardComplete.mockReturnValueOnce(true);

const { getByTestId } = render(
<TestProviders>
<DashboardsCard {...props} />
</TestProviders>
);

expect(getByTestId('dashboardsCardButton').querySelector('button')).not.toBeDisabled();
});

it('should expand integrations card when callout link is clicked', () => {
props.isCardAvailable.mockReturnValueOnce(true);
props.isCardComplete.mockReturnValueOnce(false); // To show the callout

const { getByTestId } = render(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,18 @@ export const DashboardsCard: OnboardingCardComponent = ({
isCardComplete,
setComplete,
setExpandedCardId,
isCardAvailable,
}) => {
const isIntegrationsCardComplete = useMemo(
() => isCardComplete(OnboardingCardId.integrations),
[isCardComplete]
);

const isIntegrationsCardAvailable = useMemo(
() => isCardAvailable(OnboardingCardId.integrations),
[isCardAvailable]
);

const expandIntegrationsCard = useCallback(() => {
setExpandedCardId(OnboardingCardId.integrations, { scroll: true });
}, [setExpandedCardId]);
Expand All @@ -46,7 +52,7 @@ export const DashboardsCard: OnboardingCardComponent = ({
<CardSubduedText data-test-subj="dashboardsDescription" size="s">
{i18n.DASHBOARDS_CARD_DESCRIPTION}
</CardSubduedText>
{!isIntegrationsCardComplete && (
{isIntegrationsCardAvailable && !isIntegrationsCardComplete && (
<>
<EuiSpacer size="m" />
<CardCallOut
Expand Down Expand Up @@ -77,7 +83,7 @@ export const DashboardsCard: OnboardingCardComponent = ({
cardId={OnboardingCardId.dashboards}
deepLinkId={SecurityPageName.dashboards}
fill
isDisabled={!isIntegrationsCardComplete}
isDisabled={isIntegrationsCardAvailable && !isIntegrationsCardComplete}
>
{i18n.DASHBOARDS_CARD_GO_TO_DASHBOARDS_BUTTON}
</CardLinkButton>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const props = {
checkComplete: jest.fn(),
isCardComplete: jest.fn(),
setExpandedCardId: jest.fn(),
isCardAvailable: jest.fn(),
};

describe('IntegrationsCard', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const props = {
setComplete: jest.fn(),
checkComplete: jest.fn(),
isCardComplete: jest.fn(),
isCardAvailable: jest.fn(),
setExpandedCardId: jest.fn(),
};

Expand All @@ -31,7 +32,8 @@ describe('RulesCard', () => {
expect(getByTestId('rulesCardDescription')).toBeInTheDocument();
});

it('card callout should be rendered if integrations cards is not complete', () => {
it('card callout should be rendered if integrations card is available but not complete', () => {
props.isCardAvailable.mockReturnValueOnce(true);
props.isCardComplete.mockReturnValueOnce(false);

const { getByText } = render(
Expand All @@ -43,7 +45,20 @@ describe('RulesCard', () => {
expect(getByText('To add Elastic rules add integrations first.')).toBeInTheDocument();
});

it('card button should be disabled if integrations cards is not complete', () => {
it('card callout should not be rendered if integrations card is not available', () => {
props.isCardAvailable.mockReturnValueOnce(false);

const { queryByText } = render(
<TestProviders>
<RulesCard {...props} />
</TestProviders>
);

expect(queryByText('To add Elastic rules add integrations first.')).not.toBeInTheDocument();
});

it('card button should be disabled if integrations card is available but not complete', () => {
props.isCardAvailable.mockReturnValueOnce(true);
props.isCardComplete.mockReturnValueOnce(false);

const { getByTestId } = render(
Expand All @@ -54,4 +69,17 @@ describe('RulesCard', () => {

expect(getByTestId('rulesCardButton').querySelector('button')).toBeDisabled();
});

it('card button should be enabled if integrations card is complete', () => {
props.isCardAvailable.mockReturnValueOnce(true);
props.isCardComplete.mockReturnValueOnce(true);

const { getByTestId } = render(
<TestProviders>
<RulesCard {...props} />
</TestProviders>
);

expect(getByTestId('rulesCardButton').querySelector('button')).not.toBeDisabled();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,21 @@ import { CardSubduedText } from '../common/card_subdued_text';
import rulesImageSrc from './images/rules.png';
import * as i18n from './translations';

export const RulesCard: OnboardingCardComponent = ({ isCardComplete, setExpandedCardId }) => {
export const RulesCard: OnboardingCardComponent = ({
isCardComplete,
setExpandedCardId,
isCardAvailable,
}) => {
const isIntegrationsCardComplete = useMemo(
() => isCardComplete(OnboardingCardId.integrations),
[isCardComplete]
);

const isIntegrationsCardAvailable = useMemo(
() => isCardAvailable(OnboardingCardId.integrations),
[isCardAvailable]
);

const expandIntegrationsCard = useCallback(() => {
setExpandedCardId(OnboardingCardId.integrations, { scroll: true });
}, [setExpandedCardId]);
Expand All @@ -39,7 +48,7 @@ export const RulesCard: OnboardingCardComponent = ({ isCardComplete, setExpanded
<CardSubduedText data-test-subj="rulesCardDescription" size="s">
{i18n.RULES_CARD_DESCRIPTION}
</CardSubduedText>
{!isIntegrationsCardComplete && (
{isIntegrationsCardAvailable && !isIntegrationsCardComplete && (
<>
<EuiSpacer size="m" />
<CardCallOut
Expand All @@ -64,7 +73,7 @@ export const RulesCard: OnboardingCardComponent = ({ isCardComplete, setExpanded
<SecuritySolutionLinkButton
deepLinkId={SecurityPageName.rules}
fill
isDisabled={!isIntegrationsCardComplete}
isDisabled={isIntegrationsCardAvailable && !isIntegrationsCardComplete}
>
{i18n.RULES_CARD_ADD_RULES_BUTTON}
</SecuritySolutionLinkButton>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { OnboardingCardGroup } from './onboarding_card_group';
import { OnboardingCardPanel } from './onboarding_card_panel';
import { useExpandedCard } from './hooks/use_expanded_card';
import { useCompletedCards } from './hooks/use_completed_cards';
import type { IsCardAvailable } from '../../types';

export const OnboardingBody = React.memo(() => {
const bodyConfig = useBodyConfig();
Expand Down Expand Up @@ -47,6 +48,12 @@ export const OnboardingBody = React.memo(() => {
[checkCardComplete]
);

const isCardAvailable = useCallback<IsCardAvailable>(
(cardId: OnboardingCardId) =>
bodyConfig.some((group) => group.cards.some((card) => card.id === cardId)),
[bodyConfig]
);

return (
<EuiFlexGroup direction="column" gutterSize="xl">
{bodyConfig.map((group, index) => (
Expand All @@ -72,6 +79,7 @@ export const OnboardingBody = React.memo(() => {
setComplete={createSetCardComplete(id)}
checkComplete={createCheckCardComplete(id)}
isCardComplete={isCardComplete}
isCardAvailable={isCardAvailable}
setExpandedCardId={setExpandedCardId}
checkCompleteMetadata={cardCheckCompleteResult?.metadata}
/>
Expand Down
Loading

0 comments on commit 3daaaa5

Please sign in to comment.