moved user and workout permission checks to rules
updated workoutviews, rest of views not done doesn't pass tests
This commit is contained in:
@@ -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")
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
|
||||
@@ -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/',
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
|
||||
@@ -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})
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user