diff --git a/cura/OAuth2/AuthorizationService.py b/cura/OAuth2/AuthorizationService.py index d0077cb9a6..dd63cf384e 100644 --- a/cura/OAuth2/AuthorizationService.py +++ b/cura/OAuth2/AuthorizationService.py @@ -53,7 +53,7 @@ class AuthorizationService: self.onAuthStateChanged.connect(self._authChanged) - self._secret_storage = SecretStorage() + self._secret_storage = None # type: Optional[SecretStorage] def _authChanged(self, logged_in): if logged_in and self._unable_to_get_data_message is not None: @@ -62,6 +62,7 @@ class AuthorizationService: def initialize(self, preferences: Optional["Preferences"] = None) -> None: if preferences is not None: self._preferences = preferences + self._secret_storage = SecretStorage(preferences) if self._preferences: self._preferences.addPreference(self._settings.AUTH_DATA_PREFERENCE_KEY, "{}") @@ -236,6 +237,7 @@ class AuthorizationService: # Since we stored all the sensitive stuff in the keyring, restore that now. # Don't store the access_token, as it's very long and that (or tried workarounds) causes issues on Windows. preferences_data["refresh_token"] = self._secret_storage["refresh_token"] + preferences_data["access_token"] = self._secret_storage["access_token"] if preferences_data: self._auth_data = AuthenticationResponse(**preferences_data) @@ -267,11 +269,13 @@ class AuthorizationService: # Store all the sensitive stuff in the keyring # Don't store the access_token, as it's very long and that (or tried workarounds) causes issues on Windows. self._secret_storage["refresh_token"] = auth_data.refresh_token + self._secret_storage["access_token"] = auth_data.access_token # And remove that data again so it isn't stored in the preferences. # Keep the access_token, as it's very long and that (or tried workarounds) causes issues on Windows. auth_data.refresh_token = None + auth_data.access_token = None self._preferences.setValue(self._settings.AUTH_DATA_PREFERENCE_KEY, json.dumps(vars(auth_data))) else: diff --git a/cura/OAuth2/SecretStorage.py b/cura/OAuth2/SecretStorage.py index 42f6164be2..c083aa8a0c 100644 --- a/cura/OAuth2/SecretStorage.py +++ b/cura/OAuth2/SecretStorage.py @@ -1,20 +1,47 @@ -import keyring +from typing import Optional + +import keyring # TODO: Add to about as dependency + +from UM.Logger import Logger class SecretStorage: - def __init__(self): - self._stored_secrets = [] + def __init__(self, preferences: Optional["Preferences"] = None): + self._stored_secrets = {} + if preferences: + self._preferences = preferences + keys = self._preferences.getValue("general/keyring") + if keys is not None and keys != '': + self._stored_secrets = set(keys.split(";")) def __delitem__(self, key): if key in self._stored_secrets: - del self._stored_secrets[key] + self._stored_secrets.remove(key) + self._preferences.setValue("general/keyring", ";".join(self._stored_secrets)) keyring.delete_password("cura", key) + else: + # TODO: handle removal of secret from preferences + pass def __setitem__(self, key, value): - self._stored_secrets.append(key) - keyring.set_password("cura", key, value) + try: + keyring.set_password("cura", key, value) + self._stored_secrets.add(key) + self._preferences.setValue(f"general/{key}", None) + self._preferences.setValue("general/keyring", ";".join(self._stored_secrets)) + except: + Logger.logException("w", f"Could not store {key} in keyring.") + self._preferences.setValue(f"general/{key}", value) def __getitem__(self, key): + secret = self._preferences.getValue(f"general/{key}") if key in self._stored_secrets: - return keyring.get_password("cura", key) - return None + try: + secret = keyring.get_password("cura", key) + except: + if secret: + Logger.logException("w", + f"{key} obtained from preferences, consider giving Cura access to the keyring") + if secret is None or secret == 'null': + Logger.logException("w", f"Could not load {key}") + return secret