Skip to content

fix(settings): validate GitHub Personal Access Token before saving - #139

Merged
Ri1tik merged 1 commit into
AOSSIE-Org:mainfrom
Dotify71:fix-pat-validation-138
Aug 4, 2026
Merged

fix(settings): validate GitHub Personal Access Token before saving#139
Ri1tik merged 1 commit into
AOSSIE-Org:mainfrom
Dotify71:fix-pat-validation-138

Conversation

@Dotify71

@Dotify71 Dotify71 commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Fixes #138

This updates the Settings page to verify the Personal Access Token with the GitHub API before saving it to local storage. It now displays an appropriate error message if the token is invalid and disables the save button while validating.

Summary by CodeRabbit

  • Bug Fixes
    • GitHub token saving now validates the token before completing.
    • Clearer feedback is provided for invalid tokens and network errors.
    • Save and delete actions are disabled while validation is in progress.
    • Updating or deleting a token clears previous validation errors.
    • The save button displays a validation-in-progress state.

@github-actions github-actions Bot added bug Something isn't working frontend Frontend changes javascript JavaScript/TypeScript changes labels Aug 3, 2026
@coderabbitai

coderabbitai Bot commented Aug 3, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

The Settings page now validates trimmed GitHub PATs through the rate-limit endpoint before saving them. It reports invalid-token and network errors, clears errors after edits or deletion, and prevents concurrent actions during validation.

Changes

GitHub PAT validation

Layer / File(s) Summary
Validate PAT before saving
src/pages/SettingsPage.jsx
The Settings page verifies non-empty trimmed tokens before saving them. It reports invalid responses and network failures, clears validation errors after edits or deletion, disables concurrent actions, and displays Validating... during verification.

Estimated code review effort: 2 (Simple) | ~10 minutes

Suggested reviewers: ri1tik, rahul-vyas-dev

Poem

