From e80527c688ae570205a793f2778cdc784692033d Mon Sep 17 00:00:00 2001 From: Sander Roosendaal Date: Thu, 10 Jun 2021 08:53:35 +0200 Subject: [PATCH] solving c2 imports, forbidding free coaches access to imports --- rowers/rower_rules.py | 5 +++++ rowers/tests/test_imports.py | 20 ++++++++++++++++++++ rowers/urls.py | 2 ++ rowers/views/importviews.py | 36 ++++++++++++++++++++++++++++++++++-- rowers/views/statements.py | 2 +- rowers/views/workoutviews.py | 3 +++ 6 files changed, 65 insertions(+), 3 deletions(-) diff --git a/rowers/rower_rules.py b/rowers/rower_rules.py index 757e23e4..02920408 100644 --- a/rowers/rower_rules.py +++ b/rowers/rower_rules.py @@ -110,6 +110,10 @@ def is_staff(user): # pragma: no cover def is_coach(user): return user.rower.rowerplan in ['coach','freecoach'] +@rules.predicate +def is_not_freecoach(user): + return user.rower.rowerplan != 'freecoach' + def is_paid_coach(user): return user.rower.rowerplan == 'coach' @@ -324,6 +328,7 @@ rules.add_perm('rower.add_plan',can_plan_user) # replaces checkaccessplanuser rules.add_perm('rower.is_coach',is_coach_user) # replaces checkaccessuser rules.add_perm('rower.is_pro',ispromember) rules.add_perm('rower.is_staff',is_staff) +rules.add_perm('rower.is_not_freecoach',is_not_freecoach) # WORKOUT permissions diff --git a/rowers/tests/test_imports.py b/rowers/tests/test_imports.py index d81d07e7..81688f12 100644 --- a/rowers/tests/test_imports.py +++ b/rowers/tests/test_imports.py @@ -373,6 +373,26 @@ class C2Objects(DjangoTestCase): self.assertEqual(got, want) self.assertEqual(workoutdate,'2021-05-26') + def test_c2_import_54838157(self): + with open('rowers/tests/testdata/c2_54838157.json','r') as infile: + data = json.load(infile) + ( + startdatetime, + starttime, + workoutdate, + duration, + starttimeunix, + timezone + ) = utils.get_startdatetime_from_c2data(data) + + + self.assertEqual(str(timezone),'America/Los_Angeles') + + got = arrow.get(startdatetime).isoformat() + want = arrow.get('2021-06-06 17:14:41.400000-07:00').isoformat() + + self.assertEqual(got, want) + self.assertEqual(workoutdate,'2021-06-06') @patch('rowers.c2stuff.requests.get', side_effect=mocked_requests) diff --git a/rowers/urls.py b/rowers/urls.py index 2b5d1cf2..c308e6a4 100644 --- a/rowers/urls.py +++ b/rowers/urls.py @@ -497,11 +497,13 @@ urlpatterns = [ re_path(r'^workout/c2import/all/(?P\d+)/$',views.workout_getc2workout_all,name='workout_getc2workout_all'), re_path(r'^workout/nkimport/$',views.workout_nkimport_view,name='workout_nkimport_view'), re_path(r'^workout/nkimport/(?P\d+)/(?P\d+)/$',views.workout_nkimport_view,name='workout_nkimport_view'), + re_path(r'^workout/nkimport/user/(?P\d+)/$',views.workout_nkimport_view,name='workout_nkimport_view'), re_path(r'^workout/nkimport/all/$',views.workout_getnkworkout_all,name='workout_getnkworkout_all'), re_path(r'^workout/nkimport/all/(?P\d+-\d+-\d+)/(?P\d+-\d+-\d+)/$',views.workout_getnkworkout_all, name='workout_getnkworkout_all'), re_path(r'^workout/rp3import/(?P\d+)/$',views.workout_getrp3importview, name='workout_getrp3importview'), + re_path(r'^workout/rp3import/user/(?P\d+)/$',views.workout_rp3import_view,name='workout_rp3import_view'), re_path(r'^workout/rp3import/all/$',views.workout_getrp3workout_all,name='workout_getrp3workout_all'), re_path(r'^workout/(?P\w+.*)import/(?P\d+)/$',views.workout_getimportview,name='workout_getimportview'), re_path(r'^workout/(?P\w+.*)import/(?P\d+)/async/$',views.workout_getimportview,{'do_async':True},name='workout_getimportview'), diff --git a/rowers/views/importviews.py b/rowers/views/importviews.py index ec78c966..85fdd29f 100644 --- a/rowers/views/importviews.py +++ b/rowers/views/importviews.py @@ -537,9 +537,16 @@ def workout_getnkworkout_all(request,startdatestring='',enddatestring=''): @login_required() @permission_required('rower.is_coach',fn=get_user_by_userid, raise_exception=True) +@permission_required('rower.is_not_freecoach',fn=get_user_by_userid, raise_exception=True) def workout_nkimport_view(request,userid=0,after=0,before=0): startdate,enddate = get_dates_timeperiod(request,defaulttimeperiod='last30') r = getrequestrower(request,userid=userid) + if r.user != request.user: + print(r,r.user,request.user) + messages.error(request,'You can only access your own workouts on the NK Logbook, not those of your athletes') + url = reverse('workout_nkimport_view',kwargs={'userid':request.user.id}) + return HttpResponseRedirect(url) + try: thetoken = nk_open(request.user) except NoTokenError: # pragma: no cover @@ -908,8 +915,14 @@ def workout_rp3import_view(request,userid=0): # The page where you select which Strava workout to import @login_required() @permission_required('rower.is_coach',fn=get_user_by_userid,raise_exception=True) +@permission_required('rower.is_not_freecoach',fn=get_user_by_userid, raise_exception=True) def workout_stravaimport_view(request,message="",userid=0): r = getrequestrower(request,userid=userid) + if r.user != request.user: + print(r,r.user,request.user) + messages.error(request,'You can only access your own workouts on the NK Logbook, not those of your athletes') + url = reverse('workout_stravaimport_view',kwargs={'userid':request.user.id}) + return HttpResponseRedirect(url) #if r.user != request.user: # messages.info(request,"You cannot import other people's workouts from Strava") try: @@ -1260,6 +1273,7 @@ def garmin_details_view(request): # the page where you select which Polar workout to Import @login_required() @permission_required('rower.is_coach',fn=get_user_by_userid,raise_exception=True) +@permission_required('rower.is_not_freecoach',fn=get_user_by_userid, raise_exception=True) def workout_polarimport_view(request,userid=0): # pragma: no cover exercises = polarstuff.get_polar_workouts(request.user) workouts = [] @@ -1318,8 +1332,14 @@ def workout_polarimport_view(request,userid=0): # pragma: no cover # The page where you select which SportTracks workout to import @login_required() @permission_required('rower.is_coach',fn=get_user_by_userid,raise_exception=True) +@permission_required('rower.is_not_freecoach',fn=get_user_by_userid, raise_exception=True) def workout_sporttracksimport_view(request,message="",userid=0): - + r = getrequestrower(request,userid=userid) + if r.user != request.user: + print(r,r.user,request.user) + messages.error(request,'You can only access your own workouts on the NK Logbook, not those of your athletes') + url = reverse('workout_sporttracksimport_view',kwargs={'userid':request.user.id}) + return HttpResponseRedirect(url) res = sporttracksstuff.get_sporttracks_workout_list(request.user) if (res.status_code != 200): @@ -1339,7 +1359,7 @@ def workout_sporttracksimport_view(request,message="",userid=0): return HttpResponseRedirect(url) workouts = [] - r = getrower(request.user) + stids = [int(getidfromuri(item['uri'])) for item in res.json()['items']] knownstids = uniqify([ w.uploadedtosporttracks for w in Workout.objects.filter(user=r) @@ -1469,9 +1489,15 @@ def workout_getrp3workout_all(request): # pragma: no cover # List of workouts available on Concept2 logbook - for import @login_required() @permission_required('rower.is_coach',fn=get_user_by_userid,raise_exception=True) +@permission_required('rower.is_not_freecoach',fn=get_user_by_userid, raise_exception=True) def workout_c2import_view(request,page=1,userid=0,message=""): r = getrequestrower(request,userid=userid) + if r.user != request.user: + print(r,r.user,request.user) + messages.error(request,'You can only access your own workouts on the NK Logbook, not those of your athletes') + url = reverse('workout_c2import_view',kwargs={'userid':request.user.id}) + return HttpResponseRedirect(url) try: thetoken = c2_open(request.user) @@ -1581,8 +1607,14 @@ importsources = { } @login_required() +@permission_required('rower.is_not_freecoach',fn=get_user_by_userid, raise_exception=True) def workout_getrp3importview(request,externalid): r = getrequestrower(request) + if r.user != request.user: + print(r,r.user,request.user) + messages.error(request,'You can only access your own workouts on the NK Logbook, not those of your athletes') + url = reverse('workout_rp3import_view',kwargs={'userid':request.user.id}) + return HttpResponseRedirect(url) token = rp3stuff.rp3_open(r.user) startdatetime = request.GET.get('startdatetime') diff --git a/rowers/views/statements.py b/rowers/views/statements.py index b3d39580..fec0ddb4 100644 --- a/rowers/views/statements.py +++ b/rowers/views/statements.py @@ -1194,7 +1194,7 @@ from rowers.utils import ( str2bool,range_to_color_hex,absolute,myqueue,get_call, calculate_age,rankingdistances,rankingdurations, my_dict_from_instance,wavg,NoTokenError, - request_is_ajax + request_is_ajax,dologging ) import rowers.datautils as datautils diff --git a/rowers/views/workoutviews.py b/rowers/views/workoutviews.py index 34b50c72..2206b859 100644 --- a/rowers/views/workoutviews.py +++ b/rowers/views/workoutviews.py @@ -4913,6 +4913,9 @@ def workout_upload_api(request): w.starttime = w.startdatetime.strftime('%H:%M:%S') w.timezone = timezone + dologging('debuglog.log','Start Date Time set to {s}'.format(s=w.startdatetime)) + dologging('debuglog.log','Workout Date set to {s}'.format(s=w.workoutdate)) + dologging('debuglog.log','Time zone set to {zone}'.format(zone=w.timezone)) w.save()