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
import rowers.mytypes as mytypes
from rowers.mytypes import otwtypes
from rowers.rower_rules import is_workout_user
from iso8601 import ParseError
import numpy
@@ -863,7 +864,7 @@ def workout_c2_upload(user,w):
r = Rower.objects.get(user=user)
# ready to upload. Hurray
if (checkworkoutuser(user,w)):
if (is_workout_user(user,w)):
c2userid = get_userid(r.c2token)
if not c2userid:
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 rowingdata import rowingdata, make_cumvalues
import pandas as pd
from rowers.models import Rower,Workout,checkworkoutuser,TombStone
from rowers.models import Rower,Workout,TombStone
import rowers.mytypes as mytypes
from rowsandall_app.settings import (
C2_CLIENT_ID, C2_REDIRECT_URI, C2_CLIENT_SECRET,
@@ -54,7 +54,7 @@ from rowsandall_app.settings import (
from rowers.utils import (
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()
return access_token

View File

@@ -666,6 +666,9 @@ class CoachingGroup(models.Model):
rs = Rower.objects.filter(coachinggroups__in=[self])
return rs.count()
def get_coaches(self):
return Rower.objects.filter(mycoachgroup=self)
# Extension of User with rowing specific data
@python_2_unicode_compatible
class Rower(models.Model):
@@ -1173,95 +1176,7 @@ class BasePlannedSessionFormSet(BaseFormSet):
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 = (
(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
import pandas as pd
from rowers.models import Rower,Workout
from rowers.models import checkworkoutuser
import rowers.dataprep as dataprep
from rowers.dataprep import columndict
@@ -136,7 +136,7 @@ def get_polar_notifications():
return available_data
from rowers.utils import isprorower
from rowers.rower_rules import ispromember
def get_all_new_workouts(available_data,testing=False):
for record in available_data:
@@ -146,7 +146,7 @@ def get_all_new_workouts(available_data,testing=False):
try:
r = Rower.objects.get(polaruserid=record['user-id'])
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)
if testing:
print(exercise_list)
@@ -337,7 +337,3 @@ def get_polar_workout(user,id,transactionid):
return result
return None

View File

@@ -19,6 +19,154 @@ def user_is_not_basic(user):
def is_coach(user):
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
@rules.predicate

View File

@@ -7,6 +7,8 @@ from __future__ import unicode_literals, absolute_import
from rowers.imports import *
import re
from rowers.rower_rules import is_workout_user
from rowsandall_app.settings import (
C2_CLIENT_ID, C2_REDIRECT_URI, C2_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
if (checkworkoutuser(user,w)):
if (is_workout_user(user,w)):
data = createrunkeeperworkoutdata(w)
if not data:
message = "Data error in Runkeeper Upload"

View File

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

View File

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

View File

@@ -21,7 +21,7 @@ from rowers.plannedsessions import (
from rowers import c2stuff, runkeeperstuff
from rowers.c2stuff import c2_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.utils import NoTokenError
@@ -385,14 +385,13 @@ def is_session_manager(id,user):
return ps.manager == user
from rowers.models import checkworkoutuser
@register.filter
def may_edit(workout,request):
mayedit = 0
if request.user == workout.user.user:
mayedit = True
if checkworkoutuser(request.user,workout):
if is_workout_user(request.user,workout):
mayedit = True
return mayedit
@@ -413,7 +412,7 @@ def mayeditplan(obj,request):
return request.user == obj.manager.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

View File

@@ -18,7 +18,7 @@ from django.test import TestCase, Client,override_settings
from django.core.management import call_command
from django.utils.six import StringIO
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.forms import DocumentsForm,CNsummaryForm,RegistrationFormUniqueEmail
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.utils.six import StringIO
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 (
DocumentsForm,CNsummaryForm,RegistrationFormUniqueEmail,
@@ -220,5 +220,3 @@ def cleanup(request):
request.addfinalizer(remove_test_files)

View File

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

View File

@@ -42,6 +42,8 @@ oauth_data = {
'scope':'write',
}
from rowers.rower_rules import is_workout_user
# Checks if user has UnderArmour token, renews them if they are expired
def tp_open(user):
@@ -171,7 +173,7 @@ def workout_tp_upload(user,w):
# need some code if token doesn't refresh
if (checkworkoutuser(user,w)):
if (is_workout_user(user,w)):
tcxfile = createtpworkoutdata(w)
if tcxfile:
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.utils.six import StringIO
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.forms import DocumentsForm,CNsummaryForm,RegistrationFormUniqueEmail
import rowers.plots as plots

View File

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

View File

@@ -14,6 +14,8 @@ from rowers.tasks import (
from rowers.models import GraphImage
from rowers.rower_rules import ispromember
from PIL import Image
import numpy as np
@@ -472,6 +474,8 @@ import rowers.runkeeperstuff as runkeeperstuff
import rowers.underarmourstuff as underarmourstuff
import rowers.tpstuff as tpstuff
from rowers.rower_rules import is_promember
def set_workouttype(w,options):
try:
w.workouttype = options['workouttype']
@@ -500,8 +504,6 @@ def make_private(w,options):
return 1
from rowers.utils import isprorower
def do_sync(w,options):
try:
if options['stravaid'] != 0:
@@ -511,7 +513,7 @@ def do_sync(w,options):
except KeyError:
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']):
pass
else:
@@ -521,7 +523,7 @@ def do_sync(w,options):
id = 0
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']):
pass
else:
@@ -534,7 +536,7 @@ def do_sync(w,options):
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']):
pass
else:
@@ -548,7 +550,7 @@ def do_sync(w,options):
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']):
pass
else:
@@ -561,7 +563,7 @@ def do_sync(w,options):
message = "Please connect to Runkeeper first"
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']):
pass
else:
@@ -574,7 +576,7 @@ def do_sync(w,options):
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']):
pass
else:

View File

@@ -289,8 +289,6 @@ urlpatterns = [
name='otw_use_gps'),
re_path(r'^workout/(?P<id>\b[0-9A-Fa-f]+\b)/toggle-ranking/$',views.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/$',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,

View File

@@ -405,17 +405,6 @@ def totaltime_sec_to_string(totaltime):
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):
result = False
@@ -518,4 +507,3 @@ def allsundays(startdate,enddate):
while d<=enddate:
yield d
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
@login_required()
@permission_required('workout.change_workout',fn=objectgetter(Workout, 'id'))
def workout_tcxemail_view(request,id=0):
r = getrower(request.user)
w = get_workout(id)
if not checkworkoutuser(request.user,w):
raise PermissionDenied("Access denied")
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
@login_required()
@permission_required('workout.change_workout',fn=objectgetter(Workout, 'id'))
def workout_gpxemail_view(request,id=0):
r = getrower(request.user)
w = get_workout(id)
if not checkworkoutuser(request.user,w):
raise PermissionDenied("Access denied")
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
@login_required()
@permission_required('workout.change_workout',fn=objectgetter(Workout, 'id'))
def workout_csvemail_view(request,id=0):
r = getrower(request.user)
w = get_workout(id)
if not checkworkoutuser(request.user,w):
raise PermissionDenied("Access denied")
rowdata = rdata(w.csvfilename)
code = str(uuid4())

View File

@@ -13,7 +13,7 @@ def default(o):
# Send workout to TP
@login_required()
@permission_required('workout.change_workout',fn=objectgetter(Workout, 'id'))
def workout_tp_upload_view(request,id=0):
message = ""
@@ -25,39 +25,35 @@ def workout_tp_upload_view(request,id=0):
return HttpResponseRedirect("/rowers/me/tpauthorize/")
# ready to upload. Hurray
w = get_workout_permitted(request.user,id)
w = get_object_or_404(Workout,pk=id)
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)
else: # res != 0
w.uploadedtotp = res
w.save()
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)
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)
else: # not allowed to upload
message = "You are not allowed to export this workout to TP"
else: # res != 0
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)
url = reverse(r.defaultlandingpage,
@@ -70,7 +66,7 @@ def workout_tp_upload_view(request,id=0):
# Send workout to Strava
# 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):
message = ""
r = getrower(request.user)
@@ -88,93 +84,93 @@ def workout_strava_upload_view(request,id=0):
# ready to upload. Hurray
w = get_workout_permitted(request.user,id)
r = w.user
if (checkworkoutuser(request.user,w)):
try:
tcxfile,tcxmessg = stravastuff.createstravaworkoutdata(w)
if tcxfile:
with open(tcxfile,'rb') as f:
try:
tcxfile,tcxmessg = stravastuff.createstravaworkoutdata(w)
if tcxfile:
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:
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:
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
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:
w.uploadedtostrava = res
w.save()
try:
os.remove(tcxfile)
except WindowsError:
pass
url = reverse('workout_edit_view',kwargs={'id':w.id})
os.remove(tcxfile)
except WindowsError:
pass
url = reverse(r.defaultlandingpage,
kwargs = {
'id':encoder.encode_hex(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)
except:
with open("media/stravaerrors.log","a") as errorlog:
errorstring = str(sys.exc_info()[0])
timestr = strftime("%Y%m%d-%H%M%S")
errorlog.write(timestr+errorstring+"\r\n")
errorlog.write("views.py line 826\r\n")
message = 'Error: '+errorstring
messages.error(request,message)
else: # No tcxfile
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.info(request,mes)
except:
with open("media/stravaerrors.log","a") as errorlog:
errorstring = str(sys.exc_info()[0])
timestr = strftime("%Y%m%d-%H%M%S")
errorlog.write(timestr+errorstring+"\r\n")
errorlog.write("views.py line 826\r\n")
message = 'Error: '+errorstring
messages.error(request,message)
else: # No tcxfile
message = "Strava Data error "+tcxmessg
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
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
@login_required()
@@ -206,7 +202,7 @@ def workout_c2_upload_view(request,id=0):
return response
# Upload workout to RunKeeper
@login_required()
@permission_required('workout.change_workout',fn=objectgetter(Workout, 'id'))
def workout_runkeeper_upload_view(request,id=0):
message = ""
w = get_workout(id)
@@ -219,48 +215,45 @@ def workout_runkeeper_upload_view(request,id=0):
# 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)
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)
else:
message = "You are not authorized to upload this workout"
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)
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,
kwargs = {
@@ -270,7 +263,7 @@ def workout_runkeeper_upload_view(request,id=0):
return HttpResponseRedirect(url)
# Upload workout to Underarmour
@login_required()
@permission_required('workout.change_workout',fn=objectgetter(Workout, 'id'))
def workout_underarmour_upload_view(request,id=0):
message = ""
w = get_workout(id)
@@ -283,47 +276,44 @@ def workout_underarmour_upload_view(request,id=0):
# 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)
headers = {'Authorization': authorizationstring,
'Api-Key': UNDERARMOUR_CLIENT_KEY,
'user-agent': 'sanderroosendaal',
'Content-Type': 'application/json',
}
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)
url = "https://api.ua.com/v7.1/workout/"
response = requests.post(url,headers=headers,data=json.dumps(data,default=default))
authorizationstring = str('Bearer ' + thetoken)
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
if (response.status_code == 409 ):
message = "Duplicate error"
messages.error(request,message)
w.uploadedtounderarmour = -1
w.save()
elif (response.status_code == 201 or response.status_code==200):
underarmourid = underarmourstuff.getidfromresponse(response)
w.uploadedtounderarmour = underarmourid
w.save()
url = reverse('workout_edit_view',kwargs={'id':encoder.encode_hex(w.id)})
# check for duplicate error first
if (response.status_code == 409 ):
message = "Duplicate error"
messages.error(request,message)
w.uploadedtounderarmour = -1
w.save()
elif (response.status_code == 201 or response.status_code==200):
underarmourid = underarmourstuff.getidfromresponse(response)
w.uploadedtounderarmour = underarmourid
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_underarmour_upload_view: %s " % s.reason
messages.error(request,message)
return HttpResponseRedirect(url)
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)
url = reverse(r.defaultlandingpage,
@@ -334,7 +324,7 @@ def workout_underarmour_upload_view(request,id=0):
return HttpResponseRedirect(url)
# Upload workout to SportTracks
@login_required()
@permission_required('workout.change_workout',fn=objectgetter(Workout, 'id'))
def workout_sporttracks_upload_view(request,id=0):
message = ""
# ready to upload. Hurray
@@ -347,49 +337,46 @@ def workout_sporttracks_upload_view(request,id=0):
return HttpResponseRedirect("/rowers/me/sporttracksauthorize/")
if (checkworkoutuser(request.user,w)):
data = sporttracksstuff.createsporttracksworkoutdata(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)
data = sporttracksstuff.createsporttracksworkoutdata(w)
authorizationstring = str('Bearer ' + thetoken)
headers = {'Authorization': authorizationstring,
'user-agent': 'sanderroosendaal',
'Content-Type': 'application/json'}
if not data:
message = "Data error"
messages.error(request,message)
url = reverse(r.defaultlandingpage,
kwargs = {
'id':encoder.encode_hex(w.id),
})
return HttpResponseRedirect(url)
url = "https://api.sporttracks.mobi/api/v2/fitnessActivities.json"
response = requests.post(url,headers=headers,data=json.dumps(data,default=default))
authorizationstring = str('Bearer ' + thetoken)
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
if (response.status_code == 409 ):
message = "Duplicate error"
messages.error(request,message)
w.uploadedtosporttracks = -1
w.save()
elif (response.status_code == 201 or response.status_code==200):
s= response.json()
sporttracksid = sporttracksstuff.getidfromresponse(response)
w.uploadedtosporttracks = sporttracksid
w.save()
message = "Upload to SportTracks was successful"
messages.info(request,message)
# check for duplicate error first
if (response.status_code == 409 ):
message = "Duplicate error"
messages.error(request,message)
w.uploadedtosporttracks = -1
w.save()
elif (response.status_code == 201 or response.status_code==200):
s= response.json()
sporttracksid = sporttracksstuff.getidfromresponse(response)
w.uploadedtosporttracks = sporttracksid
w.save()
message = "Upload to SportTracks was successful"
messages.info(request,message)
url = reverse('workout_edit_view',kwargs={'id':encoder.encode_hex(w.id)})
return HttpResponseRedirect(url)
else:
s = response
message = "Something went wrong in workout_sporttracks_upload_view: %s" % s.reason
messages.error(request,message)
url = reverse('workout_edit_view',kwargs={'id':encoder.encode_hex(w.id)})
return HttpResponseRedirect(url)
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)
url = reverse(r.defaultlandingpage,
@@ -1613,5 +1600,3 @@ def workout_getstravaworkout_next(request):
url = reverse('workouts_view')
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):
r = getrequestrower(request)
try:
ps = PlannedSession.objects.get(id=psid)
except PlannedSession.DoesNotExist:
raise Http404("Planned Session does not exist")
ps = get_object_or_404(PlannedSession,pk=psid)
w = get_workout(id)
if (checkworkoutuser(request.user,w)==False):
return HttpResponseForbidden("Permission Error")
remove_workout_plannedsession(w,ps)
url = reverse(plannedsession_view,kwargs={'id':psid})

View File

@@ -32,10 +32,17 @@ from icalendar import Calendar, Event
from functools import reduce
from rules.contrib.views import PermissionRequiredMixin
import rowers.braintreestuff as braintreestuff
import rowers.payments as payments
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.template.loader import render_to_string
@@ -98,7 +105,7 @@ from rowers.models import (
TrainingMesoCycleForm, TrainingMicroCycleForm,
RaceLogo,RowerBillingAddressForm,PaidPlan,
AlertEditForm, ConditionEditForm,
PlannedSessionComment,CoachRequest,CoachOffer,checkaccessplanuser,
PlannedSessionComment,CoachRequest,CoachOffer,
VideoAnalysis
)
from rowers.models import (
@@ -275,6 +282,11 @@ def getfavorites(r,row):
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):
if request.user.is_anonymous:
return reverse('workout_view',kwargs={'id':id})
@@ -310,7 +322,7 @@ def getrequestrower(request,rowerid=0,userid=0,notpermanent=False):
except Rower.DoesNotExist:
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")
if notpermanent == False:
@@ -343,7 +355,7 @@ def getrequestplanrower(request,rowerid=0,userid=0,notpermanent=False):
except Rower.DoesNotExist:
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")
if notpermanent == False:
@@ -377,21 +389,6 @@ def get_workout(id):
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):
perc = 0
@@ -774,9 +771,9 @@ def get_stored_tasks_status(request):
return taskstatus
@login_required()
@permission_required('workout.change_workout',fn=get_workout_by_opaqueid,raise_exception=True)
def get_thumbnails(request,id):
row = get_workout_permitted(request.user,id)
row = get_workout_by_opaqueid(request,id)
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()
def session_jobs_view(request):
taskstatus = get_stored_tasks_status(request)
@@ -990,10 +966,6 @@ from rowers.utils import (
import rowers.datautils as datautils
from rowers.models import (
checkworkoutuser,checkaccessuser,checkviewworkouts,checkworkoutuserview
)
# Check if a user is a Coach member
def iscoachmember(user):
if not user.is_anonymous:
@@ -1044,21 +1016,7 @@ def hasplannedsessions(user):
return result
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
def add_defaultfavorites(r):

View File

@@ -64,8 +64,10 @@ def workout_video_view_mini(request,id=''):
else:
mode = 'erg'
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
else:
mayedit = False
@@ -176,7 +178,7 @@ def workout_video_view(request,id=''):
mode = 'erg'
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
else:
mayedit = False
@@ -271,20 +273,18 @@ def workout_video_view(request,id=''):
# 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/",
message="This functionality requires a Pro plan or higher",
redirect_field_name=None)
def workout_video_create_view(request,id=0):
# get workout
w = get_workout_permitted(request.user,id)
w = get_workout_by_opaqueid(request,id)
if w.workouttype in mytypes.otwtypes:
mode = 'water'
else:
mode = 'erg'
mayedit = checkworkoutuser(request.user,w) and isprorower(request.user.rower)
# get video ID and offset
if request.method == '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)
@login_required
@permission_required('workout.change_workout',fn=get_workout_by_opaqueid,raise_exception=True)
def otw_use_impeller(request,id=0):
w = get_workout(id)
if (checkworkoutuser(request.user,w)==False):
raise PermissionDenied("Access denied")
row = rdata(w.csvfilename)
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)
@login_required
@permission_required('workout.change_workout',fn=get_workout_by_opaqueid,raise_exception=True)
def otw_use_gps(request,id=0):
w = get_workout(id)
if (checkworkoutuser(request.user,w)==False):
raise PermissionDenied("Access denied")
row = rdata(w.csvfilename)
success = row.use_gpsdata()
@@ -748,20 +744,13 @@ def fitness_metric_view(request,mode='rower',days=42):
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",
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)
def workout_update_cp_view(request,id=0):
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.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)
@login_required()
@permission_required('workout.change_workout',fn=get_workout_by_opaqueid,raise_exception=True)
def workout_recalcsummary_view(request,id=0):
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
rowdata = rdata(filename)
if rowdata:
@@ -1359,7 +1341,7 @@ def team_comparison_select(request,
if 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")
firstworkoutquery = Workout.objects.filter(id=encoder.decode_hex(id))
@@ -1791,7 +1773,7 @@ def workouts_view(request,message='',successmessage='',
# check if access is allowed
if not checkviewworkouts(request.user,r):
if not is_rower_team_member(request.user,r):
raise PermissionDenied("Access denied")
@@ -2104,6 +2086,7 @@ def workout_fusion_list(request,id=0,message='',successmessage='',
})
# Basic view of workout
@permission_required('workout.view_workout',fn=get_workout_by_opaqueid,raise_exception=True)
def workout_view(request,id=0):
request.session['referer'] = absolute(request)['PATH']
@@ -2112,19 +2095,13 @@ def workout_view(request,id=0):
else:
rower = None
try:
row = Workout.objects.get(id=encoder.decode_hex(id))
except Workout.DoesNotExist:
raise Http404("Workout doesn't exist")
row = get_workout_by_opaqueid(request,id)
comments = WorkoutComment.objects.filter(workout=row)
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")
for i in g:
try:
@@ -2204,6 +2181,7 @@ def workout_view(request,id=0):
# 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",
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)
@@ -2213,13 +2191,6 @@ def workout_undo_smoothenpace_view(
row = get_workout(id)
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
row = rdata(filename)
if row == 0:
@@ -2243,6 +2214,7 @@ def workout_undo_smoothenpace_view(
# 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",
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)
@@ -2253,12 +2225,6 @@ def workout_smoothenpace_view(request,id=0,message="",successmessage=""):
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
row = rdata(filename)
@@ -2373,6 +2339,7 @@ def workout_crewnerd_summary_view(request,id=0,message="",successmessage=""):
'id':row.id})
# 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)
@@ -2382,12 +2349,6 @@ def workout_downloadwind_view(request,id=0,
row = get_workout(id)
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
rowdata = rdata(f1)
@@ -2448,6 +2409,7 @@ def workout_downloadwind_view(request,id=0,
return response
# 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)
def workout_downloadmetar_view(request,id=0,
airportcode=None,
@@ -2455,12 +2417,7 @@ def workout_downloadmetar_view(request,id=0,
row = get_workout(id)
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
rowdata = rdata(f1)
@@ -2523,6 +2480,7 @@ def workout_downloadmetar_view(request,id=0,
# 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)
def workout_wind_view(request,id=0,message="",successmessage=""):
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
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)
@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)
def workout_stream_view(request,id=0,message="",successmessage=""):
row = get_workout(id)
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
@@ -2745,23 +2692,15 @@ def workout_stream_view(request,id=0,message="",successmessage=""):
'the_div':div})
# 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)
def workout_otwsetpower_view(request,id=0,message="",successmessage=""):
w = get_workout(id)
r = getrower(request.user)
mayedit = 0
if request.user == w.user.user:
mayedit=1
if checkworkoutuser(request.user,w):
mayedit=1
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':
@@ -2879,15 +2818,11 @@ def workout_otwsetpower_view(request,id=0,message="",successmessage=""):
'form':form,
})
@login_required()
@permission_required('workout.change_workout',fn=get_workout_by_opaqueid,raise_exception=True)
def instroke_view(request,id=0):
w = get_workout(id)
r = getrower(request.user)
mayedit = 0
if request.user == w.user.user:
mayedit=1
if checkworkoutuser(request.user,w):
mayedit=1
mayedit = 1
breadcrumbs = [
{
@@ -2909,12 +2844,7 @@ def instroke_view(request,id=0):
g = GraphImage.objects.filter(workout=w).order_by("-creationdatetime")
# 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)
try:
@@ -2937,16 +2867,11 @@ def instroke_view(request,id=0):
# 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=''):
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)
instrokemetrics = rowdata.get_instroke_columns()
@@ -2995,14 +2920,12 @@ def instroke_chart(request,id=0,metric=''):
# data explorer
@login_required()
@permission_required('workout.change_workout',fn=get_workout_by_opaqueid,raise_exception=True)
def workout_data_view(request, id=0):
r = getrower(request.user)
w = get_workout(id)
if not checkworkoutuser(request.user,w):
raise PermissionDenied('Access Denied')
breadcrumbs = [
{
@@ -3100,7 +3023,7 @@ def workout_data_view(request, id=0):
# 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=""):
r = getrower(request.user)
@@ -3109,7 +3032,7 @@ def workout_stats_view(request,id=0,message="",successmessage=""):
mayedit = 0
if request.user == w.user.user:
mayedit=1
if checkworkoutuser(request.user,w):
if is_workout_user(request.user,w):
mayedit=1
breadcrumbs = [
@@ -3135,8 +3058,7 @@ def workout_stats_view(request,id=0,message="",successmessage=""):
# prepare data frame
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,
ignoreadvanced=False)
@@ -3377,11 +3299,12 @@ def workout_workflow_config2_view(request,userid=0):
# Workflow View
@login_required()
@permission_required('workout.change_workout',fn=get_workout_by_opaqueid,raise_exception=True)
def workout_workflow_view(request,id):
request.session['referer'] = absolute(request)['PATH']
request.session['lastworkout'] = id
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)
result = request.user.is_authenticated and ispromember(request.user)
@@ -3463,7 +3386,7 @@ def workout_workflow_view(request,id):
})
# 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):
try:
@@ -3487,12 +3410,12 @@ def workout_flexchart3_view(request,*args,**kwargs):
mayedit=0
if not request.user.is_anonymous:
r = getrower(request.user)
result = request.user.is_authenticated and ispromember(request.user)
result = ispromember(request.user)
if result:
promember=1
if request.user == row.user.user:
mayedit=1
if checkworkoutuser(request.user,row):
if is_workout_user(request.user,row):
mayedit=1
workouttype = 'ote'
@@ -3977,7 +3900,7 @@ def workout_comment_view(request,id=0):
# 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=""):
request.session[translation.LANGUAGE_SESSION_KEY] = USER_LANGUAGE
request.session['referer'] = absolute(request)['PATH']
@@ -3986,8 +3909,7 @@ def workout_edit_view(request,id=0,message="",successmessage=""):
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:
data = getsmallrowdata_db(['wash'],ids=[encoder.decode_hex(id)])
@@ -4293,7 +4215,7 @@ def workout_map_view(request,id=0):
# Image upload
@login_required()
@permission_required('workout.change_workout',fn=get_workout_by_opaqueid,raise_exception=True)
def workout_uploadimage_view(request,id):
is_ajax = False
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)
@@ -4398,7 +4319,7 @@ def workout_uploadimage_view(request,id):
# 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):
w = get_workout(id)
@@ -4406,26 +4327,24 @@ def workout_add_chart_view(request,id,plotnr=1):
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:
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:
try:
request.session['async_tasks'] += [(jobid,'make_plot')]
except KeyError:
request.session['async_tasks'] = [(jobid,'make_plot')]
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)})
@@ -4437,12 +4356,13 @@ def workout_add_chart_view(request,id,plotnr=1):
@login_required
@permission_required('workout.change_workout',fn=get_workout_by_opaqueid,raise_exception=True)
def workout_toggle_ranking(request,id=0):
is_ajax = False
if request.is_ajax():
is_ajax = True
row = get_workout_permitted(request.user,id)
row = get_workout_by_opaqueid(request,id)
row.rankingpiece = not row.rankingpiece
row.save()
@@ -5237,9 +5157,9 @@ def graph_show_view(request,id):
raise Http404("This workout doesn't exist")
# 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=""):
row = get_workout_permitted(request.user,id)
row = get_workout_by_opaqueid(request,id)
s = ""
# 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)
# Split a workout
@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)
def workout_split_view(request,id=0):
row = get_workout_permitted(request.user,id)
row = get_workout_by_opaqueid(request,id)
r = row.user
@@ -5398,8 +5319,8 @@ def workout_fusion_view(request,id1=0,id2=1):
w1 = Workout.objects.get(id=id1)
w2 = Workout.objects.get(id=id2)
r = w1.user
if (checkworkoutuser(request.user,w1)==False) or \
(checkworkoutuser(request.user,w2)==False):
if (is_workout_user(request.user,w1)==False) or \
(is_workout_user(request.user,w2)==False):
raise PermissionDenied("You are not allowed to use these workouts")
except Workout.DoesNotExist:
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
@login_required()
@permission_required('workout.change_workout',fn=get_workout_by_opaqueid,raise_exception=True)
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)
breadcrumbs = [
{
@@ -6024,10 +5945,11 @@ def workout_code_delete_view(request,id=0):
return HttpResponseRedirect(url)
class WorkoutDelete(DeleteView):
class WorkoutDelete(PermissionRequiredMixin,DeleteView):
login_required = True
model = Workout
template_name = 'workout_delete_confirm.html'
permission_required = 'workout.change_workout'
# extra parameters
def get_context_data(self, **kwargs):
@@ -6082,7 +6004,6 @@ class WorkoutDelete(DeleteView):
except Workout.DoesNotExist:
raise Http404("One of the workouts doesn't exist")
# 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