From 3b25b447e0dfeff1ee648a9f6b165f2584f602c7 Mon Sep 17 00:00:00 2001 From: Jeremy Clements <79224539+jeclrsg@users.noreply.github.com> Date: Wed, 3 Apr 2024 16:37:48 -0400 Subject: [PATCH] HPCC-28452 ECL Watch fix "Session is locked" messages Remove any client code that would write a "Status" cookie when either the session timeout monitor fires, or the user manually clicks the "Lock" link. Also, though not strictly related, (1) this PR includes a fix for one of the rewrite rules for the lightweight web server config (used for local dev of ecl watch), and (2) add an additional check to ensure the browser is always redirected to /esp/files/stub.htm when using the v5 UI. Signed-off-by: Jeremy Clements <79224539+jeclrsg@users.noreply.github.com> --- esp/src/Login.html | 2 +- esp/src/eclwatch/HPCCPlatformWidget.js | 2 +- esp/src/eclwatch/LockDialogWidget.js | 10 ++-------- esp/src/index.html | 2 +- esp/src/lws.config.js | 2 +- esp/src/src-react/components/Frame.tsx | 2 +- esp/src/src-react/components/Title.tsx | 6 +++--- esp/src/src-react/components/forms/Login.tsx | 1 - esp/src/src-react/hooks/user.ts | 3 --- esp/src/src-react/index.tsx | 2 +- esp/src/src/ESPRequest.ts | 1 - esp/src/src/Session.ts | 11 +++++------ esp/src/src/Utility.ts | 2 +- 13 files changed, 17 insertions(+), 29 deletions(-) diff --git a/esp/src/Login.html b/esp/src/Login.html index 7ee298a80b5..17435f00ba7 100644 --- a/esp/src/Login.html +++ b/esp/src/Login.html @@ -140,7 +140,7 @@ var d = new Date(); d.setTime(d.getTime() + (exMins * 60 * 1000)); var expires = "expires=" + d.toUTCString(); - document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/"; + document.cookie = cname + "=" + cvalue + ";" + expires + ";"; } if (document.cookie.indexOf("ESPAuthenticationMSG") > -1) { diff --git a/esp/src/eclwatch/HPCCPlatformWidget.js b/esp/src/eclwatch/HPCCPlatformWidget.js index 635c25542cb..375ee660f9d 100644 --- a/esp/src/eclwatch/HPCCPlatformWidget.js +++ b/esp/src/eclwatch/HPCCPlatformWidget.js @@ -253,7 +253,7 @@ define([ context.checkIfAdmin(context.userName); context.refreshUserName(); if (!cookie("PasswordExpiredCheck")) { - cookie("PasswordExpiredCheck", "true", { expires: 1 }); + cookie("PasswordExpiredCheck", "true", { expires: 1, path: "/" }); if (lang.exists("MyAccountResponse.passwordDaysRemaining", response)) { switch (response.MyAccountResponse.passwordDaysRemaining) { case null: diff --git a/esp/src/eclwatch/LockDialogWidget.js b/esp/src/eclwatch/LockDialogWidget.js index 3028c6cd3b5..6b4717b0177 100644 --- a/esp/src/eclwatch/LockDialogWidget.js +++ b/esp/src/eclwatch/LockDialogWidget.js @@ -58,7 +58,6 @@ define([ show: function (event) { var context = this; if (!dojoConfig.username) { - cookie("Status", "Unlocked"); context.storage.setItem("Status", "Unlocked"); topic.publish("hpcc/session_management_status", { status: "Unlocked" @@ -96,7 +95,6 @@ define([ var context = this; if (this.unlockForm.validate()) { - cookie("Status", "login_attempt"); WsAccount.Unlock({ request: { username: this.unlockUserName.get("value"), @@ -113,7 +111,6 @@ define([ topic.publish("hpcc/session_management_status", { status: "Unlocked" }); - cookie("Status", "Unlocked"); context.storage.setItem("Status", "Unlocked"); if (context.idleFired) { dojo.publish("hpcc/brToaster", { @@ -127,7 +124,6 @@ define([ } } else { context.unlockStatus.innerHTML = response.UnlockResponse.Message; - cookie("Status", "Locked"); } }); } @@ -150,10 +146,9 @@ define([ topic.publish("hpcc/session_management_status", { status: "Locked" }); - cookie("Status", "Locked"); context.storage.setItem("Status", "Locked"); - } else if (cookie("Status") === "Unlocked") { - xhr("esp/lock", { + } else { + xhr("/esp/lock", { method: "post" }).then(function (response) { if (response) { @@ -163,7 +158,6 @@ define([ topic.publish("hpcc/session_management_status", { status: "Locked" }); - cookie("Status", "Locked"); context.storage.setItem("Status", "Locked"); } }); diff --git a/esp/src/index.html b/esp/src/index.html index 2ff97b9eed0..976da06abf0 100644 --- a/esp/src/index.html +++ b/esp/src/index.html @@ -38,7 +38,7 @@ } function checkCookie() { - document.cookie.indexOf("ESPAuthenticated=true") > -1 ? window.location.href : window.location.href = location.origin + "#/login"; + document.cookie.indexOf("ESPAuthenticated=true") > -1 ? window.location.href : window.location.href = location.origin + "/esp/files/Login.html"; } function sendAuthRequest() { diff --git a/esp/src/lws.config.js b/esp/src/lws.config.js index 0e147898d37..cd8e8dca97a 100644 --- a/esp/src/lws.config.js +++ b/esp/src/lws.config.js @@ -38,7 +38,7 @@ let rewrite = [ { from: "/esp/files/dist/(.*)", to: "/build/dist/$1" }, { from: "/esp/files/img/(.*)", to: "build/esp/files/img/$1" }, { from: "/esp/files/(.*/*.css)", to: "/build/esp/files/$1" }, - { from: "/esp/files/(.*)", to: "/$1" }, + { from: "/esp/files/(.*)", to: "/build/$1" }, { from: "/main", to: protocol + "://" + ip + ":" + port + "/main" }, { from: "/FileSpray/(.*)", to: protocol + "://" + ip + ":" + port + "/FileSpray/$1" }, { from: "/WsCloud/(.*)", to: protocol + "://" + ip + ":" + port + "/WsCloud/$1" }, diff --git a/esp/src/src-react/components/Frame.tsx b/esp/src/src-react/components/Frame.tsx index 594f756080c..d5630872736 100644 --- a/esp/src/src-react/components/Frame.tsx +++ b/esp/src/src-react/components/Frame.tsx @@ -65,7 +65,7 @@ export const Frame: React.FunctionComponent = () => { fireIdle(); } else if (publishedMessage.status === "Idle") { window.localStorage.setItem("pageOnLock", window.location.hash.substring(1)); - setUserSession({ ...userSession, Status: "Locked" }); + setUserSession({ ...userSession }); window.location.reload(); } }); diff --git a/esp/src/src-react/components/Title.tsx b/esp/src/src-react/components/Title.tsx index b04c940b178..1f423f8e60f 100644 --- a/esp/src/src-react/components/Title.tsx +++ b/esp/src/src-react/components/Title.tsx @@ -113,10 +113,10 @@ export const DevTitle: React.FunctionComponent = ({ { key: "divider_2", itemType: ContextualMenuItemType.Divider }, { key: "lock", text: nlsHPCC.Lock, disabled: !currentUser?.username, onClick: () => { - fetch("esp/lock", { + fetch("/esp/lock", { method: "post" }).then(() => { - setUserSession({ ...userSession, Status: "Locked" }); + setUserSession({ ...userSession }); replaceUrl("/login", null, true); }); } @@ -209,7 +209,7 @@ export const DevTitle: React.FunctionComponent = ({ if (!currentUser.username) return; if (!cookie("PasswordExpiredCheck")) { // cookie expires option expects whole number of days, use a decimal < 1 for hours - cookie("PasswordExpiredCheck", "true", { expires: 0.5 }); + cookie("PasswordExpiredCheck", "true", { expires: 0.5, path: "/" }); if (currentUser.passwordIsExpired) { alert(nlsHPCC.PasswordExpired); setShowMyAccount(true); diff --git a/esp/src/src-react/components/forms/Login.tsx b/esp/src/src-react/components/forms/Login.tsx index c8ab9fc5d97..9814ee5d82a 100644 --- a/esp/src/src-react/components/forms/Login.tsx +++ b/esp/src/src-react/components/forms/Login.tsx @@ -116,7 +116,6 @@ export const Login: React.FunctionComponent = ({ setErrorMessage(cookies.ESPAuthenticationMSG); setShowError(true); } else { - cookies["Status"] = "Unlocked"; cookies["ESPAuthenticated"] = "true"; createUserSession(cookies).then(() => { setErrorMessage(""); diff --git a/esp/src/src-react/hooks/user.ts b/esp/src/src-react/hooks/user.ts index 26647d03616..d5d5d000e91 100644 --- a/esp/src/src-react/hooks/user.ts +++ b/esp/src/src-react/hooks/user.ts @@ -7,7 +7,6 @@ const defaults = { ESPSessionTimeout: 7200, ESPAuthenticated: false, ECLWatchUser: false, - Status: "Unlocked", ESPSessionState: false }; @@ -17,7 +16,6 @@ export interface UserSession { ESPSessionTimeout: number; ESPAuthenticated: boolean; ECLWatchUser: boolean; - Status: string; ESPAuthenticationMSG?: string; ESPSessionState: boolean; } @@ -56,7 +54,6 @@ export function useUserSession(): { default: store.set("ESPSessionState", "false"); } - store.set("Status", "Unlocked"); store.set("ECLWatchUser", "true"); }).catch(err => console.log("Unable to create user session.")); }, [store]); diff --git a/esp/src/src-react/index.tsx b/esp/src/src-react/index.tsx index b1ecffcc918..502a2c56386 100644 --- a/esp/src/src-react/index.tsx +++ b/esp/src/src-react/index.tsx @@ -43,7 +43,7 @@ async function loadUI() { const authType = await authTypeResp?.text() ?? "None"; const userStore = cookieKeyValStore(); const userSession = await userStore.getAll(); - if (authType.indexOf("None") < 0 && (userSession["ESPSessionState"] === "false" || userSession["ECLWatchUser"] === "false" || (!userSession["Status"] || userSession["Status"] === "Locked"))) { + if (authType.indexOf("None") < 0 && (userSession["ESPSessionState"] === "false" || userSession["ECLWatchUser"] === "false")) { if (window.location.hash.indexOf("login") < 0) { replaceUrl("/login"); } diff --git a/esp/src/src/ESPRequest.ts b/esp/src/src/ESPRequest.ts index 1fbde9879f9..0f753faa61c 100644 --- a/esp/src/src/ESPRequest.ts +++ b/esp/src/src/ESPRequest.ts @@ -122,7 +122,6 @@ class RequestHelper { status: "DoIdle" }); } - cookie("Status", "Locked"); ESPUtil.LocalStorage.removeItem("Status"); } } diff --git a/esp/src/src/Session.ts b/esp/src/src/Session.ts index 15928b8b088..52f6260450a 100644 --- a/esp/src/src/Session.ts +++ b/esp/src/src/Session.ts @@ -3,12 +3,12 @@ import * as xhr from "dojo/request/xhr"; import * as topic from "dojo/topic"; import { format as d3Format } from "@hpcc-js/common"; import { SMCService } from "@hpcc-js/comms"; +import { scopedLogger } from "@hpcc-js/util"; import { cookieKeyValStore, sessionKeyValStore, userKeyValStore } from "src/KeyValStore"; import { singletonDebounce } from "../src-react/util/throttle"; import { parseSearch } from "../src-react/util/history"; import { ModernMode } from "./BuildInfo"; import * as ESPUtil from "./ESPUtil"; -import { scopedLogger } from "@hpcc-js/util"; const logger = scopedLogger("src/Session.ts"); @@ -43,6 +43,10 @@ export async function needsRedirectV5(): Promise { window.location.replace(`/esp/files/index.html${window.location.hash}`); return true; } + if (window.location.pathname.indexOf("/esp/files/stub.htm") < 0) { + window.location.replace(`/esp/files/stub.htm${window.location.search}${window.location.hash}`); + return true; + } if (isV5DirectURL()) { return false; } @@ -141,21 +145,16 @@ export function initSession() { }); idleWatcher.start(); - if (!cookie("Status")) { - document.cookie = "Status=Unlocked;Path=/"; - } } else if (cookie("ECLWatchUser")) { window.location.replace(dojoConfig.urlInfo.basePath + "/Login.html"); } } export function lock() { - cookie("Status", "Locked"); idleWatcher.stop(); } export function unlock() { - cookie("Status", "Unlocked"); idleWatcher.start(); } diff --git a/esp/src/src/Utility.ts b/esp/src/src/Utility.ts index 46bfcf4b850..62a0a087ab7 100644 --- a/esp/src/src/Utility.ts +++ b/esp/src/src/Utility.ts @@ -1057,7 +1057,7 @@ export function parseCookies(): Record { export function deleteCookie(name: string) { const expireDate = new Date(); expireDate.setSeconds(expireDate.getSeconds() + 1); - document.cookie = `${name}=; domain=${window.location.hostname}; path=/; expires=${expireDate.toUTCString()}`; + document.cookie = `${name}=; domain=${window.location.hostname}; expires=${expireDate.toUTCString()}`; } const d3FormatDecimal = d3Format(",.2f");