From 9f2d5fc82aa2dad8a2dbffbb9c84f8e01104b8be Mon Sep 17 00:00:00 2001 From: Denis Golovin Date: Thu, 13 Oct 2022 17:01:42 -0700 Subject: [PATCH 1/2] Improve sandbox workflow and go directly to 'Copy Login Command' page Signed-off-by: Denis Golovin dgolovin@redhat.com --- src/openshift/cluster.ts | 13 ++++++++++++ src/openshift/sandbox.ts | 26 +++++++++++++++++++++++- src/webview/cluster/app/sandboxView.tsx | 23 ++++++++++++++------- src/webview/cluster/clusterViewLoader.ts | 7 +++---- 4 files changed, 57 insertions(+), 12 deletions(-) diff --git a/src/openshift/cluster.ts b/src/openshift/cluster.ts index fc2f176b5..5b5248194 100644 --- a/src/openshift/cluster.ts +++ b/src/openshift/cluster.ts @@ -351,6 +351,19 @@ export class Cluster extends OpenShiftItem { } @vsCommand('openshift.explorer.login.clipboard') + static async loginUsingClipboardToken(apiEndpointUrl: string, oauthRequestTokenUrl: string): Promise { + const clipboard = await Cluster.readFromClipboard(); + if(!clipboard) { + const choice = await window.showErrorMessage('Cannot parse token in clipboard. Please click `Get token` button below, copy token into clipboard and press `Login to Sandbox` button again.', + 'Get token'); + if (choice === 'Get token') { + await commands.executeCommand('vscode.open', Uri.parse(oauthRequestTokenUrl)); + } + return; + } + return Cluster.tokenLogin(apiEndpointUrl, true, clipboard); + } + static async loginUsingClipboardInfo(dashboardUrl: string): Promise { const clipboard = await Cluster.readFromClipboard(); if(!Cluster.ocLoginCommandMatches(clipboard)) { diff --git a/src/openshift/sandbox.ts b/src/openshift/sandbox.ts index 9549122bd..b22461939 100644 --- a/src/openshift/sandbox.ts +++ b/src/openshift/sandbox.ts @@ -5,6 +5,7 @@ import { workspace } from 'vscode'; import fetch = require('make-fetch-happen'); +import { method } from 'lodash'; // eslint-disable-next-line no-shadow export enum SBAPIEndpoint { @@ -43,6 +44,18 @@ export interface VerificationCodeResponse{ json: SBResponseData; } +export const OAUTH_SERVER_INFO_PATH = '.well-known/oauth-authorization-server'; + +export interface OauthServerInfo { + issuer: string; + authorization_endpoint: string; + token_endpoint: string; + scopes_supported: string[]; + response_types_supported: string[]; + grant_types_supported: string[]; + code_challenge_methods_supported: string[]; + } + export function getSandboxAPIUrl(): string { return workspace.getConfiguration('openshiftConnector').get('sandboxApiHostUrl'); } @@ -56,6 +69,7 @@ export interface SandboxAPI { signUp(token: string): Promise; requestVerificationCode(token: string, areaCode: string, phoneNumber: string): Promise; validateVerificationCode(token: string, code: string): Promise; + getOauthServerInfo(apiEndpointUrl: string): Promise; } export async function getSignUpStatus(token: string): Promise { @@ -112,11 +126,21 @@ export async function validateVerificationCode(token: string, code: string): Pro return validationRequestResponse.ok; } +export async function getOauthServerInfo(apiEndpointUrl: string): Promise { + const oauthServerInfoResponse = await fetch(`${apiEndpointUrl}/${OAUTH_SERVER_INFO_PATH}`, { + method: 'GET', + timeout: getSandboxAPITimeout() + }); + const oauthInfoText = await oauthServerInfoResponse.text(); + return (oauthInfoText ? JSON.parse(oauthInfoText) : {}) as OauthServerInfo; +} + export function createSandboxAPI(): SandboxAPI { return { getSignUpStatus, signUp, requestVerificationCode, - validateVerificationCode + validateVerificationCode, + getOauthServerInfo }; } diff --git a/src/webview/cluster/app/sandboxView.tsx b/src/webview/cluster/app/sandboxView.tsx index 33da91fce..449800c1b 100644 --- a/src/webview/cluster/app/sandboxView.tsx +++ b/src/webview/cluster/app/sandboxView.tsx @@ -60,6 +60,8 @@ export default function addSandboxView(props): JSX.Element { action: 'sandboxPageDetectAuthSession', statusInfo: '', consoleDashboard: '', + apiEndpoint: '', + oauthTokenEndpoint: '', errorCode: undefined }); @@ -150,6 +152,8 @@ export default function addSandboxView(props): JSX.Element { action: currentState.action, consoleDashboard: currentState.consoleDashboard, statusInfo: currentState.statusInfo, + apiEndpoint: '', + oauthTokenEndpoint: '', errorCode: undefined }); postMessage('sandboxDetectStatus'); @@ -299,6 +303,8 @@ export default function addSandboxView(props): JSX.Element { action: 'sandboxPageRequestVerificationCode', statusInfo: '', consoleDashboard: '', + apiEndpoint: '', + oauthTokenEndpoint: '', errorCode: undefined }); } @@ -376,7 +382,7 @@ export default function addSandboxView(props): JSX.Element { const Provisioned = () => { const handleLoginButton = () => { - postMessage('sandboxLoginUsingDataInClipboard', {url: currentState.consoleDashboard}); + postMessage('sandboxLoginUsingDataInClipboard', {apiEndpointUrl: currentState.apiEndpoint, oauthRequestTokenUrl: `${currentState.oauthTokenEndpoint}/request`}); }; return ( @@ -399,16 +405,19 @@ export default function addSandboxView(props): JSX.Element { Next steps to connect with Developer Sandbox:

- 1. Click on Open Dashboard button. In the browser, login using DevSandbox and once loggedin, click on username dropdown.

- 2. Select Copy Login command. Once the new tab is opened, copy the entire Log in with this token command.

- 3. Come back to IDE and press 'Login To Sandbox' Button. This will login your DevSandbox in OpenShift Application View.

+ 1. Click on Get token button. In the browser, login using DevSandbox button.

+ 2. Click on Display token link and copy token to clipboard.

+ 3. Switch back to IDE and press 'Login To DevSandbox' button. This will login you to DevSandbox with token from clipboard.

4. Once successfully logged in, start creating applications and deploy on cluster.
- + - - + + + + + )} diff --git a/src/webview/cluster/clusterViewLoader.ts b/src/webview/cluster/clusterViewLoader.ts index c5d114b48..ecde12650 100644 --- a/src/webview/cluster/clusterViewLoader.ts +++ b/src/webview/cluster/clusterViewLoader.ts @@ -108,7 +108,8 @@ async function clusterEditorMessageListener (event: any ): Promise { panel.webview.postMessage({action: 'sandboxPageRequestSignup'}); } else { if (signupStatus.status.ready) { - panel.webview.postMessage({action: 'sandboxPageProvisioned', statusInfo: signupStatus.username, consoleDashboard: signupStatus.consoleURL }); + const oauthInfo = await sandboxAPI.getOauthServerInfo(signupStatus.apiEndpoint); + panel.webview.postMessage({action: 'sandboxPageProvisioned', statusInfo: signupStatus.username, consoleDashboard: signupStatus.consoleURL, apiEndpoint: signupStatus.apiEndpoint, oauthTokenEndpoint: oauthInfo.token_endpoint }); } else { // cluster is not ready and the reason is if (signupStatus.status.verificationRequired) { @@ -118,8 +119,6 @@ async function clusterEditorMessageListener (event: any ): Promise { // if (signupStatus.status.reason === 'PendingApproval') { panel.webview.postMessage({action: 'sandboxPageWaitingForApproval'}); - } else if (signupStatus.status.reason === 'Provisioned') { - panel.webview.postMessage({action: 'sandboxPageProvisioned', statusInfo: signupStatus.username, consoleDashboard: signupStatus.consoleURL}); } else { panel.webview.postMessage({action: 'sandboxPageWaitingForProvision'}) } @@ -174,7 +173,7 @@ async function clusterEditorMessageListener (event: any ): Promise { case 'sandboxLoginUsingDataInClipboard': const telemetryEventLoginToSandbox = new ExtCommandTelemetryEvent('openshift.explorer.addCluster.sandboxLoginUsingDataInClipboard'); try { - const result = await Cluster.loginUsingClipboardInfo(event.payload.url); + const result = await Cluster.loginUsingClipboardToken(event.payload.apiEndpointUrl, event.payload.oauthRequestTokenUrl); if (result) vscode.window.showInformationMessage(`${result}`); telemetryEventLoginToSandbox.send(); } catch (err) { From 4b745d72c47ec5512344eda98aad64b842afbba1 Mon Sep 17 00:00:00 2001 From: Denis Golovin Date: Thu, 13 Oct 2022 22:40:04 -0700 Subject: [PATCH 2/2] Fix eslint errors Signed-off-by: Denis Golovin dgolovin@redhat.com --- src/openshift/sandbox.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/openshift/sandbox.ts b/src/openshift/sandbox.ts index b22461939..f57e2ae91 100644 --- a/src/openshift/sandbox.ts +++ b/src/openshift/sandbox.ts @@ -5,7 +5,6 @@ import { workspace } from 'vscode'; import fetch = require('make-fetch-happen'); -import { method } from 'lodash'; // eslint-disable-next-line no-shadow export enum SBAPIEndpoint {