feat: auth store, router guard and login page
This commit is contained in:
parent
26e3efed81
commit
19aca0e5fc
@ -1,4 +1,5 @@
|
|||||||
import { createRouter, createWebHistory } from 'vue-router'
|
import { createRouter, createWebHistory } from 'vue-router'
|
||||||
|
import { useAuthStore } from '../stores/auth'
|
||||||
|
|
||||||
const router = createRouter({
|
const router = createRouter({
|
||||||
history: createWebHistory(),
|
history: createWebHistory(),
|
||||||
@ -9,4 +10,11 @@ const router = createRouter({
|
|||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
|
router.beforeEach((to) => {
|
||||||
|
if (to.meta.public) return true
|
||||||
|
const auth = useAuthStore()
|
||||||
|
if (!auth.isAuthenticated) return '/login'
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
|
||||||
export default router
|
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