Skip to content

Refresh token UI to use GQL#1990

Merged
GregorShear merged 9 commits into
mainfrom
greg/refresh-tokens
Jun 18, 2026
Merged

Refresh token UI to use GQL#1990
GregorShear merged 9 commits into
mainfrom
greg/refresh-tokens

Conversation

@GregorShear

@GregorShear GregorShear commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

Summary

Migrates the refresh token UI from PostgREST to GraphQL.

Test plan

  • Verify refresh token pagination (10 tokens/page)
  • Create a new refresh token with a description - confirm the new token appears and secret can be copied
  • Dismiss and reopen the dialog - confirm it resets to the create form
  • Revoke a token - confirmation dialog appears and the token is removed after confirming
  • Expire a token (edit its updated_at to over a year ago) - the row should be disabled and say "expired"
  • Verify error states render correctly (e.g., create failure, revoke failure, list load failure) and clear when dialog is dismissed and reopened

@GregorShear GregorShear requested a review from a team as a code owner June 3, 2026 02:50
@GregorShear GregorShear force-pushed the greg/refresh-tokens branch 5 times, most recently from d60c562 to 4db5bdd Compare June 4, 2026 03:07
Resyncs the generated GraphQL types with the live schema after rebasing onto main. Drops the service-account schema (ApiKeyInfo, ServiceAccount, createServiceAccount, revokeApiKey, serviceAccounts, the ManageServiceAccounts capability bit, TenantFilter) that an earlier codegen run had incidentally captured, and removes validFor from the RefreshTokenInfo output type and the RefreshTokens query, which the server no longer exposes.
@GregorShear GregorShear force-pushed the greg/refresh-tokens branch from 96f4766 to 2329fe9 Compare June 17, 2026 14:45

@jshearer jshearer left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Got some almost entirely 🤖🦾 review feedback for ya

Comment thread src/components/admin/Api/RefreshToken/CreateDialog.tsx Outdated
Comment thread src/components/admin/Api/RefreshToken/Table.tsx Outdated
Comment thread src/components/admin/Api/RefreshToken/Table.tsx Outdated
Comment thread src/components/admin/Api/RefreshToken/Table.tsx Outdated

const result = await revokeRefreshToken({ id });

if (result.error) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Does this ever return false? I kind of doubt it...


revokeRefreshToken is typed Boolean! and the schema documents "already-zeroed (revoked) tokens are treated as not found", but revokeToken only branches on result.error and never reads result.data?.revokeRefreshToken. If the not-found path returns false with no GraphQL error, the dialog reports success on a no-op (e.g. revoking a token already revoked elsewhere). This is partly inherited from the old PATCH-based flow and the cache invalidation makes the end state roughly correct, so it's low impact, but checking the boolean alongside result.error is the defensive fix. Confirming requires the resolver's not-found contract (returns Ok(false) vs raises an error).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

oh yeah - it can technically return false if you revoke and already-revoked token, but all we care about in this case is whether the request succeeds (i.e. the user's intent either came true ...or already was true)

@jshearer jshearer left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Once you address the above review feedback this should be good to go 👍

- Gate create dialog dismissal on the in-flight create state so backdrop/Escape can't close mid-request and orphan the new token's secret

- Realign table headers with their cells: add a Uses header and move Status over the expired column

- Suppress the empty-state message on load error so it no longer renders beneath the error banner

- Recover from an empty non-first page with a useEffect (mirrors AccessLinksTable) instead of the row-level page-back heuristic, and drop the now-unused onRevoked prop; revoke marks a token expired rather than removing it, so a revoke never empties the page
@GregorShear GregorShear merged commit 92b5da5 into main Jun 18, 2026
7 checks passed
@GregorShear GregorShear deleted the greg/refresh-tokens branch June 18, 2026 03:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants