Skip to content

Commit 90e9be3

Browse files
committed
OuraRing API integration_step1 - Oauth
Add Oura API oauth functions to authenticate user and retrieve/store oura_access and oura_refresh tokens.
1 parent ec039bf commit 90e9be3

16 files changed

+442
-108
lines changed

src/athletedataapp_apache.py

Lines changed: 75 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
from db_create_user_database import check_user_db_exists,check_host_record_exists,backup_user_db,create_sample_db,check_db_server_connectivity
1515
from db_user_insert import gc_user_update
1616
from db_dropbox import check_user_token_exists
17+
from db_oura_auth import check_oura_token_exists
1718
from diasend_data_download_db_insert import diasend_data_export_insert
1819
from glimp_data_download_db_insert import glimp_data_insert
1920
from mind_monitor_data_download_db_insert import mm_data_insert
@@ -29,8 +30,8 @@
2930
import Crypto.Random
3031
from Crypto.Cipher import AES
3132
import base64
32-
33-
33+
from requests_oauthlib import OAuth2Session
34+
3435
#----Crypto Variables----
3536
# salt size in bytes
3637
SALT_SIZE = 16
@@ -67,6 +68,12 @@ def encrypt(plaintext, password):
6768
REDIRECT_URI = str(dbx_params.get("redirect_uri"))
6869
integrated_with_dropbox = str(dbx_params.get("integrated_with_dropbox"))
6970

71+
oura_params = config(filename="encrypted_settings.ini", section="oura",encr_pass=encr_pass)
72+
OURA_CLIENT_ID = str(oura_params.get("oura_client_id"))
73+
OURA_CLIENT_SECRET = str(oura_params.get("oura_client_secret"))
74+
OURA_AUTH_URL = str(oura_params.get("oura_auth_url"))
75+
OURA_TOKEN_URL = str(oura_params.get("oura_token_url"))
76+
7077
anticaptcha_params = config(filename="encrypted_settings.ini", section="anticaptcha",encr_pass=encr_pass)
7178
anticaptcha_api_key = str(anticaptcha_params.get("api_key"))
7279
if anticaptcha_api_key == "":
@@ -126,6 +133,7 @@ def index():
126133
archive_to_dropbox = False
127134
archive_radio = None
128135
dbx_auth_token = session.get('dbx_auth_token',None)
136+
oura_refresh_token = session.get('oura_refresh_token',None)
129137
auto_synch = False
130138

131139
output = DOWNLOAD_DIR
@@ -252,8 +260,22 @@ def index():
252260
return redirect(url_for('dropbox_auth_request'))
253261
else:
254262
archive_to_dropbox = True
255-
256-
# CLEANUP BEFORE DOWNLOAD -----------------
263+
264+
#----Check for and Retrieve Oura token----
265+
if request.form.get('ouraCheckbox') is not None:
266+
if oura_refresh_token is None:
267+
db_exists = check_user_db_exists(gc_username,gc_password,db_host,superuser_un,superuser_pw,encr_pass)
268+
if db_exists == True:
269+
oura_token_exists, oura_token_from_db = check_oura_token_exists(gc_username,db_host,db_name,superuser_un,superuser_pw,encr_pass)
270+
if oura_token_exists == True: # token exists in database and it is not None
271+
oura_refresh_token = oura_token_from_db
272+
print('Refresh Token: {}'.format(oura_refresh_token))
273+
else:
274+
return redirect(url_for('oura_auth_request'))
275+
else:
276+
return redirect(url_for('oura_auth_request'))
277+
278+
# CLEANUP BEFORE DOWNLOAD -----------------
257279

