Browse Source

Add retry to OAuth token refresh failure

CURA-11406
Erwan MATHIEU 1 year ago
parent
commit
330dfd8be0
2 changed files with 31 additions and 6 deletions
  1. 8 3
      cura/OAuth2/AuthorizationHelpers.py
  2. 23 3
      cura/OAuth2/AuthorizationService.py

+ 8 - 3
cura/OAuth2/AuthorizationHelpers.py

@@ -16,6 +16,7 @@ from UM.TaskManagement.HttpRequestManager import HttpRequestManager  # To downlo
 
 catalog = i18nCatalog("cura")
 TOKEN_TIMESTAMP_FORMAT = "%Y-%m-%d %H:%M:%S"
+REQUEST_TIMEOUT = 5 # Seconds
 
 
 class AuthorizationHelpers:
@@ -52,7 +53,8 @@ class AuthorizationHelpers:
             data = urllib.parse.urlencode(data).encode("UTF-8"),
             headers_dict = headers,
             callback = lambda response: self.parseTokenResponse(response, callback),
-            error_callback = lambda response, _: self.parseTokenResponse(response, callback)
+            error_callback = lambda response, _: self.parseTokenResponse(response, callback),
+            timeout = REQUEST_TIMEOUT
         )
 
     def getAccessTokenUsingRefreshToken(self, refresh_token: str, callback: Callable[[AuthenticationResponse], None]) -> None:
@@ -75,7 +77,9 @@ class AuthorizationHelpers:
             data = urllib.parse.urlencode(data).encode("UTF-8"),
             headers_dict = headers,
             callback = lambda response: self.parseTokenResponse(response, callback),
-            error_callback = lambda response, _: self.parseTokenResponse(response, callback)
+            error_callback = lambda response, _: self.parseTokenResponse(response, callback),
+            urgent = True,
+            timeout = REQUEST_TIMEOUT
         )
 
     def parseTokenResponse(self, token_response: QNetworkReply, callback: Callable[[AuthenticationResponse], None]) -> None:
@@ -120,7 +124,8 @@ class AuthorizationHelpers:
             check_token_url,
             headers_dict = headers,
             callback = lambda reply: self._parseUserProfile(reply, success_callback, failed_callback),
-            error_callback = lambda _, _2: failed_callback() if failed_callback is not None else None
+            error_callback = lambda _, _2: failed_callback() if failed_callback is not None else None,
+            timeout = REQUEST_TIMEOUT
         )
 
     def _parseUserProfile(self, reply: QNetworkReply, success_callback: Optional[Callable[[UserProfile], None]], failed_callback: Optional[Callable[[], None]] = None) -> None:

+ 23 - 3
cura/OAuth2/AuthorizationService.py

@@ -6,13 +6,14 @@ from datetime import datetime, timedelta
 from typing import Callable, Dict, Optional, TYPE_CHECKING, Union
 from urllib.parse import urlencode, quote_plus
 
-from PyQt6.QtCore import QUrl
+from PyQt6.QtCore import QUrl, QTimer
 from PyQt6.QtGui import QDesktopServices
 
 from UM.Logger import Logger
 from UM.Message import Message
 from UM.Signal import Signal
 from UM.i18n import i18nCatalog
+from UM.TaskManagement.HttpRequestManager import HttpRequestManager  # To download log-in tokens.
 from cura.OAuth2.AuthorizationHelpers import AuthorizationHelpers, TOKEN_TIMESTAMP_FORMAT
 from cura.OAuth2.LocalAuthorizationServer import LocalAuthorizationServer
 from cura.OAuth2.Models import AuthenticationResponse, BaseModel
@@ -53,6 +54,12 @@ class AuthorizationService:
 
         self.onAuthStateChanged.connect(self._authChanged)
 
+        self._refresh_token_retries = 0
+        self._refresh_token_retry_timer = QTimer()
+        self._refresh_token_retry_timer.setInterval(1000)
+        self._refresh_token_retry_timer.setSingleShot(True)
+        self._refresh_token_retry_timer.timeout.connect(self.refreshAccessToken)
+
     def _authChanged(self, logged_in):
         if logged_in and self._unable_to_get_data_message is not None:
             self._unable_to_get_data_message.hide()
@@ -163,16 +170,29 @@ class AuthorizationService:
             return
 
         def process_auth_data(response: AuthenticationResponse) -> None:
+            self._currently_refreshing_token = False
+
             if response.success:
+                self._refresh_token_retries = 0
                 self._storeAuthData(response)
+                HttpRequestManager.getInstance().setDelayRequests(False)
                 self.onAuthStateChanged.emit(logged_in = True)
             else:
-                Logger.warning("Failed to get a new access token from the server.")
-                self.onAuthStateChanged.emit(logged_in = False)
+                if self._refresh_token_retries >= 15:
+                    self._refresh_token_retries = 0
+                    Logger.warning("Failed to get a new access token from the server, giving up.")
+                    HttpRequestManager.getInstance().setDelayRequests(False)
+                    self.onAuthStateChanged.emit(logged_in = False)
+                else:
+                    # Retry a bit later, network may be offline right now and will hopefully be back soon
+                    Logger.warning("Failed to get a new access token from the server, retrying later.")
+                    self._refresh_token_retries += 1
+                    self._refresh_token_retry_timer.start()
 
         if self._currently_refreshing_token:
             Logger.debug("Was already busy refreshing token. Do not start a new request.")
             return
+        HttpRequestManager.getInstance().setDelayRequests(True)
         self._currently_refreshing_token = True
         self._auth_helpers.getAccessTokenUsingRefreshToken(self._auth_data.refresh_token, process_auth_data)