Skip to content

Commit 7d75aac

Browse files
ci-botAniket-Engg
authored andcommitted
fix test
1 parent e488d58 commit 7d75aac

File tree

1 file changed

+194
-80
lines changed

1 file changed

+194
-80
lines changed

apps/remix-ide/src/app/files/dgitProvider.ts

Lines changed: 194 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,59 @@ export default class DGitProvider extends Plugin<any, CustomRemixApi> {
4848
return await this.call('config' as any, 'getAppParameter', 'settings/gist-access-token')
4949
}
5050

51+
private isValidGitHubToken(token: string): boolean {
52+
if (!token || typeof token !== 'string') {
53+
return false
54+
}
55+
56+
// Remove whitespace
57+
token = token.trim()
58+
59+
// Check for empty token
60+
if (token.length === 0) {
61+
return false
62+
}
63+
64+
// GitHub token patterns:
65+
// Personal Access Token (classic): ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx (40 chars)
66+
// Personal Access Token (fine-grained): github_pat_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx (varies)
67+
// OAuth token: gho_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx (40 chars)
68+
// GitHub App token: ghs_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx (40 chars)
69+
// GitHub App installation token: ghu_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx (40 chars)
70+
// Refresh token: ghr_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx (40 chars)
71+
72+
const tokenPatterns = [
73+
/^ghp_[A-Za-z0-9]{36}$/, // Personal Access Token (classic)
74+
/^github_pat_[A-Za-z0-9_]{22,255}$/, // Personal Access Token (fine-grained)
75+
/^gho_[A-Za-z0-9]{36}$/, // OAuth token
76+
/^ghs_[A-Za-z0-9]{36}$/, // GitHub App token
77+
/^ghu_[A-Za-z0-9]{36}$/, // GitHub App installation token
78+
/^ghr_[A-Za-z0-9]{36}$/, // Refresh token
79+
]
80+
81+
// Check if token matches any known GitHub token pattern
82+
const matchesPattern = tokenPatterns.some(pattern => pattern.test(token))
83+
84+
if (matchesPattern) {
85+
return true
86+
}
87+
88+
// Fallback: check if it looks like a legacy token (40 chars, alphanumeric)
89+
// Some older tokens might not follow the new prefixed format
90+
if (/^[A-Za-z0-9]{40}$/.test(token)) {
91+
console.warn('Token appears to be a legacy GitHub token format')
92+
return true
93+
}
94+
95+
console.warn('Token does not match known GitHub token patterns:', {
96+
length: token.length,
97+
prefix: token.substring(0, 4),
98+
hasValidChars: /^[A-Za-z0-9_]+$/.test(token)
99+
})
100+
101+
return false
102+
}
103+
51104
async getAuthor(input) {
52105
const author: author = {
53106
name: '',
@@ -568,19 +621,32 @@ export default class DGitProvider extends Plugin<any, CustomRemixApi> {
568621
// OCTOKIT FEATURES
569622

570623
async remotebranches(input: { owner: string, repo: string, token: string, page: number, per_page: number }) {
624+
try {
625+
// Quick validation to avoid unnecessary API calls
626+
if (!this.isValidGitHubToken(input.token)) {
627+
throw new Error('Invalid GitHub token format')
628+
}
571629

572-
const octokit = new Octokit({
573-
auth: input.token
574-
})
630+
const octokit = new Octokit({
631+
auth: input.token,
632+
retry: { enabled: false }
633+
})
575634

576-
const data = await octokit.request('GET /repos/{owner}/{repo}/branches{?protected,per_page,page}', {
577-
owner: input.owner,
578-
repo: input.repo,
579-
per_page: input.per_page || 100,
580-
page: input.page || 1
581-
})
635+
const data = await octokit.request('GET /repos/{owner}/{repo}/branches{?protected,per_page,page}', {
636+
owner: input.owner,
637+
repo: input.repo,
638+
per_page: input.per_page || 100,
639+
page: input.page || 1
640+
})
582641

583-
return data.data
642+
return data.data
643+
} catch (e) {
644+
console.error('Error fetching remote branches:', e)
645+
if (e.status === 403) {
646+
console.error('GitHub API returned 403 Forbidden - check token permissions or rate limits')
647+
}
648+
throw e // Re-throw to let caller handle
649+
}
584650
}
585651

586652
async getGitHubUser(input: { token: string }): Promise<{
@@ -589,115 +655,163 @@ export default class DGitProvider extends Plugin<any, CustomRemixApi> {
589655
scopes: string[]
590656
}> {
591657
try {
658+
// Quick validation to avoid unnecessary API calls
659+
if (!this.isValidGitHubToken(input.token)) {
660+
console.warn('Invalid GitHub token format, skipping API call')
661+
return null
662+
}
663+
664+
592665
const octokit = new Octokit({
593-
auth: input.token
666+
auth: input.token,
667+
retry: { enabled: false }
594668
})
595669

596670
const user = await octokit.request('GET /user', {
597671
headers: {
598672
'X-GitHub-Api-Version': '2022-11-28'
599673
}
600674
})
601-
const emails = await octokit.request('GET /user/emails')
675+
676+
677+
let emails = { data: [] }
678+
try {
679+
emails = await octokit.request('GET /user/emails')
680+
} catch (emailError) {
681+
console.warn('Could not fetch user emails:', emailError)
682+
// Continue without emails if this fails
683+
}
602684

603685
const scopes = user.headers['x-oauth-scopes'] || ''
604686

605687
return {
606688
user: {
607-
...user.data, isConnected:
608-
user.data.login !== undefined && user.data.login !== null && user.data.login !== ''
689+
...user.data,
690+
isConnected: user.data.login !== undefined && user.data.login !== null && user.data.login !== ''
609691
},
610692
emails: emails.data,
611693
scopes: scopes && scopes.split(',').map(scope => scope.trim())
612694
}
613695
} catch (e) {
696+
console.error('Error in getGitHubUser:', e)
697+
// Check if it's a 403 specifically
698+
if (e.status === 403) {
699+
console.error('GitHub API returned 403 Forbidden - check token permissions')
700+
}
614701
return null
615702
}
616703
}
617704

705+
706+
618707
async remotecommits(input: remoteCommitsInputType): Promise<pagedCommits[]> {
708+
try {
709+
// Quick validation to avoid unnecessary API calls
710+
if (!this.isValidGitHubToken(input.token)) {
711+
throw new Error('Invalid GitHub token format')
712+
}
619713

620-
const octokit = new Octokit({
621-
auth: input.token
622-
})
623-
input.length = input.length || 5
624-
input.page = input.page || 1
625-
const response = await octokit.request('GET /repos/{owner}/{repo}/commits', {
626-
owner: input.owner,
627-
repo: input.repo,
628-
sha: input.branch,
629-
per_page: input.length,
630-
page: input.page
631-
})
632-
const pages: pagedCommits[] = []
633-
const readCommitResults: ReadCommitResult[] = []
634-
for (const githubApiCommit of response.data) {
635-
const readCommitResult = {
636-
oid: githubApiCommit.sha,
637-
commit: {
638-
author: {
639-
name: githubApiCommit.commit.author.name,
640-
email: githubApiCommit.commit.author.email,
641-
timestamp: new Date(githubApiCommit.commit.author.date).getTime() / 1000,
642-
timezoneOffset: new Date(githubApiCommit.commit.author.date).getTimezoneOffset()
643-
},
644-
committer: {
645-
name: githubApiCommit.commit.committer.name,
646-
email: githubApiCommit.commit.committer.email,
647-
timestamp: new Date(githubApiCommit.commit.committer.date).getTime() / 1000,
648-
timezoneOffset: new Date(githubApiCommit.commit.committer.date).getTimezoneOffset()
714+
const octokit = new Octokit({
715+
auth: input.token,
716+
retry: { enabled: false }
717+
})
718+
input.length = input.length || 5
719+
input.page = input.page || 1
720+
const response = await octokit.request('GET /repos/{owner}/{repo}/commits', {
721+
owner: input.owner,
722+
repo: input.repo,
723+
sha: input.branch,
724+
per_page: input.length,
725+
page: input.page
726+
})
727+
const pages: pagedCommits[] = []
728+
const readCommitResults: ReadCommitResult[] = []
729+
for (const githubApiCommit of response.data) {
730+
const readCommitResult = {
731+
oid: githubApiCommit.sha,
732+
commit: {
733+
author: {
734+
name: githubApiCommit.commit.author.name,
735+
email: githubApiCommit.commit.author.email,
736+
timestamp: new Date(githubApiCommit.commit.author.date).getTime() / 1000,
737+
timezoneOffset: new Date(githubApiCommit.commit.author.date).getTimezoneOffset()
738+
},
739+
committer: {
740+
name: githubApiCommit.commit.committer.name,
741+
email: githubApiCommit.commit.committer.email,
742+
timestamp: new Date(githubApiCommit.commit.committer.date).getTime() / 1000,
743+
timezoneOffset: new Date(githubApiCommit.commit.committer.date).getTimezoneOffset()
744+
},
745+
message: githubApiCommit.commit.message,
746+
tree: githubApiCommit.commit.tree.sha,
747+
parent: githubApiCommit.parents.map(parent => parent.sha)
649748
},
650-
message: githubApiCommit.commit.message,
651-
tree: githubApiCommit.commit.tree.sha,
652-
parent: githubApiCommit.parents.map(parent => parent.sha)
653-
},
654-
payload: '' // You may need to reconstruct the commit object in Git's format if necessary
749+
payload: '' // You may need to reconstruct the commit object in Git's format if necessary
750+
}
751+
readCommitResults.push(readCommitResult)
655752
}
656-
readCommitResults.push(readCommitResult)
657-
}
658753

659-
// Check for the Link header to determine pagination
660-
const linkHeader = response.headers.link;
754+
// Check for the Link header to determine pagination
755+
const linkHeader = response.headers.link;
661756

662-
let hasNextPage = false;
663-
if (linkHeader) {
664-
// A simple check for the presence of a 'next' relation in the Link header
665-
hasNextPage = linkHeader.includes('rel="next"');
666-
}
757+
let hasNextPage = false;
758+
if (linkHeader) {
759+
// A simple check for the presence of a 'next' relation in the Link header
760+
hasNextPage = linkHeader.includes('rel="next"');
761+
}
667762

668-
pages.push({
669-
page: input.page,
670-
perPage: input.length,
671-
total: response.data.length,
672-
hasNextPage: hasNextPage,
673-
commits: readCommitResults
674-
})
675-
return pages
763+
pages.push({
764+
page: input.page,
765+
perPage: input.length,
766+
total: response.data.length,
767+
hasNextPage: hasNextPage,
768+
commits: readCommitResults
769+
})
770+
return pages
771+
} catch (e) {
772+
console.error('Error fetching remote commits:', e)
773+
if (e.status === 403) {
774+
console.error('GitHub API returned 403 Forbidden - check token permissions or rate limits')
775+
}
776+
throw e // Re-throw to let caller handle
777+
}
676778
}
677779

678780
async repositories(input: repositoriesInput) {
781+
try {
782+
// Quick validation to avoid unnecessary API calls
783+
if (!this.isValidGitHubToken(input.token)) {
784+
throw new Error('Invalid GitHub token format')
785+
}
679786

680-
const accessToken = input.token;
787+
const accessToken = input.token;
681788

682-
const page = input.page || 1
683-
const perPage = input.per_page || 10
789+
const page = input.page || 1
790+
const perPage = input.per_page || 10
684791

685-
const baseURL = 'https://api.github.com/user/repos'
686-
const repositories = []
687-
const sort = 'updated'
688-
const direction = 'desc'
792+
const baseURL = 'https://api.github.com/user/repos'
793+
const repositories = []
794+
const sort = 'updated'
795+
const direction = 'desc'
689796

690-
const headers = {
691-
'Authorization': `Bearer ${accessToken}`, // Include your GitHub access token
692-
'Accept': 'application/vnd.github.v3+json', // GitHub API v3 media type
693-
};
797+
const headers = {
798+
'Authorization': `Bearer ${accessToken}`, // Include your GitHub access token
799+
'Accept': 'application/vnd.github.v3+json', // GitHub API v3 media type
800+
};
694801

695-
const url = `${baseURL}?visibility=private,public&page=${page}&per_page=${perPage}&sort=${sort}&direction=${direction}`;
696-
const response = await axios.get(url, { headers });
802+
const url = `${baseURL}?visibility=private,public&page=${page}&per_page=${perPage}&sort=${sort}&direction=${direction}`;
803+
const response = await axios.get(url, { headers });
697804

698-
repositories.push(...response.data);
805+
repositories.push(...response.data);
699806

700-
return repositories
807+
return repositories
808+
} catch (e) {
809+
console.error('Error fetching repositories:', e)
810+
if (e.response?.status === 403) {
811+
console.error('GitHub API returned 403 Forbidden - check token permissions or rate limits')
812+
}
813+
throw e // Re-throw to let caller handle
814+
}
701815
}
702816

703817
}

0 commit comments

Comments
 (0)