mirror of
https://github.com/DeNNiiInc/dbgate.git
synced 2026-05-01 05:03:57 +00:00
forms login
This commit is contained in:
@@ -8,7 +8,8 @@ const AD = require('activedirectory2').promiseWrapper;
|
|||||||
const tokenSecret = uuidv1();
|
const tokenSecret = uuidv1();
|
||||||
|
|
||||||
function shouldAuthorizeApi() {
|
function shouldAuthorizeApi() {
|
||||||
return !!process.env.OAUTH_AUTH;
|
const logins = getLogins();
|
||||||
|
return !!process.env.OAUTH_AUTH || !!process.env.AD_URL || (!!logins && !process.env.BASIC_AUTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
function unauthorizedResponse(req, res, text) {
|
function unauthorizedResponse(req, res, text) {
|
||||||
@@ -22,7 +23,7 @@ function unauthorizedResponse(req, res, text) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function authMiddleware(req, res, next) {
|
function authMiddleware(req, res, next) {
|
||||||
const SKIP_AUTH_PATHS = ['/config/get', '/auth/oauth-token', 'auth/login', '/stream'];
|
const SKIP_AUTH_PATHS = ['/config/get', '/auth/oauth-token', '/auth/login', '/stream'];
|
||||||
|
|
||||||
if (!shouldAuthorizeApi()) {
|
if (!shouldAuthorizeApi()) {
|
||||||
return next();
|
return next();
|
||||||
@@ -85,14 +86,16 @@ module.exports = {
|
|||||||
try {
|
try {
|
||||||
const res = await ad.authenticate(login, password);
|
const res = await ad.authenticate(login, password);
|
||||||
if (!res) {
|
if (!res) {
|
||||||
return { error: 'login failed' };
|
return { error: 'Login failed' };
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
accessToken: jwt.sign({ login }, tokenSecret, { expiresIn: '1m' }),
|
accessToken: jwt.sign({ login }, tokenSecret, { expiresIn: '1m' }),
|
||||||
};
|
};
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log('Failed active directory authentization', err.message);
|
console.log('Failed active directory authentization', err.message);
|
||||||
return { error: err.message };
|
return {
|
||||||
|
error: err.message,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,7 +103,7 @@ module.exports = {
|
|||||||
if (!logins) {
|
if (!logins) {
|
||||||
return { error: 'Logins not configured' };
|
return { error: 'Logins not configured' };
|
||||||
}
|
}
|
||||||
if (logins[login] == password) {
|
if (logins.find(x => x.login == login)?.password == password) {
|
||||||
return {
|
return {
|
||||||
accessToken: jwt.sign({ login }, tokenSecret, { expiresIn: '1m' }),
|
accessToken: jwt.sign({ login }, tokenSecret, { expiresIn: '1m' }),
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ function start() {
|
|||||||
const server = http.createServer(app);
|
const server = http.createServer(app);
|
||||||
|
|
||||||
const logins = getLogins();
|
const logins = getLogins();
|
||||||
if (logins) {
|
if (logins && process.env.BASIC_AUTH) {
|
||||||
app.use(
|
app.use(
|
||||||
basicAuth({
|
basicAuth({
|
||||||
users: _.fromPairs(logins.map(x => [x.login, x.password])),
|
users: _.fromPairs(logins.map(x => [x.login, x.password])),
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { onMount } from 'svelte';
|
import { onMount } from 'svelte';
|
||||||
|
import { internalRedirectTo } from './clientAuth';
|
||||||
import FormButton from './forms/FormButton.svelte';
|
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 FormProvider from './forms/FormProvider.svelte';
|
||||||
@@ -22,15 +23,26 @@
|
|||||||
<div class="box">
|
<div class="box">
|
||||||
<div class="heading">Log In</div>
|
<div class="heading">Log In</div>
|
||||||
<FormProvider>
|
<FormProvider>
|
||||||
<FormTextField label="Username" name="login" />
|
<FormTextField label="Username" name="login" autocomplete="username" />
|
||||||
<FormPasswordField label="Password" name="password" />
|
<FormPasswordField label="Password" name="password" autocomplete="current-password" />
|
||||||
|
|
||||||
<div class="submit">
|
<div class="submit">
|
||||||
<FormSubmit
|
<FormSubmit
|
||||||
value="Log In"
|
value="Log In"
|
||||||
on:click={e => {
|
on:click={async e => {
|
||||||
enableApi();
|
enableApi();
|
||||||
apiCall('auth/login', e.detail);
|
const resp = await apiCall('auth/login', e.detail);
|
||||||
|
if (resp.error) {
|
||||||
|
internalRedirectTo(`/?page=not-logged&error=${encodeURIComponent(resp.error)}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const { accessToken } = resp;
|
||||||
|
if (accessToken) {
|
||||||
|
localStorage.setItem('accessToken', accessToken);
|
||||||
|
internalRedirectTo('/');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
internalRedirectTo(`/?page=not-logged`);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,18 +1,51 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { onMount } from 'svelte';
|
import { onMount } from 'svelte';
|
||||||
|
import FormStyledButton from './buttons/FormStyledButton.svelte';
|
||||||
|
import { redirectToLogin } from './clientAuth';
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
const removed = document.getElementById('starting_dbgate_zero');
|
const removed = document.getElementById('starting_dbgate_zero');
|
||||||
if (removed) removed.remove();
|
if (removed) removed.remove();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const params = new URLSearchParams(location.search);
|
||||||
|
const error = params.get('error');
|
||||||
|
|
||||||
|
function handleLogin() {
|
||||||
|
redirectToLogin(undefined, true);
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class='title'>Sorry, you are not authorized to run DbGate</div>
|
<div class="root theme-light theme-type-light">
|
||||||
|
<div class="title">Sorry, you are not authorized to run DbGate</div>
|
||||||
|
{#if error}
|
||||||
|
<div class="error">{error}</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<div class="button">
|
||||||
|
<FormStyledButton value="Log In" on:click={handleLogin} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
.root {
|
||||||
|
color: var(--theme-font-1);
|
||||||
|
}
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
font-size: x-large;
|
font-size: x-large;
|
||||||
margin-top: 20vh;
|
margin-top: 20vh;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.error {
|
||||||
|
margin-top: 1em;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
margin-top: 1em;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { apiCall, disableApi } from './utility/api';
|
import { apiCall, disableApi, enableApi } from './utility/api';
|
||||||
import { getConfig } from './utility/metadataLoaders';
|
import { getConfig } from './utility/metadataLoaders';
|
||||||
|
|
||||||
export function isOauthCallback() {
|
export function isOauthCallback() {
|
||||||
@@ -23,7 +23,7 @@ export function handleOauthCallback() {
|
|||||||
}).then(authResp => {
|
}).then(authResp => {
|
||||||
const { accessToken } = authResp;
|
const { accessToken } = authResp;
|
||||||
localStorage.setItem('accessToken', accessToken);
|
localStorage.setItem('accessToken', accessToken);
|
||||||
location.replace('/');
|
internalRedirectTo('/');
|
||||||
});
|
});
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -42,13 +42,21 @@ export async function handleAuthOnStartup(config) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function redirectToLogin(config = null) {
|
export async function redirectToLogin(config = null, force = false) {
|
||||||
if (!config) config = await getConfig();
|
if (!config) {
|
||||||
|
enableApi();
|
||||||
|
config = await getConfig();
|
||||||
|
}
|
||||||
|
|
||||||
if (config.isLoginForm) {
|
if (config.isLoginForm) {
|
||||||
const index = location.pathname.lastIndexOf('/');
|
if (!force) {
|
||||||
const loginPath = index >= 0 ? location.pathname.substring(0, index) + '/?page=login' : '/?page=login';
|
const params = new URLSearchParams(location.search);
|
||||||
location.replace(loginPath);
|
if (params.get('page') == 'login' || params.get('page') == 'not-logged') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
internalRedirectTo('/?page=login');
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.oauth) {
|
if (config.oauth) {
|
||||||
@@ -60,5 +68,12 @@ export async function redirectToLogin(config = null) {
|
|||||||
location.origin + location.pathname
|
location.origin + location.pathname
|
||||||
)}&state=${encodeURIComponent(state)}`
|
)}&state=${encodeURIComponent(state)}`
|
||||||
);
|
);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function internalRedirectTo(path) {
|
||||||
|
const index = location.pathname.lastIndexOf('/');
|
||||||
|
const newPath = index >= 0 ? location.pathname.substring(0, index) + path : path;
|
||||||
|
location.replace(newPath);
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
export let value;
|
export let value;
|
||||||
export let focused = false;
|
export let focused = false;
|
||||||
export let domEditor = undefined;
|
export let domEditor = undefined;
|
||||||
|
export let autocomplete = 'new-password';
|
||||||
|
|
||||||
if (focused) onMount(() => domEditor.focus());
|
if (focused) onMount(() => domEditor.focus());
|
||||||
</script>
|
</script>
|
||||||
@@ -17,5 +18,5 @@
|
|||||||
on:click
|
on:click
|
||||||
bind:this={domEditor}
|
bind:this={domEditor}
|
||||||
on:keydown
|
on:keydown
|
||||||
autocomplete="new-password"
|
{autocomplete}
|
||||||
/>
|
/>
|
||||||
|
|||||||
Reference in New Issue
Block a user