From 999c65896b92215c5872023c456f33822c06d38d Mon Sep 17 00:00:00 2001 From: Jeremy Clements <79224539+jeclrsg@users.noreply.github.com> Date: Thu, 28 Sep 2023 10:00:15 -0400 Subject: [PATCH] HPCC-30220 ECL Watch fix authentication & ESP session lock issues Signed-off-by: Jeremy Clements <79224539+jeclrsg@users.noreply.github.com> --- esp/src/eclwatch/stub.js | 6 ++--- esp/src/src-react/components/Frame.tsx | 26 ++++++++++++++++++-- esp/src/src-react/components/forms/Login.tsx | 11 +++++++++ esp/src/src-react/index.tsx | 7 ++++-- esp/src/src/ESPUtil.ts | 4 +-- esp/src/src/KeyValStore.ts | 2 +- esp/src/src/Session.ts | 5 ++-- 7 files changed, 49 insertions(+), 12 deletions(-) diff --git a/esp/src/eclwatch/stub.js b/esp/src/eclwatch/stub.js index 9626bcc47b4..6bff90c731e 100644 --- a/esp/src/eclwatch/stub.js +++ b/esp/src/eclwatch/stub.js @@ -35,13 +35,13 @@ define([ if (modernMode === String(true) && hpccWidget !== "IFrameWidget") { switch (hpccWidget) { case "WUDetailsWidget": - window.location.replace(`/esp/files/index.html#/workunits/${params.Wuid}`); + window.location.replace(`/#/workunits/${params.Wuid}`); break; case "GraphsWUWidget": - window.location.replace(`/esp/files/index.html#/workunits/${params.Wuid}/metrics`); + window.location.replace(`/#/workunits/${params.Wuid}/metrics`); break; default: - window.location.replace("/esp/files/index.html"); + window.location.replace("/"); } } else { ready(function () { diff --git a/esp/src/src-react/components/Frame.tsx b/esp/src/src-react/components/Frame.tsx index 73d48d509a5..587e48246d3 100644 --- a/esp/src/src-react/components/Frame.tsx +++ b/esp/src/src-react/components/Frame.tsx @@ -1,17 +1,20 @@ import * as React from "react"; +import * as topic from "dojo/topic"; import { ThemeProvider } from "@fluentui/react"; import { FluentProvider } from "@fluentui/react-components"; import { select as d3Select } from "@hpcc-js/common"; import { scopedLogger } from "@hpcc-js/util"; -import { useUserTheme } from "../hooks/theme"; import { HolyGrail } from "../layouts/HolyGrail"; import { hashHistory } from "../util/history"; import { router } from "../routes"; import { DevTitle } from "./Title"; import { MainNavigation, SubNavigation } from "./Menu"; import { CookieConsent } from "./forms/CookieConsent"; -import { userKeyValStore } from "../../src/KeyValStore"; +import { userKeyValStore } from "src/KeyValStore"; +import { fireIdle, initSession, lock, unlock } from "src/Session"; import { useGlobalStore } from "../hooks/store"; +import { useUserTheme } from "../hooks/theme"; +import { useUserSession } from "../hooks/user"; const logger = scopedLogger("../components/Frame.tsx"); @@ -21,6 +24,7 @@ interface FrameProps { export const Frame: React.FunctionComponent = () => { const [showCookieConsent, setShowCookieConsent] = React.useState(false); + const { userSession, setUserSession } = useUserSession(); const [locationPathname, setLocationPathname] = React.useState(window.location.hash.split("#").join("")); const [body, setBody] = React.useState(

...loading...

); const { theme, themeV9, isDark } = useUserTheme(); @@ -46,6 +50,24 @@ export const Frame: React.FunctionComponent = () => { return () => unlisten(); }, []); + React.useEffect(() => { + initSession(); + + topic.subscribe("hpcc/session_management_status", function (publishedMessage) { + if (publishedMessage.status === "Unlocked") { + unlock(); + } else if (publishedMessage.status === "Locked") { + lock(); + } else if (publishedMessage.status === "DoIdle") { + fireIdle(); + } else if (publishedMessage.status === "Idle") { + window.localStorage.setItem("pageOnLock", window.location.hash.substring(1)); + setUserSession({ ...userSession, Status: "Locked" }); + window.location.reload(); + } + }); + }, [setUserSession, userSession]); + React.useEffect(() => { document.title = `${showEnvironmentTitle && environmentTitle.length ? environmentTitle : "ECL Watch v9"}${locationPathname.split("/").join(" | ")}`; }, [environmentTitle, locationPathname, showEnvironmentTitle]); diff --git a/esp/src/src-react/components/forms/Login.tsx b/esp/src/src-react/components/forms/Login.tsx index a5dc021cb51..a6d7d39c769 100644 --- a/esp/src/src-react/components/forms/Login.tsx +++ b/esp/src/src-react/components/forms/Login.tsx @@ -37,6 +37,15 @@ export const Login: React.FunctionComponent = ({ const [showError, setShowError] = React.useState(false); const [errorMessage, setErrorMessage] = React.useState(""); + React.useEffect(() => { + const cookies = Utility.parseCookies(); + if (cookies["ESPSessionState"] === "true") { + const lastUrl = window.localStorage.getItem("pageOnLock") ?? "/"; + window.localStorage.removeItem("pageOnLock"); + replaceUrl(lastUrl); + } + }, []); + const loginStyles = React.useMemo(() => mergeStyleSets({ root: { height: "100%", @@ -107,6 +116,8 @@ export const Login: React.FunctionComponent = ({ setErrorMessage(cookies.ESPAuthenticationMSG); setShowError(true); } else { + cookies["Status"] = "Unlocked"; + cookies["ESPAuthenticated"] = "true"; createUserSession(cookies).then(() => { setErrorMessage(""); replaceUrl("/", null, true); diff --git a/esp/src/src-react/index.tsx b/esp/src/src-react/index.tsx index d946f22edf6..b3049252cf4 100644 --- a/esp/src/src-react/index.tsx +++ b/esp/src/src-react/index.tsx @@ -5,6 +5,7 @@ import { scopedLogger } from "@hpcc-js/util"; import { cookieKeyValStore, userKeyValStore } from "src/KeyValStore"; import { containerized, ModernMode } from "src/BuildInfo"; import { ECLWatchLogger } from "./hooks/logging"; +import { replaceUrl } from "./util/history"; import "css!dijit-themes/flat/flat.css"; import "css!hpcc/css/ecl.css"; @@ -40,8 +41,10 @@ store.getEx(ModernMode, { defaultValue: String(containerized) }).then(async mode const authType = await authTypeResp?.text() ?? "None"; const userStore = cookieKeyValStore(); const userSession = await userStore.getAll(); - if (authType.indexOf("None") < 0 && (!userSession["ESPAuthenticated"] && (!userSession["ECLWatchUser"] || !userSession["Status"] || userSession["Status"] === "Locked"))) { - window.location.replace("#/login"); + if (authType.indexOf("None") < 0 && (userSession["ESPSessionState"] === "false" || userSession["ECLWatchUser"] === "false" || (!userSession["Status"] || userSession["Status"] === "Locked"))) { + if (window.location.hash.indexOf("login") < 0) { + replaceUrl("/login"); + } import("./components/forms/Login").then(_ => { try { ReactDOM.render( diff --git a/esp/src/src/ESPUtil.ts b/esp/src/src/ESPUtil.ts index 43cf058435d..8c8a94e4abc 100644 --- a/esp/src/src/ESPUtil.ts +++ b/esp/src/src/ESPUtil.ts @@ -314,10 +314,10 @@ export function goToPageUserPreference(gridName, key) { export const MonitorLockClick = dojo.declare([Evented], { unlocked() { - this.emit("unlocked", {}); + this.emit("Unlocked", {}); }, locked() { - this.emit("locked", {}); + this.emit("Locked", {}); } }); diff --git a/esp/src/src/KeyValStore.ts b/esp/src/src/KeyValStore.ts index 3066af2b4cd..8dc900bf2d3 100644 --- a/esp/src/src/KeyValStore.ts +++ b/esp/src/src/KeyValStore.ts @@ -212,7 +212,7 @@ class CookieStorage implements IKeyValStore { set(key: string, value: string, broadcast?: boolean): Promise { const cookies = Utility.parseCookies(); const oldValue = cookies[key]; - document.cookie = `${key}=${value}`; + document.cookie = `${key}=${value};path=/`; return Promise.resolve().then(() => { if (broadcast) { this._dispatch.post(new ValueChangedMessage(key, value, oldValue)); diff --git a/esp/src/src/Session.ts b/esp/src/src/Session.ts index d24351a7771..530fe131694 100644 --- a/esp/src/src/Session.ts +++ b/esp/src/src/Session.ts @@ -14,7 +14,6 @@ const espTimeoutSeconds = cookie("ESPSessionTimeoutSeconds") || 600; // 10 minun const IDLE_TIMEOUT = espTimeoutSeconds * 1000; const SESSION_RESET_FREQ = 30 * 1000; const idleWatcher = new ESPUtil.IdleWatcher(IDLE_TIMEOUT); -const monitorLockClick = new ESPUtil.MonitorLockClick(); const sessionIsActive = espTimeoutSeconds; let _prevReset = Date.now(); @@ -73,7 +72,9 @@ export function initSession() { }); idleWatcher.start(); - monitorLockClick.unlocked(); + if (!cookie("Status")) { + document.cookie = "Status=Unlocked;Path=/"; + } } else if (cookie("ECLWatchUser")) { window.location.replace(dojoConfig.urlInfo.basePath + "/Login.html"); }