| | import {
|
| | authentication,
|
| | AuthenticationGetSessionOptions,
|
| | AuthenticationProvider,
|
| | AuthenticationProviderAuthenticationSessionsChangeEvent,
|
| | AuthenticationSession,
|
| | Disposable,
|
| | Event,
|
| | EventEmitter,
|
| | SecretStorage,
|
| | window,
|
| | } from 'vscode';
|
| |
|
| | class AzureDevOpsPatSession implements AuthenticationSession {
|
| |
|
| | readonly account = { id: AzureDevOpsAuthenticationProvider.id, label: 'Personal Access Token' };
|
| |
|
| | readonly id = AzureDevOpsAuthenticationProvider.id;
|
| |
|
| | readonly scopes = [];
|
| |
|
| | |
| | |
| | |
| |
|
| | constructor(public readonly accessToken: string) { }
|
| | }
|
| |
|
| | export class AzureDevOpsAuthenticationProvider implements AuthenticationProvider, Disposable {
|
| | static id = 'azuredevopspat';
|
| | private static secretKey = 'AzureDevOpsPAT';
|
| |
|
| |
|
| |
|
| | private currentToken: Promise<string | undefined> | undefined;
|
| | private initializedDisposable: Disposable | undefined;
|
| |
|
| | private _onDidChangeSessions = new EventEmitter<AuthenticationProviderAuthenticationSessionsChangeEvent>();
|
| | get onDidChangeSessions(): Event<AuthenticationProviderAuthenticationSessionsChangeEvent> {
|
| | return this._onDidChangeSessions.event;
|
| | }
|
| |
|
| | constructor(private readonly secretStorage: SecretStorage) { }
|
| |
|
| | dispose(): void {
|
| | this.initializedDisposable?.dispose();
|
| | }
|
| |
|
| | private ensureInitialized(): void {
|
| | if (this.initializedDisposable === undefined) {
|
| | void this.cacheTokenFromStorage();
|
| |
|
| | this.initializedDisposable = Disposable.from(
|
| |
|
| |
|
| | this.secretStorage.onDidChange(e => {
|
| | if (e.key === AzureDevOpsAuthenticationProvider.secretKey) {
|
| | void this.checkForUpdates();
|
| | }
|
| | }),
|
| |
|
| | authentication.onDidChangeSessions(e => {
|
| | if (e.provider.id === AzureDevOpsAuthenticationProvider.id) {
|
| | void this.checkForUpdates();
|
| | }
|
| | }),
|
| | );
|
| | }
|
| | }
|
| |
|
| |
|
| |
|
| | private async checkForUpdates(): Promise<void> {
|
| | const added: AuthenticationSession[] = [];
|
| | const removed: AuthenticationSession[] = [];
|
| | const changed: AuthenticationSession[] = [];
|
| |
|
| | const previousToken = await this.currentToken;
|
| | const session = (await this.getSessions(undefined))[0];
|
| |
|
| | if (session?.accessToken && !previousToken) {
|
| | added.push(session);
|
| | } else if (!session?.accessToken && previousToken) {
|
| | removed.push(session);
|
| | } else if (session?.accessToken !== previousToken) {
|
| | changed.push(session);
|
| | } else {
|
| | return;
|
| | }
|
| |
|
| | void this.cacheTokenFromStorage();
|
| | this._onDidChangeSessions.fire({ added: added, removed: removed, changed: changed });
|
| | }
|
| |
|
| | private cacheTokenFromStorage() {
|
| | this.currentToken = this.secretStorage.get(AzureDevOpsAuthenticationProvider.secretKey) as Promise<string | undefined>;
|
| | return this.currentToken;
|
| | }
|
| |
|
| |
|
| | async getSessions(_scopes: string[] | undefined, _options?: AuthenticationGetSessionOptions): Promise<AuthenticationSession[]> {
|
| | this.ensureInitialized();
|
| | const token = await this.cacheTokenFromStorage();
|
| | return token ? [new AzureDevOpsPatSession(token)] : [];
|
| | }
|
| |
|
| |
|
| |
|
| |
|
| |
|
| | async createSession(_scopes: string[]): Promise<AuthenticationSession> {
|
| | this.ensureInitialized();
|
| |
|
| |
|
| | const token = await window.showInputBox({
|
| | ignoreFocusOut: true,
|
| | placeHolder: 'Personal access token',
|
| | prompt: 'Enter an Azure DevOps Personal Access Token (PAT).',
|
| | password: true,
|
| | });
|
| |
|
| |
|
| | if (!token) {
|
| | throw new Error('PAT is required');
|
| | }
|
| |
|
| |
|
| | await this.secretStorage.store(AzureDevOpsAuthenticationProvider.secretKey, token);
|
| | console.log('Successfully logged in to Azure DevOps');
|
| |
|
| | return new AzureDevOpsPatSession(token);
|
| | }
|
| |
|
| |
|
| | async removeSession(_sessionId: string): Promise<void> {
|
| | const token = await this.currentToken;
|
| | if (!token) {
|
| | return;
|
| | }
|
| | await this.secretStorage.delete(AzureDevOpsAuthenticationProvider.secretKey);
|
| | this._onDidChangeSessions.fire({
|
| | removed: [new AzureDevOpsPatSession(token)],
|
| | added: [],
|
| | changed: [],
|
| | });
|
| | }
|
| | }
|
| |
|