258280
#----Delete Files and DB Data variables----
259281
try:
@@ -387,7 +409,8 @@ def index():
387409
#PG:Call to execute "GC login" script
388410
if gc_username is not None:
389411
try:
390-
gc_agent = gc.login(gc_username, gc_password, mfp_username,db_host,superuser_un,superuser_pw,dbx_auth_token,encr_pass,save_pwd)
412+
gc_agent = gc.login(gc_username, gc_password, mfp_username,db_host,superuser_un,superuser_pw,dbx_auth_token,oura_refresh_token,encr_pass,save_pwd)
413+
session['oura_refresh_token'] = None
391414
gc_user_update(gc_username,db_host,db_name,superuser_un,superuser_pw,encrypted_superuser_pw,auto_synch_checkbox,encr_pass) #----Set Auto_Synch switch----
392415
gc_login_progress = 'Login to GC successfull'
393416
with StdoutRedirection(gc_username):
@@ -458,6 +481,11 @@ def index():
458481
time.sleep(1)
459482
with ErrorStdoutRedirection(gc_username):
460483
print((str(datetime.datetime.now()) + ' ' + gc_fit_well_progress))
484+
485+
#TODO:
486+
#PG:Call to execute "Parse and insert Oura wellness data" script
487+
#TODO
488+
461489
#PG:Call to execute "Parse and insert JSON wellness data" script
462490
try:
463491
gc_json_well_progress = 'GC JSON wellness download started'
@@ -767,12 +795,48 @@ def dropbox_auth_request():
767795
pass
768796

769797
@app.route("/dropbox_confirm")
770-
def dropbox_confirm():
771-
token = dropbox_auth_finish(session,request)
772-
session['dbx_auth_token'] = token
773-
continue_btn = 'delete'
774-
flash(' You have successfuly authenticated with Dropbox. Click "Continue" to proceed with download.','success')
775-
return redirect(url_for('index',continue_btn = continue_btn))
798+
def dropbox_confirm():
799+
try:
800+
token = dropbox_auth_finish(session,request)
801+
session['dbx_auth_token'] = token
802+
continue_btn = 'delete'
803+
flash(' You have successfuly authenticated with Dropbox. Click "Continue" to proceed with download.','success')
804+
return redirect(url_for('index',continue_btn = continue_btn))
805+
except Exception as e:
806+
session['dbx_auth_token'] = None
807+
flash(' There was a problem authenticating with Dropbox.','warning')
808+
return redirect(url_for('index'))
809+
810+
811+
@app.route('/oura_auth_request')
812+
def oura_auth_request():
813+
try:
814+
oura_session = OAuth2Session(OURA_CLIENT_ID)
815+
authorization_url, state = oura_session.authorization_url(OURA_AUTH_URL)
816+
session['oura_oauth_state'] = state
817+
return redirect(authorization_url, 301)
818+
except Exception as e:
819+
pass
820+
821+
@app.route('/oura_confirm')# Must match Redirect URI specified in https://cloud.ouraring.com/oauth/applications.
822+
def oura_confirm():
823+
oura_session = OAuth2Session(OURA_CLIENT_ID, state=session['oura_oauth_state'])
824+
try:
825+
response = oura_session.fetch_token(
826+
OURA_TOKEN_URL,
827+
client_secret=OURA_CLIENT_SECRET,
828+
authorization_response=request.url)
829+
830+
oura_refresh_token = response['refresh_token']
831+
832+
session['oura_refresh_token'] = oura_refresh_token
833+
continue_btn = 'delete'
834+
flash(' You have successfuly authenticated with Oura. Click "Continue" to proceed with download.','success')
835+
return redirect(url_for('index',continue_btn = continue_btn))
836+
except Exception as e:
837+
session['oura_refresh_token'] = None
838+
flash(' There was a problem authenticating with Oura.','warning')
839+
return redirect(url_for('index'))
776840

777841
@app.route("/process_running", methods = ['GET','POST'])
778842
def process_running():

src/athletedataapp_flask.py

