feat: auth store, router guard and login page
This commit is contained in:
parent
26e3efed81
commit
19aca0e5fc
@ -1,12 +1,20 @@
|
||||
import { createRouter, createWebHistory } from 'vue-router'
|
||||
import { useAuthStore } from '../stores/auth'
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHistory(),
|
||||
routes: [
|
||||
{ path: '/login', component: () => import('../views/LoginView.vue'), meta: { public: true } },
|
||||
{ path: '/', component: () => import('../views/DashboardView.vue') },
|
||||
{ path: '/', component: () => import('../views/DashboardView.vue') },
|
||||
{ path: '/transactions', component: () => import('../views/TransactionsView.vue') },
|
||||
],
|
||||
})
|
||||
|
||||
router.beforeEach((to) => {
|
||||
if (to.meta.public) return true
|
||||
const auth = useAuthStore()
|
||||
if (!auth.isAuthenticated) return '/login'
|
||||
return true
|
||||
})
|
||||
|
||||
export default router
|
||||
|
||||
30
src/AccountTracking.Web/src/stores/auth.ts
Normal file
30
src/AccountTracking.Web/src/stores/auth.ts
Normal file
@ -0,0 +1,30 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import { ref, computed } from 'vue'
|
||||
import { authApi } from '../api'
|
||||
|
||||
export const useAuthStore = defineStore('auth', () => {
|
||||
const token = ref<string | null>(localStorage.getItem('token'))
|
||||
const expiresAt = ref<string | null>(localStorage.getItem('expiresAt'))
|
||||
|
||||
const isAuthenticated = computed(() => {
|
||||
if (!token.value || !expiresAt.value) return false
|
||||
return Date.now() < Date.parse(expiresAt.value)
|
||||
})
|
||||
|
||||
async function login(username: string, password: string): Promise<void> {
|
||||
const response = await authApi.login({ username, password })
|
||||
token.value = response.token ?? null
|
||||
expiresAt.value = response.expiresAt ?? null
|
||||
if (token.value) localStorage.setItem('token', token.value)
|
||||
if (expiresAt.value) localStorage.setItem('expiresAt', expiresAt.value)
|
||||
}
|
||||
|
||||
function logout() {
|
||||
token.value = null
|
||||
expiresAt.value = null
|
||||
localStorage.removeItem('token')
|
||||
localStorage.removeItem('expiresAt')
|
||||
}
|
||||
|
||||
return { token, isAuthenticated, login, logout }
|
||||
})
|
||||
@ -1 +1,65 @@
|
||||
<template><div>Login</div></template>
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useAuthStore } from '../stores/auth'
|
||||
|
||||
const router = useRouter()
|
||||
const auth = useAuthStore()
|
||||
|
||||
const username = ref('')
|
||||
const password = ref('')
|
||||
const error = ref('')
|
||||
const loading = ref(false)
|
||||
|
||||
async function submit() {
|
||||
error.value = ''
|
||||
loading.value = true
|
||||
try {
|
||||
await auth.login(username.value, password.value)
|
||||
router.push('/')
|
||||
} catch {
|
||||
error.value = 'Nesprávné přihlašovací údaje.'
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<v-container class="fill-height" fluid>
|
||||
<v-row align="center" justify="center">
|
||||
<v-col cols="12" sm="8" md="4">
|
||||
<v-card>
|
||||
<v-card-title class="text-h5 pa-6">Finance Tracker</v-card-title>
|
||||
<v-card-text>
|
||||
<v-alert v-if="error" type="error" class="mb-4">{{ error }}</v-alert>
|
||||
<v-text-field
|
||||
v-model="username"
|
||||
label="Uživatelské jméno"
|
||||
prepend-inner-icon="mdi-account"
|
||||
@keyup.enter="submit"
|
||||
/>
|
||||
<v-text-field
|
||||
v-model="password"
|
||||
label="Heslo"
|
||||
type="password"
|
||||
prepend-inner-icon="mdi-lock"
|
||||
@keyup.enter="submit"
|
||||
/>
|
||||
</v-card-text>
|
||||
<v-card-actions class="pa-6 pt-0">
|
||||
<v-btn
|
||||
block
|
||||
color="primary"
|
||||
size="large"
|
||||
:loading="loading"
|
||||
@click="submit"
|
||||
>
|
||||
Přihlásit se
|
||||
</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-container>
|
||||
</template>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user