This is an automated email from the ASF dual-hosted git repository.

ppawar pushed a commit to branch ATLAS-5062
in repository https://gitbox.apache.org/repos/asf/atlas.git

commit 24651d8527f04904cc86564afc62ef49697f60bc
Author: Prasad Pawar <[email protected]>
AuthorDate: Tue Jul 29 17:44:08 2025 +0530

    ATLAS-5062: UI:Fix for improving logout mechanism in Atlas UI code base.
---
 dashboard/src/utils/Utils.ts                       |  65 +++++++++++++-
 dashboard/src/views/ErrorPage.tsx                  |  45 ++++++++--
 dashboard/src/views/Layout/Header.tsx              |   4 +-
 dashboard/src/views/Layout/Layout.tsx              |   8 +-
 dashboard/src/views/Router.tsx                     |  15 +++-
 dashboardv2/public/css/scss/common.scss            |  41 +++++++++
 dashboardv2/public/img/error-404-icon.png          | Bin 0 -> 2529 bytes
 .../js/templates/common/ErrorView_templ.html       |  36 ++++++++
 dashboardv2/public/js/utils/Messages.js            |   5 ++
 dashboardv2/public/js/utils/UrlLinks.js            |   6 ++
 dashboardv2/public/js/utils/Utils.js               |   5 +-
 dashboardv2/public/js/views/common/ErrorView.js    |  95 +++++++++++++++++++++
 dashboardv2/public/js/views/site/Header.js         |  67 +++++++++++++--
 dashboardv3/public/css/scss/common.scss            |  41 +++++++++
 dashboardv3/public/img/error-404-icon.png          | Bin 0 -> 2529 bytes
 .../public/js/templates/common/ErrorView_tmpl.html |  36 ++++++++
 dashboardv3/public/js/utils/Messages.js            |   5 ++
 dashboardv3/public/js/utils/UrlLinks.js            |   6 ++
 dashboardv3/public/js/utils/Utils.js               |   4 +-
 dashboardv3/public/js/views/common/ErrorView.js    |  95 +++++++++++++++++++++
 dashboardv3/public/js/views/site/Header.js         |  67 +++++++++++++--
 21 files changed, 612 insertions(+), 34 deletions(-)

diff --git a/dashboard/src/utils/Utils.ts b/dashboard/src/utils/Utils.ts
index dec30ec04..ab5bb2ad5 100644
--- a/dashboard/src/utils/Utils.ts
+++ b/dashboard/src/utils/Utils.ts
@@ -23,6 +23,8 @@ import sanitizeHtml from "sanitize-html";
 import { cloneDeep, toArrayifObject, uniq } from "./Helper";
 import { attributeFilter } from "./CommonViewFunction";
 import { Messages } from "./Messages";
