From db61d2e99ce9c3b4c41cef65d3d665c0ddc89355 Mon Sep 17 00:00:00 2001 From: Jedd Morgan <45512892+JR-Morgan@users.noreply.github.com> Date: Thu, 11 Sep 2025 15:37:31 +0100 Subject: [PATCH] feat(specklepy): Make `Client.authenticate_with_token` initialise user data (#450) * easy solution * Fixed tests --- src/specklepy/core/api/client.py | 42 ++++++++++++------- src/specklepy/core/api/credentials.py | 2 +- .../integration/client/test_client_and_ops.py | 4 +- 3 files changed, 30 insertions(+), 18 deletions(-) diff --git a/src/specklepy/core/api/client.py b/src/specklepy/core/api/client.py index d63c3b0..6e79ed2 100644 --- a/src/specklepy/core/api/client.py +++ b/src/specklepy/core/api/client.py @@ -131,6 +131,18 @@ class SpeckleClient: self.account = Account.from_token(token, self.url) self._set_up_client() + userData = self.active_user.get() + + # None if the token lacked the profile:read scope or if it was None + if userData: + self.account.userInfo.id = userData.id + self.account.userInfo.email = userData.email + self.account.userInfo.name = userData.name + self.account.userInfo.company = userData.company + self.account.userInfo.avatar = userData.avatar + + self.account.serverInfo = self.server.get() + def authenticate_with_account(self, account: Account) -> None: """Authenticate the client using an Account object The account is saved in the client object and a synchronous GraphQL @@ -143,6 +155,21 @@ class SpeckleClient: self.account = account self._set_up_client() + try: + _ = self.active_user.get() + except SpeckleException as ex: + if isinstance(ex.exception, TransportServerError): + if ex.exception.code == 403: + warn( + SpeckleWarning( + "Possibly invalid token - could not authenticate " + f"Speckle Client for server {self.url}" + ), + stacklevel=2, + ) + else: + raise ex + def _set_up_client(self) -> None: headers = { "Authorization": f"Bearer {self.account.token}", @@ -162,21 +189,6 @@ class SpeckleClient: self._init_resources() - try: - _ = self.active_user.get() - except SpeckleException as ex: - if isinstance(ex.exception, TransportServerError): - if ex.exception.code == 403: - warn( - SpeckleWarning( - "Possibly invalid token - could not authenticate " - f"Speckle Client for server {self.url}" - ), - stacklevel=2, - ) - else: - raise ex - def execute_query(self, query: str) -> Dict: return self.httpclient.execute(query) diff --git a/src/specklepy/core/api/credentials.py b/src/specklepy/core/api/credentials.py index e08095f..ecde0e5 100644 --- a/src/specklepy/core/api/credentials.py +++ b/src/specklepy/core/api/credentials.py @@ -37,7 +37,7 @@ class Account(BaseModel): return self.__repr__() @classmethod - def from_token(cls, token: str, server_url: str = None): + def from_token(cls, token: str, server_url: str | None = None): acct = cls(token=token) acct.serverInfo.url = server_url return acct diff --git a/tests/integration/client/test_client_and_ops.py b/tests/integration/client/test_client_and_ops.py index 70d445a..bc0e25e 100644 --- a/tests/integration/client/test_client_and_ops.py +++ b/tests/integration/client/test_client_and_ops.py @@ -6,7 +6,7 @@ from specklepy.api import operations from specklepy.api.client import SpeckleClient from specklepy.api.credentials import Account, get_account_from_token from specklepy.core.helpers import speckle_path_provider -from specklepy.logging.exceptions import SpeckleException, SpeckleWarning +from specklepy.logging.exceptions import SpeckleException from specklepy.objects.base import Base from specklepy.transports.server import ServerTransport @@ -17,7 +17,7 @@ def test_invalid_authentication(): speckle_path_provider.override_application_data_path(gettempdir()) client = SpeckleClient() - with pytest.warns(SpeckleWarning): + with pytest.raises(SpeckleException): client.authenticate_with_token("fake token") # remove path override