Browse Source

Continuously retry to fetch login credentials

JC Brand 6 years ago
parent
commit
d868b9a9f7
5 changed files with 92 additions and 70 deletions
  1. 1 0
      CHANGES.md
  2. 27 21
      dist/converse.js
  3. 4 1
      docs/source/configuration.rst
  4. 33 27
      src/headless/converse-core.js
  5. 27 21
      src/headless/dist/converse-headless.js

+ 1 - 0
CHANGES.md

@@ -9,6 +9,7 @@
 - Don't restore a BOSH session without knowing the JID
 - Don't restore a BOSH session without knowing the JID
 - In the `/help` menu, only show allowed commands
 - In the `/help` menu, only show allowed commands
 - Message deduplication bugfixes and improvements
 - Message deduplication bugfixes and improvements
+- Continuously retry (in 2s intervals) to fetch login credentials (via [credentials_url](https://conversejs.org/docs/html/configuration.html#credentials-url)) in case of failure
 - #1296: `embedded` view mode shows `chatbox-navback` arrow in header
 - #1296: `embedded` view mode shows `chatbox-navback` arrow in header
 - #1532: Converse reloads on enter pressed in the filter box
 - #1532: Converse reloads on enter pressed in the filter box
 
 

+ 27 - 21
dist/converse.js

@@ -63914,12 +63914,13 @@ async function finishInitialization() {
 }
 }
 
 
 function fetchLoginCredentials() {
 function fetchLoginCredentials() {
-  return new es6_promise_dist_es6_promise_auto__WEBPACK_IMPORTED_MODULE_3___default.a((resolve, reject) => {
+  let wait = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
+  return new es6_promise_dist_es6_promise_auto__WEBPACK_IMPORTED_MODULE_3___default.a(_lodash_noconflict__WEBPACK_IMPORTED_MODULE_4___default.a.debounce((resolve, reject) => {
     const xhr = new XMLHttpRequest();
     const xhr = new XMLHttpRequest();
     xhr.open('GET', _converse.credentials_url, true);
     xhr.open('GET', _converse.credentials_url, true);
     xhr.setRequestHeader('Accept', "application/json, text/javascript");
     xhr.setRequestHeader('Accept', "application/json, text/javascript");
 
 
-    xhr.onload = function () {
+    xhr.onload = () => {
       if (xhr.status >= 200 && xhr.status < 400) {
       if (xhr.status >= 200 && xhr.status < 400) {
         const data = JSON.parse(xhr.responseText);
         const data = JSON.parse(xhr.responseText);
         resolve({
         resolve({
@@ -63927,20 +63928,34 @@ function fetchLoginCredentials() {
           'password': data.password
           'password': data.password
         });
         });
       } else {
       } else {
-        xhr.onerror({});
+        reject(new Error(`${xhr.status}: ${xhr.responseText}`));
       }
       }
     };
     };
 
 
-    xhr.onerror = function () {
-      delete _converse.connection;
+    xhr.onerror = reject;
+    xhr.send();
+  }, wait));
+}
 
 
-      _converse.api.trigger('noResumeableSession', this);
+async function getLoginCredentials() {
+  let credentials;
+  let wait = 0;
 
 
-      reject(new Error(xhr.responseText));
-    };
+  while (!credentials) {
+    try {
+      credentials = await fetchLoginCredentials(wait); // eslint-disable-line no-await-in-loop
+    } catch (e) {
+      _converse.log("Could not fetch login credentials", strophe_js__WEBPACK_IMPORTED_MODULE_0__["Strophe"].LogLevel.ERROR);
 
 
-    xhr.send();
-  });
+      _converse.log(e, strophe_js__WEBPACK_IMPORTED_MODULE_0__["Strophe"].LogLevel.ERROR);
+    } // If unsuccessful, we wait 2 seconds between subsequent attempts to
+    // fetch the credentials.
+
+
+    wait = 2000;
+  }
+
+  return credentials;
 }
 }
 
 
 function unregisterGlobalEventHandlers() {
 function unregisterGlobalEventHandlers() {
@@ -64769,17 +64784,8 @@ _converse.initialize = async function (settings, callback) {
       this.autoLogin(credentials);
       this.autoLogin(credentials);
     } else if (this.auto_login) {
     } else if (this.auto_login) {
       if (this.credentials_url) {
       if (this.credentials_url) {
-        let data = {};
-
-        try {
-          data = await fetchLoginCredentials();
-        } catch (e) {
-          _converse.log("Could not fetch login credentials", strophe_js__WEBPACK_IMPORTED_MODULE_0__["Strophe"].LogLevel.ERROR);
-
-          _converse.log(e, strophe_js__WEBPACK_IMPORTED_MODULE_0__["Strophe"].LogLevel.ERROR);
-        } finally {
-          this.autoLogin(data);
-        }
+        const data = await getLoginCredentials();
+        this.autoLogin(data);
       } else if (!this.jid) {
       } else if (!this.jid) {
         throw new Error("attemptNonPreboundSession: If you use auto_login, " + "you also need to give either a jid value (and if " + "applicable a password) or you need to pass in a URL " + "from where the username and password can be fetched " + "(via credentials_url).");
         throw new Error("attemptNonPreboundSession: If you use auto_login, " + "you also need to give either a jid value (and if " + "applicable a password) or you need to pass in a URL " + "from where the username and password can be fetched " + "(via credentials_url).");
       } else {
       } else {

+ 4 - 1
docs/source/configuration.rst

@@ -563,10 +563,13 @@ It allows you to specify a URL which Converse will call when it needs to get
 the username and password (or authentication token) which Converse will use
 the username and password (or authentication token) which Converse will use
 to automatically log the user in.
 to automatically log the user in.
 
 
-If ``auto_reconnect`` is also set to true, then Converse will automatically
+If ``auto_reconnect`` is also set to ``true``, then Converse will automatically
 fetch new credentials from the ``credentials_url`` whenever the connection or
 fetch new credentials from the ``credentials_url`` whenever the connection or
 session drops, and then attempt to reconnect and establish a new session.
 session drops, and then attempt to reconnect and establish a new session.
 
 
+If the request to the ``credentials_url`` URL fails for whatever reason,
+Converse will continuously retry to fetch the credentials every 2 seconds.
+
 The server behind ``credentials_url`` should return a JSON encoded object::
 The server behind ``credentials_url`` should return a JSON encoded object::
 
 
     {
     {

+ 33 - 27
src/headless/converse-core.js

@@ -483,29 +483,42 @@ async function finishInitialization () {
     }
     }
 }
 }
 
 
-function fetchLoginCredentials () {
-   return new Promise((resolve, reject) => {
+function fetchLoginCredentials (wait=0) {
+   return new Promise(_.debounce((resolve, reject) => {
       const xhr = new XMLHttpRequest();
       const xhr = new XMLHttpRequest();
       xhr.open('GET', _converse.credentials_url, true);
       xhr.open('GET', _converse.credentials_url, true);
       xhr.setRequestHeader('Accept', "application/json, text/javascript");
       xhr.setRequestHeader('Accept', "application/json, text/javascript");
-      xhr.onload = function() {
-          if (xhr.status >= 200 && xhr.status < 400) {
-             const data = JSON.parse(xhr.responseText);
-             resolve({
-                'jid': data.jid,
-                'password': data.password
-             });
-          } else {
-             xhr.onerror({});
-          }
-      };
-      xhr.onerror = function () {
-          delete _converse.connection;
-          _converse.api.trigger('noResumeableSession', this);
-          reject(new Error(xhr.responseText));
+      xhr.onload = () => {
+         if (xhr.status >= 200 && xhr.status < 400) {
+            const data = JSON.parse(xhr.responseText);
+            resolve({
+               'jid': data.jid,
+               'password': data.password
+            });
+         } else {
+            reject(new Error(`${xhr.status}: ${xhr.responseText}`));
+         }
       };
       };
+      xhr.onerror = reject;
       xhr.send();
       xhr.send();
-   });
+   }, wait));
+}
+
+async function getLoginCredentials () {
+   let credentials;
+   let wait = 0;
+   while (!credentials) {
+      try {
+         credentials = await fetchLoginCredentials(wait); // eslint-disable-line no-await-in-loop
+      } catch (e) {
+         _converse.log("Could not fetch login credentials", Strophe.LogLevel.ERROR);
+         _converse.log(e, Strophe.LogLevel.ERROR);
+      }
+      // If unsuccessful, we wait 2 seconds between subsequent attempts to
+      // fetch the credentials.
+      wait = 2000;
+   }
+   return credentials;
 }
 }
 
 
 
 
@@ -1244,15 +1257,8 @@ _converse.initialize = async function (settings, callback) {
             this.autoLogin(credentials);
             this.autoLogin(credentials);
         } else if (this.auto_login) {
         } else if (this.auto_login) {
             if (this.credentials_url) {
             if (this.credentials_url) {
-                let data = {};
-                try {
-                    data = await fetchLoginCredentials();
-                } catch (e) {
-                   _converse.log("Could not fetch login credentials", Strophe.LogLevel.ERROR);
-                   _converse.log(e, Strophe.LogLevel.ERROR);
-                } finally {
-                   this.autoLogin(data);
-                }
+                const data = await getLoginCredentials();
+                this.autoLogin(data);
             } else if (!this.jid) {
             } else if (!this.jid) {
                 throw new Error(
                 throw new Error(
                     "attemptNonPreboundSession: If you use auto_login, "+
                     "attemptNonPreboundSession: If you use auto_login, "+

+ 27 - 21
src/headless/dist/converse-headless.js

@@ -42160,12 +42160,13 @@ async function finishInitialization() {
 }
 }
 
 
 function fetchLoginCredentials() {
 function fetchLoginCredentials() {
-  return new es6_promise_dist_es6_promise_auto__WEBPACK_IMPORTED_MODULE_3___default.a((resolve, reject) => {
+  let wait = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
+  return new es6_promise_dist_es6_promise_auto__WEBPACK_IMPORTED_MODULE_3___default.a(_lodash_noconflict__WEBPACK_IMPORTED_MODULE_4___default.a.debounce((resolve, reject) => {
     const xhr = new XMLHttpRequest();
     const xhr = new XMLHttpRequest();
     xhr.open('GET', _converse.credentials_url, true);
     xhr.open('GET', _converse.credentials_url, true);
     xhr.setRequestHeader('Accept', "application/json, text/javascript");
     xhr.setRequestHeader('Accept', "application/json, text/javascript");
 
 
-    xhr.onload = function () {
+    xhr.onload = () => {
       if (xhr.status >= 200 && xhr.status < 400) {
       if (xhr.status >= 200 && xhr.status < 400) {
         const data = JSON.parse(xhr.responseText);
         const data = JSON.parse(xhr.responseText);
         resolve({
         resolve({
@@ -42173,20 +42174,34 @@ function fetchLoginCredentials() {
           'password': data.password
           'password': data.password
         });
         });
       } else {
       } else {
-        xhr.onerror({});
+        reject(new Error(`${xhr.status}: ${xhr.responseText}`));
       }
       }
     };
     };
 
 
-    xhr.onerror = function () {
-      delete _converse.connection;
+    xhr.onerror = reject;
+    xhr.send();
+  }, wait));
+}
 
 
-      _converse.api.trigger('noResumeableSession', this);
+async function getLoginCredentials() {
+  let credentials;
+  let wait = 0;
 
 
-      reject(new Error(xhr.responseText));
-    };
+  while (!credentials) {
+    try {
+      credentials = await fetchLoginCredentials(wait); // eslint-disable-line no-await-in-loop
+    } catch (e) {
+      _converse.log("Could not fetch login credentials", strophe_js__WEBPACK_IMPORTED_MODULE_0__["Strophe"].LogLevel.ERROR);
 
 
-    xhr.send();
-  });
+      _converse.log(e, strophe_js__WEBPACK_IMPORTED_MODULE_0__["Strophe"].LogLevel.ERROR);
+    } // If unsuccessful, we wait 2 seconds between subsequent attempts to
+    // fetch the credentials.
+
+
+    wait = 2000;
+  }
+
+  return credentials;
 }
 }
 
 
 function unregisterGlobalEventHandlers() {
 function unregisterGlobalEventHandlers() {
@@ -43015,17 +43030,8 @@ _converse.initialize = async function (settings, callback) {
       this.autoLogin(credentials);
       this.autoLogin(credentials);
     } else if (this.auto_login) {
     } else if (this.auto_login) {
       if (this.credentials_url) {
       if (this.credentials_url) {
-        let data = {};
-
-        try {
-          data = await fetchLoginCredentials();
-        } catch (e) {
-          _converse.log("Could not fetch login credentials", strophe_js__WEBPACK_IMPORTED_MODULE_0__["Strophe"].LogLevel.ERROR);
-
-          _converse.log(e, strophe_js__WEBPACK_IMPORTED_MODULE_0__["Strophe"].LogLevel.ERROR);
-        } finally {
-          this.autoLogin(data);
-        }
+        const data = await getLoginCredentials();
+        this.autoLogin(data);
       } else if (!this.jid) {
       } else if (!this.jid) {
         throw new Error("attemptNonPreboundSession: If you use auto_login, " + "you also need to give either a jid value (and if " + "applicable a password) or you need to pass in a URL " + "from where the username and password can be fetched " + "(via credentials_url).");
         throw new Error("attemptNonPreboundSession: If you use auto_login, " + "you also need to give either a jid value (and if " + "applicable a password) or you need to pass in a URL " + "from where the username and password can be fetched " + "(via credentials_url).");
       } else {
       } else {