diff --git a/ref-test/quiz/forms.py b/ref-test/quiz/forms.py
index c0f508f..27574a1 100644
--- a/ref-test/quiz/forms.py
+++ b/ref-test/quiz/forms.py
@@ -7,5 +7,5 @@ class StartQuiz(FlaskForm):
surname = StringField('Surname', validators=[InputRequired(), Length(max=30)])
email = StringField('Email Address', validators=[InputRequired(), Email(message='You must enter a valid email address.'), Length(max=50)])
club = StringField('Affiliated Club (Optional)', validators=[Optional(), Length(max=50)])
- auth_code = StringField('Exam Code', validators=[InputRequired(), Length(min=14, max=14)])
+ test_code = StringField('Exam Code', validators=[InputRequired(), Length(min=14, max=14)])
user_code = StringField('User Code (Optional)', validators=[Optional(), Length(min=6, max=6)])
\ No newline at end of file
diff --git a/ref-test/quiz/static/js/script.js b/ref-test/quiz/static/js/script.js
index 1919828..279761c 100644
--- a/ref-test/quiz/static/js/script.js
+++ b/ref-test/quiz/static/js/script.js
@@ -3,11 +3,53 @@ $(document).ready(function() {
$("body").css("font-family", "opendyslexic3regular")
});
- $('.auth-code-input').keyup(function() {
+ $('.test-code-input').keyup(function() {
var input = $(this).val().split("-").join("").split("—").join(""); // remove hyphens and mdashes
if (input.length > 0) {
input = input.match(new RegExp('.{1,4}', 'g')).join("—");
}
$(this).val(input);
});
+});
+
+$('form[name=form-quiz-start]').submit(function(event) {
+
+ var $form = $(this);
+ var alert = document.getElementById('alert-box');
+ var data = $form.serialize();
+
+ alert.innerHTML = ''
+
+ $.ajax({
+ url: window.location.pathname,
+ type: 'POST',
+ data: data,
+ dataType: 'json',
+ success: function(response) {
+ window.location.href = "/admin/login/";
+ },
+ error: function(response) {
+ if (typeof response.responseJSON.error === 'string' || response.responseJSON.error instanceof String) {
+ alert.innerHTML = alert.innerHTML + `
+
+
+ ${response.responseJSON.error}
+
+
+ `;
+ } else if (response.responseJSON.error instanceof Array) {
+ for (var i = 0; i < response.responseJSON.error.length; i ++) {
+ alert.innerHTML = alert.innerHTML + `
+
+
+ ${response.responseJSON.error[i]}
+
+
+ `;
+ }
+ }
+ }
+ });
+
+ event.preventDefault();
});
\ No newline at end of file
diff --git a/ref-test/quiz/templates/quiz/privacy.html b/ref-test/quiz/templates/quiz/privacy.html
index e69de29..8e117df 100644
--- a/ref-test/quiz/templates/quiz/privacy.html
+++ b/ref-test/quiz/templates/quiz/privacy.html
@@ -0,0 +1,25 @@
+{% extends "quiz/components/base.html" %}
+
+{% block content %}
+
Privacy Policy
+
+
+
This web app stores data using cookies. The web site only stores the minimum information it needs to function.
+
Site Administrators
+
+
For site administrators, this web site uses encrypted cookies to store data from your log-in session,
+
User information for administrators is encrypted and stored in a secure database, and are expunged when an account is deleted.
+
+
Test Candidates
+
+
The web site will not be trackin your log in, and all information about your test attempt will be stored on your device until you submit it to the server.
+
Data from your test, including identifying information such as your name and email address, will be recorded by the Scottish Korfball Association in order to oversee the training and qualification of referees.
+
These records will be kept for HOW MANY?? years and will be expunged securely thereafter.
+
All identifying information about candidates will be encrypted and stored in a secure database.
+
+
Requests to Delete Data
+
+
You can request to have any of your data that is held here deleted by emailing WHOM?
+
+
+{% endblock %}
\ No newline at end of file
diff --git a/ref-test/quiz/templates/quiz/start-quiz.html b/ref-test/quiz/templates/quiz/start-quiz.html
index e2918db..6987f60 100644
--- a/ref-test/quiz/templates/quiz/start-quiz.html
+++ b/ref-test/quiz/templates/quiz/start-quiz.html
@@ -23,8 +23,8 @@
{{ form.club.label }}
{{ form.user_code(class_="form-control", placeholder="Enter User Code") }}
diff --git a/ref-test/quiz/views.py b/ref-test/quiz/views.py
index 71ee15f..3f0bb35 100644
--- a/ref-test/quiz/views.py
+++ b/ref-test/quiz/views.py
@@ -1,4 +1,9 @@
-from flask import Blueprint, render_template
+from flask import Blueprint, render_template, request, redirect, jsonify
+from datetime import datetime
+from uuid import uuid4
+
+from main import db
+from security import encrypt
views = Blueprint(
'quiz_views',
@@ -17,20 +22,38 @@ def home():
def start():
from .forms import StartQuiz
form = StartQuiz()
- return render_template('/quiz/start-quiz.html', form=form)
+ if request.method == 'GET':
+ return render_template('/quiz/start-quiz.html', form=form)
+ if request.method == 'POST':
+ if form.validate_on_submit():
+ name = {
+ 'first_name': request.form.get('first_name'),
+ 'surname': request.form.get('surname')
+ }
+ email = request.form.get('email')
+ club = request.form.get('club')
+ test_code = request.form.get('test_code').replace('—', '')
+ user_code = request.form.get('user_code')
+ user_code = None if user_code == '' else user_code
+ if not db.tests.find_one({'test_code': test_code}):
+ return jsonify({'error': 'The exam code you entered is invalid.'}), 400
+ attempt = {
+ '_id': uuid4().hex,
+ 'name': encrypt(name),
+ 'email': encrypt(email),
+ 'club': encrypt(club),
+ 'test-code': test_code,
+ 'user_code': user_code,
+ 'start_time': datetime.utcnow(),
+ 'status': 'started'
+ }
+ if db.results.insert(attempt):
+ return jsonify({ 'success': f'Exam started at started {attempt["start_time"].strftime("%H:%M:%S")}.' })
+ else:
+ errors = [*form.errors]
+ return jsonify({ 'error': errors}), 400
+
@views.route('/privacy/')
def privacy():
- return f"""
Privacy Policy
-
-
-
Website stores data using cookies.
-
Site Administrators
-
This web site only uses functional cookies to store information on log-in.
-
User information for administrators will be encrypted and stored in a secure database for the purposes of administering this web site, and will be expunged when the user account is deleted.
-
Test Candidate
-
The web site will not be tracking your log in, and all information about your test attempt will be stored on your device until it is submitted to the server.
-
Data from your test as well as identifying information about the candidate will be encrypted and stored in a secure database on the server, and will be retained for a period of HOW MANY? years for the SKA's records.
-
-
- """
\ No newline at end of file
+ return render_template('/quiz/privacy.html')
\ No newline at end of file
diff --git a/ref-test/security/__init__.py b/ref-test/security/__init__.py
index 9542b24..83d22c2 100644
--- a/ref-test/security/__init__.py
+++ b/ref-test/security/__init__.py
@@ -1,4 +1,4 @@
-from os import path
+from os import environ, path
from cryptography.fernet import Fernet
def generate_keyfile():
@@ -14,14 +14,25 @@ def load_key():
def check_keyfile_exists():
return path.isfile('./security/.encryption.key')
-def encrypt(input:str):
- input = input.encode()
+def encrypt(input):
if not check_keyfile_exists():
generate_keyfile()
_encryption_key = load_key()
fernet = Fernet(_encryption_key)
- output = fernet.encrypt(input)
- return output.decode()
+ if type(input) == str:
+ input = input.encode()
+ output = fernet.encrypt(input)
+ return output.decode()
+ if type(input) == dict:
+ output = {}
+ for key,value in input.items():
+ if type(value) == dict:
+ output[key] = encrypt(value)
+ else:
+ value = value.encode()
+ output[key] = fernet.encrypt(value)
+ output[key] = output[key].decode()
+ return output
def decrypt(input):
if not check_keyfile_exists():