Merge pull request #2568 from wucm667/fix/setup-page-guard-after-init
fix(setup): 初始化完成后阻止访问 setup 页面
This commit is contained in:
commit
4fa4e372ca
@ -1,5 +1,6 @@
|
||||
import { describe, it, expect, vi, beforeEach } from 'vitest'
|
||||
import { setActivePinia, createPinia } from 'pinia'
|
||||
import { resolveCompletedSetupRedirectPath } from '@/router/setupRedirect'
|
||||
|
||||
// Mock 导航加载状态
|
||||
vi.mock('@/composables/useNavigationLoading', () => {
|
||||
@ -53,6 +54,7 @@ interface MockAuthState {
|
||||
isSimpleMode: boolean
|
||||
backendModeEnabled: boolean
|
||||
hasPendingAuthSession: boolean
|
||||
setupNeedsSetup?: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
@ -66,6 +68,10 @@ function simulateGuard(
|
||||
const requiresAuth = toMeta.requiresAuth !== false
|
||||
const requiresAdmin = toMeta.requiresAdmin === true
|
||||
|
||||
if (toPath === '/setup' && authState.setupNeedsSetup === false) {
|
||||
return resolveCompletedSetupRedirectPath(authState.isAuthenticated, authState.isAdmin)
|
||||
}
|
||||
|
||||
// 不需要认证的路由
|
||||
if (!requiresAuth) {
|
||||
if (
|
||||
@ -378,6 +384,32 @@ describe('路由守卫逻辑', () => {
|
||||
expect(redirect).toBeNull()
|
||||
})
|
||||
|
||||
it('unauthenticated: initialized /setup redirects to /login', () => {
|
||||
const authState: MockAuthState = {
|
||||
isAuthenticated: false,
|
||||
isAdmin: false,
|
||||
isSimpleMode: false,
|
||||
backendModeEnabled: true,
|
||||
hasPendingAuthSession: false,
|
||||
setupNeedsSetup: false,
|
||||
}
|
||||
const redirect = simulateGuard('/setup', { requiresAuth: false }, authState)
|
||||
expect(redirect).toBe('/login')
|
||||
})
|
||||
|
||||
it('admin: initialized /setup redirects to /admin/dashboard', () => {
|
||||
const authState: MockAuthState = {
|
||||
isAuthenticated: true,
|
||||
isAdmin: true,
|
||||
isSimpleMode: false,
|
||||
backendModeEnabled: true,
|
||||
hasPendingAuthSession: false,
|
||||
setupNeedsSetup: false,
|
||||
}
|
||||
const redirect = simulateGuard('/setup', { requiresAuth: false }, authState)
|
||||
expect(redirect).toBe('/admin/dashboard')
|
||||
})
|
||||
|
||||
it('admin: /admin/dashboard is allowed', () => {
|
||||
const authState: MockAuthState = {
|
||||
isAuthenticated: true,
|
||||
|
||||
@ -9,6 +9,8 @@ import { useAppStore } from '@/stores/app'
|
||||
import { useAdminSettingsStore } from '@/stores/adminSettings'
|
||||
import { useNavigationLoadingState } from '@/composables/useNavigationLoading'
|
||||
import { useRoutePrefetch } from '@/composables/useRoutePrefetch'
|
||||
import { getSetupStatus } from '@/api/setup'
|
||||
import { resolveCompletedSetupRedirectPath } from './setupRedirect'
|
||||
import { resolveDocumentTitle } from './title'
|
||||
|
||||
/**
|
||||
@ -715,7 +717,7 @@ function isBackendModePublicRouteAllowed(path: string, hasPendingAuthSession: bo
|
||||
return false
|
||||
}
|
||||
|
||||
router.beforeEach((to, _from, next) => {
|
||||
router.beforeEach(async (to, _from, next) => {
|
||||
// 开始导航加载状态
|
||||
navigationLoading.startNavigation()
|
||||
|
||||
@ -750,6 +752,18 @@ router.beforeEach((to, _from, next) => {
|
||||
const requiresAuth = to.meta.requiresAuth !== false // Default to true
|
||||
const requiresAdmin = to.meta.requiresAdmin === true
|
||||
|
||||
if (to.path === '/setup') {
|
||||
try {
|
||||
const status = await getSetupStatus()
|
||||
if (!status.needs_setup) {
|
||||
next(resolveCompletedSetupRedirectPath(authStore.isAuthenticated, authStore.isAdmin))
|
||||
return
|
||||
}
|
||||
} catch {
|
||||
// If setup status cannot be determined, keep the setup page reachable.
|
||||
}
|
||||
}
|
||||
|
||||
// If route doesn't require auth, allow access
|
||||
if (!requiresAuth) {
|
||||
// If already authenticated and trying to access login/register, redirect to appropriate dashboard
|
||||
|
||||
7
frontend/src/router/setupRedirect.ts
Normal file
7
frontend/src/router/setupRedirect.ts
Normal file
@ -0,0 +1,7 @@
|
||||
export function resolveCompletedSetupRedirectPath(isAuthenticated: boolean, isAdmin: boolean): string {
|
||||
if (!isAuthenticated) {
|
||||
return '/login'
|
||||
}
|
||||
|
||||
return isAdmin ? '/admin/dashboard' : '/dashboard'
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user