From 476998caa8a23835ea0f3e3bbfa1bedac7aeca7f Mon Sep 17 00:00:00 2001
From: "Mark M. Florida" <mflorida@gmail.com>
Date: Wed, 25 May 2016 12:31:08 -0500
Subject: [PATCH] XNAT-4249: '...timed out...' message won't display on login
 page unless user's last session was terminated due to inactivity. Spawner
 changes: for 'href', 'src', and 'action' properties, values starting with */
 will ensure the path starts at the site root; also added 'name' attribute to
 form panels.

---
 .../xnat/spawner/site-admin-elements.yaml     |  4 +-
 src/main/webapp/scripts/xnat/app/timeout.js   | 49 +++++++++++++------
 src/main/webapp/scripts/xnat/spawner.js       | 10 ++--
 src/main/webapp/scripts/xnat/ui/panel.js      |  6 ++-
 .../webapp/xnat-templates/screens/Login.vm    | 15 +++++-
 5 files changed, 60 insertions(+), 24 deletions(-)

diff --git a/src/main/resources/META-INF/xnat/spawner/site-admin-elements.yaml b/src/main/resources/META-INF/xnat/spawner/site-admin-elements.yaml
index 18f06b16..26b041f2 100644
--- a/src/main/resources/META-INF/xnat/spawner/site-admin-elements.yaml
+++ b/src/main/resources/META-INF/xnat/spawner/site-admin-elements.yaml
@@ -1057,7 +1057,7 @@ misc:
                 link:
                     tag: a.link
                     element:
-                        href: ./page/admin/spawner/
+                        href: */page/admin/spawner/
                         target: _blank
                         html: Manage The Spawner
         swagger:
@@ -1067,7 +1067,7 @@ misc:
                 link:
                     tag: a.link
                     element:
-                        href: ./xapi/swagger-ui.html
+                        href: */xapi/swagger-ui.html
                         target: _blank
                         html: Swagger
 development:
diff --git a/src/main/webapp/scripts/xnat/app/timeout.js b/src/main/webapp/scripts/xnat/app/timeout.js
index 4fdd7824..ab3ccb25 100644
--- a/src/main/webapp/scripts/xnat/app/timeout.js
+++ b/src/main/webapp/scripts/xnat/app/timeout.js
@@ -24,6 +24,14 @@ var XNAT = getObject(XNAT);
     XNAT.app.timeout = timeout =
         getObject(XNAT.app.timeout || {});
 
+    function dateString(ms, strip){
+        var str = (new Date(ms)).toString();
+        if (strip !== false) {
+            str = str.replace(/\s+/g,'-');
+        }
+        return str;
+    }
+
     // timeout polling interval
     timeout.interval = 1000;
 
@@ -45,21 +53,23 @@ var XNAT = getObject(XNAT);
 
         var fn = CookieFn.prototype;
 
+        fn.exists = function(name){
+            this.name = name !== undefined ? name : this.name;
+            this.cookieExists = Cookies.get()[this.name] !== undefined;
+            return this.cookieExists;
+        };
+        // go ahead and check if this cookie exists
+        fn.exists();
+
         // reset values after each call
         fn.reset = function(){
-            this.cookieExists = false;
+            //this.cookieExists = false;
             this.name = name !== undefined ? name : this.name;
             this.value = '';
             this.opts = { path: '/' };
             return this;
         };
 
