660 lines
19 KiB
Python
660 lines
19 KiB
Python
import rules
|
|
import datetime
|
|
|
|
# PERMISSIONS
|
|
|
|
# USER permissions
|
|
|
|
"""
|
|
USER permissions
|
|
- There are 5 types of user: basic, pro, plan, coach, freecoach
|
|
- These methods exist on user
|
|
- user.rower
|
|
- user.is_anonymous
|
|
- user.is_staff
|
|
|
|
- These methods exist on rower
|
|
- rower.rowerplan
|
|
- rower.protrialexpires
|
|
- rower.plantrialexpires
|
|
- rower.mycoachgroup
|
|
- rower.coachinggroups
|
|
- rower.team
|
|
|
|
- These Rules apply to Rowers
|
|
- Coach can have any number of groups
|
|
- test_permissions.PermissionFreeCoach.test_coach_groupmanager
|
|
- test_permissions.PermissionsBasicsTests.test_coach_groupmanager
|
|
- test_permissions.PermissionsViewTests.test_coach_groups_create
|
|
- Pro and Plan users can have one group and not more
|
|
- test_permissions.PermissionsFreeCoach.test_pro_groupmanager
|
|
- test_permissions.PermissionsViewTests.test_pro_groups_create
|
|
- Free Coach user cannot have workouts
|
|
- test_permissions.PermissionFreeCoach.test_add_workout_freecoach
|
|
- Free coach can create more than one group
|
|
- test_permissions.PermissionsFreeCoach.test_plan_groupmanager
|
|
- Free Coach & Plan (Self Coach) can create planned sessions and team planned sessions
|
|
- test_permissions.PermissionsFreeCoach.test_plan_create_session
|
|
- test_permissions.PermissionsFreeCoach.test_coach_create_session
|
|
- Pro cannot create planned sessions or team planned sessions
|
|
- test_permissions.PermissionsViewTests.test_pro_create_session
|
|
- Basic cannot join groups led by Free Coach
|
|
- test_permissions.PermissionFreeCoach.test_add_basic_pro_or_plan
|
|
- Coach can edit athlete settings (if in coachinggroup)
|
|
- test_permissions.PermissionsViewTests.test_coach_edit_athlete_prefs
|
|
- test_permissions.PermissionsViewTests.test_coach_edit_athlete_prefs_not
|
|
- test_permissions.PermissionsViewTests.test_coach_edit_athlete_settings
|
|
- test_permissions.PermissionsViewTests.test_coach_edit_athlete_settings_not
|
|
- test_permissions.PermissionsViewTests.test_coach_edit_athlete_account
|
|
- test_permissions.PermissionsViewTests.test_coach_edit_athlete_account_not
|
|
- test_permissions.PermissionsViewTests.test_coach_edit_athlete_exportsettings
|
|
- test_permissions.PermissionsViewTests.test_coach_edit_athlete_exportsettings_not
|
|
- Coach can upload a workout on behalf of athlete
|
|
- test_permissions.PermissionsViewTests.test_coach_edit_athlete_upload
|
|
- test_permissions.PermissionsViewTests.test_coach_edit_athlete_upload_not
|
|
- Pro and Plan cannot upload a workout on behalf of athlete
|
|
- test_permissions.PermissionsViewTests.test_plan_edit_athlete_upload
|
|
- Coach can run analytics for athlete
|
|
- test_permissions.PermissionsViewTests.test_coach_edit_athlete_analysis
|
|
- test_permissions.PermissionsViewTests.test_coach_edit_athlete_analysis_not
|
|
- test_permissions.PermissionsViewTests.test_pro_edit_athlete_analysis
|
|
- Pro and Plan user cannot run analysis for members of their groups
|
|
- test_permissions.PermissionsViewTests.test_plan_edit_athlete_analysis
|
|
- Pro and Plan user cannot edit athlete sessings
|
|
- test_permissions.PermissionsViewTests.test_plan_edit_athlete_settings
|
|
- test_permissions.PermissionsViewTests.test_pro_edit_athlete_settings
|
|
- Self-Coach and Pro cannot create more than one group
|
|
- test_permissions.PermissionsFreeCoach.test_plan_groupmanager
|
|
- Pro users and higher can join group led by other Pro or higher user
|
|
- test_permissions.PermissionsFreeCoach.test_add_proplan_pro_or_plan
|
|
- Pro or basic cannot create planned sessions or team planned sessions
|
|
- test_permissions.PermissionsFreeCoach.test_pro_create_plannedsession
|
|
|
|
"""
|
|
|
|
# used in can_plan_user
|
|
@rules.predicate
|
|
def user_is_not_basic(user):
|
|
if user.rower.rowerplan != 'basic':
|
|
return True
|
|
|
|
if user.rower.protrialexpires >= datetime.date.today() and user.rower.plantrialexpires >= datetime.date.today():
|
|
return True
|
|
|
|
return False
|
|
|
|
@rules.predicate
|
|
def can_start_trial(user):
|
|
if user.is_anonymous:
|
|
return False
|
|
|
|
|
|
return user.rower.protrialexpires == datetime.date(1970,1,1)
|
|
|
|
@rules.predicate
|
|
def can_start_plantrial(user):
|
|
if user.is_anonymous:
|
|
return False
|
|
|
|
return user.rower.plantrialexpires == datetime.date(1970,1,1)
|
|
|
|
@rules.predicate
|
|
def is_coach(user):
|
|
return user.rower.rowerplan in ['coach','freecoach']
|
|
|
|
def is_paid_coach(user):
|
|
return user.rower.rowerplan == 'coach'
|
|
|
|
@rules.predicate
|
|
def is_planmember(user):
|
|
try:
|
|
r = user.rower
|
|
except AttributeError:
|
|
return False
|
|
|
|
return r.rowerplan in ['coach','plan'] # freecoach?
|
|
|
|
@rules.predicate
|
|
def is_promember(user):
|
|
try:
|
|
r = user.rower
|
|
except AttributeError:
|
|
return False
|
|
|
|
return r.rowerplan in ['pro','coach','plan'] # freecoach?
|
|
|
|
@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
|
|
|
|
can_have_teams = ispromember | is_coach
|
|
|
|
@rules.predicate
|
|
def can_add_team(user):
|
|
if is_coach(user):
|
|
return True
|
|
|
|
if ispromember(user):
|
|
otherteams = user.rower.get_managed_teams()
|
|
if otherteams.count() == 0:
|
|
return True
|
|
|
|
return False
|
|
|
|
@rules.predicate
|
|
def can_add_plan(user):
|
|
return isplanmember(user) or is_coach(user)
|
|
|
|
@rules.predicate
|
|
def can_add_workout(user):
|
|
if user.is_anonymous:
|
|
return False
|
|
|
|
return user.rower.rowerplan != 'freecoach'
|
|
|
|
@rules.predicate
|
|
def is_plantrial(user):
|
|
try:
|
|
r = user.rower
|
|
except AttributeError:
|
|
return False
|
|
|
|
if r.rowerplan in ['basic','pro']:
|
|
return r.plantrialexpires >= datetime.date.today()
|
|
if r.rowerplan == 'freecoach':
|
|
if r.mycoachgroup is not None:
|
|
return len(r.mycoachgroup)>=4
|
|
|
|
return False
|
|
|
|
|
|
isplanmember = is_planmember | is_plantrial
|
|
|
|
@rules.predicate
|
|
def can_add_session(user):
|
|
return isplanmember(user) or is_coach(user)
|
|
|
|
# User / Coach relationships (Rower object)
|
|
|
|
@rules.predicate
|
|
def can_plan(user):
|
|
return user.rower.rowerplan in ['plan','coach','freecoach']
|
|
|
|
# checks if rower is coach of user
|
|
@rules.predicate
|
|
def is_coach_user(usercoach,userrower):
|
|
if not is_coach(usercoach):
|
|
return False
|
|
|
|
if usercoach == userrower:
|
|
return True
|
|
|
|
r = userrower.rower
|
|
|
|
coaches = []
|
|
|
|
for group in r.coachinggroups.all():
|
|
newcoaches = group.get_coaches()
|
|
for coach in newcoaches:
|
|
coaches.append(coach)
|
|
|
|
for coach in coaches:
|
|
if usercoach.rower == coach:
|
|
return True
|
|
|
|
return False
|
|
|
|
# check if rower and user are members of the same team
|
|
@rules.predicate
|
|
def is_rower_team_member(user,rower):
|
|
if user.rower == rower:
|
|
return True
|
|
|
|
teams = 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_add_workout_member(user,rower):
|
|
if not user:
|
|
return False
|
|
if user.is_anonymous:
|
|
return False
|
|
if user == rower.user:
|
|
return True
|
|
# only below tested - need test user == rower.user
|
|
return is_coach(user) and user.rower in rower.get_coaches()
|
|
|
|
# check if user can plan for the rower
|
|
@rules.predicate
|
|
def can_plan_user(user,rower):
|
|
# user must have planning permission
|
|
if not can_plan(user):
|
|
return False
|
|
|
|
# if has planning permission, can always plan for himself
|
|
if rower == user.rower:
|
|
return True
|
|
|
|
teams = user.rower.get_managed_teams()
|
|
# free coach, plan etc cannot plan for basic
|
|
if not is_paid_coach(user) and user_is_not_basic(user):
|
|
for t in teams:
|
|
if rower in t.rower.all():
|
|
return True
|
|
|
|
# paying coach can plan for all kinds of rowers
|
|
if is_paid_coach(user):
|
|
for t in teams:
|
|
if rower in t.rower.all():
|
|
return True
|
|
|
|
return False
|
|
|
|
rules.add_perm('rower.add_plan',can_plan_user) # replaces checkaccessplanuser
|
|
rules.add_perm('rower.is_coach',is_coach_user) # replaces checkaccessuser
|
|
rules.add_perm('rower.is_pro',ispromember)
|
|
|
|
# WORKOUT permissions
|
|
|
|
"""
|
|
WORKOUT permissions
|
|
- These methods exist on Workout
|
|
- workout.privacy
|
|
|
|
- These rules apply to workouts
|
|
- User can add, delete and change their own workouts
|
|
- test_aworkouts
|
|
- Coach can add and change workouts for their athletes, but not delete
|
|
- test_permissions.PermissionsViewTests.test_coach_edit_athlete_upload
|
|
- test_permissions.PermissionsViewTests.test_coach_edit_athlete_upload_not
|
|
- Basic, Pro and Plan user can view but cannot add or change an athlete's workout
|
|
- test_permissions.PermissionsViewTests.test_coach_edit_athlete_workout
|
|
- test_permissions.PermissionsViewTests.test_plan_edit_athlete_upload
|
|
- test_permissions.PermissionsViewTests.test_plan_edit_athlete_workout
|
|
- test_permissions.PermissionsViewTests.test_basic_edit_athelte_workout
|
|
- Anonymous users can view team members' workout (but not see list of workouts)
|
|
- test_aworkouts
|
|
|
|
- Rules for Workouts are transferred to objects related to the Workout,
|
|
- Charts
|
|
- Video Analysis
|
|
- WorkoutComment?
|
|
|
|
"""
|
|
|
|
# check if user is owner or coach of owner of workout
|
|
@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
|
|
|
|
return is_coach_user(user,workout.user.user)
|
|
|
|
# check if user can see workout
|
|
@rules.predicate
|
|
def can_view_workout(user,workout):
|
|
if workout.privacy != 'private':
|
|
return True
|
|
return user.rower == workout.user
|
|
|
|
can_change_workout = is_workout_user
|
|
|
|
rules.add_perm('workout.change_workout',can_change_workout) # replaces checkworkoutuser
|
|
rules.add_perm('workout.view_workout',can_view_workout) # replaces checkworkoutuserview
|
|
|
|
|
|
|
|
# checkviewworkouts
|
|
|
|
# PLANNING permissions
|
|
|
|
"""
|
|
- These rules apply to planning
|
|
- Free coach can create planned sessions and team planned sessions
|
|
- test_permissions.PermissionsViewTests.test_coach_create_session
|
|
- Self coach and higher can create planned sessions and team planned sessions
|
|
- test_permissions.PermissionsFreeCoach.test_plan_create_session
|
|
- test_permissions.PermissionsFreeCoach.test_coach_create_session
|
|
- Coach can create planned sessions and team planned sessions
|
|
- test_permissions.PermissionsFreeCoach.test_plan_create_session
|
|
- test_permissions.PermissionsFreeCoach.test_coach_create_session
|
|
- Self Coach and higher can create planned sessions and team planned sessions
|
|
- test_permissions.PermissionsViewTests.test_plan_create_session
|
|
- Pro or Basic cannot create planned sessions or team planned sessions
|
|
- test_permissions.PermissionsFreeCoach.test_pro_create_plannedsession
|
|
- test_permissions.PermissionsFreeCoach.test_basic_create_plannedsession
|
|
- WHO can comment (plannedsession_comment_view)
|
|
- Only Session manager can change session
|
|
- Strict View rules (stricter than workouts)
|
|
- Basic user cannot manage a training plan
|
|
|
|
- TrainingTarget
|
|
- rules for view, add, change, delete
|
|
- TrainingPlan
|
|
- rules for view, add, change, delete
|
|
- Cycle
|
|
- inherits rules from TrainingPlan
|
|
- PlannedSession
|
|
- rules for view, add, change, delete, clone, save as template
|
|
- check team
|
|
|
|
- Special rules for Race (cannot be edited ex post)
|
|
|
|
"""
|
|
|
|
# Training Target rules
|
|
|
|
# untested can_view_target to can_delete_target
|
|
@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
|
|
# below untested
|
|
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
|
|
|
|
# below untested
|
|
@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.add_perm('plan.can_add_plan',can_add_plan)
|
|
|
|
# untested
|
|
@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
|
|
if user.is_anonymous:
|
|
return False
|
|
# session manager can view session
|
|
if user == session.manager:
|
|
return True
|
|
# if you're a rower in the session you can view it
|
|
# below untested
|
|
if user.rower in session.rower.all():
|
|
return True
|
|
# coach users can view sessions created by their team members
|
|
# below untested
|
|
if is_coach(user):
|
|
teams = user.rower.get_managed_teams()
|
|
teamusers = [member.u for member in t.rower.all()]
|
|
if session.manager in teamusers:
|
|
return True
|
|
|
|
return False
|
|
|
|
@rules.predicate
|
|
def can_change_session(user,session):
|
|
if user.is_anonymous:
|
|
return False
|
|
# session part of a race should not be changed through the session interface
|
|
if session.sessiontype in ['race','indoorrace']:
|
|
return False
|
|
if user == session.manager:
|
|
return True
|
|
|
|
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.add_session',can_add_session)
|
|
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)
|
|
|
|
# TEAM (group) permissions
|
|
|
|
"""
|
|
- These methods exist on team
|
|
- team.manager
|
|
- team.private
|
|
|
|
- These rules apply to a team
|
|
- A Pro or Plan rower can be manager of only 1 team
|
|
- test_permissions.PermissionsFreeCoach.test_pro_groupmanager
|
|
- test_permissions.PermissionsViewTests.test_pro_groups_create
|
|
- A coach can have any number of teams (as manager)
|
|
- test_permissions.PermissionsBasicTest.test_coach_groupmanager
|
|
- Basic user cannot manage a group
|
|
- test_permissions.PermissionsFreeCoach.test_basic_groupmanager
|
|
- Basic user cannot join groups led by Free Coach or Pro
|
|
- test_permissions.PermissionFreeCoach.test_add_basic_pro_or_plan
|
|
- Basic athletes can be member of Coach led group
|
|
- test_permissions.PermissionsBasicTest.test_add_coach
|
|
- Pro users (and higher) can join team led by other Pro (or higher) user
|
|
- test_permissions.PermissionsFreeCoach.test_add_proplan_pro_or_plan
|
|
- test_permissions.PermissionsViewTests.test_team_member_request_pro_pro
|
|
- test_permissions.PermissionsViewTests.test_team_member_request_basic_pro
|
|
- On downgrade, Coach users lose all but their oldest team (add test!)
|
|
|
|
"""
|
|
|
|
# check if user is manager of the team
|
|
@rules.predicate
|
|
def is_team_manager(user,team):
|
|
return team.manager == user
|
|
|
|
# check is user is member of team - untested
|
|
@rules.predicate
|
|
def is_team_member(user,team):
|
|
members = team.rower.all()
|
|
return user in [member.user for member in members]
|
|
|
|
# check if user can view team
|
|
@rules.predicate
|
|
def can_view_team(user,team):
|
|
# user based - below untested
|
|
if user.rower.rowerplan == 'basic' and team.manager.rower.rowerplan != 'coach':
|
|
return False
|
|
# team is public
|
|
if team.private == 'open':
|
|
return True
|
|
# team is private - below untested
|
|
return is_team_member(user,team) | is_team_manager(user,team)
|
|
|
|
@rules.predicate
|
|
def can_change_team(user,team):
|
|
return is_team_manager(user,team)
|
|
|
|
@rules.predicate
|
|
def can_delete_team(user,team):
|
|
return is_team_manager(user,team)
|
|
|
|
@rules.predicate
|
|
def can_join_team(user,team):
|
|
return is_paid_coach(team.manager) or ispromember(user)
|
|
|
|
# For Team functionality
|
|
rules.add_perm('teams.view_team',can_view_team)
|
|
rules.add_perm('teams.add_team',user_is_not_basic)
|
|
rules.add_perm('teams.change_team',can_change_team)
|
|
rules.add_perm('teams.delete_team',can_delete_team)
|
|
|
|
# RACING permissions
|
|
|
|
"""
|
|
- VirtualRace
|
|
- rules to add, view, delete, change
|
|
- GeoCourse
|
|
- rules to add, view, delete, change
|
|
- RaceLogo
|
|
"""
|
|
|
|
@rules.predicate
|
|
def can_change_course(user,course):
|
|
if user.is_anonymous:
|
|
return False
|
|
|
|
return course.manager == user.rower
|
|
|
|
# untested
|
|
@rules.predicate
|
|
def can_delete_course(user,course):
|
|
if user.is_anonymous:
|
|
return False
|
|
|
|
return course.manager == user.rower
|
|
|
|
@rules.predicate
|
|
def can_delete_logo(user,logo):
|
|
if user.is_anonymous:
|
|
return False
|
|
|
|
return logo.user == user
|
|
|
|
@rules.predicate
|
|
def can_change_race(user,race):
|
|
if user.is_anonymous:
|
|
return False
|
|
|
|
return race.manager == user
|
|
|
|
# everybody can view or add a course
|
|
rules.add_perm('course.change_course',can_change_course)
|
|
rules.add_perm('course.delete_course',can_delete_course)
|
|
|
|
rules.add_perm('racelogo.delete_logo',can_delete_logo)
|
|
|
|
# everybody can view a race
|
|
rules.add_perm('virtualevent.change_race',can_change_race)
|
|
# can races be deleted?
|
|
|
|
|
|
# ANALYSIS permissions
|
|
|
|
"""
|
|
- Conditions
|
|
- Alerts
|
|
- rules to add, view, delete, change
|
|
- cpdata
|
|
"""
|