fix(web): stop doubling basePath in auth refresh redirects (#39273)

Co-authored-by: yyh <yuanyouhuilyz@gmail.com>
This commit is contained in:
Checo 2026-07-20 20:22:40 +08:00 committed by GitHub
parent 0862641533
commit 3afb9b3230
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 19 additions and 8 deletions

View File

@ -15,6 +15,7 @@ const mocks = vi.hoisted(() => ({
}),
headers: vi.fn(),
resolveServerConsoleApiUrl: vi.fn(),
basePath: '',
}))
vi.mock('@/context/query-client-server', () => ({
@ -29,6 +30,12 @@ vi.mock('@/next/navigation', () => ({
redirect: (url: string) => mocks.redirect(url),
}))
vi.mock('@/utils/var', () => ({
get basePath() {
return mocks.basePath
},
}))
vi.mock('@/features/account-profile/server', () => ({
serverUserProfileQueryOptions: () => ({
queryKey: ['common', 'user-profile'],
@ -62,6 +69,7 @@ vi.mock('@/features/system-features/server', () => ({
describe('CommonLayoutHydrationBoundary', () => {
beforeEach(() => {
vi.clearAllMocks()
mocks.basePath = ''
mocks.queryClient = new QueryClient({ defaultOptions: { queries: { retry: false } } })
mocks.headers.mockResolvedValue(
new Headers({
@ -126,6 +134,7 @@ describe('CommonLayoutHydrationBoundary', () => {
})
it('should redirect unauthorized users to the refresh route with the current path', async () => {
mocks.basePath = '/workflow'
mocks.profileQueryFn.mockRejectedValue(
new Response(JSON.stringify({ code: 'unauthorized' }), { status: 401 }),
)
@ -150,15 +159,17 @@ describe('CommonLayoutHydrationBoundary', () => {
expect(mocks.redirect).toHaveBeenCalledWith('/auth/refresh?redirect_url=%2F')
})
it('should redirect setup errors to install', async () => {
mocks.profileQueryFn.mockRejectedValue(
new Response(JSON.stringify({ code: 'not_setup' }), { status: 401 }),
)
it.each([
['not_setup', '/install'],
['not_init_validated', '/init'],
])('should use a basePath-relative destination for %s errors', async (code, destination) => {
mocks.basePath = '/workflow'
mocks.profileQueryFn.mockRejectedValue(new Response(JSON.stringify({ code }), { status: 401 }))
const { CommonLayoutHydrationBoundary } = await import('../hydration-boundary')
await expect(CommonLayoutHydrationBoundary({ children: null })).rejects.toThrow('NEXT_REDIRECT')
expect(mocks.redirect).toHaveBeenCalledWith('/install')
expect(mocks.redirect).toHaveBeenCalledWith(destination)
})
it('should render children without server prefetch when the server API URL is not resolvable', async () => {

View File

@ -42,15 +42,15 @@ const getCurrentPath = async () => {
const redirectToAuthRefresh = async () => {
const currentPath = await getCurrentPath()
redirect(`${basePath}${AUTH_REFRESH_PATH}?redirect_url=${encodeURIComponent(currentPath)}`)
redirect(`${AUTH_REFRESH_PATH}?redirect_url=${encodeURIComponent(currentPath)}`)
}
const handleProfileError = async (error: unknown) => {
if (!(error instanceof Response)) throw error
const errorData = await parseConsoleErrorPayload(error)
if (errorData?.code === 'not_setup') redirect(`${basePath}/install`)
if (errorData?.code === 'not_init_validated') redirect(`${basePath}/init`)
if (errorData?.code === 'not_setup') redirect('/install')
if (errorData?.code === 'not_init_validated') redirect('/init')
if (error.status === 401) await redirectToAuthRefresh()
throw error