diff --git a/rowers/rower_rules.py b/rowers/rower_rules.py index 74709c9d..2697ac2c 100644 --- a/rowers/rower_rules.py +++ b/rowers/rower_rules.py @@ -240,11 +240,107 @@ rules.add_perm('workout.view_workout',can_view_workout) # replaces checkworkoutu """ +# Training Target rules +@rules.predicate +def can_view_target(user,target): + if user.is_anonymous: + return False + if user == target.manager.user: + return True + + # a target's coach can view as well + if is_coach_user(user,target.manager.user): + return True + + # the object can view as well + if user.rower in target.rowers.all(): + return True + +@rules.predicate +def can_change_target(user,target): + if user.is_anonymous: + return False + return user == target.manager.user + +@rules.predicate +def can_delete_target(user,target): + if user.is_anonymous: + return False + return user == target.manager.user + +rules.add_perm('target.view_target',can_view_target) +rules.add_perm('target.change_target',can_change_target) +rules.add_perm('target.delete_target',can_delete_target) + +@rules.predicate +def can_view_plan(user,plan): + if user.is_anonymous: + return False + if user == plan.manager.user: + return True + + # a plan's coach can view as well + if is_coach_user(user,plan.manager.user): + return True + + # the object can view as well + if user.rower in plan.rowers.all(): + return True + +@rules.predicate +def can_change_plan(user,plan): + if user.is_anonymous: + return False + return user == plan.manager.user + +@rules.predicate +def can_delete_plan(user,plan): + if user.is_anonymous: + return False + return user == plan.manager.user + +rules.add_perm('plan.view_plan',can_view_plan) +rules.add_perm('plan.change_plan',can_change_plan) +rules.add_perm('plan.delete_plan',can_delete_plan) + +@rules.predicate +def can_view_cycle(user,cycle): + try: + return can_view_cycle(user,cycle.plan) + except AttributeError: + return can_view_plan(user,cycle.plan) + + return False + +@rules.predicate +def can_change_cycle(user,cycle): + try: + return can_change_cycle(user,cycle.plan) + except AttributeError: + return can_change_plan(user,cycle.plan) + + return False + +@rules.predicate +def can_delete_cycle(user,cycle): + try: + return can_delete_cycle(user,cycle.plan) + except AttributeError: + return can_delete_plan(user,cycle.plan) + + return False + + +rules.add_perm('cycle.view_cycle',can_view_cycle) +rules.add_perm('cycle.change_cycle',can_change_cycle) +rules.add_perm('cycle.delete_cycle',can_delete_cycle) + + # check if user has view access to session @rules.predicate def can_view_session(user,session): if session.sessiontype in ['race','indoorrace']: - return True + return True if user.is_anonymous: return False # session manager can view session @@ -274,8 +370,24 @@ def can_change_session(user,session): return False +@rules.predicate +def can_delete_session(user,session): + if user.is_anonymous: + return False + + if session.sessiontype in ['race','indoorrace']: + return False + + if user == session.manager: + return True + + return False + rules.add_perm('plannedsession.view_session',can_view_session) rules.add_perm('plannedsession.change_session',can_change_session) +rules.add_perm('plannedsession.delete_session',can_delete_session) + + # checkaccessplanuser (models.py) # getrequestrower, getrequestplanrower diff --git a/rowers/views/planviews.py b/rowers/views/planviews.py index c5c6d9ac..26f6aa22 100644 --- a/rowers/views/planviews.py +++ b/rowers/views/planviews.py @@ -1900,8 +1900,7 @@ class PlannedSessionDelete(DeleteView): def get_object(self, *args, **kwargs): obj = super(PlannedSessionDelete, self).get_object(*args, **kwargs) - m = Rower.objects.get(user=obj.manager) - if not is_coach_user(self.request.user,m.user): + if not can_delete_session(self.request.user,obj): raise PermissionDenied('You are not allowed to delete this planned session') return obj @@ -2039,17 +2038,11 @@ def rower_create_trainingplan(request,userid=0): @user_passes_test(isplanmember,login_url="/rowers/paidplans", message="This functionality requires a Coach or Self-Coach plan", redirect_field_name=None) +@permission_required('target.delete_target',fn=get_target_by_pk,raise_exception=True) def rower_delete_trainingtarget(request,id=0): - try: - target = TrainingTarget.objects.get(id=id) - except TrainingPlan.DoesNotExist: - raise Http404("Training Plan Does Not Exist") - if is_coach_user(request.user,target.manager): - target.delete() - messages.info(request,"We have deleted the training target") - else: - raise PermissionDenied("Access denied") + target = get_object_or_404(TrainingTarget,pk=id) + target.delete() url = reverse(rower_create_trainingplan) @@ -2059,17 +2052,10 @@ def rower_delete_trainingtarget(request,id=0): @user_passes_test(isplanmember,login_url="/rowers/paidplans", message="This functionality requires a Coach or Self-Coach plan", redirect_field_name=None) +@permission_required('target.delete_plan',fn=get_plan_by_pk,raise_exception=True) def rower_delete_trainingplan(request,id=0): - try: - plan = TrainingPlan.objects.get(id=id) - except TrainingPlan.DoesNotExist: - raise Http404("Training Plan Does Not Exist") - - if is_coach_user(request.user,plan.manager.user): - plan.delete() - messages.info(request,"We have deleted the training plan") - else: - raise PermissionDenied("Access denied") + plan = get_object_or_404(TrainingPlan,pk=id) + plan.delete() url = reverse(rower_create_trainingplan) @@ -2082,7 +2068,7 @@ class TrainingPlanDelete(DeleteView): def get_object(self, *args, **kwargs): obj = super(TrainingPlanDelete, self).get_object(*args, **kwargs) - if not is_coach_user(self.request.user,obj.manager.user): + if not can_delete_plan(self.request.user,obj): raise PermissionDenied('You are not allowed to delete this training plan') return obj @@ -2148,7 +2134,7 @@ class MicroCycleDelete(DeleteView): def get_object(self, *args, **kwargs): obj = super(MicroCycleDelete, self).get_object(*args, **kwargs) - if not is_coach_user(self.request.user,obj.plan.plan.plan.manager.user): + if not can_delete_cycle(self.request.user,obj): raise PermissionDenied('You are not allowed to delete this training plan cycle') return obj @@ -2210,7 +2196,7 @@ class MesoCycleDelete(DeleteView): def get_object(self, *args, **kwargs): obj = super(MesoCycleDelete, self).get_object(*args, **kwargs) - if not is_coach_user(self.request.user,obj.plan.plan.manager.user): + if not can_delete_cycle(self.request.user,obj): raise PermissionDenied('You are not allowed to delete this training plan cycle') return obj @@ -2264,7 +2250,7 @@ class MacroCycleDelete(DeleteView): def get_object(self, *args, **kwargs): obj = super(MacroCycleDelete, self).get_object(*args, **kwargs) - if not is_coach_user(self.request.user,obj.plan.manager.user): + if not can_delete_cycle(self.request.user,obj): raise PermissionDenied('You are not allowed to delete this training plan cycle') return obj @@ -2363,6 +2349,7 @@ def rower_trainingplan_execution_view(request, @user_passes_test(isplanmember,login_url="/rowers/paidplans", message="This functionality requires a Coach or Self-Coach plan", redirect_field_name=None) +@permission_required('plan.can_view',fn=get_plan_by_pk,raise_exception=True) def rower_trainingplan_view(request, id=0, userid=0, @@ -2373,17 +2360,7 @@ def rower_trainingplan_view(request, startdate,enddate = get_dates_timeperiod(request) - - try: - plan = TrainingPlan.objects.get(id=id) - except TrainingPlan.DoesNotExist: - raise Http404("Training Plan Does Not Exist") - - r = getrequestrower(request,userid=userid) - - if not is_coach_user(request.user,plan.manager.user): - if request.user.rower not in plan.rowers.all(): - raise PermissionDenied("Access denied") + plan = get_object_or_404(TrainingPlan,pk=id) createmacrofillers(plan) macrocycles = TrainingMacroCycle.objects.filter( @@ -2507,10 +2484,7 @@ class TrainingMacroCycleUpdate(UpdateView): def get_object(self, *args, **kwargs): obj = super(TrainingMacroCycleUpdate, self).get_object(*args, **kwargs) - if obj.plan.manager is not None and self.request.user.rower != obj.plan.manager: - raise PermissionDenied('You are not allowed to edit this training plan cycle') - - if not is_coach_user(self.request.user,obj.plan.manager.user): + if not can_change_cycle(self.request.user,obj): raise PermissionDenied('You are not allowed to edit this training plan cycle') else: obj.type = 'userdefined' @@ -2581,7 +2555,7 @@ class TrainingMesoCycleUpdate(UpdateView): def get_object(self, *args, **kwargs): obj = super(TrainingMesoCycleUpdate, self).get_object(*args, **kwargs) - if obj.plan.plan.manager is not None and self.request.user.rower != obj.plan.plan.manager: + if not can_change_cycle(self.request.user,obj): raise PermissionDenied('You are not allowed to edit this training plan cycle') else: @@ -2659,7 +2633,7 @@ class TrainingMicroCycleUpdate(UpdateView): def get_object(self, *args, **kwargs): obj = super(TrainingMicroCycleUpdate, self).get_object(*args, **kwargs) - if obj.plan.plan.plan.manager is not None and self.request.user.rower != obj.plan.plan.plan.manager: + if not can_change_cycle(self.request.user,obj): raise PermissionDenied('You are not allowed to edit this training plan cycle') @@ -2724,10 +2698,8 @@ class TrainingPlanUpdate(UpdateView): def get_object(self, *args, **kwargs): obj = super(TrainingPlanUpdate, self).get_object(*args, **kwargs) - if obj.manager is not None and self.request.user.rower != obj.manager: + if not can_change_plan(self.request.user,obj): raise PermissionDenied('You are not allowed to edit this training plan cycle') - if obj.manager.rowerplan not in ['coach','freecoach','plan']: - raise PermissionDenied('You are not allowed to edit this training plan') return obj @@ -2776,7 +2748,7 @@ class TrainingTargetUpdate(UpdateView): def get_object(self, *args, **kwargs): obj = super(TrainingTargetUpdate, self).get_object(*args, **kwargs) - if obj.manager is not None and self.request.user.rower != obj.manager: + if not can_change_target(self.request.user,obj): raise PermissionDenied('You are not allowed to edit this training plan cycle') return obj @@ -2786,14 +2758,9 @@ from rowers.utils import allsundays @user_passes_test(isplanmember,login_url="/rowers/paidplans", message="This functionality requires a Coach or Self-Coach plan", redirect_field_name=None) +@permission_required('cycle.change_cycle',fn=get_meso_by_pk,raise_exception=True) def planmesocyclebyweek(request,id=0,userid=0): - try: - cycle = TrainingMesoCycle.objects.get(id=id) - except TrainingMesoCycle.DoesNotExist: - raise Http404("Training Cycle does not exist") - - if not is_coach_user(request.user,cycle.plan.plan.manager.user): - raise PermissionDenied("You are not allowed to do this") + cycle = get_object_or_404(TrainingMesoCycle,pk=id) micros = TrainingMicroCycle.objects.filter(plan=cycle) for m in micros: @@ -2841,14 +2808,9 @@ from rowers.utils import allmonths @user_passes_test(isplanmember,login_url="/rowers/paidplans", message="This functionality requires a Coach or Self-Coach plan", redirect_field_name=None) +@permission_required('cycle.change_cycle',fn=get_macro_by_pk,raise_exception=True) def planmacrocyclebymonth(request,id=0,userid=0): - try: - cycle = TrainingMacroCycle.objects.get(id=id) - except TrainingMacroCycle.DoesNotExist: - raise Http404("Training Cycle does not exist") - - if not is_coach_user(request.user,cycle.plan.manager.user): - raise PermissionDenied("You are not allowed to do this") + cycle = get_object_or_404(TrainingMacroCycle,pk=id) mesos = TrainingMesoCycle.objects.filter(plan=cycle) for m in mesos: diff --git a/rowers/views/statements.py b/rowers/views/statements.py index 315f4df4..3048a288 100644 --- a/rowers/views/statements.py +++ b/rowers/views/statements.py @@ -40,7 +40,9 @@ from rowers.opaque import encoder from rowers.rower_rules import ( ispromember,is_coach_user,is_team_member,is_rower_team_member, - is_workout_user,isplanmember, + is_workout_user,isplanmember,can_delete_session, + can_view_target,can_change_target,can_delete_target, + can_view_plan,can_change_plan,can_delete_plan, ) from django.shortcuts import render @@ -289,9 +291,30 @@ def get_workout_by_opaqueid(request,id,**kwargs): pk = encoder.decode_hex(id) return get_object_or_404(Workout,pk=pk) -def get_session_by_pk(request,id): +def get_session_by_pk(request,*args,**kwargs): + id = kwargs['id'] return get_object_or_404(PlannedSession,pk=id) +def get_target_by_pk(request,*args,**kwargs): + id = kwargs['id'] + return get_object_or_404(TrainingTarget,pk=id) + +def get_plan_by_pk(request,*args,**kwargs): + id = kwargs['id'] + return get_object_or_404(TrainingPlan,pk=id) + +def get_macro_by_pk(request,*args,**kwargs): + id = kwargs['id'] + return get_object_or_404(TrainingMacroCycle,pk=id) + +def get_meso_by_pk(request,*args,**kwargs): + id = kwargs['id'] + return get_object_or_404(TrainingMesoCycle,pk=id) + +def get_micro_by_pk(request,*args,**kwargs): + id = kwargs['id'] + return get_object_or_404(TrainingMicroCycle,pk=id) + def get_workout_default_page(request,id): if request.user.is_anonymous: return reverse('workout_view',kwargs={'id':id})