From 1621648bf9d3f8372f9751ca8670aca7b8951b0f Mon Sep 17 00:00:00 2001 From: Gordon Smith Date: Fri, 22 Sep 2023 14:22:14 +0100 Subject: [PATCH 1/4] Split off 8.10.62 Signed-off-by: Gordon Smith --- helm/hpcc/Chart.yaml | 4 ++-- helm/hpcc/templates/_helpers.tpl | 2 +- helm/hpcc/templates/dafilesrv.yaml | 2 +- helm/hpcc/templates/dali.yaml | 2 +- helm/hpcc/templates/dfuserver.yaml | 2 +- helm/hpcc/templates/eclagent.yaml | 4 ++-- helm/hpcc/templates/eclccserver.yaml | 4 ++-- helm/hpcc/templates/eclscheduler.yaml | 2 +- helm/hpcc/templates/esp.yaml | 2 +- helm/hpcc/templates/localroxie.yaml | 2 +- helm/hpcc/templates/roxie.yaml | 8 ++++---- helm/hpcc/templates/sasha.yaml | 2 +- helm/hpcc/templates/thor.yaml | 10 +++++----- version.cmake | 2 +- 14 files changed, 24 insertions(+), 24 deletions(-) diff --git a/helm/hpcc/Chart.yaml b/helm/hpcc/Chart.yaml index a78c1e9cd8a..7f050b91f9e 100644 --- a/helm/hpcc/Chart.yaml +++ b/helm/hpcc/Chart.yaml @@ -6,9 +6,9 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. -version: 8.10.61-closedown0 +version: 8.10.63-closedown0 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. -appVersion: 8.10.61-closedown0 +appVersion: 8.10.63-closedown0 diff --git a/helm/hpcc/templates/_helpers.tpl b/helm/hpcc/templates/_helpers.tpl index 7f3a3cf74d4..b5b1d55c3b8 100644 --- a/helm/hpcc/templates/_helpers.tpl +++ b/helm/hpcc/templates/_helpers.tpl @@ -1208,7 +1208,7 @@ kind: Service metadata: name: {{ $lvars.serviceName | quote }} labels: - helmVersion: 8.10.61-closedown0 + helmVersion: 8.10.63-closedown0 {{- include "hpcc.addStandardLabels" (dict "root" $.root "instance" $lvars.serviceName ) | indent 4 }} {{- if $lvars.labels }} {{ toYaml $lvars.labels | indent 4 }} diff --git a/helm/hpcc/templates/dafilesrv.yaml b/helm/hpcc/templates/dafilesrv.yaml index a49c696dbd1..63080874c54 100644 --- a/helm/hpcc/templates/dafilesrv.yaml +++ b/helm/hpcc/templates/dafilesrv.yaml @@ -50,7 +50,7 @@ spec: labels: {{- include "hpcc.addStandardLabels" (dict "root" $ "component" "dafilesrv" "name" "dafilesrv" "instance" .name) | indent 8 }} server: {{ .name | quote }} - helmVersion: 8.10.61-closedown0 + helmVersion: 8.10.63-closedown0 annotations: checksum/config: {{ $configSHA }} spec: diff --git a/helm/hpcc/templates/dali.yaml b/helm/hpcc/templates/dali.yaml index 7b8fd476465..847fffaa841 100644 --- a/helm/hpcc/templates/dali.yaml +++ b/helm/hpcc/templates/dali.yaml @@ -81,7 +81,7 @@ spec: run: {{ $dali.name | quote }} server: {{ $dali.name | quote }} app: dali - helmVersion: 8.10.61-closedown0 + helmVersion: 8.10.63-closedown0 {{- if hasKey $.Values.global "metrics" }} {{- include "hpcc.generateMetricsReporterLabel" $.Values.global.metrics | nindent 8 }} {{- end }} diff --git a/helm/hpcc/templates/dfuserver.yaml b/helm/hpcc/templates/dfuserver.yaml index b78cb54cb0e..c83522dcc0a 100644 --- a/helm/hpcc/templates/dfuserver.yaml +++ b/helm/hpcc/templates/dfuserver.yaml @@ -56,7 +56,7 @@ spec: {{- include "hpcc.addStandardLabels" (dict "root" $ "component" "dfuserver" "name" "dfuserver" "instance" .name) | indent 8 }} run: {{ .name | quote }} accessDali: "yes" - helmVersion: 8.10.61-closedown0 + helmVersion: 8.10.63-closedown0 {{- if hasKey . "labels" }} {{ toYaml .labels | indent 8 }} {{- end }} diff --git a/helm/hpcc/templates/eclagent.yaml b/helm/hpcc/templates/eclagent.yaml index a22d419e456..8fa036065aa 100644 --- a/helm/hpcc/templates/eclagent.yaml +++ b/helm/hpcc/templates/eclagent.yaml @@ -58,7 +58,7 @@ data: {{- include "hpcc.addStandardLabels" (dict "root" $ "component" $apptype "name" "eclagent" "instance" $appJobName "instanceOf" (printf "%s-job" .me.name)) | indent 12 }} accessDali: "yes" accessEsp: "yes" - helmVersion: 8.10.61-closedown0 + helmVersion: 8.10.63-closedown0 {{- if hasKey .me "labels" }} {{ toYaml .me.labels | indent 12 }} {{- end }} @@ -137,7 +137,7 @@ spec: run: {{ .name | quote }} accessDali: "yes" accessEsp: {{ .useChildProcesses | default false | ternary "yes" "no" | quote }} - helmVersion: 8.10.61-closedown0 + helmVersion: 8.10.63-closedown0 {{- if hasKey . "labels" }} {{ toYaml .labels | indent 8 }} {{- end }} diff --git a/helm/hpcc/templates/eclccserver.yaml b/helm/hpcc/templates/eclccserver.yaml index 1d2713a7208..098ecf1fa3c 100644 --- a/helm/hpcc/templates/eclccserver.yaml +++ b/helm/hpcc/templates/eclccserver.yaml @@ -57,7 +57,7 @@ data: {{- include "hpcc.addStandardLabels" (dict "root" $ "component" "eclccserver" "name" "eclccserver" "instance" $compileJobName "instanceOf" (printf "%s-job" .me.name)) | indent 12 }} accessDali: "yes" accessEsp: "yes" - helmVersion: 8.10.61-closedown0 + helmVersion: 8.10.63-closedown0 {{- if hasKey .me "labels" }} {{ toYaml .me.labels | indent 12 }} {{- end }} @@ -142,7 +142,7 @@ spec: run: {{ .name | quote }} accessDali: "yes" accessEsp: {{ .useChildProcesses | default false | ternary "yes" "no" | quote }} - helmVersion: 8.10.61-closedown0 + helmVersion: 8.10.63-closedown0 {{- if hasKey . "labels" }} {{ toYaml .labels | indent 8 }} {{- end }} diff --git a/helm/hpcc/templates/eclscheduler.yaml b/helm/hpcc/templates/eclscheduler.yaml index 0b4a20f8b2c..22b457f823a 100644 --- a/helm/hpcc/templates/eclscheduler.yaml +++ b/helm/hpcc/templates/eclscheduler.yaml @@ -64,7 +64,7 @@ spec: run: {{ .name | quote }} accessDali: "yes" accessEsp: "no" - helmVersion: 8.10.61-closedown0 + helmVersion: 8.10.63-closedown0 {{- if hasKey . "labels" }} {{ toYaml .labels | indent 8 }} {{- end }} diff --git a/helm/hpcc/templates/esp.yaml b/helm/hpcc/templates/esp.yaml index 95ece3aee0e..ef226043918 100644 --- a/helm/hpcc/templates/esp.yaml +++ b/helm/hpcc/templates/esp.yaml @@ -116,7 +116,7 @@ spec: server: {{ .name | quote }} accessDali: "yes" app: {{ $application }} - helmVersion: 8.10.61-closedown0 + helmVersion: 8.10.63-closedown0 {{- include "hpcc.addStandardLabels" (dict "root" $ "name" $application "component" "esp" "instance" .name) | indent 8 }} {{- if hasKey $.Values.global "metrics" }} {{- include "hpcc.generateMetricsReporterLabel" $.Values.global.metrics | nindent 8 }} diff --git a/helm/hpcc/templates/localroxie.yaml b/helm/hpcc/templates/localroxie.yaml index 9c4d242575e..a09491568c2 100644 --- a/helm/hpcc/templates/localroxie.yaml +++ b/helm/hpcc/templates/localroxie.yaml @@ -70,7 +70,7 @@ spec: server: {{ $servername | quote }} accessDali: "yes" accessEsp: "yes" - helmVersion: 8.10.61-closedown0 + helmVersion: 8.10.63-closedown0 {{- include "hpcc.addStandardLabels" (dict "root" $ "component" "roxie-server" "name" "roxie" "instance" $roxie.name) | indent 8 }} {{- if hasKey . "labels" }} {{ toYaml .labels | indent 8 }} diff --git a/helm/hpcc/templates/roxie.yaml b/helm/hpcc/templates/roxie.yaml index 87149855f85..a71c7424fd5 100644 --- a/helm/hpcc/templates/roxie.yaml +++ b/helm/hpcc/templates/roxie.yaml @@ -118,7 +118,7 @@ spec: {{- include "hpcc.addStandardLabels" (dict "root" $ "component" "topology-server" "name" "roxie" "instance" $commonCtx.toponame) | indent 8 }} run: {{ $commonCtx.toponame | quote }} roxie-cluster: {{ $roxie.name | quote }} - helmVersion: 8.10.61-closedown0 + helmVersion: 8.10.63-closedown0 {{- if hasKey $.Values.global "metrics" }} {{- include "hpcc.generateMetricsReporterLabel" $.Values.global.metrics | nindent 8}} {{- end }} @@ -178,7 +178,7 @@ kind: Service metadata: name: {{ $commonCtx.toponame | quote }} labels: - helmVersion: 8.10.61-closedown0 + helmVersion: 8.10.63-closedown0 {{- include "hpcc.addStandardLabels" (dict "root" $ "component" "topology-server" "name" "roxie" "instance" $commonCtx.toponame) | indent 4 }} spec: ports: @@ -240,7 +240,7 @@ spec: roxie-cluster: {{ $roxie.name | quote }} accessDali: "yes" accessEsp: "yes" - helmVersion: 8.10.61-closedown0 + helmVersion: 8.10.63-closedown0 {{- include "hpcc.addStandardLabels" (dict "root" $ "component" "roxie-server" "name" "roxie" "instance" $servername) | indent 8 }} {{- if hasKey $.Values.global "metrics" }} {{- include "hpcc.generateMetricsReporterLabel" $.Values.global.metrics | nindent 8}} @@ -343,7 +343,7 @@ spec: roxie-cluster: {{ $roxie.name | quote }} accessDali: "yes" accessEsp: "yes" - helmVersion: 8.10.61-closedown0 + helmVersion: 8.10.63-closedown0 {{- if hasKey $.Values.global "metrics" }} {{- include "hpcc.generateMetricsReporterLabel" $.Values.global.metrics | nindent 8}} {{- end }} diff --git a/helm/hpcc/templates/sasha.yaml b/helm/hpcc/templates/sasha.yaml index 4c1de9ca988..f18acce7be2 100644 --- a/helm/hpcc/templates/sasha.yaml +++ b/helm/hpcc/templates/sasha.yaml @@ -52,7 +52,7 @@ spec: run: {{ $serviceName | quote }} server: {{ $serviceName | quote }} accessDali: {{ (has "dali" $sasha.access) | ternary "yes" "no" | quote }} - helmVersion: 8.10.61-closedown0 + helmVersion: 8.10.63-closedown0 {{- if hasKey $sasha "labels" }} {{ toYaml $sasha.labels | indent 8 }} {{- end }} diff --git a/helm/hpcc/templates/thor.yaml b/helm/hpcc/templates/thor.yaml index b0dbcc5fdad..a98a3b62b65 100644 --- a/helm/hpcc/templates/thor.yaml +++ b/helm/hpcc/templates/thor.yaml @@ -82,7 +82,7 @@ data: labels: accessDali: "yes" accessEsp: "yes" - helmVersion: 8.10.61-closedown0 + helmVersion: 8.10.63-closedown0 {{- include "hpcc.addStandardLabels" (dict "root" $ "component" "eclagent" "name" "thor" "instance" $eclAgentJobName "instanceOf" (printf "%s-job" .eclAgentName)) | indent 8 }} {{- if hasKey .me "labels" }} {{ toYaml .me.labels | indent 12 }} @@ -149,7 +149,7 @@ data: accessEsp: "yes" app: "thor" component: "thormanager" - helmVersion: 8.10.61-closedown0 + helmVersion: 8.10.63-closedown0 instance: "_HPCC_JOBNAME_" job: "_HPCC_JOBNAME_" {{- include "hpcc.addStandardLabels" (dict "root" $ "component" "thormanager" "name" "thor" "instance" $thorManagerJobName "instanceOf" (printf "%s-thormanager-job" .me.name)) | indent 12 }} @@ -218,7 +218,7 @@ data: accessEsp: "yes" app: "thor" component: "thorworker" - helmVersion: 8.10.61-closedown0 + helmVersion: 8.10.63-closedown0 instance: "_HPCC_JOBNAME_" job: "_HPCC_JOBNAME_" {{- include "hpcc.addStandardLabels" (dict "root" $ "component" "thorworker" "name" "thor" "instance" $thorWorkerJobName "instanceOf" (printf "%s-thorworker-job" .me.name)) | indent 12 }} @@ -353,7 +353,7 @@ spec: accessEsp: {{ $commonCtx.eclAgentUseChildProcesses | ternary "yes" "no" | quote }} app: "thor" component: "thor-eclagent" - helmVersion: 8.10.61-closedown0 + helmVersion: 8.10.63-closedown0 instance: {{ $commonCtx.eclAgentName | quote }} {{- include "hpcc.addStandardLabels" (dict "root" $ "component" "eclagent" "name" "thor" "instance" $commonCtx.eclAgentName ) | indent 8 }} {{- if hasKey $commonCtx.me "labels" }} @@ -418,7 +418,7 @@ spec: accessEsp: "no" app: "thor" component: "thor-thoragent" - helmVersion: 8.10.61-closedown0 + helmVersion: 8.10.63-closedown0 instance: {{ $commonCtx.thorAgentName | quote }} {{- include "hpcc.addStandardLabels" (dict "root" $ "component" "eclagent" "name" "thor" "instance" $commonCtx.thorAgentName ) | indent 8 }} {{- if hasKey $commonCtx.me "labels" }} diff --git a/version.cmake b/version.cmake index f489a4db670..699157579ff 100644 --- a/version.cmake +++ b/version.cmake @@ -5,7 +5,7 @@ set ( HPCC_NAME "Community Edition" ) set ( HPCC_PROJECT "community" ) set ( HPCC_MAJOR 8 ) set ( HPCC_MINOR 10 ) -set ( HPCC_POINT 61 ) +set ( HPCC_POINT 63 ) set ( HPCC_MATURITY "closedown" ) set ( HPCC_SEQUENCE 0 ) ### From a1a65efa07b975f1195fc904a91f8556b77146c1 Mon Sep 17 00:00:00 2001 From: Jeremy Clements <79224539+jeclrsg@users.noreply.github.com> Date: Thu, 28 Sep 2023 10:37:46 -0400 Subject: [PATCH 2/4] 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 | 28 +++++++++++++++++--- 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, 50 insertions(+), 13 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 67ecfd90b01..594f756080c 100644 --- a/esp/src/src-react/components/Frame.tsx +++ b/esp/src/src-react/components/Frame.tsx @@ -1,18 +1,21 @@ 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 { useGlobalWorkunitNotes } from "../hooks/workunit"; 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 { useGlobalWorkunitNotes } from "../hooks/workunit"; +import { useUserSession } from "../hooks/user"; const logger = scopedLogger("../components/Frame.tsx"); const envLogger = scopedLogger("environment"); @@ -23,6 +26,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(); @@ -49,6 +53,24 @@ export const Frame: React.FunctionComponent = () => { }); }, [globalWUNotes]); + 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(() => { const unlisten = hashHistory.listen(async (location, action) => { 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"); } 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 3/4] 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"); } From 7194b6dbd90c6ef68ce479c118ae2e46606c8f04 Mon Sep 17 00:00:00 2001 From: Mark Kelly Date: Wed, 27 Sep 2023 09:19:23 -0400 Subject: [PATCH 4/4] HPCC-30377 SendEmail exception while reading from mail server Signed-off-by: Mark Kelly --- common/remote/rmtsmtp.cpp | 178 ++++++++++++------ common/remote/rmtsmtp.hpp | 12 +- ecllibrary/std/system/Email.ecl | 15 +- .../ws_workunits/ws_workunitsHelpers.cpp | 6 +- .../ws_workunits/ws_workunitsHelpers.hpp | 5 +- plugins/fileservices/fileservices.cpp | 35 +++- plugins/fileservices/fileservices.hpp | 3 + plugins/proxies/lib_fileservices.ecllib | 6 +- tools/swapnode/swapnodelib.cpp | 2 +- 9 files changed, 178 insertions(+), 84 deletions(-) diff --git a/common/remote/rmtsmtp.cpp b/common/remote/rmtsmtp.cpp index 7a3cf970ea8..c0dad58a889 100644 --- a/common/remote/rmtsmtp.cpp +++ b/common/remote/rmtsmtp.cpp @@ -476,14 +476,15 @@ class CMailInfo char inbuff[200]; unsigned inlen; bool highPriority; + bool termJobOnFail; static char const * toHeader; static char const * ccHeader; static char const * subjectHeader; static char const * senderHeader; public: - CMailInfo(char const * _to, char const * _cc, char const * _bcc, char const * _subject, char const * _mailServer, unsigned _port, char const * _sender, StringArray *_warnings, bool _highPriority) - : subject(_subject), mailServer(_mailServer), port(_port), sender(_sender), lastAction("process initialization"), inlen(0), highPriority(_highPriority) + CMailInfo(char const * _to, char const * _cc, char const * _bcc, char const * _subject, char const * _mailServer, unsigned _port, char const * _sender, StringArray *_warnings, bool _highPriority, bool _termJobOnFail) + : subject(_subject), mailServer(_mailServer), port(_port), sender(_sender), lastAction("process initialization"), inlen(0), highPriority(_highPriority), termJobOnFail(_termJobOnFail) { warnings = _warnings; CSMTPValidator validator; @@ -528,6 +529,7 @@ class CMailInfo lastAction.clear().append(action); else lastAction.clear().append(len, out).clip(); + try { socket->write(out, len); @@ -545,30 +547,34 @@ class CMailInfo } } - void read() + bool read(int numRetriesRemaining) { try { - socket->read(inbuff,1,sizeof(inbuff),inlen); + socket->readtms(inbuff, 1, sizeof(inbuff), inlen, 30000); + //MORE: the following is somewhat primitive and not RFC compliant (see bug 25951) - but it is a lot better than nothing - if((*inbuff == '4') || (*inbuff == '5')) + if ( (*inbuff == '5') || ((*inbuff == '4') && (!numRetriesRemaining)) ) { StringBuffer b; - b.append("Negative reply from mail server at ").append(mailServer.get()).append(":").append(port).append(" after writing ").append(lastAction.str()).append(" in SendEmail*: ").append(inlen, inbuff).clip(); - WARNLOG("%s", b.str()); - if (warnings) - warnings->append(b.str()); + b.append("negative reply after writing ").append(inlen, inbuff).clip(); + // don't continue on after these responses ... + throw makeStringException(MSGAUD_operator, 0, b.str()); } -#ifdef SMTP_TRACE else { +#ifdef SMTP_TRACE StringBuffer b(inlen, inbuff); b.clip(); DBGLOG("SMTP read: [%s]", b.str()); - } #endif + if (*inbuff == '4') + return false; + else + return true; + } } - catch(IException * e) + catch (IException * e) { int code = e->errorCode(); StringBuffer buff; @@ -578,6 +584,34 @@ class CMailInfo } } + void readRemainingData() + { + // read any remaining bytes ... + try + { + socket->readtms(inbuff, 0, sizeof(inbuff), inlen, 0); + } + catch(IException * e) + { + e->Release(); + } + } + + void writeAndAck(char const * out, size32_t len, char const * action = NULL) + { + bool ok; + int retries = 2; + while (retries >= 0) + { + readRemainingData(); + write(out, len, action); + ok = read(retries); + if (ok) + break; + retries--; + } + } + void getHeader(StringBuffer & header) const { header.append(senderHeader).append(sender.get()).append("\r\n"); @@ -615,6 +649,17 @@ class CMailInfo out.append("RCPT TO:<").append(rcpt).append(">\r\n"); } + bool getTermJobOnFail() const + { + return termJobOnFail; + } + + void addToWarnings(const char *warnStr) const + { + if (warnings && (warnStr && *warnStr)) + warnings->append(warnStr); + } + private: void getRecipients(CSMTPValidator & validator, char const * _to, StringBuffer &destBuffer) { @@ -773,77 +818,98 @@ static const char *quit="QUIT\r\n"; static void doSendEmail(CMailInfo & info, CMailPart const & part) { - info.open(); - StringBuffer outbuff; - - info.read(); - info.getHelo(outbuff); - info.write(outbuff.str(), outbuff.length()); - info.read(); - - info.getMailFrom(outbuff.clear()); - info.write(outbuff.str(), outbuff.length()); - info.read(); - - unsigned numRcpt = info.numRecipients(); - for(unsigned i=0; i= 0) + { + info.readRemainingData(); + info.write(outbuff.str(), outbuff.length(), "mail header"); + part.write(info); + info.write(endMail, strlen(endMail), "end of mail body"); + ok = info.read(retries); + if (ok) + break; + retries--; + } + + info.writeAndAck(quit, strlen(quit)); + } + catch(IException * e) + { + if (info.getTermJobOnFail()) + throw e; + + StringBuffer msg; + info.addToWarnings(e->errorMessage(msg).str()); + EXCLOG(MCoperatorError, e, "WARNING"); + e->Release(); + } } -void sendEmail(const char * to, const char * cc, const char * bcc, const char * subject, const char * body, const char * mailServer, unsigned port, const char * sender, StringArray *warnings, bool highPriority) +void sendEmail(const char * to, const char * cc, const char * bcc, const char * subject, const char * body, const char * mailServer, unsigned port, const char * sender, StringArray *warnings, bool highPriority, bool termJobOnFail) { - CMailInfo info(to, cc, bcc, subject, mailServer, port, sender, warnings, highPriority); + CMailInfo info(to, cc, bcc, subject, mailServer, port, sender, warnings, highPriority, termJobOnFail); CTextMailPart bodyPart(body, "text/plain; charset=ISO-8859-1", NULL); doSendEmail(info, bodyPart); } -void sendEmail(const char * to, const char * subject, const char * body, const char * mailServer, unsigned port, const char * sender, StringArray *warnings, bool highPriority) +void sendEmail(const char * to, const char * subject, const char * body, const char * mailServer, unsigned port, const char * sender, StringArray *warnings, bool highPriority, bool termJobOnFail) { - sendEmail(to, nullptr, nullptr, subject, body, mailServer, port, sender, warnings, highPriority); + sendEmail(to, nullptr, nullptr, subject, body, mailServer, port, sender, warnings, highPriority, termJobOnFail); } -void sendEmailAttachText(const char * to, const char * cc, const char * bcc, const char * subject, const char * body, const char * attachment, const char * mimeType, const char * attachmentName, const char * mailServer, unsigned int port, const char * sender, StringArray *warnings, bool highPriority) +void sendEmailAttachText(const char * to, const char * cc, const char * bcc, const char * subject, const char * body, const char * attachment, const char * mimeType, const char * attachmentName, const char * mailServer, unsigned int port, const char * sender, StringArray *warnings, bool highPriority, bool termJobOnFail) { - CMailInfo info(to, cc, bcc, subject, mailServer, port, sender, warnings, highPriority); + CMailInfo info(to, cc, bcc, subject, mailServer, port, sender, warnings, highPriority, termJobOnFail); CTextMailPart inlinedPart(body, "text/plain; charset=ISO-8859-1", NULL); CTextMailPart attachmentPart(attachment, mimeType, attachmentName); CMultiMailPart multiPart(inlinedPart, attachmentPart); doSendEmail(info, multiPart); } -void sendEmailAttachText(const char * to, const char * subject, const char * body, const char * attachment, const char * mimeType, const char * attachmentName, const char * mailServer, unsigned int port, const char * sender, StringArray *warnings, bool highPriority) +void sendEmailAttachText(const char * to, const char * subject, const char * body, const char * attachment, const char * mimeType, const char * attachmentName, const char * mailServer, unsigned int port, const char * sender, StringArray *warnings, bool highPriority, bool termJobOnFail) { - sendEmailAttachText(to, nullptr, nullptr, subject, body, attachment, mimeType, attachmentName, mailServer, port, sender, warnings, highPriority); + sendEmailAttachText(to, nullptr, nullptr, subject, body, attachment, mimeType, attachmentName, mailServer, port, sender, warnings, highPriority, termJobOnFail); } -void sendEmailAttachData(const char * to, const char * cc, const char * bcc, const char * subject, const char * body, size32_t lenAttachment, const void * attachment, const char * mimeType, const char * attachmentName, const char * mailServer, unsigned int port, const char * sender, StringArray *warnings, bool highPriority) +void sendEmailAttachData(const char * to, const char * cc, const char * bcc, const char * subject, const char * body, size32_t lenAttachment, const void * attachment, const char * mimeType, const char * attachmentName, const char * mailServer, unsigned int port, const char * sender, StringArray *warnings, bool highPriority, bool termJobOnFail) { - CMailInfo info(to, cc, bcc, subject, mailServer, port, sender, warnings, highPriority); + CMailInfo info(to, cc, bcc, subject, mailServer, port, sender, warnings, highPriority, termJobOnFail); CTextMailPart inlinedPart(body, "text/plain; charset=ISO-8859-1", NULL); CDataMailPart attachmentPart(lenAttachment, attachment, mimeType, attachmentName); CMultiMailPart multiPart(inlinedPart, attachmentPart); doSendEmail(info, multiPart); } -void sendEmailAttachData(const char * to, const char * subject, const char * body, size32_t lenAttachment, const void * attachment, const char * mimeType, const char * attachmentName, const char * mailServer, unsigned int port, const char * sender, StringArray *warnings, bool highPriority) +void sendEmailAttachData(const char * to, const char * subject, const char * body, size32_t lenAttachment, const void * attachment, const char * mimeType, const char * attachmentName, const char * mailServer, unsigned int port, const char * sender, StringArray *warnings, bool highPriority, bool termJobOnFail) { - sendEmailAttachData(to, nullptr, nullptr, subject, body, lenAttachment, attachment, mimeType, attachmentName, mailServer, port, sender, warnings, highPriority); + sendEmailAttachData(to, nullptr, nullptr, subject, body, lenAttachment, attachment, mimeType, attachmentName, mailServer, port, sender, warnings, highPriority, termJobOnFail); } diff --git a/common/remote/rmtsmtp.hpp b/common/remote/rmtsmtp.hpp index 22e3f687f2c..d5933b2fd37 100644 --- a/common/remote/rmtsmtp.hpp +++ b/common/remote/rmtsmtp.hpp @@ -27,14 +27,14 @@ #define REMOTE_API DECL_IMPORT #endif -extern REMOTE_API void sendEmail( const char * to, const char * cc, const char * bcc, const char * subject, const char * body, const char * mailServer, unsigned port, const char * sender, StringArray *warnings=NULL, bool highPriority=false); -extern REMOTE_API void sendEmail( const char * to, const char * subject, const char * body, const char * mailServer, unsigned port, const char * sender, StringArray *warnings=NULL, bool highPriority=false); +extern REMOTE_API void sendEmail( const char * to, const char * cc, const char * bcc, const char * subject, const char * body, const char * mailServer, unsigned port, const char * sender, StringArray *warnings=NULL, bool highPriority=false, bool termJobOnFail=true); +extern REMOTE_API void sendEmail( const char * to, const char * subject, const char * body, const char * mailServer, unsigned port, const char * sender, StringArray *warnings=NULL, bool highPriority=false, bool termJobOnFail=true); -extern REMOTE_API void sendEmailAttachText(const char * to, const char * cc, const char * bcc, const char * subject, const char * body, const char * attachment, const char * mimeType, const char * attachmentName, const char * mailServer, unsigned int port, const char * sender, StringArray *warnings=NULL, bool highPriority=false); -extern REMOTE_API void sendEmailAttachText(const char * to, const char * subject, const char * body, const char * attachment, const char * mimeType, const char * attachmentName, const char * mailServer, unsigned int port, const char * sender, StringArray *warnings=NULL, bool highPriority=false); +extern REMOTE_API void sendEmailAttachText(const char * to, const char * cc, const char * bcc, const char * subject, const char * body, const char * attachment, const char * mimeType, const char * attachmentName, const char * mailServer, unsigned int port, const char * sender, StringArray *warnings=NULL, bool highPriority=false, bool termJobOnFail=true); +extern REMOTE_API void sendEmailAttachText(const char * to, const char * subject, const char * body, const char * attachment, const char * mimeType, const char * attachmentName, const char * mailServer, unsigned int port, const char * sender, StringArray *warnings=NULL, bool highPriority=false, bool termJobOnFail=true); -extern REMOTE_API void sendEmailAttachData(const char * to, const char * cc, const char * bcc, const char * subject, const char * body, size32_t lenAttachment, const void * attachment, const char * mimeType, const char * attachmentName, const char * mailServer, unsigned int port, const char * sender, StringArray *warnings=NULL, bool highPriority=false); -extern REMOTE_API void sendEmailAttachData(const char * to, const char * subject, const char * body, size32_t lenAttachment, const void * attachment, const char * mimeType, const char * attachmentName, const char * mailServer, unsigned int port, const char * sender, StringArray *warnings=NULL, bool highPriority=false); +extern REMOTE_API void sendEmailAttachData(const char * to, const char * cc, const char * bcc, const char * subject, const char * body, size32_t lenAttachment, const void * attachment, const char * mimeType, const char * attachmentName, const char * mailServer, unsigned int port, const char * sender, StringArray *warnings=NULL, bool highPriority=false, bool termJobOnFail=true); +extern REMOTE_API void sendEmailAttachData(const char * to, const char * subject, const char * body, size32_t lenAttachment, const void * attachment, const char * mimeType, const char * attachmentName, const char * mailServer, unsigned int port, const char * sender, StringArray *warnings=NULL, bool highPriority=false, bool termJobOnFail=true); #endif diff --git a/ecllibrary/std/system/Email.ecl b/ecllibrary/std/system/Email.ecl index 96ea6db0296..3c4d3a05678 100644 --- a/ecllibrary/std/system/Email.ecl +++ b/ecllibrary/std/system/Email.ecl @@ -18,10 +18,11 @@ RETURN MODULE * @param cc Optional comma-delimited addresses of carbon-copy recipients. Defaults to an empty string (none). * @param bcc Optional comma-delimited addresses of blind-carbon-copy recipients. Defaults to an empty string (none). * @param highPriority Optional; if true, message is sent with high priority. Defaults to false (normal priority). + * @param rptErrAsFail Optional; if true, any error while trying to send email will result in an error/exception. Defaults to true. */ -EXPORT SendEmail(varstring to, varstring subject, varstring body, varstring mailServer=GETENV('SMTPserver'), unsigned4 port=(unsigned4) GETENV('SMTPport', '25'), varstring sender=GETENV('emailSenderAddress'), varstring cc='', varstring bcc='', boolean highPriority=false) := - lib_fileservices.FileServices.SendEmail(to, subject, body, mailServer, port, sender, cc, bcc, highPriority); +EXPORT SendEmail(varstring to, varstring subject, varstring body, varstring mailServer=GETENV('SMTPserver'), unsigned4 port=(unsigned4) GETENV('SMTPport', '25'), varstring sender=GETENV('emailSenderAddress'), varstring cc='', varstring bcc='', boolean highPriority=false, boolean rptErrAsFail=true) := + lib_fileservices.FileServices.SendEmail(to, subject, body, mailServer, port, sender, cc, bcc, highPriority, rptErrAsFail); /* * Sends an email message with a text attachment using a mail server. @@ -36,10 +37,11 @@ EXPORT SendEmail(varstring to, varstring subject, varstring body, varstring mail * @param cc Optional comma-delimited addresses of carbon-copy recipients. Defaults to an empty string (none). * @param bcc Optional comma-delimited addresses of blind-carbon-copy recipients. Defaults to an empty string (none). * @param highPriority Optional; if true, message is sent with high priority. Defaults to false (normal priority). + * @param rptErrAsFail Optional; if true, any error while trying to send email will result in an error/exception. Defaults to true. */ -EXPORT SendEmailAttachText(varstring to, varstring subject, varstring body, varstring attachment, varstring mimeType, varstring attachmentName, varstring mailServer=GETENV('SMTPserver'), unsigned4 port=(unsigned4) GETENV('SMTPport', '25'), varstring sender=GETENV('emailSenderAddress'), varstring cc='', varstring bcc='', boolean highPriority=false) := - lib_fileservices.FileServices.SendEmailAttachText(to, subject, body, attachment, mimeType, attachmentName, mailServer, port, sender, cc, bcc, highPriority); +EXPORT SendEmailAttachText(varstring to, varstring subject, varstring body, varstring attachment, varstring mimeType, varstring attachmentName, varstring mailServer=GETENV('SMTPserver'), unsigned4 port=(unsigned4) GETENV('SMTPport', '25'), varstring sender=GETENV('emailSenderAddress'), varstring cc='', varstring bcc='', boolean highPriority=false, boolean rptErrAsFail=true) := + lib_fileservices.FileServices.SendEmailAttachText(to, subject, body, attachment, mimeType, attachmentName, mailServer, port, sender, cc, bcc, highPriority, rptErrAsFail); /* * Sends an email message with an arbitrary attachment using a mail server. @@ -56,9 +58,10 @@ EXPORT SendEmailAttachText(varstring to, varstring subject, varstring body, vars * @param cc Optional comma-delimited addresses of carbon-copy recipients. Defaults to an empty string (none). * @param bcc Optional comma-delimited addresses of blind-carbon-copy recipients. Defaults to an empty string (none). * @param highPriority Optional; if true, message is sent with high priority. Defaults to false (normal priority). + * @param rptErrAsFail Optional; if true, any error while trying to send email will result in an error/exception. Defaults to true. */ -EXPORT SendEmailAttachData(varstring to, varstring subject, varstring body, data attachment, varstring mimeType, varstring attachmentName, varstring mailServer=GETENV('SMTPserver'), unsigned4 port=(unsigned4) GETENV('SMTPport', '25'), varstring sender=GETENV('emailSenderAddress'), varstring cc='', varstring bcc='', boolean highPriority=false) := - lib_fileservices.FileServices.SendEmailAttachData(to, subject, body, attachment, mimeType, attachmentName, mailServer, port, sender, cc, bcc, highPriority); +EXPORT SendEmailAttachData(varstring to, varstring subject, varstring body, data attachment, varstring mimeType, varstring attachmentName, varstring mailServer=GETENV('SMTPserver'), unsigned4 port=(unsigned4) GETENV('SMTPport', '25'), varstring sender=GETENV('emailSenderAddress'), varstring cc='', varstring bcc='', boolean highPriority=false, boolean rptErrAsFail=true) := + lib_fileservices.FileServices.SendEmailAttachData(to, subject, body, attachment, mimeType, attachmentName, mailServer, port, sender, cc, bcc, highPriority, rptErrAsFail); END; diff --git a/esp/services/ws_workunits/ws_workunitsHelpers.cpp b/esp/services/ws_workunits/ws_workunitsHelpers.cpp index 8a2339fc421..b4c8450f6c7 100644 --- a/esp/services/ws_workunits/ws_workunitsHelpers.cpp +++ b/esp/services/ws_workunits/ws_workunitsHelpers.cpp @@ -4496,7 +4496,7 @@ IFileIOStream* CWsWuFileHelper::createWUZAPFileIOStream(IEspContext& context, IC if (request.sendEmail) { - CWsWuEmailHelper emailHelper(request.emailFrom.str(), request.emailTo.str(), request.emailServer.str(), request.port); + CWsWuEmailHelper emailHelper(request.emailFrom.str(), request.emailTo.str(), request.emailServer.str(), request.port, true); StringBuffer subject(request.emailSubject.str()); if (subject.isEmpty()) @@ -4928,10 +4928,10 @@ void CWsWuFileHelper::readLocalFileToBuffer(const char* file, offset_t sizeLimit void CWsWuEmailHelper::send(const char* body, const void* attachment, size32_t lenAttachment, StringArray& warnings) { if (lenAttachment == 0) - sendEmail(to.get(), subject.get(), body, mailServer.get(), port, sender.get(), &warnings); + sendEmail(to.get(), subject.get(), body, mailServer.get(), port, sender.get(), &warnings, termOnJobFail); else sendEmailAttachData(to.get(), subject.get(), body, lenAttachment, attachment, mimeType.get(), - attachmentName.get(), mailServer.get(), port, sender.get(), &warnings); + attachmentName.get(), mailServer.get(), port, sender.get(), &warnings, termOnJobFail); } } diff --git a/esp/services/ws_workunits/ws_workunitsHelpers.hpp b/esp/services/ws_workunits/ws_workunitsHelpers.hpp index d43f0849601..cd5fc99d1f2 100644 --- a/esp/services/ws_workunits/ws_workunitsHelpers.hpp +++ b/esp/services/ws_workunits/ws_workunitsHelpers.hpp @@ -708,9 +708,10 @@ class CWsWuEmailHelper StringAttr mailServer, sender, to, subject, body; StringAttr attachmentName, mimeType; unsigned port; + bool termOnJobFail; public: - CWsWuEmailHelper(const char *_sender, const char *_to, const char *_mailServer, unsigned _port) - : sender(_sender), to(_to), mailServer(_mailServer), port(_port) {}; + CWsWuEmailHelper(const char *_sender, const char *_to, const char *_mailServer, unsigned _port, bool _termOnJobFail) + : sender(_sender), to(_to), mailServer(_mailServer), port(_port), termOnJobFail(_termOnJobFail) {}; void setSubject(const char *_subject) { subject.set(_subject); }; void setMimeType(const char *_mimeType) { mimeType.set(_mimeType); }; diff --git a/plugins/fileservices/fileservices.cpp b/plugins/fileservices/fileservices.cpp index 058a1638673..e7ae50bd641 100644 --- a/plugins/fileservices/fileservices.cpp +++ b/plugins/fileservices/fileservices.cpp @@ -523,43 +523,64 @@ FILESERVICES_API void FILESERVICES_CALL fsRenameLogicalFile_v2(ICodeContext *ctx } -FILESERVICES_API void FILESERVICES_CALL fsSendEmail_v2(ICodeContext * ctx, const char * to, const char * subject, const char * body, const char * mailServer, unsigned port, const char * sender, const char *cc, const char *bcc, bool highPriority) +FILESERVICES_API void FILESERVICES_CALL fsSendEmail_v3(ICodeContext * ctx, const char * to, const char * subject, const char * body, const char * mailServer, unsigned port, const char * sender, const char *cc, const char *bcc, bool highPriority, bool termJobOnFail) { StringArray warnings; - sendEmail( to, cc, bcc, subject, body, mailServer, port, sender, &warnings, highPriority); + sendEmail( to, cc, bcc, subject, body, mailServer, port, sender, &warnings, highPriority, termJobOnFail); ForEachItemIn(i,warnings) WUmessage(ctx, SeverityWarning, "SendEmail", warnings.item(i)); } +FILESERVICES_API void FILESERVICES_CALL fsSendEmail_v2(ICodeContext * ctx, const char * to, const char * subject, const char * body, const char * mailServer, unsigned port, const char * sender, const char *cc, const char *bcc, bool highPriority) +{ + fsSendEmail_v3(ctx, to, subject, body, mailServer, port, sender, cc, bcc, highPriority, true); +} + FILESERVICES_API void FILESERVICES_CALL fsSendEmail(ICodeContext * ctx, const char * to, const char * subject, const char * body, const char * mailServer, unsigned port, const char * sender) { - fsSendEmail_v2(ctx, to, subject, body, mailServer, port, sender, nullptr, nullptr, false); + fsSendEmail_v3(ctx, to, subject, body, mailServer, port, sender, nullptr, nullptr, false, true); +} + +FILESERVICES_API void FILESERVICES_CALL fsSendEmailAttachText_v3(ICodeContext * ctx, const char * to, const char * subject, const char * body, const char * attachment, const char * mimeType, const char * attachmentName, const char * mailServer, unsigned int port, const char * sender, const char *cc, const char *bcc, bool highPriority, bool termJobOnFail) +{ + StringArray warnings; + sendEmailAttachText(to, cc, bcc, subject, body, attachment, mimeType, attachmentName, mailServer, port, sender, &warnings, highPriority, termJobOnFail); + ForEachItemIn(i,warnings) + WUmessage(ctx, SeverityWarning, "SendEmailAttachText", warnings.item(i)); } FILESERVICES_API void FILESERVICES_CALL fsSendEmailAttachText_v2(ICodeContext * ctx, const char * to, const char * subject, const char * body, const char * attachment, const char * mimeType, const char * attachmentName, const char * mailServer, unsigned int port, const char * sender, const char *cc, const char *bcc, bool highPriority) { StringArray warnings; - sendEmailAttachText(to, cc, bcc, subject, body, attachment, mimeType, attachmentName, mailServer, port, sender, &warnings, highPriority); + sendEmailAttachText(to, cc, bcc, subject, body, attachment, mimeType, attachmentName, mailServer, port, sender, &warnings, highPriority, true); ForEachItemIn(i,warnings) WUmessage(ctx, SeverityWarning, "SendEmailAttachText", warnings.item(i)); } FILESERVICES_API void FILESERVICES_CALL fsSendEmailAttachText(ICodeContext * ctx, const char * to, const char * subject, const char * body, const char * attachment, const char * mimeType, const char * attachmentName, const char * mailServer, unsigned int port, const char * sender) { - fsSendEmailAttachText_v2(ctx, to, subject, body, attachment, mimeType, attachmentName, mailServer, port, sender, nullptr, nullptr, false); + fsSendEmailAttachText_v3(ctx, to, subject, body, attachment, mimeType, attachmentName, mailServer, port, sender, nullptr, nullptr, false, true); +} + +FILESERVICES_API void FILESERVICES_CALL fsSendEmailAttachData_v3(ICodeContext * ctx, const char * to, const char * subject, const char * body, size32_t lenAttachment, const void * attachment, const char * mimeType, const char * attachmentName, const char * mailServer, unsigned int port, const char * sender, const char *cc, const char *bcc, bool highPriority, bool termJobOnFail) +{ + StringArray warnings; + sendEmailAttachData(to, cc, bcc, subject, body, lenAttachment, attachment, mimeType, attachmentName, mailServer, port, sender, &warnings, highPriority, termJobOnFail); + ForEachItemIn(i,warnings) + WUmessage(ctx, SeverityWarning, "SendEmailAttachData", warnings.item(i)); } FILESERVICES_API void FILESERVICES_CALL fsSendEmailAttachData_v2(ICodeContext * ctx, const char * to, const char * subject, const char * body, size32_t lenAttachment, const void * attachment, const char * mimeType, const char * attachmentName, const char * mailServer, unsigned int port, const char * sender, const char *cc, const char *bcc, bool highPriority) { StringArray warnings; - sendEmailAttachData(to, cc, bcc, subject, body, lenAttachment, attachment, mimeType, attachmentName, mailServer, port, sender, &warnings, highPriority); + sendEmailAttachData(to, cc, bcc, subject, body, lenAttachment, attachment, mimeType, attachmentName, mailServer, port, sender, &warnings, highPriority, true); ForEachItemIn(i,warnings) WUmessage(ctx, SeverityWarning, "SendEmailAttachData", warnings.item(i)); } FILESERVICES_API void FILESERVICES_CALL fsSendEmailAttachData(ICodeContext * ctx, const char * to, const char * subject, const char * body, size32_t lenAttachment, const void * attachment, const char * mimeType, const char * attachmentName, const char * mailServer, unsigned int port, const char * sender) { - fsSendEmailAttachData_v2(ctx, to, subject, body, lenAttachment, attachment, mimeType, attachmentName, mailServer, port, sender, nullptr, nullptr, false); + fsSendEmailAttachData_v3(ctx, to, subject, body, lenAttachment, attachment, mimeType, attachmentName, mailServer, port, sender, nullptr, nullptr, false, true); } diff --git a/plugins/fileservices/fileservices.hpp b/plugins/fileservices/fileservices.hpp index a8d5b762f61..a34fc86ab7f 100644 --- a/plugins/fileservices/fileservices.hpp +++ b/plugins/fileservices/fileservices.hpp @@ -46,10 +46,13 @@ FILESERVICES_API bool FILESERVICES_CALL fsFileValidate(ICodeContext *ctx, const FILESERVICES_API void FILESERVICES_CALL fsSetReadOnly(ICodeContext *ctx, const char *name, bool ro); FILESERVICES_API void FILESERVICES_CALL fsRenameLogicalFile(ICodeContext *ctx, const char *oldname, const char *newname); FILESERVICES_API void FILESERVICES_CALL fsRenameLogicalFile_v2(ICodeContext *ctx, const char *oldname, const char *newname, bool overwrite=false); +FILESERVICES_API void FILESERVICES_CALL fsSendEmail_v3(ICodeContext * ctx, const char *to, const char * subject, const char * body, const char * mailServer, unsigned port, const char * sender, const char *cc, const char *bcc, bool highPriority, bool termJobOnFail); FILESERVICES_API void FILESERVICES_CALL fsSendEmail_v2(ICodeContext * ctx, const char *to, const char * subject, const char * body, const char * mailServer, unsigned port, const char * sender, const char *cc, const char *bcc, bool highPriority); FILESERVICES_API void FILESERVICES_CALL fsSendEmail(ICodeContext * ctx, const char *to, const char * subject, const char * body, const char * mailServer, unsigned port, const char * sender); +FILESERVICES_API void FILESERVICES_CALL fsSendEmailAttachText_v3(ICodeContext * ctx, const char * to, const char * subject, const char * body, const char * attachment, const char * mimeType, const char * attachmentName, const char * mailServer, unsigned int port, const char * sender, const char *cc, const char *bcc, bool highPriority, bool termJobOnFail); FILESERVICES_API void FILESERVICES_CALL fsSendEmailAttachText_v2(ICodeContext * ctx, const char * to, const char * subject, const char * body, const char * attachment, const char * mimeType, const char * attachmentName, const char * mailServer, unsigned int port, const char * sender, const char *cc, const char *bcc, bool highPriority); FILESERVICES_API void FILESERVICES_CALL fsSendEmailAttachText(ICodeContext * ctx, const char * to, const char * subject, const char * body, const char * attachment, const char * mimeType, const char * attachmentName, const char * mailServer, unsigned int port, const char * sender); +FILESERVICES_API void FILESERVICES_CALL fsSendEmailAttachData_v3(ICodeContext * ctx, const char * to, const char * subject, const char * body, size32_t lenAttachment, const void * attachment, const char * mimeType, const char * attachmentName, const char * mailServer, unsigned int port, const char * sender, const char *cc, const char *bcc, bool highPriority, bool termJobOnFail); FILESERVICES_API void FILESERVICES_CALL fsSendEmailAttachData_v2(ICodeContext * ctx, const char * to, const char * subject, const char * body, size32_t lenAttachment, const void * attachment, const char * mimeType, const char * attachmentName, const char * mailServer, unsigned int port, const char * sender, const char *cc, const char *bcc, bool highPriority); FILESERVICES_API void FILESERVICES_CALL fsSendEmailAttachData(ICodeContext * ctx, const char * to, const char * subject, const char * body, size32_t lenAttachment, const void * attachment, const char * mimeType, const char * attachmentName, const char * mailServer, unsigned int port, const char * sender); FILESERVICES_API void FILESERVICES_CALL fsSprayFixed(ICodeContext *ctx, const char * sourceIP, const char * sourcePath, int recordSize, const char * destinationGroup, const char * destinationLogicalName, int timeOut, const char * espServerIpPort, int maxConnections, bool overwrite=false, bool replicate=false, bool compress=false, bool failIfNoSourceFile=false); diff --git a/plugins/proxies/lib_fileservices.ecllib b/plugins/proxies/lib_fileservices.ecllib index d1ea58e7276..a63d05e8431 100644 --- a/plugins/proxies/lib_fileservices.ecllib +++ b/plugins/proxies/lib_fileservices.ecllib @@ -36,9 +36,9 @@ export FileServices := SERVICE : plugin('fileservices'), time SetReadOnly(const varstring lfn, boolean ro) : c,action,context,entrypoint='fsSetReadOnly'; RenameLogicalFile(const varstring oldname, const varstring newname, boolean allowoverwrite=false) : c,action,context,entrypoint='fsRenameLogicalFile_v2'; varstring GetBuildInfo() : c,pure,entrypoint='fsGetBuildInfo'; - SendEmail(const varstring to, const varstring subject, const varstring body, const varstring mailServer=GETENV('SMTPserver'), unsigned4 port=(unsigned4) GETENV('SMTPport', '25'), const varstring sender=GETENV('emailSenderAddress'), const varstring cc='', const varstring bcc='', boolean highPriority=false) : c,action,context,entrypoint='fsSendEmail_v2'; - SendEmailAttachText(const varstring to, const varstring subject, const varstring body, const varstring attachment, const varstring mimeType, const varstring attachmentName, const varstring mailServer=GETENV('SMTPserver'), unsigned4 port=(unsigned4) GETENV('SMTPport', '25'), const varstring sender=GETENV('emailSenderAddress'), const varstring cc='', const varstring bcc='', boolean highPriority=false) : c,action,context,entrypoint='fsSendEmailAttachText_v2'; - SendEmailAttachData(const varstring to, const varstring subject, const varstring body, const data attachment, const varstring mimeType, const varstring attachmentName, const varstring mailServer=GETENV('SMTPserver'), unsigned4 port=(unsigned4) GETENV('SMTPport', '25'), const varstring sender=GETENV('emailSenderAddress'), const varstring cc='', const varstring bcc='', boolean highPriority=false) : c,action,context,entrypoint='fsSendEmailAttachData_v2'; + SendEmail(const varstring to, const varstring subject, const varstring body, const varstring mailServer=GETENV('SMTPserver'), unsigned4 port=(unsigned4) GETENV('SMTPport', '25'), const varstring sender=GETENV('emailSenderAddress'), const varstring cc='', const varstring bcc='', boolean highPriority=false, boolean termJobOnFail=true) : c,action,context,entrypoint='fsSendEmail_v3'; + SendEmailAttachText(const varstring to, const varstring subject, const varstring body, const varstring attachment, const varstring mimeType, const varstring attachmentName, const varstring mailServer=GETENV('SMTPserver'), unsigned4 port=(unsigned4) GETENV('SMTPport', '25'), const varstring sender=GETENV('emailSenderAddress'), const varstring cc='', const varstring bcc='', boolean highPriority=false, boolean termJobOnFail=true) : c,action,context,entrypoint='fsSendEmailAttachText_v3'; + SendEmailAttachData(const varstring to, const varstring subject, const varstring body, const data attachment, const varstring mimeType, const varstring attachmentName, const varstring mailServer=GETENV('SMTPserver'), unsigned4 port=(unsigned4) GETENV('SMTPport', '25'), const varstring sender=GETENV('emailSenderAddress'), const varstring cc='', const varstring bcc='', boolean highPriority=false, boolean termJobOnFail=true) : c,action,context,entrypoint='fsSendEmailAttachData_v3'; SprayFixed(const varstring sourceIP='', const varstring sourcePath, integer4 recordSize, const varstring destinationGroup, const varstring destinationLogicalName, integer4 timeOut=-1, const varstring espServerIpPort=GETENV('ws_fs_server'), integer4 maxConnections=-1, boolean allowoverwrite=false, boolean replicate=false,boolean compress=false, boolean failIfNoSourceFile=false, integer4 expireDays=-1, const varstring dfuServerQueue='', boolean noSplit=false, const varstring sourcePlane='', unsigned4 destinationNumParts=0, boolean noCommon=true) : c,action,context,entrypoint='fsSprayFixed_v6'; SprayVariable(const varstring sourceIP='', const varstring sourcePath, integer4 sourceMaxRecordSize=8192, const varstring sourceCsvSeparate='\\,', const varstring sourceCsvTerminate='\\n,\\r\\n', const varstring sourceCsvQuote='\"', const varstring destinationGroup, const varstring destinationLogicalName, integer4 timeOut=-1, const varstring espServerIpPort=GETENV('ws_fs_server'), integer4 maxConnections=-1, boolean allowoverwrite=false, boolean replicate=false,boolean compress=false,const varstring sourceCsvEscape='', boolean failIfNoSourceFile=false, boolean recordStructurePresent=false, boolean quotedTerminator=true, const varstring encoding='ascii', integer4 expireDays=-1, const varstring dfuServerQueue='', boolean noSplit=false, const varstring sourcePlane='', unsigned4 destinationNumParts=0, boolean noCommon=true) : c,action,context,entrypoint='fsSprayVariable_v10'; SprayXml(const varstring sourceIP='', const varstring sourcePath, integer4 sourceMaxRecordSize=8192, const varstring sourceRowTag, const varstring sourceEncoding='utf8', const varstring destinationGroup, const varstring destinationLogicalName, integer4 timeOut=-1, const varstring espServerIpPort=GETENV('ws_fs_server'), integer4 maxConnections=-1, boolean allowoverwrite=false, boolean replicate=false,boolean compress=false, boolean failIfNoSourceFile=false, integer4 expireDays=-1, const varstring dfuServerQueue='', boolean noSplit=false, const varstring sourcePlane='', unsigned4 destinationNumParts=0, boolean noCommon=true) : c,action,context,entrypoint='fsSprayXml_v6'; diff --git a/tools/swapnode/swapnodelib.cpp b/tools/swapnode/swapnodelib.cpp index f5eb6afc8ec..63e5e4a2af4 100644 --- a/tools/swapnode/swapnodelib.cpp +++ b/tools/swapnode/swapnodelib.cpp @@ -285,7 +285,7 @@ class CSwapNode // add tbd StringBuffer ips; StringArray warnings; - sendEmail(emailtarget.str(),subject,out.str(),ep.getIpText(ips).str(),ep.port,sender.str(),&warnings); + sendEmail(emailtarget.str(),subject,out.str(),ep.getIpText(ips).str(),ep.port,sender.str(),&warnings, false); ForEachItemIn(i,warnings) WARNLOG("SWAPNODE: %s",warnings.item(i)); }