From 330dfd8be0dc4ea312273df3e73654ca51618242 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Wed, 10 Jan 2024 15:13:42 +0100 Subject: [PATCH 1/3] Add retry to OAuth token refresh failure CURA-11406 --- cura/OAuth2/AuthorizationHelpers.py | 11 ++++++++--- cura/OAuth2/AuthorizationService.py | 26 +++++++++++++++++++++++--- 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/cura/OAuth2/AuthorizationHelpers.py b/cura/OAuth2/AuthorizationHelpers.py index a654ee4bdb..1bc0d545f4 100644 --- a/cura/OAuth2/AuthorizationHelpers.py +++ b/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: diff --git a/cura/OAuth2/AuthorizationService.py b/cura/OAuth2/AuthorizationService.py index 62bf31982a..7a1bfb75f7 100644 --- a/cura/OAuth2/AuthorizationService.py +++ b/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) From 844f9b3ae81faf76387d6b757d475af4a9058b9a Mon Sep 17 00:00:00 2001 From: Paul Kuiper <46715907+pkuiper-ultimaker@users.noreply.github.com> Date: Wed, 14 Feb 2024 14:44:54 +0100 Subject: [PATCH 2/3] Changed max. value warning level z support distance to prevent warnings for AA0.25 nozzle using default profiles. PP-424 --- resources/definitions/fdmprinter.def.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 20a8a698a2..2f63bf5798 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -5135,7 +5135,7 @@ "unit": "mm", "type": "float", "minimum_value": "0", - "maximum_value_warning": "machine_nozzle_size", + "maximum_value_warning": "5*layer_height", "default_value": 0.1, "limit_to_extruder": "support_interface_extruder_nr if support_interface_enable else support_infill_extruder_nr", "enabled": "support_enable or support_meshes_present", From 831af362cb9acb61192f76421c33f884c88b2f2b Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Wed, 14 Feb 2024 15:46:40 +0100 Subject: [PATCH 3/3] Constantify magic values. part of CURA-11406 --- cura/OAuth2/AuthorizationService.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/cura/OAuth2/AuthorizationService.py b/cura/OAuth2/AuthorizationService.py index 1832ff37c2..4e8d28173a 100644 --- a/cura/OAuth2/AuthorizationService.py +++ b/cura/OAuth2/AuthorizationService.py @@ -1,4 +1,4 @@ -# Copyright (c) 2021 Ultimaker B.V. +# Copyright (c) 2024 UltiMaker # Cura is released under the terms of the LGPLv3 or higher. import json @@ -26,6 +26,8 @@ if TYPE_CHECKING: MYCLOUD_LOGOFF_URL = "https://account.ultimaker.com/logoff?utm_source=cura&utm_medium=software&utm_campaign=change-account-before-adding-printers" +REFRESH_TOKEN_MAX_RETRIES = 15 +REFRESH_TOKEN_RETRY_INTERVAL = 1000 class AuthorizationService: """The authorization service is responsible for handling the login flow, storing user credentials and providing @@ -60,7 +62,7 @@ class AuthorizationService: self._refresh_token_retries = 0 self._refresh_token_retry_timer = QTimer() - self._refresh_token_retry_timer.setInterval(1000) + self._refresh_token_retry_timer.setInterval(REFRESH_TOKEN_RETRY_INTERVAL) self._refresh_token_retry_timer.setSingleShot(True) self._refresh_token_retry_timer.timeout.connect(self.refreshAccessToken) @@ -182,7 +184,7 @@ class AuthorizationService: HttpRequestManager.getInstance().setDelayRequests(False) self.onAuthStateChanged.emit(logged_in = True) else: - if self._refresh_token_retries >= 15: + if self._refresh_token_retries >= REFRESH_TOKEN_MAX_RETRIES: self._refresh_token_retries = 0 Logger.warning("Failed to get a new access token from the server, giving up.") HttpRequestManager.getInstance().setDelayRequests(False)