diff --git a/rowers/garmin_stuff.py b/rowers/garmin_stuff.py new file mode 100644 index 00000000..2aa59cfe --- /dev/null +++ b/rowers/garmin_stuff.py @@ -0,0 +1,82 @@ +from rowers.imports import * +import datetime +import requests +from requests_oauthlib import OAuth1,OAuth1Session +from requests import Request, Session +import rowers.mytypes as mytypes +from rowers.mytypes import otwtypes +from rowers.rower_rules import is_workout_user,ispromember +from iso8601 import ParseError + +import numpy +import json +from json.decoder import JSONDecodeError + +from rowsandall_app.settings import ( + GARMIN_CLIENT_KEY, GARMIN_REDIRECT_URI, GARMIN_CLIENT_SECRET + ) + +from rowers.tasks import handle_c2_import_stroke_data, handle_c2_sync +import django_rq +queue = django_rq.get_queue('default') +queuelow = django_rq.get_queue('low') +queuehigh = django_rq.get_queue('low') +from rowers.utils import myqueue +from rowers.models import C2WorldClassAgePerformance + +from django.core.exceptions import PermissionDenied + +oauth_data = { + 'client_id': GARMIN_CLIENT_KEY, + 'client_secret': GARMIN_CLIENT_SECRET, + 'redirect_uri': GARMIN_REDIRECT_URI, + 'authorization_uri': "https://connectapi.garmin.com/oauth-service/oauth/request_token", + 'content_type': 'application/x-www-form-urlencoded', + 'tokenname': 'garmintoken', + 'refreshtokenname': 'garminrefreshtoken', + 'expirydatename': 'garmintokenexpirydate', + 'bearer_auth': True, + 'base_url': "https://connect.garmin.com/oauthConfirm", + 'scope':'write', + 'headers': 'Authorization: OAuth oauth_version="1.0"' + } + +def garmin_authorize(): + redirect_uri = oauth_data['redirect_uri'] + client_secret = oauth_data['client_secret'] + client_id = oauth_data['client_id'] + base_uri = oauth_data['base_url'] + + + garmin = OAuth1Session(oauth_data['client_id'], + client_secret=oauth_data['client_secret'], + ) + fetch_response = garmin.fetch_request_token(oauth_data['authorization_uri']) + resource_owner_key = fetch_response.get('oauth_token') + resource_owner_secret = fetch_response.get('oauth_token_secret') + + authorization_url = garmin.authorization_url(base_uri) + return authorization_url + +def garmin_processcallback(redirect_respones): + garmin = OAuth1Session(oauth_data['client_id'], + client_secret=oauth_data['client_secret'], + ) + oauth_response = garmin.parse_authorization_response(redirect_response) + + verifier = oauth_response.get('oauth_verifier') + token = oauth_response.get('oauth_token') + access_token_url = 'https://connectapi.garmin.com/oauth-service/oauth/access_token' + + # Using OAuth1Session + garmin = OAuth1Session(oauth_data['client_id'], + client_secret=oauth_data['client_secret'], + resource_owner_key=resource_owner_key, + resource_owner_secret=resource_owner_secret, + verifier=verifier,) + oauth_tokens = garmin.fetch_access_token(access_token_url) + + garmintoken = oauth_tokens.get('oauth_token') + garminrefreshtoken = oauth_tokens.get('oauth_token_secret') + + return garmintoken,garminrefreshtoken diff --git a/rowers/models.py b/rowers/models.py index a3f0d391..ecdd8cf7 100644 --- a/rowers/models.py +++ b/rowers/models.py @@ -834,6 +834,10 @@ class Rower(models.Model): polaruserid = models.IntegerField(default=0) polar_auto_import = models.BooleanField(default=False) + garmintoken = models.CharField(default='',max_length=200,blank=True,null=True) + garminrefreshtoken = models.CharField(default='',max_length=1000, + blank=True,null=True) + 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, diff --git a/rowers/urls.py b/rowers/urls.py index 58829974..067b4448 100644 --- a/rowers/urls.py +++ b/rowers/urls.py @@ -532,6 +532,7 @@ urlpatterns = [ re_path(r'^me/polarauthorize/$',views.rower_polar_authorize,name='rower_polar_authorize'), re_path(r'^me/revokeapp/(?P\d+)/$',views.rower_revokeapp_view,name='rower_revokeapp_view'), re_path(r'^me/stravaauthorize/$',views.rower_strava_authorize,name='rower_strava_authorize'), + re_path(r'^me/garminauthorize/$',views.rower_garmin_authorize,name='rower_garmin_authorize'), re_path(r'^me/sporttracksauthorize/$',views.rower_sporttracks_authorize,name='rower_sporttracks_authorize'), re_path(r'^me/underarmourauthorize/$',views.rower_underarmour_authorize,name='rower_underarmour_authorize'), re_path(r'^me/tpauthorize/$',views.rower_tp_authorize,name='rower_tp_authorize'), diff --git a/rowers/views/importviews.py b/rowers/views/importviews.py index dccf2f4a..a75b8db7 100644 --- a/rowers/views/importviews.py +++ b/rowers/views/importviews.py @@ -401,6 +401,12 @@ def rower_c2_authorize(request): url += "&scope="+scope return HttpResponseRedirect(url) +# Garmin authorization +@login_required() +def rower_garmin_authorize(request): + authorization_url = garmin_stuff.garmin_authorize() + return HttpResponseRedirect(authorization_url) + # Strava Authorization @login_required() def rower_strava_authorize(request): @@ -705,7 +711,20 @@ def rower_process_polarcallback(request): return HttpResponseRedirect(url) +# process Garmin callback +@login_required() +def rower_process_garmincallback(request): + r = getrower(request.user) + absoluteurl = request.build_absolute_uri() + garmintoken,garminrefreshtoken = garmin_stuff.garmin_processcallback(absoluteurl) + r.garmintoken = garmintoken + r.garminrefreshtoken = garminrefreshtoken + r.save() + successmessage = "Tokens stored. Good to go" + messages.info(request,successmessage) + url = reverse('workouts_view') + return HttpResponseRedirect(url) # Process Strava Callback @login_required() diff --git a/rowers/views/statements.py b/rowers/views/statements.py index 6ce222f9..6003cb4b 100644 --- a/rowers/views/statements.py +++ b/rowers/views/statements.py @@ -157,6 +157,7 @@ from rowers.sporttracksstuff import sporttracks_open from rowers.tpstuff import tp_open from iso8601 import ParseError import rowers.stravastuff as stravastuff +import rowers.garmin_stuff as garmin_stuff from rowers.stravastuff import strava_open import rowers.polarstuff as polarstuff import rowers.sporttracksstuff as sporttracksstuff diff --git a/rowsandall_app/settings.py b/rowsandall_app/settings.py index aea004aa..f066df9e 100644 --- a/rowsandall_app/settings.py +++ b/rowsandall_app/settings.py @@ -282,6 +282,10 @@ STRAVA_CLIENT_ID = CFG['strava_client_id'] STRAVA_CLIENT_SECRET = CFG['strava_client_secret'] STRAVA_REDIRECT_URI = CFG['strava_callback'] +# Garmin +GARMIN_CLIENT_KEY = CFG["garmin_client_key"] +GARMIN_CLIENT_SECRET = CFG['garmin_client_secret'] +GARMIN_REDIRECT_URI = CFG['garmin_callback'] # SportTracks diff --git a/rowsandall_app/urls.py b/rowsandall_app/urls.py index 88a2cfd2..f6d3628e 100644 --- a/rowsandall_app/urls.py +++ b/rowsandall_app/urls.py @@ -71,6 +71,7 @@ urlpatterns += [ # re_path(r'^admin/rq/',include('django_rq_dashboard.urls')), re_path(r'^call\_back',rowersviews.rower_process_callback), re_path(r'^stravacall\_back',rowersviews.rower_process_stravacallback), + re_path(r'^garmin\_callback',rowersviews.rower_process_garmincallback), re_path(r'^sporttracks\_callback',rowersviews.rower_process_sporttrackscallback), re_path(r'^underarmour\_callback',rowersviews.rower_process_underarmourcallback), re_path(r'^polarflowcallback',rowersviews.rower_process_polarcallback),