Skip to content
This repository has been archived by the owner on Jul 3, 2020. It is now read-only.

Commit

Permalink
Prevent sending answers when the test timed out for the user
Browse files Browse the repository at this point in the history
  • Loading branch information
evgfilim1 committed Aug 29, 2018
1 parent f02c583 commit 75fc330
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 27 deletions.
9 changes: 7 additions & 2 deletions endpoints/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,17 @@
from secrets import randbelow
from forms import AddQuestionForm, AddAdminForm, AddUsersForm, ImportQuestionsForm
from models import db, User, UserAnswer, Question, Answer
from utils import admin_required, find_user, back, json_response
from utils import admin_required, find_user, back, json_response, remaining_time, finish_test


@admin_required
def admin_panel():
user_list = sorted(User.query.all(), key=lambda x: x.points or 0, reverse=True)
users = User.query.all()
for user in users:
if remaining_time(user) <= 0:
finish_test(user)
db.session.commit()
user_list = sorted(users, key=lambda x: x.points or 0, reverse=True)
return render_template('admin.html', users=user_list, title='Панель администратора')


Expand Down
12 changes: 8 additions & 4 deletions endpoints/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,15 @@
def save_answer():
answer_id = request.form.get('a')
user_id = request.form.get('u', None)
success = _save_answer(answer_id, user_id)
result = {'ok': success}
result = _save_answer(answer_id, user_id)
success = False
if result is True:
success = True
response = {'ok': success}
if not success:
return json_response(result, 400)
return json_response(result)
response['error'], response['error_code'] = result
return json_response(response, 400)
return json_response(response)


def change_question_data():
Expand Down
20 changes: 6 additions & 14 deletions main.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
from flask import render_template, redirect, url_for, session, g, request, flash
from markdown import markdown
from datetime import datetime, timedelta
from datetime import datetime
from random import shuffle
from app import app
from endpoints import admin, api
from forms import LoginForm
from models import Question, db, UserAnswer
from utils import find_user, get_user, login_required, back, is_browser_supported
from utils import (find_user, get_user, login_required, back, is_browser_supported, remaining_time,
finish_test)


@app.before_request
Expand Down Expand Up @@ -61,10 +62,8 @@ def solve():
if g.user.start_time is None:
g.user.start_time = datetime.utcnow()
db.session.commit()
max_end_time = g.user.start_time + timedelta(seconds=app.config.get('TIME_TO_SOLVE', 3600))
remaining = max_end_time - datetime.utcnow()
return render_template('test.html',
remaining=int(remaining.total_seconds()), answers=None, shuffle=shuffle,
remaining = remaining_time(g.user)
return render_template('test.html', remaining=int(remaining), answers=None, shuffle=shuffle,
questions=Question.query.order_by(Question.number).all())


Expand All @@ -84,16 +83,9 @@ def result(user_id=None):
return redirect(back('admin_panel'))
if request.method == 'POST':
flash('Тест завершён!', category='success')
if user.end_time is None:
user.end_time = datetime.utcnow()
user.points = 0
for a in g.user.answers:
if a.is_correct:
g.user.points += a.question.points
db.session.commit()
finish_test(user)
return redirect(url_for('result'))
if user.end_time is None:
# testctf_flag2_commit_diff
if user_id is not None:
flash('Тест ещё не был завершён!')
return redirect(back('admin_panel'))
Expand Down
18 changes: 16 additions & 2 deletions static/js/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,22 @@ function uploadAnswer(answer_id, user_id, question_id) {
$(`#q${question_id}-a${answer_id}`).addClass('answered');
localStorage.removeItem(`u${user_id}-q${question_id}`);
},
error: function () {
console.warn(`Failed to upload answer (id=${answer_id})`);
error: function (jqxhr) {
if (jqxhr.status === 400 && jqxhr.responseJSON !== undefined) {
const r = jqxhr.responseJSON;
if (r.ok === false && 1 <= r.error_code && r.error_code <= 3) {
console.warn(`Failed to upload answer (id=${answer_id}): ${r.error}`);
if (r.error_code === 1) {
location.reload(true);
} else if (r.error_code === 3) {
$('#finish-test').submit();
}
return;
}
}
console.warn(
`Failed to upload answer (id=${answer_id}): ${jqxhr.status} ${jqxhr.statusText}`
);
localStorage.setItem(`u${user_id}-q${question_id}`, answer_id);
}
});
Expand Down
30 changes: 25 additions & 5 deletions utils.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
from flask import g, Response, redirect, url_for, flash, request
from json import dumps
from functools import wraps
from datetime import datetime
from datetime import datetime, timedelta
from app import app
from models import User, Answer, UserAnswer, db


Expand All @@ -19,19 +20,38 @@ def is_browser_supported():
return ua.browser in ('chrome', 'firefox') and v >= (60, 0)


def remaining_time(user):
time_to_solve = app.config.get('TIME_TO_SOLVE', 3600)
if user.start_time is None:
return time_to_solve
max_end_time = user.start_time + timedelta(seconds=time_to_solve)
return (max_end_time - datetime.utcnow()).total_seconds()


def finish_test(user):
if user.end_time is None:
user.end_time = datetime.utcnow()
user.points = 0
for a in user.answers:
if a.is_correct:
user.points += a.question.points
db.session.commit()


def save_answer(answer_id, user_id=None):
if user_id is None:
user = g.user
else:
user = get_user(user_id)
if answer_id is None or user is None:
return False
return 'Not found', 2
if user.end_time is not None:
return True # just ignore
return 'Test finished', 1
if remaining_time(user) <= 0:
return 'Test timed out', 3
answer = Answer.query.get(answer_id)
if answer is None:
# TODO: log this, maybe it was right
return False
return 'Not found', 2
user_answer = UserAnswer.query.filter_by(user_id=user.id,
question_id=answer.question_id).first()
if user_answer is not None:
Expand Down

0 comments on commit 75fc330

Please sign in to comment.