WP-01: authentication, user management and application shell
Some checks failed
CI / backend (push) Has been cancelled
CI / frontend (push) Has been cancelled
CI / ui (push) Has been cancelled

Argon2id password hashing, JWT access tokens with rotating HttpOnly refresh
cookies and reuse detection, login rate limiting, auth audit log, bootstrap
admin, admin-only user CRUD and password reset, OpenAPI spec. Vue login page,
auth store with automatic token refresh, route guards, sidebar shell with
toasts and placeholder pages, user management page.

All tests green: 40 backend, 12 Vitest, 4 Playwright.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Dennis Nemec
2026-09-02 21:37:14 +02:00
parent 83aa500f5d
commit f1136fdf3d
32 changed files with 1899 additions and 48 deletions

View File

@ -0,0 +1,43 @@
import { defineStore } from 'pinia'
import { computed, ref } from 'vue'
import { api, ApiError } from '../api/client'
import type { TokenResponse, User } from '../api/types'
export const useAuthStore = defineStore('auth', () => {
const accessToken = ref<string | null>(null)
const user = ref<User | null>(null)
const isAuthenticated = computed(() => user.value !== null)
const isAdmin = computed(() => user.value?.role === 'admin')
function setSession(data: TokenResponse) {
accessToken.value = data.access_token
user.value = data.user
}
function clear() {
accessToken.value = null
user.value = null
}
async function login(email: string, password: string) {
const res = await fetch('/api/auth/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'same-origin',
body: JSON.stringify({ email, password }),
})
const body = await res.json().catch(() => ({}))
if (!res.ok) throw new ApiError(res.status, body.error ?? 'unknown', body.message ?? '')
setSession(body as TokenResponse)
}
async function logout() {
try {
await api.post('/api/auth/logout')
} finally {
clear()
}
}
return { accessToken, user, isAuthenticated, isAdmin, setSession, clear, login, logout }
})