From 325213ae66adb3fc575fb7c82e4d0ac09732cecd Mon Sep 17 00:00:00 2001 From: Wesley Liddick Date: Tue, 15 Sep 2026 08:59:52 +0800 Subject: [PATCH] Revert "fix(batch-image): scope access cache to the current user" --- .../__tests__/useBatchImageAccess.spec.ts | 97 ------------------- .../src/composables/useBatchImageAccess.ts | 27 +----- 2 files changed, 4 insertions(+), 120 deletions(-) delete mode 100644 frontend/src/composables/__tests__/useBatchImageAccess.spec.ts diff --git a/frontend/src/composables/__tests__/useBatchImageAccess.spec.ts b/frontend/src/composables/__tests__/useBatchImageAccess.spec.ts deleted file mode 100644 index 3840c888db..0000000000 --- a/frontend/src/composables/__tests__/useBatchImageAccess.spec.ts +++ /dev/null @@ -1,97 +0,0 @@ -import { beforeEach, describe, expect, it, vi } from 'vitest' -import { reactive } from 'vue' - -const { list } = vi.hoisted(() => ({ list: vi.fn() })) -const auth = reactive({ user: { id: 1 } as { id: number } | null, isAuthenticated: true }) -vi.mock('@/api/keys', () => ({ keysAPI: { list } })) -vi.mock('@/stores/auth', () => ({ useAuthStore: () => auth })) - -const allowed = { items: [{ status: 'active', group: { platform: 'gemini', allow_batch_image_generation: true } }], pages: 1 } -const denied = { items: [], pages: 1 } -function deferred() { - let resolve!: (value: typeof denied | typeof allowed) => void - let reject!: (error: Error) => void - const promise = new Promise((res, rej) => { resolve = res; reject = rej }) - return { promise, resolve, reject } -} -beforeEach(() => { vi.resetModules(); list.mockReset(); auth.user = { id: 1 }; auth.isAuthenticated = true }) - -describe('batch image access session cache', () => { - it.each([true, false])('reloads access after switching users (previous access: %s)', async (previous) => { - list.mockResolvedValueOnce(previous ? allowed : denied).mockResolvedValueOnce(previous ? denied : allowed) - const { useBatchImageAccess } = await import('../useBatchImageAccess') - const state = useBatchImageAccess() - expect(await state.refreshBatchImageAccess()).toBe(previous) - auth.user = { id: 2 } - expect(state.canUseBatchImage.value).toBe(false) - expect(await state.refreshBatchImageAccess()).toBe(!previous) - expect(list).toHaveBeenCalledTimes(2) - expect(state.canUseBatchImage.value).toBe(!previous) - }) - - it('does not reuse an unauthenticated result after login', async () => { - auth.user = null; auth.isAuthenticated = false - const { useBatchImageAccess } = await import('../useBatchImageAccess') - const state = useBatchImageAccess() - expect(await state.refreshBatchImageAccess()).toBe(false) - auth.user = { id: 1 }; auth.isAuthenticated = true - list.mockResolvedValue(allowed) - expect(await state.refreshBatchImageAccess()).toBe(true) - }) - - it.each(['resolve', 'reject'] as const)('ignores an old user request that later %ss', async (settle) => { - const old = deferred() - list.mockReturnValueOnce(old.promise).mockResolvedValueOnce(allowed) - const { useBatchImageAccess } = await import('../useBatchImageAccess') - const state = useBatchImageAccess() - const oldLoad = state.refreshBatchImageAccess() - auth.user = { id: 2 } - expect(await state.refreshBatchImageAccess()).toBe(true) - if (settle === 'resolve') old.resolve(denied) - else old.reject(new Error('old request failed')) - await oldLoad - expect(state.canUseBatchImage.value).toBe(true) - expect(await state.refreshBatchImageAccess()).toBe(true) - expect(list).toHaveBeenCalledTimes(2) - }) - - it('keeps the new user request pending when an older request finishes', async () => { - const old = deferred(); const current = deferred() - list.mockReturnValueOnce(old.promise).mockReturnValueOnce(current.promise) - const { useBatchImageAccess } = await import('../useBatchImageAccess') - const state = useBatchImageAccess() - const oldLoad = state.refreshBatchImageAccess() - auth.user = { id: 2 } - const newLoad = state.refreshBatchImageAccess() - expect(list).toHaveBeenCalledTimes(2) - old.resolve(denied); await oldLoad - expect(state.batchImageAccessLoading.value).toBe(true) - const sharedLoad = state.refreshBatchImageAccess() - expect(list).toHaveBeenCalledTimes(2) - current.resolve(allowed) - expect(await newLoad).toBe(true); expect(await sharedLoad).toBe(true) - expect(state.batchImageAccessLoading.value).toBe(false) - }) - - it('hides cached access immediately on logout', async () => { - list.mockResolvedValue(allowed) - const { useBatchImageAccess } = await import('../useBatchImageAccess') - const state = useBatchImageAccess() - await state.refreshBatchImageAccess() - expect(state.canUseBatchImage.value).toBe(true) - auth.user = null; auth.isAuthenticated = false - expect(state.canUseBatchImage.value).toBe(false) - }) - - it('still shares in-flight and completed results between consumers for the same user', async () => { - const response = deferred(); list.mockReturnValue(response.promise) - const { useBatchImageAccess } = await import('../useBatchImageAccess') - const first = useBatchImageAccess(); const second = useBatchImageAccess() - const one = first.refreshBatchImageAccess(); const two = second.refreshBatchImageAccess() - expect(list).toHaveBeenCalledTimes(1) - response.resolve(allowed) - expect(await one).toBe(true); expect(await two).toBe(true) - expect(await second.refreshBatchImageAccess()).toBe(true) - expect(list).toHaveBeenCalledTimes(1) - }) -}) diff --git a/frontend/src/composables/useBatchImageAccess.ts b/frontend/src/composables/useBatchImageAccess.ts index 42cf3988f5..caf1e8c0f9 100644 --- a/frontend/src/composables/useBatchImageAccess.ts +++ b/frontend/src/composables/useBatchImageAccess.ts @@ -6,8 +6,6 @@ import type { ApiKey } from '@/types' const loaded = ref(false) const loading = ref(false) const hasAllowedBatchImageKey = ref(false) -const cacheUserId = ref(null) -let requestId = 0 let pendingLoad: Promise | null = null const pageSize = 100 @@ -21,16 +19,7 @@ function keyAllowsBatchImage(key: ApiKey): boolean { async function loadBatchImageAccess(force = false): Promise { const authStore = useAuthStore() - const userId = authStore.isAuthenticated ? authStore.user?.id ?? null : null - if (cacheUserId.value !== userId) { - cacheUserId.value = userId - loaded.value = false - loading.value = false - hasAllowedBatchImageKey.value = false - pendingLoad = null - requestId += 1 - } - if (userId === null) { + if (!authStore.isAuthenticated) { loaded.value = true hasAllowedBatchImageKey.value = false return false @@ -44,8 +33,6 @@ async function loadBatchImageAccess(force = false): Promise { return pendingLoad } - const loadId = ++requestId - const isCurrentLoad = () => loadId === requestId && authStore.isAuthenticated && authStore.user?.id === userId loading.value = true pendingLoad = (async () => { let page = 1 @@ -56,8 +43,6 @@ async function loadBatchImageAccess(force = false): Promise { sort_order: 'desc' }) - if (!isCurrentLoad()) return false - if ((response.items || []).some(keyAllowsBatchImage)) { hasAllowedBatchImageKey.value = true loaded.value = true @@ -74,13 +59,11 @@ async function loadBatchImageAccess(force = false): Promise { } })() .catch(() => { - if (!isCurrentLoad()) return false hasAllowedBatchImageKey.value = false loaded.value = true return false }) .finally(() => { - if (loadId !== requestId) return loading.value = false pendingLoad = null }) @@ -89,14 +72,12 @@ async function loadBatchImageAccess(force = false): Promise { } export function useBatchImageAccess() { - const authStore = useAuthStore() - const isCurrentUser = computed(() => (authStore.isAuthenticated ? authStore.user?.id ?? null : null) === cacheUserId.value) - const canUseBatchImage = computed(() => authStore.isAuthenticated && isCurrentUser.value && hasAllowedBatchImageKey.value) + const canUseBatchImage = computed(() => hasAllowedBatchImageKey.value) return { canUseBatchImage, - batchImageAccessLoaded: computed(() => isCurrentUser.value && loaded.value), - batchImageAccessLoading: computed(() => isCurrentUser.value && loading.value), + batchImageAccessLoaded: computed(() => loaded.value), + batchImageAccessLoading: computed(() => loading.value), refreshBatchImageAccess: loadBatchImageAccess, } }