From eb1285129a8f39dd9f663f9d08409abec19da5bf Mon Sep 17 00:00:00 2001 From: Ryan Clark Date: Fri, 8 Nov 2024 09:24:20 +0100 Subject: [PATCH] Icons and nav titles for Access Graph navigation (#48568) * Add icons for TAG routes * Use `exact` from the route when matching active state * Add nav titles for TAG routes * Add history library types * Add ACL for discovery configs & access graph integrations access * Add min-height:0; to ensure flex children scroll properly * Restore types and imports for icons story * Fix test, add type definition to help catch in type checking --- package.json | 1 + pnpm-lock.yaml | 3 + web/packages/design/src/Icon/Icons.story.tsx | 4 + web/packages/design/src/Icon/Icons/Crown.tsx | 62 +++ web/packages/design/src/Icon/Icons/Layout.tsx | 67 +++ web/packages/design/src/Icon/Icons/Plugs.tsx | 68 +++ web/packages/design/src/Icon/Icons/Table.tsx | 62 +++ web/packages/design/src/Icon/assets/Crown.svg | 1 + .../design/src/Icon/assets/Layout.svg | 1 + web/packages/design/src/Icon/assets/Plugs.svg | 1 + web/packages/design/src/Icon/assets/Table.svg | 2 + web/packages/design/src/Icon/index.ts | 4 + web/packages/teleport/src/Main/Main.tsx | 1 + .../Navigation/SideNavigation/Navigation.tsx | 2 +- web/packages/teleport/src/mocks/contexts.ts | 1 + .../teleport/src/services/user/makeAcl.ts | 3 + .../teleport/src/services/user/types.ts | 1 + .../teleport/src/services/user/user.test.ts | 460 +++++++++--------- .../teleport/src/stores/storeUserContext.ts | 4 + web/packages/teleport/src/teleportContext.tsx | 12 + web/packages/teleport/src/types.ts | 9 +- 21 files changed, 542 insertions(+), 227 deletions(-) create mode 100644 web/packages/design/src/Icon/Icons/Crown.tsx create mode 100644 web/packages/design/src/Icon/Icons/Layout.tsx create mode 100644 web/packages/design/src/Icon/Icons/Plugs.tsx create mode 100644 web/packages/design/src/Icon/Icons/Table.tsx create mode 100644 web/packages/design/src/Icon/assets/Crown.svg create mode 100644 web/packages/design/src/Icon/assets/Layout.svg create mode 100644 web/packages/design/src/Icon/assets/Plugs.svg create mode 100644 web/packages/design/src/Icon/assets/Table.svg diff --git a/package.json b/package.json index e9a63311eedaf..4f974046b48ef 100644 --- a/package.json +++ b/package.json @@ -44,6 +44,7 @@ "@testing-library/react": "^16.0.0", "@testing-library/user-event": "^14.5.2", "@types/jest": "^29.5.13", + "@types/history": "^4.7.11", "@types/node": "^20.16.10", "@types/react": "^18.3.10", "@types/react-dom": "^18.3.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 793e2e15facb6..cd7c87b2ad058 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -122,6 +122,9 @@ importers: '@testing-library/user-event': specifier: ^14.5.2 version: 14.5.2(@testing-library/dom@10.1.0) + '@types/history': + specifier: ^4.7.11 + version: 4.7.11 '@types/jest': specifier: ^29.5.13 version: 29.5.13 diff --git a/web/packages/design/src/Icon/Icons.story.tsx b/web/packages/design/src/Icon/Icons.story.tsx index 4a792aeec912c..388e996fcbe73 100644 --- a/web/packages/design/src/Icon/Icons.story.tsx +++ b/web/packages/design/src/Icon/Icons.story.tsx @@ -107,6 +107,7 @@ export const Icons = () => ( + @@ -142,6 +143,7 @@ export const Icons = () => ( + @@ -172,6 +174,7 @@ export const Icons = () => ( + @@ -198,6 +201,7 @@ export const Icons = () => ( + diff --git a/web/packages/design/src/Icon/Icons/Crown.tsx b/web/packages/design/src/Icon/Icons/Crown.tsx new file mode 100644 index 0000000000000..8b00c37fa6e35 --- /dev/null +++ b/web/packages/design/src/Icon/Icons/Crown.tsx @@ -0,0 +1,62 @@ +/** + * Teleport + * Copyright (C) 2023 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 . + */ + +/* MIT License + +Copyright (c) 2020 Phosphor Icons + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +*/ + +import React from 'react'; + +import { Icon, IconProps } from '../Icon'; + +/* + +THIS FILE IS GENERATED. DO NOT EDIT. + +*/ + +export function Crown({ size = 24, color, ...otherProps }: IconProps) { + return ( + + + + ); +} diff --git a/web/packages/design/src/Icon/Icons/Layout.tsx b/web/packages/design/src/Icon/Icons/Layout.tsx new file mode 100644 index 0000000000000..5de7721ff412c --- /dev/null +++ b/web/packages/design/src/Icon/Icons/Layout.tsx @@ -0,0 +1,67 @@ +/** + * Teleport + * Copyright (C) 2023 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 . + */ + +/* MIT License + +Copyright (c) 2020 Phosphor Icons + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +*/ + +import React from 'react'; + +import { Icon, IconProps } from '../Icon'; + +/* + +THIS FILE IS GENERATED. DO NOT EDIT. + +*/ + +export function Layout({ size = 24, color, ...otherProps }: IconProps) { + return ( + + + + ); +} diff --git a/web/packages/design/src/Icon/Icons/Plugs.tsx b/web/packages/design/src/Icon/Icons/Plugs.tsx new file mode 100644 index 0000000000000..09cf4a4851605 --- /dev/null +++ b/web/packages/design/src/Icon/Icons/Plugs.tsx @@ -0,0 +1,68 @@ +/** + * Teleport + * Copyright (C) 2023 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 . + */ + +/* MIT License + +Copyright (c) 2020 Phosphor Icons + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +*/ + +import React from 'react'; + +import { Icon, IconProps } from '../Icon'; + +/* + +THIS FILE IS GENERATED. DO NOT EDIT. + +*/ + +export function Plugs({ size = 24, color, ...otherProps }: IconProps) { + return ( + + + + + ); +} diff --git a/web/packages/design/src/Icon/Icons/Table.tsx b/web/packages/design/src/Icon/Icons/Table.tsx new file mode 100644 index 0000000000000..11db553f5274c --- /dev/null +++ b/web/packages/design/src/Icon/Icons/Table.tsx @@ -0,0 +1,62 @@ +/** + * Teleport + * Copyright (C) 2023 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 . + */ + +/* MIT License + +Copyright (c) 2020 Phosphor Icons + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +*/ + +import React from 'react'; + +import { Icon, IconProps } from '../Icon'; + +/* + +THIS FILE IS GENERATED. DO NOT EDIT. + +*/ + +export function Table({ size = 24, color, ...otherProps }: IconProps) { + return ( + + + + ); +} diff --git a/web/packages/design/src/Icon/assets/Crown.svg b/web/packages/design/src/Icon/assets/Crown.svg new file mode 100644 index 0000000000000..a724783fd16b0 --- /dev/null +++ b/web/packages/design/src/Icon/assets/Crown.svg @@ -0,0 +1 @@ + diff --git a/web/packages/design/src/Icon/assets/Layout.svg b/web/packages/design/src/Icon/assets/Layout.svg new file mode 100644 index 0000000000000..96d78c2980341 --- /dev/null +++ b/web/packages/design/src/Icon/assets/Layout.svg @@ -0,0 +1 @@ + diff --git a/web/packages/design/src/Icon/assets/Plugs.svg b/web/packages/design/src/Icon/assets/Plugs.svg new file mode 100644 index 0000000000000..d797e7c954097 --- /dev/null +++ b/web/packages/design/src/Icon/assets/Plugs.svg @@ -0,0 +1 @@ + diff --git a/web/packages/design/src/Icon/assets/Table.svg b/web/packages/design/src/Icon/assets/Table.svg new file mode 100644 index 0000000000000..265ba9ed60647 --- /dev/null +++ b/web/packages/design/src/Icon/assets/Table.svg @@ -0,0 +1,2 @@ + diff --git a/web/packages/design/src/Icon/index.ts b/web/packages/design/src/Icon/index.ts index 6e24c134497db..6942c618d7fa5 100644 --- a/web/packages/design/src/Icon/index.ts +++ b/web/packages/design/src/Icon/index.ts @@ -93,6 +93,7 @@ export { Contract } from './Icons/Contract'; export { Copy } from './Icons/Copy'; export { CreditCard } from './Icons/CreditCard'; export { Cross } from './Icons/Cross'; +export { Crown } from './Icons/Crown'; export { Database } from './Icons/Database'; export { Desktop } from './Icons/Desktop'; export { DeviceMobileCamera } from './Icons/DeviceMobileCamera'; @@ -128,6 +129,7 @@ export { Kubernetes } from './Icons/Kubernetes'; export { Label } from './Icons/Label'; export { Lan } from './Icons/Lan'; export { Laptop } from './Icons/Laptop'; +export { Layout } from './Icons/Layout'; export { License } from './Icons/License'; export { LineSegment } from './Icons/LineSegment'; export { LineSegments } from './Icons/LineSegments'; @@ -158,6 +160,7 @@ export { PaperPlane } from './Icons/PaperPlane'; export { Password } from './Icons/Password'; export { Pencil } from './Icons/Pencil'; export { Planet } from './Icons/Planet'; +export { Plugs } from './Icons/Plugs'; export { PlugsConnected } from './Icons/PlugsConnected'; export { Plus } from './Icons/Plus'; export { PowerSwitch } from './Icons/PowerSwitch'; @@ -184,6 +187,7 @@ export { SquaresFour } from './Icons/SquaresFour'; export { Stars } from './Icons/Stars'; export { Sun } from './Icons/Sun'; export { SyncAlt } from './Icons/SyncAlt'; +export { Table } from './Icons/Table'; export { Tablet } from './Icons/Tablet'; export { Tags } from './Icons/Tags'; export { Terminal } from './Icons/Terminal'; diff --git a/web/packages/teleport/src/Main/Main.tsx b/web/packages/teleport/src/Main/Main.tsx index 7838bb430ccc2..8bdf8943a67f7 100644 --- a/web/packages/teleport/src/Main/Main.tsx +++ b/web/packages/teleport/src/Main/Main.tsx @@ -339,6 +339,7 @@ export const ContentMinWidth = ({ children }: { children: ReactNode }) => { flex-direction: column; flex: 1; ${enforceMinWidth ? 'min-width: 1000px;' : ''} + min-height: 0; `} > {children} diff --git a/web/packages/teleport/src/Navigation/SideNavigation/Navigation.tsx b/web/packages/teleport/src/Navigation/SideNavigation/Navigation.tsx index 9ba01936767d4..84be28f8192f9 100644 --- a/web/packages/teleport/src/Navigation/SideNavigation/Navigation.tsx +++ b/web/packages/teleport/src/Navigation/SideNavigation/Navigation.tsx @@ -177,7 +177,7 @@ function getNavSubsectionForRoute( .find(feature => matchPath(route.pathname, { path: feature.route.path, - exact: false, + exact: feature.route.exact, }) ); diff --git a/web/packages/teleport/src/mocks/contexts.ts b/web/packages/teleport/src/mocks/contexts.ts index 731ed4b55868b..bf2581de1763e 100644 --- a/web/packages/teleport/src/mocks/contexts.ts +++ b/web/packages/teleport/src/mocks/contexts.ts @@ -73,6 +73,7 @@ export const allAccessAcl: Acl = { accessGraph: fullAccess, bots: fullAccess, accessMonitoringRule: fullAccess, + discoverConfigs: fullAccess, }; export function getAcl(cfg?: { noAccess: boolean }) { diff --git a/web/packages/teleport/src/services/user/makeAcl.ts b/web/packages/teleport/src/services/user/makeAcl.ts index ae7e7c999ae77..57c5fd99615c7 100644 --- a/web/packages/teleport/src/services/user/makeAcl.ts +++ b/web/packages/teleport/src/services/user/makeAcl.ts @@ -72,6 +72,8 @@ export function makeAcl(json): Acl { const bots = json.bots || defaultAccess; const accessMonitoringRule = json.accessMonitoringRule || defaultAccess; + const discoverConfigs = json.discoverConfigs || defaultAccess; + return { accessList, authConnectors, @@ -107,6 +109,7 @@ export function makeAcl(json): Acl { accessGraph, bots, accessMonitoringRule, + discoverConfigs, }; } diff --git a/web/packages/teleport/src/services/user/types.ts b/web/packages/teleport/src/services/user/types.ts index 150a44cf40b1c..e2a5484648eb5 100644 --- a/web/packages/teleport/src/services/user/types.ts +++ b/web/packages/teleport/src/services/user/types.ts @@ -92,6 +92,7 @@ export interface Acl { connectionDiagnostic: Access; license: Access; download: Access; + discoverConfigs: Access; plugins: Access; integrations: AccessWithUse; deviceTrust: Access; diff --git a/web/packages/teleport/src/services/user/user.test.ts b/web/packages/teleport/src/services/user/user.test.ts index 7b65e467e6a0c..53c6d26d0a04e 100644 --- a/web/packages/teleport/src/services/user/user.test.ts +++ b/web/packages/teleport/src/services/user/user.test.ts @@ -21,7 +21,7 @@ import cfg from 'teleport/config'; import user from './user'; import { makeTraits } from './makeUser'; -import { ExcludeUserField, PasswordState, User } from './types'; +import { Acl, ExcludeUserField, PasswordState, User } from './types'; test('undefined values in context response gives proper default values', async () => { const mockContext = { @@ -49,233 +49,243 @@ test('undefined values in context response gives proper default values', async ( jest.spyOn(api, 'get').mockResolvedValue(mockContext); const response = await user.fetchUserContext(false); + + const acl: Acl = { + accessList: { + list: false, + read: false, + edit: false, + create: false, + remove: false, + }, + accessMonitoringRule: { + list: false, + read: false, + edit: false, + create: false, + remove: false, + }, + authConnectors: { + list: true, + read: true, + edit: true, + create: true, + remove: true, + }, + // Test that undefined acl booleans are set to default false. + trustedClusters: { + list: false, + read: false, + edit: false, + create: false, + remove: false, + }, + nodes: { + create: false, + edit: false, + list: false, + read: false, + remove: false, + }, + plugins: { + create: false, + edit: false, + list: false, + read: false, + remove: false, + }, + integrations: { + list: false, + read: false, + edit: false, + create: false, + remove: false, + use: false, + }, + roles: { + list: false, + read: false, + edit: false, + create: false, + remove: false, + }, + lock: { + list: false, + read: false, + edit: false, + create: false, + remove: false, + }, + recordedSessions: { + list: false, + read: false, + edit: false, + create: false, + remove: false, + }, + desktops: { + create: false, + edit: false, + list: false, + read: false, + remove: false, + }, + events: { + list: false, + read: false, + edit: false, + create: false, + remove: false, + }, + externalAuditStorage: { + list: false, + read: false, + edit: false, + create: false, + remove: false, + }, + users: { + list: false, + read: false, + edit: false, + create: false, + remove: false, + }, + activeSessions: { + create: false, + edit: false, + list: false, + read: false, + remove: false, + }, + appServers: { + list: false, + read: false, + edit: false, + create: false, + remove: false, + }, + kubeServers: { + list: false, + read: false, + edit: false, + create: false, + remove: false, + }, + license: { + list: false, + read: false, + edit: false, + create: false, + remove: false, + }, + download: { + list: false, + read: false, + edit: false, + create: false, + remove: false, + }, + tokens: { + list: false, + read: false, + edit: false, + create: false, + remove: false, + }, + accessRequests: { + list: false, + read: false, + edit: false, + create: false, + remove: false, + }, + billing: { + list: false, + read: false, + edit: false, + create: false, + remove: false, + }, + dbServers: { + list: false, + read: false, + edit: false, + create: false, + remove: false, + }, + db: { + list: false, + read: false, + edit: false, + create: false, + remove: false, + }, + connectionDiagnostic: { + list: false, + read: false, + edit: false, + create: false, + remove: false, + }, + deviceTrust: { + list: false, + read: false, + edit: false, + create: false, + remove: false, + }, + samlIdpServiceProvider: { + list: false, + read: false, + edit: false, + create: false, + remove: false, + }, + auditQuery: { + list: false, + read: false, + edit: false, + create: false, + remove: false, + }, + securityReport: { + list: false, + read: false, + edit: false, + create: false, + remove: false, + }, + accessGraph: { + list: false, + read: false, + edit: false, + create: false, + remove: false, + }, + discoverConfigs: { + list: false, + read: false, + edit: false, + create: false, + remove: false, + }, + bots: { + list: false, + read: false, + edit: false, + create: false, + remove: false, + }, + clipboardSharingEnabled: true, + desktopSessionRecordingEnabled: true, + directorySharingEnabled: true, + }; + expect(response).toEqual({ username: 'foo', authType: 'local', - acl: { - accessList: { - list: false, - read: false, - edit: false, - create: false, - remove: false, - }, - accessMonitoringRule: { - list: false, - read: false, - edit: false, - create: false, - remove: false, - }, - authConnectors: { - list: true, - read: true, - edit: true, - create: true, - remove: true, - }, - // Test that undefined acl booleans are set to default false. - trustedClusters: { - list: false, - read: false, - edit: false, - create: false, - remove: false, - }, - nodes: { - create: false, - edit: false, - list: false, - read: false, - remove: false, - }, - plugins: { - create: false, - edit: false, - list: false, - read: false, - remove: false, - }, - integrations: { - list: false, - read: false, - edit: false, - create: false, - remove: false, - use: false, - }, - roles: { - list: false, - read: false, - edit: false, - create: false, - remove: false, - }, - lock: { - list: false, - read: false, - edit: false, - create: false, - remove: false, - }, - recordedSessions: { - list: false, - read: false, - edit: false, - create: false, - remove: false, - }, - desktops: { - create: false, - edit: false, - list: false, - read: false, - remove: false, - }, - events: { - list: false, - read: false, - edit: false, - create: false, - remove: false, - }, - externalAuditStorage: { - list: false, - read: false, - edit: false, - create: false, - remove: false, - }, - users: { - list: false, - read: false, - edit: false, - create: false, - remove: false, - }, - activeSessions: { - create: false, - edit: false, - list: false, - read: false, - remove: false, - }, - appServers: { - list: false, - read: false, - edit: false, - create: false, - remove: false, - }, - kubeServers: { - list: false, - read: false, - edit: false, - create: false, - remove: false, - }, - license: { - list: false, - read: false, - edit: false, - create: false, - remove: false, - }, - download: { - list: false, - read: false, - edit: false, - create: false, - remove: false, - }, - tokens: { - list: false, - read: false, - edit: false, - create: false, - remove: false, - }, - accessRequests: { - list: false, - read: false, - edit: false, - create: false, - remove: false, - }, - billing: { - list: false, - read: false, - edit: false, - create: false, - remove: false, - }, - dbServers: { - list: false, - read: false, - edit: false, - create: false, - remove: false, - }, - db: { - list: false, - read: false, - edit: false, - create: false, - remove: false, - }, - connectionDiagnostic: { - list: false, - read: false, - edit: false, - create: false, - remove: false, - }, - deviceTrust: { - list: false, - read: false, - edit: false, - create: false, - remove: false, - }, - samlIdpServiceProvider: { - list: false, - read: false, - edit: false, - create: false, - remove: false, - }, - auditQuery: { - list: false, - read: false, - edit: false, - create: false, - remove: false, - }, - securityReport: { - list: false, - read: false, - edit: false, - create: false, - remove: false, - }, - accessGraph: { - list: false, - read: false, - edit: false, - create: false, - remove: false, - }, - bots: { - list: false, - read: false, - edit: false, - create: false, - remove: false, - }, - clipboardSharingEnabled: true, - desktopSessionRecordingEnabled: true, - directorySharingEnabled: true, - }, + acl, cluster: { clusterId: 'aws', lastConnected: new Date('2020-09-26T17:30:23.512Z'), diff --git a/web/packages/teleport/src/stores/storeUserContext.ts b/web/packages/teleport/src/stores/storeUserContext.ts index bc054fa2e3df9..23c075a681607 100644 --- a/web/packages/teleport/src/stores/storeUserContext.ts +++ b/web/packages/teleport/src/stores/storeUserContext.ts @@ -208,6 +208,10 @@ export default class StoreUserContext extends Store { ); } + getDiscoveryConfigAccess() { + return this.state.acl.discoverConfigs; + } + getPluginsAccess() { return this.state.acl.plugins; } diff --git a/web/packages/teleport/src/teleportContext.tsx b/web/packages/teleport/src/teleportContext.tsx index acf5b01ab39c9..535e559d4d0d8 100644 --- a/web/packages/teleport/src/teleportContext.tsx +++ b/web/packages/teleport/src/teleportContext.tsx @@ -181,6 +181,16 @@ class TeleportContext implements types.Context { ); } + function hasAccessGraphIntegrationsAccess() { + return ( + userContext.getIntegrationsAccess().list && + userContext.getIntegrationsAccess().read && + userContext.getPluginsAccess().read && + userContext.getDiscoveryConfigAccess().list && + userContext.getDiscoveryConfigAccess().read + ); + } + return { audit: userContext.getEventAccess().list, recordings: userContext.getSessionsAccess().list, @@ -224,6 +234,7 @@ class TeleportContext implements types.Context { accessMonitoring: hasAccessMonitoringAccess(), managementSection: hasManagementSectionAccess(), accessGraph: userContext.getAccessGraphAccess().list, + accessGraphIntegrations: hasAccessGraphIntegrationsAccess(), tokens: userContext.getTokenAccess().create, externalAuditStorage: userContext.getExternalAuditStorageAccess().list, listBots: userContext.getBotsAccess().list, @@ -264,6 +275,7 @@ export const disabledFeatureFlags: types.FeatureFlags = { managementSection: false, accessMonitoring: false, accessGraph: false, + accessGraphIntegrations: false, externalAuditStorage: false, addBots: false, listBots: false, diff --git a/web/packages/teleport/src/types.ts b/web/packages/teleport/src/types.ts index 2c3620e6d86b7..356dc95027ee1 100644 --- a/web/packages/teleport/src/types.ts +++ b/web/packages/teleport/src/types.ts @@ -81,7 +81,13 @@ export enum NavTitle { // Resources Requests NewRequest = 'New Request', ReviewRequests = 'Review Requests', - AccessGraph = 'Access Graph', + + // Access Graph + AccessGraphDashboard = 'Dashboard', + AccessGraphBrowse = 'Browse', + AccessGraphCrownJewels = 'Crown Jewels', + AccessGraphGraphExplorer = 'Graph Explorer', + AccessGraphSQLEditor = 'SQL Editor', // Activity SessionRecordings = 'Session Recordings', @@ -194,6 +200,7 @@ export interface FeatureFlags { // Whether or not the management section should be available. managementSection: boolean; accessGraph: boolean; + accessGraphIntegrations: boolean; externalAuditStorage: boolean; listBots: boolean; addBots: boolean;