Skip to content

feat: add 'Show all tokens' toggle for owners #6325

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

Merged
merged 12 commits into from
Mar 1, 2023
Next Next commit
add tokens switch
  • Loading branch information
Kira-Pilot committed Feb 23, 2023
commit 2a103b3209b31cbf4065ea546147e3e084104240
36 changes: 34 additions & 2 deletions site/src/pages/UserSettingsPage/TokensPage/TokensPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,25 @@ import { ConfirmDialog } from "components/Dialogs/ConfirmDialog/ConfirmDialog"
import { Typography } from "components/Typography/Typography"
import makeStyles from "@material-ui/core/styles/makeStyles"
import { useTranslation } from "react-i18next"
import { useTokensData, useDeleteToken } from "./hooks"
import {
useTokensData,
useDeleteToken,
useCheckTokenPermissions,
} from "./hooks"
import { displaySuccess, displayError } from "components/GlobalSnackbar/utils"
import { getErrorMessage } from "api/errors"
import Switch from "@material-ui/core/Switch"
import FormGroup from "@material-ui/core/FormGroup"
import FormControlLabel from "@material-ui/core/FormControlLabel"

export const TokensPage: FC<PropsWithChildren<unknown>> = () => {
const styles = useStyles()
const { t } = useTranslation("tokensPage")
const [tokenIdToDelete, setTokenIdToDelete] = useState<string | undefined>(
undefined,
)
const [viewAllTokens, setViewAllTokens] = useState<boolean>(false)
const { data: perms } = useCheckTokenPermissions()

const {
data: tokens,
Expand All @@ -23,7 +32,7 @@ export const TokensPage: FC<PropsWithChildren<unknown>> = () => {
isFetched,
queryKey,
} = useTokensData({
include_all: true,
include_all: viewAllTokens,
})

const { mutate: deleteToken, isLoading: isDeleting } =
Expand Down Expand Up @@ -59,6 +68,22 @@ export const TokensPage: FC<PropsWithChildren<unknown>> = () => {
return (
<>
<Section title={t("title")} description={description} layout="fluid">
<FormGroup row className={styles.formRow}>
{perms?.readAllApiKeys && (
<FormControlLabel
control={
<Switch
className={styles.selectAllSwitch}
checked={viewAllTokens}
onChange={() => setViewAllTokens(!viewAllTokens)}
name="viewAllTokens"
color="primary"
/>
}
label={t("toggleLabel")}
/>
)}
</FormGroup>
<TokensPageView
tokens={tokens}
isLoading={isFetching}
Expand Down Expand Up @@ -104,6 +129,13 @@ const useStyles = makeStyles((theme) => ({
justifyContent: "end",
marginBottom: "10px",
},
selectAllSwitch: {
// decrease the hover state on the switch
// so that it isn't hidden behind the container
"& .MuiIconButton-root": {
padding: "8px",
},
},
}))

export default TokensPage
30 changes: 29 additions & 1 deletion site/src/pages/UserSettingsPage/TokensPage/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,36 @@ import {
useQueryClient,
QueryKey,
} from "@tanstack/react-query"
import { getTokens, deleteAPIKey } from "api/api"
import { getTokens, deleteAPIKey, checkAuthorization } from "api/api"
import { TokensFilter } from "api/typesGenerated"

// Owners have the ability to read all API tokens,
// whereas members can only see the tokens they have created.
// We check permissions here to determine whether to display the
// 'View All' switch on the TokensPage
export const useCheckTokenPermissions = () => {
const queryKey = ["auth"]
const params = {
checks: {
readAllApiKeys: {
object: {
resource_type: "api_key",
},
action: "read",
},
},
}
const result = useQuery({
queryKey,
queryFn: () => checkAuthorization(params),
})

return {
...result,
}
}

// Load all tokens
export const useTokensData = ({ include_all }: TokensFilter) => {
const queryKey = ["tokens", include_all]
const result = useQuery({
Expand All @@ -23,6 +50,7 @@ export const useTokensData = ({ include_all }: TokensFilter) => {
}
}

// Delete a token
export const useDeleteToken = (queryKey: QueryKey) => {
const queryClient = useQueryClient()

Expand Down