From 62ba5cfebda78d2ee8138a959467213fe44886ac Mon Sep 17 00:00:00 2001 From: Michael Myers Date: Thu, 12 Dec 2024 15:50:58 -0600 Subject: [PATCH] Disable Enroll New Integration button on missing permissions This will disable to Enroll New Integration button if the user does not have the required permissions. It also updates the MissingPermissionsTooltip to handle cases where a list of permissions represents "one of these" required permissions scenarios instead of "all of these". --- .../MissingPermissionsTooltip.tsx | 10 +++- .../src/Integrations/Integrations.tsx | 10 +++- .../IntegrationsAddButton.test.tsx | 54 +++++++++++++++++++ .../Integrations/IntegrationsAddButton.tsx | 48 ++++++++++++----- web/packages/teleport/src/features.tsx | 14 ++++- 5 files changed, 118 insertions(+), 18 deletions(-) create mode 100644 web/packages/teleport/src/Integrations/IntegrationsAddButton.test.tsx diff --git a/web/packages/shared/components/MissingPermissionsTooltip/MissingPermissionsTooltip.tsx b/web/packages/shared/components/MissingPermissionsTooltip/MissingPermissionsTooltip.tsx index aaef46ec0baf6..f414c2526318f 100644 --- a/web/packages/shared/components/MissingPermissionsTooltip/MissingPermissionsTooltip.tsx +++ b/web/packages/shared/components/MissingPermissionsTooltip/MissingPermissionsTooltip.tsx @@ -20,14 +20,22 @@ import { Box, Text, Flex } from 'design'; export const MissingPermissionsTooltip = ({ missingPermissions, + requiresAll = true, }: { missingPermissions: string[]; + requiresAll?: boolean; }) => { return ( You do not have all of the required permissions. - Missing permissions: + {requiresAll ? ( + Missing permissions: + ) : ( + + You must have at least one of these role permissions: + + )} {missingPermissions.map(perm => ( {perm} diff --git a/web/packages/teleport/src/Integrations/Integrations.tsx b/web/packages/teleport/src/Integrations/Integrations.tsx index e528a252db7d0..c51acdec84563 100644 --- a/web/packages/teleport/src/Integrations/Integrations.tsx +++ b/web/packages/teleport/src/Integrations/Integrations.tsx @@ -41,7 +41,6 @@ export function Integrations() { const { attempt, run } = useAttempt('processing'); const ctx = useTeleport(); - const canCreateIntegrations = ctx.storeUser.getIntegrationsAccess().create; useEffect(() => { // TODO(lisa): handle paginating as a follow up polish. @@ -82,7 +81,14 @@ export function Integrations() { Integrations - + {attempt.status === 'failed' && } {attempt.status === 'processing' && ( diff --git a/web/packages/teleport/src/Integrations/IntegrationsAddButton.test.tsx b/web/packages/teleport/src/Integrations/IntegrationsAddButton.test.tsx new file mode 100644 index 0000000000000..6021f79e52a96 --- /dev/null +++ b/web/packages/teleport/src/Integrations/IntegrationsAddButton.test.tsx @@ -0,0 +1,54 @@ +/** + * Teleport + * Copyright (C) 2024 Gravitational, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import { MemoryRouter } from 'react-router'; +import { render, screen } from 'design/utils/testing'; + +import { IntegrationsAddButton } from './IntegrationsAddButton'; + +test('is disables if all permissions are missing', async () => { + render( + + + + ); + + expect( + screen.getByTitle('You do not have access to add new integrations') + ).toBeInTheDocument(); +}); + +test('is enabled if at least one permission is true', async () => { + render( + + + + ); + + expect(screen.getByText('Enroll New Integration')).toBeEnabled(); +}); diff --git a/web/packages/teleport/src/Integrations/IntegrationsAddButton.tsx b/web/packages/teleport/src/Integrations/IntegrationsAddButton.tsx index 3c66c1c1272e8..425e66335b744 100644 --- a/web/packages/teleport/src/Integrations/IntegrationsAddButton.tsx +++ b/web/packages/teleport/src/Integrations/IntegrationsAddButton.tsx @@ -19,26 +19,48 @@ import React from 'react'; import { Link } from 'react-router-dom'; import { Button } from 'design'; +import { HoverTooltip } from 'design/Tooltip'; +import { MissingPermissionsTooltip } from 'shared/components/MissingPermissionsTooltip'; import cfg from 'teleport/config'; export function IntegrationsAddButton({ - canCreate = false, + requiredPermissions, }: { - canCreate: boolean; + requiredPermissions: { value: boolean; label: string }[]; }) { + const canCreateIntegrations = requiredPermissions.some(v => v.value); + const missingPermissions = requiredPermissions + .filter(perm => !perm.value) + .map(perm => perm.label); + return ( - + + ); } diff --git a/web/packages/teleport/src/features.tsx b/web/packages/teleport/src/features.tsx index 7b19c2aa33856..b3f849e17ad85 100644 --- a/web/packages/teleport/src/features.tsx +++ b/web/packages/teleport/src/features.tsx @@ -247,7 +247,12 @@ export class FeatureBots implements TeleportFeature { component: Bots, }; - hasAccess() { + hasAccess(flags: FeatureFlags) { + // if feature hiding is enabled, only show + // if the user has access + if (cfg.hideInaccessibleFeatures) { + return flags.listBots; + } return true; } @@ -435,7 +440,12 @@ export class FeatureIntegrations implements TeleportFeature { section = ManagementSection.Access; hasAccess(flags: FeatureFlags) { - return flags.integrations; + // if feature hiding is enabled, only show + // if the user has access + if (cfg.hideInaccessibleFeatures) { + return flags.integrations; + } + return true; } route = {