mirror of
https://github.com/supabase/supabase.git
synced 2026-10-06 18:05:11 +03:00
## Description This is the Scoped PAT stacked PRs root branch ## How to test ### With the `scopedPAT` enabled (default on staging) Go to https://studio-staging-git-scopedpat-merge-token-lists-supabase.vercel.app/dashboard/account/tokens. - You shouldn't see two tabs anymore - If you had classic tokens, they should have the _Legacy_ badge - You can create scoped tokens - You have a way to copy newly created tokens before closing the form side panel ### With the `scopedPAT` disabled (use the devtool to override) - You shouldn't see two tabs anymore - If you had classic tokens, they should **not** have the _Legacy_ badge - You can create classic tokens - You have a way to copy newly created tokens above the list upon form submission <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Show classic and scoped access tokens together in one list, with classic tokens labeled “Legacy” when the scoped experience is enabled. * Add scoped access token creation with a two-step configure → review → success flow (when enabled). * Add a dismissible migration notice about scoped tokens with a link to API docs. * Show “View permissions” only for scoped tokens. * **Bug Fixes** * Token deletion now supports both classic and scoped tokens with the correct confirmation and success handling. * The scoped tokens page now redirects to the unified access tokens page. * **Accessibility** * Improved accessibility by adding a label to the token “more options” action. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Ali Waseem <waseema393@gmail.com> Co-authored-by: kemal.earth <606977+kemaldotearth@users.noreply.github.com>
73 lines
1.8 KiB
TypeScript
73 lines
1.8 KiB
TypeScript
import dayjs from 'dayjs'
|
|
import { Badge, TableCell } from 'ui'
|
|
import { TimestampInfo } from 'ui-patterns/TimestampInfo'
|
|
|
|
interface TokenNameCellProps {
|
|
name: string
|
|
tokenAlias: string
|
|
isClassic: boolean
|
|
scopedTokensEnabled?: boolean
|
|
}
|
|
|
|
export const TokenNameCell = ({
|
|
name,
|
|
tokenAlias,
|
|
isClassic,
|
|
scopedTokensEnabled,
|
|
}: TokenNameCellProps) => (
|
|
<TableCell className="w-auto max-w-96">
|
|
<div className="flex items-center gap-x-2">
|
|
<p className="truncate" title={name}>
|
|
{name}
|
|
</p>
|
|
{isClassic && scopedTokensEnabled && <Badge variant="default">Legacy</Badge>}
|
|
</div>
|
|
<p
|
|
className="font-mono text-foreground-lighter truncate text-xs mt-1 max-w-32 sm:max-w-48 lg:max-w-full"
|
|
title={tokenAlias}
|
|
>
|
|
{tokenAlias}
|
|
</p>
|
|
</TableCell>
|
|
)
|
|
|
|
interface LastUsedCellProps {
|
|
lastUsedAt: string | null | undefined
|
|
}
|
|
|
|
export const LastUsedCell = ({ lastUsedAt }: LastUsedCellProps) => (
|
|
<TableCell className="text-foreground-light min-w-28">
|
|
{lastUsedAt ? (
|
|
<TimestampInfo
|
|
utcTimestamp={lastUsedAt}
|
|
label={dayjs(lastUsedAt).fromNow()}
|
|
className="text-sm"
|
|
/>
|
|
) : (
|
|
<p className="text-foreground-light text-sm">Never used</p>
|
|
)}
|
|
</TableCell>
|
|
)
|
|
|
|
interface ExpiresCellProps {
|
|
expiresAt: string | null | undefined
|
|
}
|
|
|
|
export const ExpiresCell = ({ expiresAt }: ExpiresCellProps) => (
|
|
<TableCell className="min-w-28 text-foreground-light">
|
|
{expiresAt ? (
|
|
dayjs(expiresAt).isBefore(dayjs()) ? (
|
|
<TimestampInfo utcTimestamp={expiresAt} label="Expired" className="text-sm" />
|
|
) : (
|
|
<TimestampInfo
|
|
utcTimestamp={expiresAt}
|
|
label={dayjs(expiresAt).format('DD MMM YYYY')}
|
|
className="text-sm"
|
|
/>
|
|
)
|
|
) : (
|
|
<p className="text-foreground-light text-sm">Never</p>
|
|
)}
|
|
</TableCell>
|
|
)
|