modification des permissions de coach: Voit uniquement les tryouts de ses équipes.

Evaluer un joueur retourne à la page précédente au lieu de la page des evaluations
This commit is contained in:
cedrick2711
2026-07-14 12:38:57 -04:00
parent 4fd27bacfd
commit acb9bc3256
16 changed files with 56 additions and 50 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
+22
View File
@@ -65,6 +65,28 @@ class User(UserMixin, db.Model):
def can_manage_teams(self): def can_manage_teams(self):
return self.role in ['president', 'manager'] return self.role in ['president', 'manager']
def can_manage_this_tryout(self, tryout):
"""Check if user can manage a specific tryout (president, or manager/coach in charge of it)."""
if self.role == 'president':
return True
if self.role == 'manager' and tryout.created_by == self.id:
return True
if self.role == 'coach':
org_team = OrgTeam.query.filter_by(coach_id=self.id).first()
if org_team and tryout.target_org_team_id == org_team.id:
return True
return False
def can_manage_this_org_team(self, org_team):
"""Check if user can manage a specific org team (president, or manager/coach in charge of it)."""
if self.role == 'president':
return True
if self.role == 'manager':
return True # Managers can manage all org teams (create/edit/delete)
if self.role == 'coach' and org_team.coach_id == self.id:
return True
return False
@login_manager.user_loader @login_manager.user_loader
def load_user(user_id): def load_user(user_id):
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+1 -1
View File
@@ -99,7 +99,7 @@ def evaluate_player(tryout_id, player_id):
flash('Evaluation submitted successfully!', 'success') flash('Evaluation submitted successfully!', 'success')
db.session.commit() db.session.commit()
return redirect(url_for('evaluations.list_evaluations')) return redirect(url_for('tryouts.view_tryout', tryout_id=tryout_id))
evaluators = None evaluators = None
if current_user.role == 'president': if current_user.role == 'president':
+7 -8
View File
@@ -56,11 +56,11 @@ def create_team():
@teams_bp.route('/<int:team_id>/edit', methods=['POST']) @teams_bp.route('/<int:team_id>/edit', methods=['POST'])
@login_required @login_required
def edit_team(team_id): def edit_team(team_id):
if not current_user.can_manage_teams(): team = OrgTeam.query.get_or_404(team_id)
flash('You do not have permission to edit teams.', 'danger') if not current_user.can_manage_this_org_team(team):
flash('You do not have permission to edit this team.', 'danger')
return redirect(url_for('teams.list_teams')) return redirect(url_for('teams.list_teams'))
team = OrgTeam.query.get_or_404(team_id)
name = request.form.get('name') name = request.form.get('name')
coach_id = request.form.get('coach_id') coach_id = request.form.get('coach_id')
@@ -105,11 +105,10 @@ def delete_team(team_id):
@teams_bp.route('/<int:team_id>/add_player', methods=['POST']) @teams_bp.route('/<int:team_id>/add_player', methods=['POST'])
@login_required @login_required
def add_player(team_id): def add_player(team_id):
if not current_user.can_manage_teams(): team = OrgTeam.query.get_or_404(team_id)
if not current_user.can_manage_this_org_team(team):
flash('Permission denied.', 'danger') flash('Permission denied.', 'danger')
return redirect(url_for('teams.list_teams')) return redirect(url_for('teams.list_teams'))
team = OrgTeam.query.get_or_404(team_id)
player_id = request.form.get('player_id') player_id = request.form.get('player_id')
position = request.form.get('position', '') position = request.form.get('position', '')
@@ -138,11 +137,11 @@ def add_player(team_id):
@teams_bp.route('/<int:team_id>/remove_player/<int:player_id>', methods=['POST']) @teams_bp.route('/<int:team_id>/remove_player/<int:player_id>', methods=['POST'])
@login_required @login_required
def remove_player(team_id, player_id): def remove_player(team_id, player_id):
if not current_user.can_manage_teams(): team = OrgTeam.query.get_or_404(team_id)
if not current_user.can_manage_this_org_team(team):
flash('Permission denied.', 'danger') flash('Permission denied.', 'danger')
return redirect(url_for('teams.list_teams')) return redirect(url_for('teams.list_teams'))
team = OrgTeam.query.get_or_404(team_id)
player = User.query.get_or_404(player_id) player = User.query.get_or_404(player_id)
if player.team_id != team_id: if player.team_id != team_id:
+14 -30
View File
@@ -74,17 +74,8 @@ def create_tryout():
def edit_tryout(tryout_id): def edit_tryout(tryout_id):
tryout = Tryout.query.get_or_404(tryout_id) tryout = Tryout.query.get_or_404(tryout_id)
# Permission: president can edit any; manager can edit own; coach can edit if it targets their team # Permission: president, manager (own tryouts), or coach (targets their team)
if current_user.role == 'president': if not current_user.can_manage_this_tryout(tryout):
pass # allowed
elif current_user.role == 'manager' and tryout.created_by == current_user.id:
pass # allowed
elif current_user.role == 'coach':
org_team = OrgTeam.query.filter_by(coach_id=current_user.id).first()
if not org_team or tryout.target_org_team_id != org_team.id:
flash('You do not have permission to edit this tryout.', 'danger')
return redirect(url_for('tryouts.list_tryouts'))
else:
flash('You do not have permission to edit this tryout.', 'danger') flash('You do not have permission to edit this tryout.', 'danger')
return redirect(url_for('tryouts.list_tryouts')) return redirect(url_for('tryouts.list_tryouts'))
@@ -152,15 +143,7 @@ def view_tryout(tryout_id):
}) })
# Determine if current user can edit this tryout # Determine if current user can edit this tryout
can_edit = False can_edit = current_user.can_manage_this_tryout(tryout)
if current_user.role == 'president':
can_edit = True
elif current_user.role == 'manager' and tryout.created_by == current_user.id:
can_edit = True
elif current_user.role == 'coach':
org_team = OrgTeam.query.filter_by(coach_id=current_user.id).first()
if org_team and tryout.target_org_team_id == org_team.id:
can_edit = True
# Get all players (for manager registration dropdown) # Get all players (for manager registration dropdown)
all_players = User.query.filter_by(role='player').order_by(User.full_name).all() all_players = User.query.filter_by(role='player').order_by(User.full_name).all()
@@ -209,11 +192,10 @@ def register_for_tryout(tryout_id):
@tryouts_bp.route('/<int:tryout_id>/status', methods=['POST']) @tryouts_bp.route('/<int:tryout_id>/status', methods=['POST'])
@login_required @login_required
def update_status(tryout_id): def update_status(tryout_id):
if not can_manage(): tryout = Tryout.query.get_or_404(tryout_id)
if not current_user.can_manage_this_tryout(tryout):
flash('Permission denied.', 'danger') flash('Permission denied.', 'danger')
return redirect(url_for('tryouts.list_tryouts')) return redirect(url_for('tryouts.list_tryouts'))
tryout = Tryout.query.get_or_404(tryout_id)
new_status = request.form.get('status') new_status = request.form.get('status')
if new_status in ['upcoming', 'in_progress', 'completed']: if new_status in ['upcoming', 'in_progress', 'completed']:
tryout.status = new_status tryout.status = new_status
@@ -224,7 +206,8 @@ def update_status(tryout_id):
@tryouts_bp.route('/<int:tryout_id>/registration/<int:player_id>/status', methods=['POST']) @tryouts_bp.route('/<int:tryout_id>/registration/<int:player_id>/status', methods=['POST'])
@login_required @login_required
def update_registration_status(tryout_id, player_id): def update_registration_status(tryout_id, player_id):
if not can_manage(): tryout = Tryout.query.get_or_404(tryout_id)
if not current_user.can_manage_this_tryout(tryout):
flash('Permission denied.', 'danger') flash('Permission denied.', 'danger')
return redirect(url_for('tryouts.list_tryouts')) return redirect(url_for('tryouts.list_tryouts'))
@@ -239,11 +222,10 @@ def update_registration_status(tryout_id, player_id):
@tryouts_bp.route('/<int:tryout_id>/register_player', methods=['POST']) @tryouts_bp.route('/<int:tryout_id>/register_player', methods=['POST'])
@login_required @login_required
def register_player(tryout_id): def register_player(tryout_id):
if not can_manage(): tryout = Tryout.query.get_or_404(tryout_id)
if not current_user.can_manage_this_tryout(tryout):
flash('Permission denied.', 'danger') flash('Permission denied.', 'danger')
return redirect(url_for('tryouts.view_tryout', tryout_id=tryout_id)) return redirect(url_for('tryouts.view_tryout', tryout_id=tryout_id))
tryout = Tryout.query.get_or_404(tryout_id)
player_id = request.form.get('player_id') player_id = request.form.get('player_id')
if not player_id: if not player_id:
@@ -275,7 +257,8 @@ def register_player(tryout_id):
@tryouts_bp.route('/<int:tryout_id>/team/create', methods=['POST']) @tryouts_bp.route('/<int:tryout_id>/team/create', methods=['POST'])
@login_required @login_required
def create_team(tryout_id): def create_team(tryout_id):
if not can_manage(): tryout = Tryout.query.get_or_404(tryout_id)
if not current_user.can_manage_this_tryout(tryout):
flash('Permission denied.', 'danger') flash('Permission denied.', 'danger')
return redirect(url_for('tryouts.view_tryout', tryout_id=tryout_id)) return redirect(url_for('tryouts.view_tryout', tryout_id=tryout_id))
@@ -290,13 +273,14 @@ def create_team(tryout_id):
@tryouts_bp.route('/<int:tryout_id>/team/<int:team_id>/add', methods=['POST']) @tryouts_bp.route('/<int:tryout_id>/team/<int:team_id>/add', methods=['POST'])
@login_required @login_required
def add_to_team(tryout_id, team_id): def add_to_team(tryout_id, team_id):
if not can_manage(): team = Team.query.get_or_404(team_id)
tryout = Tryout.query.get_or_404(tryout_id)
if not current_user.can_manage_this_tryout(tryout):
flash('Permission denied.', 'danger') flash('Permission denied.', 'danger')
return redirect(url_for('tryouts.view_tryout', tryout_id=tryout_id)) return redirect(url_for('tryouts.view_tryout', tryout_id=tryout_id))
player_id = request.form.get('player_id') player_id = request.form.get('player_id')
position = request.form.get('position', '') position = request.form.get('position', '')
team = Team.query.get_or_404(team_id)
existing = TeamMember.query.filter_by(team_id=team_id, player_id=player_id).first() existing = TeamMember.query.filter_by(team_id=team_id, player_id=player_id).first()
if existing: if existing:
+6 -5
View File
@@ -45,6 +45,7 @@
{% endif %} {% endif %}
{% for team in teams %} {% for team in teams %}
{% set can_manage_team = can_manage or (current_user.role == 'coach' and team.coach_id == current_user.id) %}
<div class="card mb-4"> <div class="card mb-4">
<div class="card-header"> <div class="card-header">
<h3><i class="fas fa-users-cog"></i> {{ team.name }}</h3> <h3><i class="fas fa-users-cog"></i> {{ team.name }}</h3>
@@ -76,7 +77,7 @@
<th>Position / Role</th> <th>Position / Role</th>
<th>Email</th> <th>Email</th>
<th>Phone</th> <th>Phone</th>
{% if can_manage %} {% if can_manage_team %}
<th>Actions</th> <th>Actions</th>
{% endif %} {% endif %}
</tr> </tr>
@@ -93,7 +94,7 @@
<td>{{ player.role | capitalize }}</td> <td>{{ player.role | capitalize }}</td>
<td>{{ player.email }}</td> <td>{{ player.email }}</td>
<td>{{ player.phone or '-' }}</td> <td>{{ player.phone or '-' }}</td>
{% if can_manage %} {% if can_manage_team %}
<td> <td>
<form method="POST" action="{{ url_for('teams.remove_player', team_id=team.id, player_id=player.id) }}" class="inline-form" onsubmit="return confirm('Remove {{ player.full_name }} from {{ team.name }}?')"> <form method="POST" action="{{ url_for('teams.remove_player', team_id=team.id, player_id=player.id) }}" class="inline-form" onsubmit="return confirm('Remove {{ player.full_name }} from {{ team.name }}?')">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/> <input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
@@ -106,11 +107,11 @@
</tr> </tr>
{% else %} {% else %}
<tr> <tr>
<td colspan="{% if can_manage %}5{% else %}4{% endif %}" class="text-center"> <td colspan="{% if can_manage_team %}5{% else %}4{% endif %}" class="text-center">
<div class="empty-state"> <div class="empty-state">
<i class="fas fa-users-slash"></i> <i class="fas fa-users-slash"></i>
<h4>No players assigned</h4> <h4>No players assigned</h4>
{% if can_manage %} {% if can_manage_team %}
<p>Add players to this team using the form below.</p> <p>Add players to this team using the form below.</p>
{% endif %} {% endif %}
</div> </div>
@@ -121,7 +122,7 @@
</table> </table>
</div> </div>
{% if can_manage %} {% if can_manage_team %}
<hr class="my-3"> <hr class="my-3">
<div class="add-player-section"> <div class="add-player-section">
<h5 class="mb-2"><i class="fas fa-user-plus"></i> Add Player to {{ team.name }}</h5> <h5 class="mb-2"><i class="fas fa-user-plus"></i> Add Player to {{ team.name }}</h5>
+6 -6
View File
@@ -9,7 +9,7 @@
<div class="card-header"> <div class="card-header">
<h3>Tryout Details</h3> <h3>Tryout Details</h3>
<div class="card-actions"> <div class="card-actions">
{% if current_user.can_manage_tryouts() %} {% if can_edit %}
<form method="POST" action="{{ url_for('tryouts.update_status', tryout_id=tryout.id) }}" class="inline-form"> <form method="POST" action="{{ url_for('tryouts.update_status', tryout_id=tryout.id) }}" class="inline-form">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/> <input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
<select name="status" onchange="this.form.submit()" class="form-select"> <select name="status" onchange="this.form.submit()" class="form-select">
@@ -73,7 +73,7 @@
</div> </div>
{% endif %} {% endif %}
{% if current_user.can_manage_tryouts() %} {% if can_edit %}
<div class="card mb-4"> <div class="card mb-4">
<div class="card-header"> <div class="card-header">
<h3><i class="fas fa-user-plus"></i> Add Player to Tryout</h3> <h3><i class="fas fa-user-plus"></i> Add Player to Tryout</h3>
@@ -125,7 +125,7 @@
</div> </div>
</td> </td>
<td> <td>
{% if current_user.can_manage_tryouts() %} {% if can_edit %}
<form method="POST" action="{{ url_for('tryouts.update_registration_status', tryout_id=tryout.id, player_id=p.id) }}" class="inline-form"> <form method="POST" action="{{ url_for('tryouts.update_registration_status', tryout_id=tryout.id, player_id=p.id) }}" class="inline-form">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/> <input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
<select name="status" onchange="this.form.submit()" class="form-select form-select-sm"> <select name="status" onchange="this.form.submit()" class="form-select form-select-sm">
@@ -169,14 +169,14 @@
<div class="card"> <div class="card">
<div class="card-header"> <div class="card-header">
<h3><i class="fas fa-users-cog"></i> Teams</h3> <h3><i class="fas fa-users-cog"></i> Teams</h3>
{% if current_user.can_manage_tryouts() %} {% if can_edit %}
<button class="btn btn-sm btn-primary" onclick="showCreateTeam()"> <button class="btn btn-sm btn-primary" onclick="showCreateTeam()">
<i class="fas fa-plus"></i> New Team <i class="fas fa-plus"></i> New Team
</button> </button>
{% endif %} {% endif %}
</div> </div>
<div class="card-body"> <div class="card-body">
{% if current_user.can_manage_tryouts() %} {% if can_edit %}
<div id="createTeamForm" class="hidden mb-3"> <div id="createTeamForm" class="hidden mb-3">
<form method="POST" action="{{ url_for('tryouts.create_team', tryout_id=tryout.id) }}" class="form-inline"> <form method="POST" action="{{ url_for('tryouts.create_team', tryout_id=tryout.id) }}" class="form-inline">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/> <input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
@@ -203,7 +203,7 @@
<li class="text-muted">No players assigned yet.</li> <li class="text-muted">No players assigned yet.</li>
{% endfor %} {% endfor %}
</ul> </ul>
{% if current_user.can_manage_tryouts() and registered_players %} {% if can_edit and registered_players %}
<form method="POST" action="{{ url_for('tryouts.add_to_team', tryout_id=tryout.id, team_id=team.team.id) }}" class="form-inline mt-2"> <form method="POST" action="{{ url_for('tryouts.add_to_team', tryout_id=tryout.id, team_id=team.team.id) }}" class="form-inline mt-2">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/> <input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
<select name="player_id" class="form-select" required> <select name="player_id" class="form-select" required>