+import { fetchApi } from "@api/apiMethods/fetchApi";
+import { NavigateFunction } from "react-router-dom";
 
 interface childrenInterface {
   gType: string;
@@ -797,6 +799,66 @@ const globalSearchParams = {
   dslParams: {}
 };
 
+export const handleLogout = async (
+  checkKnoxSSOVal: string | boolean | undefined,
+  navigate: NavigateFunction,
+  errorCode?:string
+) => {
+  try {
+    let logoutUrl = getBaseUrl(window.location.pathname) + "/logout";
+    await fetchApi(logoutUrl, {
+      headers: {
+        "cache-control": "no-cache"
+      }
+    });
+    if (checkKnoxSSOVal !== undefined || checkKnoxSSOVal !== null) {
+      if (checkKnoxSSOVal?.toString() == "false") {
+         localStorage.setItem("atlas_ui", "v3");
+        window.location.replace("login.jsp");
+        window.localStorage.clear();
+      } else {
+        navigate("/knoxSSOWarning", { state: { errorCode: errorCode || "" } });
+      }
+    } else {
+      localStorage.setItem("atlas_ui", "v3");
+      window.location.replace("login.jsp");
+    }
+  } catch (error) {
+    toast.error(`Error occurred while logout! ${error}`);
+  }
+};
+
+const checkKnoxSSO = async (navigate: NavigateFunction) => {
+  let checkKnoxSSOresp: any = {};
+  let checkssoUrl = getBaseUrl(window.location.pathname) + 
"/api/atlas/admin/checksso";
+  try {
+    checkKnoxSSOresp = await fetchApi(checkssoUrl, {
+      method: "GET",
+      headers: {
+        "cache-control": "no-cache"
+      }
+    });
+    const { data = "" } = checkKnoxSSOresp || {};
+    if (
+      localStorage.getItem("idleTimerLoggedOut") == "true" &&
+      data?.toString() == "true"
+    ) {
+      window.location.replace("index.html?action=timeout");
+    } else if (data?.toString() == "true") {
+      // Pass "checkSSOTrue" to handleLogout
+      handleLogout(data, navigate, "checkSSOTrue");
+    } else {
+      handleLogout(data, navigate);
+    }
+  } catch (error) {
+    const respStatus = checkKnoxSSOresp?.status || "";
+    if (respStatus == "419") {
+      window.location.replace("login.jsp");
+    }
+    console.error(`Error occurred while logout! ${error}`);
+  }
+};
+
 export {
   customSortBy,
   customSortByObjectKeys,
@@ -835,5 +897,6 @@ export {
   setNavigate,
   getNavigate,
   globalSearchParams,
-  globalSearchFilterInitialQuery
+  globalSearchFilterInitialQuery,
+  checkKnoxSSO
 };
diff --git a/dashboard/src/views/ErrorPage.tsx 
b/dashboard/src/views/ErrorPage.tsx
index b17f0cef4..7ce6593d3 100644
--- a/dashboard/src/views/ErrorPage.tsx
+++ b/dashboard/src/views/ErrorPage.tsx
@@ -16,35 +16,54 @@
  */
 
 import { useState, useEffect } from "react";
-import { useNavigate } from "react-router-dom";
 import errorIcon from "/img/error-404-icon.png";
 import { Stack, Typography } from "@mui/material";
 import { CustomButton } from "@components/muiComponents";
+import { useLocation } from "react-router-dom";
+import { useNavigate } from "react-router-dom";
+
 
 export const ErrorPage = (props: { errorCode: string }) => {
   let navigate = useNavigate();
-  const [errorCode, setErrorCode] = useState<string | null>(null);
+  const location = useLocation();
+  const code = location.state?.errorCode || props.errorCode || "404";
+
+  const [errorCode, setErrorCode] = useState<string>("");
   const [errorInfo, setErrorInfo] = useState<any>(null);
 
   useEffect(() => {
-    if (props.errorCode == "checkSSOTrue") {
+    if (code == "checkSSOTrue") {
       setErrorCode("Sign Out Is Not Complete!");
       setErrorInfo(
         <Typography>
-          Authentication to this instance of Ranger is managed externally(for
-          example,Apache Knox). You can still open this instance of Ranger from
+          Authentication to this instance of Atlas is managed externally(for
+          example,Apache Knox). You can still open this instance of Atlas from
           the same web browser without re-authentication.To prevent
-          additionalPage not found (404). access to Ranger,
+          additionalPage not found (404). access to Atlas,
           <strong>close all browser windows and exit the browser</strong>.
         </Typography>
       );
     }
-    if (props.errorCode == "404") {
+    else if (code == "404") {
       setErrorCode("Page not found (404).");
       setErrorInfo("Sorry, this page isn't here or has moved.");
     }
   });
 
+  const handleBackWithReload = () => {
+    localStorage.setItem("doGoBackAfterReload", "true");
+    window.location.reload();
+  };
+
+  useEffect(() => {
+    if (localStorage.getItem("doGoBackAfterReload") === "true") {
+      localStorage.removeItem("doGoBackAfterReload");
+      setTimeout(() => {
+        window.history.back();
+      }, 1000); 
+    }
+  }, []);
+
   return (
     <Stack
       data-id="pageNotFoundPage"
@@ -74,7 +93,7 @@ export const ErrorPage = (props: { errorCode: string }) => {
           </Stack>
         </Stack>
         <Stack direction="row" spacing={2} className="mt-2">
-          {props.errorCode !== "checkSSOTrue" && (
+          {code !== "checkSSOTrue" && (
             <CustomButton
               size="small"
               variant="contained"
@@ -84,6 +103,16 @@ export const ErrorPage = (props: { errorCode: string }) => {
               Return to Dashboard
             </CustomButton>
           )}
+          {code == "checkSSOTrue" && (
+            <CustomButton
+              size="small"
+              variant="contained"
+              color="primary"
+              onClick={handleBackWithReload}
+            >
+              Go Back
+            </CustomButton>
+          )}
         </Stack>
       </Stack>
     </Stack>
diff --git a/dashboard/src/views/Layout/Header.tsx 
b/dashboard/src/views/Layout/Header.tsx
index 11f919cc4..3d52b2054 100644
--- a/dashboard/src/views/Layout/Header.tsx
+++ b/dashboard/src/views/Layout/Header.tsx
@@ -57,6 +57,7 @@ import { globalSessionData } from "@utils/Enum";
 import { downloadSearchResultsFileUrl } from "@api/apiUrlLinks/downloadApiUrl";
 import ChevronLeftIcon from "@mui/icons-material/ChevronLeft";
 import { AntSwitch } from "@utils/Muiutils";
+import { checkKnoxSSO } from "@utils/Utils";
 
 interface Header {
   handleOpenModal: () => void;
@@ -145,8 +146,7 @@ const Header: React.FC<Header> = ({
 
   const handleLogout = () => {
     localStorage.setItem("atlas_ui", "v3");
-    let path = getBaseUrl(window.location.pathname);
-    window.location.href = path + "/logout.html";
+    checkKnoxSSO(navigate);
     handleClose();
   };
 
diff --git a/dashboard/src/views/Layout/Layout.tsx 
b/dashboard/src/views/Layout/Layout.tsx
index 98dcc4e88..0a88f8484 100644
--- a/dashboard/src/views/Layout/Layout.tsx
+++ b/dashboard/src/views/Layout/Layout.tsx
@@ -17,17 +17,18 @@
 
 import { useEffect, useState } from "react";
 import SideBarBody from "../SideBar/SideBarBody";
-import { Navigate, useLocation } from "react-router-dom";
+import { Navigate, useLocation, useNavigate } from "react-router-dom";
 import Statistics from "@views/Statistics/Statistics";
 import CustomModal from "@components/Modal";
 import About from "./About";
 import { useIdleTimer } from "react-idle-timer";
 import { Typography } from "@mui/material";
-import { getBaseUrl } from "@utils/Utils";
+import { checkKnoxSSO } from "@utils/Utils";
 import { useAppSelector } from "@hooks/reducerHook";
 
 const Layout: React.FC = () => {
   const location = useLocation();
+  const navigate = useNavigate();
   const { sessionObj = "" }: any = useAppSelector(
     (state: any) => state.session
   );
@@ -90,8 +91,7 @@ const Layout: React.FC = () => {
 
   const handleLogout = () => {
     localStorage.setItem("atlas_ui", "v3");
-    let path = getBaseUrl(window.location.pathname);
-    window.location.href = path + "/logout.html";
+    checkKnoxSSO(navigate);
     handleCloseSessionModal();
   };
 
diff --git a/dashboard/src/views/Router.tsx b/dashboard/src/views/Router.tsx
index b5ab60683..6df54372a 100644
--- a/dashboard/src/views/Router.tsx
+++ b/dashboard/src/views/Router.tsx
@@ -15,9 +15,10 @@
  * limitations under the License.
  */
 
-import { Routes, Route, HashRouter } from "react-router-dom";
+import { Routes, Route, HashRouter, useLocation } from "react-router-dom";
 import { lazy } from "react";
 import DebugMetrics from "@views/Layout/DebugMetrics";
+import ErrorPage from "./ErrorPage";
 
 const Layout = lazy(() => import("@views/Layout/Layout"));
 const SearchResult = lazy(() => import("@views/SearchResult/SearchResult"));
@@ -50,7 +51,14 @@ const RelationshipDetailsLayout = lazy(
     import("@views/DetailPage/RelationshipDetails/RelationshipDetailsLayout")
 );
 
+const KnoxSSOWarningWrapper = () => {
+  const location = useLocation();
+  const errorCode = location.state?.errorCode || "";
+  return <ErrorPage errorCode={errorCode} />;
+};
+
 const Router = () => {
+
   return (
     <HashRouter>
       <Routes>
@@ -77,6 +85,11 @@ const Router = () => {
             element={<RelationshipDetailsLayout />}
           />
           <Route path="/debugMetrics" element={<DebugMetrics />} />
+
+          <Route
+            path="/knoxSSOWarning"
+            element={<KnoxSSOWarningWrapper />}
+          />
           <Route path="*" element={<DashBoard />} />
         </Route>
       </Routes>
diff --git a/dashboardv2/public/css/scss/common.scss 
b/dashboardv2/public/css/scss/common.scss
index 77b919ec6..71631d074 100644
--- a/dashboardv2/public/css/scss/common.scss
+++ b/dashboardv2/public/css/scss/common.scss
@@ -386,4 +386,45 @@ pre {
 
 .termBox {
     z-index: 1;
+}
+
+.new-error-page {
+  height: calc(100vh - 200px);
+  display: flex;
+  width: 100%;
+  justify-content: center;
+  align-items:center;
+}
+
+.new-error-box {
+  display: table;
+  max-width: 40%;
+  min-width: 450px;
+}
+
+.error-white-bg {
+  background-color: #fff;
+  display: flex;
+  flex-direction:column;
+  gap:1rem;
+}
+
+.new-icon-box,
+.new-description-box {
+  display: table-cell;
+  vertical-align: middle;
+  color: #888;
+}
+
+.new-icon-box {
+  width: 60px;
+  text-align: center;
+}
+
+.m-t-xs{
+  margin-top:5px;
+}
+
+.m-t-md{
+  margin-top:15px;
 }
\ No newline at end of file
diff --git a/dashboardv2/public/img/error-404-icon.png 
b/dashboardv2/public/img/error-404-icon.png
new file mode 100644
index 000000000..9b8f81de3
Binary files /dev/null and b/dashboardv2/public/img/error-404-icon.png differ
diff --git a/dashboardv2/public/js/templates/common/ErrorView_templ.html 
b/dashboardv2/public/js/templates/common/ErrorView_templ.html
new file mode 100644
index 000000000..114c28d20
--- /dev/null
+++ b/dashboardv2/public/js/templates/common/ErrorView_templ.html
@@ -0,0 +1,36 @@
+{{!-- 
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+--}}
+
+<div data-id="pageNotFoundPage" class="new-error-page">
+    <div class="new-error-box">
+        <div class="error-white-bg">
+            <div class="new-icon-box">
+                <img src="img/error-404-icon.png" style="margin-top:5px">
+            </div>
+            <div class="new-description-box">
+                <h4 class="m-t-xs m-b-xs" data-id="msg"></h4>
+                <div data-id="moreInfo"></div>
+            </div>
+             <div class="m-t-md">
+                <a href="javascript:;" class="btn btn-primary btn-sm" 
data-id="goBack">
+                <i class="fa-fw fa fa-long-arrow-left"></i> Go back
+                </a>
+                <a href="#/" class="btn btn-sm" data-id="home">Home</a>
+            </div>
+        </div>
+    </div>
+</div>
\ No newline at end of file
diff --git a/dashboardv2/public/js/utils/Messages.js 
b/dashboardv2/public/js/utils/Messages.js
index d79fb904d..805341dc2 100644
--- a/dashboardv2/public/js/utils/Messages.js
+++ b/dashboardv2/public/js/utils/Messages.js
@@ -56,6 +56,11 @@ define(['require'], function(require) {
         getAbbreviationMsg: function(abbrev, type) {
             var msg = abbrev ? "s were" : " was";
             return msg + this[type];
+        },
+        errorMsg: {
+            signOutIsNotComplete: 'Authentication to this instance of Atlas is 
managed externally(for example,Apache Knox). \
+                                   You can still open this instance of Atlas 
from the same web browser without re-authentication. \
+                                   To prevent additional access to Atlas, 
<b>close all browser windows and exit the browser</b>.'
         }
     };
     return Messages;
diff --git a/dashboardv2/public/js/utils/UrlLinks.js 
b/dashboardv2/public/js/utils/UrlLinks.js
index c6b1af06a..e3e313d5c 100644
--- a/dashboardv2/public/js/utils/UrlLinks.js
+++ b/dashboardv2/public/js/utils/UrlLinks.js
@@ -298,6 +298,12 @@ define(['require', 'utils/Enums', 'utils/Utils', 
'underscore'], function(require
         },
         downloadSearchResultsFileUrl: function(fileName) {
             return this.baseUrlV2 + '/search/download/' + fileName;
+        },
+        checkKnoxSsoApiUrl: function() {
+            return this.baseUrl + '/admin/checksso';
+        },
+        logOutUrl: function() {
+            return UrlLinks.apiBaseUrl + '/logout';
         }
     });
 
diff --git a/dashboardv2/public/js/utils/Utils.js 
b/dashboardv2/public/js/utils/Utils.js
index 04c31d9fc..410963123 100644
--- a/dashboardv2/public/js/utils/Utils.js
+++ b/dashboardv2/public/js/utils/Utils.js
@@ -16,7 +16,7 @@
  * limitations under the License.
  */
 
-define(['require', 'utils/Globals', 'pnotify', 'utils/Messages', 
'utils/Enums', 'moment', 'store', 'modules/Modal', 'DOMPurify', 
'moment-timezone', 'pnotify.buttons', 'pnotify.confirm', 'trumbowyg'], 
function(require, Globals, pnotify, Messages, Enums, moment, store, Modal, 
DOMPurify) {
+define(['App','require', 'utils/Globals', 'pnotify', 'utils/Messages', 
'utils/Enums', 'moment', 'store', 'modules/Modal', 'DOMPurify', 
'moment-timezone', 'pnotify.buttons', 'pnotify.confirm', 'trumbowyg'], 
function(App,require, Globals, pnotify, Messages, Enums, moment, store, Modal, 
DOMPurify) {
     'use strict';
 
     var Utils = {};
@@ -1222,7 +1222,8 @@ define(['require', 'utils/Globals', 'pnotify', 
'utils/Messages', 'utils/Enums',
             }
 
             if (currentConfig.redirectUrl) {
-                window.location.href = currentConfig.redirectUrl;
+                App.rNHeader.currentView.checkKnoxSSO();
+
             }
         };
 
diff --git a/dashboardv2/public/js/views/common/ErrorView.js 
b/dashboardv2/public/js/views/common/ErrorView.js
new file mode 100644
index 000000000..26bc0c27f
--- /dev/null
+++ b/dashboardv2/public/js/views/common/ErrorView.js
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+
+define(function (require) {
+       'use strict';
+
+       var Backbone = require('backbone');
+
+       var ErrorView_tmpl = require('hbs!tmpl/common/ErrorView_tmpl');
+       var Messages = require('utils/Messages');
+
+
+       var ErrorView = Backbone.Marionette.ItemView.extend(
+               /** @lends ErrorView */
+               {
+                       _viewName: ErrorView,
+
+                       template: ErrorView_tmpl,
+
+                       templateHelpers: function () { },
+
+                       /** ui selector cache */
+                       ui: {
+                               'goBackBtn': 'a[data-id="goBack"]',
+                               'home': 'a[data-id="home"]',
+                               'msg': '[data-id="msg"]',
+                               'moreInfo': '[data-id="moreInfo"]',
+                       },
+
+                       /** ui events hash */
+                       events: function () {
+                               var events = {};
+                               //events['change ' + this.ui.input]  = 
'onInputChange';
+                               events['click ' + this.ui.goBackBtn] = 
'goBackClick';
+                               return events;
+                       },
+
+                       /**
+                       * intialize a new ErrorView ItemView 
+                       * @constructs
+                       */
+                       initialize: function (options) {
+                               console.log("initialized a ErrorView ItemView");
+
+                               _.extend(this, _.pick(options, 'status'));
+
+                               this.bindEvents();
+                       },
+
+                       /** all events binding here */
+                       bindEvents: function () {
+                               /*this.listenTo(this.model, "change:foo", 
this.modelChanged, this);*/
+                               
/*this.listenTo(communicator.vent,'someView:someEvent', this.someEventHandler, 
this)'*/
+                       },
+
+                       /** on render callback */
+                       onRender: function () {
+                               var msg = '', moreInfo = '';
+                               var  errorMsg  = Messages.errorMsg;
+                               if (this.status == "checkSSOTrue") {
+                                       msg = 'Sign Out Is Not Complete!'
+                                       moreInfo = 
errorMsg.signOutIsNotComplete;
+                               }
+                               this.ui.msg.html(msg);
+                               this.ui.moreInfo.html(moreInfo);
+                               if (this.status == "checkSSOTrue") {
+                                       this.ui.home.hide();
+                               }
+                       },
+                       goBackClick: function () {
+                               window.location.reload();
+                       },
+
+
+               });
+
+       return ErrorView;
+});
\ No newline at end of file
diff --git a/dashboardv2/public/js/views/site/Header.js 
b/dashboardv2/public/js/views/site/Header.js
index 6108f0fb2..8ba9f58e0 100644
--- a/dashboardv2/public/js/views/site/Header.js
+++ b/dashboardv2/public/js/views/site/Header.js
@@ -16,7 +16,7 @@
  * limitations under the License.
  */
 
-define(['require',
+define(['App','require',
     'hbs!tmpl/site/Header',
     'utils/CommonViewFunction',
     'utils/Globals',
@@ -24,7 +24,7 @@ define(['require',
     'utils/UrlLinks',
     'collection/VDownloadList',
     'jquery-ui'
-], function(require, tmpl, CommonViewFunction, Globals, Utils, UrlLinks, 
VDownloadList) {
+], function(App,require, tmpl, CommonViewFunction, Globals, Utils, UrlLinks, 
VDownloadList) {
     'use strict';
 
     var Header = Marionette.LayoutView.extend({
@@ -72,11 +72,7 @@ define(['require',
                 });
                 $('body').toggleClass("full-screen");
             };
-            events['click ' + this.ui.signOut] = function() {
-                Utils.localStorage.setValue("last_ui_load", "v1");
-                var path = Utils.getBaseUrl(window.location.pathname);
-                window.location = path + "/logout.html";
-            };
+            events['click ' + this.ui.signOut] = 'checkKnoxSSO';
             events["click " + this.ui.reactUISwitch] = function() {
                 var path = Utils.getBaseUrl(window.location.pathname) + 
"/n3/index.html";
                 if (window.location.hash.length > 2) {
@@ -123,6 +119,63 @@ define(['require',
             this.bindEvent();
             this.options = options;
         },
+        onLogout: function(checksso) {
+            var url = UrlLinks.logOutUrl(),
+            that = this;
+            $.ajax({
+                url: url,
+                type : 'GET',
+                headers : {
+                    "cache-control" : "no-cache"
+                },
+                success : function() {
+                    if(!_.isUndefined(checksso) && checksso){
+                        if(checksso == 'false'){
+                            window.location.replace('locallogin');
+                        }else{
+                            that.errorAction();
+                        }
+                    } else {
+                        Utils.localStorage.setValue("atlas_ui", "classic");
+                        window.location.replace('login.jsp');
+                    }
+                }
+            });
+        },
+        errorAction: function() {
+            require(["views/common/ErrorView"], function(ErrorView) {
+                var errorView = new ErrorView({ status: "checkSSOTrue" });
+                App.rNContent.show(errorView);
+            });
+
+        },
+        checkKnoxSSO: function() {
+            var that =this
+            var url = UrlLinks.checkKnoxSsoApiUrl();
+            $.ajax({
+                url : url,
+                type : 'GET',
+                headers : {
+                    "cache-control" : "no-cache"
+                },
+                success : function(resp) {
+                    if (localStorage.getItem('idleTimerLoggedOut') == "true" 
&& resp == "true") {
+                        window.location.replace('index.html?action=timeout');
+                    } else {
+//                        if (Globals.idealTimeoutSeconds > 0 && resp == 
"true") {
+//                            
window.location.replace('index.html?action=timeout');
+//                        } else {
+                            that.onLogout(resp);
+//                        }
+                    }
+                },
+                error : function(jqXHR, textStatus, err ) {
+                    if( jqXHR.status == 419 ){
+                        window.location.replace('login.jsp');
+                    }
+                }
+            });
+        },
         setSearchBoxWidth: function(options) {
             var atlasHeaderWidth = this.$el.find(".atlas-header").width(),
                 minusWidth = (Utils.getUrlState.isDetailPage() || 
Utils.getUrlState.isRelationshipDetailPage() || Utils.getUrlState.isBSDetail()) 
? 360 : 210;
diff --git a/dashboardv3/public/css/scss/common.scss 
b/dashboardv3/public/css/scss/common.scss
index 951c88fe0..ebfb2ea74 100644
--- a/dashboardv3/public/css/scss/common.scss
+++ b/dashboardv3/public/css/scss/common.scss
@@ -385,4 +385,45 @@ pre {
 
 .termBox {
     z-index: 1;
+}
+
+.new-error-page {
+  height: calc(100vh - 200px);
+  display: flex;
+  width: 100%;
+  justify-content: center;
+  align-items:center;
+}
+
+.new-error-box {
+  display: table;
+  max-width: 40%;
+  min-width: 450px;
+}
+
+.error-white-bg {
+  background-color: #fff;
+  display: flex;
+  flex-direction:column;
+  gap:1rem;
+}
+
+.new-icon-box,
+.new-description-box {
+  display: table-cell;
+  vertical-align: middle;
+  color: #888;
+}
+
+.new-icon-box {
+  width: 60px;
+  text-align: center;
+}
+
+.m-t-xs{
+  margin-top:5px;
+}
+
+.m-t-md{
+  margin-top:15px;
 }
\ No newline at end of file
diff --git a/dashboardv3/public/img/error-404-icon.png 
b/dashboardv3/public/img/error-404-icon.png
new file mode 100644
index 000000000..9b8f81de3
Binary files /dev/null and b/dashboardv3/public/img/error-404-icon.png differ
diff --git a/dashboardv3/public/js/templates/common/ErrorView_tmpl.html 
b/dashboardv3/public/js/templates/common/ErrorView_tmpl.html
new file mode 100644
index 000000000..114c28d20
--- /dev/null
+++ b/dashboardv3/public/js/templates/common/ErrorView_tmpl.html
@@ -0,0 +1,36 @@
+{{!-- 
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+--}}
+
+<div data-id="pageNotFoundPage" class="new-error-page">
+    <div class="new-error-box">
+        <div class="error-white-bg">
+            <div class="new-icon-box">
+                <img src="img/error-404-icon.png" style="margin-top:5px">
+            </div>
+            <div class="new-description-box">
+                <h4 class="m-t-xs m-b-xs" data-id="msg"></h4>
+                <div data-id="moreInfo"></div>
+            </div>
+             <div class="m-t-md">
+                <a href="javascript:;" class="btn btn-primary btn-sm" 
data-id="goBack">
+                <i class="fa-fw fa fa-long-arrow-left"></i> Go back
+                </a>
+                <a href="#/" class="btn btn-sm" data-id="home">Home</a>
+            </div>
+        </div>
+    </div>
+</div>
\ No newline at end of file
diff --git a/dashboardv3/public/js/utils/Messages.js 
b/dashboardv3/public/js/utils/Messages.js
index d79fb904d..805341dc2 100644
--- a/dashboardv3/public/js/utils/Messages.js
+++ b/dashboardv3/public/js/utils/Messages.js
@@ -56,6 +56,11 @@ define(['require'], function(require) {
         getAbbreviationMsg: function(abbrev, type) {
             var msg = abbrev ? "s were" : " was";
             return msg + this[type];
+        },
+        errorMsg: {
+            signOutIsNotComplete: 'Authentication to this instance of Atlas is 
managed externally(for example,Apache Knox). \
+                                   You can still open this instance of Atlas 
from the same web browser without re-authentication. \
+                                   To prevent additional access to Atlas, 
<b>close all browser windows and exit the browser</b>.'
         }
     };
     return Messages;
diff --git a/dashboardv3/public/js/utils/UrlLinks.js 
b/dashboardv3/public/js/utils/UrlLinks.js
index 1c05d17be..f2470b7d2 100644
--- a/dashboardv3/public/js/utils/UrlLinks.js
+++ b/dashboardv3/public/js/utils/UrlLinks.js
@@ -293,6 +293,12 @@ define(['require', 'utils/Enums', 'utils/Utils', 
'underscore'], function(require
         },
         downloadSearchResultsFileUrl: function(fileName) {
             return this.baseUrlV2 + '/search/download/' + fileName;
+        },
+        checkKnoxSsoApiUrl: function() {
+            return this.baseUrl+ '/admin/checksso';
+        },
+        logOutUrl: function() {
+            return UrlLinks.apiBaseUrl + '/logout';
         }
     });
 
diff --git a/dashboardv3/public/js/utils/Utils.js 
b/dashboardv3/public/js/utils/Utils.js
index 71953da0b..a2fa5788e 100644
--- a/dashboardv3/public/js/utils/Utils.js
+++ b/dashboardv3/public/js/utils/Utils.js
@@ -16,7 +16,7 @@
  * limitations under the License.
  */
 
-define(['require', 'utils/Globals', 'pnotify', 'utils/Messages', 
'utils/Enums', 'moment', 'store', 'modules/Modal', 'DOMPurify', 
'moment-timezone', 'pnotify.buttons', 'pnotify.confirm', 'trumbowyg'], 
function(require, Globals, pnotify, Messages, Enums, moment, store, Modal, 
DOMPurify) {
+define(['App','require', 'utils/Globals', 'pnotify', 'utils/Messages', 
'utils/Enums', 'moment', 'store', 'modules/Modal', 'DOMPurify', 
'moment-timezone', 'pnotify.buttons', 'pnotify.confirm', 'trumbowyg'], 
function(App,require, Globals, pnotify, Messages, Enums, moment, store, Modal, 
DOMPurify) {
     'use strict';
 
     var Utils = {};
@@ -1235,7 +1235,7 @@ define(['require', 'utils/Globals', 'pnotify', 
'utils/Messages', 'utils/Enums',
             }
 
             if (currentConfig.redirectUrl) {
-                window.location.href = currentConfig.redirectUrl;
+                App.rHeader.currentView.checkKnoxSSO();
             }
         };
 
diff --git a/dashboardv3/public/js/views/common/ErrorView.js 
b/dashboardv3/public/js/views/common/ErrorView.js
new file mode 100644
index 000000000..a0b5620a5
--- /dev/null
+++ b/dashboardv3/public/js/views/common/ErrorView.js
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+
+define(function (require) {
+       'use strict';
+
+       var Backbone = require('backbone');
+
+       var ErrorView_tmpl = require('hbs!tmpl/common/ErrorView_tmpl');
+       var Messages = require('utils/Messages');
+
+
+       var ErrorView = Backbone.Marionette.ItemView.extend(
+               /** @lends ErrorView */
+               {
+                       _viewName: ErrorView,
+
+                       template: ErrorView_tmpl,
+
+                       templateHelpers: function () { },
+
+                       /** ui selector cache */
+                       ui: {
+                               'goBackBtn': 'a[data-id="goBack"]',
+                               'home': 'a[data-id="home"]',
+                               'msg': '[data-id="msg"]',
+                               'moreInfo': '[data-id="moreInfo"]',
+                       },
+
+                       /** ui events hash */
+                       events: function () {
+                               var events = {};
+                               //events['change ' + this.ui.input]  = 
'onInputChange';
+                               events['click ' + this.ui.goBackBtn] = 
'goBackClick';
+                               return events;
+                       },
+
+                       /**
+                       * intialize a new ErrorView ItemView 
+                       * @constructs
+                       */
+                       initialize: function (options) {
+                               console.log("initialized a ErrorView ItemView");
+
+                               _.extend(this, _.pick(options, 'status'));
+
+                               this.bindEvents();
+                       },
+
+                       /** all events binding here */
+                       bindEvents: function () {
+                               /*this.listenTo(this.model, "change:foo", 
this.modelChanged, this);*/
+                               
/*this.listenTo(communicator.vent,'someView:someEvent', this.someEventHandler, 
this)'*/
+                       },
+
+                       /** on render callback */
+                       onRender: function () {
+                               var msg = '', moreInfo = '';
+                               var errorMsg  = Messages.errorMsg;
+                               if (this.status == "checkSSOTrue") {
+                                       msg = 'Sign Out Is Not Complete!'
+                                       moreInfo = 
errorMsg.signOutIsNotComplete;
+                               }
+                               this.ui.msg.html(msg);
+                               this.ui.moreInfo.html(moreInfo);
+                               if (this.status == "checkSSOTrue") {
+                                       this.ui.home.hide();
+                               }
+                       },
+                       goBackClick: function () {
+                               window.location.reload();
+                       },
+
+
+               });
+
+       return ErrorView;
+});
\ No newline at end of file
diff --git a/dashboardv3/public/js/views/site/Header.js 
b/dashboardv3/public/js/views/site/Header.js
index 000be6d02..10888415c 100644
--- a/dashboardv3/public/js/views/site/Header.js
+++ b/dashboardv3/public/js/views/site/Header.js
@@ -16,14 +16,14 @@
  * limitations under the License.
  */
 
-define(['require',
+define(['App','require',
     'hbs!tmpl/site/Header',
     'utils/CommonViewFunction',
     'utils/Globals',
     'utils/Utils',
     'utils/UrlLinks',
     'collection/VDownloadList',
-], function(require, tmpl, CommonViewFunction, Globals, Utils, UrlLinks, 
VDownloadList) {
+], function(App,require, tmpl, CommonViewFunction, Globals, Utils, UrlLinks, 
VDownloadList) {
     'use strict';
 
     var Header = Marionette.LayoutView.extend({
@@ -60,11 +60,7 @@ define(['require',
                 });
                 $('body').toggleClass("full-screen");
             };
-            events['click ' + this.ui.signOut] = function() {
-                Utils.localStorage.setValue("last_ui_load", "v2");
-                var path = Utils.getBaseUrl(window.location.pathname);
-                window.location = path + "/logout.html";
-            };
+            events['click ' + this.ui.signOut] = 'checkKnoxSSO';
             events['click ' + this.ui.administrator] = function() {
                 Utils.setUrl({
                     url: "#!/administrator",
@@ -107,6 +103,63 @@ define(['require',
             _.extend(this, _.pick(options, 'exportVent'));
             this.bindEvent();
             this.options = options;
+        },
+                onLogout: function(checksso) {
+            var url = UrlLinks.logOutUrl(),
+            that = this;
+            $.ajax({
+                url: url,
+                type : 'GET',
+                headers : {
+                    "cache-control" : "no-cache"
+                },
+                success : function() {
+                    if(!_.isUndefined(checksso) && checksso){
+                        if(checksso == 'false'){
+                            window.location.replace('locallogin');
+                        }else{
+                            that.errorAction();
+                        }
+                    } else {
+                        Utils.localStorage.setValue("atlas_ui", "classic");
+                        window.location.replace('login.jsp');
+                    }
+                }
+            });
+        },
+        errorAction: function() {
+            require(["views/common/ErrorView"], function(ErrorView) {
+                var errorView = new ErrorView({ status: "checkSSOTrue" });
+                App.rContent.show(errorView);
+            });
+
+        },
+        checkKnoxSSO: function() {
+            var that =this
+            var url = UrlLinks.checkKnoxSsoApiUrl();
+            $.ajax({
+                url : url,
+                type : 'GET',
+                headers : {
+                    "cache-control" : "no-cache"
+                },
+                success : function(resp) {
+                    if (localStorage.getItem('idleTimerLoggedOut') == "true" 
&& resp == "true") {
+                        window.location.replace('index.html?action=timeout');
+                    } else {
+//                        if (Globals.idealTimeoutSeconds > 0 && resp == 
"true") {
+//                            
window.location.replace('index.html?action=timeout');
+//                        } else {
+                            that.onLogout(resp);
+//                        }
+                    }
+                },
+                error : function(jqXHR, textStatus, err ) {
+                    if( jqXHR.status == 419 ){
+                        window.location.replace('login.jsp');
+                    }
+                }
+            });
         },
         setSearchBoxWidth: function(options) {
             var atlasHeaderWidth = this.$el.find(".atlas-header").width(),


Reply via email to