mirror of
https://github.com/microsoft/vscode.git
synced 2026-08-15 18:37:00 +01:00
refactored mainthreadauth with silent option and tests (#135503)
This commit is contained in:
@@ -17,6 +17,7 @@ import { INotificationService } from 'vs/platform/notification/common/notificati
|
||||
import { fromNow } from 'vs/base/common/date';
|
||||
import { ActivationKind, IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import type { AuthenticationGetSessionOptions } from 'vscode';
|
||||
|
||||
interface TrustedExtensionsQuickPickItem {
|
||||
label: string;
|
||||
@@ -204,99 +205,67 @@ export class MainThreadAuthentication extends Disposable implements MainThreadAu
|
||||
|
||||
}
|
||||
|
||||
private async selectSession(providerId: string, extensionId: string, extensionName: string, scopes: string[], potentialSessions: readonly modes.AuthenticationSession[], clearSessionPreference: boolean, silent: boolean, showSilentPrompt: boolean): Promise<modes.AuthenticationSession | undefined> {
|
||||
if (!potentialSessions.length) {
|
||||
throw new Error('No potential sessions found');
|
||||
}
|
||||
|
||||
if (clearSessionPreference) {
|
||||
this.storageService.remove(`${extensionName}-${providerId}`, StorageScope.GLOBAL);
|
||||
} else {
|
||||
const existingSessionPreference = this.storageService.get(`${extensionName}-${providerId}`, StorageScope.GLOBAL);
|
||||
if (existingSessionPreference) {
|
||||
const matchingSession = potentialSessions.find(session => session.id === existingSessionPreference);
|
||||
if (matchingSession) {
|
||||
const allowed = this.authenticationService.isAccessAllowed(providerId, matchingSession.account.label, extensionId);
|
||||
if (!allowed) {
|
||||
if (!silent) {
|
||||
const didAcceptPrompt = await this.authenticationService.showGetSessionPrompt(providerId, matchingSession.account.label, extensionId, extensionName);
|
||||
if (!didAcceptPrompt) {
|
||||
throw new Error('User did not consent to login.');
|
||||
}
|
||||
} else {
|
||||
if (showSilentPrompt) {
|
||||
this.authenticationService.requestSessionAccess(providerId, extensionId, extensionName, scopes, potentialSessions);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
return matchingSession;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (silent) {
|
||||
this.authenticationService.requestSessionAccess(providerId, extensionId, extensionName, scopes, potentialSessions);
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return this.authenticationService.selectSession(providerId, extensionId, extensionName, scopes, potentialSessions);
|
||||
}
|
||||
|
||||
async $getSession(providerId: string, scopes: string[], extensionId: string, extensionName: string, options: { createIfNone: boolean, forceNewSession: boolean | { detail: string }, clearSessionPreference: boolean, solelyCheckExistence?: boolean }): Promise<modes.AuthenticationSession | undefined> {
|
||||
private async doGetSession(providerId: string, scopes: string[], extensionId: string, extensionName: string, options: AuthenticationGetSessionOptions): Promise<modes.AuthenticationSession | undefined> {
|
||||
const sessions = await this.authenticationService.getSessions(providerId, scopes, true);
|
||||
let silent = !options.createIfNone;
|
||||
// TODO: remove this property and implement a proper $hasSession function.
|
||||
let showSilentPrompt = !options.solelyCheckExistence;
|
||||
|
||||
// Error cases
|
||||
if (options.forceNewSession && !sessions.length) {
|
||||
throw new Error('No existing sessions found.');
|
||||
}
|
||||
if (options.forceNewSession && options.createIfNone) {
|
||||
throw new Error('Invalid combination of options. Please remove one of the following: forceNewSession, createIfNone');
|
||||
}
|
||||
if (options.forceNewSession && options.silent) {
|
||||
throw new Error('Invalid combination of options. Please remove one of the following: forceNewSession, silent');
|
||||
}
|
||||
if (options.createIfNone && options.silent) {
|
||||
throw new Error('Invalid combination of options. Please remove one of the following: createIfNone, silent');
|
||||
}
|
||||
|
||||
let session: modes.AuthenticationSession | undefined;
|
||||
// Ignore existing sessions if we are forceRecreating
|
||||
// Check if the sessions we have are valid
|
||||
if (!options.forceNewSession && sessions.length) {
|
||||
if (!this.authenticationService.supportsMultipleAccounts(providerId)) {
|
||||
session = sessions[0];
|
||||
const allowed = this.authenticationService.isAccessAllowed(providerId, session.account.label, extensionId);
|
||||
if (!allowed) {
|
||||
if (!silent) {
|
||||
const didAcceptPrompt = await this.authenticationService.showGetSessionPrompt(providerId, session.account.label, extensionId, extensionName);
|
||||
if (!didAcceptPrompt) {
|
||||
throw new Error('User did not consent to login.');
|
||||
if (this.authenticationService.supportsMultipleAccounts(providerId)) {
|
||||
if (options.clearSessionPreference) {
|
||||
this.storageService.remove(`${extensionName}-${providerId}`, StorageScope.GLOBAL);
|
||||
} else {
|
||||
const existingSessionPreference = this.storageService.get(`${extensionName}-${providerId}`, StorageScope.GLOBAL);
|
||||
if (existingSessionPreference) {
|
||||
const matchingSession = sessions.find(session => session.id === existingSessionPreference);
|
||||
if (matchingSession && this.authenticationService.isAccessAllowed(providerId, matchingSession.account.label, extensionId)) {
|
||||
return matchingSession;
|
||||
}
|
||||
} else if (allowed !== false) {
|
||||
if (showSilentPrompt) {
|
||||
this.authenticationService.requestSessionAccess(providerId, extensionId, extensionName, scopes, [session]);
|
||||
}
|
||||
return undefined;
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return this.selectSession(providerId, extensionId, extensionName, scopes, sessions, !!options.clearSessionPreference, silent, showSilentPrompt);
|
||||
}
|
||||
} else {
|
||||
// If we are forceRecreating, we need to show the prompt.
|
||||
if (options.forceNewSession || !silent) {
|
||||
const providerName = this.authenticationService.getLabel(providerId);
|
||||
const detail = (typeof options.forceNewSession === 'object') ? options.forceNewSession!.detail : undefined;
|
||||
const isAllowed = await this.loginPrompt(providerName, extensionName, !!options.forceNewSession, detail);
|
||||
if (!isAllowed) {
|
||||
throw new Error('User did not consent to login.');
|
||||
}
|
||||
|
||||
session = await this.authenticationService.createSession(providerId, scopes, true);
|
||||
await this.setTrustedExtensionAndAccountPreference(providerId, session.account.label, extensionId, extensionName, session.id);
|
||||
} else {
|
||||
if (showSilentPrompt) {
|
||||
await this.authenticationService.requestNewSession(providerId, scopes, extensionId, extensionName);
|
||||
}
|
||||
} else if (this.authenticationService.isAccessAllowed(providerId, sessions[0].account.label, extensionId)) {
|
||||
return sessions[0];
|
||||
}
|
||||
}
|
||||
|
||||
// We may need to prompt because we don't have a valid session
|
||||
// modal flows
|
||||
if (options.createIfNone || options.forceNewSession) {
|
||||
const providerName = this.authenticationService.getLabel(providerId);
|
||||
const detail = (typeof options.forceNewSession === 'object') ? options.forceNewSession!.detail : undefined;
|
||||
const isAllowed = await this.loginPrompt(providerName, extensionName, !!options.forceNewSession, detail);
|
||||
if (!isAllowed) {
|
||||
throw new Error('User did not consent to login.');
|
||||
}
|
||||
|
||||
const session = await this.authenticationService.createSession(providerId, scopes, true);
|
||||
await this.setTrustedExtensionAndAccountPreference(providerId, session.account.label, extensionId, extensionName, session.id);
|
||||
return session;
|
||||
}
|
||||
// passive flows
|
||||
if (!options.silent) {
|
||||
await this.authenticationService.requestNewSession(providerId, scopes, extensionId, extensionName);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
async $getSession(providerId: string, scopes: string[], extensionId: string, extensionName: string, options: AuthenticationGetSessionOptions): Promise<modes.AuthenticationSession | undefined> {
|
||||
const session = await this.doGetSession(providerId, scopes, extensionId, extensionName, options);
|
||||
|
||||
if (session) {
|
||||
type AuthProviderUsageClassification = {
|
||||
extensionId: { classification: 'SystemMetaData', purpose: 'FeatureInsight' };
|
||||
|
||||
Reference in New Issue
Block a user