Skip to content

Commit 2559cba

Browse files
authored
Clear account idb table on logout (#28996)
* Clear account idb table on logout to remove old deactivated refresh token when logging out Signed-off-by: Michael Telatynski <[email protected]> * Simplify code Signed-off-by: Michael Telatynski <[email protected]> * Fix test Signed-off-by: Michael Telatynski <[email protected]> --------- Signed-off-by: Michael Telatynski <[email protected]>
1 parent 5882b00 commit 2559cba

File tree

3 files changed

+46
-35
lines changed

3 files changed

+46
-35
lines changed

src/Lifecycle.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1049,9 +1049,9 @@ async function clearStorage(opts?: { deleteEverything?: boolean }): Promise<void
10491049
window.localStorage.clear();
10501050

10511051
try {
1052-
await StorageAccess.idbDelete("account", ACCESS_TOKEN_STORAGE_KEY);
1052+
await StorageAccess.idbClear("account");
10531053
} catch (e) {
1054-
logger.error("idbDelete failed for account:mx_access_token", e);
1054+
logger.error("idbClear failed for account", e);
10551055
}
10561056

10571057
// now restore those invites, registration time and previously set device language

src/utils/StorageAccess.ts

Lines changed: 38 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,27 @@ async function idbInit(): Promise<void> {
4444
});
4545
}
4646

47+
async function idbTransaction(
48+
table: string,
49+
mode: IDBTransactionMode,
50+
fn: (objectStore: IDBObjectStore) => IDBRequest<any>,
51+
): Promise<any> {
52+
if (!idb) {
53+
await idbInit();
54+
}
55+
return new Promise((resolve, reject) => {
56+
const txn = idb!.transaction([table], mode);
57+
txn.onerror = reject;
58+
59+
const objectStore = txn.objectStore(table);
60+
const request = fn(objectStore);
61+
request.onerror = reject;
62+
request.onsuccess = (): void => {
63+
resolve(request.result);
64+
};
65+
});
66+
}
67+
4768
/**
4869
* Loads an item from an IndexedDB table within the underlying `matrix-react-sdk` database.
4970
*
@@ -57,17 +78,7 @@ export async function idbLoad(table: string, key: string | string[]): Promise<an
5778
if (!idb) {
5879
await idbInit();
5980
}
60-
return new Promise((resolve, reject) => {
61-
const txn = idb!.transaction([table], "readonly");
62-
txn.onerror = reject;
63-
64-
const objectStore = txn.objectStore(table);
65-
const request = objectStore.get(key);
66-
request.onerror = reject;
67-
request.onsuccess = (event): void => {
68-
resolve(request.result);
69-
};
70-
});
81+
return idbTransaction(table, "readonly", (objectStore) => objectStore.get(key));
7182
}
7283

7384
/**
@@ -84,17 +95,7 @@ export async function idbSave(table: string, key: string | string[], data: any):
8495
if (!idb) {
8596
await idbInit();
8697
}
87-
return new Promise((resolve, reject) => {
88-
const txn = idb!.transaction([table], "readwrite");
89-
txn.onerror = reject;
90-
91-
const objectStore = txn.objectStore(table);
92-
const request = objectStore.put(data, key);
93-
request.onerror = reject;
94-
request.onsuccess = (event): void => {
95-
resolve();
96-
};
97-
});
98+
return idbTransaction(table, "readwrite", (objectStore) => objectStore.put(data, key));
9899
}
99100

100101
/**
@@ -110,15 +111,20 @@ export async function idbDelete(table: string, key: string | string[]): Promise<
110111
if (!idb) {
111112
await idbInit();
112113
}
113-
return new Promise((resolve, reject) => {
114-
const txn = idb!.transaction([table], "readwrite");
115-
txn.onerror = reject;
114+
return idbTransaction(table, "readwrite", (objectStore) => objectStore.delete(key));
115+
}
116116

117-
const objectStore = txn.objectStore(table);
118-
const request = objectStore.delete(key);
119-
request.onerror = reject;
120-
request.onsuccess = (): void => {
121-
resolve();
122-
};
123-
});
117+
/**
118+
* Clears all records from an IndexedDB table within the underlying `matrix-react-sdk` database.
119+
*
120+
* If IndexedDB access is not supported in the environment, an error is thrown.
121+
*
122+
* @param {string} table The name of the object store where the records are stored.
123+
* @returns {Promise<void>} A Promise that resolves when the record(s) have been successfully deleted.
124+
*/
125+
export async function idbClear(table: string): Promise<void> {
126+
if (!idb) {
127+
await idbInit();
128+
}
129+
return idbTransaction(table, "readwrite", (objectStore) => objectStore.clear());
124130
}

test/unit-tests/Lifecycle-test.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,11 @@ describe("Lifecycle", () => {
143143
const table = mockStore[tableKey];
144144
delete table?.[key as string];
145145
});
146+
jest.spyOn(StorageAccess, "idbClear")
147+
.mockClear()
148+
.mockImplementation(async (tableKey: string) => {
149+
mockStore[tableKey] = {};
150+
});
146151
};
147152

148153
const homeserverUrl = "https://server.org";
@@ -613,7 +618,7 @@ describe("Lifecycle", () => {
613618
it("should clear stores", async () => {
614619
await setLoggedIn(credentials);
615620

616-
expect(StorageAccess.idbDelete).toHaveBeenCalledWith("account", "mx_access_token");
621+
expect(StorageAccess.idbClear).toHaveBeenCalledWith("account");
617622
expect(sessionStorage.clear).toHaveBeenCalled();
618623
expect(mockClient.clearStores).toHaveBeenCalled();
619624
});

0 commit comments

Comments
 (0)