diff --git a/app/routes/teams.py b/app/routes/teams.py index a909437..b876d89 100644 --- a/app/routes/teams.py +++ b/app/routes/teams.py @@ -8,9 +8,11 @@ from datetime import datetime from flask import Blueprint, flash, jsonify, redirect, render_template, request, url_for from flask_babel import gettext as _ from flask_login import current_user, login_required +from marshmallow import ValidationError from app.api import json_endpoint from app.extensions import db +from app.forms import flash_validation_errors, form_payload from app.models import ( Admin, Coach, @@ -27,6 +29,7 @@ from app.models import ( User, ) from app.permissions import visible_org_teams +from app.validators import OrgTeamSchema teams_bp = Blueprint('teams', __name__, url_prefix='/teams') @@ -116,6 +119,29 @@ def my_teams(): return render_template('pages/my_teams.html', team_data=team_data, now=now) +def _staff_member(user_id, expected_class): + """The user behind an id, only if they hold the role being assigned. + + Returns None for a missing id, an unknown id, or an account of the wrong + role. That last case is the point (SEC-16): the id comes from a ` the browser + rendered, so it is a value the client chooses.""" + from app.models import OrgTeam + + player_id = make_user('player') + as_role('manager') + + client.post( + '/teams/create', + data={'name': 'Varsity', 'coach_id': str(player_id)}, + follow_redirects=False, + ) + + with app.app_context(): + team = OrgTeam.query.filter_by(name='Varsity').first() + assert team is not None, 'the team should still be created, without the bad staff' + assert team.coach_id is None + assert team.coaches.all() == [] + + def test_a_real_coach_is_still_assigned(self, app, client, as_role, make_user): + """The premise. Without it the test above passes against a route that + assigns nobody at all.""" + from app.models import OrgTeam + + coach_id = make_user('coach') + as_role('manager') + + client.post( + '/teams/create', + data={'name': 'Varsity', 'coach_id': str(coach_id)}, + follow_redirects=False, + ) + + with app.app_context(): + team = OrgTeam.query.filter_by(name='Varsity').first() + assert team.coach_id == coach_id + assert [user.id for user in team.coaches.all()] == [coach_id] + + def test_editing_cannot_slip_a_player_in_either(self, app, client, as_role, make_user): + """The branch that had no role check at all.""" + from app.models import OrgTeam + + coach_id = make_user('coach') + player_id = make_user('player') + as_role('manager') + + client.post('/teams/create', data={'name': 'Varsity', 'coach_id': str(coach_id)}) + with app.app_context(): + team_id = OrgTeam.query.filter_by(name='Varsity').first().id + + client.post( + f'/teams/{team_id}/edit', + data={'name': 'Varsity', 'coach_id': str(player_id)}, + follow_redirects=False, + ) + + with app.app_context(): + team = db.session.get(OrgTeam, team_id) + assert player_id not in [user.id for user in team.coaches.all()] + assert team.coach_id != player_id + + def test_a_team_still_needs_a_name(self, app, client, as_role): + from app.models import OrgTeam + + as_role('manager') + + response = client.post('/teams/create', data={'name': ''}, follow_redirects=False) + + assert response.status_code < 500 + with app.app_context(): + assert OrgTeam.query.count() == 0