Closes #247: Adapter config changes are now only persisted after clicking Edit
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import abc
|
||||
import copy
|
||||
import hashlib
|
||||
import uuid
|
||||
from dataclasses import dataclass
|
||||
@@ -174,18 +175,47 @@ class ConfigurationStore(dict):
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
self._changed_secrets_store = {}
|
||||
|
||||
def __repr__(self) -> str:
|
||||
values = ", ".join(f"{k}={v!r}" for k, v in sorted(self.items()))
|
||||
return f"ConfigurationStore({values})"
|
||||
|
||||
def clone(self) -> "ConfigurationStore":
|
||||
configuration_store = ConfigurationStore(**copy.deepcopy(self))
|
||||
configuration_store._changed_secrets_store = copy.deepcopy(
|
||||
self._changed_secrets_store
|
||||
)
|
||||
return configuration_store
|
||||
|
||||
def persist_secrets(self):
|
||||
if not keyring_imported or ConfigurationStore.MOCK:
|
||||
return
|
||||
|
||||
for key, secret in self._changed_secrets_store.items():
|
||||
try:
|
||||
password_id = None
|
||||
if password_type_and_id := self.get(key):
|
||||
if cast(List[str], password_type_and_id)[0] == "keyring":
|
||||
password_id = password_type_and_id[1]
|
||||
|
||||
if password_id is None:
|
||||
password_id = str(uuid.uuid4())
|
||||
|
||||
keyring.set_password(KEYRING_APP_NAME, password_id, secret)
|
||||
self[key] = ["keyring", password_id]
|
||||
except Exception:
|
||||
return
|
||||
|
||||
def get_secret(self, key: str) -> Optional[str]:
|
||||
"""
|
||||
Get the secret value in the store with the given key. If the key doesn't exist
|
||||
in the store, return the default. This will retrieve the secret from whatever is
|
||||
configured as the underlying secret storage mechanism so you don't have to deal
|
||||
with secret storage yourself.
|
||||
Get the secret value in the store with the given key. This will retrieve the
|
||||
secret from whatever is configured as the underlying secret storage mechanism so
|
||||
you don't have to deal with secret storage yourself.
|
||||
"""
|
||||
if secret := self._changed_secrets_store.get(key):
|
||||
return secret
|
||||
|
||||
value = self.get(key)
|
||||
if not isinstance(value, list) or len(value) != 2:
|
||||
return None
|
||||
@@ -199,26 +229,11 @@ class ConfigurationStore(dict):
|
||||
def set_secret(self, key: str, value: str = None):
|
||||
"""
|
||||
Set the secret value of the given key in the store. This should be used for
|
||||
things such as passwords or API tokens. This will store the secret in whatever
|
||||
is configured as the underlying secret storage mechanism so you don't have to
|
||||
deal with secret storage yourself.
|
||||
things such as passwords or API tokens. When :class:`persist_secrets` is called,
|
||||
the secrets will be stored in whatever is configured as the underlying secret
|
||||
storage mechanism so you don't have to deal with secret storage yourself.
|
||||
"""
|
||||
if keyring_imported and not ConfigurationStore.MOCK:
|
||||
try:
|
||||
password_id = None
|
||||
if password_type_and_id := self.get(key):
|
||||
if cast(List[str], password_type_and_id)[0] == "keyring":
|
||||
password_id = password_type_and_id[1]
|
||||
|
||||
if password_id is None:
|
||||
password_id = str(uuid.uuid4())
|
||||
|
||||
keyring.set_password(KEYRING_APP_NAME, password_id, value)
|
||||
self[key] = ["keyring", password_id]
|
||||
return
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
self._changed_secrets_store[key] = value
|
||||
self[key] = ["plaintext", value]
|
||||
|
||||
|
||||
|
@@ -594,7 +594,7 @@ class SublimeMusicApp(Gtk.Application):
|
||||
self.show_configure_servers_dialog()
|
||||
|
||||
def on_edit_current_music_provider(self, *args):
|
||||
self.show_configure_servers_dialog(self.app_config.provider)
|
||||
self.show_configure_servers_dialog(self.app_config.provider.clone())
|
||||
|
||||
def on_switch_music_provider(self, _, provider_id: GLib.Variant):
|
||||
if self.app_config.state.playing:
|
||||
@@ -983,7 +983,9 @@ class SublimeMusicApp(Gtk.Application):
|
||||
if result == Gtk.ResponseType.APPLY:
|
||||
assert dialog.provider_config is not None
|
||||
provider_id = dialog.provider_config.id
|
||||
dialog.provider_config.persist_secrets()
|
||||
self.app_config.providers[provider_id] = dialog.provider_config
|
||||
self.app_config.save()
|
||||
|
||||
if provider_id == self.app_config.current_provider_id:
|
||||
# Just update the window.
|
||||
|
@@ -47,6 +47,25 @@ class ProviderConfiguration:
|
||||
if self.caching_adapter_type:
|
||||
self.caching_adapter_type.migrate_configuration(self.caching_adapter_config)
|
||||
|
||||
def clone(self) -> "ProviderConfiguration":
|
||||
return ProviderConfiguration(
|
||||
self.id,
|
||||
self.name,
|
||||
self.ground_truth_adapter_type,
|
||||
self.ground_truth_adapter_config.clone(),
|
||||
self.caching_adapter_type,
|
||||
(
|
||||
self.caching_adapter_config.clone()
|
||||
if self.caching_adapter_config
|
||||
else None
|
||||
),
|
||||
)
|
||||
|
||||
def persist_secrets(self):
|
||||
self.ground_truth_adapter_config.persist_secrets()
|
||||
if self.caching_adapter_config:
|
||||
self.caching_adapter_config.persist_secrets()
|
||||
|
||||
|
||||
def encode_providers(
|
||||
providers_dict: Dict[str, Dict[str, Any]]
|
||||
|
Reference in New Issue
Block a user