From cc2c10745b4c2673d963ead44e9f9e8fc679ee32 Mon Sep 17 00:00:00 2001 From: Christian Byrne Date: Wed, 18 Feb 2026 20:47:12 -0800 Subject: [PATCH] fix: use getAuthHeader in createCustomer for API key auth support (#8983) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary Re-apply the fix from PR #8408 that was accidentally reverted by PR #8508 — `createCustomer` must use `getAuthHeader()` (not `getFirebaseAuthHeader()`) so API key authentication works. ## Changes - **What**: Changed `createCustomer` in `firebaseAuthStore.ts` to use `getAuthHeader()` which falls back through workspace token → Firebase token → API key. Added regression tests covering API key auth, Firebase auth, and no-auth paths. ## Review Focus This is the same one-line fix from #8408. PR #8508 ("Feat/workspaces 6 billing") overwrote it during merge because it was branched before #8408 landed. The regression test should prevent this from happening again. Fixes COM-15060 ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-8983-fix-use-getAuthHeader-in-createCustomer-for-API-key-auth-support-30c6d73d365081c2aab6d5defa5298d6) by [Unito](https://www.unito.io) --- src/stores/firebaseAuthStore.test.ts | 58 ++++++++++++++++++++++++++++ src/stores/firebaseAuthStore.ts | 2 +- 2 files changed, 59 insertions(+), 1 deletion(-) diff --git a/src/stores/firebaseAuthStore.test.ts b/src/stores/firebaseAuthStore.test.ts index 8dd0ec7735..9196f71c95 100644 --- a/src/stores/firebaseAuthStore.test.ts +++ b/src/stores/firebaseAuthStore.test.ts @@ -99,6 +99,19 @@ vi.mock('@/stores/toastStore', () => ({ // Mock useDialogService vi.mock('@/services/dialogService') +// Mock apiKeyAuthStore +const mockApiKeyGetAuthHeader = vi.fn().mockReturnValue(null) +vi.mock('@/stores/apiKeyAuthStore', () => ({ + useApiKeyAuthStore: () => ({ + getAuthHeader: mockApiKeyGetAuthHeader, + getApiKey: vi.fn(), + currentUser: null, + isAuthenticated: false, + storeApiKey: vi.fn(), + clearStoredApiKey: vi.fn() + }) +})) + describe('useFirebaseAuthStore', () => { let store: ReturnType let authStateCallback: (user: User | null) => void @@ -164,6 +177,9 @@ describe('useFirebaseAuthStore', () => { // Reset and set up getIdToken mock mockUser.getIdToken.mockReset() mockUser.getIdToken.mockResolvedValue('mock-id-token') + + // Default: no API key auth + mockApiKeyGetAuthHeader.mockReturnValue(null) }) describe('token refresh events', () => { @@ -628,4 +644,46 @@ describe('useFirebaseAuthStore', () => { await expect(store.accessBillingPortal()).rejects.toThrow() }) }) + + describe('createCustomer', () => { + it('should succeed with API key auth when no Firebase user is present', async () => { + authStateCallback(null) + mockApiKeyGetAuthHeader.mockReturnValue({ 'X-API-KEY': 'test-api-key' }) + + const result = await store.createCustomer() + + expect(mockFetch).toHaveBeenCalledWith( + expect.stringContaining('/customers'), + expect.objectContaining({ + method: 'POST', + headers: expect.objectContaining({ + 'X-API-KEY': 'test-api-key' + }) + }) + ) + expect(result).toEqual({ id: 'test-customer-id' }) + }) + + it('should use Firebase token when Firebase user is present', async () => { + const result = await store.createCustomer() + + expect(mockFetch).toHaveBeenCalledWith( + expect.stringContaining('/customers'), + expect.objectContaining({ + method: 'POST', + headers: expect.objectContaining({ + Authorization: 'Bearer mock-id-token' + }) + }) + ) + expect(result).toEqual({ id: 'test-customer-id' }) + }) + + it('should throw when no auth method is available', async () => { + authStateCallback(null) + mockApiKeyGetAuthHeader.mockReturnValue(null) + + await expect(store.createCustomer()).rejects.toThrow() + }) + }) }) diff --git a/src/stores/firebaseAuthStore.ts b/src/stores/firebaseAuthStore.ts index 76caf20582..c09380c237 100644 --- a/src/stores/firebaseAuthStore.ts +++ b/src/stores/firebaseAuthStore.ts @@ -277,7 +277,7 @@ export const useFirebaseAuthStore = defineStore('firebaseAuth', () => { } const createCustomer = async (): Promise => { - const authHeader = await getFirebaseAuthHeader() + const authHeader = await getAuthHeader() if (!authHeader) { throw new FirebaseAuthStoreError(t('toastMessages.userNotAuthenticated')) }