Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[vscode] support AuthenticationForceNewSessionOptions #12752

Merged
merged 1 commit into from
Jul 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
- [vscode] Add support for the TaskPresentationOptions close property [#12749](https://github.com/eclipse-theia/theia/pull/12749) - Contributed on behalf of STMicroelectronics

<a name="breaking_changes_1.40.0">[Breaking Changes:](#breaking_changes_1.40.0)</a>
Expand Down
29 changes: 23 additions & 6 deletions packages/plugin-ext/src/main/browser/authentication-main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import { interfaces } from '@theia/core/shared/inversify';
import { AuthenticationExt, AuthenticationMain, MAIN_RPC_CONTEXT } from '../../common/plugin-api-rpc';
import { RPCProtocol } from '../../common/rpc-protocol';
import { MessageService } from '@theia/core/lib/common/message-service';
import { Dialog, StorageService } from '@theia/core/lib/browser';
import { ConfirmDialog, Dialog, StorageService } from '@theia/core/lib/browser';
import {
AuthenticationProvider,
AuthenticationService,
Expand All @@ -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;
rschnekenbu marked this conversation as resolved.
Show resolved Hide resolved
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,12 +198,24 @@ 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> {
const msg = document.createElement('span');
msg.textContent = 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);
const choice = await this.messageService.info(message, 'Allow', 'Cancel');
return choice === 'Allow';

if (detail) {
const detailElement = document.createElement('p');
detailElement.textContent = detail;
msg.appendChild(detailElement);
}

return !!await new ConfirmDialog({
title: nls.localize('theia/plugin-ext/authentication-main/loginTitle', 'Login'),
msg,
ok: nls.localizeByDefault('Allow'),
cancel: Dialog.CANCEL
}).open();
}

protected async isAccessAllowed(providerId: string, accountName: string, extensionId: string): Promise<boolean> {
Expand All @@ -224,6 +237,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 @@ -13671,6 +13671,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 @@ -13705,7 +13716,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