-
Notifications
You must be signed in to change notification settings - Fork 127
feature: Added FGTs support in github integration #648
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -20,7 +20,7 @@ export const linkProvider = async ( | |||||||||||||||||||||||||||||||||||||||||||||||||||||
reject(isNil, { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
provider, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
the_good_stuff: stuff, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
meta_data: meta | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
meta_data: { ...meta, tokenType: meta?.tokenType || 'PAT' } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
}) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -29,21 +29,49 @@ export const linkProvider = async ( | |||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
export async function checkGitHubValidity( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
good_stuff: string | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
): Promise<boolean> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
): Promise<{ isValid: boolean; tokenType: 'PAT' | 'FGT' }> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
try { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
await axios.get('https://api.github.com/user', { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
const response = await axios.get('https://api.github.com/user', { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
headers: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
Authorization: `token ${good_stuff}` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
return true; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
const scopesString = response.headers['x-oauth-scopes'] as string; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
// PATs have scopes in x-oauth-scopes, FGTs do not | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
const tokenType = scopesString ? 'PAT' : 'FGT'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
return { isValid: true, tokenType }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
} catch (error) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
return false; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
return { isValid: false, tokenType: 'PAT' }; // Default to PAT for error handling | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
const PAT_SCOPES = ['read:org', 'read:user', 'repo', 'workflow']; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
export const getMissingPATScopes = async (pat: string) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
export const getMissingTokenScopes = async (pat: string, tokenType: 'PAT' | 'FGT') => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (tokenType === 'FGT') { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
try { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
// For FGTs, check repository permissions (example endpoint) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
const response = await axios.get('https://api.github.com/user/repos', { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
headers: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
Authorization: `token ${pat}` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
params: { per_page: 1 } // Fetch one repo to check permissions | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
// FGTs don't return scopes in headers, so we infer permissions from API access | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Example: Check if user has access to repos (simplified) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (!response.data.length) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
return ['repository_access']; // Custom error for missing repo access | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Note: For precise FGT permission checking, use /repos/{owner}/{repo} or specific endpoints | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
return []; // Assume permissions are sufficient for this example | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
} catch (error) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
throw new Error('Failed to verify FGT permissions', error); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
- throw new Error('Failed to verify FGT permissions', error);
+ // Node ≥ 16 supports `cause`; fall back to message concat otherwise.
+ throw new Error('Failed to verify FGT permissions', { cause: error as any }); The same pattern exists for the PAT branch (line 88 – unchanged). Fixing both prevents double‑faults in the modal. 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Existing PAT logic | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
try { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
const response = await axios.get('https://api.github.com', { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
headers: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -62,7 +90,6 @@ export const getMissingPATScopes = async (pat: string) => { | |||||||||||||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Gitlab functions | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
export const checkGitLabValidity = async ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
accessToken: string, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
customDomain?: string | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
❓ Verification inconclusive
Invalid‑token path always labels the token as a PAT
Inside the
catch
block we return{ isValid: false, tokenType: 'PAT' }
.If the call fails because the user supplied an FGT with no user scope, we’ll still tell the UI it’s a PAT. The UI then shows “PAT” in its error toast, which can mislead users.
Diff suggestion:
You can branch on
'unknown'
in the caller to render a neutral error message.#!/bin/bash
set -e
echo "=== checkGitHubValidity implementation ==="
rg -n "export async function checkGitHubValidity" -A10 -B3 web-server/src/utils/auth.ts || true
echo
echo "=== All references to checkGitHubValidity ==="
rg -n "checkGitHubValidity" -n || true
Revise catch handling to avoid mis‑labeling tokens
The catch block today always returns
{ isValid: false, tokenType: 'PAT' }
, which misleads callers when the failure was for an FGT (no scopes). Instead, we should surface “unknown” and update the function’s signature and callers accordingly.Changes required:
"UNKNOWN"
variant.catch
, return{ isValid: false, tokenType: 'UNKNOWN' }
.checkGitHubValidity
to handle the new"UNKNOWN"
branch and render a neutral error.Diff in
web-server/src/utils/auth.ts
:And in each caller:
tokenType === 'UNKNOWN'
and show a neutral “couldn’t verify token” message.