mirror of
https://github.com/DeNNiiInc/dbgate.git
synced 2026-04-22 19:16:01 +00:00
multiauth WIP
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
const { getTokenSecret, getTokenLifetime } = require('./authCommon');
|
||||
const _ = require('lodash');
|
||||
const axios = require('axios');
|
||||
const { getLogger } = require('dbgate-tools');
|
||||
const { getLogger, getPredefinedPermissions } = require('dbgate-tools');
|
||||
|
||||
const AD = require('activedirectory2').promiseWrapper;
|
||||
const jwt = require('jsonwebtoken');
|
||||
@@ -12,7 +12,15 @@ class AuthProviderBase {
|
||||
amoid = 'none';
|
||||
|
||||
async login(login, password, options = undefined) {
|
||||
return {};
|
||||
return {
|
||||
accessToken: jwt.sign(
|
||||
{
|
||||
amoid: this.amoid,
|
||||
},
|
||||
getTokenSecret(),
|
||||
{ expiresIn: getTokenLifetime() }
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
shouldAuthorizeApi() {
|
||||
@@ -57,6 +65,7 @@ class AuthProviderBase {
|
||||
toJson() {
|
||||
return {
|
||||
amoid: this.amoid,
|
||||
workflowType: 'anonymous',
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -127,12 +136,19 @@ class OAuthProvider extends AuthProviderBase {
|
||||
oauthLogout: process.env.OAUTH_LOGOUT,
|
||||
};
|
||||
}
|
||||
|
||||
toJson() {
|
||||
return {
|
||||
...super.toJson(),
|
||||
workflowType: 'redirect',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
class ADProvider extends AuthProviderBase {
|
||||
amoid = 'ad';
|
||||
|
||||
async login(login, password) {
|
||||
async login(login, password, options = undefined) {
|
||||
const adConfig = {
|
||||
url: process.env.AD_URL,
|
||||
baseDN: process.env.AD_BASEDN,
|
||||
@@ -152,7 +168,14 @@ class ADProvider extends AuthProviderBase {
|
||||
return { error: `Username ${login} not allowed to log in` };
|
||||
}
|
||||
return {
|
||||
accessToken: jwt.sign({ login }, getTokenSecret(), { expiresIn: getTokenLifetime() }),
|
||||
accessToken: jwt.sign(
|
||||
{
|
||||
amoid: this.amoid,
|
||||
login,
|
||||
},
|
||||
getTokenSecret(),
|
||||
{ expiresIn: getTokenLifetime() }
|
||||
),
|
||||
};
|
||||
} catch (e) {
|
||||
return { error: 'Login failed' };
|
||||
@@ -166,15 +189,29 @@ class ADProvider extends AuthProviderBase {
|
||||
isLoginForm() {
|
||||
return !process.env.BASIC_AUTH;
|
||||
}
|
||||
|
||||
toJson() {
|
||||
return {
|
||||
...super.toJson(),
|
||||
workflowType: 'credentials',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
class LoginsProvider extends AuthProviderBase {
|
||||
amoid = 'logins';
|
||||
|
||||
async login(login, password) {
|
||||
async login(login, password, options = undefined) {
|
||||
if (password == process.env[`LOGIN_PASSWORD_${login}`]) {
|
||||
return {
|
||||
accessToken: jwt.sign({ login }, getTokenSecret(), { expiresIn: getTokenLifetime() }),
|
||||
accessToken: jwt.sign(
|
||||
{
|
||||
amoid: this.amoid,
|
||||
login,
|
||||
},
|
||||
getTokenSecret(),
|
||||
{ expiresIn: getTokenLifetime() }
|
||||
),
|
||||
};
|
||||
}
|
||||
return { error: 'Invalid credentials' };
|
||||
@@ -187,6 +224,13 @@ class LoginsProvider extends AuthProviderBase {
|
||||
isLoginForm() {
|
||||
return !process.env.BASIC_AUTH;
|
||||
}
|
||||
|
||||
toJson() {
|
||||
return {
|
||||
...super.toJson(),
|
||||
workflowType: 'credentials',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
class DenyAllProvider extends AuthProviderBase {
|
||||
@@ -196,9 +240,16 @@ class DenyAllProvider extends AuthProviderBase {
|
||||
return true;
|
||||
}
|
||||
|
||||
async login(login, password) {
|
||||
async login(login, password, options = undefined) {
|
||||
return { error: 'Login not allowed' };
|
||||
}
|
||||
|
||||
toJson() {
|
||||
return {
|
||||
...super.toJson(),
|
||||
workflowType: 'credentials',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function hasEnvLogins() {
|
||||
|
||||
@@ -30,6 +30,9 @@
|
||||
|
||||
$: selectedConnection = availableConnections?.find(x => x.conid == $values.databaseServer);
|
||||
|
||||
$: selectedProvider = availableProviders?.find(x => x.amoid == $values.amoid);
|
||||
$: workflowType = selectedProvider?.workflowType ?? 'credentials';
|
||||
|
||||
async function loadAvailableServers(amoid) {
|
||||
if (amoid) {
|
||||
availableConnections = await apiCall('storage/get-connections-for-login-page', { amoid });
|
||||
@@ -80,7 +83,7 @@
|
||||
/>
|
||||
{/if}
|
||||
|
||||
{#if !isAdminPage && availableConnections}
|
||||
{#if !isAdminPage && availableConnections && workflowType == 'database'}
|
||||
<FormSelectField
|
||||
label="Database server"
|
||||
name="databaseServer"
|
||||
@@ -97,10 +100,12 @@
|
||||
<FormPasswordField label="Password" name="password" autocomplete="current-password" saveOnInput />
|
||||
{/if}
|
||||
{:else}
|
||||
{#if !isAdminPage}
|
||||
{#if !isAdminPage && workflowType == 'credentials'}
|
||||
<FormTextField label="Username" name="login" autocomplete="username" saveOnInput />
|
||||
{/if}
|
||||
<FormPasswordField label="Password" name="password" autocomplete="current-password" saveOnInput />
|
||||
{#if workflowType == 'credentials'}
|
||||
<FormPasswordField label="Password" name="password" autocomplete="current-password" saveOnInput />
|
||||
{/if}
|
||||
{/if}
|
||||
|
||||
{#if isAdminPage && $config && !$config.isAdminLoginForm}
|
||||
@@ -173,31 +178,38 @@
|
||||
/>
|
||||
{:else}
|
||||
<FormSubmit
|
||||
value={isAdminPage ? 'Log In as Administrator' : 'Log In'}
|
||||
value={isAdminPage
|
||||
? 'Log In as Administrator'
|
||||
: workflowType == 'redirect'
|
||||
? 'Redirect to login page'
|
||||
: 'Log In'}
|
||||
on:click={async e => {
|
||||
enableApi();
|
||||
const resp = await apiCall('auth/login', {
|
||||
amoid: $values.amoid,
|
||||
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('/');
|
||||
|
||||
if (isAdminPage || workflowType == 'credentials' || workflowType == 'anonymous') {
|
||||
const resp = await apiCall('auth/login', {
|
||||
amoid: $values.amoid,
|
||||
isAdminPage,
|
||||
...e.detail,
|
||||
});
|
||||
if (resp.error) {
|
||||
internalRedirectTo(
|
||||
`/?page=not-logged&error=${encodeURIComponent(resp.error)}&is-admin=${isAdminPage ? 'true' : ''}`
|
||||
);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
const { accessToken } = resp;
|
||||
if (accessToken) {
|
||||
localStorage.setItem(isAdminPage ? 'adminAccessToken' : 'accessToken', accessToken);
|
||||
if (isAdminPage) {
|
||||
internalRedirectTo('/?page=admin');
|
||||
} else {
|
||||
internalRedirectTo('/');
|
||||
}
|
||||
return;
|
||||
}
|
||||
internalRedirectTo(`/?page=not-logged`);
|
||||
}
|
||||
internalRedirectTo(`/?page=not-logged`);
|
||||
}}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
Reference in New Issue
Block a user