From 292e70376603bb5b373a07cbcdef1214f0b5b993 Mon Sep 17 00:00:00 2001 From: Sander Roosendaal Date: Wed, 13 Feb 2019 21:42:08 +0100 Subject: [PATCH] passing all but one test --- rowers/interactiveplots.py | 2 +- rowers/templates/teamresponseemail.html | 2 +- rowers/tests/test_aworkouts.py | 51 ++++---- rowers/tests/test_flexchart.py | 10 +- rowers/tests/test_imports.py | 5 +- rowers/tests/test_plans.py | 2 +- rowers/tests/test_simplefunctions.py | 2 +- rowers/tests/test_urls.py | 6 +- rowers/tests/testdata/testdata.csv.gz | Bin 11426 -> 12525 bytes rowers/urls.py | 43 ++++--- rowers/views/importviews.py | 51 ++++---- rowers/views/racesviews.py | 2 +- rowers/views/statements.py | 8 +- rowers/views/workoutviews.py | 156 +++++++++++++----------- 14 files changed, 188 insertions(+), 152 deletions(-) diff --git a/rowers/interactiveplots.py b/rowers/interactiveplots.py index 271455e8..b17fdc7d 100644 --- a/rowers/interactiveplots.py +++ b/rowers/interactiveplots.py @@ -2230,7 +2230,7 @@ def interactive_chart(id=0,promember=0,intervaldata = {}): intervaldf['itime'] = intervaldf['itime']*1.e3 intervaldf['time'] = intervaldf['itime'].cumsum() intervaldf['time'] = intervaldf['time'].shift(1) - intervaldf.ix[0,'time'] = 0 + intervaldf.loc[:,'time'].iloc[0] = 0 intervaldf['time_r'] = intervaldf['time'] +intervaldf['itime'] intervaldf['value'] = 100 mask = intervaldf['itype'] == 3 diff --git a/rowers/templates/teamresponseemail.html b/rowers/templates/teamresponseemail.html index 4144b282..dd6b5cda 100644 --- a/rowers/templates/teamresponseemail.html +++ b/rowers/templates/teamresponseemail.html @@ -14,7 +14,7 @@ You can read the comment here:

- + {{ siteurl }}{{ commentlink }}

