Răsfoiți Sursa

Continuously retry to fetch login credentials

JC Brand 6 ani în urmă
părinte
comite
d868b9a9f7

+ 1 - 0
CHANGES.md

@@ -9,6 +9,7 @@
 - Don't restore a BOSH session without knowing the JID
 - In the `/help` menu, only show allowed commands
 - 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
 - #1532: Converse reloads on enter pressed in the filter box
 

+ 27 - 21
dist/converse.js

@@ -63914,12 +63914,13 @@ async function finishInitialization() {
 }
 
 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();
     xhr.open('GET', _converse.credentials_url, true);
     xhr.setRequestHeader('Accept', "application/json, text/javascript");
 
-    xhr.onload = function () {
+    xhr.onload = () => {
       if (xhr.status >= 200 && xhr.status < 400) {
         const data = JSON.parse(xhr.responseText);
         resolve({
@@ -63927,20 +63928,34 @@ function fetchLoginCredentials() {
           'password': data.password
         });
       } 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() {
@@ -64769,17 +64784,8 @@ _converse.initialize = async function (settings, callback) {
       this.autoLogin(credentials);
     } else if (this.auto_login) {
       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) {
         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 {

+ 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
 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
 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::
 
     {

+ 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();
       xhr.open('GET', _converse.credentials_url, true);
       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();
-   });
+   }, 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);
         } else if (this.auto_login) {
             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) {
                 throw new Error(
                     "attemptNonPreboundSession: If you use auto_login, "+

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

@@ -42160,12 +42160,13 @@ async function finishInitialization() {
 }
 
 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();
     xhr.open('GET', _converse.credentials_url, true);
     xhr.setRequestHeader('Accept', "application/json, text/javascript");
 
-    xhr.onload = function () {
+    xhr.onload = () => {
       if (xhr.status >= 200 && xhr.status < 400) {
         const data = JSON.parse(xhr.responseText);
         resolve({
@@ -42173,20 +42174,34 @@ function fetchLoginCredentials() {
           'password': data.password
         });
       } 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() {
@@ -43015,17 +43030,8 @@ _converse.initialize = async function (settings, callback) {
       this.autoLogin(credentials);
     } else if (this.auto_login) {
       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) {
         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 {