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
Prev Previous commit
Next Next commit
add owner col
  • Loading branch information
Kira-Pilot committed Feb 23, 2023
commit ade9548a62471cb32122fcdb3d968d62c6eec238
20 changes: 18 additions & 2 deletions coderd/apikey.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,11 @@ func (api *API) apiKey(rw http.ResponseWriter, r *http.Request) {
httpapi.Write(ctx, rw, http.StatusOK, convertAPIKey(key))
}

type ConvertedAPIKey struct {
codersdk.APIKey
Username string `json:"username"`
}

// @Summary Get user tokens
// @ID get-user-tokens
// @Security CoderSessionToken
Expand Down Expand Up @@ -216,9 +221,20 @@ func (api *API) tokens(rw http.ResponseWriter, r *http.Request) {
return
}

var apiKeys []codersdk.APIKey
var apiKeys []ConvertedAPIKey
for _, key := range keys {
apiKeys = append(apiKeys, convertAPIKey(key))
user, err := api.Database.GetUserByID(ctx, key.UserID)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should use GetUsersByIDs here instead, otherwise, you could execute hundreds of separate queries if there are hundreds of users.

Generally, we should never query in for loops!

if err != nil {
apiKeys = append(apiKeys, ConvertedAPIKey{
APIKey: convertAPIKey(key),
Username: "",
})
} else {
apiKeys = append(apiKeys, ConvertedAPIKey{
APIKey: convertAPIKey(key),
Username: user.Username,
})
}
}

httpapi.Write(ctx, rw, http.StatusOK, apiKeys)
Expand Down
3 changes: 2 additions & 1 deletion site/src/i18n/en/tokensPage.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"id": "ID",
"createdAt": "Created At",
"lastUsed": "Last Used",
"expiresAt": "Expires At"
"expiresAt": "Expires At",
"owner": "Owner"
}
}
1 change: 1 addition & 0 deletions site/src/pages/UserSettingsPage/TokensPage/TokensPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ export const TokensPage: FC<PropsWithChildren<unknown>> = () => {
/>
<TokensPageView
tokens={tokens}
viewAllTokens={viewAllTokens}
isLoading={isFetching}
hasLoaded={isFetched}
getTokensError={getTokensError}
Expand Down
27 changes: 22 additions & 5 deletions site/src/pages/UserSettingsPage/TokensPage/TokensPageView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,13 @@ const lastUsedOrNever = (lastUsed: string) => {
return now.isBefore(t.add(100, "year")) ? t.fromNow() : "Never"
}

interface ConvertedAPIKey extends APIKey {
username: string
}

export interface TokensPageViewProps {
tokens?: APIKey[]
tokens?: ConvertedAPIKey[]
viewAllTokens: boolean
getTokensError?: Error | unknown
isLoading: boolean
hasLoaded: boolean
Expand All @@ -36,6 +41,7 @@ export const TokensPageView: FC<
React.PropsWithChildren<TokensPageViewProps>
> = ({
tokens,
viewAllTokens,
getTokensError,
isLoading,
hasLoaded,
Expand All @@ -44,6 +50,7 @@ export const TokensPageView: FC<
}) => {
const theme = useTheme()
const { t } = useTranslation("tokensPage")
const colWidth = viewAllTokens ? "20%" : "25%"

return (
<Stack>
Expand All @@ -57,10 +64,13 @@ export const TokensPageView: FC<
<Table>
<TableHead>
<TableRow>
<TableCell width="25%">{t("table.id")}</TableCell>
<TableCell width="25%">{t("table.createdAt")}</TableCell>
<TableCell width="25%">{t("table.lastUsed")}</TableCell>
<TableCell width="25%">{t("table.expiresAt")}</TableCell>
<TableCell width={colWidth}>{t("table.id")}</TableCell>
<TableCell width={colWidth}>{t("table.createdAt")}</TableCell>
<TableCell width={colWidth}>{t("table.lastUsed")}</TableCell>
<TableCell width={colWidth}>{t("table.expiresAt")}</TableCell>
{viewAllTokens && (
<TableCell width="20%">{t("table.owner")}</TableCell>
)}
<TableCell width="0%"></TableCell>
</TableRow>
</TableHead>
Expand Down Expand Up @@ -102,6 +112,13 @@ export const TokensPageView: FC<
{dayjs(token.expires_at).fromNow()}
</span>
</TableCell>
{viewAllTokens && (
<TableCell>
<span style={{ color: theme.palette.text.secondary }}>
{token.username}
</span>
</TableCell>
)}
<TableCell>
<span style={{ color: theme.palette.text.secondary }}>
<IconButton
Expand Down
2 changes: 1 addition & 1 deletion site/src/pages/UserSettingsPage/TokensPage/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ 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
// 'View All' switch on the TokensPage.
export const useCheckTokenPermissions = () => {
const queryKey = ["auth"]
const params = {
Expand Down