fix(auth): secure sessions and app routing
Validate sessions against the API, honor configurable base paths, and route unknown pages to 404. Keep development ports stable so user and admin apps cannot be confused. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
+10
-5
@@ -1,5 +1,6 @@
|
||||
import { createRouter, createWebHistory } from 'vue-router'
|
||||
import { getCachedUser, isAuthenticated } from '@/services/authService'
|
||||
import { useAuthStore } from '@/stores/auth'
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHistory(import.meta.env.BASE_URL),
|
||||
@@ -250,20 +251,24 @@ const router = createRouter({
|
||||
component: () => import('@/views/profile/ProfileChecksView.vue'),
|
||||
meta: { requiresAuth: true },
|
||||
},
|
||||
{
|
||||
path: '/:pathMatch(.*)*',
|
||||
name: 'not-found',
|
||||
component: () => import('@/views/NotFoundView.vue'),
|
||||
},
|
||||
],
|
||||
scrollBehavior() {
|
||||
return { top: 0 }
|
||||
},
|
||||
})
|
||||
|
||||
router.beforeEach((to) => {
|
||||
router.beforeEach(async (to) => {
|
||||
const auth = useAuthStore()
|
||||
await auth.hydrate()
|
||||
const authed = isAuthenticated()
|
||||
|
||||
if (to.meta.requiresAuth && !authed) {
|
||||
if (to.name === 'home' || to.path === '/') {
|
||||
return { name: 'welcome' }
|
||||
}
|
||||
return { name: 'welcome', query: { redirect: to.fullPath } }
|
||||
return { name: 'login', query: { redirect: to.fullPath } }
|
||||
}
|
||||
|
||||
if (to.meta.guest && authed) {
|
||||
|
||||
@@ -131,7 +131,8 @@ export async function fetchMe(): Promise<User | null> {
|
||||
cacheUser(me)
|
||||
return me
|
||||
} catch {
|
||||
return getCachedUser()
|
||||
cacheUser(null)
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -123,11 +123,12 @@ export async function apiRequest<T>(path: string, options: RequestOptions = {}):
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
if (typeof window !== 'undefined' && !window.location.pathname.startsWith('/login')) {
|
||||
const loginPath = `${import.meta.env.BASE_URL}login`
|
||||
if (typeof window !== 'undefined' && !window.location.pathname.startsWith(loginPath)) {
|
||||
const redirect = encodeURIComponent(
|
||||
`${window.location.pathname}${window.location.search}`,
|
||||
)
|
||||
window.location.assign(`/login?redirect=${redirect}`)
|
||||
window.location.assign(`${loginPath}?redirect=${redirect}`)
|
||||
}
|
||||
}
|
||||
throw new ApiError(res.status, errorMessageFromBody(data, res.status))
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
<template>
|
||||
<main class="not-found">
|
||||
<p class="not-found__code">404</p>
|
||||
<h1>صفحه پیدا نشد</h1>
|
||||
<p>آدرسی که وارد کردهاید وجود ندارد.</p>
|
||||
<RouterLink to="/">بازگشت به صفحه اصلی</RouterLink>
|
||||
</main>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.not-found {
|
||||
display: grid;
|
||||
min-height: 60vh;
|
||||
place-content: center;
|
||||
gap: 12px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.not-found__code {
|
||||
margin: 0;
|
||||
color: var(--color-primary, #c89b3c);
|
||||
font-size: 72px;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
h1,
|
||||
p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--color-primary, #c89b3c);
|
||||
font-weight: 700;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user