Hotfix: Embed - Fix issue in accessing sessionStorage in certain scenarios (#3851)

* Fixes issue when sessionStorage is not accessible in privacy focussed modes in various browsers

* Fix eslint errors

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
This commit is contained in:
Hariom Balhara 2022-08-16 09:48:13 +05:30 committed by GitHub
parent 732acb5b25
commit bc6c9e1b0a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 72 additions and 3 deletions

View File

@ -3,12 +3,26 @@ import Document, { DocumentContext, Head, Html, Main, NextScript, DocumentProps
type Props = Record<string, unknown> & DocumentProps;
function toRunBeforeReactOnClient() {
window.sessionStorage.setItem("calEmbedMode", String(location.search.includes("embed=")));
const calEmbedMode = location.search.includes("embed=");
try {
// eslint-disable-next-line @calcom/eslint/avoid-web-storage
window.sessionStorage.setItem("calEmbedMode", String(calEmbedMode));
} catch (e) {}
window.isEmbed = () => {
return window.sessionStorage.getItem("calEmbedMode") === "true";
try {
// eslint-disable-next-line @calcom/eslint/avoid-web-storage
return window.sessionStorage.getItem("calEmbedMode") === "true";
} catch (e) {}
// If we can't use sessionStorage to retrieve embed mode, just use the variable. It would fail to detect embed if page in iframe reloads without embed query param in it.
return calEmbedMode;
};
window.resetEmbedStatus = () => {
window.sessionStorage.removeItem("calEmbedMode");
try {
// eslint-disable-next-line @calcom/eslint/avoid-web-storage
window.sessionStorage.removeItem("calEmbedMode");
} catch (e) {}
};
window.getEmbedTheme = () => {

View File

@ -40,6 +40,9 @@ import { UsernameAvailability } from "@components/ui/UsernameAvailability";
import { TRPCClientErrorLike } from "@trpc/client";
// Embed isn't applicable to onboarding, so ignore the rule
/* eslint-disable @calcom/eslint/avoid-web-storage */
type ScheduleFormValues = {
schedule: ScheduleType;
};

View File

@ -179,6 +179,8 @@ function SettingsView(props: ComponentProps<typeof Settings> & { localeProp: str
const enteredTimeFormat = selectedTimeFormat.value;
// Write time format to localStorage if available
// Embed isn't applicable to profile pages. So ignore the rule
// eslint-disable-next-line @calcom/eslint/avoid-web-storage
window.localStorage.setItem("timeOption.is24hClock", selectedTimeFormat.value === 12 ? "false" : "true");
// TODO: Add validation

View File

@ -36,6 +36,7 @@ test.describe("Onboarding", () => {
*/
test.fixme();
await page.addInitScript(() => {
// eslint-disable-next-line @calcom/eslint/avoid-web-storage
window.localStorage.setItem("username", "alwaysavailable");
}, {});
// Try to go getting started with a available username

View File

@ -3,6 +3,7 @@ const recommended = {
parserOptions: { sourceType: "module" },
rules: {
"@calcom/eslint/deprecated-imports": "error",
"@calcom/eslint/avoid-web-storage": "error",
},
};

View File

@ -0,0 +1,45 @@
import { ESLintUtils } from "@typescript-eslint/utils";
const createRule = ESLintUtils.RuleCreator((name) => `https://developer.cal.com/eslint/rule/${name}`);
const rule = createRule({
create(context) {
return {
CallExpression(node) {
const webStorages = ["localStorage", "sessionStorage"];
const callee = node.callee;
if (
// Can't figure out how to fix this TS issue
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
callee.object?.object?.name === "window" &&
// Can't figure out how to fix this TS issue
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
webStorages.includes(node?.callee?.object?.property?.name)
) {
return context.report({
node: node,
loc: node.loc,
messageId: "possible-issue-with-embed",
});
}
},
};
},
name: "avoid-web-storage",
meta: {
fixable: "code",
docs: {
description: "Avoid deprecated imports",
recommended: "warn",
},
messages: {
"possible-issue-with-embed": `Be aware that accessing localStorage/sessionStorage throws error in Chrome Incognito mode when embed is in cross domain context. If you know what you are doing, \`import {localStorage, sessionStorage} from "@calcom/lib/webstorage"\` for safe usage. See https://github.com/calcom/cal.com/issues/2618`,
},
type: "suggestion",
schema: [],
},
defaultOptions: [],
});
export default rule;

View File

@ -4,4 +4,5 @@ import type { ESLint } from "eslint";
export default {
"my-first-rule": require("./my-first-rule").default,
"deprecated-imports": require("./deprecated-imports").default,
"avoid-web-storage": require("./avoid-web-storage").default,
} as ESLint.Plugin["rules"];

View File

@ -2,6 +2,7 @@
export const localStorage = {
getItem(key: string) {
try {
// eslint-disable-next-line @calcom/eslint/avoid-web-storage
return window.localStorage.getItem(key);
} catch (e) {
// In case storage is restricted. Possible reasons
@ -11,6 +12,7 @@ export const localStorage = {
},
setItem(key: string, value: string) {
try {
// eslint-disable-next-line @calcom/eslint/avoid-web-storage
window.localStorage.setItem(key, value);
} catch (e) {
// In case storage is restricted. Possible reasons