Private
Public Access
1
0

moved user and workout permission checks to rules

updated workoutviews, rest of views not done
doesn't pass tests
This commit is contained in:
Sander Roosendaal
2020-01-12 17:58:55 +01:00
parent 892b6c0e60
commit c82a60f02e
23 changed files with 618 additions and 711 deletions

View File

@@ -14,6 +14,7 @@ import datetime
from requests import Request, Session from requests import Request, Session
import rowers.mytypes as mytypes import rowers.mytypes as mytypes
from rowers.mytypes import otwtypes from rowers.mytypes import otwtypes
from rowers.rower_rules import is_workout_user
from iso8601 import ParseError from iso8601 import ParseError
import numpy import numpy
@@ -863,7 +864,7 @@ def workout_c2_upload(user,w):
r = Rower.objects.get(user=user) r = Rower.objects.get(user=user)
# ready to upload. Hurray # ready to upload. Hurray
if (checkworkoutuser(user,w)): if (is_workout_user(user,w)):
c2userid = get_userid(r.c2token) c2userid = get_userid(r.c2token)
if not c2userid: if not c2userid:
raise NoTokenError("User has no token") raise NoTokenError("User has no token")

View File

@@ -43,7 +43,7 @@ from django.contrib.auth.decorators import login_required
# from .models import Profile # from .models import Profile
from rowingdata import rowingdata, make_cumvalues from rowingdata import rowingdata, make_cumvalues
import pandas as pd import pandas as pd
from rowers.models import Rower,Workout,checkworkoutuser,TombStone from rowers.models import Rower,Workout,TombStone
import rowers.mytypes as mytypes import rowers.mytypes as mytypes
from rowsandall_app.settings import ( from rowsandall_app.settings import (
C2_CLIENT_ID, C2_REDIRECT_URI, C2_CLIENT_SECRET, C2_CLIENT_ID, C2_REDIRECT_URI, C2_CLIENT_SECRET,
@@ -54,7 +54,7 @@ from rowsandall_app.settings import (
from rowers.utils import ( from rowers.utils import (
NoTokenError, custom_exception_handler, ewmovingaverage, NoTokenError, custom_exception_handler, ewmovingaverage,
geo_distance,isprorower,uniqify geo_distance,uniqify
) )
@@ -309,4 +309,3 @@ def imports_token_refresh(user,tokenname,refreshtokenname,expirydatename,oauth_d
r.save() r.save()
return access_token return access_token

View File

@@ -666,6 +666,9 @@ class CoachingGroup(models.Model):
rs = Rower.objects.filter(coachinggroups__in=[self]) rs = Rower.objects.filter(coachinggroups__in=[self])
return rs.count() return rs.count()
def get_coaches(self):
return Rower.objects.filter(mycoachgroup=self)
# Extension of User with rowing specific data # Extension of User with rowing specific data
@python_2_unicode_compatible @python_2_unicode_compatible
class Rower(models.Model): class Rower(models.Model):
@@ -1173,95 +1176,7 @@ class BasePlannedSessionFormSet(BaseFormSet):
return return
# Check if workout is owned by this user
def checkworkoutuser(user,workout):
if user.is_anonymous:
return False
try:
r = Rower.objects.get(user=user)
if workout.user == r:
return True
coaches = []
for group in workout.user.coachinggroups.all():
coach = Rower.objects.get(mycoachgroup=group)
coaches.append(coach)
for coach in coaches:
if user.rower == coach and workout.privacy == 'visible':
return True
else:
return False
except Rower.DoesNotExist:
return False
# Check if workout may be viewed by this user
def checkworkoutuserview(user,workout):
if user.is_anonymous:
return False
try:
r = Rower.objects.get(user=user)
if workout.user == r:
return True
teams = workout.user.team.all()
for team in teams:
if team in r.team.all():
return True
return False
except Rower.DoesNotExist:
return False
return False
def checkviewworkouts(user,rower):
try:
r = user.rower
if rower == r:
return True
teams = Team.objects.filter(manager=user)
if rower in Rower.objects.filter(team__in=teams):
return True
if rower in Rower.objects.filter(coachinggroups__in=[user.rower.mycoachgroup]):
return True
except Rower.DoesNotExist:
return False
# check if user is plan and rower is in his group
def checkaccessplanuser(user,rower):
try:
r = Rower.objects.get(user=user)
if rower == r:
return True
team_managers = [t.manager for t in rower.team.all() if t.manager.rower.rowerplan in ['plan','coach','freecoach']]
if user.rower.rowerplan != 'basic':
return user in team_managers
else:
return False
return False
except Rower.DoesNotExist:
return False
# Check if user is coach or rower
def checkaccessuser(user,rower):
try:
r = Rower.objects.get(user=user)
if rower == r:
return True
coaches = []
for group in rower.coachinggroups.all():
coach = Rower.objects.get(mycoachgroup=group)
coaches.append(coach)
for coach in coaches:
if user.rower == coach:
return True
else:
return False
except Rower.DoesNotExist:
return False
timezones = ( timezones = (
(x,x) for x in pytz.common_timezones (x,x) for x in pytz.common_timezones

View File

@@ -38,7 +38,7 @@ from django.contrib.auth.decorators import login_required
from rowingdata import rowingdata from rowingdata import rowingdata
import pandas as pd import pandas as pd
from rowers.models import Rower,Workout from rowers.models import Rower,Workout
from rowers.models import checkworkoutuser
import rowers.dataprep as dataprep import rowers.dataprep as dataprep
from rowers.dataprep import columndict from rowers.dataprep import columndict
@@ -136,7 +136,7 @@ def get_polar_notifications():
return available_data return available_data
from rowers.utils import isprorower from rowers.rower_rules import ispromember
def get_all_new_workouts(available_data,testing=False): def get_all_new_workouts(available_data,testing=False):
for record in available_data: for record in available_data:
@@ -146,7 +146,7 @@ def get_all_new_workouts(available_data,testing=False):
try: try:
r = Rower.objects.get(polaruserid=record['user-id']) r = Rower.objects.get(polaruserid=record['user-id'])
u = r.user u = r.user
if r.polar_auto_import and isprorower(r): if r.polar_auto_import and ispromember(u):
exercise_list = get_polar_workouts(u) exercise_list = get_polar_workouts(u)
if testing: if testing:
print(exercise_list) print(exercise_list)
@@ -337,7 +337,3 @@ def get_polar_workout(user,id,transactionid):
return result return result
return None return None

View File

@@ -19,6 +19,154 @@ def user_is_not_basic(user):
def is_coach(user): def is_coach(user):
return user.rower.rowerplan in ['coach','freecoach'] return user.rower.rowerplan in ['coach','freecoach']
@rules.predicate
def is_promember(user):
try:
r = user.rower
except AttributeError:
return False
return r.rowerplan in ['pro','coach','plan']
@rules.predicate
def is_protrial(user):
try:
r = user.rower
except AttributeError:
return False
if r.rowerplan == 'basic':
return r.protrialexpires >= datetime.date.today()
if r.rowerplan == 'freecoach':
if r.mycoachgroup is not None:
return len(r.mycoachgroup)>=4
return False
ispromember = is_promember | is_protrial
# User / Coach relationships (Rower object)
@rules.predicate
def can_plan(user):
return user.rower.rowerplan in ['plan','coach','freecoach']
@rules.predicate
def is_coach_user(user,rower):
try:
r = user.rower
except AttributeError:
return False
if rower == r:
return True
coaches = []
for group in r.coachinggroups.all():
newcoaches = group.get_coaches()
for coach in newcoaches:
coaches.append(coach)
print(coaches)
for coach in coaches:
if rower == coach:
return True
return False
@rules.predicate
def is_rower_team_member(user,rower):
if user.rower == rower:
return True
teams = user.rower.team.all()
for team in teams:
if team.private == 'open':
if team in rower.team.all():
return True
if team.manager == rower.user:
return True
return False
@rules.predicate
def can_plan_user(user,rower):
try:
r = user.rower
except AttributeError:
return False
if rower == r:
return True
# below
team_managers = [t.manager for t in rower.team.all() and can_plan(t.manager)]
if user_is_not_basic(user):
return user in team_managers
return False
rules.add_perm('rower.can_plan',can_plan_user) # replaces checkaccessplanuser
rules.add_perm('rower.is_coach',is_coach_user) # replaces checkaccessuser
# WORKOUT permissions
@rules.predicate
def is_workout_user(user,workout):
if user.is_anonymous:
return False
try:
r = user.rower
except AttributeError:
return False
if workout.user == r:
return True
coaches = []
for group in workout.user.coachinggroups.all():
coach = group.coachingrole
coaches.append(coach)
for coach in coaches:
if r == coach and workout.privacy == 'visible':
return True
return False
@rules.predicate
def can_view_workout(user,workout):
if user.is_anonymous:
if workout.privacy != 'private':
return True
return False
try:
r = user.rower
except AttributeError:
return False
teams = workout.user.team.all()
for team in teams:
if team in r.team.all():
return True
return False
rules.add_perm('workout.change_workout',is_workout_user) # replaces checkworkoutuser
rules.add_perm('workout.view_workout',can_view_workout) # replaces checkworkoutuserview
# checkviewworkouts
# PLANNING permissions
# checkaccessplanuser (models.py)
# TEAM permissions # TEAM permissions
@rules.predicate @rules.predicate

View File

@@ -7,6 +7,8 @@ from __future__ import unicode_literals, absolute_import
from rowers.imports import * from rowers.imports import *
import re import re
from rowers.rower_rules import is_workout_user
from rowsandall_app.settings import ( from rowsandall_app.settings import (
C2_CLIENT_ID, C2_REDIRECT_URI, C2_CLIENT_SECRET, C2_CLIENT_ID, C2_REDIRECT_URI, C2_CLIENT_SECRET,
STRAVA_CLIENT_ID, STRAVA_REDIRECT_URI, STRAVA_CLIENT_SECRET, STRAVA_CLIENT_ID, STRAVA_REDIRECT_URI, STRAVA_CLIENT_SECRET,
@@ -285,7 +287,7 @@ def workout_runkeeper_upload(user,w):
# ready to upload. Hurray # ready to upload. Hurray
if (checkworkoutuser(user,w)): if (is_workout_user(user,w)):
data = createrunkeeperworkoutdata(w) data = createrunkeeperworkoutdata(w)
if not data: if not data:
message = "Data error in Runkeeper Upload" message = "Data error in Runkeeper Upload"

View File

@@ -18,6 +18,7 @@ from rowsandall_app.settings import (
) )
import rowers.mytypes as mytypes import rowers.mytypes as mytypes
from rowers.rower_rules import is_workout_user
oauth_data = { oauth_data = {
'client_id': SPORTTRACKS_CLIENT_ID, 'client_id': SPORTTRACKS_CLIENT_ID,
@@ -265,7 +266,7 @@ def workout_sporttracks_upload(user,w):
thetoken = sporttracks_open(user) thetoken = sporttracks_open(user)
if (checkworkoutuser(user,w)): if (is_workout_user(user,w)):
data = createsporttracksworkoutdata(w) data = createsporttracksworkoutdata(w)
if not data: if not data:
message = "Data error" message = "Data error"

View File

@@ -18,6 +18,8 @@ queuehigh = django_rq.get_queue('low')
from rowers.dataprep import columndict from rowers.dataprep import columndict
from rowers.rower_rules import is_workout_user
import stravalib import stravalib
from stravalib.exc import ActivityUploadFailed,TimeoutExceeded from stravalib.exc import ActivityUploadFailed,TimeoutExceeded
@@ -632,7 +634,7 @@ def workout_strava_upload(user,w):
s = "Token doesn't exist. Need to authorize" s = "Token doesn't exist. Need to authorize"
raise NoTokenError("Your hovercraft is full of eels") raise NoTokenError("Your hovercraft is full of eels")
else: else:
if (checkworkoutuser(user,w)): if (is_workout_user(user,w)):
try: try:
tcxfile,tcxmesg = createstravaworkoutdata(w) tcxfile,tcxmesg = createstravaworkoutdata(w)
if tcxfile: if tcxfile:

View File

@@ -21,7 +21,7 @@ from rowers.plannedsessions import (
from rowers import c2stuff, runkeeperstuff from rowers import c2stuff, runkeeperstuff
from rowers.c2stuff import c2_open from rowers.c2stuff import c2_open
from rowers.runkeeperstuff import runkeeper_open from rowers.runkeeperstuff import runkeeper_open
from rowers.models import checkaccessuser from rowers.rower_rules import is_coach_user, is_workout_user
from rowers.mytypes import otwtypes from rowers.mytypes import otwtypes
from rowers.utils import NoTokenError from rowers.utils import NoTokenError
@@ -385,14 +385,13 @@ def is_session_manager(id,user):
return ps.manager == user return ps.manager == user
from rowers.models import checkworkoutuser
@register.filter @register.filter
def may_edit(workout,request): def may_edit(workout,request):
mayedit = 0 mayedit = 0
if request.user == workout.user.user: if request.user == workout.user.user:
mayedit = True mayedit = True
if checkworkoutuser(request.user,workout): if is_workout_user(request.user,workout):
mayedit = True mayedit = True
return mayedit return mayedit
@@ -413,7 +412,7 @@ def mayeditplan(obj,request):
return request.user == obj.manager.user return request.user == obj.manager.user
rr = Rower.objects.get(user=request.user) rr = Rower.objects.get(user=request.user)
if checkaccessuser(request.user,obj.rower) and rr.rowerplan not in ['basic','pro']: if is_coach_user(request.user,obj.rower) and rr.rowerplan not in ['basic','pro']:
mayedit = True mayedit = True

View File

@@ -18,7 +18,7 @@ from django.test import TestCase, Client,override_settings
from django.core.management import call_command from django.core.management import call_command
from django.utils.six import StringIO from django.utils.six import StringIO
from django.test.client import RequestFactory from django.test.client import RequestFactory
from rowers.views import checkworkoutuser,c2_open from rowers.views import c2_open
from rowers.models import Workout, User, Rower, WorkoutForm,RowerForm,GraphImage from rowers.models import Workout, User, Rower, WorkoutForm,RowerForm,GraphImage
from rowers.forms import DocumentsForm,CNsummaryForm,RegistrationFormUniqueEmail from rowers.forms import DocumentsForm,CNsummaryForm,RegistrationFormUniqueEmail
import rowers.plots as plots import rowers.plots as plots

View File

@@ -26,7 +26,7 @@ from django.core.management import call_command
from django.core.files.uploadedfile import SimpleUploadedFile from django.core.files.uploadedfile import SimpleUploadedFile
from django.utils.six import StringIO from django.utils.six import StringIO
from django.test.client import RequestFactory from django.test.client import RequestFactory
from rowers.views import checkworkoutuser,c2_open, multi_compare_view from rowers.views import c2_open, multi_compare_view
from rowers.forms import ( from rowers.forms import (
DocumentsForm,CNsummaryForm,RegistrationFormUniqueEmail, DocumentsForm,CNsummaryForm,RegistrationFormUniqueEmail,
@@ -220,5 +220,3 @@ def cleanup(request):
request.addfinalizer(remove_test_files) request.addfinalizer(remove_test_files)

View File

@@ -209,7 +209,6 @@ class URLTests(TestCase):
'/rowers/workout/'+encoded1+'/editintervals/', '/rowers/workout/'+encoded1+'/editintervals/',
'/rowers/workout/'+encoded1+'/flexchart/', '/rowers/workout/'+encoded1+'/flexchart/',
'/rowers/workout/'+encoded1+'/forcecurve/', '/rowers/workout/'+encoded1+'/forcecurve/',
'/rowers/workout/'+encoded1+'/get-testscript/',
'/rowers/workout/'+encoded1+'/get-thumbnails/', '/rowers/workout/'+encoded1+'/get-thumbnails/',
'/rowers/workout/'+encoded1+'/histo/', '/rowers/workout/'+encoded1+'/histo/',
'/rowers/workout/'+encoded1+'/image/', '/rowers/workout/'+encoded1+'/image/',

View File

@@ -42,6 +42,8 @@ oauth_data = {
'scope':'write', 'scope':'write',
} }
from rowers.rower_rules import is_workout_user
# Checks if user has UnderArmour token, renews them if they are expired # Checks if user has UnderArmour token, renews them if they are expired
def tp_open(user): def tp_open(user):
@@ -171,7 +173,7 @@ def workout_tp_upload(user,w):
# need some code if token doesn't refresh # need some code if token doesn't refresh
if (checkworkoutuser(user,w)): if (is_workout_user(user,w)):
tcxfile = createtpworkoutdata(w) tcxfile = createtpworkoutdata(w)
if tcxfile: if tcxfile:
res,reason,status_code,headers = uploadactivity( res,reason,status_code,headers = uploadactivity(

View File

@@ -9,7 +9,7 @@ from django.test import TestCase, Client,override_settings
from django.core.management import call_command from django.core.management import call_command
from django.utils.six import StringIO from django.utils.six import StringIO
from django.test.client import RequestFactory from django.test.client import RequestFactory
from .views import checkworkoutuser,c2_open from .views import c2_open
from rowers.models import Workout, User, Rower, WorkoutForm,RowerForm,GraphImage from rowers.models import Workout, User, Rower, WorkoutForm,RowerForm,GraphImage
from rowers.forms import DocumentsForm,CNsummaryForm,RegistrationFormUniqueEmail from rowers.forms import DocumentsForm,CNsummaryForm,RegistrationFormUniqueEmail
import rowers.plots as plots import rowers.plots as plots

View File

@@ -9,6 +9,7 @@ import numpy
import rowers.mytypes as mytypes import rowers.mytypes as mytypes
from rowers.mytypes import otwtypes from rowers.mytypes import otwtypes
from rowers.rower_rules import is_workout_user
from rowsandall_app.settings import ( from rowsandall_app.settings import (
UNDERARMOUR_CLIENT_KEY, UNDERARMOUR_CLIENT_KEY,
@@ -331,7 +332,7 @@ def workout_ua_upload(user,w):
# ready to upload. Hurray # ready to upload. Hurray
if (checkworkoutuser(user,w)): if (is_workout_user(user,w)):
data = createunderarmourworkoutdata(w) data = createunderarmourworkoutdata(w)
# return HttpResponse(json.dumps(data)) # return HttpResponse(json.dumps(data))
if not data: if not data:

View File

@@ -14,6 +14,8 @@ from rowers.tasks import (
from rowers.models import GraphImage from rowers.models import GraphImage
from rowers.rower_rules import ispromember
from PIL import Image from PIL import Image
import numpy as np import numpy as np
@@ -472,6 +474,8 @@ import rowers.runkeeperstuff as runkeeperstuff
import rowers.underarmourstuff as underarmourstuff import rowers.underarmourstuff as underarmourstuff
import rowers.tpstuff as tpstuff import rowers.tpstuff as tpstuff
from rowers.rower_rules import is_promember
def set_workouttype(w,options): def set_workouttype(w,options):
try: try:
w.workouttype = options['workouttype'] w.workouttype = options['workouttype']
@@ -500,8 +504,6 @@ def make_private(w,options):
return 1 return 1
from rowers.utils import isprorower
def do_sync(w,options): def do_sync(w,options):
try: try:
if options['stravaid'] != 0: if options['stravaid'] != 0:
@@ -511,7 +513,7 @@ def do_sync(w,options):
except KeyError: except KeyError:
pass pass
if ('upload_to_C2' in options and options['upload_to_C2']) or (w.user.c2_auto_export and isprorower(w.user)): if ('upload_to_C2' in options and options['upload_to_C2']) or (w.user.c2_auto_export and ispromember(w.user)):
if ('upload_to_C2' in options and not options['upload_to_C2']): if ('upload_to_C2' in options and not options['upload_to_C2']):
pass pass
else: else:
@@ -521,7 +523,7 @@ def do_sync(w,options):
id = 0 id = 0
message = "Something went wrong with the Concept2 sync" message = "Something went wrong with the Concept2 sync"
if ('upload_to_Strava' in options and options['upload_to_Strava']) or (w.user.strava_auto_export and isprorower(w.user)): if ('upload_to_Strava' in options and options['upload_to_Strava']) or (w.user.strava_auto_export and ispromember(w.user)):
if ('upload_to_Strava' in options and not options['upload_to_Strava']): if ('upload_to_Strava' in options and not options['upload_to_Strava']):
pass pass
else: else:
@@ -534,7 +536,7 @@ def do_sync(w,options):
message = "Please connect to Strava first" message = "Please connect to Strava first"
if ('upload_to_SportTracks' in options and options['upload_to_SportTracks']) or (w.user.sporttracks_auto_export and isprorower(w.user)): if ('upload_to_SportTracks' in options and options['upload_to_SportTracks']) or (w.user.sporttracks_auto_export and ispromember(w.user)):
if ('upload_to_SportTracks' in options and not options['upload_to_SportTracks']): if ('upload_to_SportTracks' in options and not options['upload_to_SportTracks']):
pass pass
else: else:
@@ -548,7 +550,7 @@ def do_sync(w,options):
id = 0 id = 0
if ('upload_to_RunKeeper' in options and options['upload_to_RunKeeper']) or (w.user.runkeeper_auto_export and isprorower(w.user)): if ('upload_to_RunKeeper' in options and options['upload_to_RunKeeper']) or (w.user.runkeeper_auto_export and ispromember(w.user)):
if ('upload_to_RunKeeper' in options and not options['upload_to_RunKeeper']): if ('upload_to_RunKeeper' in options and not options['upload_to_RunKeeper']):
pass pass
else: else:
@@ -561,7 +563,7 @@ def do_sync(w,options):
message = "Please connect to Runkeeper first" message = "Please connect to Runkeeper first"
id = 0 id = 0
if ('upload_to_MapMyFitness' in options and options['upload_to_MapMyFitness']) or (w.user.mapmyfitness_auto_export and isprorower(w.user)): if ('upload_to_MapMyFitness' in options and options['upload_to_MapMyFitness']) or (w.user.mapmyfitness_auto_export and ispromember(w.user)):
if ('upload_to_MapMyFitness' in options and not options['upload_to_MapMyFitness']): if ('upload_to_MapMyFitness' in options and not options['upload_to_MapMyFitness']):
pass pass
else: else:
@@ -574,7 +576,7 @@ def do_sync(w,options):
id = 0 id = 0
if ('upload_to_TrainingPeaks' in options and options['upload_to_TrainingPeaks']) or (w.user.trainingpeaks_auto_export and isprorower(w.user)): if ('upload_to_TrainingPeaks' in options and options['upload_to_TrainingPeaks']) or (w.user.trainingpeaks_auto_export and ispromember(w.user)):
if ('upload_to_TrainingPeaks' in options and not options['upload_to_TrainingPeaks']): if ('upload_to_TrainingPeaks' in options and not options['upload_to_TrainingPeaks']):
pass pass
else: else:

View File

@@ -289,8 +289,6 @@ urlpatterns = [
name='otw_use_gps'), name='otw_use_gps'),
re_path(r'^workout/(?P<id>\b[0-9A-Fa-f]+\b)/toggle-ranking/$',views.workout_toggle_ranking, re_path(r'^workout/(?P<id>\b[0-9A-Fa-f]+\b)/toggle-ranking/$',views.workout_toggle_ranking,
name='workout_toggle_ranking'), name='workout_toggle_ranking'),
re_path(r'^workout/(?P<id>\b[0-9A-Fa-f]+\b)/get-testscript/$',views.get_testscript,
name='get_testscript'),
re_path(r'^workout/upload/team/$',views.team_workout_upload_view,name='team_workout_upload_view'), re_path(r'^workout/upload/team/$',views.team_workout_upload_view,name='team_workout_upload_view'),
re_path(r'^workout/upload/$',views.workout_upload_view,name='workout_upload_view'), re_path(r'^workout/upload/$',views.workout_upload_view,name='workout_upload_view'),
re_path(r'^workout/(?P<id>\b[0-9A-Fa-f]+\b)/histo/$',views.workout_histo_view, re_path(r'^workout/(?P<id>\b[0-9A-Fa-f]+\b)/histo/$',views.workout_histo_view,

View File

@@ -405,17 +405,6 @@ def totaltime_sec_to_string(totaltime):
return duration return duration
def isprorower(r):
result = False
result = r.rowerplan in ['pro','coach','plan']
if not result and r.protrialexpires:
result = r.rowerplan == 'basic' and r.protrialexpires >= datetime.date.today()
if not result and r.rowerplan == 'freecoach':
if r.mycoachgroup is not None:
result = len(r.mycoachgroup)>=4
return result
def iscoach(m,r): def iscoach(m,r):
result = False result = False
@@ -518,4 +507,3 @@ def allsundays(startdate,enddate):
while d<=enddate: while d<=enddate:
yield d yield d
d += datetime.timedelta(days=7) d += datetime.timedelta(days=7)

View File

@@ -6,13 +6,12 @@ from rowers.views.statements import *
# Export workout to TCX and send to user's email address # Export workout to TCX and send to user's email address
@login_required() @permission_required('workout.change_workout',fn=objectgetter(Workout, 'id'))
def workout_tcxemail_view(request,id=0): def workout_tcxemail_view(request,id=0):
r = getrower(request.user) r = getrower(request.user)
w = get_workout(id) w = get_workout(id)
if not checkworkoutuser(request.user,w):
raise PermissionDenied("Access denied")
row = rdata(w.csvfilename) row = rdata(w.csvfilename)
@@ -169,13 +168,12 @@ def course_kmldownload_view(request,id=0):
# Export workout to GPX and send to user's email address # Export workout to GPX and send to user's email address
@login_required() @permission_required('workout.change_workout',fn=objectgetter(Workout, 'id'))
def workout_gpxemail_view(request,id=0): def workout_gpxemail_view(request,id=0):
r = getrower(request.user) r = getrower(request.user)
w = get_workout(id) w = get_workout(id)
if not checkworkoutuser(request.user,w):
raise PermissionDenied("Access denied")
row = rdata(w.csvfilename) row = rdata(w.csvfilename)
@@ -236,14 +234,13 @@ def workouts_summaries_email_view(request):
# Get Workout CSV file and send it to user's email address # Get Workout CSV file and send it to user's email address
@login_required() @permission_required('workout.change_workout',fn=objectgetter(Workout, 'id'))
def workout_csvemail_view(request,id=0): def workout_csvemail_view(request,id=0):
r = getrower(request.user) r = getrower(request.user)
w = get_workout(id) w = get_workout(id)
if not checkworkoutuser(request.user,w):
raise PermissionDenied("Access denied")
rowdata = rdata(w.csvfilename) rowdata = rdata(w.csvfilename)
code = str(uuid4()) code = str(uuid4())

View File

@@ -13,7 +13,7 @@ def default(o):
# Send workout to TP # Send workout to TP
@login_required() @permission_required('workout.change_workout',fn=objectgetter(Workout, 'id'))
def workout_tp_upload_view(request,id=0): def workout_tp_upload_view(request,id=0):
message = "" message = ""
@@ -25,39 +25,35 @@ def workout_tp_upload_view(request,id=0):
return HttpResponseRedirect("/rowers/me/tpauthorize/") return HttpResponseRedirect("/rowers/me/tpauthorize/")
# ready to upload. Hurray # ready to upload. Hurray
w = get_workout_permitted(request.user,id) w = get_object_or_404(Workout,pk=id)
r = w.user r = w.user
if (checkworkoutuser(request.user,w)):
tcxfile = tpstuff.createtpworkoutdata(w)
if tcxfile:
res,reason,status_code,headers = tpstuff.uploadactivity(
r.tptoken,tcxfile,
name=w.name
)
if res == 0:
message = "Upload to TrainingPeaks failed with status code "+str(status_code)+": "+reason
try:
os.remove(tcxfile)
except WindowsError:
pass
messages.error(request,message) tcxfile = tpstuff.createtpworkoutdata(w)
if tcxfile:
else: # res != 0 res,reason,status_code,headers = tpstuff.uploadactivity(
w.uploadedtotp = res r.tptoken,tcxfile,
w.save() name=w.name
)
if res == 0:
message = "Upload to TrainingPeaks failed with status code "+str(status_code)+": "+reason
try:
os.remove(tcxfile) os.remove(tcxfile)
messages.info(request,'Uploaded to TrainingPeaks') except WindowsError:
pass
else: # no tcxfile
message = "Upload to TrainingPeaks failed"
w.uploadedtotp = -1
w.save()
messages.error(request,message) messages.error(request,message)
else: # not allowed to upload else: # res != 0
message = "You are not allowed to export this workout to TP" w.uploadedtotp = res
w.save()
os.remove(tcxfile)
messages.info(request,'Uploaded to TrainingPeaks')
else: # no tcxfile
message = "Upload to TrainingPeaks failed"
w.uploadedtotp = -1
w.save()
messages.error(request,message) messages.error(request,message)
url = reverse(r.defaultlandingpage, url = reverse(r.defaultlandingpage,
@@ -70,7 +66,7 @@ def workout_tp_upload_view(request,id=0):
# Send workout to Strava # Send workout to Strava
# abundance of error logging here because there were/are some bugs # abundance of error logging here because there were/are some bugs
@login_required() @permission_required('workout.change_workout',fn=objectgetter(Workout, 'id'))
def workout_strava_upload_view(request,id=0): def workout_strava_upload_view(request,id=0):
message = "" message = ""
r = getrower(request.user) r = getrower(request.user)
@@ -88,93 +84,93 @@ def workout_strava_upload_view(request,id=0):
# ready to upload. Hurray # ready to upload. Hurray
w = get_workout_permitted(request.user,id) w = get_workout_permitted(request.user,id)
r = w.user r = w.user
if (checkworkoutuser(request.user,w)):
try: try:
tcxfile,tcxmessg = stravastuff.createstravaworkoutdata(w) tcxfile,tcxmessg = stravastuff.createstravaworkoutdata(w)
if tcxfile: if tcxfile:
with open(tcxfile,'rb') as f: with open(tcxfile,'rb') as f:
try:
newnotes = w.notes+'\n from '+w.workoutsource+' via rowsandall.com'
except TypeError:
newnotes = 'from '+w.workoutsource+' via rowsandall.com'
if w.workouttype in mytypes.rowtypes:
activity_type = r.stravaexportas
else:
try: try:
newnotes = w.notes+'\n from '+w.workoutsource+' via rowsandall.com' activity_type = mytypes.stravamapping[w.workouttype]
except TypeError: except KeyError:
newnotes = 'from '+w.workoutsource+' via rowsandall.com' activity_type = 'Ride'
if w.workouttype in mytypes.rowtypes:
activity_type = r.stravaexportas
else:
try:
activity_type = mytypes.stravamapping[w.workouttype]
except KeyError:
activity_type = 'Ride'
res,mes = stravastuff.handle_stravaexport(
f,w.name,
r.stravatoken,
description=newnotes,
activity_type=activity_type)
if res==0:
messages.error(request,mes)
w.uploadedtostrava = -1
w.save()
try:
os.remove(tcxfile)
except WindowsError:
pass
url = reverse(r.defaultlandingpage,
kwargs = {
'id':encoder.encode_hex(w.id),
})
response = HttpResponseRedirect(url)
return response
res,mes = stravastuff.handle_stravaexport(
f,w.name,
r.stravatoken,
description=newnotes,
activity_type=activity_type)
if res==0:
messages.error(request,mes)
w.uploadedtostrava = -1
w.save()
try: try:
w.uploadedtostrava = res os.remove(tcxfile)
w.save() except WindowsError:
try: pass
os.remove(tcxfile) url = reverse(r.defaultlandingpage,
except WindowsError: kwargs = {
pass 'id':encoder.encode_hex(w.id),
url = reverse('workout_edit_view',kwargs={'id':w.id}) })
response = HttpResponseRedirect(url)
return response
try:
w.uploadedtostrava = res
w.save()
try:
os.remove(tcxfile)
except WindowsError:
pass
url = reverse('workout_edit_view',kwargs={'id':w.id})
messages.info(request,mes) messages.info(request,mes)
except: except:
with open("media/stravaerrors.log","a") as errorlog: with open("media/stravaerrors.log","a") as errorlog:
errorstring = str(sys.exc_info()[0]) errorstring = str(sys.exc_info()[0])
timestr = strftime("%Y%m%d-%H%M%S") timestr = strftime("%Y%m%d-%H%M%S")
errorlog.write(timestr+errorstring+"\r\n") errorlog.write(timestr+errorstring+"\r\n")
errorlog.write("views.py line 826\r\n") errorlog.write("views.py line 826\r\n")
message = 'Error: '+errorstring message = 'Error: '+errorstring
messages.error(request,message) messages.error(request,message)
else: # No tcxfile else: # No tcxfile
message = "Strava Data error "+tcxmessg message = "Strava Data error "+tcxmessg
messages.error(request,message)
w.uploadedtostrava = -1
w.save()
url = reverse(r.defaultlandingpage,
kwargs = {
'id':encoder.encode_hex(w.id),
})
response = HttpResponseRedirect(url)
url = reverse(r.defaultlandingpage,
kwargs = {
'id':encoder.encode_hex(w.id),
}
)
response = HttpResponseRedirect(url)
except ActivityUploadFailed as e:
message = "Strava Upload error: %s" % e
messages.error(request,message) messages.error(request,message)
w.uploadedtostrava = -1 w.uploadedtostrava = -1
w.save() w.save()
os.remove(tcxfile)
url = reverse(r.defaultlandingpage, url = reverse(r.defaultlandingpage,
kwargs = { kwargs = {
'id':encoder.encode_hex(w.id), 'id':encoder.encode_hex(w.id),
}) })
response = HttpResponseRedirect(url) response = HttpResponseRedirect(url)
return response
url = reverse(r.defaultlandingpage,
kwargs = {
'id':encoder.encode_hex(w.id),
}
)
response = HttpResponseRedirect(url)
except ActivityUploadFailed as e:
message = "Strava Upload error: %s" % e
messages.error(request,message)
w.uploadedtostrava = -1
w.save()
os.remove(tcxfile)
url = reverse(r.defaultlandingpage,
kwargs = {
'id':encoder.encode_hex(w.id),
})
response = HttpResponseRedirect(url)
return response
# Upload workout to Concept2 logbook # Upload workout to Concept2 logbook
@login_required() @login_required()
@@ -206,7 +202,7 @@ def workout_c2_upload_view(request,id=0):
return response return response
# Upload workout to RunKeeper # Upload workout to RunKeeper
@login_required() @permission_required('workout.change_workout',fn=objectgetter(Workout, 'id'))
def workout_runkeeper_upload_view(request,id=0): def workout_runkeeper_upload_view(request,id=0):
message = "" message = ""
w = get_workout(id) w = get_workout(id)
@@ -219,48 +215,45 @@ def workout_runkeeper_upload_view(request,id=0):
# ready to upload. Hurray # ready to upload. Hurray
if (checkworkoutuser(request.user,w)):
data = runkeeperstuff.createrunkeeperworkoutdata(w)
if not data:
message = "Data error"
messages.error(request,message)
url = reverse(r.defaultlandingpage,
kwargs = {
'id':id,
})
return HttpResponseRedirect(url)
authorizationstring = str('Bearer ' + thetoken) data = runkeeperstuff.createrunkeeperworkoutdata(w)
headers = {'Authorization': authorizationstring, if not data:
'user-agent': 'sanderroosendaal', message = "Data error"
'Content-Type': 'application/vnd.com.runkeeper.NewFitnessActivity+json',
'Content-Length':'nnn'}
url = "https://api.runkeeper.com/fitnessActivities"
response = requests.post(url,headers=headers,data=json.dumps(data,default=default))
# check for duplicate error first
if (response.status_code == 409 ):
message = "Duplicate error"
messages.error(request,message)
w.uploadedtorunkeeper = -1
w.save()
elif (response.status_code == 201 or response.status_code==200):
runkeeperid = runkeeperstuff.getidfromresponse(response)
w.uploadedtorunkeeper = runkeeperid
w.save()
url = reverse('workout_edit_view',
kwargs={'id':encoder.encode_hex(w.id)})
return HttpResponseRedirect(url)
else:
s = response
message = "Something went wrong in workout_runkeeper_upload_view: %s - %s" % (s.reason,s.text)
messages.error(request,message)
else:
message = "You are not authorized to upload this workout"
messages.error(request,message) messages.error(request,message)
url = reverse(r.defaultlandingpage,
kwargs = {
'id':id,
})
return HttpResponseRedirect(url)
authorizationstring = str('Bearer ' + thetoken)
headers = {'Authorization': authorizationstring,
'user-agent': 'sanderroosendaal',
'Content-Type': 'application/vnd.com.runkeeper.NewFitnessActivity+json',
'Content-Length':'nnn'}
url = "https://api.runkeeper.com/fitnessActivities"
response = requests.post(url,headers=headers,data=json.dumps(data,default=default))
# check for duplicate error first
if (response.status_code == 409 ):
message = "Duplicate error"
messages.error(request,message)
w.uploadedtorunkeeper = -1
w.save()
elif (response.status_code == 201 or response.status_code==200):
runkeeperid = runkeeperstuff.getidfromresponse(response)
w.uploadedtorunkeeper = runkeeperid
w.save()
url = reverse('workout_edit_view',
kwargs={'id':encoder.encode_hex(w.id)})
return HttpResponseRedirect(url)
else:
s = response
message = "Something went wrong in workout_runkeeper_upload_view: %s - %s" % (s.reason,s.text)
messages.error(request,message)
url = reverse(r.defaultlandingpage, url = reverse(r.defaultlandingpage,
kwargs = { kwargs = {
@@ -270,7 +263,7 @@ def workout_runkeeper_upload_view(request,id=0):
return HttpResponseRedirect(url) return HttpResponseRedirect(url)
# Upload workout to Underarmour # Upload workout to Underarmour
@login_required() @permission_required('workout.change_workout',fn=objectgetter(Workout, 'id'))
def workout_underarmour_upload_view(request,id=0): def workout_underarmour_upload_view(request,id=0):
message = "" message = ""
w = get_workout(id) w = get_workout(id)
@@ -283,47 +276,44 @@ def workout_underarmour_upload_view(request,id=0):
# ready to upload. Hurray # ready to upload. Hurray
if (checkworkoutuser(request.user,w)):
data = underarmourstuff.createunderarmourworkoutdata(w)
if not data:
message = "Data error"
messages.error(request,message)
url = reverse(r.defaultlandingpage,
kwargs = {
'id':encoder.encode_hex(w.id),
})
return HttpResponseRedirect(url)
authorizationstring = str('Bearer ' + thetoken) data = underarmourstuff.createunderarmourworkoutdata(w)
headers = {'Authorization': authorizationstring, if not data:
'Api-Key': UNDERARMOUR_CLIENT_KEY, message = "Data error"
'user-agent': 'sanderroosendaal', messages.error(request,message)
'Content-Type': 'application/json', url = reverse(r.defaultlandingpage,
} kwargs = {
'id':encoder.encode_hex(w.id),
})
return HttpResponseRedirect(url)
url = "https://api.ua.com/v7.1/workout/" authorizationstring = str('Bearer ' + thetoken)
response = requests.post(url,headers=headers,data=json.dumps(data,default=default)) headers = {'Authorization': authorizationstring,
'Api-Key': UNDERARMOUR_CLIENT_KEY,
'user-agent': 'sanderroosendaal',
'Content-Type': 'application/json',
}
url = "https://api.ua.com/v7.1/workout/"
response = requests.post(url,headers=headers,data=json.dumps(data,default=default))
# check for duplicate error first # check for duplicate error first
if (response.status_code == 409 ): if (response.status_code == 409 ):
message = "Duplicate error" message = "Duplicate error"
messages.error(request,message) messages.error(request,message)
w.uploadedtounderarmour = -1 w.uploadedtounderarmour = -1
w.save() w.save()
elif (response.status_code == 201 or response.status_code==200): elif (response.status_code == 201 or response.status_code==200):
underarmourid = underarmourstuff.getidfromresponse(response) underarmourid = underarmourstuff.getidfromresponse(response)
w.uploadedtounderarmour = underarmourid w.uploadedtounderarmour = underarmourid
w.save() w.save()
url = reverse('workout_edit_view',kwargs={'id':encoder.encode_hex(w.id)}) url = reverse('workout_edit_view',kwargs={'id':encoder.encode_hex(w.id)})
return HttpResponseRedirect(url) return HttpResponseRedirect(url)
else:
s = response
message = "Something went wrong in workout_underarmour_upload_view: %s " % s.reason
messages.error(request,message)
else: else:
message = "You are not authorized to upload this workout" s = response
message = "Something went wrong in workout_underarmour_upload_view: %s " % s.reason
messages.error(request,message) messages.error(request,message)
url = reverse(r.defaultlandingpage, url = reverse(r.defaultlandingpage,
@@ -334,7 +324,7 @@ def workout_underarmour_upload_view(request,id=0):
return HttpResponseRedirect(url) return HttpResponseRedirect(url)
# Upload workout to SportTracks # Upload workout to SportTracks
@login_required() @permission_required('workout.change_workout',fn=objectgetter(Workout, 'id'))
def workout_sporttracks_upload_view(request,id=0): def workout_sporttracks_upload_view(request,id=0):
message = "" message = ""
# ready to upload. Hurray # ready to upload. Hurray
@@ -347,49 +337,46 @@ def workout_sporttracks_upload_view(request,id=0):
return HttpResponseRedirect("/rowers/me/sporttracksauthorize/") return HttpResponseRedirect("/rowers/me/sporttracksauthorize/")
if (checkworkoutuser(request.user,w)):
data = sporttracksstuff.createsporttracksworkoutdata(w)
if not data: data = sporttracksstuff.createsporttracksworkoutdata(w)
message = "Data error"
messages.error(request,message)
url = reverse(r.defaultlandingpage,
kwargs = {
'id':encoder.encode_hex(w.id),
})
return HttpResponseRedirect(url)
authorizationstring = str('Bearer ' + thetoken) if not data:
headers = {'Authorization': authorizationstring, message = "Data error"
'user-agent': 'sanderroosendaal', messages.error(request,message)
'Content-Type': 'application/json'} url = reverse(r.defaultlandingpage,
kwargs = {
'id':encoder.encode_hex(w.id),
})
return HttpResponseRedirect(url)
url = "https://api.sporttracks.mobi/api/v2/fitnessActivities.json" authorizationstring = str('Bearer ' + thetoken)
response = requests.post(url,headers=headers,data=json.dumps(data,default=default)) headers = {'Authorization': authorizationstring,
'user-agent': 'sanderroosendaal',
'Content-Type': 'application/json'}
url = "https://api.sporttracks.mobi/api/v2/fitnessActivities.json"
response = requests.post(url,headers=headers,data=json.dumps(data,default=default))
# check for duplicate error first # check for duplicate error first
if (response.status_code == 409 ): if (response.status_code == 409 ):
message = "Duplicate error" message = "Duplicate error"
messages.error(request,message) messages.error(request,message)
w.uploadedtosporttracks = -1 w.uploadedtosporttracks = -1
w.save() w.save()
elif (response.status_code == 201 or response.status_code==200): elif (response.status_code == 201 or response.status_code==200):
s= response.json() s= response.json()
sporttracksid = sporttracksstuff.getidfromresponse(response) sporttracksid = sporttracksstuff.getidfromresponse(response)
w.uploadedtosporttracks = sporttracksid w.uploadedtosporttracks = sporttracksid
w.save() w.save()
message = "Upload to SportTracks was successful" message = "Upload to SportTracks was successful"
messages.info(request,message) messages.info(request,message)
url = reverse('workout_edit_view',kwargs={'id':encoder.encode_hex(w.id)}) url = reverse('workout_edit_view',kwargs={'id':encoder.encode_hex(w.id)})
return HttpResponseRedirect(url) return HttpResponseRedirect(url)
else:
s = response
message = "Something went wrong in workout_sporttracks_upload_view: %s" % s.reason
messages.error(request,message)
else: else:
message = "You are not authorized to upload this workout" s = response
message = "Something went wrong in workout_sporttracks_upload_view: %s" % s.reason
messages.error(request,message) messages.error(request,message)
url = reverse(r.defaultlandingpage, url = reverse(r.defaultlandingpage,
@@ -1613,5 +1600,3 @@ def workout_getstravaworkout_next(request):
url = reverse('workouts_view') url = reverse('workouts_view')
return HttpResponseRedirect(url) return HttpResponseRedirect(url)

View File

@@ -1697,21 +1697,16 @@ def plannedsession_edit_view(request,id=0,userid=0):
}) })
@login_required() @permission_required('workout.change_workout',fn=objectgetter(Workout, 'id'))
def plannedsession_detach_view(request,id=0,psid=0): def plannedsession_detach_view(request,id=0,psid=0):
r = getrequestrower(request) r = getrequestrower(request)
try:
ps = PlannedSession.objects.get(id=psid) ps = get_object_or_404(PlannedSession,pk=psid)
except PlannedSession.DoesNotExist:
raise Http404("Planned Session does not exist")
w = get_workout(id) w = get_workout(id)
if (checkworkoutuser(request.user,w)==False):
return HttpResponseForbidden("Permission Error")
remove_workout_plannedsession(w,ps) remove_workout_plannedsession(w,ps)
url = reverse(plannedsession_view,kwargs={'id':psid}) url = reverse(plannedsession_view,kwargs={'id':psid})

View File

@@ -32,10 +32,17 @@ from icalendar import Calendar, Event
from functools import reduce from functools import reduce
from rules.contrib.views import PermissionRequiredMixin
import rowers.braintreestuff as braintreestuff import rowers.braintreestuff as braintreestuff
import rowers.payments as payments import rowers.payments as payments
from rowers.opaque import encoder from rowers.opaque import encoder
from rowers.rower_rules import (
ispromember,is_coach_user,is_team_member,is_rower_team_member,
is_workout_user
)
from django.shortcuts import render from django.shortcuts import render
from django.template.loader import render_to_string from django.template.loader import render_to_string
@@ -98,7 +105,7 @@ from rowers.models import (
TrainingMesoCycleForm, TrainingMicroCycleForm, TrainingMesoCycleForm, TrainingMicroCycleForm,
RaceLogo,RowerBillingAddressForm,PaidPlan, RaceLogo,RowerBillingAddressForm,PaidPlan,
AlertEditForm, ConditionEditForm, AlertEditForm, ConditionEditForm,
PlannedSessionComment,CoachRequest,CoachOffer,checkaccessplanuser, PlannedSessionComment,CoachRequest,CoachOffer,
VideoAnalysis VideoAnalysis
) )
from rowers.models import ( from rowers.models import (
@@ -275,6 +282,11 @@ def getfavorites(r,row):
return favorites,maxfav return favorites,maxfav
def get_workout_by_opaqueid(request,id,**kwargs):
pk = encoder.decode_hex(id)
return get_object_or_404(Workout,pk=pk)
def get_workout_default_page(request,id): def get_workout_default_page(request,id):
if request.user.is_anonymous: if request.user.is_anonymous:
return reverse('workout_view',kwargs={'id':id}) return reverse('workout_view',kwargs={'id':id})
@@ -310,7 +322,7 @@ def getrequestrower(request,rowerid=0,userid=0,notpermanent=False):
except Rower.DoesNotExist: except Rower.DoesNotExist:
raise Http404("Rower doesn't exist") raise Http404("Rower doesn't exist")
if not checkaccessuser(request.user,r): if userid != 0 and not is_coach_user(u,r):
raise PermissionDenied("You have no access to this user") raise PermissionDenied("You have no access to this user")
if notpermanent == False: if notpermanent == False:
@@ -343,7 +355,7 @@ def getrequestplanrower(request,rowerid=0,userid=0,notpermanent=False):
except Rower.DoesNotExist: except Rower.DoesNotExist:
raise Http404("Rower doesn't exist") raise Http404("Rower doesn't exist")
if not checkaccessplanuser(request.user,r): if not is_coach_user(request.user,r):
raise PermissionDenied("You have no access to this user") raise PermissionDenied("You have no access to this user")
if notpermanent == False: if notpermanent == False:
@@ -377,21 +389,6 @@ def get_workout(id):
return w return w
def get_workout_permitted(user,id):
w = get_workout(id)
if (checkworkoutuser(user,w)==False):
raise PermissionDenied("Access denied")
return w
def get_workout_permittedview(user,id):
w = get_workout(id)
if (checkworkoutuserview(user,w)==False):
raise PermissionDenied("Access denied")
return w
def getvalue(data): def getvalue(data):
perc = 0 perc = 0
@@ -774,9 +771,9 @@ def get_stored_tasks_status(request):
return taskstatus return taskstatus
@login_required() @permission_required('workout.change_workout',fn=get_workout_by_opaqueid,raise_exception=True)
def get_thumbnails(request,id): def get_thumbnails(request,id):
row = get_workout_permitted(request.user,id) row = get_workout_by_opaqueid(request,id)
r = getrower(request.user) r = getrower(request.user)
@@ -861,27 +858,6 @@ def get_blog_posts_old(request):
@login_required()
def get_testscript(request,id):
row = get_workout_permitted(request.user,id)
r = getrower(request.user)
object = {
"script":"""
<div id="id_script">
<script>alert("hi")</script>
</div>
""",
"div":"""
<div id="id_div">
Hoi
</div>
"""
}
return JSONResponse([object,object])
@login_required() @login_required()
def session_jobs_view(request): def session_jobs_view(request):
taskstatus = get_stored_tasks_status(request) taskstatus = get_stored_tasks_status(request)
@@ -990,10 +966,6 @@ from rowers.utils import (
import rowers.datautils as datautils import rowers.datautils as datautils
from rowers.models import (
checkworkoutuser,checkaccessuser,checkviewworkouts,checkworkoutuserview
)
# Check if a user is a Coach member # Check if a user is a Coach member
def iscoachmember(user): def iscoachmember(user):
if not user.is_anonymous: if not user.is_anonymous:
@@ -1044,21 +1016,7 @@ def hasplannedsessions(user):
return result return result
from rowers.utils import ProcessorCustomerError from rowers.utils import ProcessorCustomerError
from rowers.utils import isprorower
# Check if a user is a Pro member
def ispromember(user):
if user and not user.is_anonymous:
try:
r = Rower.objects.get(user=user)
except Rower.DoesNotExist:
r = Rower(user=user)
r.save()
result = user.is_authenticated and isprorower(r)
else:
result = False
return result
# More User/Rower utils # More User/Rower utils
def add_defaultfavorites(r): def add_defaultfavorites(r):

View File

@@ -64,8 +64,10 @@ def workout_video_view_mini(request,id=''):
else: else:
mode = 'erg' mode = 'erg'
if request.user.is_authenticated: if request.user.is_authenticated:
mayedit = checkworkoutuser(request.user,w) and isprorower(request.user.rower) mayedit = is_workout_user(request.user,w) and is_promember(request.user)
rower = request.user.rower rower = request.user.rower
else: else:
mayedit = False mayedit = False
@@ -176,7 +178,7 @@ def workout_video_view(request,id=''):
mode = 'erg' mode = 'erg'
if request.user.is_authenticated: if request.user.is_authenticated:
mayedit = checkworkoutuser(request.user,w) and isprorower(request.user.rower) mayedit = is_promember(request.user) and is_workout_user(request.user,w)
rower = request.user.rower rower = request.user.rower
else: else:
mayedit = False mayedit = False
@@ -271,20 +273,18 @@ def workout_video_view(request,id=''):
# Create a video compared with data # Create a video compared with data
@permission_required('workout.change_workout',fn=get_workout_by_opaqueid,raise_exception=True)
@user_passes_test(ispromember,login_url="/rowers/paidplans/", @user_passes_test(ispromember,login_url="/rowers/paidplans/",
message="This functionality requires a Pro plan or higher", message="This functionality requires a Pro plan or higher",
redirect_field_name=None) redirect_field_name=None)
def workout_video_create_view(request,id=0): def workout_video_create_view(request,id=0):
# get workout # get workout
w = get_workout_permitted(request.user,id) w = get_workout_by_opaqueid(request,id)
if w.workouttype in mytypes.otwtypes: if w.workouttype in mytypes.otwtypes:
mode = 'water' mode = 'water'
else: else:
mode = 'erg' mode = 'erg'
mayedit = checkworkoutuser(request.user,w) and isprorower(request.user.rower)
# get video ID and offset # get video ID and offset
if request.method == 'POST': if request.method == 'POST':
form = VideoAnalysisCreateForm(request.POST) form = VideoAnalysisCreateForm(request.POST)
@@ -457,12 +457,10 @@ def workout_forcecurve_view(request,id=0,workstrokesonly=False):
}) })
# Switch from GPS to Impeller (only for SpeedCoach 2, if impeller data) # Switch from GPS to Impeller (only for SpeedCoach 2, if impeller data)
@login_required @permission_required('workout.change_workout',fn=get_workout_by_opaqueid,raise_exception=True)
def otw_use_impeller(request,id=0): def otw_use_impeller(request,id=0):
w = get_workout(id) w = get_workout(id)
if (checkworkoutuser(request.user,w)==False):
raise PermissionDenied("Access denied")
row = rdata(w.csvfilename) row = rdata(w.csvfilename)
success = row.use_impellerdata() success = row.use_impellerdata()
@@ -481,12 +479,10 @@ def otw_use_impeller(request,id=0):
# Switch from Impeller to GPS (only for SpeedCoach 2, if impeller data) # Switch from Impeller to GPS (only for SpeedCoach 2, if impeller data)
@login_required @permission_required('workout.change_workout',fn=get_workout_by_opaqueid,raise_exception=True)
def otw_use_gps(request,id=0): def otw_use_gps(request,id=0):
w = get_workout(id) w = get_workout(id)
if (checkworkoutuser(request.user,w)==False):
raise PermissionDenied("Access denied")
row = rdata(w.csvfilename) row = rdata(w.csvfilename)
success = row.use_gpsdata() success = row.use_gpsdata()
@@ -748,20 +744,13 @@ def fitness_metric_view(request,mode='rower',days=42):
return HttpResponse("job queued") return HttpResponse("job queued")
@login_required() @permission_required('workout.change_workout',fn=get_workout_by_opaqueid,raise_exception=True)
@user_passes_test(ispromember,login_url="/rowers/paidplans", @user_passes_test(ispromember,login_url="/rowers/paidplans",
message="This functionality requires a Pro plan or higher. If you are already a Pro user, please log in to access this functionality. If you are already a Pro user, please log in to access this functionality", message="This functionality requires a Pro plan or higher. If you are already a Pro user, please log in to access this functionality. If you are already a Pro user, please log in to access this functionality",
redirect_field_name=None) redirect_field_name=None)
def workout_update_cp_view(request,id=0): def workout_update_cp_view(request,id=0):
row = get_workout(id) row = get_workout(id)
if (checkworkoutuser(request.user,row)==False):
message = "You are not allowed to edit this workout"
messages.error(request,message)
url = reverse('workouts_view')
return HttpResponseRedirect(url)
row.rankingpiece = True row.rankingpiece = True
row.save() row.save()
@@ -778,17 +767,10 @@ def workout_update_cp_view(request,id=0):
# Reload the workout and calculate the summary from the stroke data (lapIDx) # Reload the workout and calculate the summary from the stroke data (lapIDx)
@login_required() @permission_required('workout.change_workout',fn=get_workout_by_opaqueid,raise_exception=True)
def workout_recalcsummary_view(request,id=0): def workout_recalcsummary_view(request,id=0):
row = get_workout(id) row = get_workout(id)
if (checkworkoutuser(request.user,row)==False):
message = "You are not allowed to edit this workout"
messages.error(request,message)
url = reverse('workouts_view')
return HttpResponseRedirect(url)
filename = row.csvfilename filename = row.csvfilename
rowdata = rdata(filename) rowdata = rdata(filename)
if rowdata: if rowdata:
@@ -1359,7 +1341,7 @@ def team_comparison_select(request,
if id: if id:
firstworkout = get_workout(id) firstworkout = get_workout(id)
if not checkworkoutuserview(request.user,firstworkout): if not is_workout_user(request.user,firstworkout):
raise PermissionDenied("You are not allowed to use this workout") raise PermissionDenied("You are not allowed to use this workout")
firstworkoutquery = Workout.objects.filter(id=encoder.decode_hex(id)) firstworkoutquery = Workout.objects.filter(id=encoder.decode_hex(id))
@@ -1791,7 +1773,7 @@ def workouts_view(request,message='',successmessage='',
# check if access is allowed # check if access is allowed
if not checkviewworkouts(request.user,r): if not is_rower_team_member(request.user,r):
raise PermissionDenied("Access denied") raise PermissionDenied("Access denied")
@@ -2104,6 +2086,7 @@ def workout_fusion_list(request,id=0,message='',successmessage='',
}) })
# Basic view of workout # Basic view of workout
@permission_required('workout.view_workout',fn=get_workout_by_opaqueid,raise_exception=True)
def workout_view(request,id=0): def workout_view(request,id=0):
request.session['referer'] = absolute(request)['PATH'] request.session['referer'] = absolute(request)['PATH']
@@ -2112,19 +2095,13 @@ def workout_view(request,id=0):
else: else:
rower = None rower = None
try: row = get_workout_by_opaqueid(request,id)
row = Workout.objects.get(id=encoder.decode_hex(id))
except Workout.DoesNotExist:
raise Http404("Workout doesn't exist")
comments = WorkoutComment.objects.filter(workout=row) comments = WorkoutComment.objects.filter(workout=row)
aantalcomments = len(comments) aantalcomments = len(comments)
if row.privacy == 'private' and not checkworkoutuser(request.user,row):
raise PermissionDenied("Access denied")
g = GraphImage.objects.filter(workout=row).order_by("-creationdatetime") g = GraphImage.objects.filter(workout=row).order_by("-creationdatetime")
for i in g: for i in g:
try: try:
@@ -2204,6 +2181,7 @@ def workout_view(request,id=0):
# Resets stroke data to raw data (pace) # Resets stroke data to raw data (pace)
@permission_required('workout.change_workout',fn=get_workout_by_opaqueid,raise_exception=True)
@user_passes_test(ispromember,login_url="/rowers/paidplans", @user_passes_test(ispromember,login_url="/rowers/paidplans",
message="This functionality requires a Pro plan or higher. If you are already a Pro user, please log in to access this functionality. If you are already a Pro user, please log in to access this functionality", message="This functionality requires a Pro plan or higher. If you are already a Pro user, please log in to access this functionality. If you are already a Pro user, please log in to access this functionality",
redirect_field_name=None) redirect_field_name=None)
@@ -2213,13 +2191,6 @@ def workout_undo_smoothenpace_view(
row = get_workout(id) row = get_workout(id)
r = getrower(request.user) r = getrower(request.user)
if (checkworkoutuser(request.user,row)==False):
message = "You are not allowed to edit this workout"
messages.error(request,message)
url = reverse('workouts_view')
return HttpResponseRedirect(url)
filename = row.csvfilename filename = row.csvfilename
row = rdata(filename) row = rdata(filename)
if row == 0: if row == 0:
@@ -2243,6 +2214,7 @@ def workout_undo_smoothenpace_view(
# Data smoothing of pace data # Data smoothing of pace data
@permission_required('workout.change_workout',fn=get_workout_by_opaqueid,raise_exception=True)
@user_passes_test(ispromember,login_url="/rowers/paidplans", @user_passes_test(ispromember,login_url="/rowers/paidplans",
message="This functionality requires a Pro plan or higher. If you are already a Pro user, please log in to access this functionality. If you are already a Pro user, please log in to access this functionality", message="This functionality requires a Pro plan or higher. If you are already a Pro user, please log in to access this functionality. If you are already a Pro user, please log in to access this functionality",
redirect_field_name=None) redirect_field_name=None)
@@ -2253,12 +2225,6 @@ def workout_smoothenpace_view(request,id=0,message="",successmessage=""):
r = getrower(request.user) r = getrower(request.user)
if (checkworkoutuser(request.user,row)==False):
message = "You are not allowed to edit this workout"
messages.error(request,message)
url = reverse('workouts_view')
return HttpResponseRedirect(url)
filename = row.csvfilename filename = row.csvfilename
row = rdata(filename) row = rdata(filename)
@@ -2373,6 +2339,7 @@ def workout_crewnerd_summary_view(request,id=0,message="",successmessage=""):
'id':row.id}) 'id':row.id})
# Get weather for given location and date/time # Get weather for given location and date/time
@permission_required('workout.change_workout',fn=get_workout_by_opaqueid,raise_exception=True)
@user_passes_test(ispromember,login_url="/rowers/paidplans", @user_passes_test(ispromember,login_url="/rowers/paidplans",
message="This functionality requires a Pro plan or higher. If you are already a Pro user, please log in to access this functionality", message="This functionality requires a Pro plan or higher. If you are already a Pro user, please log in to access this functionality",
redirect_field_name=None) redirect_field_name=None)
@@ -2382,12 +2349,6 @@ def workout_downloadwind_view(request,id=0,
row = get_workout(id) row = get_workout(id)
f1 = row.csvfilename f1 = row.csvfilename
if (checkworkoutuser(request.user,row)==False):
message = "You are not allowed to edit this workout"
messages.error(request,message)
url = reverse('workouts_view')
return HttpResponseRedirect(url)
# create bearing # create bearing
rowdata = rdata(f1) rowdata = rdata(f1)
@@ -2448,6 +2409,7 @@ def workout_downloadwind_view(request,id=0,
return response return response
# Get weather for given location and date/time # Get weather for given location and date/time
@permission_required('workout.change_workout',fn=get_workout_by_opaqueid,raise_exception=True)
@user_passes_test(ispromember,login_url="/rowers/paidplans",message="This functionality requires a Pro plan or higher. If you are already a Pro user, please log in to access this functionality",redirect_field_name=None) @user_passes_test(ispromember,login_url="/rowers/paidplans",message="This functionality requires a Pro plan or higher. If you are already a Pro user, please log in to access this functionality",redirect_field_name=None)
def workout_downloadmetar_view(request,id=0, def workout_downloadmetar_view(request,id=0,
airportcode=None, airportcode=None,
@@ -2455,12 +2417,7 @@ def workout_downloadmetar_view(request,id=0,
row = get_workout(id) row = get_workout(id)
f1 = row.csvfilename f1 = row.csvfilename
if (checkworkoutuser(request.user,row)==False):
message = "You are not allowed to edit this workout"
messages.error(request,message)
url = reverse('workouts_view')
return HttpResponseRedirect(url)
# create bearing # create bearing
rowdata = rdata(f1) rowdata = rdata(f1)
@@ -2523,6 +2480,7 @@ def workout_downloadmetar_view(request,id=0,
# Show form to update wind data # Show form to update wind data
@permission_required('workout.change_workout',fn=get_workout_by_opaqueid,raise_exception=True)
@user_passes_test(ispromember,login_url="/rowers/paidplans",message="This functionality requires a Pro plan or higher. If you are already a Pro user, please log in to access this functionality",redirect_field_name=None) @user_passes_test(ispromember,login_url="/rowers/paidplans",message="This functionality requires a Pro plan or higher. If you are already a Pro user, please log in to access this functionality",redirect_field_name=None)
def workout_wind_view(request,id=0,message="",successmessage=""): def workout_wind_view(request,id=0,message="",successmessage=""):
row = get_workout(id) row = get_workout(id)
@@ -2543,13 +2501,6 @@ def workout_wind_view(request,id=0,message="",successmessage=""):
] ]
if (checkworkoutuser(request.user,row)==False):
message = "You are not allowed to edit this workout"
messages.error(request,message)
url = reverse('workouts_view')
return HttpResponseRedirect(url)
# get data # get data
f1 = row.csvfilename f1 = row.csvfilename
@@ -2659,17 +2610,13 @@ def workout_wind_view(request,id=0,message="",successmessage=""):
# Show form to update River stream data (for river dwellers) # Show form to update River stream data (for river dwellers)
@permission_required('workout.change_workout',fn=get_workout_by_opaqueid,raise_exception=True)
@user_passes_test(ispromember,login_url="/rowers/paidplans",message="This functionality requires a Pro plan or higher. If you are already a Pro user, please log in to access this functionality",redirect_field_name=None) @user_passes_test(ispromember,login_url="/rowers/paidplans",message="This functionality requires a Pro plan or higher. If you are already a Pro user, please log in to access this functionality",redirect_field_name=None)
def workout_stream_view(request,id=0,message="",successmessage=""): def workout_stream_view(request,id=0,message="",successmessage=""):
row = get_workout(id) row = get_workout(id)
r = getrower(request.user) r = getrower(request.user)
if (checkworkoutuser(request.user,row)==False):
message = "You are not allowed to edit this workout"
messages.error(request,message)
url = reverse('workouts_view')
return HttpResponseRedirect(url)
# create interactive plot # create interactive plot
@@ -2745,23 +2692,15 @@ def workout_stream_view(request,id=0,message="",successmessage=""):
'the_div':div}) 'the_div':div})
# Form to set average crew weight and boat type, then run power calcs # Form to set average crew weight and boat type, then run power calcs
@permission_required('workout.change_workout',fn=get_workout_by_opaqueid,raise_exception=True)
@user_passes_test(ispromember, login_url="/rowers/paidplans",redirect_field_name=None) @user_passes_test(ispromember, login_url="/rowers/paidplans",redirect_field_name=None)
def workout_otwsetpower_view(request,id=0,message="",successmessage=""): def workout_otwsetpower_view(request,id=0,message="",successmessage=""):
w = get_workout(id) w = get_workout(id)
r = getrower(request.user) r = getrower(request.user)
mayedit = 0 mayedit = 1
if request.user == w.user.user:
mayedit=1
if checkworkoutuser(request.user,w):
mayedit=1
if (checkworkoutuser(request.user,w)==False):
message = "You are not allowed to edit this workout"
messages.error(request,message)
url = reverse('workouts_view')
return HttpResponseRedirect(url)
if request.method == 'POST': if request.method == 'POST':
@@ -2879,15 +2818,11 @@ def workout_otwsetpower_view(request,id=0,message="",successmessage=""):
'form':form, 'form':form,
}) })
@login_required() @permission_required('workout.change_workout',fn=get_workout_by_opaqueid,raise_exception=True)
def instroke_view(request,id=0): def instroke_view(request,id=0):
w = get_workout(id) w = get_workout(id)
r = getrower(request.user) r = getrower(request.user)
mayedit = 0 mayedit = 1
if request.user == w.user.user:
mayedit=1
if checkworkoutuser(request.user,w):
mayedit=1
breadcrumbs = [ breadcrumbs = [
{ {
@@ -2909,12 +2844,7 @@ def instroke_view(request,id=0):
g = GraphImage.objects.filter(workout=w).order_by("-creationdatetime") g = GraphImage.objects.filter(workout=w).order_by("-creationdatetime")
# check if user is owner of this workout # check if user is owner of this workout
if (checkworkoutuser(request.user,w)==False):
message = "You are not allowed to edit this workout"
messages.error(request,message)
url = reverse('workouts_view')
return HttpResponseRedirect(url)
rowdata = rrdata(csvfile=w.csvfilename) rowdata = rrdata(csvfile=w.csvfilename)
try: try:
@@ -2937,16 +2867,11 @@ def instroke_view(request,id=0):
# generate instroke chart # generate instroke chart
@login_required() @permission_required('workout.change_workout',fn=get_workout_by_opaqueid,raise_exception=True)
def instroke_chart(request,id=0,metric=''): def instroke_chart(request,id=0,metric=''):
w = get_workout(id) w = get_workout(id)
if (checkworkoutuser(request.user,w)==False):
message = "You are not allowed to edit this workout"
messages.error(request,message)
url = reverse('workouts_view')
return HttpResponseRedirect(url)
rowdata = rrdata(csvfile=w.csvfilename) rowdata = rrdata(csvfile=w.csvfilename)
instrokemetrics = rowdata.get_instroke_columns() instrokemetrics = rowdata.get_instroke_columns()
@@ -2995,14 +2920,12 @@ def instroke_chart(request,id=0,metric=''):
# data explorer # data explorer
@login_required() @permission_required('workout.change_workout',fn=get_workout_by_opaqueid,raise_exception=True)
def workout_data_view(request, id=0): def workout_data_view(request, id=0):
r = getrower(request.user) r = getrower(request.user)
w = get_workout(id) w = get_workout(id)
if not checkworkoutuser(request.user,w):
raise PermissionDenied('Access Denied')
breadcrumbs = [ breadcrumbs = [
{ {
@@ -3100,7 +3023,7 @@ def workout_data_view(request, id=0):
# Stats page # Stats page
@login_required() @permission_required('workout.change_workout',fn=get_workout_by_opaqueid,raise_exception=True)
def workout_stats_view(request,id=0,message="",successmessage=""): def workout_stats_view(request,id=0,message="",successmessage=""):
r = getrower(request.user) r = getrower(request.user)
@@ -3109,7 +3032,7 @@ def workout_stats_view(request,id=0,message="",successmessage=""):
mayedit = 0 mayedit = 0
if request.user == w.user.user: if request.user == w.user.user:
mayedit=1 mayedit=1
if checkworkoutuser(request.user,w): if is_workout_user(request.user,w):
mayedit=1 mayedit=1
breadcrumbs = [ breadcrumbs = [
@@ -3135,8 +3058,7 @@ def workout_stats_view(request,id=0,message="",successmessage=""):
# prepare data frame # prepare data frame
datadf,row = dataprep.getrowdata_db(id=encoder.decode_hex(id)) datadf,row = dataprep.getrowdata_db(id=encoder.decode_hex(id))
if (checkworkoutuserview(request.user,row)==False):
raise PermissionDenied('Access Denied')
datadf = dataprep.clean_df_stats(datadf,workstrokesonly=workstrokesonly, datadf = dataprep.clean_df_stats(datadf,workstrokesonly=workstrokesonly,
ignoreadvanced=False) ignoreadvanced=False)
@@ -3377,11 +3299,12 @@ def workout_workflow_config2_view(request,userid=0):
# Workflow View # Workflow View
@login_required() @login_required()
@permission_required('workout.change_workout',fn=get_workout_by_opaqueid,raise_exception=True)
def workout_workflow_view(request,id): def workout_workflow_view(request,id):
request.session['referer'] = absolute(request)['PATH'] request.session['referer'] = absolute(request)['PATH']
request.session['lastworkout'] = id request.session['lastworkout'] = id
request.session[translation.LANGUAGE_SESSION_KEY] = USER_LANGUAGE request.session[translation.LANGUAGE_SESSION_KEY] = USER_LANGUAGE
row = get_workout_permittedview(request.user,id) row = get_workout_by_opaqueid(request,id)
r = getrower(request.user) r = getrower(request.user)
result = request.user.is_authenticated and ispromember(request.user) result = request.user.is_authenticated and ispromember(request.user)
@@ -3463,7 +3386,7 @@ def workout_workflow_view(request,id):
}) })
# The famous flex chart # The famous flex chart
@login_required() @permission_required('workout.view_workout',fn=get_workout_by_opaqueid,raise_exception=True)
def workout_flexchart3_view(request,*args,**kwargs): def workout_flexchart3_view(request,*args,**kwargs):
try: try:
@@ -3487,12 +3410,12 @@ def workout_flexchart3_view(request,*args,**kwargs):
mayedit=0 mayedit=0
if not request.user.is_anonymous: if not request.user.is_anonymous:
r = getrower(request.user) r = getrower(request.user)
result = request.user.is_authenticated and ispromember(request.user) result = ispromember(request.user)
if result: if result:
promember=1 promember=1
if request.user == row.user.user: if request.user == row.user.user:
mayedit=1 mayedit=1
if checkworkoutuser(request.user,row): if is_workout_user(request.user,row):
mayedit=1 mayedit=1
workouttype = 'ote' workouttype = 'ote'
@@ -3977,7 +3900,7 @@ def workout_comment_view(request,id=0):
# The basic edit page # The basic edit page
@login_required() @permission_required('workout.change_workout',fn=get_workout_by_opaqueid,raise_exception=True)
def workout_edit_view(request,id=0,message="",successmessage=""): def workout_edit_view(request,id=0,message="",successmessage=""):
request.session[translation.LANGUAGE_SESSION_KEY] = USER_LANGUAGE request.session[translation.LANGUAGE_SESSION_KEY] = USER_LANGUAGE
request.session['referer'] = absolute(request)['PATH'] request.session['referer'] = absolute(request)['PATH']
@@ -3986,8 +3909,7 @@ def workout_edit_view(request,id=0,message="",successmessage=""):
row = get_workout(id) row = get_workout(id)
if (checkworkoutuser(request.user,row)==False):
raise PermissionDenied("Access denied")
if request.user.rower.rowerplan == 'basic' and 'speedcoach2' in row.workoutsource: if request.user.rower.rowerplan == 'basic' and 'speedcoach2' in row.workoutsource:
data = getsmallrowdata_db(['wash'],ids=[encoder.decode_hex(id)]) data = getsmallrowdata_db(['wash'],ids=[encoder.decode_hex(id)])
@@ -4293,7 +4215,7 @@ def workout_map_view(request,id=0):
# Image upload # Image upload
@login_required() @permission_required('workout.change_workout',fn=get_workout_by_opaqueid,raise_exception=True)
def workout_uploadimage_view(request,id): def workout_uploadimage_view(request,id):
is_ajax = False is_ajax = False
if request.is_ajax(): if request.is_ajax():
@@ -4319,8 +4241,7 @@ def workout_uploadimage_view(request,id):
] ]
if not checkworkoutuser(request.user,w):
raise PermissionDenied("You are not allowed to edit this workout")
images = GraphImage.objects.filter(workout=w) images = GraphImage.objects.filter(workout=w)
@@ -4398,7 +4319,7 @@ def workout_uploadimage_view(request,id):
# Generic chart creation # Generic chart creation
@login_required() @permission_required('workout.change_workout',fn=get_workout_by_opaqueid,raise_exception=True)
def workout_add_chart_view(request,id,plotnr=1): def workout_add_chart_view(request,id,plotnr=1):
w = get_workout(id) w = get_workout(id)
@@ -4406,26 +4327,24 @@ def workout_add_chart_view(request,id,plotnr=1):
plotnr = int(plotnr) plotnr = int(plotnr)
if (checkworkoutuser(request.user,w)==False):
raise PermissionDenied("You are not allowed add plots to this workout") f1 = w.csvfilename[6:-4]
timestr = strftime("%Y%m%d-%H%M%S")
imagename = f1+timestr+'.png'
u = w.user.user
r = getrower(u)
title = w.name
res,jobid = uploads.make_plot(
r,w,f1,w.csvfilename,'timeplot',title,plotnr=plotnr,
imagename=imagename
)
if res == 0:
messages.error(request,jobid)
else: else:
f1 = w.csvfilename[6:-4] try:
timestr = strftime("%Y%m%d-%H%M%S") request.session['async_tasks'] += [(jobid,'make_plot')]
imagename = f1+timestr+'.png' except KeyError:
u = w.user.user request.session['async_tasks'] = [(jobid,'make_plot')]
r = getrower(u)
title = w.name
res,jobid = uploads.make_plot(
r,w,f1,w.csvfilename,'timeplot',title,plotnr=plotnr,
imagename=imagename
)
if res == 0:
messages.error(request,jobid)
else:
try:
request.session['async_tasks'] += [(jobid,'make_plot')]
except KeyError:
request.session['async_tasks'] = [(jobid,'make_plot')]
url = reverse(r.defaultlandingpage,kwargs={'id':encoder.encode_hex(w.id)}) url = reverse(r.defaultlandingpage,kwargs={'id':encoder.encode_hex(w.id)})
@@ -4437,12 +4356,13 @@ def workout_add_chart_view(request,id,plotnr=1):
@login_required @login_required
@permission_required('workout.change_workout',fn=get_workout_by_opaqueid,raise_exception=True)
def workout_toggle_ranking(request,id=0): def workout_toggle_ranking(request,id=0):
is_ajax = False is_ajax = False
if request.is_ajax(): if request.is_ajax():
is_ajax = True is_ajax = True
row = get_workout_permitted(request.user,id) row = get_workout_by_opaqueid(request,id)
row.rankingpiece = not row.rankingpiece row.rankingpiece = not row.rankingpiece
row.save() row.save()
@@ -5237,9 +5157,9 @@ def graph_show_view(request,id):
raise Http404("This workout doesn't exist") raise Http404("This workout doesn't exist")
# Restore original stroke data and summary # Restore original stroke data and summary
@login_required() @permission_required('workout.change_workout',fn=get_workout_by_opaqueid,raise_exception=True)
def workout_summary_restore_view(request,id,message="",successmessage=""): def workout_summary_restore_view(request,id,message="",successmessage=""):
row = get_workout_permitted(request.user,id) row = get_workout_by_opaqueid(request,id)
s = "" s = ""
# still here - this is a workout we may edit # still here - this is a workout we may edit
@@ -5287,11 +5207,12 @@ def workout_summary_restore_view(request,id,message="",successmessage=""):
return HttpResponseRedirect(url) return HttpResponseRedirect(url)
# Split a workout # Split a workout
@permission_required('workout.change_workout',fn=get_workout_by_opaqueid,raise_exception=True)
@user_passes_test(ispromember,login_url="/rowers/paidplans", @user_passes_test(ispromember,login_url="/rowers/paidplans",
message="This functionality requires a Pro plan or higher. If you are already a Pro user, please log in to access this functionality", message="This functionality requires a Pro plan or higher. If you are already a Pro user, please log in to access this functionality",
redirect_field_name=None) redirect_field_name=None)
def workout_split_view(request,id=0): def workout_split_view(request,id=0):
row = get_workout_permitted(request.user,id) row = get_workout_by_opaqueid(request,id)
r = row.user r = row.user
@@ -5398,8 +5319,8 @@ def workout_fusion_view(request,id1=0,id2=1):
w1 = Workout.objects.get(id=id1) w1 = Workout.objects.get(id=id1)
w2 = Workout.objects.get(id=id2) w2 = Workout.objects.get(id=id2)
r = w1.user r = w1.user
if (checkworkoutuser(request.user,w1)==False) or \ if (is_workout_user(request.user,w1)==False) or \
(checkworkoutuser(request.user,w2)==False): (is_workout_user(request.user,w2)==False):
raise PermissionDenied("You are not allowed to use these workouts") raise PermissionDenied("You are not allowed to use these workouts")
except Workout.DoesNotExist: except Workout.DoesNotExist:
raise Http404("One of the workouts doesn't exist") raise Http404("One of the workouts doesn't exist")
@@ -5475,10 +5396,10 @@ def workout_fusion_view(request,id1=0,id2=1):
# Edit the splits/summary # Edit the splits/summary
@login_required() @permission_required('workout.change_workout',fn=get_workout_by_opaqueid,raise_exception=True)
def workout_summary_edit_view(request,id,message="",successmessage="" def workout_summary_edit_view(request,id,message="",successmessage=""
): ):
row = get_workout_permitted(request.user,id) row = get_workout_by_opaqueid(request,id)
r = getrower(request.user) r = getrower(request.user)
breadcrumbs = [ breadcrumbs = [
{ {
@@ -6024,10 +5945,11 @@ def workout_code_delete_view(request,id=0):
return HttpResponseRedirect(url) return HttpResponseRedirect(url)
class WorkoutDelete(DeleteView): class WorkoutDelete(PermissionRequiredMixin,DeleteView):
login_required = True login_required = True
model = Workout model = Workout
template_name = 'workout_delete_confirm.html' template_name = 'workout_delete_confirm.html'
permission_required = 'workout.change_workout'
# extra parameters # extra parameters
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
@@ -6082,7 +6004,6 @@ class WorkoutDelete(DeleteView):
except Workout.DoesNotExist: except Workout.DoesNotExist:
raise Http404("One of the workouts doesn't exist") raise Http404("One of the workouts doesn't exist")
# obj = super(WorkoutDelete, self).get_object(*args, **kwargs) # obj = super(WorkoutDelete, self).get_object(*args, **kwargs)
if not checkaccessuser(self.request.user,obj.user):
raise PermissionDenied('You are not allowed to delete this workout')
return obj return obj