fix(auth): isolate client cache by session
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { afterEach, expect, test, vi } from 'vitest';
|
||||
import { api } from './client';
|
||||
import { PLATFORM_UNAUTHORIZED_EVENT } from '../v2/auth/session';
|
||||
|
||||
afterEach(() => {
|
||||
vi.restoreAllMocks();
|
||||
@@ -15,6 +16,23 @@ test('authenticated requests use the session-only bearer token', async () => {
|
||||
expect(window.localStorage.getItem('vehicle-platform.access-token')).toBeNull();
|
||||
});
|
||||
|
||||
test('a protected 401 terminates the client session but login validation errors stay local', async () => {
|
||||
window.sessionStorage.setItem('vehicle-platform.access-token', 'expired-token');
|
||||
const unauthorized = vi.fn();
|
||||
window.addEventListener(PLATFORM_UNAUTHORIZED_EVENT, unauthorized);
|
||||
vi.spyOn(globalThis, 'fetch').mockResolvedValue({
|
||||
ok: false,
|
||||
status: 401,
|
||||
json: async () => ({ error: { message: '访问令牌无效' } })
|
||||
} as Response);
|
||||
|
||||
await expect(api.monitorSummary()).rejects.toThrow('访问令牌无效');
|
||||
expect(unauthorized).toHaveBeenCalledTimes(1);
|
||||
await expect(api.session()).rejects.toThrow('访问令牌无效');
|
||||
expect(unauthorized).toHaveBeenCalledTimes(1);
|
||||
window.removeEventListener(PLATFORM_UNAUTHORIZED_EVENT, unauthorized);
|
||||
});
|
||||
|
||||
test('durable alert APIs keep versioned actions, rules and notification reads explicit', async () => {
|
||||
const fetchMock = vi.spyOn(globalThis, 'fetch').mockResolvedValue({ ok: true, json: async () => ({ data: {}, traceId: 'trace-alert', timestamp: 1 }) } as Response);
|
||||
await api.alertEventsV2({ status: 'unprocessed', limit: 20, offset: 0 });
|
||||
|
||||
@@ -55,7 +55,7 @@ import type {
|
||||
VehicleServiceSummary,
|
||||
VehicleRow
|
||||
} from './types';
|
||||
import { getAccessToken } from '../v2/auth/session';
|
||||
import { getAccessToken, notifyUnauthorizedSession } from '../v2/auth/session';
|
||||
|
||||
export type RawFrameQuery = {
|
||||
keyword?: string;
|
||||
@@ -90,6 +90,7 @@ async function request<T>(path: string, init?: RequestInit): Promise<T> {
|
||||
const requestInit = token ? { ...init, headers: withAuthorization(init?.headers, token) } : init;
|
||||
const response = await fetch(path, requestInit);
|
||||
if (!response.ok) {
|
||||
if (response.status === 401 && token && path !== '/api/v2/session') notifyUnauthorizedSession();
|
||||
throw new Error(await responseErrorMessage(response));
|
||||
}
|
||||
const envelope = (await response.json()) as ApiEnvelope<T>;
|
||||
|
||||
Reference in New Issue
Block a user