diff --git a/package.json b/package.json index d3746f15..f6e4d37e 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "start:api:portal": "yarn workspace dbgate-api start:portal", "start:api:singledb": "yarn workspace dbgate-api start:singledb", "start:api:auth": "yarn workspace dbgate-api start:auth", + "start:api:dblogin": "yarn workspace dbgate-api start:dblogin", "start:web": "yarn workspace dbgate-web dev", "start:sqltree": "yarn workspace dbgate-sqltree start", "start:tools": "yarn workspace dbgate-tools start", diff --git a/packages/api/env/dblogin/.env b/packages/api/env/dblogin/.env new file mode 100644 index 00000000..db6b9bb0 --- /dev/null +++ b/packages/api/env/dblogin/.env @@ -0,0 +1,11 @@ +DEVMODE=1 + +CONNECTIONS=mysql + +LABEL_mysql=MySql localhost +SERVER_mysql=localhost +USER_mysql=root +PORT_mysql=3306 +# PASSWORD_mysql=Pwd2020Db +ENGINE_mysql=mysql@dbgate-plugin-mysql +PASSWORD_MODE_mysql=askPassword diff --git a/packages/api/package.json b/packages/api/package.json index 27e7ba1c..64caf1d1 100644 --- a/packages/api/package.json +++ b/packages/api/package.json @@ -60,6 +60,7 @@ "start:portal": "env-cmd -f env/portal/.env node src/index.js --listen-api", "start:singledb": "env-cmd -f env/singledb/.env node src/index.js --listen-api", "start:auth": "env-cmd -f env/auth/.env node src/index.js --listen-api", + "start:dblogin": "env-cmd -f env/dblogin/.env node src/index.js --listen-api", "start:filedb": "env-cmd node src/index.js /home/jena/test/chinook/Chinook.db --listen-api", "start:singleconn": "env-cmd node src/index.js --server localhost --user root --port 3307 --engine mysql@dbgate-plugin-mysql --password test --listen-api", "ts": "tsc", diff --git a/packages/api/src/controllers/connections.js b/packages/api/src/controllers/connections.js index bf967bd0..8757deec 100644 --- a/packages/api/src/controllers/connections.js +++ b/packages/api/src/controllers/connections.js @@ -52,6 +52,7 @@ function getPortalCollections() { server: process.env[`SERVER_${id}`], user: process.env[`USER_${id}`], password: process.env[`PASSWORD_${id}`], + passwordMode: process.env[`PASSWORD_MODE_${id}`], port: process.env[`PORT_${id}`], databaseUrl: process.env[`URL_${id}`], useDatabaseUrl: !!process.env[`URL_${id}`], @@ -204,7 +205,7 @@ module.exports = { }, saveVolatile_meta: true, - async saveVolatile({ conid, user, password }) { + async saveVolatile({ conid, user, password, test }) { const old = await this.getCore({ conid }); const res = { ...old, @@ -217,8 +218,20 @@ module.exports = { res.user = user; } - volatileConnections[res._id] = res; - return res; + if (test) { + const testRes = await this.test(res); + if (testRes.msgtype == 'connected') { + volatileConnections[res._id] = res; + return { + ...res, + msgtype: 'connected', + }; + } + return testRes; + } else { + volatileConnections[res._id] = res; + return res; + } }, save_meta: true, diff --git a/packages/api/src/controllers/serverConnections.js b/packages/api/src/controllers/serverConnections.js index 2ed0189a..831dda44 100644 --- a/packages/api/src/controllers/serverConnections.js +++ b/packages/api/src/controllers/serverConnections.js @@ -131,9 +131,9 @@ module.exports = { }, ping_meta: true, - async ping({ connections }) { + async ping({ conidArray }) { await Promise.all( - _.uniq(connections).map(async conid => { + _.uniq(conidArray).map(async conid => { const last = this.lastPinged[conid]; if (last && new Date().getTime() - last < 30 * 1000) { return Promise.resolve(); diff --git a/packages/web/src/modals/DatabaseLoginModal.svelte b/packages/web/src/modals/DatabaseLoginModal.svelte index e5c14ddc..d4991aea 100644 --- a/packages/web/src/modals/DatabaseLoginModal.svelte +++ b/packages/web/src/modals/DatabaseLoginModal.svelte @@ -11,15 +11,20 @@ import { onDestroy, onMount } from 'svelte'; import { writable } from 'svelte/store'; import FormStyledButton from '../buttons/FormStyledButton.svelte'; + import Link from '../elements/Link.svelte'; import FormPasswordField from '../forms/FormPasswordField.svelte'; import FormProviderCore from '../forms/FormProviderCore.svelte'; import FormSubmit from '../forms/FormSubmit.svelte'; import FormTextField from '../forms/FormTextField.svelte'; + import FontIcon from '../icons/FontIcon.svelte'; import { apiCall, setVolatileConnectionRemapping } from '../utility/api'; + import { dispatchCacheChange } from '../utility/cache'; + import createRef from '../utility/createRef'; import { getConnectionInfo } from '../utility/metadataLoaders'; + import ErrorMessageModal from './ErrorMessageModal.svelte'; import ModalBase from './ModalBase.svelte'; - import { closeCurrentModal } from './modalTools'; + import { closeCurrentModal, showModal } from './modalTools'; export let conid; export let passwordMode; @@ -27,6 +32,10 @@ const values = writable({}); let connection; + let isTesting; + let sqlConnectResult; + const testIdRef = createRef(0); + currentModalConid = conid; onMount(async () => { @@ -44,14 +53,31 @@ currentModalConid = null; }); + function handleCancelTest() { + testIdRef.update(x => x + 1); // invalidate current test + isTesting = false; + } + async function handleSubmit(ev) { - const con = await apiCall('connections/save-volatile', { + isTesting = true; + testIdRef.update(x => x + 1); + const testid = testIdRef.get(); + const resp = await apiCall('connections/save-volatile', { conid, user: ev.detail.user, password: ev.detail.password, + test: true, }); - setVolatileConnectionRemapping(conid, con._id); - closeCurrentModal(); + if (testIdRef.get() != testid) return; + isTesting = false; + if (resp.msgtype == 'connected') { + setVolatileConnectionRemapping(conid, resp._id); + dispatchCacheChange(`database-list-changed-${conid}`); + dispatchCacheChange(`server-status-changed`); + closeCurrentModal(); + } else { + sqlConnectResult = resp; + } } @@ -74,9 +100,36 @@ focused={passwordMode == 'askPassword'} /> + {#if isTesting} +