From 64e87f3c1993b72cb34f91ec87b1177bf57c1d1a Mon Sep 17 00:00:00 2001 From: coliu-akamai Date: Tue, 22 Aug 2023 16:08:08 -0400 Subject: [PATCH 1/9] add vpc grant and permissions --- packages/api-v4/src/account/types.ts | 9 ++++-- packages/manager/src/factories/grants.ts | 18 +++++++++++ .../src/features/Users/UserPermissions.tsx | 4 +++ .../Users/UserPermissionsEntitySection.tsx | 1 + .../src/features/VPC/VPCCreate/VPCCreate.tsx | 1 + .../features/VPC/VPCLanding/VPCEditDrawer.tsx | 18 ++++++++++- packages/manager/src/features/VPC/index.tsx | 32 ++++++++++++++----- 7 files changed, 71 insertions(+), 12 deletions(-) diff --git a/packages/api-v4/src/account/types.ts b/packages/api-v4/src/account/types.ts index 6dbba2df579..bdf78e9fdad 100644 --- a/packages/api-v4/src/account/types.ts +++ b/packages/api-v4/src/account/types.ts @@ -45,7 +45,8 @@ export type AccountCapability = | 'Vlans' | 'Machine Images' | 'LKE HA Control Planes' - | 'Managed Databases'; + | 'Managed Databases' + | 'VPCs'; export interface AccountSettings { managed: boolean; @@ -147,7 +148,8 @@ export type GlobalGrantTypes = | 'add_nodebalancers' | 'add_images' | 'add_volumes' - | 'add_firewalls'; + | 'add_firewalls' + | 'add_vpcs'; export interface GlobalGrants { global: Record; @@ -162,7 +164,8 @@ export type GrantType = | 'stackscript' | 'volume' | 'database' - | 'firewall'; + | 'firewall' + | 'vpc'; export type Grants = GlobalGrants & Record; diff --git a/packages/manager/src/factories/grants.ts b/packages/manager/src/factories/grants.ts index 623ff53325c..c7851989f12 100644 --- a/packages/manager/src/factories/grants.ts +++ b/packages/manager/src/factories/grants.ts @@ -39,6 +39,7 @@ export const grantsFactory = Factory.Sync.makeFactory({ add_nodebalancers: true, add_stackscripts: true, add_volumes: true, + add_vpcs: true, cancel_account: false, longview_subscription: true, }, @@ -84,4 +85,21 @@ export const grantsFactory = Factory.Sync.makeFactory({ permissions: 'read_only', }, ], + vpc: [ + { + id: 123, + label: 'example-entity1', + permissions: 'read_only', + }, + { + id: 124, + label: 'example-entity2', + permissions: 'read_write', + }, + { + id: 125, + label: 'example-entity3', + permissions: null, + }, + ], }); diff --git a/packages/manager/src/features/Users/UserPermissions.tsx b/packages/manager/src/features/Users/UserPermissions.tsx index 7f5b5ee94a7..dc832b310ee 100644 --- a/packages/manager/src/features/Users/UserPermissions.tsx +++ b/packages/manager/src/features/Users/UserPermissions.tsx @@ -201,6 +201,7 @@ class UserPermissions extends React.Component { 'domain', 'longview', 'database', + 'vpc', ]; entitySetAllTo = (entity: GrantType, value: GrantLevel) => () => { @@ -283,6 +284,7 @@ class UserPermissions extends React.Component { 'add_volumes', 'add_firewalls', 'add_databases', + 'add_vpcs', 'cancel_account', ]; @@ -460,6 +462,8 @@ class UserPermissions extends React.Component { add_nodebalancers: 'Can add NodeBalancers to this account ($)', add_stackscripts: 'Can create StackScripts under this account', add_volumes: 'Can add Block Storage Volumes to this account ($)', + // VPC beta is currently no charge but will show up on invoice, so including the ($) + add_vpcs: 'Can add VPCs to this account ($)', cancel_account: 'Can cancel the entire account', longview_subscription: 'Can modify this account\u{2019}s Longview subscription ($)', diff --git a/packages/manager/src/features/Users/UserPermissionsEntitySection.tsx b/packages/manager/src/features/Users/UserPermissionsEntitySection.tsx index 066f1da99af..e869aaa3df2 100644 --- a/packages/manager/src/features/Users/UserPermissionsEntitySection.tsx +++ b/packages/manager/src/features/Users/UserPermissionsEntitySection.tsx @@ -23,6 +23,7 @@ export const entityNameMap: Record = { longview: 'Longview Clients', firewall: 'Firewalls', database: 'Databases', + vpc: 'VPCs', }; interface Props { diff --git a/packages/manager/src/features/VPC/VPCCreate/VPCCreate.tsx b/packages/manager/src/features/VPC/VPCCreate/VPCCreate.tsx index 701cabf2bf1..d92e13b70e1 100644 --- a/packages/manager/src/features/VPC/VPCCreate/VPCCreate.tsx +++ b/packages/manager/src/features/VPC/VPCCreate/VPCCreate.tsx @@ -1,6 +1,7 @@ import * as React from 'react'; import { DocumentTitleSegment } from 'src/components/DocumentTitle'; +// note: creating vpc permissions for this page handled in M3-6757 const VPCCreate = () => { return ( <> diff --git a/packages/manager/src/features/VPC/VPCLanding/VPCEditDrawer.tsx b/packages/manager/src/features/VPC/VPCLanding/VPCEditDrawer.tsx index 807c2b6adde..c888b3f6c4f 100644 --- a/packages/manager/src/features/VPC/VPCLanding/VPCEditDrawer.tsx +++ b/packages/manager/src/features/VPC/VPCLanding/VPCEditDrawer.tsx @@ -7,6 +7,7 @@ import { Drawer } from 'src/components/Drawer'; import { RegionSelect } from 'src/components/EnhancedSelect/variants/RegionSelect'; import { Notice } from 'src/components/Notice/Notice'; import { TextField } from 'src/components/TextField'; +import { useGrants, useProfile } from 'src/queries/profile'; import { useRegionsQuery } from 'src/queries/regions'; import { useUpdateVPCMutation } from 'src/queries/vpcs'; import { getErrorMap } from 'src/utilities/errorUtils'; @@ -22,6 +23,12 @@ const REGION_HELPER_TEXT = 'Region cannot be changed during beta.'; export const VPCEditDrawer = (props: Props) => { const { onClose, open, vpc } = props; + const { data: profile } = useProfile(); + const { data: grants } = useGrants(); + + const vpcPermissions = grants?.vpc.find((v) => v.id === vpc?.id); + const readOnly = Boolean(profile?.restricted) && vpcPermissions?.permissions === 'read_only'; + const { error, isLoading, @@ -55,6 +62,13 @@ export const VPCEditDrawer = (props: Props) => { return ( {errorMap.none && } + {readOnly && ( + + )}
{ name="label" onChange={form.handleChange} value={form.values.label} + disabled={readOnly} /> { onChange={form.handleChange} rows={1} value={form.values.description} + disabled={readOnly} /> {regionsData && ( { import('./VPCCreate/VPCCreate')); const VPCDetail = React.lazy(() => import('./VPCDetail/VPCDetail')); const VPCLanding = React.lazy(() => import('./VPCLanding/VPCLanding')); const VPC = () => { + const flags = useFlags(); + const { data: account } = useAccount(); + + const showVPCs = isFeatureEnabled( + 'VPCs', + Boolean(flags.vpc), + account?.capabilities ?? [] + ); + return ( - }> - - - - - - - + <> + {showVPCs ? + }> + + + + + + + + : null} + ); }; From c3251e634c27607969bd8f8b38a603f209a5dfdf Mon Sep 17 00:00:00 2001 From: coliu-akamai Date: Tue, 22 Aug 2023 16:28:41 -0400 Subject: [PATCH 2/9] yarn changeset --- packages/api-v4/.changeset/pr-9585-changed-1692736077405.md | 5 +++++ .../.changeset/pr-9585-upcoming-features-1692736112038.md | 5 +++++ 2 files changed, 10 insertions(+) create mode 100644 packages/api-v4/.changeset/pr-9585-changed-1692736077405.md create mode 100644 packages/manager/.changeset/pr-9585-upcoming-features-1692736112038.md diff --git a/packages/api-v4/.changeset/pr-9585-changed-1692736077405.md b/packages/api-v4/.changeset/pr-9585-changed-1692736077405.md new file mode 100644 index 00000000000..0efc4189fdf --- /dev/null +++ b/packages/api-v4/.changeset/pr-9585-changed-1692736077405.md @@ -0,0 +1,5 @@ +--- +"@linode/api-v4": Changed +--- + +Change `Account` and `Grant` related types to include VPC related grants and capabilities ([#9585](https://github.com/linode/manager/pull/9585)) diff --git a/packages/manager/.changeset/pr-9585-upcoming-features-1692736112038.md b/packages/manager/.changeset/pr-9585-upcoming-features-1692736112038.md new file mode 100644 index 00000000000..743819b935d --- /dev/null +++ b/packages/manager/.changeset/pr-9585-upcoming-features-1692736112038.md @@ -0,0 +1,5 @@ +--- +"@linode/manager": Upcoming Features +--- + +Add VPC related permissions, capabilities, and grants ([#9585](https://github.com/linode/manager/pull/9585)) From cd123857f1470be64c668ca58c43236587517943 Mon Sep 17 00:00:00 2001 From: Connie Liu <139280159+coliu-akamai@users.noreply.github.com> Date: Wed, 23 Aug 2023 14:20:06 -0400 Subject: [PATCH 3/9] Update packages/api-v4/.changeset/pr-9585-changed-1692736077405.md Co-authored-by: Dajahi Wiley <114682940+dwiley-akamai@users.noreply.github.com> --- packages/api-v4/.changeset/pr-9585-changed-1692736077405.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/api-v4/.changeset/pr-9585-changed-1692736077405.md b/packages/api-v4/.changeset/pr-9585-changed-1692736077405.md index 0efc4189fdf..39906f378ef 100644 --- a/packages/api-v4/.changeset/pr-9585-changed-1692736077405.md +++ b/packages/api-v4/.changeset/pr-9585-changed-1692736077405.md @@ -2,4 +2,4 @@ "@linode/api-v4": Changed --- -Change `Account` and `Grant` related types to include VPC related grants and capabilities ([#9585](https://github.com/linode/manager/pull/9585)) +Change `Account` and `Grant`-related types to include VPC-related grants and capabilities ([#9585](https://github.com/linode/manager/pull/9585)) From 985443424058674ea854e3b1d8b4be842253b38b Mon Sep 17 00:00:00 2001 From: Connie Liu <139280159+coliu-akamai@users.noreply.github.com> Date: Wed, 23 Aug 2023 14:20:14 -0400 Subject: [PATCH 4/9] Update packages/manager/.changeset/pr-9585-upcoming-features-1692736112038.md Co-authored-by: Dajahi Wiley <114682940+dwiley-akamai@users.noreply.github.com> --- .../.changeset/pr-9585-upcoming-features-1692736112038.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/manager/.changeset/pr-9585-upcoming-features-1692736112038.md b/packages/manager/.changeset/pr-9585-upcoming-features-1692736112038.md index 743819b935d..e3a84848592 100644 --- a/packages/manager/.changeset/pr-9585-upcoming-features-1692736112038.md +++ b/packages/manager/.changeset/pr-9585-upcoming-features-1692736112038.md @@ -2,4 +2,4 @@ "@linode/manager": Upcoming Features --- -Add VPC related permissions, capabilities, and grants ([#9585](https://github.com/linode/manager/pull/9585)) +Add VPC-related permissions, capabilities, and grants ([#9585](https://github.com/linode/manager/pull/9585)) From e9735669c2ab9f4fb2f3378ab10c6d666bd2d471 Mon Sep 17 00:00:00 2001 From: coliu-akamai Date: Wed, 23 Aug 2023 14:57:06 -0400 Subject: [PATCH 5/9] fix unresolved merge conflict issues --- packages/manager/src/factories/grants.ts | 1 - packages/manager/src/features/VPC/VPCCreate/VPCCreate.tsx | 1 - 2 files changed, 2 deletions(-) diff --git a/packages/manager/src/factories/grants.ts b/packages/manager/src/factories/grants.ts index ad942450879..c7851989f12 100644 --- a/packages/manager/src/factories/grants.ts +++ b/packages/manager/src/factories/grants.ts @@ -42,7 +42,6 @@ export const grantsFactory = Factory.Sync.makeFactory({ add_vpcs: true, cancel_account: false, longview_subscription: true, - add_vpcs: true, }, image: [ { diff --git a/packages/manager/src/features/VPC/VPCCreate/VPCCreate.tsx b/packages/manager/src/features/VPC/VPCCreate/VPCCreate.tsx index 365f0d91e7b..009ae3d61cf 100644 --- a/packages/manager/src/features/VPC/VPCCreate/VPCCreate.tsx +++ b/packages/manager/src/features/VPC/VPCCreate/VPCCreate.tsx @@ -35,7 +35,6 @@ import { StyledHeaderTypography, } from './VPCCreate.styles'; -// note: creating vpc permissions for this page handled in M3-6757 const VPCCreate = () => { const theme = useTheme(); const history = useHistory(); From da7f8fba90cfcffced0f6e15fcaec7b5d7f9b247 Mon Sep 17 00:00:00 2001 From: coliu-akamai Date: Wed, 23 Aug 2023 15:04:08 -0400 Subject: [PATCH 6/9] update vpc global grant text --- packages/manager/src/features/Users/UserPermissions.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/manager/src/features/Users/UserPermissions.tsx b/packages/manager/src/features/Users/UserPermissions.tsx index dc832b310ee..6b65965cbb8 100644 --- a/packages/manager/src/features/Users/UserPermissions.tsx +++ b/packages/manager/src/features/Users/UserPermissions.tsx @@ -462,8 +462,7 @@ class UserPermissions extends React.Component { add_nodebalancers: 'Can add NodeBalancers to this account ($)', add_stackscripts: 'Can create StackScripts under this account', add_volumes: 'Can add Block Storage Volumes to this account ($)', - // VPC beta is currently no charge but will show up on invoice, so including the ($) - add_vpcs: 'Can add VPCs to this account ($)', + add_vpcs: 'Can add VPCs to this account', cancel_account: 'Can cancel the entire account', longview_subscription: 'Can modify this account\u{2019}s Longview subscription ($)', From 6cba1a81dd3e74643f7a066c2b09983c85b58887 Mon Sep 17 00:00:00 2001 From: coliu-akamai Date: Fri, 25 Aug 2023 14:36:44 -0400 Subject: [PATCH 7/9] add missing files --- packages/manager/src/MainContent.tsx | 10 +++++++++- .../manager/src/components/PrimaryNav/PrimaryNav.tsx | 12 +++++++++--- .../src/features/TopMenu/AddNewMenu/AddNewMenu.tsx | 11 ++++++++++- 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/packages/manager/src/MainContent.tsx b/packages/manager/src/MainContent.tsx index 1edd9b94104..4a975ae2a18 100644 --- a/packages/manager/src/MainContent.tsx +++ b/packages/manager/src/MainContent.tsx @@ -203,6 +203,12 @@ const MainContent = (props: CombinedProps) => { account?.capabilities ?? [] ); + const showVPCs = isFeatureEnabled( + 'VPCs', + Boolean(flags.vpc), + account?.capabilities ?? [] + ); + const defaultRoot = _isManagedAccount ? '/managed' : '/linodes'; const shouldDisplayMainContentBanner = @@ -358,7 +364,9 @@ const MainContent = (props: CombinedProps) => { {flags.selfServeBetas ? ( ) : null} - {flags.vpc && } + {showVPCs ? ( + + ) : null} {/** We don't want to break any bookmarks. This can probably be removed eventually. */} diff --git a/packages/manager/src/components/PrimaryNav/PrimaryNav.tsx b/packages/manager/src/components/PrimaryNav/PrimaryNav.tsx index 160aa6a8d02..96424e22f71 100644 --- a/packages/manager/src/components/PrimaryNav/PrimaryNav.tsx +++ b/packages/manager/src/components/PrimaryNav/PrimaryNav.tsx @@ -3,6 +3,7 @@ import * as React from 'react'; import { Link, LinkProps, useLocation } from 'react-router-dom'; import Account from 'src/assets/icons/account.svg'; +import Beta from 'src/assets/icons/entityIcons/beta.svg'; import Storage from 'src/assets/icons/entityIcons/bucket.svg'; import Database from 'src/assets/icons/entityIcons/database.svg'; import Domain from 'src/assets/icons/entityIcons/domain.svg'; @@ -18,7 +19,6 @@ import Volume from 'src/assets/icons/entityIcons/volume.svg'; import VPC from 'src/assets/icons/entityIcons/vpc.svg'; import TooltipIcon from 'src/assets/icons/get_help.svg'; import Longview from 'src/assets/icons/longview.svg'; -import Beta from 'src/assets/icons/entityIcons/beta.svg'; import AkamaiLogo from 'src/assets/logo/akamai-logo.svg'; import { BetaChip } from 'src/components/BetaChip/BetaChip'; import { Divider } from 'src/components/Divider'; @@ -127,6 +127,12 @@ export const PrimaryNav = (props: Props) => { account?.capabilities ?? [] ); + const showVPCs = isFeatureEnabled( + 'VPCs', + Boolean(flags.vpc), + account?.capabilities ?? [] + ); + const prefetchObjectStorage = () => { if (!enableObjectPrefetch) { setEnableObjectPrefetch(true); @@ -177,7 +183,7 @@ export const PrimaryNav = (props: Props) => { }, { display: 'VPC', - hide: !flags.vpc, + hide: !showVPCs, href: '/vpc', icon: , isBeta: true, @@ -273,7 +279,7 @@ export const PrimaryNav = (props: Props) => { allowMarketplacePrefetch, flags.databaseBeta, flags.aglb, - flags.vpc, + showVPCs, ] ); diff --git a/packages/manager/src/features/TopMenu/AddNewMenu/AddNewMenu.tsx b/packages/manager/src/features/TopMenu/AddNewMenu/AddNewMenu.tsx index 47d96b14136..2e34d7ef36b 100644 --- a/packages/manager/src/features/TopMenu/AddNewMenu/AddNewMenu.tsx +++ b/packages/manager/src/features/TopMenu/AddNewMenu/AddNewMenu.tsx @@ -25,6 +25,8 @@ import VPCIcon from 'src/assets/icons/entityIcons/vpc.svg'; import { Button } from 'src/components/Button/Button'; import { Divider } from 'src/components/Divider'; import { useFlags } from 'src/hooks/useFlags'; +import { useAccount } from 'src/queries/account'; +import { isFeatureEnabled } from 'src/utilities/accountCapabilities'; interface LinkProps { attr?: { [key: string]: boolean }; @@ -37,10 +39,17 @@ interface LinkProps { export const AddNewMenu = () => { const theme = useTheme(); + const { data: account } = useAccount(); const [anchorEl, setAnchorEl] = React.useState(null); const flags = useFlags(); const open = Boolean(anchorEl); + const showVPCs = isFeatureEnabled( + 'VPCs', + Boolean(flags.vpc), + account?.capabilities ?? [] + ); + const handleClick = (event: React.MouseEvent) => { setAnchorEl(event.currentTarget); }; @@ -80,7 +89,7 @@ export const AddNewMenu = () => { { description: 'Create a private and isolated network', entity: 'VPC', - hide: !flags.vpc, + hide: !showVPCs, icon: VPCIcon, link: '/vpc/create', }, From 64df7007e1a0a49ccbc42835d94d493d38c7fb8a Mon Sep 17 00:00:00 2001 From: Connie Liu <139280159+coliu-akamai@users.noreply.github.com> Date: Mon, 28 Aug 2023 12:38:45 -0400 Subject: [PATCH 8/9] Update packages/manager/src/features/VPC/VPCLanding/VPCEditDrawer.tsx Co-authored-by: Dajahi Wiley <114682940+dwiley-akamai@users.noreply.github.com> --- packages/manager/src/features/VPC/VPCLanding/VPCEditDrawer.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/manager/src/features/VPC/VPCLanding/VPCEditDrawer.tsx b/packages/manager/src/features/VPC/VPCLanding/VPCEditDrawer.tsx index c99e36e13fd..16a9d0214a0 100644 --- a/packages/manager/src/features/VPC/VPCLanding/VPCEditDrawer.tsx +++ b/packages/manager/src/features/VPC/VPCLanding/VPCEditDrawer.tsx @@ -28,7 +28,7 @@ export const VPCEditDrawer = (props: Props) => { const vpcPermissions = grants?.vpc.find((v) => v.id === vpc?.id); const readOnly = - Boolean(profile?.restricted) && vpcPermissions?.permissions === 'read_only'; + Boolean(profile?.restricted) && (vpcPermissions?.permissions === 'read_only' || grants?.vpc.length === 0); const { error, From f2cd240d129baf320c58c55115c5bb8b0ac12345 Mon Sep 17 00:00:00 2001 From: coliu-akamai Date: Mon, 28 Aug 2023 12:47:51 -0400 Subject: [PATCH 9/9] add comment to explain VPC permissions --- .../manager/src/features/VPC/VPCLanding/VPCEditDrawer.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/manager/src/features/VPC/VPCLanding/VPCEditDrawer.tsx b/packages/manager/src/features/VPC/VPCLanding/VPCEditDrawer.tsx index 16a9d0214a0..140b2199951 100644 --- a/packages/manager/src/features/VPC/VPCLanding/VPCEditDrawer.tsx +++ b/packages/manager/src/features/VPC/VPCLanding/VPCEditDrawer.tsx @@ -27,8 +27,12 @@ export const VPCEditDrawer = (props: Props) => { const { data: grants } = useGrants(); const vpcPermissions = grants?.vpc.find((v) => v.id === vpc?.id); + + // there isn't a 'view VPC/Subnet' grant that does anything, so all VPCs get returned even for restricted users + // with permissions set to 'None'. Therefore, we're treating those as read_only as well const readOnly = - Boolean(profile?.restricted) && (vpcPermissions?.permissions === 'read_only' || grants?.vpc.length === 0); + Boolean(profile?.restricted) && + (vpcPermissions?.permissions === 'read_only' || grants?.vpc.length === 0); const { error,