diff --git a/rowers/tests/test_aworkouts.py b/rowers/tests/test_aworkouts.py index 5e705614..534aa8a4 100644 --- a/rowers/tests/test_aworkouts.py +++ b/rowers/tests/test_aworkouts.py @@ -125,7 +125,7 @@ class WorkoutViewTest(TestCase): login = self.c.login(username=self.u.username, password=self.password) self.assertTrue(login) - url = reverse('workout_forcecurve_view',kwargs={'id':self.wwater.id}) + url = reverse('workout_forcecurve_view',kwargs={'id':encoder.encode_hex(self.wwater.id)}) response = self.c.get(url) self.assertEqual(response.status_code,200) @@ -186,7 +186,7 @@ class WorkoutViewTest(TestCase): expected_url = reverse(self.r.defaultlandingpage, kwargs = { - 'id':12 + 'id':encoder.encode_hex(12) }) self.assertRedirects(response, @@ -209,7 +209,7 @@ class WorkoutViewTest(TestCase): response = self.c.get('/') url = reverse('multi_compare_view',kwargs={ 'userid':self.u.id, - 'id':self.werg1.id, + 'id':encoder.encode_hex(self.werg1.id), }) print url @@ -241,13 +241,13 @@ class WorkoutViewTest(TestCase): login = self.c.login(username=self.u.username, password=self.password) self.assertTrue(login) - url = reverse('workout_view',kwargs={'id':self.wwater.id}) + url = reverse('workout_view',kwargs={'id':encoder.encode_hex(self.wwater.id)}) response = self.c.get(url) self.assertEqual(response.status_code,200) url = reverse('workout_downloadmetar_view',kwargs={ - 'id': self.wwater.id, + 'id': encoder.encode_hex(self.wwater.id), 'airportcode': 'LKHO' } ) @@ -256,7 +256,7 @@ class WorkoutViewTest(TestCase): self.assertEqual(response.status_code,200) url = reverse('workout_downloadwind_view',kwargs={ - 'id': self.wwater.id, + 'id': encoder.encode_hex(self.wwater.id), } ) @@ -270,14 +270,14 @@ class WorkoutViewTest(TestCase): self.assertTrue(login) - url = reverse('workout_smoothenpace_view',kwargs={'id':self.wwater.id}) + url = reverse('workout_smoothenpace_view',kwargs={'id':encoder.encode_hex(self.wwater.id)}) response = self.c.get(url,follow=True) self.assertEqual(response.status_code,200) expected_url = reverse(self.r.defaultlandingpage, kwargs = { - 'id':self.wwater.id + 'id':encoder.encode_hex(self.wwater.id) } ) @@ -285,14 +285,14 @@ class WorkoutViewTest(TestCase): expected_url=expected_url, status_code=302,target_status_code=200) - url = reverse('workout_undo_smoothenpace_view',kwargs={'id':self.wwater.id}) + url = reverse('workout_undo_smoothenpace_view',kwargs={'id':encoder.encode_hex(self.wwater.id)}) response = self.c.get(url,follow=True) self.assertEqual(response.status_code,200) expected_url = reverse(self.r.defaultlandingpage, kwargs = { - 'id':self.wwater.id + 'id':encoder.encode_hex(self.wwater.id) } ) @@ -308,7 +308,7 @@ class WorkoutViewTest(TestCase): self.assertTrue(login) - url = reverse('workout_wind_view',kwargs={'id':self.wwater.id}) + url = reverse('workout_wind_view',kwargs={'id':encoder.encode_hex(self.wwater.id)}) response = self.c.get(url) self.assertEqual(response.status_code,200) @@ -336,7 +336,7 @@ class WorkoutViewTest(TestCase): self.assertTrue(login) - url = reverse('workout_stream_view',kwargs={'id':self.wwater.id}) + url = reverse('workout_stream_view',kwargs={'id':encoder.encode_hex(self.wwater.id)}) response = self.c.get(url) self.assertEqual(response.status_code,200) @@ -363,7 +363,7 @@ class WorkoutViewTest(TestCase): login = self.c.login(username=self.u.username, password=self.password) self.assertTrue(login) - url = reverse('instroke_view',kwargs={'id':self.winstroke.id}) + url = reverse('instroke_view',kwargs={'id':encoder.encode_hex(self.winstroke.id)}) response = self.c.get(url) self.assertEqual(response.status_code,200) @@ -380,7 +380,7 @@ class WorkoutViewTest(TestCase): self.assertTrue(login) - url = reverse('workout_otwsetpower_view',kwargs={'id':self.wwater.id}) + url = reverse('workout_otwsetpower_view',kwargs={'id':encoder.encode_hex(self.wwater.id)}) response = self.c.get(url) self.assertEqual(response.status_code,200) @@ -397,7 +397,7 @@ class WorkoutViewTest(TestCase): response = self.c.post(url,form_data,follow=True) self.assertEqual(response.status_code,200) - expected_url = reverse('workout_edit_view',kwargs={'id':self.wwater.id}) + expected_url = reverse('workout_edit_view',kwargs={'id':encoder.encode_hex(self.wwater.id)}) self.assertRedirects(response, expected_url=expected_url, @@ -410,7 +410,7 @@ class WorkoutViewTest(TestCase): self.assertTrue(login) - url = reverse('workout_comment_view',kwargs={'id':self.wwater.id}) + url = reverse('workout_comment_view',kwargs={'id':encoder.encode_hex(self.wwater.id)}) response = self.c.get(url) self.assertEqual(response.status_code,200) @@ -425,7 +425,7 @@ class WorkoutViewTest(TestCase): response = self.c.post(url,form_data,follow=True) self.assertEqual(response.status_code,200) - url = reverse('workout_unsubscribe_view',kwargs={'id':self.wwater.id}) + url = reverse('workout_unsubscribe_view',kwargs={'id':encoder.encode_hex(self.wwater.id)}) response = self.c.get(url) self.assertEqual(response.status_code,200) @@ -436,7 +436,7 @@ class WorkoutViewTest(TestCase): self.assertTrue(login) - url = reverse('workout_map_view',kwargs={'id':self.wwater.id}) + url = reverse('workout_map_view',kwargs={'id':encoder.encode_hex(self.wwater.id)}) response = self.c.get(url) self.assertEqual(response.status_code,200) @@ -448,7 +448,8 @@ class WorkoutViewTest(TestCase): login = self.c.login(username=self.u.username, password=self.password) self.assertTrue(login) - url = reverse('workout_uploadimage_view',kwargs={'id':self.werg1.id}) + url = reverse('workout_uploadimage_view', + kwargs={'id':encoder.encode_hex(self.werg1.id)}) response = self.c.get(url) self.assertEqual(response.status_code,200) @@ -466,7 +467,8 @@ class WorkoutViewTest(TestCase): response = self.c.post(url,form_data,format='multipart',follow=True) - expected_url = reverse(self.r.defaultlandingpage,kwargs={'id':self.werg1.id}) + expected_url = reverse(self.r.defaultlandingpage, + kwargs={'id':encoder.encode_hex(self.werg1.id)}) self.assertRedirects(response, expected_url=expected_url, @@ -480,7 +482,7 @@ class WorkoutViewTest(TestCase): login = self.c.login(username=self.u.username, password=self.password) self.assertTrue(login) - url = reverse('workout_split_view',kwargs={'id':self.werg1.id}) + url = reverse('workout_split_view',kwargs={'id':encoder.encode_hex(self.werg1.id)}) response = self.c.get(url) self.assertEqual(response.status_code,200) @@ -505,8 +507,9 @@ class WorkoutViewTest(TestCase): login = self.c.login(username=self.u.username, password=self.password) self.assertTrue(login) - url = reverse('workout_fusion_view',kwargs={'id1':self.werg2.id, - 'id2':self.werg2copy.id}) + url = reverse('workout_fusion_view', + kwargs={'id1':encoder.encode_hex(self.werg2.id), + 'id2':encoder.encode_hex(self.werg2copy.id)}) response = self.c.get(url) @@ -534,7 +537,7 @@ class WorkoutViewTest(TestCase): self.assertTrue(login) - url = reverse('workout_summary_edit_view',kwargs={'id':self.wwater.id}) + url = reverse('workout_summary_edit_view',kwargs={'id':encoder.encode_hex(self.wwater.id)}) response = self.c.get(url) self.assertEqual(response.status_code,200) diff --git a/rowers/tests/test_flexchart.py b/rowers/tests/test_flexchart.py index 26a7f931..0e764182 100644 --- a/rowers/tests/test_flexchart.py +++ b/rowers/tests/test_flexchart.py @@ -103,7 +103,8 @@ class WorkoutViewTest(TestCase): login = self.c.login(username=self.u.username, password=self.password) self.assertTrue(login) - url = reverse('workout_flexchart3_view',kwargs={'id':self.wwater.id}) + url = reverse('workout_flexchart3_view', + kwargs={'id':encoder.encode_hex(self.wwater.id)}) response = self.c.get(url) self.assertEqual(response.status_code,200) @@ -126,7 +127,7 @@ class WorkoutViewTest(TestCase): self.assertEqual(response.status_code,200) url = reverse('workout_flexchart3_view',kwargs={ - 'id':self.wwater.id, + 'id':encoder.encode_hex(self.wwater.id), 'xparam':'distance', 'yparam1':'hr', 'yparam2':'power' @@ -150,7 +151,8 @@ class WorkoutViewTest(TestCase): login = self.c.login(username=self.u.username, password=self.password) self.assertTrue(login) - url = reverse('workout_flexchart3_view',kwargs={'id':self.werg1.id}) + url = reverse('workout_flexchart3_view', + kwargs={'id':encoder.encode_hex(self.werg1.id)}) response = self.c.get(url) self.assertEqual(response.status_code,200) @@ -168,7 +170,7 @@ class WorkoutViewTest(TestCase): self.assertEqual(response.status_code,200) url = reverse('workout_flexchart3_view',kwargs={ - 'id':self.werg1.id, + 'id':encoder.encode_hex(self.werg1.id), 'xparam':'distance', 'yparam1':'hr', 'yparam2':'power' diff --git a/rowers/tests/test_imports.py b/rowers/tests/test_imports.py index 227577fb..28974cdb 100644 --- a/rowers/tests/test_imports.py +++ b/rowers/tests/test_imports.py @@ -431,8 +431,11 @@ class STObjects(DjangoTestCase): response = self.c.get('/rowers/workout/sporttracksimport/13/',follow=True) + expected_url = reverse('workout_edit_view', + kwargs = {'id':encoder.encode_hex(2)}) + self.assertRedirects(response, - expected_url='/rowers/workout/2/edit/', + expected_url=expected_url, status_code=302,target_status_code=200) self.assertEqual(response.status_code, 200) diff --git a/rowers/tests/test_plans.py b/rowers/tests/test_plans.py index ff464120..51395c25 100644 --- a/rowers/tests/test_plans.py +++ b/rowers/tests/test_plans.py @@ -1575,7 +1575,7 @@ class PlannedSessionsView(TestCase): url = '/rowers/sessions/{psid}/detach/{id}/'.format( psid=self.ps_time.id, - id = self.w1.id, + id = encoder.encode_hex(self.w1.id), ) response = self.c.get(url,follow=True) diff --git a/rowers/tests/test_simplefunctions.py b/rowers/tests/test_simplefunctions.py index d9250fec..be86cc16 100644 --- a/rowers/tests/test_simplefunctions.py +++ b/rowers/tests/test_simplefunctions.py @@ -74,7 +74,7 @@ class SimpleViewTest(TestCase): def test_getworkout(self): with assert_raises(Http404): - w = get_workout(123) + w = get_workout(encoder.encode_hex(123)) def test_deactivate(self): login = self.c.login(username=self.u.username, password=self.password) diff --git a/rowers/tests/test_urls.py b/rowers/tests/test_urls.py index 1f2bbcf9..e01e4d69 100644 --- a/rowers/tests/test_urls.py +++ b/rowers/tests/test_urls.py @@ -219,7 +219,7 @@ class URLTests(TestCase): '/rowers/workout/'+encoded1+'/stats/', '/rowers/workout/'+encoded1+'/stream/', # '/rowers/workout/'+encoded1+'/task/', - '/rowers/workout/'+encoded1+'/teststrokedata/', +# '/rowers/workout/'+encoded1+'/teststrokedata/', '/rowers/workout/'+encoded1+'/toggle-ranking/', '/rowers/workout/'+encoded1+'/undosmoothenpace/', '/rowers/workout/'+encoded1+'/unsubscribe/', @@ -270,6 +270,10 @@ class URLTests(TestCase): expected) html = BeautifulSoup(response.content,'html.parser') + + if 'restore' in url: + print html.find_all('a') + urls = [a['href'] for a in html.find_all('a')] for u in urls: diff --git a/rowers/tests/testdata/testdata.csv.gz b/rowers/tests/testdata/testdata.csv.gz index c60941362b0d823f0a5e18b9dd02730902c74ffb..b836d629b5998ddb5a7beb3cbec1f184b7088d51 100644 GIT binary patch literal 12525 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

E>@Zpm<_Jc%b( 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 D&vahH literal 11426 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≧H45L=aOTS%qgk;V1wi1PKj;iI4c2}S5$G_DS@M}T$s}xDsfQ_sca9yNYo=a zPCDCE?WUOLbsW;&j4N!2yBlA32(1x-az>deb;w6}&P@rx&*e-V&cRRt648*#_75Dy zT4g1C6i+RsUPhh^ASdTCo4q`y<&{)rrG&-KlAJum)%)=7#Ml|3X)%q% z$m;O-#!U@GOuUfF{g?2NW=Lgw2v)Bbg$0Klu9ZXr~pf z%YpfZTG`$e=~bC3%1urd&FKqjapk_V>r>De|-oD$0_Pzw-=hE%tE=yyMaABBi|M&FiaP37cU z(Y17#+*a*33V;R z)xD!E#a9 zpI2U%mQ+8l!&aPar|&{iKDuAb;rHu2Li9`C>~2?InU`)#95vf{sEZ}Y1|mRN^+-f;H`vLzPeU|`aXinILeml z_6@Umy|8HeT$yUSOVqKQB{>alNP_$thPdvsxiobi_d&GnRS}4kTuspSeGpva;VhX4 z!MdKqOVo8c2M%}-zc&@wilSPs2*wYZ>YShP*3`Zuxhq0HH_(sv;Hj$T2KsIft{W$~ z!kOxJ4RiW5RFNTR%q3E*XD%I&%F>Kil<7Odciz=cho2w)-bXUM7oyIF?^=jaGJS6e z=M-1j3(gYQv~icXu~a_r&9z~sn{VIn43~-1a~y|ynmEplWzJr(mKnz|?VPBl{c5_`=nIkf zmg>b!Z6tRU&+o0_oG8*$;2@T|Qi3B#by<;*k)CEpzG{S!E!-8<&fACVGQvRX8C zLid3B8q2TL)O&dt*cb!~TZeb>M5V1eKR&yyS(n@L{o#4udARu2WkvdN=i%YDkV+fZ zqw0r7moG9@9ctOwIL#|;+$PX949TKhRwO@bnU0Ox;9JCZVc&Ka&d252>F_Jgu98{j zN@e4mu<^Ft>dz{&A>EtAnQb}e+th6md{44VQBWsxJjJ$bs7`UTB=q-W00%VZ2 zh-}a_UIu>h&LZE(%M99w#bHbZxv^9O%T#KLjp$8Be4fuvnzL%Mg1vowC8V@T4ts069FTfdKzA#eG< z0^oKe4wvi7$0Xdouo&V$Yb(CxvM1pzGBz20VX+{IY)EbU2inBtSGh1UoOc#4bRUXK z3!Q08==SbR&cXia*;5LUEFUJL{XM0uXNH!$f9-?&LNGQ4nw`s&VahT4P z;=U1E=ptu}NKOmpkIu-Wqck2Pjz&1VHaPa@rIN>pqacZFNVZ)>jlSJmbR8}fYG@cc zujYUQ?L5UH__eB^)U@WM4}p!Z68r}6{x`R_8D!2CK!Me$z~7f**MM1u*k*i-}J^ z=_X!HZ+{q+Te<$)&N=RNh=|)*W{_6w?HsP&a)Zd>l|?rs+kS%A_pOtKr!aLLbbodA zY`>iF?1IO1-?x$b=e}24`@s_T5t~QKI^{d zhGg4WSh?Zx!ldc&mR-=y^4`T#O|D)clrJmi&&B?u!Sk-uoNf9pL%Ka-FB-UEU%;Zq0na)7mAJ;ls6= z!X&yO_3bUVukWcp6I~9g@hN6s<*a<}ElV-Xvr_FHoh$ptrHgHiS?$6Ef)w7K#wg`z zS9AD*)g1)_#3Z^Q_3bZk5^Zr0{sPa#EO5l}$<;pLk;UaP9DiITnAF>hTl7wEmdLW) zbPo~OT-Xi}yu9d!)VIUv^(szqr)4H}thp-a@cNZk=tiueDLgN$`y%t>`gup^;c+>} zNs$)DS+h4ckBOnkKIic6CLxJzNPYVYwuLO2q9MzbUihAKYoDvJ9_O6%k!Lk_cbpy(JRyl}NPW8umiAn4c|$bRy6E=*yutyy zx}3WCZ)(hvdQ0Vwk8$RsSJzhQ?r4Zjj-zRnkp&RWsa2Jr_=l{#bwW&{8`9W5W7bs= z;GJSAX#;l5Ykc#b%B`ze;^_DU>5im0gEF^6yOzT4)QmTH6}H=sp3b8^tUuH-Reu`W zU9hgbj+K|>RSh@ISl8OYNT<&FoaO5Jug&N3sq62plX_g_eO@tkv`!F?4sMG3Uu#H< zZbYXL2lD8_hyK(P!%#T3u4~~4Nn}I1m!UH!Cs##)$sDhuBlCP5LqjJ=l&6{KD?}dc zbL)Q`m*e&`MCR1+=+B#>41TTg4=l+X6Ozb=bZ`P{y*Z_mfp%ejMaU*F!i0cx#yqk{Yr*^us4>C9^|rso#b|I`R2 z$~O~)&OV~Mw-9_=dgO2IS*6F$I}*9kxY9SD_0MDFT?`Z1knVkHpez3O7Il9~V+2#x w5V\d+)/adddiscipline/$',views.virtualevent_addboat_view,name='virtualevent_addboat_view'), url(r'^virtualevent/(?P\d+)/withdraw/(?P\d+)/$',views.virtualevent_withdraw_view,name='virtualevent_withdraw_view'), url(r'^virtualevent/(?P\d+)/withdraw/$',views.virtualevent_withdraw_view,name='virtualevent_withdraw_view'), - url(r'^virtualevent/(?P\d+)/submit/$', + url(r'^virtualevent/(?P\b[0-9A-Fa-f]+\b)/submit/$', views.virtualevent_submit_result_view,name='virtualevent_submit_result_view'), - url(r'^virtualevent/(?P\d+)/submit/(?P\d+)/$', + url(r'^virtualevent/(?P\d+)/submit/(?P\b[0-9A-Fa-f]+\b)/$', views.virtualevent_submit_result_view,name='virtualevent_submit_result_view'), url(r'^virtualevent/(?P\d+)/disqualify/(?P\d+)/', views.virtualevent_disqualify_view,name='virtualevent_disqualify_view'), @@ -251,21 +251,32 @@ urlpatterns = [ url(r'^cumstats/$',views.cumstats,name='cumstats'), url(r'^graph/(?P\d+)/$',views.graph_show_view,name='graph_show_view'), url(r'^graph/(?P\d+)/delete/$',views.GraphDelete.as_view(),name='graph_delete'), - url(r'^workout/(?P\b[0-9A-Fa-f]+\b)/get-thumbnails/$',views.get_thumbnails,name='get_thumbnails'), - url(r'^workout/(?P\b[0-9A-Fa-f]+\b)/toggle-ranking/$',views.workout_toggle_ranking,name='workout_toggle_ranking'), - url(r'^workout/(?P\b[0-9A-Fa-f]+\b)/get-testscript/$',views.get_testscript,name='get_testscript'), + url(r'^workout/(?P\b[0-9A-Fa-f]+\b)/get-thumbnails/$',views.get_thumbnails, + name='get_thumbnails'), + url(r'^workout/(?P\b[0-9A-Fa-f]+\b)/toggle-ranking/$',views.workout_toggle_ranking, + name='workout_toggle_ranking'), + url(r'^workout/(?P\b[0-9A-Fa-f]+\b)/get-testscript/$',views.get_testscript, + name='get_testscript'), url(r'^workout/upload/team/$',views.team_workout_upload_view,name='team_workout_upload_view'), url(r'^workout/upload/$',views.workout_upload_view,name='workout_upload_view'), - url(r'^workout/(?P\b[0-9A-Fa-f]+\b)/histo/$',views.workout_histo_view,name='workout_histo_view'), + url(r'^workout/(?P\b[0-9A-Fa-f]+\b)/histo/$',views.workout_histo_view, + name='workout_histo_view'), # url(r'^workout/(?P\b[0-9A-Fa-f]+\b)/task/$',views.workout_test_task_view,name='workout_test_task_view'), - url(r'^workout/(?P\b[0-9A-Fa-f]+\b)/forcecurve/$',views.workout_forcecurve_view,name='workout_forcecurve_view'), - url(r'^workout/(?P\b[0-9A-Fa-f]+\b)/unsubscribe/$',views.workout_unsubscribe_view,name='workout_unsubscribe_view'), + url(r'^workout/(?P\b[0-9A-Fa-f]+\b)/forcecurve/$',views.workout_forcecurve_view, + name='workout_forcecurve_view'), + url(r'^workout/(?P\b[0-9A-Fa-f]+\b)/unsubscribe/$',views.workout_unsubscribe_view, + name='workout_unsubscribe_view'), # url(r'^workout/(?P\b[0-9A-Fa-f]+\b)/export/$',views.workout_export_view), - url(r'^workout/(?P\b[0-9A-Fa-f]+\b)/comment/$',views.workout_comment_view,name='workout_comment_view'), - url(r'^workout/(?P\b[0-9A-Fa-f]+\b)/emailtcx/$',views.workout_tcxemail_view,name='workout_tcxemail_view'), - url(r'^workout/(?P\b[0-9A-Fa-f]+\b)/emailgpx/$',views.workout_gpxemail_view,name='workout_gpxemail_view'), - url(r'^workout/(?P\b[0-9A-Fa-f]+\b)/emailcsv/$',views.workout_csvemail_view,name='workout_csvemail_view'), - url(r'^workout/(?P\b[0-9A-Fa-f]+\b)/csvtoadmin/$',views.workout_csvtoadmin_view,name='workout_csvtoadmin_view'), + url(r'^workout/(?P\b[0-9A-Fa-f]+\b)/comment/$',views.workout_comment_view, + name='workout_comment_view'), + url(r'^workout/(?P\b[0-9A-Fa-f]+\b)/emailtcx/$',views.workout_tcxemail_view, + name='workout_tcxemail_view'), + url(r'^workout/(?P\b[0-9A-Fa-f]+\b)/emailgpx/$',views.workout_gpxemail_view, + name='workout_gpxemail_view'), + url(r'^workout/(?P\b[0-9A-Fa-f]+\b)/emailcsv/$',views.workout_csvemail_view, + name='workout_csvemail_view'), + url(r'^workout/(?P\b[0-9A-Fa-f]+\b)/csvtoadmin/$',views.workout_csvtoadmin_view, + name='workout_csvtoadmin_view'), url(r'^ergcpdatatoadmin/(?P\d+)/(?P\d+-\d+-\d+)/(?P\d+-\d+-\d+)/$',views.otecp_toadmin_view,name='otecp_toadmin_view'), url(r'^otwcpdatatoadmin/(?P\d+)/(?P\d+-\d+-\d+)/(?P\d+-\d+-\d+)/$',views.otwcp_toadmin_view,name='otwcp_toadmin_view'), url(r'^workout/(?P\b[0-9A-Fa-f]+\b)/edit/$',views.workout_edit_view, @@ -314,7 +325,7 @@ urlpatterns = [ # keeping the old URLs for retrofit url(r'^workout/(?P\b[0-9A-Fa-f]+\b)/addtimeplot/$', views.workout_add_chart_view, - {'plotnr':'1'}), + {'plotnr':'1'},name='workout_add_chart_view'), url(r'^workout/(?P\b[0-9A-Fa-f]+\b)/adddistanceplot/$', views.workout_add_chart_view, {'plotnr':'2'},name='workout_add_chart_view'), @@ -576,8 +587,8 @@ urlpatterns = [ url(r'^sessions/(?P\d+)/edit/user/(?P\d+)/$',views.plannedsession_edit_view), url(r'^sessions/(?P\d+)/clone/user/(?P\d+)/$',views.plannedsession_clone_view), url(r'^sessions/(?P\d+)/clone/$',views.plannedsession_clone_view), - url(r'^sessions/(?P\d+)/detach/(?P\d+)/user/(?P\d+)/$',views.plannedsession_detach_view), - url(r'^sessions/(?P\d+)/detach/(?P\d+)/$',views.plannedsession_detach_view), + url(r'^sessions/(?P\d+)/detach/(?P\b[0-9A-Fa-f]+\b)/user/(?P\d+)/$',views.plannedsession_detach_view), + url(r'^sessions/(?P\d+)/detach/(?P\b[0-9A-Fa-f]+\b)/$',views.plannedsession_detach_view), url(r'^sessions/(?P\d+)/$',views.plannedsession_view, name='plannedsession_view'), url(r'^sessions/(?P\d+)/user/(?P\d+)/$',views.plannedsession_view, diff --git a/rowers/views/importviews.py b/rowers/views/importviews.py index b0891fe4..dfe4b936 100644 --- a/rowers/views/importviews.py +++ b/rowers/views/importviews.py @@ -51,7 +51,7 @@ def workout_tp_upload_view(request,id=0): url = reverse(r.defaultlandingpage, kwargs = { - 'id':str(w.id), + 'id':encoder.encode_hex(w.id), }) return HttpResponseRedirect(url) @@ -106,7 +106,7 @@ def workout_strava_upload_view(request,id=0): pass url = reverse(r.defaultlandingpage, kwargs = { - 'id':str(w.id), + 'id':encoder.encode_hex(w.id), }) response = HttpResponseRedirect(url) return response @@ -137,14 +137,14 @@ def workout_strava_upload_view(request,id=0): w.save() url = reverse(r.defaultlandingpage, kwargs = { - 'id':str(w.id), + 'id':encoder.encode_hex(w.id), }) response = HttpResponseRedirect(url) url = reverse(r.defaultlandingpage, kwargs = { - 'id':str(w.id), + 'id':encoder.encode_hex(w.id), } ) response = HttpResponseRedirect(url) @@ -156,7 +156,7 @@ def workout_strava_upload_view(request,id=0): os.remove(tcxfile) url = reverse(r.defaultlandingpage, kwargs = { - 'id':str(w.id), + 'id':encoder.encode_hex(w.id), }) response = HttpResponseRedirect(url) @@ -183,7 +183,7 @@ def workout_c2_upload_view(request,id=0): url = reverse(r.defaultlandingpage, kwargs = { - 'id':int(id) + 'id':encoder.encode_hex(w.id) }) @@ -212,7 +212,7 @@ def workout_runkeeper_upload_view(request,id=0): messages.error(request,message) url = reverse(r.defaultlandingpage, kwargs = { - 'id':str(w.id), + 'id':id, }) return HttpResponseRedirect(url) @@ -235,7 +235,8 @@ def workout_runkeeper_upload_view(request,id=0): runkeeperid = runkeeperstuff.getidfromresponse(response) w.uploadedtorunkeeper = runkeeperid w.save() - url = reverse('workout_edit_view', kwargs={'id':w.id}) + url = reverse('workout_edit_view', + kwargs={'id':encoder.encode_hex(w.id)}) return HttpResponseRedirect(url) else: @@ -249,7 +250,7 @@ def workout_runkeeper_upload_view(request,id=0): url = reverse(r.defaultlandingpage, kwargs = { - 'id':str(w.id), + 'id':encoder.encode_hex(w.id), }) return HttpResponseRedirect(url) @@ -275,7 +276,7 @@ def workout_underarmour_upload_view(request,id=0): messages.error(request,message) url = reverse(r.defaultlandingpage, kwargs = { - 'id':str(w.id), + 'id':encoder.encode_hex(w.id), }) return HttpResponseRedirect(url) @@ -300,7 +301,7 @@ def workout_underarmour_upload_view(request,id=0): underarmourid = underarmourstuff.getidfromresponse(response) w.uploadedtounderarmour = underarmourid w.save() - url = reverse('workout_edit_view',kwargs={'id':w.id}) + url = reverse('workout_edit_view',kwargs={'id':encoder.encode_hex(w.id)}) return HttpResponseRedirect(url) else: @@ -313,7 +314,7 @@ def workout_underarmour_upload_view(request,id=0): url = reverse(r.defaultlandingpage, kwargs = { - 'id':str(w.id), + 'id':encoder.encode_hex(w.id), }) return HttpResponseRedirect(url) @@ -340,7 +341,7 @@ def workout_sporttracks_upload_view(request,id=0): messages.error(request,message) url = reverse(r.defaultlandingpage, kwargs = { - 'id':str(w.id), + 'id':encoder.encode_hex(w.id), }) return HttpResponseRedirect(url) @@ -367,7 +368,7 @@ def workout_sporttracks_upload_view(request,id=0): message = "Upload to SportTracks was successful" messages.info(request,message) - url = reverse('workout_edit_view',kwargs={'id':w.id}) + url = reverse('workout_edit_view',kwargs={'id':encoder.encode_hex(w.id)}) return HttpResponseRedirect(url) else: s = response @@ -379,7 +380,7 @@ def workout_sporttracks_upload_view(request,id=0): url = reverse(r.defaultlandingpage, kwargs = { - 'id':str(w.id), + 'id':encoder.encode_hex(w.id), }) return HttpResponseRedirect(url) @@ -965,7 +966,7 @@ def workout_stravaimport_view(request,message="",userid=0): 'name':'Workouts' }, { - 'url':reverse(workout_stravaimport_view), + 'url':reverse('workout_stravaimport_view'), 'name':'Strava' }, ] @@ -1021,7 +1022,7 @@ def workout_runkeeperimport_view(request,message="",userid=0): 'name':'Workouts' }, { - 'url':reverse(workout_runkeeperimport_view), + 'url':reverse('workout_runkeeperimport_view'), 'name':'Runkeeper' } ] @@ -1073,7 +1074,7 @@ def workout_underarmourimport_view(request,message="",userid=0): 'name':'Workouts' }, { - 'url':reverse(workout_c2import_view), + 'url':reverse('workout_c2import_view'), 'name':'Concept2' }, ] @@ -1126,7 +1127,7 @@ def workout_polarimport_view(request,userid=0): 'name':'Workouts' }, { - 'url':reverse(workout_polarimport_view), + 'url':reverse('workout_polarimport_view'), 'name':'Polar' }, ] @@ -1198,7 +1199,7 @@ def workout_sporttracksimport_view(request,message="",userid=0): 'name':'Workouts' }, { - 'url':reverse(workout_sporttracksimport_view), + 'url':reverse('workout_sporttracksimport_view'), 'name':'SportTracks' }, ] @@ -1343,11 +1344,11 @@ def workout_c2import_view(request,page=1,userid=0,message=""): 'name':'Workouts' }, { - 'url':reverse(workout_c2import_view), + 'url':reverse('workout_c2import_view'), 'name':'Concept2' }, { - 'url':reverse(workout_c2import_view,kwargs={'page':page}), + 'url':reverse('workout_c2import_view',kwargs={'page':page}), 'name':'Page '+str(page) } ] @@ -1445,7 +1446,7 @@ def workout_getimportview(request,externalid,source = 'c2'): messages.info(request,message) url = reverse(r.defaultlandingpage, kwargs = { - 'id':int(id), + 'id':encoder.encode_hex(w.id), }) return HttpResponseRedirect(url) @@ -1458,7 +1459,7 @@ def workout_getimportview(request,externalid,source = 'c2'): source=source, workoutsource=source) - w = get_workout(id) + w = get_workout(encoder.encode_hex(id)) if 'workout' in data: if 'splits' in data['workout']: @@ -1516,7 +1517,7 @@ def workout_getimportview(request,externalid,source = 'c2'): url = reverse(r.defaultlandingpage, kwargs = { - 'id':int(id) + 'id':encoder.encode_hex(w.id) }) return HttpResponseRedirect(url) diff --git a/rowers/views/racesviews.py b/rowers/views/racesviews.py index e7addf43..438f9033 100644 --- a/rowers/views/racesviews.py +++ b/rowers/views/racesviews.py @@ -2251,7 +2251,7 @@ def virtualevent_submit_result_view(request,id=0,workoutid=0): else: if workoutid: - workoutdata['initial'] = workoutid + workoutdata['initial'] = encoder.decode_hex(workoutid) w_form = WorkoutRaceSelectForm(workoutdata,entries) diff --git a/rowers/views/statements.py b/rowers/views/statements.py index ee597981..9c17a7f4 100644 --- a/rowers/views/statements.py +++ b/rowers/views/statements.py @@ -30,6 +30,7 @@ import cgi from icalendar import Calendar, Event import rowers.braintreestuff as braintreestuff import rowers.payments as payments +from rowers.opaque import encoder from django.shortcuts import render from django.template.loader import render_to_string @@ -258,13 +259,13 @@ def getfavorites(r,row): def get_workout_default_page(request,id): if request.user.is_anonymous(): - return reverse('workout_view',kwargs={'id':str(id)}) + return reverse('workout_view',kwargs={'id':id}) else: r = Rower.objects.get(user=request.user) if r.defaultlandingpage == 'workout_edit_view': - return reverse('workout_edit_view',kwargs={'id':str(id)}) + return reverse('workout_edit_view',kwargs={'id':id}) else: - return reverse('workout_workflow_view',kwargs={'id':str(id)}) + return reverse('workout_workflow_view',kwargs={'id':id}) def getrequestrower(request,rowerid=0,userid=0,notpermanent=False): @@ -318,6 +319,7 @@ def getrower(user): def get_workout(id): try: + id = encoder.decode_hex(id) w = Workout.objects.get(id=id) except Workout.DoesNotExist: raise Http404("Workout doesn't exist") diff --git a/rowers/views/workoutviews.py b/rowers/views/workoutviews.py index 8f5aa617..f97de731 100644 --- a/rowers/views/workoutviews.py +++ b/rowers/views/workoutviews.py @@ -60,7 +60,7 @@ def workout_forcecurve_view(request,id=0,workstrokesonly=False): 'the_div':div, 'js_res': js_resources, 'css_res':css_resources, - 'id':int(id), + 'id':id, 'mayedit':mayedit, 'workstrokesonly': not workstrokesonly, 'teams':get_my_teams(request.user), @@ -126,7 +126,7 @@ def workout_histo_view(request,id=0): 'workout':w, 'rower':r, 'the_div':div, - 'id':int(id), + 'id':id, 'mayedit':mayedit, 'teams':get_my_teams(request.user), }) @@ -248,7 +248,7 @@ def addmanual_view(request): url = reverse( 'workout_edit_view', - kwargs={'id':id} + kwargs={'id':encoder.encode_hex(id)} ) return HttpResponseRedirect(url) else: @@ -371,14 +371,14 @@ def workout_recalcsummary_view(request,id=0): messages.info(request,successmessage) url = reverse('workout_edit_view', kwargs = { - 'id':int(id), + 'id':id, }) else: message = "Something went wrong. Could not update summary" messages.error(request,message) url = reverse('workout_edit_view', kwargs = { - 'id':int(id), + 'id':id, }) return HttpResponseRedirect(url) @@ -419,7 +419,7 @@ def workouts_join_view(request): url = reverse(r.defaultlandingpage, kwargs = { - 'id':int(id), + 'id':encoder.encode_hex(id), }) return HttpResponseRedirect(url) @@ -740,7 +740,7 @@ def team_comparison_select(request, if not checkworkoutuser(request.user,firstworkout): raise PermissionDenied("You are not allowed to sue this workout") - firstworkoutquery = Workout.objects.filter(id=id) + firstworkoutquery = Workout.objects.filter(id=encoder.decode_hex(id)) workouts = firstworkoutquery | workouts else: firstworkout = None @@ -856,7 +856,7 @@ def virtualevent_compare_view(request,id=0): workouts = [] for id in workoutids: try: - workouts.append(Workout.objects.get(id=id)) + workouts.append(Workout.objects.get(id=encode.decode_hex(id))) except Workout.DoesNotExist: pass @@ -888,7 +888,7 @@ def virtualevent_compare_view(request,id=0): workouts = [] for id in workoutids: try: - workouts.append(Workout.objects.get(id=id)) + workouts.append(Workout.objects.get(id=encoded.decode_hex(id))) except Workout.DoesNotExist: pass @@ -989,7 +989,8 @@ def plannedsession_compare_view(request,id=0,userid=0): request.session['ps'] = ps.id if ids: - url = reverse('multi_compare_view',kwargs={'userid':userid,'id':ids[0]}) + url = reverse('multi_compare_view', + kwargs={'userid':userid,'id':encoder.encode_hex(ids[0])}) else: url = reverse('plannedsession_view',kwargs={'id':ps.id}) @@ -1400,10 +1401,13 @@ def workout_fusion_list(request,id=0,message='',successmessage='', s = enddate enddate = startdate startdate = s + + if id: + theid = encoder.decode_hex(id) workouts = Workout.objects.filter(user=r, startdatetime__gte=startdate, - startdatetime__lte=enddate).order_by("-date", "-starttime").exclude(id=id) + startdatetime__lte=enddate).order_by("-date", "-starttime").exclude(id=theid) query = request.GET.get('q') if query: @@ -1438,7 +1442,7 @@ def workout_fusion_list(request,id=0,message='',successmessage='', 'name':'Workouts' }, { - 'url':get_workout_default_page(request,row.id), + 'url':get_workout_default_page(request,encoder.encode_hex(row.id)), 'name': row.name }, { @@ -1449,7 +1453,7 @@ def workout_fusion_list(request,id=0,message='',successmessage='', ] return render(request, 'fusion_list.html', - {'id':int(id), + {'id':id, 'workout':row, 'rower':r, 'searchform':searchform, @@ -1474,7 +1478,7 @@ def workout_view(request,id=0): rower = None try: - row = Workout.objects.get(id=id) + row = Workout.objects.get(id=encoder.decode_hex(id)) except Workout.DoesNotExist: raise Http404("Workout doesn't exist") @@ -1499,7 +1503,7 @@ def workout_view(request,id=0): # create interactive plot - res = interactive_chart(id) + res = interactive_chart(encoder.decode_hex(id)) script = res[0] div = res[1] @@ -1591,7 +1595,7 @@ def workout_undo_smoothenpace_view( row.df[' Stroke500mPace (sec/500m)'] = 500./velo row.write_csv(filename,gzip=True) - dataprep.update_strokedata(id,row.df) + dataprep.update_strokedata(encoder.decode_hex(id),row.df) url = reverse(r.defaultlandingpage, kwargs = { @@ -1641,7 +1645,7 @@ def workout_smoothenpace_view(request,id=0,message="",successmessage=""): row.df = row.df.fillna(0) row.write_csv(filename,gzip=True) - dataprep.update_strokedata(id,row.df) + dataprep.update_strokedata(encoder.decode_hex(id),row.df) messages.info(request,'A smoothening filter was applied to your pace data') @@ -1694,7 +1698,7 @@ def workout_crewnerd_summary_view(request,id=0,message="",successmessage=""): messages.info(request,successmessage) url = reverse('workout_edit_view', kwargs = { - 'id':int(id), + 'id':id, }) return HttpResponseRedirect(url) @@ -1707,7 +1711,7 @@ def workout_crewnerd_summary_view(request,id=0,message="",successmessage=""): messages.error(request,message) url = reverse('workout_edit_view', kwargs = { - 'id':int(id), + 'id':id, }) return HttpResponseRedirect(url) else: @@ -1785,7 +1789,7 @@ def workout_downloadwind_view(request,id=0, messages.info(request,message) kwargs = { - 'id':int(id)} + 'id':id} url = reverse('workout_wind_view',kwargs=kwargs) response = HttpResponseRedirect(url) @@ -1793,7 +1797,7 @@ def workout_downloadwind_view(request,id=0, message = "No latitude/longitude data" messages.error(request,message) kwargs = { - 'id':int(id) + 'id':id } url = reverse('workout_wind_view',kwargs=kwargs) response = HttpResponseRedirect(url) @@ -1851,7 +1855,7 @@ def workout_downloadmetar_view(request,id=0, messages.info(request,message) kwargs = { - 'id':int(id)} + 'id':id} url = reverse('workout_wind_view',kwargs=kwargs) response = HttpResponseRedirect(url) @@ -1859,7 +1863,7 @@ def workout_downloadmetar_view(request,id=0, message = "No latitude/longitude data" messages.error(request,message) kwargs = { - 'id':int(id) + 'id':id } url = reverse('workout_wind_view',kwargs=kwargs) response = HttpResponseRedirect(url) @@ -1963,7 +1967,7 @@ def workout_wind_view(request,id=0,message="",successmessage=""): message = "Invalid Form" messages.error(request,message) kwargs = { - 'id':int(id) + 'id':id } url = reverse('workout_wind_view',kwargs=kwargs) response = HttpResponseRedirect(url) @@ -1972,7 +1976,7 @@ def workout_wind_view(request,id=0,message="",successmessage=""): form = UpdateWindForm() # create interactive plot - res = interactive_windchart(id,promember=1) + res = interactive_windchart(encoder.decode_hex(id),promember=1) script = res[0] div = res[1] @@ -2050,7 +2054,7 @@ def workout_stream_view(request,id=0,message="",successmessage=""): message = "Invalid Form" messages.error(request,message) kwargs = { - 'id':int(id)} + 'id':id} url = reverse('workout_wind_view',kwargs=kwargs) response = HttpResponseRedirect(url) @@ -2058,7 +2062,7 @@ def workout_stream_view(request,id=0,message="",successmessage=""): form = UpdateStreamForm() # create interactive plot - res = interactive_streamchart(id,promember=1) + res = interactive_streamchart(encoder.decode_hex(id),promember=1) script = res[0] div = res[1] @@ -2173,7 +2177,7 @@ def workout_otwsetpower_view(request,id=0,message="",successmessage=""): successmessage = 'Your calculations have been submitted. You will receive an email when they are done. You can check the status of your calculations here' messages.info(request,successmessage) kwargs = { - 'id':int(id)} + 'id':id} try: url = request.session['referer'] @@ -2187,7 +2191,7 @@ def workout_otwsetpower_view(request,id=0,message="",successmessage=""): message = "Invalid Form" messages.error(request,message) kwargs = { - 'id':int(id)} + 'id':id} url = reverse('workout_otwsetpower_view',kwargs=kwargs) response = HttpResponseRedirect(url) @@ -2366,7 +2370,7 @@ def workout_data_view(request, id=0): ] - datadf,row = dataprep.getrowdata_db(id=id) + datadf,row = dataprep.getrowdata_db(id=encoder.decode_hex(id)) datadf.sort_values(['ftime'],inplace=True) @@ -2473,14 +2477,14 @@ def workout_stats_view(request,id=0,message="",successmessage=""): # prepare data frame - datadf,row = dataprep.getrowdata_db(id=id) + datadf,row = dataprep.getrowdata_db(id=encoder.decode_hex(id)) if (checkworkoutuser(request.user,row)==False): raise PermissionDenied('Access Denied') datadf = dataprep.clean_df_stats(datadf,workstrokesonly=workstrokesonly) if datadf.empty: - datadf,row = dataprep.getrowdata_db(id=id) + datadf,row = dataprep.getrowdata_db(id=encoder.decode_hex(id)) datadf = dataprep.clean_df_stats(datadf,workstrokesonly=False) workstrokesonly=False if datadf.empty: @@ -2964,7 +2968,7 @@ def workout_flexchart3_view(request,*args,**kwargs): css_resources, workstrokesonly ) = interactive_flex_chart2( - id,xparam=xparam,yparam1=yparam1, + encoder.decode_hex(id),xparam=xparam,yparam1=yparam1, yparam2=yparam2, promember=promember,plottype=plottype, workstrokesonly=workstrokesonly @@ -2977,7 +2981,7 @@ def workout_flexchart3_view(request,*args,**kwargs): css_resources, workstrokesonly ) = interactive_flex_chart2( - id,xparam=xparam,yparam1=yparam1, + encoder.decode_hex(id),xparam=xparam,yparam1=yparam1, yparam2=yparam2, promember=promember,plottype=plottype, workstrokesonly=workstrokesonly @@ -3044,7 +3048,7 @@ def workout_flexchart3_view(request,*args,**kwargs): flexoptionsform = FlexOptionsForm(initial=initial) - row = Workout.objects.get(id=id) + row = Workout.objects.get(id=encoder.decode_hex(id)) breadcrumbs = [ { @@ -3076,7 +3080,7 @@ def workout_flexchart3_view(request,*args,**kwargs): 'js_res': js_resources, 'css_res':css_resources, 'teams':get_my_teams(request.user), - 'id':int(id), + 'id':id, 'xparam':xparam, 'yparam1':yparam1, 'yparam2':yparam2, @@ -3135,7 +3139,7 @@ def workout_otwpowerplot_view(request,id=0,message="",successmessage=""): mayedit=1 # create interactive plot - res = interactive_otw_advanced_pace_chart(id,promember=promember) + res = interactive_otw_advanced_pace_chart(encoder.decode_hex(id),promember=promember) script = res[0] div = res[1] @@ -3213,7 +3217,7 @@ def workout_comment_view(request,id=0): c.save() url = reverse('workout_comment_view', kwargs={ - 'id':id + 'id':id, }) message = '{name} says: {comment}'.format( name = request.user.first_name, @@ -3342,20 +3346,20 @@ def workout_edit_view(request,id=0,message="",successmessage=""): try: boattype = request.POST['boattype'] except KeyError: - boattype = Workout.objects.get(id=id).boattype + boattype = Workout.objects.get(id=encoder.decode_hex(id)).boattype try: privacy = request.POST['privacy'] except KeyError: - privacy = Workout.objects.get(id=id).privacy + privacy = Workout.objects.get(id=row.id).privacy try: rankingpiece = form.cleaned_data['rankingpiece'] except KeyError: - rankingpiece =- Workout.objects.get(id=id).rankingpiece + rankingpiece =- Workout.objects.get(id=row.id).rankingpiece try: duplicate = form.cleaned_data['duplicate'] except KeyError: - duplicate = Workout.objects.get(id=id).duplicate + duplicate = Workout.objects.get(id=row.id).duplicate if private: privacy = 'private' @@ -3418,7 +3422,7 @@ def workout_edit_view(request,id=0,message="",successmessage=""): return HttpResponse("Error: CSV Data File Not Found") r.rowdatetime = startdatetime r.write_csv(row.csvfilename,gzip=True) - dataprep.update_strokedata(id,r.df) + dataprep.update_strokedata(encoder.decode_hex(id),r.df) successmessage = "Changes saved" if rankingpiece: @@ -3427,7 +3431,7 @@ def workout_edit_view(request,id=0,message="",successmessage=""): messages.info(request,successmessage) url = reverse('workout_edit_view', kwargs = { - 'id':str(row.id), + 'id':encoder.encode_hex(row.id), }) response = HttpResponseRedirect(url) @@ -3486,11 +3490,11 @@ def workout_edit_view(request,id=0,message="",successmessage=""): 'name':'Workouts' }, { - 'url':get_workout_default_page(request,id), + 'url':get_workout_default_page(request,encoder.encode_hex(row.id)), 'name': row.name }, { - 'url':reverse('workout_edit_view',kwargs={'id':id}), + 'url':reverse('workout_edit_view',kwargs={'id':encoder.encode_hex(row.id)}), 'name': 'Edit' } @@ -3631,7 +3635,7 @@ def workout_uploadimage_view(request,id): messages.error(request,message) url = reverse(r.defaultlandingpage, kwargs = { - 'id':int(id), + 'id':id, }) return HttpResponseRedirect(url) @@ -3729,7 +3733,7 @@ def workout_add_chart_view(request,id,plotnr=1): request.session['async_tasks'] = [(jobid,'make_plot')] - url = reverse(r.defaultlandingpage,kwargs={'id':str(w.id)}) + url = reverse(r.defaultlandingpage,kwargs={'id':encoder.encode_hex(w.id)}) return HttpResponseRedirect(url) @@ -4004,9 +4008,11 @@ def workout_upload_view(request, if message: messages.error(request,message) + w = Workout.objects.get(id=id) + url = reverse('workout_edit_view', kwargs = { - 'id':int(id), + 'id':encoder.encode_hex(w.id), }) if is_ajax: @@ -4014,7 +4020,6 @@ def workout_upload_view(request, else: response = HttpResponseRedirect(url) - w = Workout.objects.get(id=id) r = getrower(request.user) if (make_plot): @@ -4135,7 +4140,7 @@ def workout_upload_view(request, if landingpage != 'workout_upload_view': url = reverse(landingpage, kwargs = { - 'id':w.id, + 'id':encoder.encode_hex(w.id), }) else: url = reverse(landingpage) @@ -4326,7 +4331,7 @@ def team_workout_upload_view(request,message="", url = reverse('team_workout_upload_view') response = HttpResponseRedirect(url) - w = Workout.objects.get(id=id) + w = Workout.objects.get(id=encoder.decode_hex(id)) r = getrower(request.user) if (make_plot): @@ -4459,12 +4464,7 @@ def graph_show_view(request,id): # Restore original stroke data and summary @login_required() def workout_summary_restore_view(request,id,message="",successmessage=""): - try: - row = Workout.objects.get(id=id) - if (checkworkoutuser(request.user,row)==False): - raise PermissionDenied("You are not allowed to edit this workout") - except Workout.DoesNotExist: - raise Http404("Workout doesn't exist") + row = get_workout_permitted(request.user,id) s = "" # still here - this is a workout we may edit @@ -4489,14 +4489,14 @@ def workout_summary_restore_view(request,id,message="",successmessage=""): raise Http404("Error: CSV Data File Not Found") rowdata.restoreintervaldata() rowdata.write_csv(f1,gzip=True) - dataprep.update_strokedata(id,rowdata.df) + dataprep.update_strokedata(encoder.decode_hex(id),rowdata.df) intervalstats = rowdata.allstats() row.summary = intervalstats row.save() # create interactive plot try: - res = interactive_chart(id,promember=1) + res = interactive_chart(encoder.decode_hex(id),promember=1) script = res[0] div = res[1] except ValueError: @@ -4506,14 +4506,14 @@ def workout_summary_restore_view(request,id,message="",successmessage=""): messages.info(request,'Original Interval Data Restored') url = reverse('workout_summary_edit_view', kwargs={ - 'id':int(id), + 'id':encoder.encode_hex(row.id), } ) return HttpResponseRedirect(url) # Split a workout @user_passes_test(ispromember,login_url="/rowers/paidplans",message="This functionality requires a Pro plan or higher",redirect_field_name=None) -def workout_split_view(request,id=id): +def workout_split_view(request,id=0): row = get_workout_permitted(request.user,id) r = row.user @@ -4524,11 +4524,11 @@ def workout_split_view(request,id=id): 'name':'Workouts' }, { - 'url':get_workout_default_page(request,row.id), + 'url':get_workout_default_page(request,id), 'name': row.name }, { - 'url':reverse('graph_show_view', + 'url':reverse('workout_split_view', kwargs={'id':id}), 'name': 'Chart' } @@ -4586,7 +4586,7 @@ def workout_split_view(request,id=id): # create interactive plot try: - res = interactive_chart(id,promember=1) + res = interactive_chart(encoder.decode_hex(id),promember=1) script = res[0] div = res[1] except ValueError: @@ -4607,6 +4607,12 @@ def workout_split_view(request,id=id): @user_passes_test(ispromember,login_url="/rowers/paidplans",message="This functionality requires a Pro plan or higher",redirect_field_name=None) def workout_fusion_view(request,id1=0,id2=1): + try: + id1 = encoder.decode_hex(id1) + id2 = encoder.decode_hex(id2) + except: + pass + r = getrower(request.user) try: @@ -4645,7 +4651,7 @@ def workout_fusion_view(request,id1=0,id2=1): url = reverse('workout_edit_view', kwargs={ - 'id':idnew, + 'id':encoder.encode_hex(idnew), }) return HttpResponseRedirect(url) @@ -4662,12 +4668,15 @@ def workout_fusion_view(request,id1=0,id2=1): 'name': str(w1.id) }, { - 'url':reverse('workout_fusion_list',kwargs={'id':id1}), + 'url':reverse('workout_fusion_list',kwargs={'id':encoder.encode_hex(id1)}), 'name': 'Sensor Fusion' }, { 'url':reverse('workout_fusion_view', - kwargs={'id1':id1,'id2':id2}), + kwargs={ + 'id1':encoder.encode_hex(id1), + 'id2':encoder.encode_hex(id2) + }), 'name': str(w2.id) } @@ -4837,7 +4846,7 @@ def workout_summary_edit_view(request,id,message="",successmessage="" rowdata.write_csv(f1,gzip=True) - dataprep.update_strokedata(id,rowdata.df) + dataprep.update_strokedata(encoder.decode_hex(id),rowdata.df) messages.info(request,"Updated interval data saved") data = { @@ -4881,7 +4890,7 @@ def workout_summary_edit_view(request,id,message="",successmessage="" row.save() rowdata.write_csv(f1,gzip=True) - dataprep.update_strokedata(id,rowdata.df) + dataprep.update_strokedata(encoder.decode_hex(id),rowdata.df) messages.info(request,"Updated interval data saved") data = {'intervalstring':s} form = SummaryStringForm(initial=data) @@ -4996,7 +5005,7 @@ def workout_summary_edit_view(request,id,message="",successmessage="" row.save() rowdata.write_csv(f1,gzip=True) - dataprep.update_strokedata(id,rowdata.df) + dataprep.update_strokedata(encoder.decode_hex(id),rowdata.df) messages.info(request,"Updated interval data saved") form = SummaryStringForm() @@ -5077,11 +5086,12 @@ def workout_summary_edit_view(request,id,message="",successmessage="" 'normp': normp, 'normv': normv, } - res = interactive_chart(id,promember=1,intervaldata=intervaldata) + res = interactive_chart(encoder.decode_hex(id),promember=1,intervaldata=intervaldata) script = res[0] div = res[1] except ValueError: - pass + script = '' + div = '' # render page