Add change-password API and dynamic 404 redirect
Introduce ChangePasswordRequest DTO and a new ChangePassword endpoint in AuthController that validates input, changes the user's password via UserManager, updates the security stamp, signs out the user to invalidate sessions, and returns localized messages. Add a simple authorized AppUserController stub (GET /auth/user). Update the 404 view to resolve auth status via fetchCurrentUser, show a dynamic CTA/icon (Dashboard vs Home), auto-redirect after a short delay with proper timer cleanup, and adjust navigation behavior. Update codexInfo.md to document the 404 behavior change.
This commit is contained in:
@@ -1,18 +1,74 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, onBeforeUnmount, onMounted, ref } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
|
||||
import notFoundImage from '@/assets/images/404NotFound.png'
|
||||
import { fetchCurrentUser } from '@/services/authSession'
|
||||
|
||||
const router = useRouter()
|
||||
const isAuthenticated = ref(false)
|
||||
let autoRedirectTimer: ReturnType<typeof setTimeout> | null = null
|
||||
|
||||
const redirectRouteName = computed(() => (isAuthenticated.value ? 'Dashboard' : 'Home'))
|
||||
const redirectButtonLabel = computed(() =>
|
||||
isAuthenticated.value ? 'Zum Dashboard' : 'Zur Startseite',
|
||||
)
|
||||
const redirectButtonIcon = computed(() =>
|
||||
isAuthenticated.value ? 'mdi-view-dashboard-outline' : 'mdi-home-outline',
|
||||
)
|
||||
const autoRedirectTargetLabel = computed(() => (isAuthenticated.value ? 'Dashboard' : 'Startseite'))
|
||||
|
||||
function clearAutoRedirectTimer() {
|
||||
if (autoRedirectTimer === null) {
|
||||
return
|
||||
}
|
||||
|
||||
clearTimeout(autoRedirectTimer)
|
||||
autoRedirectTimer = null
|
||||
}
|
||||
|
||||
function scheduleAutoRedirect() {
|
||||
clearAutoRedirectTimer()
|
||||
|
||||
autoRedirectTimer = setTimeout(() => {
|
||||
void router.replace({ name: redirectRouteName.value })
|
||||
}, 2000)
|
||||
}
|
||||
|
||||
async function resolveRedirectTarget() {
|
||||
try {
|
||||
const currentUser = await fetchCurrentUser()
|
||||
isAuthenticated.value = currentUser !== null
|
||||
} catch {
|
||||
isAuthenticated.value = false
|
||||
}
|
||||
|
||||
scheduleAutoRedirect()
|
||||
}
|
||||
|
||||
function navigateToPrimaryTarget() {
|
||||
clearAutoRedirectTimer()
|
||||
void router.replace({ name: redirectRouteName.value })
|
||||
}
|
||||
|
||||
function navigateBack() {
|
||||
clearAutoRedirectTimer()
|
||||
|
||||
if (window.history.length > 1) {
|
||||
router.back()
|
||||
return
|
||||
}
|
||||
|
||||
router.push({ name: 'Dashboard' })
|
||||
void router.push({ name: redirectRouteName.value })
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
void resolveRedirectTarget()
|
||||
})
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
clearAutoRedirectTimer()
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -29,12 +85,17 @@ function navigateBack() {
|
||||
<h1>Seite nicht gefunden</h1>
|
||||
<p class="not-found-text">
|
||||
Der Link ist ungültig oder die Seite wurde verschoben. Du kannst direkt zur
|
||||
Dashboard-Seite zurück oder die vorherige Ansicht öffnen.
|
||||
{{ autoRedirectTargetLabel }} weitergehen oder die vorherige Ansicht öffnen.
|
||||
Du wirst automatisch dorthin weitergeleitet.
|
||||
</p>
|
||||
|
||||
<div class="not-found-actions hoard-action-row">
|
||||
<v-btn color="primary" prepend-icon="mdi-view-dashboard-outline" :to="{ name: 'Dashboard' }">
|
||||
Zum Dashboard
|
||||
<v-btn
|
||||
color="primary"
|
||||
:prepend-icon="redirectButtonIcon"
|
||||
@click="navigateToPrimaryTarget"
|
||||
>
|
||||
{{ redirectButtonLabel }}
|
||||
</v-btn>
|
||||
<v-btn variant="outlined" prepend-icon="mdi-arrow-left" @click="navigateBack">Zurück</v-btn>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user