340 lines
6.9 KiB
JavaScript
340 lines
6.9 KiB
JavaScript
import { defineStore } from 'pinia'
|
|
import { ref } from 'vue'
|
|
import { API_BASE_URL } from '@/config/api'
|
|
|
|
const API_URL = API_BASE_URL
|
|
|
|
export const useAuthStore = defineStore('auth', () => {
|
|
const user = ref(null)
|
|
const token = ref(null)
|
|
const isAuthenticated = ref(false)
|
|
const isLoading = ref(false)
|
|
|
|
/**
|
|
* Token in localStorage speichern
|
|
*/
|
|
const saveToken = (newToken) => {
|
|
token.value = newToken
|
|
localStorage.setItem('timeclock_token', newToken)
|
|
}
|
|
|
|
/**
|
|
* Token aus localStorage laden
|
|
*/
|
|
const loadToken = () => {
|
|
const savedToken = localStorage.getItem('timeclock_token')
|
|
if (savedToken) {
|
|
token.value = savedToken
|
|
return savedToken
|
|
}
|
|
return null
|
|
}
|
|
|
|
/**
|
|
* Token und Benutzerdaten löschen
|
|
*/
|
|
const clearAuth = () => {
|
|
token.value = null
|
|
user.value = null
|
|
isAuthenticated.value = false
|
|
localStorage.removeItem('timeclock_token')
|
|
}
|
|
|
|
/**
|
|
* Registrierung
|
|
*/
|
|
const register = async (userData) => {
|
|
try {
|
|
isLoading.value = true
|
|
|
|
const response = await fetch(`${API_URL}/auth/register`, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json'
|
|
},
|
|
body: JSON.stringify(userData)
|
|
})
|
|
|
|
const data = await response.json()
|
|
|
|
if (!response.ok) {
|
|
throw new Error(data.error || 'Registrierung fehlgeschlagen')
|
|
}
|
|
|
|
return data
|
|
} catch (error) {
|
|
console.error('Registrierungsfehler:', error)
|
|
throw error
|
|
} finally {
|
|
isLoading.value = false
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Login
|
|
*/
|
|
const login = async (credentials) => {
|
|
try {
|
|
isLoading.value = true
|
|
|
|
const response = await fetch(`${API_URL}/auth/login`, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json'
|
|
},
|
|
body: JSON.stringify(credentials)
|
|
})
|
|
|
|
const data = await response.json()
|
|
|
|
if (!response.ok) {
|
|
throw new Error(data.error || 'Login fehlgeschlagen')
|
|
}
|
|
|
|
// Token speichern
|
|
saveToken(data.token)
|
|
|
|
// Benutzerdaten setzen
|
|
user.value = data.user
|
|
isAuthenticated.value = true
|
|
|
|
return data
|
|
} catch (error) {
|
|
console.error('Login-Fehler:', error)
|
|
clearAuth()
|
|
throw error
|
|
} finally {
|
|
isLoading.value = false
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Logout
|
|
*/
|
|
const logout = async () => {
|
|
try {
|
|
if (token.value) {
|
|
await fetch(`${API_URL}/auth/logout`, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Authorization': `Bearer ${token.value}`
|
|
}
|
|
})
|
|
}
|
|
} catch (error) {
|
|
console.error('Logout-Fehler:', error)
|
|
} finally {
|
|
clearAuth()
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Aktuellen Benutzer laden (für Session-Wiederherstellung)
|
|
*/
|
|
const fetchCurrentUser = async () => {
|
|
try {
|
|
const savedToken = loadToken()
|
|
|
|
if (!savedToken) {
|
|
return false
|
|
}
|
|
|
|
isLoading.value = true
|
|
|
|
const response = await fetch(`${API_URL}/auth/me`, {
|
|
headers: {
|
|
'Authorization': `Bearer ${savedToken}`
|
|
}
|
|
})
|
|
|
|
const data = await response.json()
|
|
|
|
if (!response.ok) {
|
|
// Token ungültig - ausloggen
|
|
clearAuth()
|
|
return false
|
|
}
|
|
|
|
// Session wiederherstellen
|
|
user.value = data.user
|
|
isAuthenticated.value = true
|
|
|
|
return true
|
|
} catch (error) {
|
|
console.error('Fehler beim Laden des Benutzers:', error)
|
|
clearAuth()
|
|
return false
|
|
} finally {
|
|
isLoading.value = false
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Token validieren
|
|
*/
|
|
const validateToken = async () => {
|
|
try {
|
|
const savedToken = loadToken()
|
|
|
|
if (!savedToken) {
|
|
return false
|
|
}
|
|
|
|
const response = await fetch(`${API_URL}/auth/validate`, {
|
|
headers: {
|
|
'Authorization': `Bearer ${savedToken}`
|
|
}
|
|
})
|
|
|
|
if (!response.ok) {
|
|
clearAuth()
|
|
return false
|
|
}
|
|
|
|
return true
|
|
} catch (error) {
|
|
console.error('Token-Validierungsfehler:', error)
|
|
clearAuth()
|
|
return false
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Passwort-Reset anfordern
|
|
*/
|
|
const requestPasswordReset = async (email) => {
|
|
try {
|
|
isLoading.value = true
|
|
|
|
const response = await fetch(`${API_URL}/auth/request-reset`, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json'
|
|
},
|
|
body: JSON.stringify({ email })
|
|
})
|
|
|
|
const data = await response.json()
|
|
|
|
if (!response.ok) {
|
|
throw new Error(data.error || 'Anfrage fehlgeschlagen')
|
|
}
|
|
|
|
return data
|
|
} catch (error) {
|
|
console.error('Passwort-Reset-Anfrage-Fehler:', error)
|
|
throw error
|
|
} finally {
|
|
isLoading.value = false
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Passwort zurücksetzen
|
|
*/
|
|
const resetPassword = async (resetToken, password) => {
|
|
try {
|
|
isLoading.value = true
|
|
|
|
const response = await fetch(`${API_URL}/auth/reset-password`, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json'
|
|
},
|
|
body: JSON.stringify({
|
|
token: resetToken,
|
|
password
|
|
})
|
|
})
|
|
|
|
const data = await response.json()
|
|
|
|
if (!response.ok) {
|
|
throw new Error(data.error || 'Passwort-Reset fehlgeschlagen')
|
|
}
|
|
|
|
return data
|
|
} catch (error) {
|
|
console.error('Passwort-Reset-Fehler:', error)
|
|
throw error
|
|
} finally {
|
|
isLoading.value = false
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Passwort ändern (eingeloggter Benutzer)
|
|
*/
|
|
const changePassword = async (oldPassword, newPassword) => {
|
|
try {
|
|
isLoading.value = true
|
|
|
|
const response = await fetch(`${API_URL}/auth/change-password`, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'Authorization': `Bearer ${token.value}`
|
|
},
|
|
body: JSON.stringify({
|
|
oldPassword,
|
|
newPassword
|
|
})
|
|
})
|
|
|
|
const data = await response.json()
|
|
|
|
if (!response.ok) {
|
|
throw new Error(data.error || 'Passwort-Änderung fehlgeschlagen')
|
|
}
|
|
|
|
return data
|
|
} catch (error) {
|
|
console.error('Passwort-Änderungs-Fehler:', error)
|
|
throw error
|
|
} finally {
|
|
isLoading.value = false
|
|
}
|
|
}
|
|
|
|
/**
|
|
* HTTP-Header mit Authorization zurückgeben
|
|
*/
|
|
const getAuthHeaders = () => {
|
|
const savedToken = token.value || loadToken()
|
|
|
|
if (savedToken) {
|
|
return {
|
|
'Authorization': `Bearer ${savedToken}`,
|
|
'Content-Type': 'application/json'
|
|
}
|
|
}
|
|
|
|
return {
|
|
'Content-Type': 'application/json'
|
|
}
|
|
}
|
|
|
|
return {
|
|
// State
|
|
user,
|
|
token,
|
|
isAuthenticated,
|
|
isLoading,
|
|
|
|
// Actions
|
|
register,
|
|
login,
|
|
logout,
|
|
fetchCurrentUser,
|
|
validateToken,
|
|
requestPasswordReset,
|
|
resetPassword,
|
|
changePassword,
|
|
getAuthHeaders,
|
|
loadToken,
|
|
saveToken,
|
|
clearAuth
|
|
}
|
|
})
|
|
|