Skip to content

Show your API token on the profile#448

Open
HazAT wants to merge 4 commits into
mainfrom
api-token-profile
Open

Show your API token on the profile#448
HazAT wants to merge 4 commits into
mainfrom
api-token-profile

Conversation

@HazAT

@HazAT HazAT commented Jul 10, 2026

Copy link
Copy Markdown
Member

Everyone already has an API token, but there's no way to actually see it without digging in the database.

Now the profile shows your token — so you can hit stuff like /api/leaderboard from wherever — plus a regenerate button in case you leak it in a screenshot 🥔

Every user already gets an API token on creation (used by the Bearer
token authenticator on /api routes), but there was no way to see or
rotate it without querying the database.

Backend:
- Add GET /api/user/token returning the current user's token,
  generating one on the fly for users that predate token creation.
- Add POST /api/user/token/regenerate which rotates the token in place
  via the new ApiTokensTable::regenerateApiToken() and returns the new
  value, so the frontend state is updated in the same request.

Frontend:
- New 'Your API Token' section on the Profile view with a masked token
  display plus Show/Hide, Copy, and Regenerate buttons. Regenerating
  swaps the displayed token to the fresh value from the response.
@HazAT HazAT requested a review from a team as a code owner July 10, 2026 09:34
Comment thread frontend/src/views/Profile.vue
Comment thread frontend/src/views/Profile.vue
Address Cursor Bugbot findings on PR #448:

- Add the sentry-mask class to the token display so the plaintext
  token never ends up in Sentry Session Replay recordings. Replay is
  configured with maskAllText: false, and .sentry-mask is always
  masked regardless of that setting.
- Turn Regenerate into a two-step confirmation: first click arms the
  button ('Really? Old token stops working!'), second click rotates.
  Prevents a misclick from instantly invalidating the old token for
  existing API clients and mobile sessions.

Also add dark-mode variants to the Show/Hide and Copy buttons, which
was flagged in the earlier code review.
Comment thread frontend/src/views/Profile.vue
Comment thread src/Model/Table/ApiTokensTable.php Outdated
Address the second round of bot findings on PR #448:

- Add a unique index on api_tokens.user_id (with a dedupe of any
  existing duplicates, keeping the most recently used token). Without
  the constraint, concurrent requests to the token endpoint could
  insert multiple rows for one user, and regenerating only rotated the
  first row — leaving extra tokens silently valid. Flagged by Cursor
  Bugbot; also matches an earlier code-review finding.
- Reset tokenVisible after regenerating so the fresh token is not
  immediately revealed if the old one was showing. Flagged by Seer.
Comment on lines +182 to +188
try {
await navigator.clipboard.writeText(this.apiToken)
this.copied = true
setTimeout(() => this.copied = false, 2000)
} catch (error) {
console.log(error)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Bug: The copyToken function can copy an empty API token if the user clicks "Copy" before the fetchToken async call completes, leading to misleading "Copied!" feedback.
Severity: MEDIUM

Suggested Fix

Disable the "Copy" button until the apiToken has been successfully fetched and is no longer an empty string. This can be achieved by adding a :disabled="!apiToken" attribute to the button in the template. Alternatively, introduce a loading state to prevent interaction until the token is available.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.

Location: frontend/src/views/Profile.vue#L182-L188

Potential issue: The `copyToken` function copies `this.apiToken` to the clipboard. This
token is initialized as an empty string and populated by the asynchronous `fetchToken()`
call in the `mounted` hook. If a user clicks the "Copy" button before `fetchToken()`
resolves, which is possible on slow networks, an empty string is copied. The UI then
incorrectly displays a "Copied!" message, misleading the user into thinking they have
successfully copied the API token when their clipboard is empty.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 85525c8. Configure here.

Comment thread src/Controller/Api/UsersController.php Outdated
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