From 2ac021ff94124560ce43701e43a3febc130904d9 Mon Sep 17 00:00:00 2001 From: Netanel Gilad Date: Tue, 5 Aug 2025 09:58:39 +0300 Subject: [PATCH 1/7] reload page after logout if no redirect --- src/modules/auth.ts | 14 ++++++++------ tests/unit/auth.test.js | 30 ++++++++++++++++++++++++++++-- 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/src/modules/auth.ts b/src/modules/auth.ts index 081bf77..8537bad 100644 --- a/src/modules/auth.ts +++ b/src/modules/auth.ts @@ -57,8 +57,8 @@ export function createAuthModule( /** * Logout the current user - * Removes the token from localStorage and optionally redirects to a URL - * @param redirectUrl - Optional URL to redirect to after logout + * Removes the token from localStorage and optionally redirects to a URL or reloads the page + * @param redirectUrl - Optional URL to redirect to after logout. Reloads the page if not provided * @returns {Promise} */ async logout(redirectUrl?: string) { @@ -75,11 +75,13 @@ export function createAuthModule( } // Redirect if a URL is provided - if (redirectUrl && typeof window !== "undefined") { - window.location.href = redirectUrl; + if (typeof window !== "undefined") { + if (redirectUrl) { + window.location.href = redirectUrl; + } else { + window.location.reload(); + } } - - return Promise.resolve(); }, /** diff --git a/tests/unit/auth.test.js b/tests/unit/auth.test.js index 98016ae..b0fa1ec 100644 --- a/tests/unit/auth.test.js +++ b/tests/unit/auth.test.js @@ -214,7 +214,10 @@ describe('Auth Module', () => { }; const originalWindow = global.window; global.window = { - localStorage: mockLocalStorage + localStorage: mockLocalStorage, + location: { + reload: vi.fn() + } }; // Set a token to localStorage first @@ -241,7 +244,10 @@ describe('Auth Module', () => { const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {}); const originalWindow = global.window; global.window = { - localStorage: mockLocalStorage + localStorage: mockLocalStorage, + location: { + reload: vi.fn() + } }; // Call logout - should not throw @@ -272,6 +278,26 @@ describe('Auth Module', () => { // Restore window global.window = originalWindow; }); + + test('should reload page when no redirect URL is provided', async () => { + // Mock window object with reload function + const mockReload = vi.fn(); + const originalWindow = global.window; + global.window = { + location: { + reload: mockReload + } + }; + + // Call logout without redirect URL + await base44.auth.logout(); + + // Verify page reload was called + expect(mockReload).toHaveBeenCalledTimes(1); + + // Restore window + global.window = originalWindow; + }); }); describe('setToken()', () => { From 7b2382b991f2183f30a91df514a00146b4c14703 Mon Sep 17 00:00:00 2001 From: Netanel Gilad Date: Tue, 5 Aug 2025 10:19:27 +0300 Subject: [PATCH 2/7] handle server url already ending with /api --- src/client.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/client.ts b/src/client.ts index 32272ce..25e1939 100644 --- a/src/client.ts +++ b/src/client.ts @@ -32,7 +32,7 @@ export function createClient(config: { // Create the base axios client const axiosClient = createAxiosClient({ - baseURL: `${serverUrl}/api`, + baseURL: `${serverUrl.endsWith("/api") ? serverUrl : `${serverUrl}/api`}`, headers: { "X-App-Id": String(appId), "X-Environment": env, @@ -44,7 +44,7 @@ export function createClient(config: { }); const functionsAxiosClient = createAxiosClient({ - baseURL: `${serverUrl}/api`, + baseURL: `${serverUrl.endsWith("/api") ? serverUrl : `${serverUrl}/api`}`, headers: { "X-App-Id": String(appId), "X-Environment": env, From 0a400bd25f335ca50e858bcb76752e0885ac45f4 Mon Sep 17 00:00:00 2001 From: Netanel Gilad Date: Tue, 5 Aug 2025 10:23:42 +0300 Subject: [PATCH 3/7] back --- src/client.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/client.ts b/src/client.ts index 25e1939..32272ce 100644 --- a/src/client.ts +++ b/src/client.ts @@ -32,7 +32,7 @@ export function createClient(config: { // Create the base axios client const axiosClient = createAxiosClient({ - baseURL: `${serverUrl.endsWith("/api") ? serverUrl : `${serverUrl}/api`}`, + baseURL: `${serverUrl}/api`, headers: { "X-App-Id": String(appId), "X-Environment": env, @@ -44,7 +44,7 @@ export function createClient(config: { }); const functionsAxiosClient = createAxiosClient({ - baseURL: `${serverUrl.endsWith("/api") ? serverUrl : `${serverUrl}/api`}`, + baseURL: `${serverUrl}/api`, headers: { "X-App-Id": String(appId), "X-Environment": env, From 29b4ee7bbbb763a2414a950fea439f9e473b8890 Mon Sep 17 00:00:00 2001 From: Netanel Gilad Date: Tue, 5 Aug 2025 13:46:05 +0300 Subject: [PATCH 4/7] don't use server url for login, use relative --- src/modules/auth.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/modules/auth.ts b/src/modules/auth.ts index 8537bad..60fc66d 100644 --- a/src/modules/auth.ts +++ b/src/modules/auth.ts @@ -31,7 +31,7 @@ export function createAuthModule( }, /** - * Redirects the user to the Base44 login page + * Redirects the user to the app's login page * @param {string} nextUrl - URL to redirect to after successful login * @throws {Error} When not in a browser environment */ @@ -47,9 +47,7 @@ export function createAuthModule( const redirectUrl = nextUrl || window.location.href; // Build the login URL - const loginUrl = `${serverUrl}/login?from_url=${encodeURIComponent( - redirectUrl - )}&app_id=${appId}`; + const loginUrl = `/login?from_url=${encodeURIComponent(redirectUrl)}`; // Redirect to the login page window.location.href = loginUrl; From ca6e5b535c6390cd0d38a6e03cf5ce134c7d4bb3 Mon Sep 17 00:00:00 2001 From: Netanel Gilad Date: Tue, 5 Aug 2025 13:51:15 +0300 Subject: [PATCH 5/7] fix --- tests/unit/auth.test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/unit/auth.test.js b/tests/unit/auth.test.js index b0fa1ec..2097479 100644 --- a/tests/unit/auth.test.js +++ b/tests/unit/auth.test.js @@ -149,7 +149,7 @@ describe('Auth Module', () => { // Verify the redirect URL was set correctly expect(mockLocation.href).toBe( - `${serverUrl}/login?from_url=${encodeURIComponent(nextUrl)}&app_id=${appId}` + `/login?from_url=${encodeURIComponent(nextUrl)}` ); // Restore window @@ -169,7 +169,7 @@ describe('Auth Module', () => { // Verify the redirect URL uses current URL expect(mockLocation.href).toBe( - `${serverUrl}/login?from_url=${encodeURIComponent(currentUrl)}&app_id=${appId}` + `/login?from_url=${encodeURIComponent(currentUrl)}` ); // Restore window From 9e79cdbcd34f40f1127e4d7ecdf47b1d7b3f5523 Mon Sep 17 00:00:00 2001 From: Netanel Gilad Date: Tue, 5 Aug 2025 14:00:09 +0300 Subject: [PATCH 6/7] it's not async --- src/modules/auth.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/auth.ts b/src/modules/auth.ts index 60fc66d..2d734ac 100644 --- a/src/modules/auth.ts +++ b/src/modules/auth.ts @@ -59,7 +59,7 @@ export function createAuthModule( * @param redirectUrl - Optional URL to redirect to after logout. Reloads the page if not provided * @returns {Promise} */ - async logout(redirectUrl?: string) { + logout(redirectUrl?: string) { // Remove token from axios headers delete axios.defaults.headers.common["Authorization"]; From 28e87268f7b7184b94759c2f02d01dc18d655549 Mon Sep 17 00:00:00 2001 From: Netanel Gilad Date: Tue, 5 Aug 2025 14:04:25 +0300 Subject: [PATCH 7/7] and tests --- tests/unit/auth.test.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/unit/auth.test.js b/tests/unit/auth.test.js index 2097479..603c064 100644 --- a/tests/unit/auth.test.js +++ b/tests/unit/auth.test.js @@ -192,7 +192,7 @@ describe('Auth Module', () => { expect(scope.isDone()).toBe(true); // Call logout - await base44.auth.logout(); + base44.auth.logout(); // Mock another me() call to verify no Authorization header is sent scope.get(`/api/apps/${appId}/entities/User/me`) @@ -225,7 +225,7 @@ describe('Auth Module', () => { expect(mockLocalStorage.setItem).toHaveBeenCalledWith('base44_access_token', 'test-token'); // Call logout - await base44.auth.logout(); + base44.auth.logout(); // Verify token was removed from localStorage expect(mockLocalStorage.removeItem).toHaveBeenCalledWith('base44_access_token'); @@ -251,7 +251,7 @@ describe('Auth Module', () => { }; // Call logout - should not throw - await expect(base44.auth.logout()).resolves.toBeUndefined(); + base44.auth.logout(); // Verify error was logged expect(consoleSpy).toHaveBeenCalledWith('Failed to remove token from localStorage:', expect.any(Error)); @@ -270,7 +270,7 @@ describe('Auth Module', () => { }; const redirectUrl = 'https://example.com/logout-success'; - await base44.auth.logout(redirectUrl); + base44.auth.logout(redirectUrl); // Verify redirect expect(mockLocation.href).toBe(redirectUrl); @@ -290,7 +290,7 @@ describe('Auth Module', () => { }; // Call logout without redirect URL - await base44.auth.logout(); + base44.auth.logout(); // Verify page reload was called expect(mockReload).toHaveBeenCalledTimes(1);