diff --git a/src/api/Configuration.ts b/src/api/Configuration.ts index 4dffbf84c..07e78b3c7 100644 --- a/src/api/Configuration.ts +++ b/src/api/Configuration.ts @@ -37,9 +37,17 @@ export interface StoredConnection { const getPasswordKey = (connectionName:string) => `${connectionName}_password`; export namespace ConnectionManager { - export function getByName(name: string): StoredConnection | undefined { + export function getByHost(host: string, caseInsensitive = false): StoredConnection | undefined { const connections = getAll(); - const index = connections.findIndex(conn => conn.name === name); + const index = connections.findIndex(conn => caseInsensitive ? conn.host.toLowerCase() === host.toLowerCase() : conn.host === host); + if (index !== -1) { + return { index, data: connections[index] }; + } + } + + export function getByName(name: string, caseInsensitive = false): StoredConnection | undefined { + const connections = getAll(); + const index = connections.findIndex(conn => caseInsensitive ? conn.name.toLowerCase() === name.toLowerCase() : conn.name === name); if (index !== -1) { return { index, data: connections[index] }; } diff --git a/src/extension.ts b/src/extension.ts index a2b4c97bc..a94ca8bec 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -19,7 +19,6 @@ import { Deployment } from "./api/local/deployment"; import { IFSFS } from "./filesystems/ifsFs"; import { LocalActionCompletionItemProvider } from "./languages/actions/completion"; import { updateLocale } from "./locale"; -import * as Sandbox from "./sandbox"; import { initialise } from "./testing"; import { CodeForIBMi, ConnectionData } from "./typings"; import { initializeConnectionBrowser } from "./views/ConnectionBrowser"; @@ -31,6 +30,8 @@ import { initializeIFSBrowser } from "./views/ifsBrowser"; import { initializeObjectBrowser } from "./views/objectBrowser"; import { initializeSearchView } from "./views/searchView"; import { SettingsUI } from "./webviews/settings"; +import { registerUriHandler } from "./uri"; +import { handleSandboxStartup } from "./sandbox"; export async function activate(context: ExtensionContext): Promise { // Use the console to output diagnostic information (console.log) and errors (console.error) @@ -105,8 +106,8 @@ export async function activate(context: ExtensionContext): Promise Deployment.initialize(context); updateLastConnectionAndServerCache(); - Sandbox.handleStartup(); - Sandbox.registerUriHandler(context); + handleSandboxStartup(); + registerUriHandler(context); console.log(`Developer environment: ${process.env.DEV}`); if (process.env.DEV) { diff --git a/src/locale/ids/en.json b/src/locale/ids/en.json index d73988885..e67815370 100644 --- a/src/locale/ids/en.json +++ b/src/locale/ids/en.json @@ -397,6 +397,10 @@ "searchView.find.message": "{0} file(s) named '{1}'", "searchView.search.message": "{0} file(s) contain(s) '{1}'", "service.certificate.exists": "Remote service certificate exists", + "uriOpen.openError": "Error opening file", + "uriOpen.hostMismatch": "A file on another host is trying to be opened. Do you want to open on the current connection instead?", + "uriOpen.missingPath": "The provided URI is missing the path attribute.", + "uriOpen.noConnection": "You must have an active connection to open a file.", "shortcut": "shortcut", "size": "Size", "skip": "Skip", diff --git a/src/sandbox.ts b/src/sandbox.ts index b7e5dd380..f26d9d4e4 100644 --- a/src/sandbox.ts +++ b/src/sandbox.ts @@ -7,96 +7,7 @@ import { instance } from "./instantiate"; import { t } from "./locale"; import { ConnectionData } from "./typings"; -export async function registerUriHandler(context: ExtensionContext) { - context.subscriptions.push( - window.registerUriHandler({ - async handleUri(uri: Uri) { - console.log(uri); - - const connection = instance.getConnection(); - - switch (uri.path) { - case `/connect`: - if (connection === undefined) { - const queryData = querystring.parse(uri.query); - - const save = queryData.save === `true`; - const server = String(queryData.server); - let user: string | string[] | undefined = queryData.user; - let pass: string | string[] | undefined = queryData.pass; - - if (server) { - if (!user) { - user = await window.showInputBox({ - title: t(`sandbox.input.user.title`), - prompt: t(`sandbox.input.user.prompt`, server) - }); - } - - if (pass) { - pass = Buffer.from(String(pass), `base64`).toString(); - } else { - pass = await window.showInputBox({ - password: true, - title: t(`sandbox.input.password.title`), - prompt: t(`sandbox.input.password.prompt`, String(user), server) - }); - } - - if (user && pass) { - const serverParts = String(server).split(`:`); - const host = serverParts[0]; - const port = serverParts.length === 2 ? Number(serverParts[1]) : 22; - - const connectionData: ConnectionData = { - host, - name: `${user}-${host}`, - username: String(user), - password: String(pass), - port - }; - - const connectionResult = await commands.executeCommand(`code-for-ibmi.connectDirect`, connectionData); - - if (connectionResult) { - await initialSetup(connectionData.username); - - if (save) { - const existingConnection = ConnectionManager.getByName(connectionData.name); - - if (!existingConnection) { - // New connection! - await ConnectionManager.storeNew(connectionData); - } - } - - } else { - window.showInformationMessage(t(`sandbox.failedToConnect.title`), { - modal: true, - detail: t(`sandbox.failedToConnect`, server, user) - }); - } - - } else { - window.showErrorMessage(t(`sandbox.noPassword`, server)); - } - } - } else { - window.showInformationMessage(t(`sandbox.failedToConnect.title`), { - modal: true, - detail: t(`sandbox.alreadyConnected`) - }); - } - - break; - } - - } - }) - ); -} - -export async function handleStartup() { +export async function handleSandboxStartup() { let server: string | undefined = env.SANDBOX_SERVER; let username: string | undefined = env.SANDBOX_USER; @@ -156,7 +67,7 @@ export async function handleStartup() { const connectionResult = await commands.executeCommand(`code-for-ibmi.connectDirect`, connectionData); if (connectionResult) { - await initialSetup(connectionData.username); + await initialSandboxSetup(connectionData.username); } else { window.showInformationMessage(t(`sandbox.noconnection.modal.title`), { @@ -167,7 +78,7 @@ export async function handleStartup() { } } -async function initialSetup(username: string) { +export async function initialSandboxSetup(username: string) { const config = instance.getConfig(); if (config) { const libraryList = config.libraryList; diff --git a/src/uri/index.ts b/src/uri/index.ts new file mode 100644 index 000000000..da27589d7 --- /dev/null +++ b/src/uri/index.ts @@ -0,0 +1,153 @@ +import querystring from "querystring"; +import { commands, ExtensionContext, Uri, window } from "vscode"; +import { ConnectionManager, GlobalConfiguration } from "../api/Configuration"; +import { instance } from "../instantiate"; +import { t } from "../locale"; +import { ConnectionData } from "../typings"; +import { initialSandboxSetup } from "../sandbox"; + +export async function registerUriHandler(context: ExtensionContext) { + context.subscriptions.push( + window.registerUriHandler({ + async handleUri(uri: Uri) { + const queryData = querystring.parse(uri.query); + + const connection = instance.getConnection(); + + switch (uri.path) { + case '/open': + if (queryData.path) { + if (queryData.host) { + const host = Array.isArray(queryData.host) ? queryData.host[0] : queryData.host; + if (connection) { + if (host !== connection.currentHost) { + const chosen = await window.showInformationMessage(t(`uriOpen.openError`), { + detail: t(`uriOpen.hostMismatch`), + modal: true + }, `Open`); + + if (chosen !== `Open`) { + return; + } + } + } else { + const connection = ConnectionManager.getByHost(host, true) || ConnectionManager.getByName(host, true); + if (connection) { + let password = await ConnectionManager.getStoredPassword(context, connection.data.name); + + if (!password) { + password = await window.showInputBox({ + password: true, + title: t(`sandbox.input.password.title`), + prompt: t(`sandbox.input.password.prompt`, connection.data.username, connection.data.host) + }); + } + + const connected = await commands.executeCommand(`code-for-ibmi.connectDirect`, { + ...connection.data, + password + }); + + if (!connected) { + window.showWarningMessage(t(`uriOpen.noConnection`)); + return; + }; + } else { + window.showWarningMessage(t(`uriOpen.noConnection`)); + return; + } + } + + const paths = Array.isArray(queryData.path) ? queryData.path : [queryData.path]; + for (const path of paths) { + commands.executeCommand(`code-for-ibmi.openEditable`, path); + } + } else { + window.showWarningMessage(t(`uriOpen.missingPath`)); + } + } else { + window.showWarningMessage(t(`uriOpen.noConnection`)); + } + break; + + case `/connect`: + if (connection === undefined) { + const save = queryData.save === `true`; + const server = String(queryData.server); + let user: string | string[] | undefined = queryData.user; + let pass: string | string[] | undefined = queryData.pass; + + if (server) { + if (!user) { + user = await window.showInputBox({ + title: t(`sandbox.input.user.title`), + prompt: t(`sandbox.input.user.prompt`, server) + }); + } + + if (pass) { + pass = Buffer.from(String(pass), `base64`).toString(); + } else { + pass = await window.showInputBox({ + password: true, + title: t(`sandbox.input.password.title`), + prompt: t(`sandbox.input.password.prompt`, String(user), server) + }); + } + + if (user && pass) { + const serverParts = String(server).split(`:`); + const host = serverParts[0]; + const port = serverParts.length === 2 ? Number(serverParts[1]) : 22; + + const connectionData: ConnectionData = { + host, + name: `${user}-${host}`, + username: String(user), + password: String(pass), + port + }; + + const connectionResult = await commands.executeCommand(`code-for-ibmi.connectDirect`, connectionData); + + if (connectionResult) { + await initialSandboxSetup(connectionData.username); + + if (save) { + const existingConnection = ConnectionManager.getByHost(host); + + if (!existingConnection) { + await ConnectionManager.storeNew({ + ...connectionData, + password: undefined, // Removes the password from the object + }); + + await ConnectionManager.setStoredPassword(context, host, pass); + } + } + + } else { + window.showInformationMessage(t(`sandbox.failedToConnect.title`), { + modal: true, + detail: t(`sandbox.failedToConnect`, server, user) + }); + } + + } else { + window.showErrorMessage(t(`sandbox.noPassword`, server)); + } + } + } else { + window.showInformationMessage(t(`sandbox.failedToConnect.title`), { + modal: true, + detail: t(`sandbox.alreadyConnected`) + }); + } + + break; + } + + } + }) + ); +} \ No newline at end of file