Private
Public Access
1
0

Merge branch 'release/v9.26'

This commit is contained in:
Sander Roosendaal
2019-02-19 21:25:44 +01:00
15 changed files with 159 additions and 63 deletions
+1 -1
View File
@@ -172,7 +172,7 @@ def update_subscription(rower,data,method='up'):
if rower.paidplan != 'coach': if rower.paidplan != 'coach':
try: try:
coachgroup = coach.mycoachgroup coachgroup = rower.mycoachgroup
except CoachingGroup.DoesNotExist: except CoachingGroup.DoesNotExist:
coachgroup = CoachingGroup() coachgroup = CoachingGroup()
coachgroup.save() coachgroup.save()
+27
View File
@@ -1023,7 +1023,34 @@ def checkworkoutuser(user,workout):
except Rower.DoesNotExist: 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)
print Rower.objects.filter(team__in=teams)
if rower in Rower.objects.filter(team__in=teams):
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']]
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 # Check if user is coach or rower
def checkaccessuser(user,rower): def checkaccessuser(user,rower):
try: try:
+18 -1
View File
@@ -189,7 +189,7 @@
</td> </td>
<td> {{ workout.date|date:"Y-m-d" }} </td> <td> {{ workout.date|date:"Y-m-d" }} </td>
<td> {{ workout.starttime|date:"H:i" }} </td> <td> {{ workout.starttime|date:"H:i" }} </td>
{% if workout.user.user == user or user == team.manager %} {% if workout|may_edit:request %}
{% if workout.name != '' %} {% if workout.name != '' %}
<td> <td>
<a href={% url rower.defaultlandingpage id=workout.id|encode %}> <a href={% url rower.defaultlandingpage id=workout.id|encode %}>
@@ -215,18 +215,27 @@
<td> {{ workout.maxhr }} </td> <td> {{ workout.maxhr }} </td>
{% if team %} {% if team %}
<td colspan="2"> <td colspan="2">
{% if workout|may_edit:request %}
<a class="small" href="/rowers/{{ workout.user.id }}/list-workouts/"> <a class="small" href="/rowers/{{ workout.user.id }}/list-workouts/">
{{ workout.user.user.first_name }} {{ workout.user.user.first_name }}
{{ workout.user.user.last_name }} {{ workout.user.user.last_name }}
</a> </a>
{% else %}
{{ workout.user.user.first_name }}
{{ workout.user.user.last_name }}
{% endif %}
</td> </td>
{% endif %} {% endif %}
<td> <td>
{% if workout|may_edit:request %}
<a class="small" <a class="small"
href="/rowers/workout/{{ workout.id|encode }}/edit/" href="/rowers/workout/{{ workout.id|encode }}/edit/"
title="Edit"> title="Edit">
<i class="fas fa-pencil-alt fa-fw"></i> <i class="fas fa-pencil-alt fa-fw"></i>
</a> </a>
{% else %}
&nbsp;
{% endif %}
</td> </td>
<td> <td>
<a class="small" <a class="small"
@@ -236,17 +245,25 @@
</a> </a>
</td> </td>
<td> <td>
{% if workout|may_edit:request %}
<a class="small" <a class="small"
href="/rowers/workout/{{ workout.id|encode }}/stats/" href="/rowers/workout/{{ workout.id|encode }}/stats/"
title="Stats"> title="Stats">
<i class="fal fa-table fa-fw"></i> <i class="fal fa-table fa-fw"></i>
</a> </a>
{% else %}
&nbsp;
{% endif %}
</td> </td>
<td> <td>
{% if workout.user.user == user or user == team.manager %}
<a class="small" href="/rowers/workout/{{ workout.id|encode }}/delete/" <a class="small" href="/rowers/workout/{{ workout.id|encode }}/delete/"
title="Delete"> title="Delete">
<i class="fas fa-trash-alt fa-fw"></i> <i class="fas fa-trash-alt fa-fw"></i>
</a> </a>
{% else %}
&nbsp;
{% endif %}
</td> </td>
</tr> </tr>
+16 -17
View File
@@ -40,7 +40,7 @@
</li> </li>
<li id="sessions-coach"> <li id="sessions-coach">
<a href="/rowers/sessions/coach/?when={{ timeperiod }}"> <a href="/rowers/sessions/coach/?when={{ timeperiod }}">
<i class="fas fa-bullhorn fa-fw"></i>&nbsp;Coach View <i class="fas fa-bullhorn fa-fw"></i>&nbsp;Training Group View
</a> </a>
</li> </li>
<li id="sessions-print"> <li id="sessions-print">
@@ -82,27 +82,26 @@
<p>&nbsp;</p> <p>&nbsp;</p>
{% if user.is_authenticated and user|is_planmember %}
{% if user.is_authenticated and user|is_manager %}
<p>&nbsp;</p> <p>&nbsp;</p>
{% if user|team_members %}
{% if user|coach_rowers %}
<ul class="cd-accordion-menu animated"> <ul class="cd-accordion-menu animated">
<li class="has-children" id="athletes"> <li class="has-children" id="athletes">
<input type="checkbox" name="athlete-selector" id="athlete-selector"> <input type="checkbox" name="athlete-selector" id="athlete-selector">
<label for="athlete-selector"><i class="fas fa-users fa-fw"></i>&nbsp;Athletes</label> <label for="athlete-selector"><i class="fas fa-users fa-fw"></i>&nbsp;Group Members</label>
<ul> <ul>
{% for member in user|coach_rowers %} {% for member in user|team_members %}
<a href={{ request.path|userurl:member.user }}?when={{ timeperiod }}> <li>
<i class="fas fa-user fa-fw"></i> <a href={{ request.path|userurl:member }}>
{% if member.user == rower.user %} <i class="fas fa-user fa-fw"></i>
&bull; {% if member == rower.user%}
{% else %} &bull;
&nbsp; {% else %}
{% endif %} &nbsp;
{{ member.user.first_name }} {{ member.user.last_name }} {% endif %}
</a> {{ member.first_name }} {{ member.last_name }}
</a>
</li>
{% endfor %} {% endfor %}
</ul> </ul>
</li> </li>
+12 -11
View File
@@ -45,8 +45,11 @@
</li> </li>
</ul> <!-- cd-accordion-menu --> </ul> <!-- cd-accordion-menu -->
{% if user.is_authenticated and user|is_manager %} {% if user.is_authenticated and user|is_manager %}
<p>&nbsp;</p> <p>&nbsp;</p>
{% if user|coach_rowers %} {% if user|coach_rowers %}
<ul class="cd-accordion-menu animated"> <ul class="cd-accordion-menu animated">
<li class="has-children" id="athletes"> <li class="has-children" id="athletes">
@@ -54,17 +57,15 @@
<label for="athlete-selector"><i class="fas fa-users fa-fw"></i>&nbsp;Athletes</label> <label for="athlete-selector"><i class="fas fa-users fa-fw"></i>&nbsp;Athletes</label>
<ul> <ul>
{% for member in user|coach_rowers %} {% for member in user|coach_rowers %}
<li> <a href={{ request.path|userurl:member.user }}?when={{ timeperiod }}>
<a href={{ request.path|userurl:member.user }}> <i class="fas fa-user fa-fw"></i>
<i class="fas fa-user fa-fw"></i> {% if member == rower.user %}
{% if member.user == rower.user and not team %} &bull;
&bull; {% else %}
{% else %} &nbsp;
&nbsp; {% endif %}
{% endif %} {{ member.user.first_name }} {{ member.user.last_name }}
{{ member.user.first_name }} {{ member.user.last_name }} </a>
</a>
</li>
{% endfor %} {% endfor %}
</ul> </ul>
</li> </li>
+6 -6
View File
@@ -346,7 +346,7 @@ def has_teams(user):
def team_members(user): def team_members(user):
try: try:
therower = Rower.objects.get(user=user) therower = Rower.objects.get(user=user)
if therower.rowerplan != 'coach': if therower.rowerplan == 'basic':
return [] return []
teams = Team.objects.filter(manager=user) teams = Team.objects.filter(manager=user)
members = Rower.objects.filter( members = Rower.objects.filter(
@@ -364,7 +364,7 @@ def team_members(user):
def team_rowers(user): def team_rowers(user):
try: try:
therower = Rower.objects.get(user=user) therower = Rower.objects.get(user=user)
if therower.rowerplan != 'coach': if therower.rowerplan == 'basic':
return [] return []
teams = Team.objects.filter(manager=user) teams = Team.objects.filter(manager=user)
members = Rower.objects.filter(team__in=teams).distinct().order_by( members = Rower.objects.filter(team__in=teams).distinct().order_by(
@@ -464,11 +464,11 @@ def is_final(race):
@register.filter @register.filter
def userurl(path,member): def userurl(path,member):
pattern = re.compile('user\/\d+') pattern = re.compile('user\/\d+/')
userstring = 'user/%s/' % member.id userstring = 'user/%s/' % member.id
# remove team # remove team
tpattern = re.compile('\/team\/\d+') tpattern = re.compile('\/team\/\d+/')
if tpattern.search(path) is not None: if tpattern.search(path) is not None:
path = tpattern.sub('',path) path = tpattern.sub('',path)
@@ -481,11 +481,11 @@ def userurl(path,member):
@register.filter @register.filter
def teamurl(path,team): def teamurl(path,team):
pattern = re.compile('team\/\d+') pattern = re.compile('team\/\d+/')
teamstring = 'team/%s/' % team.id teamstring = 'team/%s/' % team.id
# remove user # remove user
upattern = re.compile('\/user\/\d+') upattern = re.compile('\/user\/\d+/')
if upattern.search(path) is not None: if upattern.search(path) is not None:
path = upattern.sub('',path) path = upattern.sub('',path)
+7
View File
@@ -1414,3 +1414,10 @@ class PermissionsCoachingTests(TestCase):
## Basic and Pro users can create races ## Basic and Pro users can create races
## Basic users can subscribe to any race ## Basic users can subscribe to any race
# group related
## group members can see but not edit each other's workouts and charts
## group members can see but not edit each other's plans
Binary file not shown.
+1 -1
View File
@@ -638,7 +638,7 @@ urlpatterns = [
name='plannedsessions_manage_view'), name='plannedsessions_manage_view'),
url(r'^sessions/coach/$',views.plannedsessions_coach_view, url(r'^sessions/coach/$',views.plannedsessions_coach_view,
name='plannedsessions_coach_view'), name='plannedsessions_coach_view'),
url(r'^sessions/coach/user/\d+/$',views.plannedsessions_coach_view, url(r'^sessions/coach/user/(?P<userid>\d+)/$',views.plannedsessions_coach_view,
name='plannedsessions_coach_view'), name='plannedsessions_coach_view'),
url(r'^sessions/print/?/$',views.plannedsessions_print_view, url(r'^sessions/print/?/$',views.plannedsessions_print_view,
name='plannedsessions_print_view'), name='plannedsessions_print_view'),
+15 -13
View File
@@ -2,7 +2,7 @@ from statements import *
@login_required() @login_required()
def plannedsession_comment_view(request,id=0,userid=0): def plannedsession_comment_view(request,id=0,userid=0):
r = getrequestrower(request,userid=userid) r = getrequestplanrower(request,userid=userid)
try: try:
ps = PlannedSession.objects.get(id=id) ps = PlannedSession.objects.get(id=id)
@@ -170,7 +170,7 @@ def plannedsession_multiclone_view(
request, request,
userid=0,): userid=0,):
r = getrequestrower(request,userid=userid) r = getrequestplanrower(request,userid=userid)
startdate,enddate = get_dates_timeperiod(request) startdate,enddate = get_dates_timeperiod(request)
@@ -301,7 +301,7 @@ def plannedsession_create_view(request,
startdatestring='', startdatestring='',
enddatestring=''): enddatestring=''):
r = getrequestrower(request,userid=userid) r = getrequestplanrower(request,userid=userid)
@@ -442,7 +442,7 @@ def plannedsession_multicreate_view(request,
extrasessions=int(extrasessions) extrasessions=int(extrasessions)
r = getrequestrower(request,userid=userid) r = getrequestplanrower(request,userid=userid)
startdate,enddate = get_dates_timeperiod(request) startdate,enddate = get_dates_timeperiod(request)
@@ -547,12 +547,13 @@ def plannedsession_multicreate_view(request,
return render(request,'plannedsession_multicreate.html',context) return render(request,'plannedsession_multicreate.html',context)
# Manager creates sessions for entire team # Manager creates sessions for entire team
@user_passes_test(iscoachmember,login_url="/rowers/paidplans/", @user_passes_test(hasplannedsessions,login_url="/rowers/paidplans/",
message="This functionality requires a Coach or Self-Coach plan",
redirect_field_name=None) redirect_field_name=None)
def plannedsession_teamcreate_view(request, def plannedsession_teamcreate_view(request,
teamid=0,userid=0): teamid=0,userid=0):
therower = getrequestrower(request,userid=userid) therower = getrequestplanrower(request,userid=userid)
@@ -716,11 +717,12 @@ def plannedsession_teamcreate_view(request,
# Manager edits sessions for entire team # Manager edits sessions for entire team
@user_passes_test(iscoachmember,login_url="/rowers/paidplans/", @user_passes_test(iscoachmember,login_url="/rowers/paidplans/",
message="This functionality requires a Coach or Self-Coach plan",
redirect_field_name=None) redirect_field_name=None)
def plannedsession_teamedit_view(request, def plannedsession_teamedit_view(request,
sessionid=0,userid=0): sessionid=0,userid=0):
r = getrequestrower(request,userid=userid) r = getrequestplanrower(request,userid=userid)
try: try:
@@ -880,7 +882,7 @@ def plannedsessions_coach_view(request,
teamid=0,userid=0): teamid=0,userid=0):
therower = getrower(request.user) therower = getrequestplanrower(request,userid=userid)
startdate,enddate = get_dates_timeperiod(request) startdate,enddate = get_dates_timeperiod(request)
@@ -984,7 +986,7 @@ from rowers.plannedsessions import cratiocolors
def plannedsessions_view(request, def plannedsessions_view(request,
userid=0,startdatestring='',enddatestring=''): userid=0,startdatestring='',enddatestring=''):
r = getrequestrower(request,userid=userid) r = getrequestplanrower(request,userid=userid)
if startdatestring: if startdatestring:
try: try:
@@ -1127,7 +1129,7 @@ def plannedsessions_view(request,
@login_required() @login_required()
def plannedsessions_print_view(request,userid=0): def plannedsessions_print_view(request,userid=0):
r = getrequestrower(request,userid=userid) r = getrequestplanrower(request,userid=userid)
@@ -1330,7 +1332,7 @@ def plannedsessions_manage_view(request,userid=0,
redirect_field_name=None) redirect_field_name=None)
def plannedsession_clone_view(request,id=0,userid=0): def plannedsession_clone_view(request,id=0,userid=0):
r = getrequestrower(request,userid=userid) r = getrequestplanrower(request,userid=userid)
startdate,enddate = get_dates_timeperiod(request) startdate,enddate = get_dates_timeperiod(request)
@@ -1391,7 +1393,7 @@ def plannedsession_clone_view(request,id=0,userid=0):
redirect_field_name=None) redirect_field_name=None)
def plannedsession_edit_view(request,id=0,userid=0): def plannedsession_edit_view(request,id=0,userid=0):
r = getrequestrower(request,userid=userid) r = getrequestplanrower(request,userid=userid)
@@ -1536,7 +1538,7 @@ def plannedsession_detach_view(request,id=0,psid=0):
@login_required() @login_required()
def plannedsession_view(request,id=0,userid=0): def plannedsession_view(request,id=0,userid=0):
r = getrequestrower(request,userid=userid) r = getrequestplanrower(request,userid=userid)
+35 -2
View File
@@ -88,7 +88,7 @@ from rowers.models import (
microcyclecheckdates,mesocyclecheckdates,macrocyclecheckdates, microcyclecheckdates,mesocyclecheckdates,macrocyclecheckdates,
TrainingMesoCycleForm, TrainingMicroCycleForm, TrainingMesoCycleForm, TrainingMicroCycleForm,
RaceLogo,RowerBillingAddressForm,PaidPlan, RaceLogo,RowerBillingAddressForm,PaidPlan,
PlannedSessionComment,CoachRequest,CoachOffer, PlannedSessionComment,CoachRequest,CoachOffer,checkaccessplanuser
) )
from rowers.models import ( from rowers.models import (
RowerPowerForm,RowerForm,GraphImage,AdvancedWorkoutForm, RowerPowerForm,RowerForm,GraphImage,AdvancedWorkoutForm,
@@ -300,6 +300,39 @@ def getrequestrower(request,rowerid=0,userid=0,notpermanent=False):
return r return r
def getrequestplanrower(request,rowerid=0,userid=0,notpermanent=False):
userid = int(userid)
rowerid = int(rowerid)
if notpermanent == False:
if rowerid == 0 and 'rowerid' in request.session:
rowerid = request.session['rowerid']
if userid != 0:
rowerid = 0
try:
if rowerid != 0:
r = Rower.objects.get(id=rowerid)
elif userid != 0:
u = User.objects.get(id=userid)
r = getrower(u)
else:
r = getrower(request.user)
except Rower.DoesNotExist:
raise Http404("Rower doesn't exist")
if not checkaccessplanuser(request.user,r):
raise PermissionDenied("You have no access to this user")
if notpermanent == False:
request.session['rowerid'] = r.id
return r
def getrower(user): def getrower(user):
try: try:
@@ -911,7 +944,7 @@ from rowers.utils import (
import rowers.datautils as datautils import rowers.datautils as datautils
from rowers.models import checkworkoutuser,checkaccessuser from rowers.models import checkworkoutuser,checkaccessuser,checkviewworkouts
# Check if a user is a Coach member # Check if a user is a Coach member
def iscoachmember(user): def iscoachmember(user):
+14 -7
View File
@@ -186,15 +186,22 @@ def rower_teams_view(request,message='',successmessage=''):
invitedcoaches = [rekwest.coach for rekwest in mycoachrequests] invitedcoaches = [rekwest.coach for rekwest in mycoachrequests]
coaches = teams.rower_get_coaches(r) coaches = teams.rower_get_coaches(r)
potentialcoaches = [t.manager for t in memberteams if t.manager not in coaches ] print coaches,'aap'
potentialcoaches = [c for c in potentialcoaches if c.rower not in invitedcoaches]
potentialcoaches = [t.manager for t in memberteams if t.manager not in coaches and t.manager.rower.rowerplan == 'coach']
potentialcoaches = [c for c in potentialcoaches if c.rower not in invitedcoaches+coaches]
coachees = teams.coach_getcoachees(r) coachees = teams.coach_getcoachees(r)
potentialathletes = Rower.objects.filter( if request.user.rower.rowerplan == 'coach':
team__in=myteams).exclude( potentialathletes = Rower.objects.filter(
user__in=invitedathletes).exclude( team__in=myteams).exclude(
user=request.user user__in=invitedathletes).exclude(
).exclude(coachinggroups__in=[request.user.rower.mycoachgroup]) user=request.user
).exclude(coachinggroups__in=[request.user.rower.mycoachgroup])
else:
potentialathletes = []
# clubsize = teams.count_invites(request.user)+teams.count_club_members(request.user) # clubsize = teams.count_invites(request.user)+teams.count_club_members(request.user)
+2 -2
View File
@@ -856,7 +856,7 @@ def virtualevent_compare_view(request,id=0):
workouts = [] workouts = []
for id in workoutids: for id in workoutids:
try: try:
workouts.append(Workout.objects.get(id=encode.decode_hex(id))) workouts.append(Workout.objects.get(id=id))
except Workout.DoesNotExist: except Workout.DoesNotExist:
pass pass
@@ -1157,7 +1157,7 @@ def workouts_view(request,message='',successmessage='',
r = getrequestrower(request,rowerid=rowerid,userid=userid) r = getrequestrower(request,rowerid=rowerid,userid=userid)
# check if access is allowed # check if access is allowed
if not checkaccessuser(request.user,r): if not checkviewworkouts(request.user,r):
raise PermissionDenied("Access denied") raise PermissionDenied("Access denied")
if startdatestring: if startdatestring:
+1
View File
@@ -75,6 +75,7 @@ urlpatterns += [
url(r'^twitter\_callback',rowersviews.rower_process_twittercallback), url(r'^twitter\_callback',rowersviews.rower_process_twittercallback),
url(r'^i18n/', include('django.conf.urls.i18n')), url(r'^i18n/', include('django.conf.urls.i18n')),
url(r'^tz_detect/', include('tz_detect.urls')), url(r'^tz_detect/', include('tz_detect.urls')),
url(r'^jsi18n/', 'django.views.i18n.javascript_catalog',name='jsi18n'),
] ]
+4 -2
View File
@@ -12,7 +12,7 @@
<title>{% block title %}Rowsandall Rowing Data Analytics{% endblock %}</title> <title>{% block title %}Rowsandall Rowing Data Analytics{% endblock %}</title>
{% block scripts %} {% endblock %} {% block scripts %} {% endblock %}
<script type="text/javascript" src="/admin/jsi18n/"></script> <script type="text/javascript" src="/jsi18n/"></script>
<script type="text/javascript" src="/static/admin/js/core.js"></script> <script type="text/javascript" src="/static/admin/js/core.js"></script>
<script type="text/javascript" src="/static/admin/js/jquery.min.js"></script> <script type="text/javascript" src="/static/admin/js/jquery.min.js"></script>
<script type="text/javascript" src="/static/admin/js/jquery.init.js"></script> <script type="text/javascript" src="/static/admin/js/jquery.init.js"></script>
@@ -31,7 +31,9 @@
<link rel="stylesheet" href="/static/css/bokeh-0.12.3.min.css" type="text/css" /> <link rel="stylesheet" href="/static/css/bokeh-0.12.3.min.css" type="text/css" />
<link rel="stylesheet" href="/static/css/bokeh-widgets-0.12.3.min.css" type="text/css" /> <link rel="stylesheet" href="/static/css/bokeh-widgets-0.12.3.min.css" type="text/css" />
<link rel="stylesheet" type="text/css" href="/static/admin/css/forms.css"/>
<link rel="stylesheet" type="text/css" href="/static/admin/css/widgets.css"/>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" >
<link rel="shortcut icon" href="/static/img/favicon.ico" type="image/x-icon" /> <link rel="shortcut icon" href="/static/img/favicon.ico" type="image/x-icon" />
<link rel="icon" sizes="32x32" href="/static/img/favicon-32x32.png" type="image/png"/> <link rel="icon" sizes="32x32" href="/static/img/favicon-32x32.png" type="image/png"/>
<link rel="icon" sizes="64x64" href="/static/img/favicon-64x64.png" type="image/png"/> <link rel="icon" sizes="64x64" href="/static/img/favicon-64x64.png" type="image/png"/>