Compare commits

...

1 Commits

Author SHA1 Message Date
Amin Ghadersohi
67d861ae7b fix(logout): purge the namespaced Cache API store on logout
GET responses with an ETag were persisted into the @SUPERSET-UI/CONNECTION
Cache API namespace and retained across sessions, with no purge on logout. The
logout handler already cleared the persisted redux localStorage and session
storage; extend it to also delete the namespaced Cache API store so cached
responses are not retained on the device after the session ends.

Best-effort (the promise is not awaited since logout navigates away). Extends
the existing RightMenu logout test to assert the cache namespace is purged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-22 17:47:12 -07:00
2 changed files with 17 additions and 0 deletions

View File

@@ -401,6 +401,10 @@ test('Logs out and clears local storage item redux', async () => {
expect(localStorage.getItem('redux')).not.toBeNull();
expect(sessionStorage.getItem('login_attempted')).not.toBeNull();
// Mock the Cache API so we can assert the namespaced store is purged.
const deleteMock = jest.fn().mockResolvedValue(true);
(global as any).caches = { delete: deleteMock };
await userEvent.hover(await screen.findByText(/Settings/i));
// Simulate user clicking the logout button
@@ -412,6 +416,10 @@ test('Logs out and clears local storage item redux', async () => {
expect(localStorage.getItem('redux')).toBeNull();
expect(sessionStorage.getItem('login_attempted')).toBeNull();
});
// The namespaced Cache API store is purged on logout.
expect(deleteMock).toHaveBeenCalledWith('@SUPERSET-UI/CONNECTION');
delete (global as any).caches;
});
test('shows logout button when not embedded', async () => {

View File

@@ -28,6 +28,7 @@ import {
getExtensionsRegistry,
isFeatureEnabled,
FeatureFlag,
CACHE_KEY,
} from '@superset-ui/core';
import {
styled,
@@ -353,6 +354,14 @@ const RightMenu = ({
try {
window.localStorage.removeItem('redux');
window.sessionStorage.removeItem('login_attempted');
// Purge the namespaced Cache API store so cached GET responses are not
// retained on the device after the session ends. Best-effort: the
// returned promise is not awaited since logout navigates away.
if (typeof caches !== 'undefined') {
caches.delete(CACHE_KEY).catch(() => {
/* best-effort: ignore cache deletion failures */
});
}
} catch (error) {
console.warn('Failed to clear storage on logout:', error);
}