Skip to content

Commit

Permalink
[vscode] support AuthenticationForceNewSessionOptions with detail mes…
Browse files Browse the repository at this point in the history
…sage

* Defines and supports this new type in the authentification service.
* Updates prompt when new session is forced if detail message is present.

Contributed on behalf of STMicroelectronics
  • Loading branch information
rschnekenbu committed Jul 25, 2023
1 parent 2b4fb4b commit 7d9d1d4
Show file tree
Hide file tree
Showing 4 changed files with 25 additions and 6 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
- [workspace] Implement CanonicalUriProvider API #12743 (https://github.com/eclipse-theia/theia/pull/12743 - Contributed on behalf of STMicroelectronics
- Show command shortcuts in toolbar item tooltips. #12660 (https://github.com/eclipse-theia/theia/pull/12660) - Contributed on behalf of STMicroelectronics
- [cli] added `check:theia-extensions` which checks the uniqueness of Theia extension versions [#12596](https://github.com/eclipse-theia/theia/pull/12596) - Contributed on behalf of STMicroelectronics
- [vscode] Support AuthenticationForceNewSessionOptions and detail message [#12752](https://github.com/eclipse-theia/theia/pull/12752) - Contributed on behalf of STMicroelectronics

<a name="breaking_changes_1.40.0">[Breaking Changes:](#breaking_changes_1.40.0)</a>

Expand Down
13 changes: 10 additions & 3 deletions packages/plugin-ext/src/main/browser/authentication-main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import { QuickPickService } from '@theia/core/lib/common/quick-pick-service';
import * as theia from '@theia/plugin';
import { QuickPickValue } from '@theia/core/lib/browser/quick-input/quick-input-service';
import { nls } from '@theia/core/lib/common/nls';
import { isObject } from '@theia/core';

export function getAuthenticationProviderActivationEvent(id: string): string { return `onAuthenticationRequest:${id}`; }

Expand Down Expand Up @@ -117,7 +118,7 @@ export class AuthenticationMainImpl implements AuthenticationMain {
// 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 detail = isAuthenticationForceNewSessionOptions(options.forceNewSession) ? 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.');
Expand Down Expand Up @@ -197,10 +198,12 @@ export class AuthenticationMainImpl implements AuthenticationMain {
return allow;
}

protected async loginPrompt(providerName: string, extensionName: string, recreatingSession: boolean, _detail?: string): Promise<boolean> {
const message = recreatingSession
protected async loginPrompt(providerName: string, extensionName: string, recreatingSession: boolean, detail?: string): Promise<boolean> {
let message = recreatingSession
? nls.localizeByDefault("The extension '{0}' wants you to sign in again using {1}.", extensionName, providerName)
: nls.localizeByDefault("The extension '{0}' wants to sign in using {1}.", extensionName, providerName);

message = detail ? message + ' ' + detail : message;
const choice = await this.messageService.info(message, 'Allow', 'Cancel');
return choice === 'Allow';
}
Expand All @@ -224,6 +227,10 @@ export class AuthenticationMainImpl implements AuthenticationMain {
}
}

function isAuthenticationForceNewSessionOptions(arg: unknown): arg is theia.AuthenticationForceNewSessionOptions {
return isObject<theia.AuthenticationForceNewSessionOptions>(arg) && typeof arg.detail === 'string';
}

async function addAccountUsage(storageService: StorageService, providerId: string, accountName: string, extensionId: string, extensionName: string): Promise<void> {
const accountKey = `authentication-${providerId}-${accountName}-usages`;
const usages = await readAccountUsages(storageService, providerId, accountName);
Expand Down
4 changes: 2 additions & 2 deletions packages/plugin-ext/src/plugin/authentication-ext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,12 @@ export class AuthenticationExtImpl implements AuthenticationExt {
}

async getSession(requestingExtension: InternalPlugin, providerId: string, scopes: readonly string[],
options: theia.AuthenticationGetSessionOptions & ({ createIfNone: true } | { forceNewSession: true } | { forceNewSession: { detail: string } })):
options: theia.AuthenticationGetSessionOptions & ({ createIfNone: true } | { forceNewSession: true } | { forceNewSession: theia.AuthenticationForceNewSessionOptions })):
Promise<theia.AuthenticationSession>;
async getSession(requestingExtension: InternalPlugin, providerId: string, scopes: readonly string[],
options: theia.AuthenticationGetSessionOptions & { forceNewSession: true }): Promise<theia.AuthenticationSession>;
async getSession(requestingExtension: InternalPlugin, providerId: string, scopes: readonly string[],
options: theia.AuthenticationGetSessionOptions & { forceNewSession: { detail: string } }): Promise<theia.AuthenticationSession>;
options: theia.AuthenticationGetSessionOptions & { forceNewSession: theia.AuthenticationForceNewSessionOptions }): Promise<theia.AuthenticationSession>;
async getSession(requestingExtension: InternalPlugin, providerId: string, scopes: readonly string[],
options: theia.AuthenticationGetSessionOptions): Promise<theia.AuthenticationSession | undefined>;
async getSession(requestingExtension: InternalPlugin, providerId: string, scopes: readonly string[],
Expand Down
13 changes: 12 additions & 1 deletion packages/plugin/src/theia.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13666,6 +13666,17 @@ export module '@theia/plugin' {
readonly label: string;
}

/**
* Optional options to be used when calling {@link authentication.getSession} with the flag `forceNewSession`.
*/
export interface AuthenticationForceNewSessionOptions {
/**
* An optional message that will be displayed to the user when we ask to re-authenticate. Providing additional context
* as to why you are asking a user to re-authenticate can help increase the odds that they will accept.
*/
detail?: string;
}

/**
* Options to be used when getting an {@link AuthenticationSession AuthenticationSession} from an {@link AuthenticationProvider AuthenticationProvider}.
*/
Expand Down Expand Up @@ -13700,7 +13711,7 @@ export module '@theia/plugin' {
*
* Defaults to false.
*/
forceNewSession?: boolean | { detail: string };
forceNewSession?: boolean | AuthenticationForceNewSessionOptions;

/**
* Whether we should show the indication to sign in in the Accounts menu.
Expand Down

0 comments on commit 7d9d1d4

Please sign in to comment.