fix(sync): skip replica upload when not authenticated (#4327)

Prevents 'Please log in to continue' error when importing fonts or images
locally without logging in. The replica upload is now gated on
getAccessToken() so unauthenticated users are never enqueued.
This commit is contained in:
loveheaven
2026-05-27 23:34:07 +08:00
committed by GitHub
parent d7b633d8f7
commit 64651a65ef
2 changed files with 18 additions and 0 deletions
@@ -7,7 +7,12 @@ vi.mock('@/services/transferManager', () => ({
},
}));
vi.mock('@/utils/access', () => ({
getAccessToken: vi.fn().mockResolvedValue('mock-token'),
}));
import { transferManager } from '@/services/transferManager';
import { getAccessToken } from '@/utils/access';
import { queueDictionaryBinaryUpload } from '@/services/sync/replicaBinaryUpload';
import { clearReplicaAdapters, registerReplicaAdapter } from '@/services/sync/replicaRegistry';
import { dictionaryAdapter } from '@/services/sync/adapters/dictionary';
@@ -16,6 +21,7 @@ import type { AppService } from '@/types/system';
const mockIsReady = transferManager.isReady as ReturnType<typeof vi.fn>;
const mockQueueReplicaUpload = transferManager.queueReplicaUpload as ReturnType<typeof vi.fn>;
const mockGetAccessToken = getAccessToken as ReturnType<typeof vi.fn>;
const makeFakeAppService = (sizes: Record<string, number>) => ({
openFile: vi.fn(async (path: string) => ({
@@ -37,6 +43,7 @@ const baseDict = (overrides: Partial<ImportedDictionary> = {}): ImportedDictiona
beforeEach(() => {
vi.clearAllMocks();
mockGetAccessToken.mockResolvedValue('mock-token');
clearReplicaAdapters();
registerReplicaAdapter(dictionaryAdapter);
});
@@ -66,6 +73,15 @@ describe('queueDictionaryBinaryUpload', () => {
expect(mockQueueReplicaUpload).not.toHaveBeenCalled();
});
test('no-ops when user is not authenticated', async () => {
mockIsReady.mockReturnValue(true);
mockGetAccessToken.mockResolvedValue(null);
const fakeAppService = makeFakeAppService({}) as unknown as AppService;
const result = await queueDictionaryBinaryUpload(baseDict(), fakeAppService);
expect(result).toBe(null);
expect(mockQueueReplicaUpload).not.toHaveBeenCalled();
});
test('queues upload with file sizes resolved via fs', async () => {
mockIsReady.mockReturnValue(true);
mockQueueReplicaUpload.mockReturnValue('transfer-id-1');
@@ -1,5 +1,6 @@
import { transferManager } from '@/services/transferManager';
import { getReplicaAdapter } from './replicaRegistry';
import { getAccessToken } from '@/utils/access';
import type { AppService, BaseDir } from '@/types/system';
import type { ReplicaTransferFile } from '@/store/transferStore';
import type { ClosableFile } from '@/utils/file';
@@ -55,6 +56,7 @@ export const queueReplicaBinaryUpload = async <T extends ReplicaBinaryRecord>(
appService: AppService,
): Promise<string | null> => {
if (!record.contentId) return null;
if (!(await getAccessToken())) return null;
if (!transferManager.isReady()) return null;
const adapter = getReplicaAdapter<T>(kind);