From 3850afa56366ddfc850555914220a92185d1312a Mon Sep 17 00:00:00 2001 From: worksofliam Date: Thu, 4 Apr 2024 19:32:56 -0400 Subject: [PATCH 01/16] Introduce ConnectionManager Signed-off-by: worksofliam --- src/api/Configuration.ts | 75 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 74 insertions(+), 1 deletion(-) diff --git a/src/api/Configuration.ts b/src/api/Configuration.ts index 405f1e74e..cff8f5d84 100644 --- a/src/api/Configuration.ts +++ b/src/api/Configuration.ts @@ -1,6 +1,6 @@ import os from "os"; import * as vscode from 'vscode'; -import { DeploymentMethod } from '../typings'; +import { ConnectionData, DeploymentMethod } from '../typings'; import { FilterType } from './Filter'; import { DEFAULT_CERT_DIRECTORY } from "./debug/certificates"; @@ -30,6 +30,79 @@ export namespace GlobalConfiguration { } } +export interface StoredConnection { + index: number, + data: ConnectionData +}; + +export namespace ConnectionManager { + export function getByName(name: string): StoredConnection | undefined { + const connections = getAll(); + if (connections) { + const index = connections.findIndex(conn => conn.name === name); + if (index !== -1) { + return { index, data: connections[index] }; + } + } + } + + export function sort() { + const connections = getAll(); + connections.sort((a, b) => a.name.localeCompare(b.name)); + return GlobalConfiguration.set(`connections`, connections); + } + + export function getAll(): ConnectionData[] { + return GlobalConfiguration.get(`connections`) || []; + } + + function setAll(connections: ConnectionData[]) { + return GlobalConfiguration.set(`connections`, connections); + } + + export async function storeNew(data: ConnectionData): Promise { + let connections = getAll(); + const newId = connections.length; + connections.push(data); + await setAll(connections); + return { index: newId, data }; + } + + export function deleteByName(name: string) { + const connections = getAll(); + const index = connections.findIndex(conn => conn.name === name); + if (index !== -1) { + connections.splice(index, 1); + return setAll(connections); + } + } + + export function updateByIndex(index: number, data: ConnectionData) { + const connections = getAll(); + connections[index] = data; + + // Remove possible password from any connection + connections.forEach(conn => delete conn.password); + + return GlobalConfiguration.set(`connections`, connections); + } + + export function getStoredPassword(context: vscode.ExtensionContext, connectionName: string) { + const connectionKey = `${connectionName}_password`; + return context.secrets.get(connectionKey); + } + + export function setStoredPassword(context: vscode.ExtensionContext, connectionName: string, password: string) { + const connectionKey = `${connectionName}_password`; + return context.secrets.store(connectionKey, password); + } + + export function deleteStoredPassword(context: vscode.ExtensionContext, connectionName: string) { + const connectionKey = `${connectionName}_password`; + return context.secrets.delete(connectionKey); + } +} + export namespace ConnectionConfiguration { export interface Parameters extends ConnectionProfile { host: string; From b7c77c342a9eecef79e7dd99eb97231d794a14f8 Mon Sep 17 00:00:00 2001 From: worksofliam Date: Thu, 4 Apr 2024 19:33:17 -0400 Subject: [PATCH 02/16] Replace all usages of raw connection access Signed-off-by: worksofliam --- src/extension.ts | 38 ++------------------ src/sandbox.ts | 20 +++-------- src/views/ConnectionBrowser.ts | 39 +++++++++----------- src/webviews/login/index.ts | 65 ++++++++++++++++------------------ src/webviews/settings/index.ts | 23 ++++++------ 5 files changed, 64 insertions(+), 121 deletions(-) diff --git a/src/extension.ts b/src/extension.ts index bdd44af8a..21111f9be 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -8,7 +8,7 @@ import { CustomUI } from "./api/CustomUI"; import { instance, loadAllofExtension } from './instantiate'; import { CompileTools } from "./api/CompileTools"; -import { ConnectionConfiguration, GlobalConfiguration, onCodeForIBMiConfigurationChange } from "./api/Configuration"; +import { ConnectionConfiguration, ConnectionManager, GlobalConfiguration, onCodeForIBMiConfigurationChange } from "./api/Configuration"; import IBMi from "./api/IBMi"; import { GlobalStorage } from "./api/Storage"; import { Tools } from "./api/Tools"; @@ -36,7 +36,7 @@ export async function activate(context: ExtensionContext): Promise await loadAllofExtension(context); const checkLastConnections = () => { - const connections = (GlobalConfiguration.get(`connections`) || []); + const connections = (ConnectionManager.getAll() || []); const lastConnections = (GlobalStorage.get().getLastConnections() || []).filter(lc => connections.find(c => c.name === lc.name)); GlobalStorage.get().setLastConnections(lastConnections); commands.executeCommand(`setContext`, `code-for-ibmi:hasPreviousConnection`, lastConnections.length > 0); @@ -115,43 +115,9 @@ export async function activate(context: ExtensionContext): Promise ]); }); - await fixLoginSettings(); - return { instance, customUI: () => new CustomUI(), deployTools: DeployTools, evfeventParser: parseErrors, tools: Tools }; } -async function fixLoginSettings(){ - const connections = (GlobalConfiguration.get(`connections`) || []); - let update = false; - for(const connection of connections){ - //privateKey was used to hold privateKeyPath - if('privateKey' in connection){ - const privateKey = connection["privateKey"] as string; - if(privateKey){ - connection.privateKeyPath = privateKey; - } - delete connection["privateKey"]; - update = true; - } - - //An empty privateKeyPath will crash the connection - if(!connection.privateKeyPath?.trim()) { - connection.privateKeyPath = undefined; - update = true; - } - - //buttons were added by the login settings page - if(`buttons` in connection) { - delete connection["buttons"]; - update = true; - } - } - - if(update){ - await GlobalConfiguration.set(`connections`, connections); - } -} - // this method is called when your extension is deactivated export async function deactivate() { await commands.executeCommand(`code-for-ibmi.disconnect`, true); diff --git a/src/sandbox.ts b/src/sandbox.ts index e7f9cc091..b7e5dd380 100644 --- a/src/sandbox.ts +++ b/src/sandbox.ts @@ -1,7 +1,7 @@ import { env } from "process"; import querystring from "querystring"; import { commands, ExtensionContext, Uri, window } from "vscode"; -import { ConnectionConfiguration, GlobalConfiguration } from "./api/Configuration"; +import { ConnectionConfiguration, ConnectionManager, GlobalConfiguration } from "./api/Configuration"; import { Tools } from "./api/Tools"; import { instance } from "./instantiate"; import { t } from "./locale"; @@ -62,21 +62,11 @@ export async function registerUriHandler(context: ExtensionContext) { await initialSetup(connectionData.username); if (save) { - let existingConnections: ConnectionData[] | undefined = GlobalConfiguration.get(`connections`); + const existingConnection = ConnectionManager.getByName(connectionData.name); - if (existingConnections) { - const existingConnection = existingConnections.find(item => item.name === host); - - if (!existingConnection) { - // New connection! - existingConnections.push({ - ...connectionData, - password: undefined, // Removes the password from the object - }); - - await context.secrets.store(`${host}_password`, pass); - await GlobalConfiguration.set(`connections`, existingConnections); - } + if (!existingConnection) { + // New connection! + await ConnectionManager.storeNew(connectionData); } } diff --git a/src/views/ConnectionBrowser.ts b/src/views/ConnectionBrowser.ts index b93e958d3..22fe5f92d 100644 --- a/src/views/ConnectionBrowser.ts +++ b/src/views/ConnectionBrowser.ts @@ -1,7 +1,7 @@ import vscode from 'vscode'; import { ConnectionData, Server } from '../typings'; -import { ConnectionConfiguration, GlobalConfiguration } from '../api/Configuration'; +import { ConnectionConfiguration, ConnectionManager, GlobalConfiguration } from '../api/Configuration'; import { GlobalStorage } from '../api/Storage'; import { instance } from '../instantiate'; import { t } from "../locale"; @@ -80,7 +80,7 @@ export function initializeConnectionBrowser(context: vscode.ExtensionContext) { vscode.commands.registerCommand(`code-for-ibmi.renameConnection`, async (server: Server) => { if (!connectionBrowser.attemptingConnection && server) { - const existingConnections = GlobalConfiguration.get(`connections`) || []; + const existingConnections = ConnectionManager.getAll(); const newName = await vscode.window.showInputBox({ prompt: t(`connectionBrowser.renameConnection.prompt`, server.name), value: server.name, @@ -95,12 +95,12 @@ export function initializeConnectionBrowser(context: vscode.ExtensionContext) { if (newName) { try { - let index; // First rename the connection details - const connections = GlobalConfiguration.get(`connections`) || []; - index = connections.findIndex(connection => connection.name === server.name); + const existingConnection = ConnectionManager.getByName(server.name)!; + let { index, data } = existingConnection! if (index === -1) throw (t(`connectionBrowser.renameConnection.noConnectionFound`, server.name)); - connections[index].name = newName; + data.name = newName; + await ConnectionManager.updateByIndex(index, data); // Then rename the connection settings const connectionSettings = GlobalConfiguration.get(`connectionSettings`) || []; @@ -116,14 +116,13 @@ export function initializeConnectionBrowser(context: vscode.ExtensionContext) { // No errors - update the settings. await GlobalConfiguration.set(`connectionSettings`, connectionSettings); - await GlobalConfiguration.set(`connections`, connections); if (cachedConnectionSettings) { GlobalStorage.get().setServerSettingsCache(newName, cachedConnectionSettings); GlobalStorage.get().deleteServerSettingsCache(server.name); } if (secret) { - await context.secrets.store(`${newName}_password`, secret); - await context.secrets.delete(`${server.name}_password`); + await ConnectionManager.setStoredPassword(context, newName, secret); + await ConnectionManager.deleteStoredPassword(context, server.name); } connectionBrowser.refresh(); @@ -136,9 +135,7 @@ export function initializeConnectionBrowser(context: vscode.ExtensionContext) { }), vscode.commands.registerCommand(`code-for-ibmi.sortConnections`, async () => { - const connections = GlobalConfiguration.get(`connections`) || []; - connections.sort((conn1, conn2) => conn1.name.localeCompare(conn2.name)); - await GlobalConfiguration.set(`connections`, connections); + await ConnectionManager.sort(); connectionBrowser.refresh(); }), @@ -160,9 +157,7 @@ export function initializeConnectionBrowser(context: vscode.ExtensionContext) { if (await vscode.window.showWarningMessage(message, { modal: true, detail }, t(`Yes`))) { for (const server of toBeDeleted) { // First remove the connection details - const connections = GlobalConfiguration.get(`connections`) || []; - const newConnections = connections.filter(connection => connection.name !== server.name); - await GlobalConfiguration.set(`connections`, newConnections); + await ConnectionManager.deleteByName(server.name); // Also remove the connection settings const connectionSettings = GlobalConfiguration.get(`connectionSettings`) || []; @@ -173,7 +168,7 @@ export function initializeConnectionBrowser(context: vscode.ExtensionContext) { GlobalStorage.get().deleteServerSettingsCache(server.name); // Then remove the password - await context.secrets.delete(`${server.name}_password`); + await ConnectionManager.deleteStoredPassword(context, server.name); } connectionBrowser.refresh(); @@ -181,10 +176,9 @@ export function initializeConnectionBrowser(context: vscode.ExtensionContext) { } }), vscode.commands.registerCommand(`code-for-ibmi.copyConnection`, async (server: Server) => { - const connections = GlobalConfiguration.get(`connections`) || []; const connectionSettings = GlobalConfiguration.get(`connectionSettings`) || []; - const connection = connections.find(connection => server.name === connection.name); + const connection = ConnectionManager.getByName(server.name); const connectionSetting = connectionSettings.find(connection => server.name === connection.name); if (connection && connectionSetting) { @@ -195,7 +189,7 @@ export function initializeConnectionBrowser(context: vscode.ExtensionContext) { prompt: t("connectionBrowser.copyConnection.prompt", server.name), placeHolder: t('connectionBrowser.copyConnection.placeholder'), value: newConnectionName, - validateInput: value => connections.some(connection => connection.name === value) ? + validateInput: value => ConnectionManager.getByName(value) ? t('connectionBrowser.copyConnection.already.exists', value) : undefined }); @@ -218,10 +212,9 @@ export function initializeConnectionBrowser(context: vscode.ExtensionContext) { } while (newConnectionName && !copyOperations); if (newConnectionName && copyOperations) { - const newConnection = Object.assign({}, connection); + const newConnection = Object.assign({}, connection.data); newConnection.name = newConnectionName; - connections.push(newConnection); - await GlobalConfiguration.set(`connections`, connections); + await ConnectionManager.storeNew(newConnection); const newConnectionSetting = Object.assign({}, connectionSetting); newConnectionSetting.name = newConnectionName; @@ -268,7 +261,7 @@ class ConnectionBrowser implements vscode.TreeDataProvider { async getChildren(): Promise { const lastConnection = GlobalStorage.get().getLastConnections()?.[0]; - return (GlobalConfiguration.get(`connections`) || []) + return (ConnectionManager.getAll() || []) .map(connection => new ServerItem(connection, connection.name === lastConnection?.name)); } } diff --git a/src/webviews/login/index.ts b/src/webviews/login/index.ts index 41c629913..1480f05e2 100644 --- a/src/webviews/login/index.ts +++ b/src/webviews/login/index.ts @@ -1,5 +1,5 @@ import vscode from "vscode"; -import { ConnectionConfiguration, GlobalConfiguration } from "../../api/Configuration"; +import { ConnectionConfiguration, ConnectionManager, GlobalConfiguration } from "../../api/Configuration"; import { CustomUI, Section } from "../../api/CustomUI"; import IBMi from "../../api/IBMi"; import { disconnect, instance } from "../../instantiate"; @@ -25,8 +25,6 @@ export class Login { if (!disconnect()) return; } - const existingConnections = GlobalConfiguration.get(`connections`) || []; - const connectionTab = new Section() .addInput(`name`, `Connection Name`, undefined, { minlength: 1 }) .addInput(`host`, t(`login.host`), undefined, { minlength: 1 }) @@ -59,35 +57,32 @@ export class Login { data.port = Number(data.port); data.privateKeyPath = data.privateKeyPath?.trim() ? data.privateKeyPath : undefined; if (data.name) { - const existingConnection = existingConnections.find(item => item.name === data.name); + const existingConnection = ConnectionManager.getByName(data.name); if (existingConnection) { vscode.window.showErrorMessage(`Connection with name ${data.name} already exists.`); } else { - const newConnection = (!existingConnections.some(item => item.name === data.name)); - if (newConnection) { - // New connection! - existingConnections.push({ - name: data.name, - host: data.host, - port: data.port, - username: data.username, - privateKeyPath: data.privateKeyPath - }); - - if (data.savePassword) { - await context.secrets.store(`${data.name}_password`, `${data.password}`); - } - - await GlobalConfiguration.set(`connections`, existingConnections); - - const config = await ConnectionConfiguration.load(data.name) - config.tempLibrary = data.tempLibrary; - config.tempDir = data.tempDir; - ConnectionConfiguration.update(config); - vscode.commands.executeCommand(`code-for-ibmi.refreshConnections`); + // New connection! + const newConnection: ConnectionData = { + name: data.name, + host: data.host, + port: data.port, + username: data.username, + privateKeyPath: data.privateKeyPath + }; + + if (data.savePassword && data.password) { + await ConnectionManager.setStoredPassword(context, data.name, data.password); } + await ConnectionManager.storeNew(newConnection); + + const config = await ConnectionConfiguration.load(data.name) + config.tempLibrary = data.tempLibrary; + config.tempDir = data.tempDir; + ConnectionConfiguration.update(config); + vscode.commands.executeCommand(`code-for-ibmi.refreshConnections`); + switch (data.buttons) { case `saveExit`: vscode.window.showInformationMessage(`Connection to ${data.host} saved!`); @@ -141,25 +136,25 @@ export class Login { * @param context */ static async LoginToPrevious(name: string, context: vscode.ExtensionContext, reloadServerSettings?: boolean) { - const connection = instance.getConnection(); - if (connection) { + const existingConnection = instance.getConnection(); + if (existingConnection) { // If the user is already connected and trying to connect to a different system, disconnect them first - if (name !== connection.currentConnectionName) { - vscode.window.showInformationMessage(`Disconnecting from ${connection.currentHost}.`); + if (name !== existingConnection.currentConnectionName) { + vscode.window.showInformationMessage(`Disconnecting from ${existingConnection.currentHost}.`); if (!disconnect()) return false; } } - const existingConnections = GlobalConfiguration.get(`connections`) || []; - let connectionConfig = existingConnections.find(item => item.name === name); - if (connectionConfig) { + const connection = ConnectionManager.getByName(name); + if (connection) { + const connectionConfig = connection.data; if (connectionConfig.privateKeyPath) { // If connecting with a private key, remove the password - await context.secrets.delete(`${connectionConfig.name}_password`); + await ConnectionManager.deleteStoredPassword(context, connectionConfig.name); } else { // Assume connection with a password, but prompt if we don't have one - connectionConfig.password = await context.secrets.get(`${connectionConfig.name}_password`); + connectionConfig.password = await ConnectionManager.getStoredPassword(context, connectionConfig.name); if (!connectionConfig.password) { connectionConfig.password = await vscode.window.showInputBox({ prompt: `Password for ${connectionConfig.name}`, diff --git a/src/webviews/settings/index.ts b/src/webviews/settings/index.ts index 84adda223..bcbee6956 100644 --- a/src/webviews/settings/index.ts +++ b/src/webviews/settings/index.ts @@ -1,5 +1,5 @@ import vscode from "vscode"; -import { ConnectionConfiguration, GlobalConfiguration } from "../../api/Configuration"; +import { ConnectionManager, ConnectionConfiguration, GlobalConfiguration } from "../../api/Configuration"; import { ComplexTab, CustomUI, Section } from "../../api/CustomUI"; import { GlobalStorage } from '../../api/Storage'; import { Tools } from "../../api/Tools"; @@ -307,21 +307,20 @@ export class SettingsUI { vscode.commands.registerCommand(`code-for-ibmi.showLoginSettings`, async (server?: Server) => { if (server) { - const connections = GlobalConfiguration.get(`connections`); const name = server.name; - if (connections) { - const connectionIdx = connections.findIndex(item => item.name === name); - let connection = connections[connectionIdx]; - const storedPassword = await context.secrets.get(`${name}_password`); + const connection = ConnectionManager.getByName(name); + if (connection) { + const storedPassword = await ConnectionManager.getStoredPassword(context, name); + let { data: stored, index } = connection; const page = await new CustomUI() - .addInput(`host`, t(`login.host`), undefined, { default: connection.host, minlength: 1 }) - .addInput(`port`, t(`login.port`), undefined, { default: String(connection.port), minlength: 1, maxlength: 5, regexTest: `^\\d+$` }) - .addInput(`username`, t(`username`), undefined, { default: connection.username, minlength: 1 }) + .addInput(`host`, t(`login.host`), undefined, { default: stored.host, minlength: 1 }) + .addInput(`port`, t(`login.port`), undefined, { default: String(stored.port), minlength: 1, maxlength: 5, regexTest: `^\\d+$` }) + .addInput(`username`, t(`username`), undefined, { default: stored.username, minlength: 1 }) .addParagraph(t(`login.authDecision`)) .addPassword(`password`, `${t(`password`)}${storedPassword ? ` (${t(`stored`)})` : ``}`, t(`login.password.label`)) - .addFile(`privateKeyPath`, `${t(`privateKey`)}${connection.privateKeyPath ? ` (${t(`current`)}: ${connection.privateKeyPath})` : ``}`, t(`login.privateKey.label`) + ' ' + t(`login.privateKey.support`)) + .addFile(`privateKeyPath`, `${t(`privateKey`)}${stored.privateKeyPath ? ` (${t(`current`)}: ${stored.privateKeyPath})` : ``}`, t(`login.privateKey.label`) + ' ' + t(`login.privateKey.support`)) .addButtons( { id: `submitButton`, label: t(`save`), requiresValidation: true }, { id: `removeAuth`, label: t(`login.removeAuth`) } @@ -381,8 +380,8 @@ export class SettingsUI { delete data.password; delete data.buttons; - connections[connectionIdx] = Object.assign(connection, data); - await GlobalConfiguration.set(`connections`, connections); + stored = Object.assign(stored, data); + await ConnectionManager.updateByIndex(index, stored); } } } From b1c22275c3d49dadff314bb4cb15a8abff0fc709 Mon Sep 17 00:00:00 2001 From: worksofliam Date: Thu, 4 Apr 2024 19:36:18 -0400 Subject: [PATCH 03/16] Replace all places of raw password access Signed-off-by: worksofliam --- src/api/debug/index.ts | 3 ++- src/extension.ts | 2 +- src/instantiate.ts | 5 ++--- src/views/ConnectionBrowser.ts | 6 +++--- src/webviews/settings/index.ts | 6 +++--- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/api/debug/index.ts b/src/api/debug/index.ts index a90774cd9..4f14d0b28 100644 --- a/src/api/debug/index.ts +++ b/src/api/debug/index.ts @@ -12,6 +12,7 @@ import { getEnvConfig } from "../local/env"; import * as certificates from "./certificates"; import * as server from "./server"; import { debug } from "console"; +import { ConnectionManager } from "../Configuration"; const debugExtensionId = `IBM.ibmidebug`; @@ -186,7 +187,7 @@ export async function initialize(context: ExtensionContext) { const getPassword = async () => { const connection = instance.getConnection(); - let password = await context.secrets.get(`${connection!.currentConnectionName}_password`); + let password = await ConnectionManager.getStoredPassword(context, connection!.currentConnectionName); if (!password) { password = temporaryPassword; diff --git a/src/extension.ts b/src/extension.ts index 21111f9be..171b051f7 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -69,7 +69,7 @@ export async function activate(context: ExtensionContext): Promise } if (savePassword && connectionData.password) { - await context.secrets.store(`${connectionData.name}_password`, `${connectionData.password}`); + await ConnectionManager.setStoredPassword(context, connectionData.name, connectionData.password); } return (await new IBMi().connect(connectionData, undefined, reloadSettings)).success; diff --git a/src/instantiate.ts b/src/instantiate.ts index d9a7afb96..13d45ba2a 100644 --- a/src/instantiate.ts +++ b/src/instantiate.ts @@ -3,7 +3,7 @@ import { Tools } from './api/Tools'; import path, { dirname } from 'path'; import * as vscode from "vscode"; import { CompileTools } from './api/CompileTools'; -import { ConnectionConfiguration, DefaultOpenMode, GlobalConfiguration, onCodeForIBMiConfigurationChange } from "./api/Configuration"; +import { ConnectionConfiguration, ConnectionManager, DefaultOpenMode, GlobalConfiguration, onCodeForIBMiConfigurationChange } from "./api/Configuration"; import Instance from "./api/Instance"; import { Search } from "./api/Search"; import { Terminal } from './api/Terminal'; @@ -639,8 +639,7 @@ export async function loadAllofExtension(context: vscode.ExtensionContext) { throw new Error(`Password request denied for extension ${displayName}.`); } - const connectionKey = `${instance.getConnection()!.currentConnectionName}_password`; - const storedPassword = await context.secrets.get(connectionKey); + const storedPassword = await ConnectionManager.getStoredPassword(context, instance.getConnection()!.currentConnectionName); if (storedPassword) { let isAuthed = storage.getExtensionAuthorisation(extension) !== undefined; diff --git a/src/views/ConnectionBrowser.ts b/src/views/ConnectionBrowser.ts index 22fe5f92d..0d43b83e0 100644 --- a/src/views/ConnectionBrowser.ts +++ b/src/views/ConnectionBrowser.ts @@ -112,7 +112,7 @@ export function initializeConnectionBrowser(context: vscode.ExtensionContext) { const cachedConnectionSettings = GlobalStorage.get().getServerSettingsCache(server.name); // Then get the password key - const secret = await context.secrets.get(`${server.name}_password`); + const secret = await ConnectionManager.getStoredPassword(context, server.name); // No errors - update the settings. await GlobalConfiguration.set(`connectionSettings`, connectionSettings); @@ -230,9 +230,9 @@ export function initializeConnectionBrowser(context: vscode.ExtensionContext) { connectionSettings.push(newConnectionSetting); await GlobalConfiguration.set(`connectionSettings`, connectionSettings); - const password = await context.secrets.get(`${server.name}_password`); + const password = await ConnectionManager.getStoredPassword(context, server.name); if (password) { - await context.secrets.store(`${newConnectionName}_password`, password); + await ConnectionManager.setStoredPassword(context, newConnectionName, password); } connectionBrowser.refresh(); diff --git a/src/webviews/settings/index.ts b/src/webviews/settings/index.ts index bcbee6956..ef53f7669 100644 --- a/src/webviews/settings/index.ts +++ b/src/webviews/settings/index.ts @@ -341,7 +341,7 @@ export class SettingsUI { if (data.password) { // New password was entered, so store the password // and remove the private key path from the data - await context.secrets.store(`${name}_password`, `${data.password}`); + await ConnectionManager.setStoredPassword(context, name, data.password); data.privateKeyPath = undefined; vscode.window.showInformationMessage(t(`login.password.updated`, name)); @@ -353,7 +353,7 @@ export class SettingsUI { // then remove the password from the data and // use the keypath instead if (data.privateKeyPath?.trim()) { - await context.secrets.delete(`${name}_password`); + await ConnectionManager.deleteStoredPassword(context, name); vscode.window.showInformationMessage(t(`login.privateKey.updated`, name)); @@ -363,7 +363,7 @@ export class SettingsUI { break; case `removeAuth`: - await context.secrets.delete(`${name}_password`); + await ConnectionManager.deleteStoredPassword(context, name); data.password = undefined; data.privateKeyPath = undefined; From d25afa97b08d5935029b4703adee0a041c545faa Mon Sep 17 00:00:00 2001 From: "S. Julliand" Date: Sat, 20 Apr 2024 19:23:25 +0200 Subject: [PATCH 04/16] Fixed login settings not saved if auth method is unchanged Signed-off-by: S. Julliand --- src/webviews/settings/index.ts | 52 ++++++++++++---------------------- 1 file changed, 18 insertions(+), 34 deletions(-) diff --git a/src/webviews/settings/index.ts b/src/webviews/settings/index.ts index ef53f7669..998f1ab31 100644 --- a/src/webviews/settings/index.ts +++ b/src/webviews/settings/index.ts @@ -1,13 +1,13 @@ import vscode from "vscode"; -import { ConnectionManager, ConnectionConfiguration, GlobalConfiguration } from "../../api/Configuration"; +import { ConnectionConfiguration, ConnectionManager, GlobalConfiguration } from "../../api/Configuration"; import { ComplexTab, CustomUI, Section } from "../../api/CustomUI"; import { GlobalStorage } from '../../api/Storage'; import { Tools } from "../../api/Tools"; import { isManaged } from "../../api/debug"; import * as certificates from "../../api/debug/certificates"; import { instance } from "../../instantiate"; -import { ConnectionData, Server } from '../../typings'; import { t } from "../../locale"; +import { ConnectionData, Server } from '../../typings'; const ENCODINGS = [`37`, `256`, `273`, `277`, `278`, `280`, `284`, `285`, `297`, `500`, `871`, `870`, `905`, `880`, `420`, `875`, `424`, `1026`, `290`, `win37`, `win256`, `win273`, `win277`, `win278`, `win280`, `win284`, `win285`, `win297`, `win500`, `win871`, `win870`, `win905`, `win880`, `win420`, `win875`, `win424`, `win1026`]; @@ -331,58 +331,42 @@ export class SettingsUI { page.panel.dispose(); const data = page.data; - - let doUpdate = false; - const chosenButton = data.buttons as "submitButton" | "removeAuth"; switch (chosenButton) { case `submitButton`: if (data.password) { - // New password was entered, so store the password - // and remove the private key path from the data - await ConnectionManager.setStoredPassword(context, name, data.password); data.privateKeyPath = undefined; - - vscode.window.showInformationMessage(t(`login.password.updated`, name)); - - doUpdate = true; - - } else { + if (data.password !== storedPassword) { + // New password was entered, so store the password + // and remove the private key path from the data + await ConnectionManager.setStoredPassword(context, name, data.password); + vscode.window.showInformationMessage(t(`login.password.updated`, name)); + } + } else if (data.privateKeyPath?.trim()) { // If no password was entered, but a keypath exists // then remove the password from the data and // use the keypath instead - if (data.privateKeyPath?.trim()) { - await ConnectionManager.deleteStoredPassword(context, name); - - vscode.window.showInformationMessage(t(`login.privateKey.updated`, name)); - - doUpdate = true; - } + await ConnectionManager.deleteStoredPassword(context, name); + vscode.window.showInformationMessage(t(`login.privateKey.updated`, name)); } break; case `removeAuth`: await ConnectionManager.deleteStoredPassword(context, name); - data.password = undefined; data.privateKeyPath = undefined; - vscode.window.showInformationMessage(t(`login.authRemoved`, name)); - - doUpdate = true; break; } + //Fix values before assigning the data + data.port = Number(data.port); + delete data.password; + delete data.buttons; - if (doUpdate) { - //Fix values before assigning the data - data.port = Number(data.port); - delete data.password; - delete data.buttons; - - stored = Object.assign(stored, data); - await ConnectionManager.updateByIndex(index, stored); - } + stored = Object.assign(stored, data); + await ConnectionManager.updateByIndex(index, stored); + vscode.commands.executeCommand(`code-for-ibmi.refreshConnections`); } } } From f93524a3818e5aafbe764100b320be677aa137b2 Mon Sep 17 00:00:00 2001 From: "S. Julliand" Date: Sat, 20 Apr 2024 19:24:35 +0200 Subject: [PATCH 05/16] Update auth method if enter is pressed to save settings Signed-off-by: S. Julliand --- src/webviews/settings/index.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/webviews/settings/index.ts b/src/webviews/settings/index.ts index 998f1ab31..0d1a9db58 100644 --- a/src/webviews/settings/index.ts +++ b/src/webviews/settings/index.ts @@ -333,8 +333,14 @@ export class SettingsUI { const data = page.data; const chosenButton = data.buttons as "submitButton" | "removeAuth"; - switch (chosenButton) { - case `submitButton`: + switch (chosenButton) { + case `removeAuth`: + await ConnectionManager.deleteStoredPassword(context, name); + data.privateKeyPath = undefined; + vscode.window.showInformationMessage(t(`login.authRemoved`, name)); + break; + + default: if (data.password) { data.privateKeyPath = undefined; if (data.password !== storedPassword) { @@ -351,12 +357,6 @@ export class SettingsUI { vscode.window.showInformationMessage(t(`login.privateKey.updated`, name)); } break; - - case `removeAuth`: - await ConnectionManager.deleteStoredPassword(context, name); - data.privateKeyPath = undefined; - vscode.window.showInformationMessage(t(`login.authRemoved`, name)); - break; } //Fix values before assigning the data From a5fff0861fdb220d9cc948e20e303d53d3aad9d9 Mon Sep 17 00:00:00 2001 From: worksofliam Date: Wed, 24 Apr 2024 13:59:43 -0400 Subject: [PATCH 06/16] Connections is never falsy Signed-off-by: worksofliam --- src/api/Configuration.ts | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/api/Configuration.ts b/src/api/Configuration.ts index cff8f5d84..1662f8fda 100644 --- a/src/api/Configuration.ts +++ b/src/api/Configuration.ts @@ -38,11 +38,9 @@ export interface StoredConnection { export namespace ConnectionManager { export function getByName(name: string): StoredConnection | undefined { const connections = getAll(); - if (connections) { - const index = connections.findIndex(conn => conn.name === name); - if (index !== -1) { - return { index, data: connections[index] }; - } + const index = connections.findIndex(conn => conn.name === name); + if (index !== -1) { + return { index, data: connections[index] }; } } From 0a316b99f9c79995d347f19c5d6d9b04d76b17cb Mon Sep 17 00:00:00 2001 From: worksofliam Date: Wed, 24 Apr 2024 14:00:02 -0400 Subject: [PATCH 07/16] Switch to use const for connections Signed-off-by: worksofliam --- src/api/Configuration.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/Configuration.ts b/src/api/Configuration.ts index 1662f8fda..a74f700e1 100644 --- a/src/api/Configuration.ts +++ b/src/api/Configuration.ts @@ -59,7 +59,7 @@ export namespace ConnectionManager { } export async function storeNew(data: ConnectionData): Promise { - let connections = getAll(); + const connections = getAll(); const newId = connections.length; connections.push(data); await setAll(connections); From d5bfb943f1a63cdd18d4b617e23f97b129b76298 Mon Sep 17 00:00:00 2001 From: worksofliam Date: Wed, 24 Apr 2024 14:01:10 -0400 Subject: [PATCH 08/16] reusable getPasswordKey function Signed-off-by: worksofliam --- src/api/Configuration.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/api/Configuration.ts b/src/api/Configuration.ts index a74f700e1..c49fafd13 100644 --- a/src/api/Configuration.ts +++ b/src/api/Configuration.ts @@ -35,6 +35,8 @@ export interface StoredConnection { data: ConnectionData }; +const getPasswordKey = (connectionName:string) => `${connectionName}_password`; + export namespace ConnectionManager { export function getByName(name: string): StoredConnection | undefined { const connections = getAll(); @@ -86,17 +88,17 @@ export namespace ConnectionManager { } export function getStoredPassword(context: vscode.ExtensionContext, connectionName: string) { - const connectionKey = `${connectionName}_password`; + const connectionKey = getPasswordKey(connectionName); return context.secrets.get(connectionKey); } export function setStoredPassword(context: vscode.ExtensionContext, connectionName: string, password: string) { - const connectionKey = `${connectionName}_password`; + const connectionKey = getPasswordKey(connectionName); return context.secrets.store(connectionKey, password); } export function deleteStoredPassword(context: vscode.ExtensionContext, connectionName: string) { - const connectionKey = `${connectionName}_password`; + const connectionKey = getPasswordKey(connectionName); return context.secrets.delete(connectionKey); } } From 47affe560b1fd91e284a1f26248a35f2b53d9e8c Mon Sep 17 00:00:00 2001 From: worksofliam Date: Wed, 24 Apr 2024 14:02:06 -0400 Subject: [PATCH 09/16] getAll always returns an array Signed-off-by: worksofliam --- src/extension.ts | 2 +- src/views/ConnectionBrowser.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/extension.ts b/src/extension.ts index 171b051f7..3b16f603d 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -36,7 +36,7 @@ export async function activate(context: ExtensionContext): Promise await loadAllofExtension(context); const checkLastConnections = () => { - const connections = (ConnectionManager.getAll() || []); + const connections = ConnectionManager.getAll(); const lastConnections = (GlobalStorage.get().getLastConnections() || []).filter(lc => connections.find(c => c.name === lc.name)); GlobalStorage.get().setLastConnections(lastConnections); commands.executeCommand(`setContext`, `code-for-ibmi:hasPreviousConnection`, lastConnections.length > 0); diff --git a/src/views/ConnectionBrowser.ts b/src/views/ConnectionBrowser.ts index 0d43b83e0..bf5ecb8fc 100644 --- a/src/views/ConnectionBrowser.ts +++ b/src/views/ConnectionBrowser.ts @@ -261,7 +261,7 @@ class ConnectionBrowser implements vscode.TreeDataProvider { async getChildren(): Promise { const lastConnection = GlobalStorage.get().getLastConnections()?.[0]; - return (ConnectionManager.getAll() || []) + return ConnectionManager.getAll() .map(connection => new ServerItem(connection, connection.name === lastConnection?.name)); } } From 36ba09af3f40d108f042b92d7c64ba192ddc9141 Mon Sep 17 00:00:00 2001 From: worksofliam Date: Wed, 24 Apr 2024 14:02:40 -0400 Subject: [PATCH 10/16] Simplify assignment Signed-off-by: worksofliam --- src/views/ConnectionBrowser.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/views/ConnectionBrowser.ts b/src/views/ConnectionBrowser.ts index bf5ecb8fc..5edacc8f9 100644 --- a/src/views/ConnectionBrowser.ts +++ b/src/views/ConnectionBrowser.ts @@ -96,8 +96,7 @@ export function initializeConnectionBrowser(context: vscode.ExtensionContext) { if (newName) { try { // First rename the connection details - const existingConnection = ConnectionManager.getByName(server.name)!; - let { index, data } = existingConnection! + let { index, data } = ConnectionManager.getByName(server.name)! if (index === -1) throw (t(`connectionBrowser.renameConnection.noConnectionFound`, server.name)); data.name = newName; await ConnectionManager.updateByIndex(index, data); From 2d89b9b1fba122a8e3c4fd3a6ba62d544f9e35ae Mon Sep 17 00:00:00 2001 From: worksofliam Date: Wed, 24 Apr 2024 14:02:52 -0400 Subject: [PATCH 11/16] Add missing await Signed-off-by: worksofliam --- src/webviews/login/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/webviews/login/index.ts b/src/webviews/login/index.ts index 1480f05e2..b1924e58a 100644 --- a/src/webviews/login/index.ts +++ b/src/webviews/login/index.ts @@ -141,7 +141,7 @@ export class Login { // If the user is already connected and trying to connect to a different system, disconnect them first if (name !== existingConnection.currentConnectionName) { vscode.window.showInformationMessage(`Disconnecting from ${existingConnection.currentHost}.`); - if (!disconnect()) return false; + if (!await disconnect()) return false; } } From 1e6353dc2c35a1c66a7598fc91933cd27f0227ad Mon Sep 17 00:00:00 2001 From: worksofliam Date: Tue, 7 May 2024 10:14:34 -0500 Subject: [PATCH 12/16] Disable certain buttons when editing a connection Signed-off-by: worksofliam --- package.json | 12 +- src/webviews/settings/index.ts | 221 +++++++++++++++++---------------- 2 files changed, 122 insertions(+), 111 deletions(-) diff --git a/package.json b/package.json index 28e929418..1feacceb3 100644 --- a/package.json +++ b/package.json @@ -964,7 +964,8 @@ "command": "code-for-ibmi.connect", "title": "New Connection", "category": "IBM i", - "icon": "$(add)" + "icon": "$(add)", + "enablement": "code-for-ibmi:editingConnection !== true" }, { "command": "code-for-ibmi.connectTo", @@ -976,7 +977,8 @@ "command": "code-for-ibmi.connectToPrevious", "title": "Connect to Previous IBM i", "category": "IBM i", - "icon": "$(remote)" + "icon": "$(remote)", + "enablement": "code-for-ibmi:editingConnection !== true" }, { "command": "code-for-ibmi.connectToAndReload", @@ -987,13 +989,15 @@ "command": "code-for-ibmi.refreshConnections", "title": "Refresh", "category": "IBM i", - "icon": "$(refresh)" + "icon": "$(refresh)", + "enablement": "code-for-ibmi:editingConnection !== true" }, { "command": "code-for-ibmi.sortConnections", "title": "Sort", "category": "IBM i", - "icon": "$(list-ordered)" + "icon": "$(list-ordered)", + "enablement": "code-for-ibmi:editingConnection !== true" }, { "command": "code-for-ibmi.showAdditionalSettings", diff --git a/src/webviews/settings/index.ts b/src/webviews/settings/index.ts index 980ca9b5f..c56b77fa8 100644 --- a/src/webviews/settings/index.ts +++ b/src/webviews/settings/index.ts @@ -10,6 +10,8 @@ import { instance } from "../../instantiate"; import { t } from "../../locale"; import { ConnectionData, Server } from '../../typings'; +const EDITING_CONTEXT = `code-for-ibmi:editingConnection`; + const ENCODINGS = [`37`, `256`, `273`, `277`, `278`, `280`, `284`, `285`, `297`, `500`, `871`, `870`, `905`, `880`, `420`, `875`, `424`, `1026`, `290`, `win37`, `win256`, `win273`, `win277`, `win278`, `win280`, `win284`, `win285`, `win297`, `win500`, `win871`, `win870`, `win905`, `win880`, `win420`, `win875`, `win424`, `win1026`]; const TERMINAL_TYPES = [ @@ -243,87 +245,89 @@ export class SettingsUI { .addHorizontalRule() .addButtons({ id: `save`, label: `Save settings`, requiresValidation: true }); - const page = await ui.loadPage(`Settings: ${config.name}`); - if (page) { - page.panel.dispose(); + await Tools.withContext(EDITING_CONTEXT, async () => { + const page = await ui.loadPage(`Settings: ${config.name}`); + if (page) { + page.panel.dispose(); - if (page.data) { - const data = page.data; - const button = data.buttons; + if (page.data) { + const data = page.data; + const button = data.buttons; - switch (button) { - case `import`: - vscode.commands.executeCommand(`code-for-ibmi.debug.setup.local`); - break; + switch (button) { + case `import`: + vscode.commands.executeCommand(`code-for-ibmi.debug.setup.local`); + break; - case `generate`: - vscode.commands.executeCommand(`code-for-ibmi.debug.setup.remote`); - break; + case `generate`: + vscode.commands.executeCommand(`code-for-ibmi.debug.setup.remote`); + break; - case `clearAllowedExts`: - instance.getStorage()?.revokeAllExtensionAuthorisations(); - break; + case `clearAllowedExts`: + instance.getStorage()?.revokeAllExtensionAuthorisations(); + break; - default: - const data = page.data; - for (const key in data) { - - //In case we need to play with the data - switch (key) { - case `sourceASP`: - if (data[key].trim() === ``) data[key] = null; - break; - case `hideCompileErrors`: - data[key] = String(data[key]).split(`,`) - .map(item => item.toUpperCase().trim()) - .filter(item => item !== ``) - .filter(Tools.distinct); - break; - case `protectedPaths`: - data[key] = String(data[key]).split(`,`) - .map(item => item.trim()) - .map(item => item.startsWith('/') ? item : connection?.upperCaseName(item) || item.toUpperCase()) - .filter(item => item !== ``) - .filter(Tools.distinct); - break; - } + default: + const data = page.data; + for (const key in data) { + + //In case we need to play with the data + switch (key) { + case `sourceASP`: + if (data[key].trim() === ``) data[key] = null; + break; + case `hideCompileErrors`: + data[key] = String(data[key]).split(`,`) + .map(item => item.toUpperCase().trim()) + .filter(item => item !== ``) + .filter(Tools.distinct); + break; + case `protectedPaths`: + data[key] = String(data[key]).split(`,`) + .map(item => item.trim()) + .map(item => item.startsWith('/') ? item : connection?.upperCaseName(item) || item.toUpperCase()) + .filter(item => item !== ``) + .filter(Tools.distinct); + break; + } - //Refresh connection browser if not connected - if (!instance.getConnection()) { - vscode.commands.executeCommand(`code-for-ibmi.refreshConnections`); + //Refresh connection browser if not connected + if (!instance.getConnection()) { + vscode.commands.executeCommand(`code-for-ibmi.refreshConnections`); + } } - } - - if (restartFields.some(item => data[item] && data[item] !== config[item])) { - restart = true; - } - const reloadBrowsers = config.protectedPaths.join(",") !== data.protectedPaths.join(","); - const removeCachedSettings = (!data.quickConnect && data.quickConnect !== config.quickConnect); - - Object.assign(config, data); - await instance.setConfig(config); - if (removeCachedSettings) - GlobalStorage.get().deleteServerSettingsCache(config.name); - - if (connection) { - if (restart) { - vscode.window.showInformationMessage(`Some settings require a restart to take effect. Reload workspace now?`, `Reload`, `No`) - .then(async (value) => { - if (value === `Reload`) { - await vscode.commands.executeCommand(`workbench.action.reloadWindow`); - } - }); + if (restartFields.some(item => data[item] && data[item] !== config[item])) { + restart = true; } - else if (reloadBrowsers) { - vscode.commands.executeCommand("code-for-ibmi.refreshIFSBrowser"); - vscode.commands.executeCommand("code-for-ibmi.refreshObjectBrowser"); + + const reloadBrowsers = config.protectedPaths.join(",") !== data.protectedPaths.join(","); + const removeCachedSettings = (!data.quickConnect && data.quickConnect !== config.quickConnect); + + Object.assign(config, data); + await instance.setConfig(config); + if (removeCachedSettings) + GlobalStorage.get().deleteServerSettingsCache(config.name); + + if (connection) { + if (restart) { + vscode.window.showInformationMessage(`Some settings require a restart to take effect. Reload workspace now?`, `Reload`, `No`) + .then(async (value) => { + if (value === `Reload`) { + await vscode.commands.executeCommand(`workbench.action.reloadWindow`); + } + }); + } + else if (reloadBrowsers) { + vscode.commands.executeCommand("code-for-ibmi.refreshIFSBrowser"); + vscode.commands.executeCommand("code-for-ibmi.refreshObjectBrowser"); + } } - } - break; + break; + } } } - } + }) }), vscode.commands.registerCommand(`code-for-ibmi.showLoginSettings`, async (server?: Server) => { @@ -335,7 +339,7 @@ export class SettingsUI { const storedPassword = await ConnectionManager.getStoredPassword(context, name); let { data: stored, index } = connection; - const page = await new CustomUI() + const ui = await new CustomUI() .addInput(`host`, t(`login.host`), undefined, { default: stored.host, minlength: 1 }) .addInput(`port`, t(`login.port`), undefined, { default: String(stored.port), minlength: 1, maxlength: 5, regexTest: `^\\d+$` }) .addInput(`username`, t(`username`), undefined, { default: stored.username, minlength: 1 }) @@ -345,50 +349,53 @@ export class SettingsUI { .addButtons( { id: `submitButton`, label: t(`save`), requiresValidation: true }, { id: `removeAuth`, label: t(`login.removeAuth`) } - ) - .loadPage(t(`login.title.edit`, name)); + ); - if (page && page.data) { - page.panel.dispose(); + await Tools.withContext(EDITING_CONTEXT, async () => { + const page = await ui.loadPage(t(`login.title.edit`, name)); + if (page && page.data) { + page.panel.dispose(); - const data = page.data; - const chosenButton = data.buttons as "submitButton" | "removeAuth"; + const data = page.data; + const chosenButton = data.buttons as "submitButton" | "removeAuth"; - switch (chosenButton) { - case `removeAuth`: - await ConnectionManager.deleteStoredPassword(context, name); - data.privateKeyPath = undefined; - vscode.window.showInformationMessage(t(`login.authRemoved`, name)); - break; - - default: - if (data.password) { + switch (chosenButton) { + case `removeAuth`: + await ConnectionManager.deleteStoredPassword(context, name); data.privateKeyPath = undefined; - if (data.password !== storedPassword) { - // New password was entered, so store the password - // and remove the private key path from the data - await ConnectionManager.setStoredPassword(context, name, data.password); - vscode.window.showInformationMessage(t(`login.password.updated`, name)); + vscode.window.showInformationMessage(t(`login.authRemoved`, name)); + break; + + default: + if (data.password) { + data.privateKeyPath = undefined; + if (data.password !== storedPassword) { + // New password was entered, so store the password + // and remove the private key path from the data + await ConnectionManager.setStoredPassword(context, name, data.password); + vscode.window.showInformationMessage(t(`login.password.updated`, name)); + } + } else if (data.privateKeyPath?.trim()) { + // If no password was entered, but a keypath exists + // then remove the password from the data and + // use the keypath instead + await ConnectionManager.deleteStoredPassword(context, name); + vscode.window.showInformationMessage(t(`login.privateKey.updated`, name)); } - } else if (data.privateKeyPath?.trim()) { - // If no password was entered, but a keypath exists - // then remove the password from the data and - // use the keypath instead - await ConnectionManager.deleteStoredPassword(context, name); - vscode.window.showInformationMessage(t(`login.privateKey.updated`, name)); - } - break; - } + break; + } - //Fix values before assigning the data - data.port = Number(data.port); - delete data.password; - delete data.buttons; + //Fix values before assigning the data + data.port = Number(data.port); + delete data.password; + delete data.buttons; - stored = Object.assign(stored, data); - await ConnectionManager.updateByIndex(index, stored); - vscode.commands.executeCommand(`code-for-ibmi.refreshConnections`); - } + stored = Object.assign(stored, data); + await ConnectionManager.updateByIndex(index, stored); + vscode.commands.executeCommand(`code-for-ibmi.refreshConnections`); + + } + }); } } }) From 0aa6401867c0bf764506c06101e79416745051b9 Mon Sep 17 00:00:00 2001 From: worksofliam Date: Mon, 13 May 2024 16:27:12 -0400 Subject: [PATCH 13/16] No await needed on CustomUI contructor Signed-off-by: worksofliam --- src/webviews/settings/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/webviews/settings/index.ts b/src/webviews/settings/index.ts index c56b77fa8..9c1540748 100644 --- a/src/webviews/settings/index.ts +++ b/src/webviews/settings/index.ts @@ -339,7 +339,7 @@ export class SettingsUI { const storedPassword = await ConnectionManager.getStoredPassword(context, name); let { data: stored, index } = connection; - const ui = await new CustomUI() + const ui = new CustomUI() .addInput(`host`, t(`login.host`), undefined, { default: stored.host, minlength: 1 }) .addInput(`port`, t(`login.port`), undefined, { default: String(stored.port), minlength: 1, maxlength: 5, regexTest: `^\\d+$` }) .addInput(`username`, t(`username`), undefined, { default: stored.username, minlength: 1 }) From 273cf99830b71f636995a03196797db6f444a458 Mon Sep 17 00:00:00 2001 From: Seb Julliand Date: Mon, 13 May 2024 22:40:01 +0200 Subject: [PATCH 14/16] Correctly increment/decrement withContext's stack Signed-off-by: Seb Julliand --- src/api/Tools.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/api/Tools.ts b/src/api/Tools.ts index bb6f93682..bd50862d1 100644 --- a/src/api/Tools.ts +++ b/src/api/Tools.ts @@ -363,7 +363,8 @@ export namespace Tools { activeContexts.set(context, 0); } else { - activeContexts.set(context, stack++); + stack++; + activeContexts.set(context, stack); } return await task(); } @@ -371,7 +372,8 @@ export namespace Tools { let stack = activeContexts.get(context); if (stack !== undefined) { if (stack) { - activeContexts.set(context, stack--); + stack--; + activeContexts.set(context, stack); } else { await vscode.commands.executeCommand(`setContext`, context, undefined); From 7cb240f2141f78a88d07483b229aa0074bb2e136 Mon Sep 17 00:00:00 2001 From: worksofliam Date: Mon, 13 May 2024 16:58:47 -0400 Subject: [PATCH 15/16] Disable more UI options when editing a connection Signed-off-by: worksofliam --- package.json | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index 1feacceb3..22f85906e 100644 --- a/package.json +++ b/package.json @@ -971,7 +971,8 @@ "command": "code-for-ibmi.connectTo", "title": "Connect to IBM i", "category": "IBM i", - "icon": "$(debug-start)" + "icon": "$(debug-start)", + "enablement": "code-for-ibmi:editingConnection !== true" }, { "command": "code-for-ibmi.connectToPrevious", @@ -983,7 +984,8 @@ { "command": "code-for-ibmi.connectToAndReload", "title": "Connect and Reload Server Settings", - "category": "IBM i" + "category": "IBM i", + "enablement": "code-for-ibmi:editingConnection !== true" }, { "command": "code-for-ibmi.refreshConnections", @@ -1002,27 +1004,32 @@ { "command": "code-for-ibmi.showAdditionalSettings", "title": "Connection Settings", - "category": "IBM i" + "category": "IBM i", + "enablement": "code-for-ibmi:editingConnection !== true" }, { "command": "code-for-ibmi.showLoginSettings", "title": "Login Settings", - "category": "IBM i" + "category": "IBM i", + "enablement": "code-for-ibmi:editingConnection !== true" }, { "command": "code-for-ibmi.renameConnection", "title": "Rename...", - "category": "IBM i" + "category": "IBM i", + "enablement": "code-for-ibmi:editingConnection !== true" }, { "command": "code-for-ibmi.deleteConnection", "title": "Delete...", - "category": "IBM i" + "category": "IBM i", + "enablement": "code-for-ibmi:editingConnection !== true" }, { "command": "code-for-ibmi.copyConnection", "title": "Copy...", - "category": "IBM i" + "category": "IBM i", + "enablement": "code-for-ibmi:editingConnection !== true" }, { "command": "code-for-ibmi.disconnect", From e1974fdedcde764a0ac77a78e6be9b105d241b62 Mon Sep 17 00:00:00 2001 From: worksofliam Date: Tue, 14 May 2024 08:41:50 -0400 Subject: [PATCH 16/16] Remove context for settings views Signed-off-by: worksofliam --- package.json | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 22f85906e..35529d39c 100644 --- a/package.json +++ b/package.json @@ -1004,14 +1004,12 @@ { "command": "code-for-ibmi.showAdditionalSettings", "title": "Connection Settings", - "category": "IBM i", - "enablement": "code-for-ibmi:editingConnection !== true" + "category": "IBM i" }, { "command": "code-for-ibmi.showLoginSettings", "title": "Login Settings", - "category": "IBM i", - "enablement": "code-for-ibmi:editingConnection !== true" + "category": "IBM i" }, { "command": "code-for-ibmi.renameConnection",