Skip to content

Commit

Permalink
Fix super long unauthed contexts (#19637)
Browse files Browse the repository at this point in the history
  • Loading branch information
filiptronicek authored Apr 26, 2024
1 parent d8b8243 commit f48dc13
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 1 deletion.
46 changes: 45 additions & 1 deletion components/dashboard/src/components/QuickStart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { useHistory, useLocation } from "react-router";
import { AppLoading } from "../app/AppLoading";
import { Link } from "react-router-dom";
import { authProviderClient, userClient } from "../service/public-api";
import { storageAvailable } from "../utils";

const parseErrorFromSearch = (search: string): string => {
const searchParams = new URLSearchParams(search);
Expand All @@ -22,6 +23,14 @@ const parseErrorFromSearch = (search: string): string => {
return "";
};

const generateLocalStorageItemName = async (hash: string) => {
const id = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(hash));
return `quickstart-${Array.from(new Uint8Array(id))
.map((b) => b.toString(16).padStart(2, "0"))
.join("")
.slice(0, 10)}` as const;
};

const QuickStart: FC = () => {
const [error, setError] = useState(parseErrorFromSearch(window.location.search));
const history = useHistory();
Expand All @@ -40,10 +49,33 @@ const QuickStart: FC = () => {
.then((r) => r?.descriptions);

const hashValue = hash.slice(1);

// The browser will reject cookies larger than 4096 bytes, so we store the hash in local storage if it's too long and restore it later.
if (hashValue.length > 2048) {
const isLocalStorageAvailable = storageAvailable("localStorage");
if (isLocalStorageAvailable) {
const localStorageItemName = await generateLocalStorageItemName(hashValue);

console.log(`Hash value too long, storing in local storage as ${localStorageItemName}`);
localStorage.setItem(localStorageItemName, hashValue);
window.location.hash = `#${localStorageItemName}`;
return;
}

setError("Context URL value is too long.");
return;
}

let contextUrl: URL;
try {
const value = hashValue.startsWith("quickstart-") ? localStorage.getItem(hashValue) : hashValue;
if (!value) {
setError("Invalid hash value");
return;
}

// We have to account for the case where environment variables are provided through the hash, so we search it for the URL.
const toParse = hashValue.match(/^https?:/) ? hashValue : hashValue.slice(hashValue.indexOf("/") + 1);
const toParse = value.match(/^https?:/) ? value : value.slice(value.indexOf("/") + 1);
contextUrl = new URL(toParse);
} catch {
setError("Invalid context URL");
Expand Down Expand Up @@ -87,6 +119,18 @@ const QuickStart: FC = () => {
const searchParams = new URLSearchParams(window.location.search);
searchParams.delete("message");

if (hashValue.startsWith("quickstart-")) {
const storedHash = localStorage.getItem(hashValue);
if (!storedHash) {
setError("Invalid hash value");
return;
}

localStorage.removeItem(hashValue);
history.push(`/new/?${searchParams}#${storedHash}`);
return;
}

history.push(`/new/?${searchParams}${window.location.hash}`);

return;
Expand Down
32 changes: 32 additions & 0 deletions components/dashboard/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,3 +117,35 @@ export function isWebsiteSlug(pathName: string) {
];
return slugs.some((slug) => pathName.startsWith("/" + slug + "/") || pathName === "/" + slug);
}

// https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API#testing_for_availability
export function storageAvailable(type: "localStorage" | "sessionStorage"): boolean {
let storage;
try {
storage = window[type];
const x = "__storage_test__";
storage.setItem(x, x);
storage.removeItem(x);
return true;
} catch (e) {
if (!storage) {
return false;
}

return (
e instanceof DOMException &&
// everything except Firefox
(e.code === 22 ||
// Firefox
e.code === 1014 ||
// test name field too, because code might not be present
// everything except Firefox
e.name === "QuotaExceededError" ||
// Firefox
e.name === "NS_ERROR_DOM_QUOTA_REACHED") &&
// acknowledge QuotaExceededError only if there's something already stored
storage &&
storage.length !== 0
);
}
}

0 comments on commit f48dc13

Please sign in to comment.