fix: Fix multiple bugs with new authentication flow
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import '@angular/compiler';
|
||||
import { Injector, runInInjectionContext } from '@angular/core';
|
||||
import {
|
||||
beforeEach,
|
||||
@@ -13,6 +14,21 @@ import { CapacitorDatabaseService } from './capacitor-database.service';
|
||||
import { DatabaseService } from './database.service';
|
||||
import { ElectronDatabaseService } from './electron-database.service';
|
||||
|
||||
function installLocalStorageMock(): void {
|
||||
const store = new Map<string, string>();
|
||||
|
||||
vi.stubGlobal('localStorage', {
|
||||
getItem: (key: string) => store.get(key) ?? null,
|
||||
setItem: (key: string, value: string) => store.set(key, String(value)),
|
||||
removeItem: (key: string) => store.delete(key),
|
||||
clear: () => store.clear(),
|
||||
key: (index: number) => Array.from(store.keys())[index] ?? null,
|
||||
get length() {
|
||||
return store.size;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
describe('DatabaseService', () => {
|
||||
let browserDatabase: {
|
||||
getBansForRoom: ReturnType<typeof vi.fn>;
|
||||
@@ -28,6 +44,9 @@ describe('DatabaseService', () => {
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
installLocalStorageMock();
|
||||
localStorage.clear();
|
||||
|
||||
browserDatabase = {
|
||||
getBansForRoom: vi.fn(() => Promise.resolve([])),
|
||||
initialize: vi.fn(() => Promise.resolve())
|
||||
@@ -69,6 +88,56 @@ describe('DatabaseService', () => {
|
||||
expect(service.isReady()).toBe(true);
|
||||
});
|
||||
|
||||
it('rechecks backend initialization when the user scope changes during an in-flight initialize call', async () => {
|
||||
let finishInitialInitialize!: () => void;
|
||||
|
||||
browserDatabase.initialize = vi.fn()
|
||||
.mockImplementationOnce(() => new Promise<void>((resolve) => {
|
||||
finishInitialInitialize = resolve;
|
||||
}))
|
||||
.mockResolvedValue(undefined);
|
||||
|
||||
localStorage.setItem('metoyou_currentUserId', 'user-a');
|
||||
|
||||
const service = createService({ isBrowser: true, isElectron: false, isCapacitor: false });
|
||||
const initialInitialize = service.initialize();
|
||||
|
||||
localStorage.setItem('metoyou_currentUserId', 'user-b');
|
||||
const initializeAfterScopeChange = service.initialize();
|
||||
|
||||
expect(browserDatabase.initialize).toHaveBeenCalledTimes(1);
|
||||
|
||||
finishInitialInitialize();
|
||||
await Promise.all([initialInitialize, initializeAfterScopeChange]);
|
||||
|
||||
expect(browserDatabase.initialize).toHaveBeenCalledTimes(2);
|
||||
expect(service.isReady()).toBe(true);
|
||||
});
|
||||
|
||||
it('does not reinitialize the browser backend for repeated reads in the same user scope', async () => {
|
||||
const service = createService({ isBrowser: true, isElectron: false, isCapacitor: false });
|
||||
|
||||
await service.getBansForRoom('room-1');
|
||||
await service.getBansForRoom('room-2');
|
||||
|
||||
expect(browserDatabase.initialize).toHaveBeenCalledTimes(1);
|
||||
expect(browserDatabase.getBansForRoom).toHaveBeenCalledWith('room-1');
|
||||
expect(browserDatabase.getBansForRoom).toHaveBeenCalledWith('room-2');
|
||||
});
|
||||
|
||||
it('reinitializes the browser backend when the stored user scope changes', async () => {
|
||||
localStorage.setItem('metoyou_currentUserId', 'user-a');
|
||||
|
||||
const service = createService({ isBrowser: true, isElectron: false, isCapacitor: false });
|
||||
|
||||
await service.getBansForRoom('room-1');
|
||||
localStorage.setItem('metoyou_currentUserId', 'user-b');
|
||||
await service.getBansForRoom('room-2');
|
||||
|
||||
expect(browserDatabase.initialize).toHaveBeenCalledTimes(2);
|
||||
expect(browserDatabase.getBansForRoom).toHaveBeenCalledWith('room-2');
|
||||
});
|
||||
|
||||
it('routes Capacitor shells to native SQLite instead of IndexedDB', async () => {
|
||||
const service = createService({ isBrowser: false, isElectron: false, isCapacitor: true });
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ import {
|
||||
} from '../../shared-kernel';
|
||||
import type { ChatAttachmentMeta, CustomEmoji } from '../../shared-kernel';
|
||||
import { PlatformService } from '../../core/platform';
|
||||
import { getStoredCurrentUserId } from '../../core/storage/current-user-storage';
|
||||
import { BrowserDatabaseService } from './browser-database.service';
|
||||
import { CapacitorDatabaseService } from './capacitor-database.service';
|
||||
import { resolveDatabaseBackend } from './database-backend.rules';
|
||||
@@ -42,6 +43,7 @@ export class DatabaseService {
|
||||
private readonly capacitorDb = inject(CapacitorDatabaseService);
|
||||
private readonly electronDb = inject(ElectronDatabaseService);
|
||||
private initializationPromise: Promise<void> | null = null;
|
||||
private validatedUserScope: string | null | undefined;
|
||||
|
||||
/** Reactive flag: `true` once {@link initialize} has completed. */
|
||||
isReady = signal(false);
|
||||
@@ -66,8 +68,15 @@ export class DatabaseService {
|
||||
|
||||
/** Initialise the platform-specific database. */
|
||||
async initialize(): Promise<void> {
|
||||
const userScope = getStoredCurrentUserId();
|
||||
|
||||
if (this.initializationPromise) {
|
||||
await this.initializationPromise;
|
||||
|
||||
if (this.isReady() && this.validatedUserScope === userScope) {
|
||||
return;
|
||||
}
|
||||
} else if (this.isReady() && this.validatedUserScope === userScope) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -75,6 +84,7 @@ export class DatabaseService {
|
||||
|
||||
this.initializationPromise = backend.initialize()
|
||||
.then(() => {
|
||||
this.validatedUserScope = userScope;
|
||||
this.isReady.set(true);
|
||||
})
|
||||
.finally(() => {
|
||||
@@ -85,8 +95,11 @@ export class DatabaseService {
|
||||
}
|
||||
|
||||
private async ensureReady(): Promise<void> {
|
||||
if (this.isReady())
|
||||
const userScope = getStoredCurrentUserId();
|
||||
|
||||
if (this.isReady() && this.validatedUserScope === userScope) {
|
||||
return;
|
||||
}
|
||||
|
||||
await this.initialize();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user