dblogin auth

This commit is contained in:
Jan Prochazka
2024-08-05 17:00:29 +02:00
parent 17fd9035ee
commit 04b195f4c6
4 changed files with 121 additions and 35 deletions

View File

@@ -9,7 +9,7 @@ const jwt = require('jsonwebtoken');
const logger = getLogger('authProvider'); const logger = getLogger('authProvider');
class AuthProviderBase { class AuthProviderBase {
async login(login, password) { async login(login, password, options = undefined) {
return {}; return {};
} }

View File

@@ -27,6 +27,8 @@ function authMiddleware(req, res, next) {
'/auth/login', '/auth/login',
'/stream', '/stream',
'storage/get-connections-for-login-page', 'storage/get-connections-for-login-page',
'/connections/dblogin',
'/connections/dblogin-auth',
]; ];
// console.log('********************* getAuthProvider()', getAuthProvider()); // console.log('********************* getAuthProvider()', getAuthProvider());

View File

@@ -17,6 +17,7 @@ const platformInfo = require('../utility/platformInfo');
const { connectionHasPermission, testConnectionPermission } = require('../utility/hasPermission'); const { connectionHasPermission, testConnectionPermission } = require('../utility/hasPermission');
const pipeForkLogs = require('../utility/pipeForkLogs'); const pipeForkLogs = require('../utility/pipeForkLogs');
const requireEngineDriver = require('../utility/requireEngineDriver'); const requireEngineDriver = require('../utility/requireEngineDriver');
const { getAuthProvider } = require('../auth/authProvider');
const logger = getLogger('connections'); const logger = getLogger('connections');
@@ -410,4 +411,14 @@ module.exports = {
return { error: err.message }; return { error: err.message };
} }
}, },
dbloginAuth_meta: true,
async dbloginAuth({ conid, user, password }) {
const saveResp = await this.saveVolatile({ conid, user, password, test: true });
if (saveResp.msgtype == 'connected') {
const loginResp = await getAuthProvider().login(user, password, { conid: saveResp._id });
return loginResp;
}
return saveResp;
},
}; };

View File

