Skip to content
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
13 changes: 13 additions & 0 deletions src/openshift/cluster.ts
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,19 @@ export class Cluster extends OpenShiftItem {
}

@vsCommand('openshift.explorer.login.clipboard')
static async loginUsingClipboardToken(apiEndpointUrl: string, oauthRequestTokenUrl: string): Promise<string | null> {
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<string | null> {
const clipboard = await Cluster.readFromClipboard();
if(!Cluster.ocLoginCommandMatches(clipboard)) {
Expand Down
25 changes: 24 additions & 1 deletion src/openshift/sandbox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,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');
}
Expand All @@ -56,6 +68,7 @@ export interface SandboxAPI {
signUp(token: string): Promise<boolean>;
requestVerificationCode(token: string, areaCode: string, phoneNumber: string): Promise<VerificationCodeResponse>;
validateVerificationCode(token: string, code: string): Promise<boolean>;
getOauthServerInfo(apiEndpointUrl: string): Promise<OauthServerInfo>;
}

export async function getSignUpStatus(token: string): Promise<SBSignupResponse | undefined> {
Expand Down Expand Up @@ -112,11 +125,21 @@ export async function validateVerificationCode(token: string, code: string): Pro
return validationRequestResponse.ok;
}

export async function getOauthServerInfo(apiEndpointUrl: string): Promise<OauthServerInfo> {
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
};
}
23 changes: 16 additions & 7 deletions src/webview/cluster/app/sandboxView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ export default function addSandboxView(props): JSX.Element {
action: 'sandboxPageDetectAuthSession',
statusInfo: '',
consoleDashboard: '',
apiEndpoint: '',
oauthTokenEndpoint: '',
errorCode: undefined
});

Expand Down Expand Up @@ -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');
Expand Down Expand Up @@ -299,6 +303,8 @@ export default function addSandboxView(props): JSX.Element {
action: 'sandboxPageRequestVerificationCode',
statusInfo: '',
consoleDashboard: '',
apiEndpoint: '',
oauthTokenEndpoint: '',
errorCode: undefined
});
}
Expand Down Expand Up @@ -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 (
Expand All @@ -399,16 +405,19 @@ export default function addSandboxView(props): JSX.Element {
</Typography>
<Typography variant="caption" display="block" style={{ textAlign:'left', margin: '20px 70px' }}>
Next steps to connect with Developer Sandbox:<br></br>
1. Click on <strong>Open Dashboard button</strong>. In the browser, login using <strong>DevSandbox</strong> and once loggedin, click on username dropdown.<br></br>
2. Select <strong>Copy Login command</strong>. Once the new tab is opened, copy the entire <strong>Log in with this token</strong> command.<br></br>
3. Come back to IDE and press <strong>'Login To Sandbox'</strong> Button. This will login your DevSandbox in OpenShift Application View.<br></br>
1. Click on <strong>Get token</strong> button. In the browser, login using <strong>DevSandbox</strong> button.<br></br>
2. Click on <strong>Display token</strong> link and copy token to clipboard.<br></br>
3. Switch back to IDE and press <strong>'Login To DevSandbox'</strong> button. This will login you to DevSandbox with token from clipboard.<br></br>
4. Once successfully logged in, start creating applications and deploy on cluster.
</Typography>
<Tooltip title="Launch your Sandbox console in browser" placement="bottom">
<Tooltip title="Launch your DevSandbox console in browser" placement="bottom">
<Button variant="contained" className={classes.button} href={currentState.consoleDashboard}>Open Dashboard</Button>
</Tooltip>
<Tooltip title="Connect in OpenShift Application View" placement="bottom">
<Button variant="contained" className={classes.buttonSecondary} onClick={handleLoginButton}>Login to Sandbox</Button>
<Tooltip title="Copy token from DevSandbox console page in browser" placement="bottom">
<Button variant="contained" className={classes.button} href={`${currentState.oauthTokenEndpoint}/request`}>Get token</Button>
</Tooltip>
<Tooltip title="Login to DevSandbox OpenShift cluster with token from clipboard" placement="bottom">
<Button variant="contained" className={classes.buttonSecondary} onClick={handleLoginButton}>Login to DevSandbox</Button>
</Tooltip>
</div>
)}
Expand Down
7 changes: 3 additions & 4 deletions src/webview/cluster/clusterViewLoader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,8 @@ async function clusterEditorMessageListener (event: any ): Promise<any> {
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) {
Expand All @@ -118,8 +119,6 @@ async function clusterEditorMessageListener (event: any ): Promise<any> {
//
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'})
}
Expand Down Expand Up @@ -174,7 +173,7 @@ async function clusterEditorMessageListener (event: any ): Promise<any> {
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) {
Expand Down