Lines changed: 74 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
from db_create_user_database import check_user_db_exists,check_host_record_exists,backup_user_db,create_sample_db,check_db_server_connectivity
1515
from db_user_insert import gc_user_update
1616
from db_dropbox import check_user_token_exists
17+
from db_oura_auth import check_oura_token_exists
1718
from diasend_data_download_db_insert import diasend_data_export_insert
1819
from glimp_data_download_db_insert import glimp_data_insert
1920
from mind_monitor_data_download_db_insert import mm_data_insert
@@ -29,8 +30,8 @@
2930
import Crypto.Random
3031
from Crypto.Cipher import AES
3132
import base64
32-
33-
33+
from requests_oauthlib import OAuth2Session
34+
3435
#----Crypto Variables----
3536
# salt size in bytes
3637
SALT_SIZE = 16
@@ -55,7 +56,6 @@ def create_app(encr_pass_input,debug=False):
5556
DOWNLOAD_DIR = str(path_params.get("download_dir"))
5657
TEMP_FILE_PATH = str(path_params.get("temp_file_path"))
5758

58-
5959
encr_pass = encr_pass_input
6060

6161
dbx_params = config(filename="encrypted_settings.ini", section="dropbox",encr_pass=encr_pass)
@@ -64,6 +64,12 @@ def create_app(encr_pass_input,debug=False):
6464
REDIRECT_URI = str(dbx_params.get("redirect_uri"))
6565
integrated_with_dropbox = str(dbx_params.get("integrated_with_dropbox"))
6666

67+
oura_params = config(filename="encrypted_settings.ini", section="oura",encr_pass=encr_pass)
68+
OURA_CLIENT_ID = str(oura_params.get("oura_client_id"))
69+
OURA_CLIENT_SECRET = str(oura_params.get("oura_client_secret"))
70+
OURA_AUTH_URL = str(oura_params.get("oura_auth_url"))
71+
OURA_TOKEN_URL = str(oura_params.get("oura_token_url"))
72+
6773
anticaptcha_params = config(filename="encrypted_settings.ini", section="anticaptcha",encr_pass=encr_pass)
6874
anticaptcha_api_key = str(anticaptcha_params.get("api_key"))
6975
if anticaptcha_api_key == "":
@@ -123,6 +129,7 @@ def index():
123129
archive_to_dropbox = False
124130
archive_radio = None
125131
dbx_auth_token = session.get('dbx_auth_token',None)
132+
oura_refresh_token = session.get('oura_refresh_token',None)
126133
auto_synch = False
127134

128135
output = DOWNLOAD_DIR
@@ -249,7 +256,21 @@ def index():
249256
return redirect(url_for('dropbox_auth_request'))
250257
else:
251258
archive_to_dropbox = True
252-
259+
260+
#----Check for and Retrieve Oura token----
261+
if request.form.get('ouraCheckbox') is not None:
262+
if oura_refresh_token is None:
263+
db_exists = check_user_db_exists(gc_username,gc_password,db_host,superuser_un,superuser_pw,encr_pass)
264+
if db_exists == True:
265+
oura_token_exists, oura_token_from_db = check_oura_token_exists(gc_username,db_host,db_name,superuser_un,superuser_pw,encr_pass)
266+
if oura_token_exists == True: # token exists in database and it is not None
267+
oura_refresh_token = oura_token_from_db
268+
print('Refresh Token: {}'.format(oura_refresh_token))
269+
else:
270+
return redirect(url_for('oura_auth_request'))
271+
else:
272+
return redirect(url_for('oura_auth_request'))
273+
253274
# CLEANUP BEFORE DOWNLOAD -----------------
254275

