summaryrefslogtreecommitdiff
path: root/addons
diff options
context:
space:
mode:
authorDavid Beguin <dbe@odoo.com>2019-12-02 12:50:25 +0000
committerAurélien Warnon <awa@odoo.com>2020-01-10 11:01:04 +0000
commit26147efeab9bd37679c0202950c48bdb1c8ec04a (patch)
tree1efeff8e6bb7d5958c65d61f2ad673b9c369a630 /addons
parent94fd0624afc508bb46b9444ac232d313a200c168 (diff)
[IMP] survey: save questions on time limit reached
Purpose ======= If the timer goes to 00:00, the form is automatically submitted but the answers are not saved. The form should be submitted, validation should filter out invalid answers to avoid showing validation errors on the form, and save answers. If the answer is not in the correct format : skip the question If the answer is required but there is no answer : skip the question This way, we can still compute score. Specifications ============== This commit removes the invalid answers from the question to save, only if the timer is not over, to be able to compute score on not finished survey. In order to avoid being able to submit answers when the survey is marked as done, a check was added to return an error for that use case. Also, to avoid frontend timer hacking, an extra buffer of 10 seconds has been added. If the time limit is reached and the submit occurs 10 seconds after the maximum stop time (start time + time limit), no answer can be submitted. Task ID: 2152223 PR #41453
Diffstat (limited to 'addons')
-rw-r--r--addons/survey/controllers/main.py49
1 files changed, 22 insertions, 27 deletions
diff --git a/addons/survey/controllers/main.py b/addons/survey/controllers/main.py
index 11b2e287e04..db5b65a3ea9 100644
--- a/addons/survey/controllers/main.py
+++ b/addons/survey/controllers/main.py
@@ -5,7 +5,7 @@ import json
import logging
import werkzeug
-from datetime import datetime
+from datetime import datetime, timedelta
from dateutil.relativedelta import relativedelta
from odoo import fields, http, _
@@ -302,42 +302,37 @@ class Survey(http.Controller):
# Survey Validation
access_data = self._get_access_data(survey_token, answer_token, ensure_token=True)
if access_data['validity_code'] is not True:
- return {
- 'error': access_data['validity_code'],
- }
+ return {'error': access_data['validity_code']}
survey_sudo, answer_sudo = access_data['survey_sudo'], access_data['answer_sudo']
+ if answer_sudo.state == 'done':
+ return {'error': 'unauthorized'}
+
questions, page_or_question_id = survey_sudo._get_survey_questions(answer=answer_sudo,
page_id=post.get('page_id'),
question_id=post.get('question_id'))
if not answer_sudo.test_entry and not survey_sudo._has_attempts_left(answer_sudo.partner_id, answer_sudo.email, answer_sudo.invite_token):
# prevent cheating with users creating multiple 'user_input' before their last attempt
- return {}
-
- if not answer_sudo.is_time_limit_reached:
- # Prepare answers and comment by question
- prepared_questions = {}
- for question in questions:
- answer_full = post.get(str(question.id))
- answer_without_comment, comment = self._extract_comment_from_answers(question, answer_full)
- prepared_questions[question.id] = {'answer': answer_without_comment, 'comment': comment}
-
- # Questions Validation
- errors = {}
- for question in questions:
- answer = prepared_questions[question.id]['answer']
- comment = prepared_questions[question.id]['comment']
- errors.update(question.validate_question(answer, comment))
- if errors:
- return {'error': 'validation', 'fields': errors}
-
- # Submitting questions
- for question in questions:
- answer = prepared_questions[question.id]['answer']
- comment = prepared_questions[question.id]['comment']
+ return {'error': 'unauthorized'}
+
+ if answer_sudo.is_time_limit_reached:
+ time_limit = answer_sudo.start_datetime + timedelta(minutes=survey_sudo.time_limit)
+ if fields.Datetime.now() > (time_limit + timedelta(seconds=10)):
+ # prevent cheating with users blocking the JS timer and taking all their time to answer
+ return {'error': 'unauthorized'}
+
+ errors = {}
+ # Prepare answers / comment by question, validate and save answers
+ for question in questions:
+ answer, comment = self._extract_comment_from_answers(question, post.get(str(question.id)))
+ errors.update(question.validate_question(answer, comment))
+ if not errors.get(question.id):
answer_sudo.save_lines(question, answer, comment)
+ if errors and not answer_sudo.is_time_limit_reached:
+ return {'error': 'validation', 'fields': errors}
+
if answer_sudo.is_time_limit_reached or survey_sudo.questions_layout == 'one_page':
answer_sudo._mark_done()
elif 'previous_page_id' in post: