Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions src/github/credentials.ts
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,54 @@ export class CredentialStore extends Disposable {
github.isEmu = getUser.then(result => result.data.plan?.name === 'emu_user');
}

/**
* Check if the user is authenticated and might benefit from checking account preferences.
* Note: Due to VS Code API limitations, we cannot directly check if multiple accounts are available.
* This method returns true if the user is authenticated, as they may have multiple accounts
* configured in VS Code that they can switch to via the "Manage Account Preferences" command.
*/
public async isAuthenticatedForAccountPreferences(authProviderId: AuthProvider): Promise<boolean> {
return this.isAuthenticated(authProviderId);
}

/**
* Show a modal dialog suggesting the user might be using the wrong GitHub account.
* Offers to open the "Manage Account Preferences" command.
* @param repoName The repository name that couldn't be accessed
* @param authProviderId The authentication provider ID
* @returns true if the user chose to manage account preferences, false otherwise
*/
public async showWrongAccountModal(repoName: string, authProviderId: AuthProvider): Promise<boolean> {
let accountName: string;
try {
const currentUser = await this.getCurrentUser(authProviderId);
accountName = currentUser?.login ?? vscode.l10n.t('your current account');
} catch {
accountName = vscode.l10n.t('your current account');
}

const manageAccountPreferences = vscode.l10n.t('Manage Account Preferences');
const result = await vscode.window.showErrorMessage(
vscode.l10n.t(
'Unable to access repository "{0}" with the current GitHub account ({1}). You may have multiple GitHub accounts configured. Would you like to check your account preferences?',
repoName,
accountName
),
{ modal: true },
manageAccountPreferences
);

if (result === manageAccountPreferences) {
try {
await vscode.commands.executeCommand('_account.manageAccountPreferences', 'GitHub.vscode-pull-request-github');
} catch (e) {
Logger.error(`Failed to open manage account preferences: ${e}`, CredentialStore.ID);
}
return true;
}
return false;
}

private async getSession(authProviderId: AuthProvider, getAuthSessionOptions: vscode.AuthenticationGetSessionOptions, scopes: string[], requireScopes: boolean): Promise<{ session: vscode.AuthenticationSession | undefined, isNew: boolean, scopes: string[] }> {
const existingSession = (getAuthSessionOptions.forceNewSession || requireScopes) ? undefined : await this.findExistingScopes(authProviderId);
if (existingSession?.session) {
Expand Down
15 changes: 11 additions & 4 deletions src/github/folderRepositoryManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1360,10 +1360,17 @@ export class FolderRepositoryManager extends Disposable {
} catch (e) {
Logger.error(`Fetching pull request with query failed: ${e}`, this.id);
if (e.status === 404) {
// not found
vscode.window.showWarningMessage(
`Fetching pull requests for remote ${githubRepository.remote.remoteName} with query failed, please check if the repo ${githubRepository.remote.owner}/${githubRepository.remote.repositoryName} is valid.`,
);
// not found - this might be due to using the wrong account
const repoName = `${githubRepository.remote.owner}/${githubRepository.remote.repositoryName}`;
const isAuthenticated = await this._credentialStore.isAuthenticatedForAccountPreferences(githubRepository.remote.authProviderId);
if (isAuthenticated) {
// Show modal suggesting the user might be using the wrong account
await this._credentialStore.showWrongAccountModal(repoName, githubRepository.remote.authProviderId);
} else {
vscode.window.showWarningMessage(
vscode.l10n.t('Fetching pull requests for remote {0} with query failed, please check if the repo {1} is valid.', githubRepository.remote.remoteName, repoName),
);
}
} else {
throw e;
}
Expand Down
18 changes: 16 additions & 2 deletions src/view/treeNodes/categoryNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import * as vscode from 'vscode';
import { RemoteInfo } from '../../../common/types';
import { AuthenticationError } from '../../common/authentication';
import { AuthenticationError, AuthProvider } from '../../common/authentication';
import { DEV_MODE, PR_SETTINGS_NAMESPACE } from '../../common/settingKeys';
import { ITelemetry } from '../../common/telemetry';
import { toQueryUri } from '../../common/uri';
Expand Down Expand Up @@ -299,15 +299,29 @@ export class CategoryTreeNode extends TreeNode implements vscode.TreeItem {
} catch (e) {
if (this.isCopilot && (e.response.status === 422) && e.message.includes('the users do not exist')) {
// Skip it, it's copilot and the repo doesn't have copilot
} else if (e.status === 404 || e.response?.status === 404) {
// 404 errors might indicate wrong account - this is handled in folderRepositoryManager
// but we catch it here to prevent duplicate error messages
needLogin = e instanceof AuthenticationError;
} else {
const error = formatError(e);
const actions: string[] = [];
if (error.includes('Bad credentials')) {
actions.push(vscode.l10n.t('Login again'));
} else if (e.status === 403 || e.response?.status === 403) {
// 403 forbidden - user might not have access with current account
// Check both GitHub.com and Enterprise providers since we might have repos from either
const isAuthenticatedGitHub = await this.folderRepoManager.credentialStore.isAuthenticatedForAccountPreferences(AuthProvider.github);
const isAuthenticatedEnterprise = await this.folderRepoManager.credentialStore.isAuthenticatedForAccountPreferences(AuthProvider.githubEnterprise);
if (isAuthenticatedGitHub || isAuthenticatedEnterprise) {
actions.push(vscode.l10n.t('Check Account Preferences'));
}
}
vscode.window.showErrorMessage(vscode.l10n.t('Fetching pull requests failed: {0}', formatError(e)), ...actions).then(action => {
if (action && action === actions[0]) {
if (action === vscode.l10n.t('Login again')) {
this.folderRepoManager.credentialStore.recreate(vscode.l10n.t('Your login session is no longer valid.'));
} else if (action === vscode.l10n.t('Check Account Preferences')) {
vscode.commands.executeCommand('_account.manageAccountPreferences', 'GitHub.vscode-pull-request-github');
}
});
needLogin = e instanceof AuthenticationError;
Expand Down