Skip to content

Commit f731f39

Browse files
author
k9ert
authored
Chore: Removing the Singleton (#1914)
1 parent 08b63f8 commit f731f39

File tree

10 files changed

+122
-104
lines changed

10 files changed

+122
-104
lines changed

src/cryptoadvance/specter/managers/node_manager.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ def update(self, data_folder=None):
5353
for node_alias in nodes_files:
5454
fullpath = os.path.join(self.data_folder, "%s.json" % node_alias)
5555
node_class = (
56-
Node if nodes_files[node_alias]["external_node"] else InternalNode
56+
Node if nodes_files[node_alias].get("external_node") else InternalNode
5757
)
5858
nodes[nodes_files[node_alias]["name"]] = node_class.from_json(
5959
nodes_files[node_alias],

src/cryptoadvance/specter/managers/service_manager.py

Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010

1111
from cryptoadvance.specter.config import ProductionConfig
1212
from cryptoadvance.specter.device import Device
13-
from cryptoadvance.specter.managers.singleton import ConfigurableSingletonException
1413
from cryptoadvance.specter.specter_error import SpecterError
1514
from cryptoadvance.specter.user import User
1615
from cryptoadvance.specter.util.reflection import get_template_static_folder
@@ -20,10 +19,6 @@
2019

2120
from ..services.service import Service
2221
from ..services import callbacks, ExtensionException
23-
from ..services.service_encrypted_storage import (
24-
ServiceEncryptedStorageManager,
25-
ServiceUnencryptedStorageManager,
26-
)
2722
from ..util.reflection import (
2823
_get_module_from_class,
2924
get_classlist_of_type_clazz_from_modulelist,
@@ -84,20 +79,6 @@ def __init__(self, specter, devstatus_threshold):
8479
logger.info(
8580
f"Service {clazz.__name__} not activated due to devstatus ( {self.devstatus_threshold} > {clazz.devstatus} )"
8681
)
87-
88-
# Configure and instantiate the one and only ServiceEncryptedStorageManager
89-
try:
90-
ServiceEncryptedStorageManager.configure_instance(
91-
specter.data_folder, specter.user_manager
92-
)
93-
except ConfigurableSingletonException as e:
94-
# Test suite triggers multiple calls; ignore for now.
95-
pass
96-
97-
specter.service_unencrypted_storage_manager = ServiceUnencryptedStorageManager(
98-
specter.user_manager, specter.data_folder
99-
)
100-
10182
logger.info("----> finished service processing")
10283
self.execute_ext_callbacks("afterServiceManagerInit")
10384

@@ -328,9 +309,8 @@ def user_has_encrypted_storage(self, user: User) -> bool:
328309
This check works even if the user doesn't have their plaintext_user_secret
329310
available."""
330311
encrypted_data = (
331-
ServiceEncryptedStorageManager.get_instance().get_raw_encrypted_data(user)
312+
self.specter.service_encrypted_storage_manager.get_raw_encrypted_data(user)
332313
)
333-
print(f"encrypted_data: {encrypted_data} for {user}")
334314
return encrypted_data != {}
335315

336316
def set_active_services(self, service_names_active):
@@ -363,7 +343,7 @@ def remove_all_services_from_user(self, user: User):
363343
if self.user_has_encrypted_storage(user=user):
364344
# Encrypted Service data is now orphaned since there is no
365345
# password. So wipe it from the disk.
366-
ServiceEncryptedStorageManager.get_instance().delete_all_service_data(user)
346+
app.specter.service_encrypted_storage_manager.delete_all_service_data(user)
367347

368348
@classmethod
369349
def get_service_x_dirs(cls, x):

src/cryptoadvance/specter/managers/singleton.py

Lines changed: 0 additions & 40 deletions
This file was deleted.

src/cryptoadvance/specter/services/service.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,20 +54,20 @@ def callback(self, callback_id, *argv, **kwargv):
5454

5555
@classmethod
5656
def set_current_user_service_data(cls, service_data: dict):
57-
ServiceEncryptedStorageManager.get_instance().set_current_user_service_data(
57+
app.specter.service_encrypted_storage_manager.set_current_user_service_data(
5858
service_id=cls.id, service_data=service_data
5959
)
6060

6161
@classmethod
6262
def update_current_user_service_data(cls, service_data: dict):
63-
ServiceEncryptedStorageManager.get_instance().update_current_user_service_data(
63+
app.specter.service_encrypted_storage_manager.update_current_user_service_data(
6464
service_id=cls.id, service_data=service_data
6565
)
6666

6767
@classmethod
6868
def get_current_user_service_data(cls) -> dict:
6969
return (
70-
ServiceEncryptedStorageManager.get_instance().get_current_user_service_data(
70+
app.specter.service_encrypted_storage_manager.get_current_user_service_data(
7171
service_id=cls.id
7272
)
7373
)

src/cryptoadvance/specter/services/service_encrypted_storage.py

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import os
44

55
from cryptoadvance.specter.managers.genericdata_manager import GenericDataManager
6-
from cryptoadvance.specter.managers.singleton import ConfigurableSingleton
6+
from cryptoadvance.specter.managers.user_manager import UserManager
77
from cryptoadvance.specter.specter_error import SpecterError
88
from cryptoadvance.specter.user import User
99

@@ -110,7 +110,7 @@ def __init__(self, data_folder: str, user: User, disable_decrypt: bool = False):
110110
"ServiceUnencryptedStorage needs to be initialized with disable_decrypt = True"
111111
)
112112
if disable_decrypt:
113-
super().__init__(data_folder, encryption_key=None, disable_decrypt=True)
113+
super().__init__(data_folder, user, disable_decrypt=True)
114114

115115
@property
116116
def data_file(self):
@@ -119,19 +119,15 @@ def data_file(self):
119119
)
120120

121121

122-
class ServiceEncryptedStorageManager(ConfigurableSingleton):
123-
"""Singleton that manages access to users' ServiceApiKeyStorage; context-aware so it
122+
class ServiceEncryptedStorageManager:
123+
"""manages access to users' ServiceApiKeyStorage; context-aware so it
124124
knows who the current_user is for the given request context.
125-
126-
Requires a one-time configuration call on startup in the ServiceManager.
127125
"""
128126

129-
@classmethod
130-
def configure_instance(cls, data_folder, user_manager):
131-
super().configure_instance()
132-
cls._instance.data_folder = data_folder
133-
cls._instance.user_manager = user_manager
134-
cls._instance.storage_by_user = {}
127+
def __init__(self, data_folder, user_manager: UserManager):
128+
self.user_manager = user_manager
129+
self.data_folder = data_folder
130+
self.storage_by_user = {}
135131

136132
def get_raw_encrypted_data(self, user: User) -> dict:
137133
"""Doesn't attempt to decrypt the ServiceEncryptedStorage, just returns the
@@ -184,7 +180,7 @@ def delete_all_service_data(self, user: User):
184180

185181

186182
class ServiceUnencryptedStorageManager(ServiceEncryptedStorageManager):
187-
def __init__(self, user_manager, data_folder):
183+
def __init__(self, data_folder, user_manager: UserManager):
188184
self.user_manager = user_manager
189185
self.data_folder = data_folder
190186
self.storage_by_user = {}

src/cryptoadvance/specter/services/swan/config.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,15 @@
55

66

77
class BaseConfig:
8+
# Unfortunately this setup is currently broken
9+
# It worked for the original and now legacy api-dev.swanbitcoin.com
10+
# But the new one doesn't have that configuration configured.
811
SWAN_CLIENT_ID = "specter-dev"
912
SWAN_CLIENT_SECRET = (
1013
"BcetcVcmueWf5P3UPJnHhCBMQ49p38fhzYwM7t3DJGzsXSjm89dDR5URE46SY69j"
1114
)
12-
SWAN_API_URL = "https://dev-api.swanbitcoin.com"
13-
SWAN_FRONTEND_URL = "https://dev-app.swanbitcoin.com/signup"
15+
SWAN_API_URL = "https://api.dev.swanbitcoin.com"
16+
SWAN_FRONTEND_URL = "https://app.dev.swanbitcoin.com/signup"
1417

1518
# There is a whitelist at the oauth2-infra of swan which is hopefully in sync with this list:
1619
SWAN_ALLOWED_SPECTER_HOSTNAMES = [

src/cryptoadvance/specter/specter.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@
2020
from urllib3.exceptions import NewConnectionError
2121

2222
from cryptoadvance.specter.devices.device_types import DeviceTypes
23+
from cryptoadvance.specter.services.service_encrypted_storage import (
24+
ServiceEncryptedStorageManager,
25+
ServiceUnencryptedStorageManager,
26+
)
2327

2428
from .helpers import clean_psbt, deep_update, is_liquid, is_testnet, get_asset_label
2529
from .internal_node import InternalNode
@@ -140,6 +144,16 @@ def __init__(
140144
if self.price_check and self.price_provider and checker_threads:
141145
self.price_checker.start()
142146

147+
# Configuring the two different storages (Universal json-files)
148+
logger.info("Instantiate ServiceEncryptedStorageManager")
149+
self.service_encrypted_storage_manager = ServiceEncryptedStorageManager(
150+
self.data_folder, self.user_manager
151+
)
152+
logger.info("Instantiate ServiceUnencryptedStorageManager")
153+
self.service_unencrypted_storage_manager = ServiceUnencryptedStorageManager(
154+
self.data_folder, self.user_manager
155+
)
156+
143157
if threading.current_thread() is threading.main_thread():
144158
# Python signal handlers are always executed in the main Python thread and only the main thread is allowed to set a new signal handler.
145159
# This is for CTRL-C --> SIGINT

tests/test_hwibridge.py

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -114,16 +114,15 @@ def test_calling_method_with_non_existing_parameters(client):
114114
"forwarded_request": True,
115115
},
116116
)
117-
assert { # TODO This is a temporary fix that should be handled in https://github.com/cryptoadvance/specter-desktop/pull/1693
118-
"error": {
119-
"code": -32000,
120-
"message": "Internal error: HWIBridge.enumerate() got an unexpected keyword argument 'non_existing_parameter'.",
121-
},
122-
"id": 1,
123-
"jsonrpc": "2.0",
124-
} == json.loads(
125-
req.data
117+
118+
resp = json.loads(req.data)
119+
assert resp["error"]["code"] == -32000
120+
assert resp["error"]["message"].startswith("Internal error:")
121+
assert resp["error"]["message"].endswith(
122+
"got an unexpected keyword argument 'non_existing_parameter'."
126123
)
124+
assert resp["id"] == 1
125+
assert resp["jsonrpc"] == "2.0"
127126

128127

129128
def test_call_not_connected_device(client):

tests/test_managers_service.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ def test_ServiceManager2(mock_specter, mock_flaskapp, caplog):
1515
# We have passed the TestConfig which is (hopefully) not existing in the Swan Extension
1616
# So the ServiceManager will move up the dependency tree of TestConfig until it finds
1717
# a Config and will copy the keys into the flask-config
18-
assert mock_flaskapp.config["SWAN_API_URL"] == "https://dev-api.swanbitcoin.com"
18+
assert mock_flaskapp.config["SWAN_API_URL"] == "https://api.dev.swanbitcoin.com"
1919
assert sm.services["bitcoinreserve"] != None
2020
assert sm.services["swan"] != None
2121

0 commit comments

Comments
 (0)