Skip to content

Commit cc7e752

Browse files
authored
Merge pull request #17 from DataCrunch-io/feature/CLOUD-26-inspect-potential-python-sdk-bug
Feature/cloud 26 inspect potential python sdk bug
2 parents e25c06f + 7c14f24 commit cc7e752

File tree

5 files changed

+55
-30
lines changed

5 files changed

+55
-30
lines changed

CHANGELOG.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
11
Changelog
22
=========
33

4+
v1.4.1 (2023-06-20)
5+
-------------------
6+
7+
* Fixed a bug where token refresh failed
8+
9+
v1.4.0 (2023-06-14)
10+
-------------------
11+
412
* Added support for permanent deletion of volumes
513
* Added a Volume class method that inits a new Volume instance from a dict
614
* Added a few integration tests for permanent deletion of volumes

datacrunch/__version__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
VERSION = '1.4.0'
1+
VERSION = '1.4.1'

datacrunch/authentication/authentication.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,12 @@ def refresh(self) -> dict:
7878

7979
response = requests.post(
8080
url, json=payload, headers=self._generate_headers())
81-
handle_error(response)
81+
82+
# if refresh token is also expired, authenticate again:
83+
if response.status_code == 401 or response.status_code == 400:
84+
return self.authenticate()
85+
else:
86+
handle_error(response)
8287

8388
auth_data = response.json()
8489

@@ -104,4 +109,4 @@ def is_expired(self) -> bool:
104109
:return: True if the access token is expired, otherwise False.
105110
:rtype: bool
106111
"""
107-
return time.time() > self._expires_at
112+
return time.time() >= self._expires_at

datacrunch/http_client/http_client.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,11 @@ def post(self, url: str, json: dict = None, **kwargs) -> requests.Response:
4949
:return: Response object
5050
:rtype: requests.Response
5151
"""
52+
self._refresh_token_if_expired()
53+
5254
url = self._add_base_url(url)
5355
headers = self._generate_headers()
5456

55-
self._refresh_token_if_expired()
56-
5757
response = requests.post(url, json=json, headers=headers, **kwargs)
5858
handle_error(response)
5959

@@ -76,11 +76,11 @@ def put(self, url: str, json: dict = None, **kwargs) -> requests.Response:
7676
:return: Response object
7777
:rtype: requests.Response
7878
"""
79+
self._refresh_token_if_expired()
80+
7981
url = self._add_base_url(url)
8082
headers = self._generate_headers()
8183

82-
self._refresh_token_if_expired()
83-
8484
response = requests.put(url, json=json, headers=headers, **kwargs)
8585
handle_error(response)
8686

@@ -103,11 +103,11 @@ def get(self, url: str, params: dict = None, **kwargs) -> requests.Response:
103103
:return: Response object
104104
:rtype: requests.Response
105105
"""
106+
self._refresh_token_if_expired()
107+
106108
url = self._add_base_url(url)
107109
headers = self._generate_headers()
108110

109-
self._refresh_token_if_expired()
110-
111111
response = requests.get(url, params=params, headers=headers, **kwargs)
112112
handle_error(response)
113113

