diff --git a/apps/studio/components/interfaces/APIKeys/APIKeyRow.tsx b/apps/studio/components/interfaces/APIKeys/APIKeyRow.tsx index 2800dcda2d8..1a0eaa02a9e 100644 --- a/apps/studio/components/interfaces/APIKeys/APIKeyRow.tsx +++ b/apps/studio/components/interfaces/APIKeys/APIKeyRow.tsx @@ -1,5 +1,6 @@ -import { MoreVertical } from 'lucide-react' +import { APIKeysData } from 'data/api-keys/api-keys-query' import { motion } from 'framer-motion' +import { MoreVertical } from 'lucide-react' import { Button, DropdownMenu, @@ -10,7 +11,6 @@ import { } from 'ui' import { APIKeyDeleteDialog } from './APIKeyDeleteDialog' import { ApiKeyPill } from './ApiKeyPill' -import { APIKeysData } from 'data/api-keys/api-keys-query' export const APIKeyRow = ({ apiKey, @@ -34,14 +34,25 @@ export const APIKeyRow = ({ mass: 1, }} > - {apiKey.name} + +
+ {apiKey.name} +
+ {apiKey.description || No description} +
+
+
- {apiKey.description || '/'} - {lastSeen?.timestamp ?? '/'} + + +
+ {lastSeen?.timestamp ?? Never used} +
+
diff --git a/apps/studio/components/interfaces/APIKeys/APIKeysTable.tsx b/apps/studio/components/interfaces/APIKeys/APIKeysTable.tsx deleted file mode 100644 index 49aa3a94a97..00000000000 --- a/apps/studio/components/interfaces/APIKeys/APIKeysTable.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import { AnimatePresence } from 'framer-motion' - -import { APIKeysData } from 'data/api-keys/api-keys-query' -import { APIKeyRow } from './APIKeyRow' - -const APIKeysTable = ({ - apiKeys, -}: { - apiKeys: Extract[] -}) => { - return ( - - - - - {apiKeys.map((apiKey) => ( - - ))} - - -
- ) -} - -export default APIKeysTable diff --git a/apps/studio/components/interfaces/APIKeys/ApiKeyPill.tsx b/apps/studio/components/interfaces/APIKeys/ApiKeyPill.tsx index 6024d017720..28d24040b1d 100644 --- a/apps/studio/components/interfaces/APIKeys/ApiKeyPill.tsx +++ b/apps/studio/components/interfaces/APIKeys/ApiKeyPill.tsx @@ -1,10 +1,10 @@ +import { PermissionAction } from '@supabase/shared-types/out/constants' import { useQueryClient } from '@tanstack/react-query' import { AnimatePresence, motion } from 'framer-motion' import { Eye } from 'lucide-react' import { useEffect, useState } from 'react' import { toast } from 'sonner' -import { PermissionAction } from '@supabase/shared-types/out/constants' import { InputVariants } from '@ui/components/shadcn/ui/input' import { useParams } from 'common' import CopyButton from 'components/ui/CopyButton' @@ -35,7 +35,6 @@ export function ApiKeyPill({ // It fetches the fully revealed API key when needed const { data, - isLoading: isLoadingApiKey, error, refetch: refetchApiKey, } = useAPIKeyIdQuery( @@ -106,7 +105,6 @@ export function ApiKeyPill({ // States for disabling buttons/showing tooltips const isRestricted = isSecret && !canManageSecretKeys - const isLoading = isLoadingPermission return ( <> @@ -118,7 +116,7 @@ export function ApiKeyPill({ isSecret ? 'overflow-hidden' : '', show ? 'ring-1 ring-foreground-lighter ring-opacity-50' : 'ring-0 ring-opacity-0', 'transition-all', - 'max-w-[340px]', + 'max-w-[100px] sm:max-w-[140px] md:max-w-[180px] lg:max-w-[340px]', 'cursor-text', 'relative' )} diff --git a/apps/studio/components/interfaces/APIKeys/PublishableAPIKeys.tsx b/apps/studio/components/interfaces/APIKeys/PublishableAPIKeys.tsx index 99627770315..179df09b662 100644 --- a/apps/studio/components/interfaces/APIKeys/PublishableAPIKeys.tsx +++ b/apps/studio/components/interfaces/APIKeys/PublishableAPIKeys.tsx @@ -1,12 +1,14 @@ import { PermissionAction } from '@supabase/shared-types/out/constants' +import { useMemo } from 'react' + import { InputVariants } from '@ui/components/shadcn/ui/input' import { useParams } from 'common' import CopyButton from 'components/ui/CopyButton' import { FormHeader } from 'components/ui/Forms/FormHeader' import { useAPIKeysQuery } from 'data/api-keys/api-keys-query' import { useCheckPermissions, usePermissionsLoaded } from 'hooks/misc/useCheckPermissions' -import { useMemo } from 'react' import { cn, EyeOffIcon, Input_Shadcn_, Skeleton, WarningIcon } from 'ui' + // to add in later with follow up PR // import CreatePublishableAPIKeyDialog from './CreatePublishableAPIKeyDialog' // to add in later with follow up PR @@ -38,7 +40,7 @@ export const PublishableAPIKeys = () => { description="This key is safe to use in a browser if you have enabled Row Level Security (RLS) for your tables and configured policies." />
-
+
Publishable key
@@ -59,7 +61,7 @@ export const PublishableAPIKeys = () => {
) : (
- Publishable key can be safely shared in public + The publishable key can be safely shared publicly
)}
@@ -91,7 +93,8 @@ function ApiKeyInput() { // The default publisahble key will always be the first one const apiKey = publishableApiKeys[0] - const baseClasses = 'flex-1 grow gap-1 rounded-full min-w-[32em]' + const baseClasses = + 'flex-1 grow gap-1 rounded-full min-w-0 max-w-[200px] sm:max-w-[300px] md:max-w-[400px] lg:min-w-[24rem]' const size = 'tiny' if (isApiKeysLoading || isPermissionsLoading) { diff --git a/apps/studio/components/interfaces/APIKeys/SecretAPIKeys.tsx b/apps/studio/components/interfaces/APIKeys/SecretAPIKeys.tsx index 16a6a60e9fb..5f6c6e1b83f 100644 --- a/apps/studio/components/interfaces/APIKeys/SecretAPIKeys.tsx +++ b/apps/studio/components/interfaces/APIKeys/SecretAPIKeys.tsx @@ -112,10 +112,8 @@ export const SecretAPIKeys = () => { API Key - - Description - - + + Last Seen diff --git a/apps/studio/components/interfaces/JwtSecrets/algorithm-hover-card.tsx b/apps/studio/components/interfaces/JwtSecrets/algorithm-hover-card.tsx index e546c0900e3..1d69c0051a0 100644 --- a/apps/studio/components/interfaces/JwtSecrets/algorithm-hover-card.tsx +++ b/apps/studio/components/interfaces/JwtSecrets/algorithm-hover-card.tsx @@ -1,5 +1,4 @@ import { LockKeyholeOpen, RectangleEllipsis } from 'lucide-react' -import React from 'react' import { InfoPill } from 'components/ui/InfoPill' import { AlgorithmDetail, algorithmDetails } from './algorithm-details' @@ -9,7 +8,7 @@ interface AlgorithmHoverCardProps { legacy?: boolean } -export const AlgorithmHoverCard: React.FC = ({ algorithm, legacy }) => { +export const AlgorithmHoverCard = ({ algorithm, legacy }: AlgorithmHoverCardProps) => { const details: AlgorithmDetail = algorithmDetails[algorithm] return ( @@ -17,9 +16,9 @@ export const AlgorithmHoverCard: React.FC = ({ algorith label={{legacy ? `Legacy ${details.label}` : details.label}} icon={ algorithm === 'HS256' ? ( - + ) : ( - + ) } title={details.name} diff --git a/apps/studio/components/interfaces/JwtSecrets/jwt-secret-keys-table/index.tsx b/apps/studio/components/interfaces/JwtSecrets/jwt-secret-keys-table/index.tsx index 5b0389385c3..51eb792891c 100644 --- a/apps/studio/components/interfaces/JwtSecrets/jwt-secret-keys-table/index.tsx +++ b/apps/studio/components/interfaces/JwtSecrets/jwt-secret-keys-table/index.tsx @@ -257,6 +257,9 @@ export default function JWTSecretKeysTable() { Type + + Last rotated at + Actions @@ -280,8 +283,14 @@ export default function JWTSecretKeysTable() { ) : ( -
- No previously used keys +
+ +
+

No previously used keys

+

+ Rotated keys will appear here for verification of existing tokens +

+
)} @@ -312,6 +321,9 @@ export default function JWTSecretKeysTable() { Type + + Last rotated at + Actions diff --git a/apps/studio/components/interfaces/JwtSecrets/jwt-secret-keys-table/signing-key-row.tsx b/apps/studio/components/interfaces/JwtSecrets/jwt-secret-keys-table/signing-key-row.tsx index 4459f71e1f2..15ea69469ce 100644 --- a/apps/studio/components/interfaces/JwtSecrets/jwt-secret-keys-table/signing-key-row.tsx +++ b/apps/studio/components/interfaces/JwtSecrets/jwt-secret-keys-table/signing-key-row.tsx @@ -1,3 +1,4 @@ +import dayjs from 'dayjs' import { motion } from 'framer-motion' import { CircleArrowDown, @@ -73,24 +74,26 @@ export const SigningKeyRow = ({ )} > {signingKey.status === 'standby' ? ( - + ) : ( - + )} - {statusLabels[signingKey.status]} + {statusLabels[signingKey.status]}
-
+
- {signingKey.id} + + {signingKey.id} +
@@ -100,6 +103,11 @@ export const SigningKeyRow = ({ legacy={signingKey.id === legacyKey?.id} /> + {(signingKey.status === 'previously_used' || signingKey.status === 'revoked') && ( + + {dayjs(signingKey.updated_at).fromNow()} + + )} {(signingKey.status !== 'in_use' || signingKey.algorithm !== 'HS256') && ( diff --git a/apps/studio/components/ui/InfoPill.tsx b/apps/studio/components/ui/InfoPill.tsx index a1287d2a693..d88beae7ebf 100644 --- a/apps/studio/components/ui/InfoPill.tsx +++ b/apps/studio/components/ui/InfoPill.tsx @@ -1,11 +1,12 @@ -import React from 'react' +import { ExternalLink } from 'lucide-react' +import React, { ReactNode } from 'react' + +import { Badge } from 'ui/src/components/shadcn/ui/badge' import { HoverCard, HoverCardContent, HoverCardTrigger, } from 'ui/src/components/shadcn/ui/hover-card' -import { Badge } from 'ui/src/components/shadcn/ui/badge' -import { ExternalLink } from 'lucide-react' interface Link { url: string @@ -13,19 +14,21 @@ interface Link { } interface InfoPillProps { - label: string | React.ReactNode - icon: React.ReactNode + label: string | ReactNode + icon: ReactNode title: string - description: string | React.ReactNode + description: string | ReactNode links?: Link[] } -export const InfoPill: React.FC = ({ label, icon, title, description, links }) => { +export const InfoPill = ({ label, icon, title, description, links }: InfoPillProps) => { return ( - - - {icon} {label} + + + + {icon} {label} +