WIP: Add login logic
This commit is contained in:
parent
0f21339ea1
commit
791cba91d3
4 changed files with 75 additions and 7 deletions
|
@ -1,5 +1,6 @@
|
||||||
from dotenv import load_dotenv
|
from dotenv import load_dotenv
|
||||||
from fastapi import APIRouter, FastAPI
|
from fastapi import APIRouter, FastAPI
|
||||||
|
from fastapi.middleware.cors import CORSMiddleware
|
||||||
from starlette.middleware.authentication import AuthenticationMiddleware
|
from starlette.middleware.authentication import AuthenticationMiddleware
|
||||||
|
|
||||||
load_dotenv()
|
load_dotenv()
|
||||||
|
@ -47,6 +48,19 @@ def create_app():
|
||||||
app.include_router(api_v1_router)
|
app.include_router(api_v1_router)
|
||||||
app.mount(path="/v1/ocpp", app=create_ocpp_app())
|
app.mount(path="/v1/ocpp", app=create_ocpp_app())
|
||||||
|
|
||||||
|
origins = [
|
||||||
|
"http://localhost",
|
||||||
|
"http://localhost:5173",
|
||||||
|
]
|
||||||
|
|
||||||
|
app.add_middleware(
|
||||||
|
CORSMiddleware,
|
||||||
|
allow_origins=origins,
|
||||||
|
allow_credentials=True,
|
||||||
|
allow_methods=["*"],
|
||||||
|
allow_headers=["*"],
|
||||||
|
)
|
||||||
|
|
||||||
return app
|
return app
|
||||||
|
|
||||||
app = create_app()
|
app = create_app()
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { dev } from '$app/environment';
|
import { dev } from '$app/environment';
|
||||||
import { goto } from '$app/navigation';
|
import { goto } from '$app/navigation';
|
||||||
|
import { get } from 'svelte/store';
|
||||||
|
import { persistentSettings } from '$lib/persistent-store';
|
||||||
|
|
||||||
if (dev) {
|
if (dev) {
|
||||||
axios.defaults.baseURL = "http://localhost:8000/api/v1"
|
axios.defaults.baseURL = "http://localhost:8000/api/v1"
|
||||||
|
@ -28,11 +30,17 @@ function createTokenRefreshInterceptor() {
|
||||||
|
|
||||||
return axios
|
return axios
|
||||||
.post("/auth/refresh", {
|
.post("/auth/refresh", {
|
||||||
refresh_token: "",
|
refresh_token: get(persistentSettings).refreshToken,
|
||||||
})
|
})
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
// TODO: Save token
|
// Save new refresh token
|
||||||
error.response.config.headers["Authorization"] = "Bearer " + response.data.access_token;
|
persistentSettings.update(setting=> setting.refreshToken=response.data.refresh_token)
|
||||||
|
|
||||||
|
// Update access token
|
||||||
|
const authHeader = "Bearer " + response.data.access_token;
|
||||||
|
axios.defaults.headers.common['Authorization'] = authHeader;
|
||||||
|
error.response.config.headers["Authorization"] = authHeader;
|
||||||
|
|
||||||
// Retry initial request with new token
|
// Retry initial request with new token
|
||||||
return axios(error.response.config);
|
return axios(error.response.config);
|
||||||
})
|
})
|
||||||
|
@ -48,3 +56,5 @@ function createTokenRefreshInterceptor() {
|
||||||
}
|
}
|
||||||
|
|
||||||
createTokenRefreshInterceptor();
|
createTokenRefreshInterceptor();
|
||||||
|
|
||||||
|
export default axios;
|
|
@ -2,6 +2,8 @@
|
||||||
import { goto } from '$app/navigation'
|
import { goto } from '$app/navigation'
|
||||||
import { persistentSettings } from '$lib/persistent-store'
|
import { persistentSettings } from '$lib/persistent-store'
|
||||||
import i18n from '$lib/i18n'
|
import i18n from '$lib/i18n'
|
||||||
|
import axios from '$lib/axios.svelte'
|
||||||
|
|
||||||
let { children } = $props()
|
let { children } = $props()
|
||||||
|
|
||||||
if (!$persistentSettings.loggedIn) {
|
if (!$persistentSettings.loggedIn) {
|
||||||
|
@ -9,6 +11,17 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
let drawerOpen = $state(false)
|
let drawerOpen = $state(false)
|
||||||
|
|
||||||
|
function logout() {
|
||||||
|
axios.post('/auth/logout').then(() => {
|
||||||
|
$persistentSettings.email = ''
|
||||||
|
$persistentSettings.friendlyName = ''
|
||||||
|
$persistentSettings.loggedIn = false
|
||||||
|
$persistentSettings.refreshToken = ''
|
||||||
|
$persistentSettings.role = 'member'
|
||||||
|
goto('/login?logout')
|
||||||
|
})
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="w-full h-full p-4 flex flex-col bg-base-200">
|
<div class="w-full h-full p-4 flex flex-col bg-base-200">
|
||||||
|
@ -86,7 +99,7 @@
|
||||||
class="menu menu-sm dropdown-content bg-base-100 rounded-box z-1 mt-3 w-52 p-2 shadow"
|
class="menu menu-sm dropdown-content bg-base-100 rounded-box z-1 mt-3 w-52 p-2 shadow"
|
||||||
>
|
>
|
||||||
<li><a href="/profile">{$i18n.t('common:navbar.link.profile')}</a></li>
|
<li><a href="/profile">{$i18n.t('common:navbar.link.profile')}</a></li>
|
||||||
<li><a href="/login?logout">{$i18n.t('common:navbar.link.logout')}</a></li>
|
<li><button onclick={logout}>{$i18n.t('common:navbar.link.logout')}</button></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { fly } from 'svelte/transition'
|
import { fly } from 'svelte/transition'
|
||||||
import i18n from '$lib/i18n'
|
import i18n from '$lib/i18n'
|
||||||
|
import axios from '$lib/axios.svelte'
|
||||||
|
import { persistentSettings } from '$lib/persistent-store'
|
||||||
|
import { goto } from '$app/navigation'
|
||||||
$i18n.loadNamespaces('login')
|
$i18n.loadNamespaces('login')
|
||||||
|
|
||||||
const urlParams = new URLSearchParams(window.location.search)
|
const urlParams = new URLSearchParams(window.location.search)
|
||||||
|
@ -13,6 +16,29 @@
|
||||||
showToast = false
|
showToast = false
|
||||||
}, 6000)
|
}, 6000)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let email: string = $state('')
|
||||||
|
let password: string = $state('')
|
||||||
|
|
||||||
|
function login() {
|
||||||
|
axios
|
||||||
|
.post('/auth/login', {
|
||||||
|
email,
|
||||||
|
password,
|
||||||
|
})
|
||||||
|
.then((response) => {
|
||||||
|
$persistentSettings.loggedIn = true
|
||||||
|
$persistentSettings.refreshToken = response.data.refresh_token
|
||||||
|
axios.defaults.headers.common['Authorization'] = 'Bearer ' + response.data.access_token
|
||||||
|
axios.get('/me').then((response) => {
|
||||||
|
$persistentSettings.email = response.data.email
|
||||||
|
$persistentSettings.friendlyName = response.data.friendly_name
|
||||||
|
$persistentSettings.role = response.data.role
|
||||||
|
})
|
||||||
|
goto('/')
|
||||||
|
})
|
||||||
|
.catch((error) => {})
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="w-full h-full flex flex-col justify-center items-center bg-base-200">
|
<div class="w-full h-full flex flex-col justify-center items-center bg-base-200">
|
||||||
|
@ -30,13 +56,18 @@
|
||||||
<fieldset class="fieldset">
|
<fieldset class="fieldset">
|
||||||
<label class="fieldset-label input text-base-content">
|
<label class="fieldset-label input text-base-content">
|
||||||
<i class="bi bi-envelope-at"></i>
|
<i class="bi bi-envelope-at"></i>
|
||||||
<input type="email" placeholder="me@example.com" required />
|
<input type="email" bind:value={email} placeholder="me@example.com" required />
|
||||||
</label>
|
</label>
|
||||||
<label class="fieldset-label input text-base-content">
|
<label class="fieldset-label input text-base-content">
|
||||||
<i class="bi bi-key"></i>
|
<i class="bi bi-key"></i>
|
||||||
<input type="password" placeholder={$i18n.t('login:passwordPlaceholder')} required />
|
<input
|
||||||
|
type="password"
|
||||||
|
bind:value={password}
|
||||||
|
placeholder={$i18n.t('login:passwordPlaceholder')}
|
||||||
|
required
|
||||||
|
/>
|
||||||
</label>
|
</label>
|
||||||
<button class="btn btn-primary mt-4">{$i18n.t('login:button')}</button>
|
<button class="btn btn-primary mt-4" onclick={login}>{$i18n.t('login:button')}</button>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Add table
Reference in a new issue