azure auth
Some checks are pending
Run tests / test-runner (push) Waiting to run

This commit is contained in:
Jan Prochazka 2024-08-05 12:56:43 +02:00
parent fb2e261a08
commit 97aa563fe7
9 changed files with 64 additions and 37 deletions

View File

@ -252,6 +252,7 @@ module.exports = {
accessToken, accessToken,
passwordMode: undefined, passwordMode: undefined,
unsaved: true, unsaved: true,
useRedirectDbLogin: false,
}; };
if (old.passwordMode == 'askUser') { if (old.passwordMode == 'askUser') {
res.user = user; res.user = user;
@ -395,12 +396,18 @@ module.exports = {
}, },
dbloginToken_meta: true, dbloginToken_meta: true,
async dbloginToken({ code, conid, redirectUri }) { async dbloginToken({ code, conid, strmid, redirectUri }) {
const connection = await this.getCore({ conid }); try {
const driver = requireEngineDriver(connection); const connection = await this.getCore({ conid });
const accessToken = await driver.getAuthTokenFromCode(connection, { code, redirectUri }); const driver = requireEngineDriver(connection);
const volatile = await this.saveVolatile({ conid, accessToken }); const accessToken = await driver.getAuthTokenFromCode(connection, { code, redirectUri });
// console.log('******************************** WE HAVE ACCESS TOKEN', accessToken); const volatile = await this.saveVolatile({ conid, accessToken });
socket.emit('got-volatile-token', { savedConId: conid, volatileConId: volatile._id }); // console.log('******************************** WE HAVE ACCESS TOKEN', accessToken);
socket.emit('got-volatile-token', { strmid, savedConId: conid, volatileConId: volatile._id });
return { success: true };
} catch (err) {
logger.error({ err }, 'Error getting DB token');
return { error: err.message };
}
}, },
}; };

View File