-        fn.exists = function(name){
-            this.name = name;
-            this.cookieExists = !!Cookies.get(this.name);
-            return this.cookieExists;
-        };
-
         fn.set = function(name, value){
             if (value === undefined) {
                 value = name;
@@ -73,8 +83,9 @@ var XNAT = getObject(XNAT);
         };
 
         // 'value' is a default value to set if the cookie doesn't exist
-        fn.get = function(){
-            this.value = Cookies.get()[this.name];
+        fn.get = function(value){
+            value = value !== undefined ? value : '';
+            this.value = this.exists() ? Cookies.get()[this.name] : value;
             return this;
         };
 
@@ -109,9 +120,12 @@ var XNAT = getObject(XNAT);
     // has the session timed out?
     cookie.SESSION_TIMED_OUT = timeoutCookie('SESSION_TIMED_OUT').get();
 
-    // the time, in ms, that the session will end
+    // the time, in ms, that the session will end or has ended
     cookie.SESSION_TIMEOUT_TIME = timeoutCookie('SESSION_TIMEOUT_TIME');
 
+    // the date and time, as a string, that the session will end or has ended
+    // cookie.SESSION_TIMEOUT_STRING = timeoutCookie('SESSION_TIMEOUT_STRING');
+
     // has the user been redirected after timout?
     cookie.SESSION_LOGOUT_REDIRECT = timeoutCookie('SESSION_LOGOUT_REDIRECT').get();
 
@@ -130,10 +144,10 @@ var XNAT = getObject(XNAT);
         var expCookie = cookie.SESSION_EXPIRATION_TIME.get().value;
         if (timeout.expCookie && timeout.expCookie === expCookie) return;
         timeout.expCookie = expCookie; // save it for next time
-        expCookie = expCookie.replace(/"/g, '').split(',');
+        expCookie = (expCookie||'').replace(/"/g, '').split(',');
         //timeout.startTime = +expCookie[0].trim() + 100;
         timeout.startTime = Date.now();
-        timeout.duration = +expCookie[1].trim();
+        timeout.duration = +(expCookie[1]||'').trim();
         timeout.endTime = timeout.startTime + timeout.duration;
         return {
             startTime: timeout.startTime,
@@ -143,8 +157,9 @@ var XNAT = getObject(XNAT);
     };
 
 
-    // set SESSION_TIMEOUT_TIME cookie
+    // set SESSION_TIMEOUT_* cookies on load
     cookie.SESSION_TIMEOUT_TIME.set(timeout.endTime);
+    // cookie.SESSION_TIMEOUT_STRING.set(dateString(timeout.endTime));
 
 
     function parseTimestamp(time) {
@@ -239,15 +254,17 @@ var XNAT = getObject(XNAT);
 
 
         function redirectToLogin() {
+            var NOW = Date.now();
             timeout.redirecting = true;
             if (!window.top.debug) {
                 xmodal.loading.open('#redirecting');
             }
             timeout.dialog.hide();
-            cookie.SESSION_TIMEOUT_TIME.set(Date.now());
             cookie.SESSION_DIALOG_OPEN.set('false');
             cookie.SESSION_DIALOG_CANCELLED.set('false');
             cookie.SESSION_TIMED_OUT.set('true');
+            cookie.SESSION_TIMEOUT_TIME.set(NOW);
+            // cookie.SESSION_TIMEOUT_STRING.set(dateString(NOW));
             cookie.SESSION_LOGOUT_REDIRECT.set('true');
             cookie.SESSION_LAST_PAGE.set(window.location.href);
             timeoutCookie('WARNING_BAR').set('OPEN');
@@ -271,6 +288,10 @@ var XNAT = getObject(XNAT);
             cookie.SESSION_DIALOG_CANCELLED.set('false');
             cookie.SESSION_TIMED_OUT.set('false');
             cookie.SESSION_TIMEOUT_TIME.set(timeout.endTime);
+            // cookie.SESSION_TIMEOUT_STRING.set(dateString(timeout.endTime));
+            if (console && console.log) {
+                console.log('Session ends: ' + dateString(timeout.endTime, false));
+            }
             cookie.SESSION_LOGOUT_REDIRECT.set('false');
             timeout.cancelled = false;
         }
diff --git a/src/main/webapp/scripts/xnat/spawner.js b/src/main/webapp/scripts/xnat/spawner.js
index 4e1968c4..6918f517 100644
--- a/src/main/webapp/scripts/xnat/spawner.js
+++ b/src/main/webapp/scripts/xnat/spawner.js
@@ -34,7 +34,7 @@ var XNAT = getObject(XNAT);
     spawner.notSpawned = [];
 
     function setRoot(url){
-        url = url.replace(/^(\.\/+)/, '/');
+        url = url.replace(/^([*.]\/+)/, '/');
         return XNAT.url.rootUrl(url)
     }
 
@@ -65,7 +65,7 @@ var XNAT = getObject(XNAT);
             kind = prop.kind || prop.type || 'div.spawned';
 
             // make 'href' 'src' and 'action' properties
-            // start at the site root if starting with './'
+            // start at the site root if starting with '*/'
             if (prop.config.href) {
                 prop.config.href = setRoot(prop.config.href)
             }
@@ -78,7 +78,7 @@ var XNAT = getObject(XNAT);
 
             // do a raw spawn() if 'kind' is 'element'
             // or if there's a tag property
-            if (kind === 'element' || prop.tag) {
+            if (kind === 'element' || prop.tag || prop.config.tag) {
                 try {
                     spawnedElement =
                         spawn(prop.tag || prop.config.tag || 'div', prop.config);
@@ -144,8 +144,8 @@ var XNAT = getObject(XNAT);
             if (prop.contains || prop.contents || prop.content || prop.children || prop[prop.kind]) {
                 prop.contents = prop[prop.contains] || prop.contents || prop.content || prop.children || prop[prop.kind];
                 // if there's a 'target' property, put contents in there
-                if (spawnedElement.target) {
-                    $spawnedElement = $(spawnedElement.target);
+                if (spawnedElement.target || spawnedElement.inner) {
+                    $spawnedElement = $(spawnedElement.target || spawnedElement.inner);
                 }
                 else {
                     $spawnedElement = $(spawnedElement.element);
diff --git a/src/main/webapp/scripts/xnat/ui/panel.js b/src/main/webapp/scripts/xnat/ui/panel.js
index 33ef10c7..c79640bb 100644
--- a/src/main/webapp/scripts/xnat/ui/panel.js
+++ b/src/main/webapp/scripts/xnat/ui/panel.js
@@ -95,6 +95,8 @@ var XNAT = getObject(XNAT || {});
         opts = cloneObject(opts);
         opts.element = opts.element || opts.config || {};
 
+        opts.name = opts.name || opts.element.name || opts.id || opts.element.id || randomID('form-', false)
+
         var _target = spawn('div.panel-body', opts.element),
 
             hideFooter = (isDefined(opts.footer) && (opts.footer === false || /^-/.test(opts.footer))),
@@ -109,7 +111,8 @@ var XNAT = getObject(XNAT || {});
                 ['div.clear']
             ],
 
-            _formPanel = spawn('form.xnat-form-panel.panel.panel-default', {
+            _formPanel = spawn('form.validate.xnat-form-panel.panel.panel-default', {
+                name: opts.name,
                 method: opts.method || 'POST',
                 action: opts.action ? XNAT.url.rootUrl(opts.action) : '#!'
             }, [
@@ -790,6 +793,7 @@ var XNAT = getObject(XNAT || {});
     return XNAT.ui.panel = panel;
 
 
+    
     // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
     // STOP EVERYTHING!!!!!
     // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
diff --git a/src/main/webapp/xnat-templates/screens/Login.vm b/src/main/webapp/xnat-templates/screens/Login.vm
index 5dd17f54..55683b74 100644
--- a/src/main/webapp/xnat-templates/screens/Login.vm
+++ b/src/main/webapp/xnat-templates/screens/Login.vm
@@ -136,10 +136,21 @@ $page.setTitle("$siteId - Please Login")
     </div>
 
     <div id="login_box">
+
         #if($data.getMessage())
-            <div class="message" style="border-bottom: 0">
-                <p><strong>Note: </strong><br />$data.getMessage()</p>
+
+            <div id="login-note" class="message" style="display:none;border-bottom:0">
+                <p><strong>Note: </strong><br>$data.getMessage()</p>
             </div>
+
+            <script>
+                (function(){
+                    if ((Cookies.get('SESSION_TIMED_OUT')||'').toString() === 'true') {
+                        $('#login-note').show();
+                    }
+                })()
+            </script>
+
         #end
 
         <form name="form1" method="post" action="$content.getURI("/login")" class="friendlyForm" id="login_form">
-- 
GitLab