Skip to content

Commit abd3660

Browse files
authored
Merge branch 'expired_oauth_tokens' of 'https://github.com/sduenas/sortinghat-eclipse-foundation'
Merges #5 Closes #5
2 parents 303b56a + 6e217c3 commit abd3660

3 files changed

Lines changed: 59 additions & 24 deletions

File tree

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
title: OAuth2 token refreshing
3+
category: added
4+
author: Santiago Dueñas <sduenas@bitergia.com>
5+
issue: null
6+
notes: >
7+
OAuth2 token will be refreshed when they expired.

sortinghat/core/importer/backends/eclipse.py

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -206,9 +206,14 @@ class EclipseFoundationAPIClient:
206206
ECLIPSE_API_URL = "https://api.eclipse.org"
207207
ECLIPSE_ACCOUNTS_URL = "https://accounts.eclipse.org"
208208
OAUTH_TOKEN_ENDPOINT = "https://accounts.eclipse.org/oauth2/token"
209+
ECLIPSE_SCOPE = "eclipsefdn_view_all_profiles"
210+
211+
MAX_RETRIES = 3
209212

210213
def __init__(self):
211214
self.token = None
215+
self.user_id = None
216+
self.password = None
212217

213218
def login(self, user_id, password):
214219
"""Login on the Eclipse platform.
@@ -217,10 +222,12 @@ def login(self, user_id, password):
217222
"eclipsefdn_view_all_profiles" that will allow us to
218223
fetch all the info about profiles/identities.
219224
"""
225+
self.user_id = user_id
226+
self.password = password
220227
self.token = self._authenticate(
221-
user_id,
222-
password,
223-
"eclipsefdn_view_all_profiles",
228+
self.user_id,
229+
self.password,
230+
self.ECLIPSE_SCOPE,
224231
)
225232

226233
def logout(self):
@@ -281,8 +288,7 @@ def _fetch(self, url, params=None):
281288
"""Generic query to Eclipse usr API."""
282289

283290
try:
284-
response = requests.get(url, params=params, auth=self.token)
285-
response.raise_for_status()
291+
data = self._fetch_retry(url, params)
286292
except requests.exceptions.HTTPError as error:
287293
# Ignore 5xx errors
288294
if 500 <= error.response.status_code < 600:
@@ -296,7 +302,41 @@ def _fetch(self, url, params=None):
296302
else:
297303
raise error
298304

299-
return response.json()
305+
return data
306+
307+
def _fetch_retry(self, url, params=None):
308+
"""Fetch URL retrying in case of 403 or 500 errors.
309+
310+
When getting a 403 error, the method will try to authenticate
311+
again in case the OAuth2 token has expired.
312+
"""
313+
retries = 0
314+
max_retries = self.MAX_RETRIES
315+
316+
while retries < max_retries:
317+
response = requests.get(url, params=params, auth=self.token)
318+
319+
if response.status_code == 200:
320+
return response.json()
321+
elif response.status_code == 403:
322+
# Refresh token if needed and try again
323+
if self.token.expires_at <= datetime_utcnow():
324+
self.token = self._authenticate(
325+
self.user_id,
326+
self.password,
327+
self.ECLIPSE_SCOPE,
328+
)
329+
retries += 1
330+
elif 500 <= response.status_code < 600:
331+
# Errors could have been related to server overloading
332+
retries += 1
333+
else:
334+
response.raise_for_status()
335+
336+
response = requests.get(url, params=params, auth=self.token)
337+
response.raise_for_status()
338+
339+
return response
300340

301341
def _authenticate(self, client_id, client_secret, scope):
302342
"""Authenticate using OAuth2.

tests/test_eclipse.py

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -67,15 +67,17 @@ def request_callback(request, uri, headers):
6767
# John Smith profile pages
6868
httpretty.register_uri(httpretty.GET,
6969
ECLIPSE_API_URL + "/account/profile/jsmith",
70-
body=read_file('data/eclipse_jsmith.json'))
70+
body=read_file('data/eclipse_jsmith.json') if not raise_5xx_errors else "",
71+
status=200 if not raise_5xx_errors else 500)
7172
httpretty.register_uri(httpretty.GET,
7273
ECLIPSE_API_URL + "/account/profile/jsmith/employment-history",
7374
body=read_file('data/eclipse_jsmith_employment.json'))
7475

7576
# John Doe profile pages
7677
httpretty.register_uri(httpretty.GET,
7778
ECLIPSE_API_URL + "/account/profile/jdoe",
78-
body=read_file('data/eclipse_jdoe.json'))
79+
body=read_file('data/eclipse_jdoe.json') if not raise_5xx_errors else "",
80+
status=200 if not raise_5xx_errors else 500)
7981
httpretty.register_uri(httpretty.GET,
8082
ECLIPSE_API_URL + "/account/profile/jdoe/employment-history",
8183
body=read_file('data/eclipse_jdoe_employment.json'))
@@ -86,22 +88,8 @@ def request_callback(request, uri, headers):
8688
body=read_file('data/eclipse_jrae.json'))
8789
httpretty.register_uri(httpretty.GET,
8890
ECLIPSE_API_URL + "/account/profile/jrae/employment-history",
89-
body=read_file('data/eclipse_jrae_employment.json'))
90-
91-
# Overwrite jsmith and jdoe profile replies to raise 5xx errors
92-
if raise_5xx_errors:
93-
httpretty.register_uri(httpretty.GET,
94-
ECLIPSE_API_URL + "/account/profile/jsmith",
95-
body="",
96-
status=500)
97-
httpretty.register_uri(httpretty.GET,
98-
ECLIPSE_API_URL + "/account/profile/jdoe",
99-
body="",
100-
status=504)
101-
httpretty.register_uri(httpretty.GET,
102-
ECLIPSE_API_URL + "/account/profile/jrae/employment-history",
103-
body="",
104-
status=504)
91+
body=read_file('data/eclipse_jrae_employment.json') if not raise_5xx_errors else "",
92+
status=200 if not raise_5xx_errors else 500)
10593

10694
return requests, bodies
10795

0 commit comments

Comments
 (0)