Skip to content

Commit

Permalink
Expose functions under authentication namespace instead of providers …
Browse files Browse the repository at this point in the history
…array, #88309
  • Loading branch information
Rachel Macfarlane committed Mar 6, 2020
1 parent 223a90d commit 6f230c5
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 49 deletions.
30 changes: 27 additions & 3 deletions src/vs/vscode.proposed.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ declare module 'vscode' {
readonly added: string[];

/**
* The ids of the [authenticationProvider](#AuthenticationProvider)s that have been removed..
* The ids of the [authenticationProvider](#AuthenticationProvider)s that have been removed.
*/
readonly removed: string[];
}
Expand All @@ -50,7 +50,7 @@ declare module 'vscode' {
readonly displayName: string;

/**
* A [enent](#Event) which fires when the array of sessions has changed, or data
* A [event](#Event) which fires when the array of sessions has changed, or data

This comment has been minimized.

Copy link
@KamasamaK

KamasamaK Mar 9, 2020

An event

This comment has been minimized.

Copy link
@RMacfarlane

RMacfarlane Mar 9, 2020

Contributor

Thanks, will fix!

* within a session has changed.
*/
readonly onDidChangeSessions: Event<void>;
Expand All @@ -75,7 +75,31 @@ declare module 'vscode' {
*/
export const onDidChangeAuthenticationProviders: Event<AuthenticationProvidersChangeEvent>;

export const providers: ReadonlyArray<AuthenticationProvider>;
/**
* Returns whether a provider with providerId is currently registered.
*/
export function hasProvider(providerId: string): boolean;

/**
* Get existing authentication sessions. Rejects if a provider with providerId is not
* registered, or if the user does not consent to sharing authentication information with
* the extension.
*/
export function getSessions(providerId: string): Thenable<readonly AuthenticationSession[]>;

/**
* Prompt a user to login to create a new authenticaiton session. Rejects if a provider with
* providerId is not registered, or if the user does not consent to sharing authentication
* information with the extension.
*/
export function login(providerId: string, scopes: string[]): Thenable<AuthenticationSession>;

/**
* A [event](#Event) which fires when the array of sessions has changed, or data
* within a session has changed for a provider. Fires with the ids of the providers
* that have had session data change.
*/
export const onDidChangeSessions: Event<string[]>;
}

//#endregion
Expand Down
17 changes: 13 additions & 4 deletions src/vs/workbench/api/common/extHost.api.impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -185,12 +185,21 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
registerAuthenticationProvider(provider: vscode.AuthenticationProvider): vscode.Disposable {
return extHostAuthentication.registerAuthenticationProvider(provider);
},
get providers() {
return extHostAuthentication.providers(extension);
},
get onDidChangeAuthenticationProviders(): Event<vscode.AuthenticationProvidersChangeEvent> {
return extHostAuthentication.onDidChangeAuthenticationProviders;
}
},
hasProvider(providerId: string): boolean {
return extHostAuthentication.hasProvider(providerId);
},
getSessions(providerId: string): Thenable<readonly vscode.AuthenticationSession[]> {
return extHostAuthentication.getSessions(extension, providerId);
},
login(providerId: string, scopes: string[]): Thenable<vscode.AuthenticationSession> {
return extHostAuthentication.login(extension, providerId, scopes);
},
get onDidChangeSessions(): Event<string[]> {
return extHostAuthentication.onDidChangeSessions;
},
};

