mirror of
https://github.com/microsoft/vscode.git
synced 2025-12-24 20:26:08 +00:00
Show sign in entry for all auth providers in accounts menu, fixes #94488
This commit is contained in:
@@ -18,11 +18,13 @@ export async function activate(context: vscode.ExtensionContext) {
|
||||
vscode.authentication.registerAuthenticationProvider({
|
||||
id: 'github',
|
||||
displayName: 'GitHub',
|
||||
supportsMultipleAccounts: false,
|
||||
onDidChangeSessions: onDidChangeSessions.event,
|
||||
getSessions: () => Promise.resolve(loginService.sessions),
|
||||
login: async (scopeList: string[]) => {
|
||||
login: async (scopeList: string[] | undefined) => {
|
||||
try {
|
||||
const session = await loginService.login(scopeList.join(' '));
|
||||
const loginScopes = scopeList ? scopeList.sort().join(' ') : 'user:email';
|
||||
const session = await loginService.login(loginScopes);
|
||||
Logger.info('Login success!');
|
||||
onDidChangeSessions.fire({ added: [session.id], removed: [], changed: [] });
|
||||
return session;
|
||||
|
||||
@@ -20,17 +20,15 @@ export async function activate(context: vscode.ExtensionContext) {
|
||||
context.subscriptions.push(vscode.authentication.registerAuthenticationProvider({
|
||||
id: 'microsoft',
|
||||
displayName: 'Microsoft',
|
||||
supportsMultipleAccounts: true,
|
||||
onDidChangeSessions: onDidChangeSessions.event,
|
||||
getSessions: () => Promise.resolve(loginService.sessions),
|
||||
login: async (scopes: string[]) => {
|
||||
try {
|
||||
await loginService.login(scopes.sort().join(' '));
|
||||
const session = loginService.sessions[loginService.sessions.length - 1];
|
||||
onDidChangeSessions.fire({ added: [session.id], removed: [], changed: [] });
|
||||
return loginService.sessions[0]!;
|
||||
} catch (e) {
|
||||
throw e;
|
||||
}
|
||||
login: async (scopes: string[] | undefined) => {
|
||||
const loginScopes = scopes ? scopes.sort().join(' ') : 'https://management.core.windows.net/.default offline_access';
|
||||
await loginService.login(loginScopes);
|
||||
const session = loginService.sessions[loginService.sessions.length - 1];
|
||||
onDidChangeSessions.fire({ added: [session.id], removed: [], changed: [] });
|
||||
return loginService.sessions[0]!;
|
||||
},
|
||||
logout: async (id: string) => {
|
||||
await loginService.logout(id);
|
||||
|
||||
8
src/vs/vscode.proposed.d.ts
vendored
8
src/vs/vscode.proposed.d.ts
vendored
@@ -74,6 +74,12 @@ declare module 'vscode' {
|
||||
readonly id: string;
|
||||
readonly displayName: string;
|
||||
|
||||
/**
|
||||
* Whether the authentication provider supports the user being logged into
|
||||
* multiple different accounts at the same time.
|
||||
*/
|
||||
supportsMultipleAccounts: boolean;
|
||||
|
||||
/**
|
||||
* An [event](#Event) which fires when the array of sessions has changed, or data
|
||||
* within a session has changed.
|
||||
@@ -88,7 +94,7 @@ declare module 'vscode' {
|
||||
/**
|
||||
* Prompts a user to login.
|
||||
*/
|
||||
login(scopes: string[]): Thenable<AuthenticationSession>;
|
||||
login(scopes?: string[]): Thenable<AuthenticationSession>;
|
||||
logout(sessionId: string): Thenable<void>;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,22 +17,6 @@ import { CommandsRegistry } from 'vs/platform/commands/common/commands';
|
||||
import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
|
||||
interface AuthDependent {
|
||||
providerId: string;
|
||||
label: string;
|
||||
scopes: string[];
|
||||
scopeDescriptions?: string;
|
||||
}
|
||||
|
||||
const BUILT_IN_AUTH_DEPENDENTS: AuthDependent[] = [
|
||||
{
|
||||
providerId: 'microsoft',
|
||||
label: 'Settings sync',
|
||||
scopes: ['https://management.core.windows.net/.default', 'offline_access'],
|
||||
scopeDescriptions: 'Read user email'
|
||||
}
|
||||
];
|
||||
|
||||
interface AllowedExtension {
|
||||
id: string;
|
||||
name: string;
|
||||
@@ -74,12 +58,13 @@ export class MainThreadAuthenticationProvider extends Disposable {
|
||||
private _accounts = new Map<string, string[]>(); // Map account name to session ids
|
||||
private _sessions = new Map<string, string>(); // Map account id to name
|
||||
private _signInMenuItem: IMenuItem | undefined;
|
||||
private _signInMenuDisposables: IDisposable[] = [];
|
||||
|
||||
constructor(
|
||||
private readonly _proxy: ExtHostAuthenticationShape,
|
||||
public readonly id: string,
|
||||
public readonly displayName: string,
|
||||
public readonly dependents: AuthDependent[],
|
||||
private readonly supportsMultipleAccounts: boolean,
|
||||
private readonly notificationService: INotificationService
|
||||
) {
|
||||
super();
|
||||
@@ -135,29 +120,33 @@ export class MainThreadAuthenticationProvider extends Disposable {
|
||||
quickPick.show();
|
||||
}
|
||||
|
||||
private createSignInMenu(hasSessions: boolean): void {
|
||||
this._signInMenuDisposables.push(CommandsRegistry.registerCommand({
|
||||
id: `signIn${this.id}`,
|
||||
handler: (accessor, args) => {
|
||||
this.login();
|
||||
},
|
||||
}));
|
||||
|
||||
this._signInMenuItem = {
|
||||
group: '2_providers',
|
||||
command: {
|
||||
id: `signIn${this.id}`,
|
||||
title: hasSessions
|
||||
? nls.localize('addAnotherAccount', "Sign in to another {0} account", this.displayName)
|
||||
: nls.localize('addAccount', "Sign in to {0}", this.displayName)
|
||||
},
|
||||
order: 3
|
||||
};
|
||||
|
||||
this._signInMenuDisposables.push(MenuRegistry.appendMenuItem(MenuId.AccountsContext, this._signInMenuItem));
|
||||
}
|
||||
|
||||
private async registerCommandsAndContextMenuItems(): Promise<void> {
|
||||
const sessions = await this._proxy.$getSessions(this.id);
|
||||
|
||||
if (this.dependents.length) {
|
||||
this._register(CommandsRegistry.registerCommand({
|
||||
id: `signIn${this.id}`,
|
||||
handler: (accessor, args) => {
|
||||
this.login(this.dependents.reduce((previous: string[], current) => previous.concat(current.scopes), []));
|
||||
},
|
||||
}));
|
||||
|
||||
this._signInMenuItem = {
|
||||
group: '2_providers',
|
||||
command: {
|
||||
id: `signIn${this.id}`,
|
||||
title: sessions.length
|
||||
? nls.localize('addAnotherAccount', "Sign in to another {0} account", this.displayName)
|
||||
: nls.localize('addAccount', "Sign in to {0}", this.displayName)
|
||||
},
|
||||
order: 3
|
||||
};
|
||||
|
||||
this._register(MenuRegistry.appendMenuItem(MenuId.AccountsContext, this._signInMenuItem));
|
||||
if (!sessions.length || (sessions.length && this.supportsMultipleAccounts)) {
|
||||
this.createSignInMenu(!!sessions.length);
|
||||
}
|
||||
|
||||
sessions.forEach(session => this.registerSession(session));
|
||||
@@ -261,6 +250,8 @@ export class MainThreadAuthenticationProvider extends Disposable {
|
||||
|
||||
if (this._signInMenuItem) {
|
||||
this._signInMenuItem.command.title = nls.localize('addAccount', "Sign in to {0}", this.displayName);
|
||||
} else {
|
||||
this.createSignInMenu(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -269,11 +260,16 @@ export class MainThreadAuthenticationProvider extends Disposable {
|
||||
addedSessions.forEach(session => this.registerSession(session));
|
||||
|
||||
if (addedSessions.length && this._signInMenuItem) {
|
||||
this._signInMenuItem.command.title = nls.localize('addAnotherAccount', "Sign in to another {0} account", this.displayName);
|
||||
if (this.supportsMultipleAccounts) {
|
||||
this._signInMenuItem.command.title = nls.localize('addAnotherAccount', "Sign in to another {0} account", this.displayName);
|
||||
} else {
|
||||
this._signInMenuDisposables.forEach(item => item.dispose());
|
||||
this._signInMenuItem = undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
login(scopes: string[]): Promise<modes.AuthenticationSession> {
|
||||
login(scopes?: string[]): Promise<modes.AuthenticationSession> {
|
||||
return this._proxy.$login(this.id, scopes).then(session => {
|
||||
return {
|
||||
id: session.id,
|
||||
@@ -292,6 +288,7 @@ export class MainThreadAuthenticationProvider extends Disposable {
|
||||
super.dispose();
|
||||
this._sessionMenuItems.forEach(item => item.forEach(d => d.dispose()));
|
||||
this._sessionMenuItems.clear();
|
||||
this._signInMenuDisposables.forEach(item => item.dispose());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -310,10 +307,8 @@ export class MainThreadAuthentication extends Disposable implements MainThreadAu
|
||||
this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostAuthentication);
|
||||
}
|
||||
|
||||
async $registerAuthenticationProvider(id: string, displayName: string): Promise<void> {
|
||||
const dependentBuiltIns = BUILT_IN_AUTH_DEPENDENTS.filter(dependency => dependency.providerId === id);
|
||||
|
||||
const provider = new MainThreadAuthenticationProvider(this._proxy, id, displayName, dependentBuiltIns, this.notificationService);
|
||||
async $registerAuthenticationProvider(id: string, displayName: string, supportsMultipleAccounts: boolean): Promise<void> {
|
||||
const provider = new MainThreadAuthenticationProvider(this._proxy, id, displayName, supportsMultipleAccounts, this.notificationService);
|
||||
this.authenticationService.registerAuthenticationProvider(id, provider);
|
||||
}
|
||||
|
||||
|
||||
@@ -155,7 +155,7 @@ export interface MainThreadCommentsShape extends IDisposable {
|
||||
}
|
||||
|
||||
export interface MainThreadAuthenticationShape extends IDisposable {
|
||||
$registerAuthenticationProvider(id: string, displayName: string): void;
|
||||
$registerAuthenticationProvider(id: string, displayName: string, supportsMultipleAccounts: boolean): void;
|
||||
$unregisterAuthenticationProvider(id: string): void;
|
||||
$onDidChangeSessions(providerId: string, event: modes.AuthenticationSessionsChangeEvent): void;
|
||||
$getSessionsPrompt(providerId: string, accountName: string, providerName: string, extensionId: string, extensionName: string): Promise<boolean>;
|
||||
@@ -997,7 +997,7 @@ export interface ExtHostLabelServiceShape {
|
||||
export interface ExtHostAuthenticationShape {
|
||||
$getSessions(id: string): Promise<ReadonlyArray<modes.AuthenticationSession>>;
|
||||
$getSessionAccessToken(id: string, sessionId: string): Promise<string>;
|
||||
$login(id: string, scopes: string[]): Promise<modes.AuthenticationSession>;
|
||||
$login(id: string, scopes: string[] | undefined): Promise<modes.AuthenticationSession>;
|
||||
$logout(id: string, sessionId: string): Promise<void>;
|
||||
}
|
||||
|
||||
|
||||
@@ -114,7 +114,7 @@ export class ExtHostAuthentication implements ExtHostAuthenticationShape {
|
||||
this._onDidChangeSessions.fire({ [provider.id]: e });
|
||||
});
|
||||
|
||||
this._proxy.$registerAuthenticationProvider(provider.id, provider.displayName);
|
||||
this._proxy.$registerAuthenticationProvider(provider.id, provider.displayName, provider.supportsMultipleAccounts);
|
||||
this._onDidChangeAuthenticationProviders.fire({ added: [provider.id], removed: [] });
|
||||
|
||||
return new Disposable(() => {
|
||||
@@ -125,7 +125,7 @@ export class ExtHostAuthentication implements ExtHostAuthenticationShape {
|
||||
});
|
||||
}
|
||||
|
||||
$login(providerId: string, scopes: string[]): Promise<modes.AuthenticationSession> {
|
||||
$login(providerId: string, scopes: string[] | undefined): Promise<modes.AuthenticationSession> {
|
||||
const authProvider = this._authenticationProviders.get(providerId);
|
||||
if (authProvider) {
|
||||
return Promise.resolve(authProvider.login(scopes));
|
||||
|
||||
@@ -60,7 +60,7 @@ export class AuthenticationService extends Disposable implements IAuthentication
|
||||
this._authenticationProviders.set(id, authenticationProvider);
|
||||
this._onDidRegisterAuthenticationProvider.fire(id);
|
||||
|
||||
if (authenticationProvider.dependents.length && this._placeholderMenuItem) {
|
||||
if (this._placeholderMenuItem) {
|
||||
this._placeholderMenuItem.dispose();
|
||||
this._placeholderMenuItem = undefined;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user