255276
#----Delete Files and DB Data variables----
@@ -384,7 +405,8 @@ def index():
384405
#PG:Call to execute "GC login" script
385406
if gc_username is not None:
386407
try:
387-
gc_agent = gc.login(gc_username, gc_password, mfp_username,db_host,superuser_un,superuser_pw,dbx_auth_token,encr_pass,save_pwd)
408+
gc_agent = gc.login(gc_username, gc_password, mfp_username,db_host,superuser_un,superuser_pw,dbx_auth_token,oura_refresh_token,encr_pass,save_pwd)
409+
session['oura_refresh_token'] = None
388410
gc_user_update(gc_username,db_host,db_name,superuser_un,superuser_pw,encrypted_superuser_pw,auto_synch_checkbox,encr_pass) #----Set Auto_Synch switch----
389411
gc_login_progress = 'Login to GC successfull'
390412
with StdoutRedirection(gc_username):
@@ -455,6 +477,11 @@ def index():
455477
time.sleep(1)
456478
with ErrorStdoutRedirection(gc_username):
457479
print((str(datetime.datetime.now()) + ' ' + gc_fit_well_progress))
480+
481+
#TODO:
482+
#PG:Call to execute "Parse and insert Oura wellness data" script
483+
#TODO
484+
458485
#PG:Call to execute "Parse and insert JSON wellness data" script
459486
try:
460487
gc_json_well_progress = 'GC JSON wellness download started'
@@ -764,12 +791,48 @@ def dropbox_auth_request():
764791
pass
765792

766793
@app.route("/dropbox_confirm")
767-
def dropbox_confirm():
768-
token = dropbox_auth_finish(session,request)
769-
session['dbx_auth_token'] = token
770-
continue_btn = 'delete'
771-
flash(' You have successfuly authenticated with Dropbox. Click "Continue" to proceed with download.','success')
772-
return redirect(url_for('index',continue_btn = continue_btn))
794+
def dropbox_confirm():
795+
try:
796+
token = dropbox_auth_finish(session,request)
797+
session['dbx_auth_token'] = token
798+
continue_btn = 'delete'
799+
flash(' You have successfuly authenticated with Dropbox. Click "Continue" to proceed with download.','success')
800+
return redirect(url_for('index',continue_btn = continue_btn))
801+
except Exception as e:
802+
session['dbx_auth_token'] = None
803+
flash(' There was a problem authenticating with Dropbox.','warning')
804+
return redirect(url_for('index'))
805+
806+
807+
@app.route('/oura_auth_request')
808+
def oura_auth_request():
809+
try:
810+
oura_session = OAuth2Session(OURA_CLIENT_ID)
811+
authorization_url, state = oura_session.authorization_url(OURA_AUTH_URL)
812+
session['oura_oauth_state'] = state
813+
return redirect(authorization_url, 301)
814+
except Exception as e:
815+
pass
816+
817+
@app.route('/oura_confirm')# Must match Redirect URI specified in https://cloud.ouraring.com/oauth/applications.
818+
def oura_confirm():
819+
oura_session = OAuth2Session(OURA_CLIENT_ID, state=session['oura_oauth_state'])
820+
try:
821+
response = oura_session.fetch_token(
822+
OURA_TOKEN_URL,
823+
client_secret=OURA_CLIENT_SECRET,
824+
authorization_response=request.url)
825+
826+
oura_refresh_token = response['refresh_token']
827+
828+
session['oura_refresh_token'] = oura_refresh_token
829+
continue_btn = 'delete'
830+
flash(' You have successfuly authenticated with Oura. Click "Continue" to proceed with download.','success')
831+
return redirect(url_for('index',continue_btn = continue_btn))
832+
except Exception as e:
833+
session['oura_refresh_token'] = None
834+
flash(' There was a problem authenticating with Oura.','warning')
835+
return redirect(url_for('index'))
773836

774837
@app.route("/process_running", methods = ['GET','POST'])
775838
def process_running():

src/database_ini_parser.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,23 @@ def config(filename, section, encr_pass=None):
9191
db[param[0]] = ""
9292
else:
9393
db[param[0]] = param[1]
94+
elif section == 'oura':
95+
params = parser.items(section)
96+
for param in params:
97+
if param[0] == 'oura_client_id':
98+
try:
99+
decrypted_param = decrypt(base64.b64decode(param[1]), encr_pass)
100+
db[param[0]] = str(decrypted_param)
101+
except:
102+
db[param[0]] = ""
103+
elif param[0] == 'oura_client_secret':
104+
try:
105+
decrypted_param = decrypt(base64.b64decode(param[1]), encr_pass)
106+
db[param[0]] = str(decrypted_param)
107+
except:
108+
db[param[0]] = ""
109+
else:
110+
db[param[0]] = param[1]
94111
elif section == 'anticaptcha':
95112
params = parser.items(section)
96113
for param in params:

