|
|
@ -1,8 +1,12 @@ |
|
|
|
import type { AuthenticationSession, Range } from 'vscode'; |
|
|
|
import { Uri, window } from 'vscode'; |
|
|
|
import type { AuthenticationSession, Disposable, QuickInputButton, Range } from 'vscode'; |
|
|
|
import { env, ThemeIcon, Uri, window } from 'vscode'; |
|
|
|
import type { Autolink, DynamicAutolinkReference } from '../../annotations/autolinks'; |
|
|
|
import type { AutolinkReference } from '../../config'; |
|
|
|
import type { Container } from '../../container'; |
|
|
|
import type { |
|
|
|
IntegrationAuthenticationProvider, |
|
|
|
IntegrationAuthenticationSessionDescriptor, |
|
|
|
} from '../../plus/integrationAuthentication'; |
|
|
|
import { isSubscriptionPaidPlan, isSubscriptionPreviewTrialExpired } from '../../subscription'; |
|
|
|
import { log } from '../../system/decorators/log'; |
|
|
|
import { memoize } from '../../system/decorators/memoize'; |
|
|
@ -397,3 +401,82 @@ export function getGitHubNoReplyAddressParts( |
|
|
|
const [, userId, login, authority] = match; |
|
|
|
return { userId: userId, login: login, authority: authority }; |
|
|
|
} |
|
|
|
|
|
|
|
export class GitHubAuthenticationProvider implements Disposable, IntegrationAuthenticationProvider { |
|
|
|
private readonly _disposable: Disposable; |
|
|
|
|
|
|
|
constructor(container: Container) { |
|
|
|
this._disposable = container.integrationAuthentication.registerProvider('github-enterprise', this); |
|
|
|
} |
|
|
|
|
|
|
|
dispose() { |
|
|
|
this._disposable.dispose(); |
|
|
|
} |
|
|
|
|
|
|
|
getSessionId(descriptor?: IntegrationAuthenticationSessionDescriptor): string { |
|
|
|
return descriptor?.domain ?? ''; |
|
|
|
} |
|
|
|
|
|
|
|
async createSession( |
|
|
|
descriptor?: IntegrationAuthenticationSessionDescriptor, |
|
|
|
): Promise<AuthenticationSession | undefined> { |
|
|
|
const input = window.createInputBox(); |
|
|
|
input.ignoreFocusOut = true; |
|
|
|
|
|
|
|
const disposables: Disposable[] = []; |
|
|
|
|
|
|
|
let token; |
|
|
|
try { |
|
|
|
const infoButton: QuickInputButton = { |
|
|
|
iconPath: new ThemeIcon(`link-external`), |
|
|
|
tooltip: 'Open Access Tokens page on GitHub', |
|
|
|
}; |
|
|
|
|
|
|
|
token = await new Promise<string | undefined>(resolve => { |
|
|
|
disposables.push( |
|
|
|
input.onDidHide(() => resolve(undefined)), |
|
|
|
input.onDidChangeValue(() => (input.validationMessage = undefined)), |
|
|
|
input.onDidAccept(() => { |
|
|
|
const value = input.value.trim(); |
|
|
|
if (!value) { |
|
|
|
input.validationMessage = 'A personal access token is required'; |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
resolve(value); |
|
|
|
}), |
|
|
|
input.onDidTriggerButton(e => { |
|
|
|
if (e === infoButton) { |
|
|
|
void env.openExternal( |
|
|
|
Uri.parse(`https://${descriptor?.domain ?? 'github.com'}/settings/tokens`), |
|
|
|
); |
|
|
|
} |
|
|
|
}), |
|
|
|
); |
|
|
|
|
|
|
|
input.password = true; |
|
|
|
input.title = `GitHub Authentication${descriptor?.domain ? ` \u2022 ${descriptor.domain}` : ''}`; |
|
|
|
input.placeholder = `Requires ${descriptor?.scopes.join(', ') ?? 'all'} scopes`; |
|
|
|
input.prompt = 'Paste your GitHub Personal Access Token'; |
|
|
|
input.buttons = [infoButton]; |
|
|
|
|
|
|
|
input.show(); |
|
|
|
}); |
|
|
|
} finally { |
|
|
|
input.dispose(); |
|
|
|
disposables.forEach(d => void d.dispose()); |
|
|
|
} |
|
|
|
|
|
|
|
if (!token) return undefined; |
|
|
|
|
|
|
|
return { |
|
|
|
id: this.getSessionId(descriptor), |
|
|
|
accessToken: token, |
|
|
|
scopes: [], |
|
|
|
account: { |
|
|
|
id: '', |
|
|
|
label: '', |
|
|
|
}, |
|
|
|
}; |
|
|
|
} |
|
|
|
} |