WIP: Add login logic

This commit is contained in:
Oliver Traber 2025-03-27 21:35:15 +00:00
parent 0f21339ea1
commit 791cba91d3
Signed by: Bluemedia
GPG key ID: C0674B105057136C
4 changed files with 75 additions and 7 deletions

View file

@ -1,5 +1,6 @@
from dotenv import load_dotenv
from fastapi import APIRouter, FastAPI
from fastapi.middleware.cors import CORSMiddleware
from starlette.middleware.authentication import AuthenticationMiddleware
load_dotenv()
@ -47,6 +48,19 @@ def create_app():
app.include_router(api_v1_router)
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
app = create_app()

View file

@ -1,6 +1,8 @@
import axios from 'axios';
import { dev } from '$app/environment';
import { goto } from '$app/navigation';
import { get } from 'svelte/store';
import { persistentSettings } from '$lib/persistent-store';
if (dev) {
axios.defaults.baseURL = "http://localhost:8000/api/v1"
@ -28,11 +30,17 @@ function createTokenRefreshInterceptor() {
return axios
.post("/auth/refresh", {
refresh_token: "",
refresh_token: get(persistentSettings).refreshToken,
})
.then((response) => {
// TODO: Save token
error.response.config.headers["Authorization"] = "Bearer " + response.data.access_token;
// Save new refresh 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
return axios(error.response.config);
})
@ -48,3 +56,5 @@ function createTokenRefreshInterceptor() {
}
createTokenRefreshInterceptor();
export default axios;

View file

@ -2,6 +2,8 @@
import { goto } from '$app/navigation'
import { persistentSettings } from '$lib/persistent-store'
import i18n from '$lib/i18n'
import axios from '$lib/axios.svelte'
let { children } = $props()
if (!$persistentSettings.loggedIn) {
@ -9,6 +11,17 @@
}
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>
<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"
>
<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>
</div>
</div>

View file

@ -1,6 +1,9 @@
<script lang="ts">
import { fly } from 'svelte/transition'
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')
const urlParams = new URLSearchParams(window.location.search)
@ -13,6 +16,29 @@
showToast = false
}, 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>
<div class="w-full h-full flex flex-col justify-center items-center bg-base-200">
@ -30,13 +56,18 @@
<fieldset class="fieldset">
<label class="fieldset-label input text-base-content">
<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 class="fieldset-label input text-base-content">
<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>
<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>
</div>
</div>