Skip to content

Commit d94e1ad

Browse files
committed
Use the value saved in the clipboard when logging in using a token redhat-developer#4165
Fixes: redhat-developer#4165 Signed-off-by: Victor Rubezhny <[email protected]>
1 parent 5d47695 commit d94e1ad

File tree

3 files changed

+48
-23
lines changed

3 files changed

+48
-23
lines changed

Diff for: src/openshift/cluster.ts

+12-21
Original file line numberDiff line numberDiff line change
@@ -935,13 +935,11 @@ export class Cluster extends OpenShiftItem {
935935
}
936936

937937
static async readFromClipboard(): Promise<string> {
938-
let r = '';
939938
try {
940-
r = await env.clipboard.readText();
939+
return await env.clipboard.readText();
941940
} catch (ignore) {
942-
// ignore exceptions and return empty string
941+
return '';
943942
}
944-
return r;
945943
}
946944

947945
static async getUrlFromClipboard(): Promise<string | null> {
@@ -952,41 +950,35 @@ export class Cluster extends OpenShiftItem {
952950
return null;
953951
}
954952

953+
static async getTokenFromClipboard(): Promise<string> {
954+
const clipboard = (await Cluster.readFromClipboard()).trim();
955+
return Cluster.validateLoginToken(clipboard) ? clipboard : '';
956+
}
957+
955958
@vsCommand('openshift.explorer.login.tokenLogin')
956959
static async tokenLogin(
957960
userClusterUrl: string,
958961
skipConfirmation = false,
959962
userToken?: string,
960963
abortController?: AbortController
961964
): Promise<string | null> {
962-
let token: string;
963965
const response = await Cluster.requestLoginConfirmation(skipConfirmation);
964966

965967
if (response !== 'Yes') return null;
966968

967969
let clusterURL = userClusterUrl;
968-
let clusterUrlFromClipboard: string;
969-
970-
if (!clusterURL) {
971-
clusterUrlFromClipboard = await Cluster.getUrlFromClipboard();
972-
}
973-
974-
if (
975-
(!clusterURL && clusterUrlFromClipboard) ||
976-
clusterURL?.trim() === clusterUrlFromClipboard
977-
) {
978-
token = NameValidator.getToken(await Cluster.readFromClipboard());
979-
clusterURL = clusterUrlFromClipboard;
980-
}
981970

982971
if (!clusterURL) {
983972
clusterURL = await Cluster.getUrl(abortController);
984973
}
985974

975+
if (!clusterURL) return null;
976+
986977
let ocToken: string;
987978
if (!userToken) {
988979
const prompt = 'Provide Bearer token for authentication to the API server';
989-
const validateInput = (value: string) => NameValidator.emptyName('Bearer token cannot be empty', value ? value : '');
980+
const validateInput = (value: string) => NameValidator.validateLoginToken('Bearer token should be a valid "sha256" token', value ? value : '');
981+
const token = await Cluster.getTokenFromClipboard();
990982
ocToken = await inputValue(prompt, token ? token : '', true, validateInput,
991983
`Provide Bearer token for: ${clusterURL}`, abortController);
992984
if (ocToken === null) {
@@ -1027,8 +1019,7 @@ export class Cluster extends OpenShiftItem {
10271019
}
10281020

10291021
static validateLoginToken(token: string): boolean {
1030-
const sha256Regex = /^sha256~([A-Za-z0-9_-]+)$/;
1031-
return sha256Regex.test(token);
1022+
return NameValidator.validateLoginToken('Error', token) === null;
10321023
}
10331024

10341025
@vsCommand('openshift.explorer.login.clipboard')

Diff for: src/openshift/nameValidator.ts

+4
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ export function validateRFC1123DNSLabel(message: string, value: string): string
3636
return validator.matches(value, '^[a-z0-9]([-a-z0-9]*[a-z0-9])*$') ? null : message;
3737
}
3838

39+
export function validateLoginToken(message: string, value: string): string | null {
40+
return validator.matches(value, '^sha256~([A-Za-z0-9_-]+)$') ? null : message
41+
}
42+
3943
export function clusterURL(value: string): string | null {
4044
const urlRegex = value.match(/--server=(https?:\/\/[^ ]*)/);
4145
return urlRegex ? urlRegex[1] : null;

Diff for: src/util/inputValue.ts

+32-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
* Copyright (c) Red Hat, Inc. All rights reserved.
33
* Licensed under the MIT License. See LICENSE file in the project root for license information.
44
*-----------------------------------------------------------------------------------------------*/
5-
import { InputBox, QuickInputButton, QuickInputButtons, ThemeIcon, window } from 'vscode';
5+
import { env, InputBox, QuickInputButton, QuickInputButtons, ThemeIcon, window } from 'vscode';
66

77
export class quickBtn implements QuickInputButton {
88
constructor(public iconPath: ThemeIcon, public tooltip: string) { }
@@ -31,12 +31,35 @@ export function inputValue(prompt: string, initialValue: string, password: boole
3131
if (placeHolder) input.placeholder = placeHolder;
3232
const enterBtn = new quickBtn(new ThemeIcon('check'), 'Enter');
3333
const cancelBtn = new quickBtn(new ThemeIcon('close'), 'Cancel');
34-
input.buttons = [QuickInputButtons.Back, enterBtn, cancelBtn];
34+
const pasteBtn = new quickBtn(new ThemeIcon('output'), 'Paste from Clipboard');
35+
const hideBtn = new quickBtn(new ThemeIcon('eye'), 'Hide value');
36+
const showBtn = new quickBtn(new ThemeIcon('eye-closed'), 'Show value');
37+
let isHidden = password;
38+
const updateButtons = (() => {
39+
const buttons = [];
40+
if (password) {
41+
buttons.push(isHidden ? showBtn : hideBtn);
42+
}
43+
buttons.push(pasteBtn, QuickInputButtons.Back, enterBtn, cancelBtn);
44+
input.buttons = buttons;
45+
});
46+
updateButtons();
3547
const validationMessage: string = validate(input.value? input.value : '');
3648
const resolveAndClose = ((result) => {
3749
input.dispose();
3850
resolve(result);
3951
});
52+
const pasteFromClipboard = (async () => {
53+
try {
54+
const clipboard = (await env.clipboard.readText()).trim();
55+
if (clipboard.length > 0) {
56+
input.value = clipboard;
57+
input.validationMessage = validate(clipboard);
58+
}
59+
} catch (ignore) {
60+
// Do nothing
61+
}
62+
});
4063
input.ignoreFocusOut = true;
4164
if (validationMessage) {
4265
input.validationMessage = validationMessage;
@@ -67,6 +90,13 @@ export function inputValue(prompt: string, initialValue: string, password: boole
6790
})
6891
input.onDidTriggerButton(async (event) => {
6992
if (event === QuickInputButtons.Back) resolveAndClose(undefined);
93+
else if (event === showBtn) {
94+
input.password = isHidden = !isHidden;
95+
updateButtons();
96+
} else if (event === hideBtn) {
97+
input.password = isHidden = !isHidden;
98+
updateButtons();
99+
} else if (event === pasteBtn) await pasteFromClipboard();
70100
else if (event === cancelBtn) resolveAndClose(null);
71101
else if (event === enterBtn) await acceptInput();
72102
});

0 commit comments

Comments
 (0)