// namespace: commands
Expand Down
73 changes: 31 additions & 42 deletions src/vs/workbench/api/common/extHostAuthentication.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,36 +10,41 @@ import { IMainContext, MainContext, MainThreadAuthenticationShape, ExtHostAuthen
import { Disposable } from 'vs/workbench/api/common/extHostTypes';
import { IExtensionDescription, ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';

export class AuthenticationProviderWrapper implements vscode.AuthenticationProvider {
readonly onDidChangeSessions: vscode.Event<void>;
export class ExtHostAuthentication implements ExtHostAuthenticationShape {
private _proxy: MainThreadAuthenticationShape;
private _authenticationProviders: Map<string, vscode.AuthenticationProvider> = new Map<string, vscode.AuthenticationProvider>();

constructor(private _requestingExtension: IExtensionDescription,
private _provider: vscode.AuthenticationProvider,
private _proxy: MainThreadAuthenticationShape) {
private _onDidChangeAuthenticationProviders = new Emitter<vscode.AuthenticationProvidersChangeEvent>();
readonly onDidChangeAuthenticationProviders: Event<vscode.AuthenticationProvidersChangeEvent> = this._onDidChangeAuthenticationProviders.event;

this.onDidChangeSessions = this._provider.onDidChangeSessions;
}
private _onDidChangeSessions = new Emitter<string[]>();
readonly onDidChangeSessions: Event<string[]> = this._onDidChangeSessions.event;

get id(): string {
return this._provider.id;
constructor(mainContext: IMainContext) {
this._proxy = mainContext.getProxy(MainContext.MainThreadAuthentication);
}

get displayName(): string {
return this._provider.displayName;
hasProvider(providerId: string): boolean {
return !!this._authenticationProviders.get(providerId);
}

async getSessions(): Promise<ReadonlyArray<vscode.AuthenticationSession>> {
return (await this._provider.getSessions()).map(session => {
async getSessions(requestingExtension: IExtensionDescription, providerId: string): Promise<readonly vscode.AuthenticationSession[]> {
const provider = this._authenticationProviders.get(providerId);
if (!provider) {
throw new Error(`No authentication provider with id '${providerId}' is currently registered.`);
}

return (await provider.getSessions()).map(session => {
return {
id: session.id,
accountName: session.accountName,
scopes: session.scopes,
getAccessToken: async () => {
const isAllowed = await this._proxy.$getSessionsPrompt(
this._provider.id,
this.displayName,
ExtensionIdentifier.toKey(this._requestingExtension.identifier),
this._requestingExtension.displayName || this._requestingExtension.name);
provider.id,
provider.displayName,
ExtensionIdentifier.toKey(requestingExtension.identifier),
requestingExtension.displayName || requestingExtension.name);

if (!isAllowed) {
throw new Error('User did not consent to token access.');
Expand All @@ -51,35 +56,18 @@ export class AuthenticationProviderWrapper implements vscode.AuthenticationProvi
});
}

async login(scopes: string[]): Promise<vscode.AuthenticationSession> {
const isAllowed = await this._proxy.$loginPrompt(this._provider.id, this.displayName, ExtensionIdentifier.toKey(this._requestingExtension.identifier), this._requestingExtension.displayName || this._requestingExtension.name);
async login(requestingExtension: IExtensionDescription, providerId: string, scopes: string[]): Promise<vscode.AuthenticationSession> {
const provider = this._authenticationProviders.get(providerId);
if (!provider) {
throw new Error(`No authentication provider with id '${providerId}' is currently registered.`);
}

const isAllowed = await this._proxy.$loginPrompt(provider.id, provider.displayName, ExtensionIdentifier.toKey(requestingExtension.identifier), requestingExtension.displayName || requestingExtension.name);
if (!isAllowed) {
throw new Error('User did not consent to login.');
}

return this._provider.login(scopes);
}

logout(sessionId: string): Thenable<void> {
return this._provider.logout(sessionId);
}
}

export class ExtHostAuthentication implements ExtHostAuthenticationShape {
private _proxy: MainThreadAuthenticationShape;
private _authenticationProviders: Map<string, vscode.AuthenticationProvider> = new Map<string, vscode.AuthenticationProvider>();

private _onDidChangeAuthenticationProviders = new Emitter<vscode.AuthenticationProvidersChangeEvent>();
readonly onDidChangeAuthenticationProviders: Event<vscode.AuthenticationProvidersChangeEvent> = this._onDidChangeAuthenticationProviders.event;

constructor(mainContext: IMainContext) {
this._proxy = mainContext.getProxy(MainContext.MainThreadAuthentication);
}

providers(requestingExtension: IExtensionDescription): vscode.AuthenticationProvider[] {
let providers: vscode.AuthenticationProvider[] = [];
this._authenticationProviders.forEach(provider => providers.push(new AuthenticationProviderWrapper(requestingExtension, provider, this._proxy)));
return providers;
return provider.login(scopes);
}

registerAuthenticationProvider(provider: vscode.AuthenticationProvider): vscode.Disposable {
Expand All @@ -91,6 +79,7 @@ export class ExtHostAuthentication implements ExtHostAuthenticationShape {

const listener = provider.onDidChangeSessions(_ => {
this._proxy.$onDidChangeSessions(provider.id);
this._onDidChangeSessions.fire([provider.id]);
});

this._proxy.$registerAuthenticationProvider(provider.id, provider.displayName);
Expand Down

0 comments on commit 6f230c5

Please sign in to comment.