@@ -130,11 +130,11 @@ def delete(self, url: str, json: dict = None, **kwargs) -> requests.Response:
130130
:return: Response object
131131
:rtype: requests.Response
132132
"""
133+
self._refresh_token_if_expired()
134+
133135
url = self._add_base_url(url)
134136
headers = self._generate_headers()
135137

136-
self._refresh_token_if_expired()
137-
138138
response = requests.delete(url, headers=headers, json=json, **kwargs)
139139
handle_error(response)
140140

@@ -147,7 +147,7 @@ def _refresh_token_if_expired(self) -> None:
147147
148148
:raises APIException: an api exception with message and error type code
149149
"""
150-
if(self._auth_service.is_expired()):
150+
if (self._auth_service.is_expired()):
151151
# try to refresh. if refresh token has expired, reauthenticate
152152
try:
153153
self._auth_service.refresh()
@@ -182,7 +182,7 @@ def _generate_user_agent(self) -> str:
182182
:rtype: str
183183
"""
184184
# get the first 10 chars of the client id
185-
client_id_truncated = self._auth_service._client_id[:10]
185+
client_id_truncated = self._auth_service._client_id[:10]
186186

187187
return f'datacrunch-python-v{self._version}-{client_id_truncated}'
188188

tests/unit_tests/authentication/test_authentication.py

Lines changed: 29 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import pytest
2-
import responses # https://github.com/getsentry/responses
2+
import responses # https://github.com/getsentry/responses
33
from responses import matchers
44
import time
55

@@ -22,6 +22,7 @@
2222
ACCESS_TOKEN2 = 'access2'
2323
REFRESH_TOKEN2 = 'refresh2'
2424

25+
2526
class TestAuthenticationService:
2627

2728
@pytest.fixture
@@ -78,7 +79,8 @@ def test_authenticate_failed(self, authentication_service, endpoint):
7879
assert excinfo.value.code == INVALID_REQUEST
7980
assert excinfo.value.message == INVALID_REQUEST_MESSAGE
8081
assert responses.assert_call_count(endpoint, 1) is True
81-
assert responses.calls[0].request.body == f'{{"grant_type": "client_credentials", "client_id": "{CLIENT_ID}", "client_secret": "{CLIENT_SECRET}"}}'.encode()
82+
assert responses.calls[0].request.body == f'{{"grant_type": "client_credentials", "client_id": "{CLIENT_ID}", "client_secret": "{CLIENT_SECRET}"}}'.encode(
83+
)
8284

8385
def test_refresh_successful(self, authentication_service, endpoint):
8486
# add a response for the client credentials grant
@@ -92,7 +94,8 @@ def test_refresh_successful(self, authentication_service, endpoint):
9294
'token_type': TOKEN_TYPE,
9395
'expires_in': EXPIRES_IN
9496
},
95-
match=[matchers.json_params_matcher({"grant_type":"client_credentials", "client_id": CLIENT_ID, "client_secret": CLIENT_SECRET})],
97+
match=[matchers.json_params_matcher(
98+
{"grant_type": "client_credentials", "client_id": CLIENT_ID, "client_secret": CLIENT_SECRET})],
9699
status=200
97100
)
98101

@@ -107,12 +110,13 @@ def test_refresh_successful(self, authentication_service, endpoint):
107110
'token_type': TOKEN_TYPE,
108111
'expires_in': EXPIRES_IN
109112
},
110-
match=[matchers.json_params_matcher({"grant_type":"refresh_token", "refresh_token": REFRESH_TOKEN})],
113+
match=[matchers.json_params_matcher(
114+
{"grant_type": "refresh_token", "refresh_token": REFRESH_TOKEN})],
111115
status=200
112116
)
113117

114118
# act
115-
auth_data = authentication_service.authenticate() # authenticate first
119+
auth_data = authentication_service.authenticate() # authenticate first
116120

117121
# assert
118122
assert type(auth_data) == dict
@@ -121,17 +125,19 @@ def test_refresh_successful(self, authentication_service, endpoint):
121125
assert authentication_service._scope == SCOPE
122126
assert authentication_service._token_type == TOKEN_TYPE
123127
assert authentication_service._expires_at != None
124-
assert responses.calls[0].request.body == f'{{"grant_type": "client_credentials", "client_id": "{CLIENT_ID}", "client_secret": "{CLIENT_SECRET}"}}'.encode()
128+
assert responses.calls[0].request.body == f'{{"grant_type": "client_credentials", "client_id": "{CLIENT_ID}", "client_secret": "{CLIENT_SECRET}"}}'.encode(
129+
)
125130

126-
auth_data2 = authentication_service.refresh() # refresh
131+
auth_data2 = authentication_service.refresh() # refresh
127132

128133
assert type(auth_data2) == dict
129134
assert authentication_service._access_token == ACCESS_TOKEN2
130135
assert authentication_service._refresh_token == REFRESH_TOKEN2
131136
assert authentication_service._scope == SCOPE
132137
assert authentication_service._token_type == TOKEN_TYPE
133138
assert authentication_service._expires_at != None
134-
assert responses.calls[1].request.body == f'{{"grant_type": "refresh_token", "refresh_token": "{REFRESH_TOKEN}"}}'.encode()
139+
assert responses.calls[1].request.body == f'{{"grant_type": "refresh_token", "refresh_token": "{REFRESH_TOKEN}"}}'.encode(
140+
)
135141
assert responses.assert_call_count(endpoint, 2) is True
136142

137143
def test_refresh_failed(self, authentication_service, endpoint):
@@ -147,7 +153,8 @@ def test_refresh_failed(self, authentication_service, endpoint):
147153
'token_type': TOKEN_TYPE,
148154
'expires_in': EXPIRES_IN
149155
},
150-
match=[matchers.json_params_matcher({"grant_type":"client_credentials", "client_id": CLIENT_ID, "client_secret": CLIENT_SECRET})],
156+
match=[matchers.json_params_matcher(
157+
{"grant_type": "client_credentials", "client_id": CLIENT_ID, "client_secret": CLIENT_SECRET})],
151158
status=200
152159
)
153160

@@ -156,12 +163,13 @@ def test_refresh_failed(self, authentication_service, endpoint):
156163
responses.POST,
157164
endpoint,
158165
json={"code": INVALID_REQUEST, "message": INVALID_REQUEST_MESSAGE},
159-
match=[matchers.json_params_matcher({"grant_type":"refresh_token", "refresh_token": REFRESH_TOKEN})],
160-
status=400
166+
match=[matchers.json_params_matcher(
167+
{"grant_type": "refresh_token", "refresh_token": REFRESH_TOKEN})],
168+
status=500
161169
)
162170

163171
# act
164-
authentication_service.authenticate() # authenticate first
172+
authentication_service.authenticate() # authenticate first
165173

166174
with pytest.raises(APIException) as excinfo:
167175
authentication_service.refresh()
@@ -170,21 +178,25 @@ def test_refresh_failed(self, authentication_service, endpoint):
170178
assert excinfo.value.code == INVALID_REQUEST
171179
assert excinfo.value.message == INVALID_REQUEST_MESSAGE
172180
assert responses.assert_call_count(endpoint, 2) is True
173-
assert responses.calls[0].request.body == f'{{"grant_type": "client_credentials", "client_id": "{CLIENT_ID}", "client_secret": "{CLIENT_SECRET}"}}'.encode()
174-
assert responses.calls[1].request.body == f'{{"grant_type": "refresh_token", "refresh_token": "{REFRESH_TOKEN}"}}'.encode()
181+
assert responses.calls[0].request.body == f'{{"grant_type": "client_credentials", "client_id": "{CLIENT_ID}", "client_secret": "{CLIENT_SECRET}"}}'.encode(
182+
)
183+
assert responses.calls[1].request.body == f'{{"grant_type": "refresh_token", "refresh_token": "{REFRESH_TOKEN}"}}'.encode(
184+
)
175185

176186
def test_is_expired(self, authentication_service, endpoint):
177187
# arrange
178188
current_time = time.time()
179189
future_time = current_time + 3600
180190

181191
# act
182-
authentication_service._expires_at = current_time # set the expired_at as current time
192+
# set the expired_at as current time
193+
authentication_service._expires_at = current_time
183194
is_expired_current = authentication_service.is_expired()
184195

185-
authentication_service._expires_at = future_time # set the expired_at as future time
196+
# set the expired_at as future time
197+
authentication_service._expires_at = future_time
186198
is_expired_future = authentication_service.is_expired()
187199

188200
# assert
189201
assert is_expired_current == True
190-
assert is_expired_future == False
202+
assert is_expired_future == False

0 commit comments

Comments
 (0)