diff --git a/rowers/admin.py b/rowers/admin.py index a314ebe6..f28aecae 100644 --- a/rowers/admin.py +++ b/rowers/admin.py @@ -44,7 +44,8 @@ class RowerInline(admin.StackedInline): 'polartoken','polartokenexpirydate', 'polarrefreshtoken','polaruserid', 'polar_auto_import', - 'stravatoken','stravaexportas','strava_auto_export', + 'stravatoken','stravatokenexpirydate','stravarefreshtoken', + 'stravaexportas','strava_auto_export', 'strava_auto_import', 'runkeepertoken','runkeeper_auto_export',)}), ('Team', diff --git a/rowers/imports.py b/rowers/imports.py index 70f765c0..bcddd768 100644 --- a/rowers/imports.py +++ b/rowers/imports.py @@ -94,7 +94,7 @@ def imports_open(user,oauth_data): tokenname = oauth_data['tokenname'] refreshtokenname = oauth_data['refreshtokenname'] expirydatename = oauth_data['expirydatename'] - if tokenexpirydate and timezone.now()>tokenexpirydate: + if tokenexpirydate and timezone.now()+timedelta(seconds=3599)>tokenexpirydate: token = imports_token_refresh( user, tokenname, @@ -102,6 +102,15 @@ def imports_open(user,oauth_data): expirydatename, oauth_data, ) + elif tokenexpirydate is None and 'strava' in expirydatename: + token = imports_token_refresh( + user, + tokenname, + refreshtokenname, + expirydatename, + oauth_data, + ) + return token @@ -156,7 +165,11 @@ def imports_do_refresh_token(refreshtoken,oauth_data,access_token=''): try: expires_in = token_json['expires_in'] except KeyError: - expires_in = 0 + try: + expires_at = arrow.get(token_json['expires_at']).timestamp + expires_in = expires_at - arrow.now().timestamp + except KeyError: + expires_in = 0 try: refresh_token = token_json['refresh_token'] except KeyError: @@ -266,6 +279,11 @@ def imports_token_refresh(user,tokenname,refreshtokenname,expirydatename,oauth_d r = Rower.objects.get(user=user) refreshtoken = getattr(r,refreshtokenname) + + # for Strava transition + if not refreshtoken: + refreshtoken = getattr(r,tokenname) + res = imports_do_refresh_token(refreshtoken,oauth_data) access_token = res[0] diff --git a/rowers/models.py b/rowers/models.py index 5db5bb25..f628078f 100644 --- a/rowers/models.py +++ b/rowers/models.py @@ -653,6 +653,9 @@ class Rower(models.Model): polar_auto_import = models.BooleanField(default=False) stravatoken = models.CharField(default='',max_length=200,blank=True,null=True) + stravatokenexpirydate = models.DateTimeField(blank=True,null=True) + stravarefreshtoken = models.CharField(default='',max_length=1000, + blank=True,null=True) stravaexportas = models.CharField(default="Rowing", max_length=30, choices=stravatypes, diff --git a/rowers/stravastuff.py b/rowers/stravastuff.py index 32eb785f..3ce5125e 100644 --- a/rowers/stravastuff.py +++ b/rowers/stravastuff.py @@ -40,11 +40,11 @@ oauth_data = { 'autorization_uri': "https://www.strava.com/oauth/authorize", 'content_type': 'application/json', 'tokenname': 'stravatoken', - 'refreshtokenname': '', - 'expirydatename': '', + 'refreshtokenname': 'stravarefreshtoken', + 'expirydatename': 'stravatokenexpirydate', 'bearer_auth': True, 'base_url': "https://www.strava.com/oauth/token", - 'grant_type': None, + 'grant_type': 'refresh_token', } @@ -52,6 +52,27 @@ oauth_data = { def get_token(code): return imports_get_token(code, oauth_data) +def strava_open(user): + return imports_open(user, oauth_data) + +def do_refresh_token(refreshtoken): + return imports_do_refresh_token(refreshtoken, oauth_data) + +def rower_strava_token_refresh(user): + r = Rower.objects.get(user=user) + res = do_refresh_token(r.stravarefreshtoken) + access_token = res[0] + expires_in = res[1] + refresh_token = res[2] + expirydatetime = timezone.now()+timedelta(seconds=expires_in) + + r.stravatoken = access_token + r.stravatokenexpirydate = expirydatetime + r.stravarefreshtoken = refresh_token + r.save() + + return r.stravatoken + # Make authorization URL including random string def make_authorization_url(request): return imports_make_authorization_url(oauth_data) @@ -62,6 +83,9 @@ def get_strava_workout_list(user,limit_n=0): if (r.stravatoken == '') or (r.stravatoken is None): s = "Token doesn't exist. Need to authorize" return custom_exception_handler(401,s) + elif (r.stravatokenexpirydate is None or timezone.now()+timedelta(seconds=3599)>r.stravatokenexpirydate): + s = "Token expired. Needs to refresh." + return custom_exception_handler(401,s) else: # ready to fetch. Hurray authorizationstring = str('Bearer ' + r.stravatoken) @@ -86,10 +110,13 @@ def get_strava_workouts(rower): if not isprorower(rower): return 0 - - res = get_strava_workout_list(rower.user,limit_n=10) - print res.status_code + try: + thetoken = strava_open(rower.user) + except NoTokenError: + return 0 + + res = get_strava_workout_list(rower.user,limit_n=10) if (res.status_code != 200): return 0 @@ -227,6 +254,9 @@ def get_workout(user,stravaid): if (r.stravatoken == '') or (r.stravatoken is None): s = "Token doesn't exist. Need to authorize" return custom_exception_handler(401,s) + elif (r.stravatokenexpirydate is not None and timezone.now()>r.stravatokenexpirydate): + s = "Token expired. Needs to refresh." + return custom_exception_handler(401,s) else: # ready to fetch. Hurray fetchresolution = 'high' diff --git a/rowers/views.py b/rowers/views.py index cc9cdd8d..d22b882c 100644 --- a/rowers/views.py +++ b/rowers/views.py @@ -116,6 +116,7 @@ from sporttracksstuff import sporttracks_open from tpstuff import tp_open from iso8601 import ParseError import stravastuff +from stravastuff import strava_open import polarstuff import sporttracksstuff import underarmourstuff @@ -2421,15 +2422,22 @@ def rower_process_stravacallback(request): if res[0]: access_token = res[0] - + expires_in = res[1] + refresh_token = res[2] + + expirydatetime = timezone.now()+datetime.timedelta(seconds=expires_in) + r = getrower(request.user) r.stravatoken = access_token + r.stravatokenexpirydate = expirydatetime + r.stravarefreshtoken = refresh_token r.save() successmessage = "Tokens stored. Good to go" messages.info(request,successmessage) - return imports_view(request) + url = reverse(workouts_view) + return HttpResponseRedirect(url) else: message = "Something went wrong with the Strava authorization" messages.error(request,message) @@ -10272,6 +10280,11 @@ def workout_stravaimport_view(request,message="",userid=0): r = getrequestrower(request,userid=userid) + try: + thetoken = strava_open(request.user) + except NoTokenError: + return HttpResponseRedirect("/rowers/me/stravaauthorize/") + if r.user != request.user: messages.info(request,"You cannot import other people's workouts from Concept2")