-
Notifications
You must be signed in to change notification settings - Fork 367
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: [M3-7529] β Support VPC in Personal Access Token drawer #10024
Changes from 7 commits
1ce7027
f6a06b6
9d42a01
7d4a5bb
1fec282
4c46984
e3eaa66
cf80e18
2f09ba1
576cd97
286c6d9
40c81d0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"@linode/manager": Upcoming Features | ||
--- | ||
|
||
Support VPC in Access Token drawers ([#10024](https://github.com/linode/manager/pull/10024)) |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,10 +16,13 @@ import { TableRow } from 'src/components/TableRow'; | |
import { TextField } from 'src/components/TextField'; | ||
import { ISO_DATETIME_NO_TZ_FORMAT } from 'src/constants'; | ||
import { AccessCell } from 'src/features/ObjectStorage/AccessKeyLanding/AccessCell'; | ||
import { VPC_READ_ONLY_TOOLTIP } from 'src/features/VPCs/constants'; | ||
import { useFlags } from 'src/hooks/useFlags'; | ||
import { useAccount } from 'src/queries/account'; | ||
import { useAccountUser } from 'src/queries/accountUsers'; | ||
import { useProfile } from 'src/queries/profile'; | ||
import { useCreatePersonalAccessTokenMutation } from 'src/queries/tokens'; | ||
import { isFeatureEnabled } from 'src/utilities/accountCapabilities'; | ||
import { getErrorMap } from 'src/utilities/errorUtils'; | ||
|
||
import { | ||
|
@@ -29,9 +32,9 @@ import { | |
StyledSelectCell, | ||
} from './APITokenDrawer.styles'; | ||
import { | ||
basePermNameMap as _basePermNameMap, | ||
Permission, | ||
allScopesAreTheSame, | ||
basePermNameMap, | ||
permTuplesToScopeString, | ||
scopeStringToPermTuples, | ||
} from './utils'; | ||
|
@@ -94,6 +97,7 @@ export const CreateAPITokenDrawer = (props: Props) => { | |
}; | ||
|
||
const { data: profile } = useProfile(); | ||
const { data: account } = useAccount(); | ||
const { data: user } = useAccountUser(profile?.username ?? ''); | ||
|
||
const { | ||
|
@@ -102,6 +106,16 @@ export const CreateAPITokenDrawer = (props: Props) => { | |
mutateAsync: createPersonalAccessToken, | ||
} = useCreatePersonalAccessTokenMutation(); | ||
|
||
const [basePermNameMap, setBasePermNameMap] = React.useState( | ||
_basePermNameMap | ||
); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Rather than having state for this, could we derive the value? Would it work if we had something like const basePermNameMap = getPermsMap(flags.vpc ? [] : ['vpc']); There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It can be derived. Avoiding the edge case I referenced previously would require having So we could do a simplified approach like
where the VPC perm would get removed if |
||
|
||
const showVPCs = isFeatureEnabled( | ||
'VPCs', | ||
Boolean(flags.vpc), | ||
account?.capabilities ?? [] | ||
); | ||
|
||
const form = useFormik<{ | ||
expiry: string; | ||
label: string; | ||
|
@@ -122,8 +136,19 @@ export const CreateAPITokenDrawer = (props: Props) => { | |
React.useEffect(() => { | ||
if (open) { | ||
form.resetForm({ values: initialValues }); | ||
|
||
// If VPCs should not be shown, do not display the VPC option | ||
if (!showVPCs) { | ||
const basePermNameMapCopy = Object.assign({}, basePermNameMap); | ||
delete basePermNameMapCopy.vpc; | ||
setBasePermNameMap(basePermNameMapCopy); | ||
} | ||
} | ||
}, [open]); | ||
|
||
return () => { | ||
setBasePermNameMap(basePermNameMap); | ||
}; | ||
dwiley-akamai marked this conversation as resolved.
Show resolved
Hide resolved
|
||
}, [open, showVPCs]); | ||
|
||
const handleScopeChange = (e: React.SyntheticEvent<RadioButton>): void => { | ||
const newScopes = form.values.scopes; | ||
|
@@ -258,6 +283,9 @@ export const CreateAPITokenDrawer = (props: Props) => { | |
if (!basePermNameMap[scopeTup[0]]) { | ||
return null; | ||
} | ||
|
||
const scopeIsForVPC = scopeTup[0] === 'vpc'; | ||
|
||
return ( | ||
<TableRow | ||
data-qa-row={basePermNameMap[scopeTup[0]]} | ||
|
@@ -281,8 +309,11 @@ export const CreateAPITokenDrawer = (props: Props) => { | |
parentColumn="Read Only" | ||
> | ||
<AccessCell | ||
tooltipText={ | ||
scopeIsForVPC ? VPC_READ_ONLY_TOOLTIP : undefined | ||
} | ||
active={scopeTup[1] === 1} | ||
disabled={false} | ||
disabled={scopeIsForVPC} // "Read Only" is not a valid scope for VPC | ||
onChange={handleScopeChange} | ||
scope="1" | ||
scopeDisplay={scopeTup[0]} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,15 +8,20 @@ import { TableHead } from 'src/components/TableHead'; | |
import { TableRow } from 'src/components/TableRow'; | ||
import { AccessCell } from 'src/features/ObjectStorage/AccessKeyLanding/AccessCell'; | ||
import { useFlags } from 'src/hooks/useFlags'; | ||
import { useAccount } from 'src/queries/account'; | ||
import { useAccountUser } from 'src/queries/accountUsers'; | ||
import { useProfile } from 'src/queries/profile'; | ||
import { isFeatureEnabled } from 'src/utilities/accountCapabilities'; | ||
|
||
import { | ||
StyledAccessCell, | ||
StyledPermissionsCell, | ||
StyledPermsTable, | ||
} from './APITokenDrawer.styles'; | ||
import { basePermNameMap, scopeStringToPermTuples } from './utils'; | ||
import { | ||
basePermNameMap as _basePermNameMap, | ||
scopeStringToPermTuples, | ||
} from './utils'; | ||
|
||
interface Props { | ||
onClose: () => void; | ||
|
@@ -30,8 +35,32 @@ export const ViewAPITokenDrawer = (props: Props) => { | |
const flags = useFlags(); | ||
|
||
const { data: profile } = useProfile(); | ||
const { data: account } = useAccount(); | ||
const { data: user } = useAccountUser(profile?.username ?? ''); | ||
|
||
const [basePermNameMap, setBasePermNameMap] = React.useState( | ||
_basePermNameMap | ||
); | ||
|
||
const showVPCs = isFeatureEnabled( | ||
'VPCs', | ||
Boolean(flags.vpc), | ||
account?.capabilities ?? [] | ||
); | ||
|
||
React.useEffect(() => { | ||
if (open && !showVPCs) { | ||
// If VPCs should not be shown, do not display the VPC scope | ||
const basePermNameMapCopy = Object.assign({}, basePermNameMap); | ||
delete basePermNameMapCopy.vpc; | ||
setBasePermNameMap(basePermNameMapCopy); | ||
} | ||
|
||
return () => { | ||
setBasePermNameMap(basePermNameMap); | ||
}; | ||
}, [open, showVPCs]); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We actually took a slightly different approach which I'm interested in hearing your thoughts. We actually removed them from the list of perms until it no longer needs to be feature flagged: https://github.com/linode/manager/pull/10040/files There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I noticed that and gave that approach a try earlier in the week, commenting out
It resulted in some weird behavior though where the scope for VPC doesn't appear until another scope is clicked on: Screen.Recording.2024-01-11.at.1.05.10.PM.movSince GA isn't far off and because API is returning |
||
|
||
const allPermissions = scopeStringToPermTuples(token?.scopes ?? ''); | ||
|
||
// Filter permissions for all users except parent user accounts. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By default, tooltips do not activate on disabled elements. The workaround for this is to add a wrapper such as a
<span>
. More details here.