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,47 +58,114 @@
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 !isAdminPage} {#if selectedConnection}
<FormTextField label="Username" name="login" autocomplete="username" saveOnInput /> {#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}
<FormTextField label="Username" name="login" autocomplete="username" saveOnInput />
{/if}
<FormPasswordField label="Password" name="password" autocomplete="current-password" saveOnInput />
{/if} {/if}
<FormPasswordField label="Password" name="password" autocomplete="current-password" saveOnInput />
{#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">
<FormSubmit {#if selectedConnection?.useRedirectDbLogin}
value={isAdminPage ? 'Log In as Administrator' : 'Log In'} <FormSubmit
on:click={async e => { value="Open database login page"
enableApi(); on:click={async e => {
const resp = await apiCall('auth/login', { const state = `dbg-dblogin:${strmid}:${selectedConnection?.conid}`;
isAdminPage, localStorage.setItem('dbloginState', state);
...e.detail, openWebLink(
}); `connections/dblogin?conid=${selectedConnection?.conid}&state=${encodeURIComponent(state)}&redirectUri=${
if (resp.error) { location.origin + location.pathname
internalRedirectTo( }`
`?page=not-logged&error=${encodeURIComponent(resp.error)}&is-admin=${isAdminPage ? 'true' : ''}`
); );
return; // internalRedirectTo(
} // `connections/dblogin?conid=${selectedConnection?.conid}&state=${encodeURIComponent(state)}&redirectUri=${
const { accessToken } = resp; // location.origin + location.pathname
if (accessToken) { // }`
localStorage.setItem(isAdminPage ? 'adminAccessToken' : 'accessToken', accessToken); // );
if (isAdminPage) { }}
internalRedirectTo('?page=admin'); />
} else { {:else if selectedConnection}
internalRedirectTo('?'); <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;
}
} }
return; }}
} />
internalRedirectTo(`?page=not-logged`); {:else}
}} <FormSubmit
/> value={isAdminPage ? 'Log In as Administrator' : 'Log In'}
on:click={async e => {
enableApi();
const resp = await apiCall('auth/login', {
isAdminPage,
...e.detail,
});
if (resp.error) {
internalRedirectTo(
`?page=not-logged&error=${encodeURIComponent(resp.error)}&is-admin=${isAdminPage ? 'true' : ''}`
);
return;
}
const { accessToken } = resp;
if (accessToken) {
localStorage.setItem(isAdminPage ? 'adminAccessToken' : 'accessToken', accessToken);
if (isAdminPage) {
internalRedirectTo('?page=admin');
} else {
internalRedirectTo('?');
}
return;
}
internalRedirectTo(`?page=not-logged`);
}}
/>
{/if}
</div> </div>
</FormProviderCore> </FormProviderCore>
</div> </div>