def submit_solution(self): """ A special form that, in addition to the form provided by :meth:`challenge`, allows a user to submit solutions for a challenge. The difference here is that the challenge is chosen from a select list. Otherwise it is basically the same and boils down to the same logic. """ form = SolutionSubmitListForm(self.request.POST, csrf_context=self.request) retparams = {'form': form} if self.request.method == 'POST': if not form.validate(): return retparams is_solved, msg = check_submission(form.challenge.data, form.solution.data, self.request.team, self.request.settings, ) self.request.session.flash(msg, 'success' if is_solved else 'error') if is_solved: return HTTPFound( location=self.request.route_url( 'challenge', id=form.challenge.data.id, ), ) else: return retparams return retparams
def test_check_submission_already_solved(self): c = self.make_challenge(solution="Test", online=True) t = self.make_team() s = Submission(team=t, challenge=c) self.dbsession.add(s) self.dbsession.flush() result, msg = check_submission(c, "Test", t, self.dbsettings) assert result is False assert msg == "Already solved."
def test_check_submission(self, solution, input_): c = self.make_challenge(online=True, solution=solution) t = self.make_team() self.dbsession.add_all([c, t]) self.dbsession.flush() result, msg = check_submission(c, input_, t, self.dbsettings) assert result is True assert msg.startswith('Congratulations: You solved this challenge as first!') assert len(c.submissions) == 1 assert len(t.submissions) == 1
def test_check_submission_places(self): c = self.make_challenge(online=True, solution="Test") teams = [self.make_team() for _ in range(4)] self.dbsession.add_all(teams + [c]) self.dbsession.flush() msgs = ['Congratulations: You solved this challenge as first!', 'Congratulations: You solved this challenge as second!', 'Congratulations: You solved this challenge as third!', 'Congratulations: That was the correct solution!'] for i in range(4): result, msg = check_submission(c, "Test", teams[i], self.dbsettings) assert result is True assert msg.startswith(msgs[i]) assert len(c.submissions) == i + 1 assert len(teams[i].submissions) == 1
def test_check_submission_ctf_over(self): self.dbsettings.ctf_end_date = now() - timedelta(1) result, msg = check_submission(None, None, None, self.dbsettings) assert result is False assert msg == "The CTF is over, no more solutions can be submitted."
def test_check_submission_dynamic(self): c = self.make_challenge(solution="Test", dynamic=True, online=True) result, msg = check_submission(c, "Test", None, self.dbsettings) assert result is False assert msg == "The challenge is dynamic, no submission possible."
def test_check_submission_manual(self): c = self.make_challenge(solution="Test", manual=True, online=True) result, msg = check_submission(c, "Test", None, self.dbsettings) assert result is False assert msg == "Credits for this challenge will be given manually."
def test_check_submission_incorrect_solution(self): c = self.make_challenge(solution="Test", online=True) result, msg = check_submission(c, "TestX", None, self.dbsettings) assert result is False assert msg == "Solution incorrect."
def test_check_submission_offline(self): result, msg = check_submission(self.make_challenge(), None, None, self.dbsettings) assert result is False assert msg == "Challenge is offline."
def test_check_submission_disabled(self): result, msg = check_submission(None, None, None, Settings(submission_disabled=True)) assert result is False assert msg == "Submission is currently disabled"
def challenge(self): """ A view of a single challenge. The query is very similar to that of :meth:`challenges` with the limitation that only one challenge is fetched. Additionally, this page displays a form to enter the solution of that challenge and fetches a list of announcements for the challenge. """ challenge_id = int(self.request.matchdict["id"]) team_id = self.request.authenticated_userid team_solved_subquery = get_team_solved_subquery(team_id) try: challenge, is_solved = ( DBSession.query(Challenge, team_solved_subquery). filter(Challenge.id == challenge_id). filter(Challenge.published).one() ) except NoResultFound: self.request.session.flash("Challenge not found or published.") return HTTPFound(location=self.request.route_url('challenges')) form = SolutionSubmitForm(self.request.POST, csrf_context=self.request) retparams = {'challenge': challenge, 'form': form, 'is_solved': is_solved, } # solved or after CTF feedback_obj = None if is_solved or (CTF_ENDED, True) == self.current_state: feedback_obj = ( DBSession.query(Feedback). filter(Feedback.team_id == self.request.team.id). filter(Feedback.challenge_id == challenge.id). first()) if not feedback_obj: feedback_obj = Feedback(team_id=self.request.team.id, challenge_id=challenge.id) DBSession.add(feedback_obj) retparams['feedback'] = FeedbackForm( self.request.POST, obj=feedback_obj, csrf_context=self.request) if self.request.method == 'POST': if 'submit_feedback' in self.request.POST: if not retparams['feedback'].validate(): return retparams if feedback_obj: retparams['feedback'].populate_obj(feedback_obj) self.request.session.flash( 'Thanks for your feedback. You can edit it at any ' 'point.') else: if not form.validate(): return retparams is_solved, msg = check_submission( challenge, form.solution.data, self.request.team, self.request.settings) self.request.session.flash(msg, 'success' if is_solved else 'error') return HTTPFound(location=self.request.route_url('challenge', id=challenge.id) ) return retparams