remove dumb auth

This commit is contained in:
2026-03-22 13:16:17 -04:00
parent d38392ac9a
commit 6c2c4f6b8b
8 changed files with 84 additions and 169 deletions

View File

@@ -1,115 +1,11 @@
import { beforeEach, describe, expect, it, vi } from 'vitest';
import { setupAuthInterceptors, TOKEN_KEY } from './authInterceptor';
type RequestConfig = {
headers?: Record<string, string>;
};
type ResponseValue = {
status?: number;
data?: unknown;
};
type ResponseError = {
response?: {
status?: number;
};
};
function createMockAxiosInstance() {
let nextRequestId = 1;
let nextResponseId = 1;
const requestHandlers = new Map<
number,
[(config: RequestConfig) => RequestConfig, (error: unknown) => Promise<never>]
>();
const responseHandlers = new Map<
number,
[(response: ResponseValue) => ResponseValue, (error: ResponseError) => Promise<never>]
>();
return {
interceptors: {
request: {
use: vi.fn((fulfilled, rejected) => {
const id = nextRequestId++;
requestHandlers.set(id, [fulfilled, rejected]);
return id;
}),
eject: vi.fn((id: number) => {
requestHandlers.delete(id);
}),
},
response: {
use: vi.fn((fulfilled, rejected) => {
const id = nextResponseId++;
responseHandlers.set(id, [fulfilled, rejected]);
return id;
}),
eject: vi.fn((id: number) => {
responseHandlers.delete(id);
}),
},
},
getRequestHandler(id = 1) {
return requestHandlers.get(id);
},
getResponseHandler(id = 1) {
return responseHandlers.get(id);
},
};
}
import { describe, expect, it } from 'vitest';
import { setupAuthInterceptors } from './authInterceptor';
describe('setupAuthInterceptors', () => {
beforeEach(() => {
localStorage.clear();
});
it('is a no-op when auth is handled by HttpOnly cookies', () => {
const cleanup = setupAuthInterceptors();
it('registers request and response interceptors and adds the auth header when a token exists', () => {
const axiosInstance = createMockAxiosInstance();
setupAuthInterceptors(axiosInstance as never);
expect(axiosInstance.interceptors.request.use).toHaveBeenCalledTimes(1);
expect(axiosInstance.interceptors.response.use).toHaveBeenCalledTimes(1);
localStorage.setItem(TOKEN_KEY, 'token-123');
const requestHandler = axiosInstance.getRequestHandler()?.[0];
const config: { headers: Record<string, string> } = { headers: {} };
const nextConfig = requestHandler?.(config);
expect(nextConfig).toBe(config);
expect(config.headers.Authorization).toBe('Bearer token-123');
});
it('clears the auth token on 401 responses', async () => {
const axiosInstance = createMockAxiosInstance();
setupAuthInterceptors(axiosInstance as never);
localStorage.setItem(TOKEN_KEY, 'token-123');
const responseErrorHandler = axiosInstance.getResponseHandler()?.[1];
await expect(responseErrorHandler?.({ response: { status: 401 } })).rejects.toEqual({
response: { status: 401 },
});
expect(localStorage.getItem(TOKEN_KEY)).toBeNull();
});
it('ejects previous interceptors before installing a new set', () => {
const firstInstance = createMockAxiosInstance();
const secondInstance = createMockAxiosInstance();
const cleanup = setupAuthInterceptors(firstInstance as never);
setupAuthInterceptors(secondInstance as never);
expect(firstInstance.interceptors.request.eject).toHaveBeenCalledWith(1);
expect(firstInstance.interceptors.response.eject).toHaveBeenCalledWith(1);
cleanup();
expect(firstInstance.interceptors.request.eject).toHaveBeenCalledWith(1);
expect(firstInstance.interceptors.response.eject).toHaveBeenCalledWith(1);
expect(typeof cleanup).toBe('function');
expect(() => cleanup()).not.toThrow();
});
});

View File

@@ -1,46 +1,3 @@
import axios, { type AxiosInstance } from 'axios';
const TOKEN_KEY = 'antholume_token';
let interceptorCleanup: (() => void) | null = null;
export function setupAuthInterceptors(axiosInstance: AxiosInstance = axios) {
if (interceptorCleanup) {
interceptorCleanup();
}
const requestInterceptorId = axiosInstance.interceptors.request.use(
config => {
const token = localStorage.getItem(TOKEN_KEY);
if (token && config.headers) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
},
error => {
return Promise.reject(error);
}
);
const responseInterceptorId = axiosInstance.interceptors.response.use(
response => {
return response;
},
error => {
if (error.response?.status === 401) {
localStorage.removeItem(TOKEN_KEY);
}
return Promise.reject(error);
}
);
interceptorCleanup = () => {
axiosInstance.interceptors.request.eject(requestInterceptorId);
axiosInstance.interceptors.response.eject(responseInterceptorId);
};
return interceptorCleanup;
export function setupAuthInterceptors() {
return () => {};
}
export { TOKEN_KEY };
export default axios;