src/db_auto_sync.py

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,9 @@ def retrieve_decrypt_creds(synch_req_db_list,encr_pass):
9090

9191
dbx_encr_token = None
9292
dbx_decr_token = None
93-
93+
94+
oura_encr_token = None
95+
oura_decr_token = None
9496

9597
glimp_encr_export_link = None
9698
glimp_decr_export_link = None
@@ -103,7 +105,7 @@ def retrieve_decrypt_creds(synch_req_db_list,encr_pass):
103105

104106
sql_get_creds = """
105107
SELECT
106-
gc_email,gc_password,mfp_username,mfp_password,diasend_username,diasend_password,dropbox_access_token,glimp_export_link,libreview_export_link,mm_export_link
108+
gc_email,gc_password,mfp_username,mfp_password,diasend_username,diasend_password,dropbox_access_token,glimp_export_link,libreview_export_link,mm_export_link,oura_refresh_token
107109
FROM
108110
athlete;
109111
"""
@@ -172,6 +174,7 @@ def retrieve_decrypt_creds(synch_req_db_list,encr_pass):
172174
glimp_encr_export_link=result[7]
173175
libreview_encr_export_link=result[8]
174176
mm_encr_export_link=result[9]
177+
oura_encr_token=result[10]
175178

176179
#Now decrypt (gc_encr_pw,mfp_encr_pw,dbx_encr_token and others)
177180
if gc_encr_pw is not None:
@@ -181,21 +184,23 @@ def retrieve_decrypt_creds(synch_req_db_list,encr_pass):
181184
if cgm_encr_pw is not None:
182185
cgm_decr_pw = decrypt(base64.b64decode(cgm_encr_pw), encr_pass)
183186
if dbx_encr_token is not None:
184-
dbx_decr_token = decrypt(base64.b64decode(dbx_encr_token), encr_pass)
187+
dbx_decr_token = decrypt(base64.b64decode(dbx_encr_token), encr_pass)
185188
if glimp_encr_export_link is not None:
186189
glimp_decr_export_link = decrypt(base64.b64decode(glimp_encr_export_link), encr_pass)
187190
if libreview_encr_export_link is not None:
188191
libreview_decr_export_link = decrypt(base64.b64decode(libreview_encr_export_link), encr_pass)
189192
if mm_encr_export_link is not None:
190-
mm_decr_export_link = decrypt(base64.b64decode(mm_encr_export_link), encr_pass)
193+
mm_decr_export_link = decrypt(base64.b64decode(mm_encr_export_link), encr_pass)
194+
if oura_encr_token is not None:
195+
oura_decr_token = decrypt(base64.b64decode(oura_encr_token), encr_pass)
191196

192197
###Execute auto synch from "main_data_autosynch.py"###
193-
auto_synch(db, db_host, superuser_un, superuser_pw, gc_un, gc_decr_pw, mfp_un, mfp_decr_pw, cgm_un, cgm_decr_pw, glimp_decr_export_link, libreview_decr_export_link, mm_decr_export_link, dbx_decr_token, encr_pass)
194-
198+
auto_synch(db, db_host, superuser_un, superuser_pw, gc_un, gc_decr_pw, mfp_un, mfp_decr_pw, cgm_un, cgm_decr_pw, glimp_decr_export_link, libreview_decr_export_link, mm_decr_export_link, dbx_decr_token, oura_decr_token, encr_pass)
199+
195200
except (Exception, psycopg2.DatabaseError) as error:
196201
with ConsolidatedProgressStdoutRedirection():
197-
print('Autosynch DB Error 2: '+str(error))
202+
print(('Autosynch DB Error: '+str(error)))
198203

199204
finally:
200205
if conn is not None:
201-
conn.close()
206+
conn.close()

0 commit comments

Comments
 (0)