A bunny checks the token bright,
Then hops through GitHub’s rate-limit light.
Bad keys raise an error clear,
Good keys make “Authenticated” appear.
While checks run, buttons wait—
Safe little hops before the save gate.

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes validation of the GitHub Personal Access Token before saving.
Linked Issues check ✅ Passed The changes verify the token before saving, report invalid tokens, and prevent authenticated status when validation fails [#138].
Out of Scope Changes check ✅ Passed The changes support token validation and related save-state handling without introducing unrelated functionality.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added size/M 51-200 lines changed external-contributor External contributor and removed size/M 51-200 lines changed labels Aug 3, 2026

@coderabbitai coderabbitai 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.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/pages/SettingsPage.jsx`:
- Around line 18-46: The handleSave validation flow can save a stale token and
permits concurrent submissions. Update handleSave and the associated token
input/save controls to prevent edits and reject duplicate saves while
isValidating is true; ensure every validation path restores the validation state
so only the currently submitted token can reach savePat.
- Around line 18-46: The handleSave response handling must distinguish
authentication failures from rate-limit or permission failures: show “Invalid
Personal Access Token” only when response.status is 401, and use a retryable
verification/rate-limit error for 403 and 429 (and other non-OK responses as
appropriate). Keep successful token saving and the existing network-error
handling unchanged.
- Around line 34-43: Update the PAT validation flow in SettingsPage around the
validation error handling and validating-state render to replace the visible
strings “Invalid Personal Access Token”, “Network error verifying token”, and
“Validating...” with app i18n lookups. Add corresponding keys and translations
to the existing translation resources, then use the established translation hook
or helper so all three labels are localized before rendering.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 8dd5ad03-41ea-4b43-afee-625d2915f1b1

📥 Commits

Reviewing files that changed from the base of the PR and between 4243735 and 855207f.

📒 Files selected for processing (1)
  • src/pages/SettingsPage.jsx

Comment on lines +18 to +46
const handleSave = async () => {
const token = draft.trim();
if (!token) return;

setIsValidating(true);
setTokenError('');

try {
const response = await fetch('https://api.github.com/rate_limit', {
headers: {
Accept: 'application/vnd.github.v3+json',
Authorization: `token ${token}`
}
});

if (!response.ok) {
setTokenError('Invalid Personal Access Token');
setIsValidating(false);
return;
}

savePat(token);
setSaved(true);
setTimeout(() => setSaved(false), 2000);
} catch (err) {
setTokenError('Network error verifying token');
} finally {
setIsValidating(false);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Prevent stale validation from saving a different token.

The input remains editable while validation is pending. If token A is validating and the user changes the draft to token B, a successful response for token A calls savePat(token) while the input displays token B. Repeated Enter presses can also start concurrent validations because handleSave has no in-flight guard.

Disable token editing during validation and reject duplicate saves. Alternatively, associate a request identifier with the draft and discard stale responses before savePat.

Also applies to: 163-166

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/pages/SettingsPage.jsx` around lines 18 - 46, The handleSave validation
flow can save a stale token and permits concurrent submissions. Update
handleSave and the associated token input/save controls to prevent edits and
reject duplicate saves while isValidating is true; ensure every validation path
restores the validation state so only the currently submitted token can reach
savePat.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

GitHub REST API authenticate with Personal Access Token rate limiting 403 404 401

💡 Result:

When working with the GitHub REST API using a Personal Access Token (PAT), errors often relate to authentication status, authorization scope, or rate limit policies [1][2]. 401 Unauthorized A 401 error indicates that your request is missing credentials, or the provided token is invalid, expired, or revoked [1][2]. Ensure you are including the token in the Authorization header (e.g., Authorization: Bearer ) and that the token is active [3][4]. 403 Forbidden A 403 error may occur for several reasons: - Primary Rate Limits: You have exceeded your hourly request limit (e.g., 5,000 requests per hour for authenticated users) [5][1]. The response may include a Retry-After header or indicate in the x-ratelimit-remaining header that your budget is exhausted [1][6]. - Secondary Rate Limits: These are triggered by rapid, concurrent, or computationally expensive requests [1][6][2]. - Authentication Rejection: If you submit multiple requests with invalid credentials in a short period, GitHub may temporarily block all authentication attempts for your account, responding with a 403 [3]. - Permissions: Your PAT may lack the specific scopes or organization-level permissions required to access the requested resource [1][7]. 404 Not Found A 404 error is returned if the resource does not exist, but it is also intentionally used when you attempt to access a private resource for which you are not authenticated (or lack permissions) [7][6]. This is a security measure to avoid confirming the existence of private repositories [7][6]. If you know the resource exists, verify your authentication and ensure your token has the correct scope to access that private data [7][6]. Handling Rate Limits - Primary Limits: Check the x-ratelimit-remaining header. If it is 0, do not retry until after the time specified in the x-ratelimit-reset header [1][6]. - Secondary Limits: Use exponential backoff if you receive a 403 or 429 error and no Retry-After header is provided [1][6][2]. - Conditional Requests: To optimize your rate limit usage, use ETag or Last-Modified headers to perform conditional requests, which do not count against your limit if the data has not changed [2].

Citations:


🌐 Web query:

site:docs.github.com/rest/authentication/authenticating-to-the-rest-api 401 bad credentials 403 rate limit

💡 Result:

  • 401 Unauthorized / “Bad credentials”: The token or credentials are invalid. GitHub initially returns 401; repeated invalid attempts can temporarily result in 403. [1]
  • 403 Forbidden: Usually means insufficient token permissions, SAML SSO authorization is missing, or you triggered a secondary/failed-login rate limit. [1][2]
  • 403/429 rate limit: If x-ratelimit-remaining: 0, wait until the Unix timestamp in x-ratelimit-reset. For secondary limits, honor retry-after; otherwise wait at least one minute and use exponential backoff. [2]

Check status with:

curl https://api.github.com/rate_limit

[3]


🌐 Web query:

site:docs.github.com/rest/authentication/authenticating-to-the-rest-api 401 Bad credentials

💡 Result:

A 401 status code, officially defined as 401 Unauthorized, indicates that a request lacks valid authentication credentials for the target resource. While the HTTP standard specifies this as Unauthorized, it is colloquially referred to as Bad credentials because the error typically arises when the provided credentials—such as a username, password, API token, or access key—are incorrect, expired, or improperly formatted [1]. To resolve a 401 error, verify the following: 1. Credentials: Ensure the username, password, or API token being sent in the request headers or body is accurate [1]. 2. Authentication Method: Confirm that the server expects the authentication format being used, such as Basic Auth, Bearer Token, or an API-specific header [1]. 3. Expiration: Check if the access token has expired and if it needs to be refreshed. 4. Permissions: Ensure the account associated with the credentials has the necessary scope or permissions to access the requested resource [1].

Citations:


Distinguish token auth failures from rate-limit failures.

Invalid Personal Access Token should only be shown for 401 auth failures. 403 and 429 can mean rate limiting, permissions, or SSO/scopes rather than an invalid PAT, so display a retryable verification/rate-limit error for those statuses.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/pages/SettingsPage.jsx` around lines 18 - 46, The handleSave response
handling must distinguish authentication failures from rate-limit or permission
failures: show “Invalid Personal Access Token” only when response.status is 401,
and use a retryable verification/rate-limit error for 403 and 429 (and other
non-OK responses as appropriate). Keep successful token saving and the existing
network-error handling unchanged.

Comment on lines +34 to +43
setTokenError('Invalid Personal Access Token');
setIsValidating(false);
return;
}

savePat(token);
setSaved(true);
setTimeout(() => setSaved(false), 2000);
} catch (err) {
setTokenError('Network error verifying token');

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== files =="
git ls-files | sed -n '1,200p'

echo "== target file outline/sections =="
if [ -f src/pages/SettingsPage.jsx ]; then
  wc -l src/pages/SettingsPage.jsx
  sed -n '1,240p' src/pages/SettingsPage.jsx | nl -ba
fi

echo "== i18n/resource/string candidates =="
rg -n --glob '!node_modules/**' '('use client'|i18n|useTranslation|t\(|translation|locales|en|zh|messages|translations|Validating|Network error|Invalid Personal Access Token' src package.json . 2>/dev/null | sed -n '1,240p'

Repository: AOSSIE-Org/OrgExplorer

Length of output: 2107


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== target file first 240 lines with line numbers =="
awk '{printf "%6d\t%s\n", NR, $0}' src/pages/SettingsPage.jsx | sed -n '1,240p'

echo "== search hardcoded strings and i18n usage =="
rg -n --glob '!node_modules/**' \
  "'use client'|useTranslation|t\(|translation|locales|messages|Validating|Network error|Invalid Personal Access Token|Validating\\.\\.\\." \
  src package.json eslint.config.js 2>/dev/null | sed -n '1,260p'

echo "== package/deps summary =="
python3 - <<'PY'
import json
p=json.load(open('package.json'))
for sec in ['dependencies','devDependencies','dependenciesExpo']:
    vals=p.get(sec, {})
    hits={k:v for k,v in vals.items() if 'i18n' in k.lower() or 'translate' in k.lower() or k.lower() in ['react-i18next','i18next','next-intl','expo-localization','expo-i18n']}
    print(sec, hits)
PY

Repository: AOSSIE-Org/OrgExplorer

Length of output: 35357


Externalize the PAT validation labels.

Invalid Personal Access Token, Network error verifying token, and Validating... are visible to users. Add them to translation resources and resolve them through the app’s i18n mechanism before rendering them at lines 34, 43, and 189.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/pages/SettingsPage.jsx` around lines 34 - 43, Update the PAT validation
flow in SettingsPage around the validation error handling and validating-state
render to replace the visible strings “Invalid Personal Access Token”, “Network
error verifying token”, and “Validating...” with app i18n lookups. Add
corresponding keys and translations to the existing translation resources, then
use the established translation hook or helper so all three labels are localized
before rendering.

Source: Path instructions

@Ri1tik
Ri1tik merged commit f911298 into AOSSIE-Org:main Aug 4, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working external-contributor External contributor frontend Frontend changes javascript JavaScript/TypeScript changes size/M 51-200 lines changed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG]: Invalid GitHub Personal Access Tokens are accepted and shown as "Authenticated"

2 participants