def register_administrator(): """Register a new user""" body = flask_rebar.get_validated_body() email = body["email"] username = body["username"] password = body["password"] # Validate user uniqueness constraint. user = User.query.filter_by(email=email).first() if user is not None: administrator = user.get_administrator() if administrator is not None: raise errors.UnprocessableEntity("An administrator with that email already exists") user = User.query.filter_by(username=username).first() if user is not None: administrator = user.get_administrator() if administrator: raise errors.UnprocessableEntity("An administrator with that username already exists for this event") user = User(email=email, username=username) user.set_password(password) administrator = Administrator(is_platform_admin=False, user=user) DB.session.add(administrator) DB.session.commit() return administrator, 201
def create_team(current_participant: Participant): """Create a team for a given event.""" body = flask_rebar.get_validated_body() team_name = body["team_name"] if not team_name: raise errors.UnprocessableEntity("Please choose a team name") team = current_participant.get_team() if team is not None: raise errors.UnprocessableEntity( "You cannot create a team if you already are in a team.") team = Team.query.filter_by(name=team_name).first() if team is not None: raise errors.UnprocessableEntity( "A team with that name already exists.") team = Team(name=team_name, event_id=current_participant.event_id, members=[ TeamMember(participant_id=current_participant.id, captain=True) ]) DB.session.add(team) DB.session.commit() return team
def send_team_request(current_participant: Participant): """Request to join a team.""" body = flask_rebar.get_validated_body() team_id = body["team_id"] team_member = current_participant.get_team() if team_member is not None: raise errors.UnprocessableEntity( "You cannot request to join a team if you already are in a team.") team = Team.query.filter_by(id=team_id).first() if team is None: raise errors.UnprocessableEntity("The team doesn't exist.") # FIXMEFUTURE: If team is not already full # (on a pas de configuration pour le nombre de membres d'une équipe for now) team_request = TeamRequest.query.filter_by( participant_id=current_participant.id).first() if team_request is not None: raise errors.UnprocessableEntity( "You already have requested to join a team.") team_request = TeamRequest(team_id=team_id, participant_id=current_participant.id) DB.session.add(team_request) DB.session.commit() return ""
def edit_challenge(current_admin: Administrator, challenge_id: int): """Edit a challenge and its associated ressources (flags, links, files)""" body = flask_rebar.get_validated_body() name = body["name"] points = body["points"] hidden = body["hidden"] description = body["description"] category_id = body["category_id"] flags = body["flags"] editable_challenge = Challenge.query.filter_by(id=challenge_id).first() if editable_challenge is None: raise errors.UnprocessableEntity("This challenge does not exist.") if not current_admin.is_admin_of_event( editable_challenge.category.event_id): raise errors.Unauthorized( "You do not have the permission to administer this challenge.") if category_id != editable_challenge.category_id: category = Category.query.filter_by( id=category_id, event_id=editable_challenge.category.event_id).first() if category is None: raise errors.UnprocessableEntity("The category doesn't exist.") if name != editable_challenge.name: if not name: raise errors.UnprocessableEntity("Name must not be empty.") challenge = Challenge.query.filter_by(name=name).first() if challenge is not None: raise errors.UnprocessableEntity( "A challenge with that name already exists.") if points != editable_challenge.points and points <= 0: raise errors.UnprocessableEntity("Points must be positive.") editable_challenge.name = name editable_challenge.points = points editable_challenge.hidden = hidden editable_challenge.description = description editable_challenge.category_id = category_id flag_objects = list( map(lambda flag: Flag(is_regex=flag['is_regex'], value=flag['value']), flags)) editable_challenge.flags = flag_objects DB.session.commit() return editable_challenge
def create_event(current_admin: Administrator): """Create a new event""" # pylint: disable=unused-argument body = flask_rebar.get_validated_body() name = body["name"] teams = body["teams"] is_open = body["is_open"] is_visible = body["is_visible"] front_page = body["front_page"] if "front_page" in body else "" flag_format = body["flag_format"] if "flag_format" in body else "" event = Event.query.filter_by(name=name).first() if event: raise errors.UnprocessableEntity( "An event with that name already exists") event = Event(name=name, front_page=front_page, flag_format=flag_format, is_open=is_open, is_visible=is_visible, teams=teams) DB.session.add(event) DB.session.commit() return event
def create_category(current_admin: Administrator): """Add a category """ body = flask_rebar.get_validated_body() name = body["name"] event_id = body["event_id"] event = Event.query.filter_by(id=event_id).first() if event is None: raise errors.NotFound(f'Event with id "{event_id}" not found.') if not current_admin.is_admin_of_event(event_id): raise errors.Unauthorized( "You do not have the permission to administer this event.") category = Category.query.filter_by(name=name, event_id=event_id).first() if category is not None: raise errors.UnprocessableEntity( "A category with that name already exists") category = Category(name=name, event_id=event_id) DB.session.add(category) DB.session.commit() return category
def accept_team_request(current_participant: Participant): """Accepts a team request. Only captains can accept a request.""" body = flask_rebar.get_validated_body() participant_id = body["participant_id"] current_member = TeamMember.query.filter_by( participant_id=current_participant.id).first() if not current_member or not current_member.captain: raise errors.Unauthorized( "You don't have the rights to accept this request.") # Remove TeamRequest and add the new member team_request = TeamRequest.query.filter_by( team_id=current_member.team_id, participant_id=participant_id).first() if team_request is None: raise errors.UnprocessableEntity("The request doesn't exist.") new_member = TeamMember(participant_id=participant_id, team_id=current_member.team_id) DB.session.delete(team_request) DB.session.add(new_member) DB.session.commit() return ""
def submit_flag(challenge: Challenge, event: Event): """Submit a flag for a given challenge""" body = flask_rebar.get_validated_body() submitted_flag = body["flag"] team = current_user.get_team() if team is None: raise errors.NotFound(f'Current user has no team.') if event.id != team.event_id: raise errors.UnprocessableEntity( f'Team "{team.name}" and challenge "{challenge.id}" are not part of the same event') submission = Submission(team_id=team.id, challenge_id=challenge.id, input=submitted_flag) flags = Flag.query.filter_by(challenge_id=challenge.id).all() is_correct = any(validate_flag(x, submitted_flag) for x in flags) submission.is_correct = is_correct DB.session.add(submission) DB.session.commit() return {'correct': is_correct}
def register_participant(event: Event): """Register a new user""" body = flask_rebar.get_validated_body() email = body["email"] username = body["username"] password = body["password"] if not username: raise errors.UnprocessableEntity("Please choose a username") # Validate user uniqueness constraint. user = User.query.filter_by(email=email).first() if user is not None: participant = user.get_participant() if user is not None and participant and participant.event_id == event.id: raise errors.UnprocessableEntity("A participant with that email already exists for this event") user = User.query.filter_by(username=username).first() if user is not None: participant = user.get_participant() if user is not None and participant and participant.event_id == event.id: raise errors.UnprocessableEntity("A participant with that username already exists for this event") user = User(email=email, username=username) user.set_password(password) participant = Participant(event_id=event.id, user=user) DB.session.add(participant) if not event.teams: # means that its a solo event, need to create a team with the participant in it. team = Team(event_id=event.id, name=user.username, members=[TeamMember(participant=participant, captain=True)]) DB.session.add(team) DB.session.commit() login_user(participant.user, remember=True) return participant, 201
def leave_team(current_participant: Participant): """Leave a team""" # NOTE: When the last member of a team leaves, what should happen? We do not want to delete a team. team_member = TeamMember.query.filter_by( participant_id=current_participant.id).first() if team_member is None: raise errors.UnprocessableEntity("You are not in a team.") DB.session.delete(team_member) DB.session.commit() return ""
def remove_own_team_request(current_participant: Participant): """Remove own request.""" team_request = TeamRequest.query.filter_by( participant_id=current_participant.id).first() if team_request is None: raise errors.UnprocessableEntity( "You don't have any pending requests.") DB.session.delete(team_request) DB.session.commit() return ""
def edit_event(current_admin: Administrator, event_id: int): """Edit an new event""" # pylint: disable=unused-argument body = flask_rebar.get_validated_body() name = body["name"] teams = body["teams"] is_open = body["is_open"] is_visible = body["is_visible"] front_page = body["front_page"] if "front_page" in body else "" flag_format = body["flag_format"] if "flag_format" in body else "" editable_event = Event.query.filter_by(id=event_id).first() if editable_event is None: raise errors.NotFound(f'Event with id "{event_id}" not found.') if name != editable_event.name: if not name: raise errors.UnprocessableEntity("Name must not be empty.") event = Event.query.filter_by(name=name).first() if event is not None: raise errors.UnprocessableEntity( "An event with that name already exists.") editable_event.name = name editable_event.front_page = front_page editable_event.flag_format = flag_format editable_event.is_open = is_open editable_event.is_visible = is_visible editable_event.teams = teams DB.session.commit() return editable_event
def make_challenge_hidden(current_admin: Administrator, challenge_id: int): """Make a challenge hidden""" challenge = Challenge.query.filter_by(id=challenge_id).first() if challenge is None: raise errors.UnprocessableEntity("This challenge does not exist.") if not current_admin.is_admin_of_event(challenge.category.event_id): raise errors.Unauthorized( "You do not have the permission to administer this challenge.") challenge.hidden = True DB.session.commit() return {"name": "OK"}
def login_administrator(): """Login an administrator""" body = flask_rebar.get_validated_body() email = body["email"] password = body["password"] remember = body["remember"] if "remember" in body else False user = User.query.filter_by(email=email).first() if user is None or not user.check_password(password): raise errors.UnprocessableEntity("Invalid email or password.") administrator = user.get_administrator() if administrator is None: raise errors.Unauthorized("You must be an administrator to access this resource.") login_user(user, remember=remember) return administrator
def login(event: Event): """Login a participant""" body = flask_rebar.get_validated_body() email = body["email"] password = body["password"] remember = body["remember"] participant = Participant.query\ .join(Participant.user) \ .filter(User.email == email, Participant.event_id == event.id)\ .first() if participant is None or participant.user is None or not participant.user.check_password(password): raise errors.UnprocessableEntity("Invalid email or password.") login_user(participant.user, remember=remember) return participant
def kick_team_member(current_participant: Participant): """Kick a member of the team. Only captains can kick a team member""" body = flask_rebar.get_validated_body() participant_id = body["participant_id"] current_member = TeamMember.query.filter_by( participant_id=current_participant.id).first() if not current_member or not current_member.captain: raise errors.Unauthorized( "You don't have the rights to kick a team member.") if participant_id == current_participant.id: raise errors.UnprocessableEntity( "You cannot kick yourself from a team.") team_member = TeamMember.query.filter_by( participant_id=participant_id).first() DB.session.delete(team_member) DB.session.commit() return ""
def delete_challenge(current_admin: Administrator, challenge_id: int): """Delete a challenge""" challenge = Challenge.query.filter_by(id=challenge_id).first() if challenge is None: raise errors.UnprocessableEntity("This challenge does not exist.") if not current_admin.is_admin_of_event(challenge.category.event_id): raise errors.Unauthorized( "You do not have the permission to administer this challenge.") # Cleanup associated ressources flags = Flag.query.filter_by(challenge_id=challenge_id).all() submissions = Submission.query.filter_by(challenge_id=challenge_id).all() DB.session.delete(challenge) for flag in flags: DB.session.delete(flag) for submission in submissions: DB.session.delete(submission) DB.session.commit() return ""
def change_role(current_participant: Participant): """Change the role of a team member. Only captains can change a team member's role""" body = flask_rebar.get_validated_body() participant_id = body["participant_id"] new_role = body["captain"] current_member = TeamMember.query.filter_by( participant_id=current_participant.id).first() if not current_member or not current_member.captain: raise errors.Unauthorized( "You don't have the rights to change a team member's role.") if participant_id == current_participant.id: # In order to avoid a team "bricking" itself raise errors.UnprocessableEntity( "You cannot remove your own privileges.") team_member = TeamMember.query.filter_by( participant_id=participant_id).first() team_member.captain = new_role DB.session.commit() return ""