@@ -1,30 +1,36 @@
<script lang="ts"> <script lang="ts">
import { onMount } from 'svelte'; import { onMount } from 'svelte';
import { internalRedirectTo } from './clientAuth'; import { internalRedirectTo } from './clientAuth';
import FormButton from './forms/FormButton.svelte';
import FormPasswordField from './forms/FormPasswordField.svelte'; import FormPasswordField from './forms/FormPasswordField.svelte';
import FormProvider from './forms/FormProvider.svelte';
import FormSubmit from './forms/FormSubmit.svelte'; import FormSubmit from './forms/FormSubmit.svelte';
import FormTextField from './forms/FormTextField.svelte'; import FormTextField from './forms/FormTextField.svelte';
import { apiCall, enableApi } from './utility/api'; import { apiCall, enableApi, strmid } from './utility/api';
import { useConfig } from './utility/metadataLoaders'; import { useConfig } from './utility/metadataLoaders';
import ErrorInfo from './elements/ErrorInfo.svelte'; import ErrorInfo from './elements/ErrorInfo.svelte';
import FormSelectField from './forms/FormSelectField.svelte'; import FormSelectField from './forms/FormSelectField.svelte';
import { writable } from 'svelte/store'; import { writable } from 'svelte/store';
import FormProviderCore from './forms/FormProviderCore.svelte'; import FormProviderCore from './forms/FormProviderCore.svelte';
import { openWebLink } from './utility/exportFileTools';
import FontIcon from './icons/FontIcon.svelte';
import createRef from './utility/createRef';
export let isAdminPage; export let isAdminPage;
const config = useConfig(); const config = useConfig();
let availableConnections = null; let availableConnections = null;
let isTesting = false;
const testIdRef = createRef(0);
let sqlConnectResult;
const values = writable({}); const values = writable({ databaseServer: null });
$: selectedConnection = availableConnections?.find(x => x.conid == $values.databaseServer);
async function loadAvailableServers() { async function loadAvailableServers() {
availableConnections = await apiCall('storage/get-connections-for-login-page'); availableConnections = await apiCall('storage/get-connections-for-login-page');
if (availableConnections?.length > 0) { if (availableConnections?.length > 0) {
values.set({ databaseServer: availableConnections[0].id }); values.set({ databaseServer: availableConnections[0].conid });
} }
} }
@@ -52,20 +58,86 @@
label="Database server" label="Database server"
name="databaseServer" name="databaseServer"
isNative isNative
options={availableConnections.map(conn => ({ value: conn.id, label: conn.label }))} options={availableConnections.map(conn => ({ value: conn.conid, label: conn.label }))}
/> />
{/if} {/if}
{#if selectedConnection}
{#if selectedConnection.passwordMode == 'askUser'}
<FormTextField label="Username" name="login" autocomplete="username" saveOnInput />
{/if}
{#if selectedConnection.passwordMode == 'askUser' || selectedConnection.passwordMode == 'askPassword'}
<FormPasswordField label="Password" name="password" autocomplete="current-password" saveOnInput />
{/if}
{:else}
{#if !isAdminPage} {#if !isAdminPage}
<FormTextField label="Username" name="login" autocomplete="username" saveOnInput /> <FormTextField label="Username" name="login" autocomplete="username" saveOnInput />
{/if} {/if}
<FormPasswordField label="Password" name="password" autocomplete="current-password" saveOnInput /> <FormPasswordField label="Password" name="password" autocomplete="current-password" saveOnInput />
{/if}
{#if isAdminPage && $config && !$config.isAdminLoginForm} {#if isAdminPage && $config && !$config.isAdminLoginForm}
<ErrorInfo message="Admin login is not configured. Please set ADMIN_PASSWORD environment variable" /> <ErrorInfo message="Admin login is not configured. Please set ADMIN_PASSWORD environment variable" />
{/if} {/if}
{#if isTesting}
<div class="ml-5">
<FontIcon icon="icon loading" /> Testing connection
</div>
{/if}
{#if !isTesting && sqlConnectResult && sqlConnectResult.msgtype == 'error'}
<div class="error-result ml-5">
Connect failed: <FontIcon icon="img error" />
{sqlConnectResult.error}
</div>
{/if}
<div class="submit"> <div class="submit">
{#if selectedConnection?.useRedirectDbLogin}
<FormSubmit
value="Open database login page"
on:click={async e => {
const state = `dbg-dblogin:${strmid}:${selectedConnection?.conid}`;
localStorage.setItem('dbloginState', state);
openWebLink(
`connections/dblogin?conid=${selectedConnection?.conid}&state=${encodeURIComponent(state)}&redirectUri=${
location.origin + location.pathname
}`
);
// internalRedirectTo(
// `connections/dblogin?conid=${selectedConnection?.conid}&state=${encodeURIComponent(state)}&redirectUri=${
// location.origin + location.pathname
// }`
// );
}}
/>
{:else if selectedConnection}
<FormSubmit
value="Log In"
on:click={async e => {
if (selectedConnection.passwordMode == 'askUser' || selectedConnection.passwordMode == 'askPassword') {
enableApi();
isTesting = true;
testIdRef.update(x => x + 1);
const testid = testIdRef.get();
const resp = await apiCall('connections/dblogin-auth', {
conid: selectedConnection.conid,
user: $values['login'],
password: $values['password'],
});
if (testIdRef.get() != testid) return;
isTesting = false;
if (resp.accessToken) {
localStorage.setItem('accessToken', resp.accessToken);
internalRedirectTo('?');
} else {
sqlConnectResult = resp;
}
}
}}
/>
{:else}
<FormSubmit <FormSubmit
value={isAdminPage ? 'Log In as Administrator' : 'Log In'} value={isAdminPage ? 'Log In as Administrator' : 'Log In'}
on:click={async e => { on:click={async e => {
@@ -93,6 +165,7 @@
internalRedirectTo(`?page=not-logged`); internalRedirectTo(`?page=not-logged`);
}} }}
/> />
{/if}
</div> </div>
</FormProviderCore> </FormProviderCore>
</div> </div>