Use globalThis instead of window (S7764)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -90,7 +90,7 @@ apiClient.interceptors.response.use(
|
|||||||
deleteCookie("luciaToken");
|
deleteCookie("luciaToken");
|
||||||
deleteCookie("luciaRefreshToken");
|
deleteCookie("luciaRefreshToken");
|
||||||
deleteCookie("isLuciaLoggedIn");
|
deleteCookie("isLuciaLoggedIn");
|
||||||
window.location.href = "/login";
|
globalThis.location.href = "/login";
|
||||||
return Promise.reject(refreshError);
|
return Promise.reject(refreshError);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -34,6 +34,6 @@ export const printObject = (obj, indent = 0) => {
|
|||||||
*/
|
*/
|
||||||
export const getRandomInt = (max) => {
|
export const getRandomInt = (max) => {
|
||||||
const array = new Uint32Array(1);
|
const array = new Uint32Array(1);
|
||||||
window.crypto.getRandomValues(array);
|
globalThis.crypto.getRandomValues(array);
|
||||||
return Math.floor((array[0] / (0xffffffff + 1)) * (max + 1));
|
return Math.floor((array[0] / (0xffffffff + 1)) * (max + 1));
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -409,7 +409,7 @@ function handleClick(tagId) {
|
|||||||
isActive.value = tagId;
|
isActive.value = tagId;
|
||||||
|
|
||||||
if (isSafeTagId(tagId)) {
|
if (isSafeTagId(tagId)) {
|
||||||
window.location.href = tagId;
|
globalThis.location.href = tagId;
|
||||||
} else {
|
} else {
|
||||||
console.warn("Unsafe tagId: ", tagId);
|
console.warn("Unsafe tagId: ", tagId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -392,7 +392,7 @@ function handleClick(tagId) {
|
|||||||
isActive.value = tagId;
|
isActive.value = tagId;
|
||||||
|
|
||||||
if (isSafeTagId(tagId)) {
|
if (isSafeTagId(tagId)) {
|
||||||
window.location.href = tagId;
|
globalThis.location.href = tagId;
|
||||||
} else {
|
} else {
|
||||||
console.warn("Unsafe tagId: ", tagId);
|
console.warn("Unsafe tagId: ", tagId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -928,7 +928,7 @@ const handleWindowClick = (e) => {
|
|||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
isLoading.value = true;
|
isLoading.value = true;
|
||||||
await store.fetchAllFiles();
|
await store.fetchAllFiles();
|
||||||
window.addEventListener("click", handleWindowClick);
|
globalThis.addEventListener("click", handleWindowClick);
|
||||||
// Add the .scrollbar class to the DataTable tbody
|
// Add the .scrollbar class to the DataTable tbody
|
||||||
const tbodyElement = document.querySelector(".p-datatable-tbody");
|
const tbodyElement = document.querySelector(".p-datatable-tbody");
|
||||||
tbodyElement?.classList.add("scrollbar");
|
tbodyElement?.classList.add("scrollbar");
|
||||||
@@ -936,7 +936,7 @@ onMounted(async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
onBeforeUnmount(() => {
|
||||||
window.removeEventListener("click", handleWindowClick);
|
globalThis.removeEventListener("click", handleWindowClick);
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|||||||
@@ -329,7 +329,7 @@ function getTextWidth(text, e) {
|
|||||||
const hiddenSpan = document.createElement("span");
|
const hiddenSpan = document.createElement("span");
|
||||||
|
|
||||||
hiddenSpan.textContent = processedText;
|
hiddenSpan.textContent = processedText;
|
||||||
hiddenSpan.style.font = window.getComputedStyle(e).font;
|
hiddenSpan.style.font = globalThis.getComputedStyle(e).font;
|
||||||
hiddenSpan.style.visibility = "hidden";
|
hiddenSpan.style.visibility = "hidden";
|
||||||
document.body.appendChild(hiddenSpan);
|
document.body.appendChild(hiddenSpan);
|
||||||
const width = hiddenSpan.getBoundingClientRect().width;
|
const width = hiddenSpan.getBoundingClientRect().width;
|
||||||
|
|||||||
@@ -235,13 +235,13 @@ describe("filesStore", () => {
|
|||||||
it("downloads CSV for a log", async () => {
|
it("downloads CSV for a log", async () => {
|
||||||
mockGet.mockResolvedValue({ data: "col1,col2\na,b" });
|
mockGet.mockResolvedValue({ data: "col1,col2\na,b" });
|
||||||
|
|
||||||
window.URL.createObjectURL = vi.fn().mockReturnValue("blob:test");
|
globalThis.URL.createObjectURL = vi.fn().mockReturnValue("blob:test");
|
||||||
window.URL.revokeObjectURL = vi.fn();
|
globalThis.URL.revokeObjectURL = vi.fn();
|
||||||
|
|
||||||
await store.downloadFileCSV("log", 3, "my-file");
|
await store.downloadFileCSV("log", 3, "my-file");
|
||||||
|
|
||||||
expect(mockGet).toHaveBeenCalledWith("/api/logs/3/csv");
|
expect(mockGet).toHaveBeenCalledWith("/api/logs/3/csv");
|
||||||
expect(window.URL.revokeObjectURL).toHaveBeenCalledWith("blob:test");
|
expect(globalThis.URL.revokeObjectURL).toHaveBeenCalledWith("blob:test");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("returns early for unsupported type", async () => {
|
it("returns early for unsupported type", async () => {
|
||||||
|
|||||||
@@ -96,15 +96,15 @@ describe("loginStore", () => {
|
|||||||
// btoa('/dashboard') = 'L2Rhc2hib2FyZA=='
|
// btoa('/dashboard') = 'L2Rhc2hib2FyZA=='
|
||||||
store.rememberedReturnToUrl = btoa("/dashboard");
|
store.rememberedReturnToUrl = btoa("/dashboard");
|
||||||
|
|
||||||
// Mock window.location.href setter
|
// Mock globalThis.location.href setter
|
||||||
const originalLocation = window.location;
|
const originalLocation = globalThis.location;
|
||||||
delete window.location;
|
delete globalThis.location;
|
||||||
window.location = { href: "" };
|
globalThis.location = { href: "" };
|
||||||
|
|
||||||
await store.signIn();
|
await store.signIn();
|
||||||
|
|
||||||
expect(window.location.href).toBe("/dashboard");
|
expect(globalThis.location.href).toBe("/dashboard");
|
||||||
window.location = originalLocation;
|
globalThis.location = originalLocation;
|
||||||
});
|
});
|
||||||
|
|
||||||
it("does not redirect to external URL (open redirect prevention)", async () => {
|
it("does not redirect to external URL (open redirect prevention)", async () => {
|
||||||
@@ -117,17 +117,17 @@ describe("loginStore", () => {
|
|||||||
// Attacker crafts a return-to URL pointing to an external site
|
// Attacker crafts a return-to URL pointing to an external site
|
||||||
store.rememberedReturnToUrl = btoa("https://evil.example.com/steal");
|
store.rememberedReturnToUrl = btoa("https://evil.example.com/steal");
|
||||||
|
|
||||||
const originalLocation = window.location;
|
const originalLocation = globalThis.location;
|
||||||
delete window.location;
|
delete globalThis.location;
|
||||||
window.location = { href: "" };
|
globalThis.location = { href: "" };
|
||||||
|
|
||||||
await store.signIn();
|
await store.signIn();
|
||||||
|
|
||||||
// Should NOT redirect to the external URL
|
// Should NOT redirect to the external URL
|
||||||
expect(window.location.href).not.toBe("https://evil.example.com/steal");
|
expect(globalThis.location.href).not.toBe("https://evil.example.com/steal");
|
||||||
// Should fall back to /files
|
// Should fall back to /files
|
||||||
expect(store.$router.push).toHaveBeenCalledWith("/files");
|
expect(store.$router.push).toHaveBeenCalledWith("/files");
|
||||||
window.location = originalLocation;
|
globalThis.location = originalLocation;
|
||||||
});
|
});
|
||||||
|
|
||||||
it("falls back to /files when return-to is not valid base64", async () => {
|
it("falls back to /files when return-to is not valid base64", async () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user