@ -19,6 +19,7 @@ async function handleRefresh() {
const databases = await driver.listDatabases(systemConnection); const databases = await driver.listDatabases(systemConnection);
setStatusName('ok'); setStatusName('ok');
const databasesString = stableStringify(databases); const databasesString = stableStringify(databases);
console.log('************* DATABASES *************', databases);
if (lastDatabases != databasesString) { if (lastDatabases != databasesString) {
process.send({ msgtype: 'databases', databases }); process.send({ msgtype: 'databases', databases });
lastDatabases = databasesString; lastDatabases = databasesString;
@ -59,8 +60,11 @@ async function handleConnect(connection) {
const driver = requireEngineDriver(storedConnection); const driver = requireEngineDriver(storedConnection);
try { try {
console.log('************* CONNECTING *************');
systemConnection = await connectUtility(driver, storedConnection, 'app'); systemConnection = await connectUtility(driver, storedConnection, 'app');
console.log('************* VERSION *************');
readVersion(); readVersion();
console.log('************* REFRESH *************');
handleRefresh(); handleRefresh();
if (extractBoolSettingsValue(globalSettings, 'connection.autoRefresh', false)) { if (extractBoolSettingsValue(globalSettings, 'connection.autoRefresh', false)) {
setInterval( setInterval(

View File

@ -31,6 +31,9 @@ module.exports = {
electronSender.send(message, data == null ? null : data); electronSender.send(message, data == null ? null : data);
} }
for (const strmid in sseResponses) { for (const strmid in sseResponses) {
if (data?.strmid && data?.strmid != strmid) {
continue;
}
let skipThisStream = false; let skipThisStream = false;
if (sseResponses[strmid].filter) { if (sseResponses[strmid].filter) {
for (const key in sseResponses[strmid].filter) { for (const key in sseResponses[strmid].filter) {
@ -47,7 +50,7 @@ module.exports = {
} }
sseResponses[strmid].response?.write( sseResponses[strmid].response?.write(
`event: ${message}\ndata: ${stableStringify(data == null ? null : data)}\n\n` `event: ${message}\ndata: ${stableStringify(data == null ? null : _.omit(data, ['strmid']))}\n\n`
); );
} }
}, },

View File

@ -6,6 +6,9 @@
const config = useConfig(); const config = useConfig();
const params = new URLSearchParams(location.search);
const error = params.get('error');
onMount(() => { onMount(() => {
const removed = document.getElementById('starting_dbgate_zero'); const removed = document.getElementById('starting_dbgate_zero');
if (removed) removed.remove(); if (removed) removed.remove();
@ -21,7 +24,11 @@
<div class="box"> <div class="box">
<div class="heading">Configuration error</div> <div class="heading">Configuration error</div>
{#if !$config?.isLicenseValid} {#if !$config?.isLicenseValid}
<ErrorInfo message={`Invalid license. Please contact sales@dbgate.eu for more details. ${$config?.licenseError}`} /> <ErrorInfo
message={`Invalid license. Please contact sales@dbgate.eu for more details. ${$config?.licenseError}`}
/>
{:else if error}
<ErrorInfo message={error} />
{:else} {:else}
<ErrorInfo message="No error found, try to open app again" /> <ErrorInfo message="No error found, try to open app again" />
<div class="m-2"> <div class="m-2">

View File

@ -10,6 +10,7 @@
export let passProps; export let passProps;
$: databases = useDatabaseList({ conid: data._id }); $: databases = useDatabaseList({ conid: data._id });
console.log('USED DATABASE LIST', data._id);
</script> </script>
<AppObjectList <AppObjectList

View File

@ -47,26 +47,22 @@ export function handleOauthCallback() {
return true; return true;
} }
console.log('****************** IS DB LOGIN TEST');
if (isDbLoginCallback()) { if (isDbLoginCallback()) {
console.log('****************** IS DB LOGIN TRUE'); const [_prefix, strmid, conid] = localStorage.getItem('dbloginState').split(':');
const conid = localStorage.getItem('dbloginState').split('@')[1];
localStorage.removeItem('dbloginState'); localStorage.removeItem('dbloginState');
apiCall('connections/dblogin-token', { apiCall('connections/dblogin-token', {
code: sentCode, code: sentCode,
conid, conid,
strmid,
redirectUri: location.origin + location.pathname, redirectUri: location.origin + location.pathname,
}).then(authResp => { }).then(authResp => {
const { accessToken, error, errorMessage } = authResp; if (authResp.success) {
window.close();
if (accessToken) { } else if (authResp.error) {
console.log('Settings access token from OAUTH'); internalRedirectTo(`?page=error&error=${encodeURIComponent(authResp)}`);
localStorage.setItem('accessToken', accessToken);
internalRedirectTo('/');
} else { } else {
console.log('Error when processing OAUTH callback', error || errorMessage); internalRedirectTo(`?page=error`);
internalRedirectTo(`?page=not-logged&error=${error || errorMessage}`);
} }
}); });

View File

@ -10,9 +10,10 @@ import DatabaseLoginModal, { isDatabaseLoginVisible } from '../modals/DatabaseLo
import _ from 'lodash'; import _ from 'lodash';
import uuidv1 from 'uuid/v1'; import uuidv1 from 'uuid/v1';
import { openWebLink } from './exportFileTools'; import { openWebLink } from './exportFileTools';
import { callServerPing } from './connectionsPinger';
import { batchDispatchCacheTriggers, dispatchCacheChange } from './cache';
export const strmid = uuidv1(); export const strmid = uuidv1();
const privateApiState = Math.random().toString().substr(2);
let eventSource; let eventSource;
let apiLogging = false; let apiLogging = false;
@ -66,7 +67,7 @@ function processApiResponse(route, args, resp) {
if (resp?.missingCredentials) { if (resp?.missingCredentials) {
if (resp.detail.redirectToDbLogin) { if (resp.detail.redirectToDbLogin) {
const state = `dbg-dblogin:${privateApiState}@${resp.detail.conid}`; const state = `dbg-dblogin:${strmid}:${resp.detail.conid}`;
localStorage.setItem('dbloginState', state); localStorage.setItem('dbloginState', state);
openWebLink( openWebLink(
`connections/dblogin?conid=${resp.detail.conid}&state=${encodeURIComponent(state)}&redirectUri=${ `connections/dblogin?conid=${resp.detail.conid}&state=${encodeURIComponent(state)}&redirectUri=${
@ -224,8 +225,12 @@ export function getVolatileConnections() {
} }
export function installNewVolatileConnectionListener() { export function installNewVolatileConnectionListener() {
apiOn('got-volatile-token', ({ savedConId, volatileConId }) => { apiOn('got-volatile-token', async ({ savedConId, volatileConId }) => {
console.log('************************** GOT VOLASTILE TOKEN', savedConId, volatileConId);
setVolatileConnectionRemapping(savedConId, volatileConId); setVolatileConnectionRemapping(savedConId, volatileConId);
await callServerPing();
dispatchCacheChange({ key: `server-status-changed` });
batchDispatchCacheTriggers(x => x.conid == savedConId);
}); });
} }

View File

@ -1,7 +1,6 @@
import _ from 'lodash'; import _ from 'lodash';
import { openedConnections, currentDatabase, openedConnectionsWithTemporary, getCurrentConfig, getOpenedConnections } from '../stores'; import { currentDatabase, openedConnectionsWithTemporary, getCurrentConfig, getOpenedConnections } from '../stores';
import { apiCall, getVolatileConnections, strmid } from './api'; import { apiCall, getVolatileConnections, strmid } from './api';
import { getConnectionList } from './metadataLoaders';
import hasPermission from '../utility/hasPermission'; import hasPermission from '../utility/hasPermission';
// const doServerPing = async value => { // const doServerPing = async value => {

View File

@ -2,6 +2,7 @@ const _ = require('lodash');
const stream = require('stream'); const stream = require('stream');
const tedious = require('tedious'); const tedious = require('tedious');
const makeUniqueColumnNames = require('./makeUniqueColumnNames'); const makeUniqueColumnNames = require('./makeUniqueColumnNames');
const { getAzureAuthOptions } = require('./azureAuth');
function extractTediousColumns(columns, addDriverNativeColumn = false) { function extractTediousColumns(columns, addDriverNativeColumn = false) {
const res = columns.map(col => { const res = columns.map(col => {
@ -22,10 +23,11 @@ function extractTediousColumns(columns, addDriverNativeColumn = false) {
return res; return res;
} }
async function tediousConnect({ server, port, user, password, database, ssl, trustServerCertificate, windowsDomain }) { async function tediousConnect(storedConnection) {
const { server, port, user, password, database, ssl, trustServerCertificate, windowsDomain, authType } = storedConnection;
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const connectionOptions = { const connectionOptions = {
encrypt: !!ssl, encrypt: !!ssl || authType == 'msentra',
cryptoCredentialsDetails: ssl ? _.pick(ssl, ['ca', 'cert', 'key']) : undefined, cryptoCredentialsDetails: ssl ? _.pick(ssl, ['ca', 'cert', 'key']) : undefined,
trustServerCertificate: ssl ? (!ssl.ca && !ssl.cert && !ssl.key ? true : ssl.rejectUnauthorized) : undefined, trustServerCertificate: ssl ? (!ssl.ca && !ssl.cert && !ssl.key ? true : ssl.rejectUnauthorized) : undefined,
enableArithAbort: true, enableArithAbort: true,
@ -40,18 +42,21 @@ async function tediousConnect({ server, port, user, password, database, ssl, tru
connectionOptions.database = database; connectionOptions.database = database;
} }
const authentication =
authType == 'msentra'
? getAzureAuthOptions(storedConnection)
: {
type: windowsDomain ? 'ntlm' : 'default',
options: {
userName: user,
password: password,
...(windowsDomain ? { domain: windowsDomain } : {}),
},
};
const connection = new tedious.Connection({ const connection = new tedious.Connection({
server, server,
authentication,
authentication: {
type: windowsDomain ? 'ntlm' : 'default',
options: {
userName: user,
password: password,
...(windowsDomain ? { domain: windowsDomain } : {}),
},
},
options: connectionOptions, options: connectionOptions,
}); });
connection.on('connect', function (err) { connection.on('connect', function (err) {