Quiz registration form

This commit is contained in:
Vivek Santayana 2021-11-25 23:12:20 +00:00
parent 9b1d8fca71
commit 52019e61c1
6 changed files with 125 additions and 24 deletions

View File

@ -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)])

View File

@ -3,7 +3,7 @@ $(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("—");
@ -11,3 +11,45 @@ $(document).ready(function() {
$(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 + `
<div class="alert alert-danger alert-dismissible fade show" role="alert">
<i class="bi bi-exclamation-triangle-fill" title="Danger"></i>
${response.responseJSON.error}
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
`;
} else if (response.responseJSON.error instanceof Array) {
for (var i = 0; i < response.responseJSON.error.length; i ++) {
alert.innerHTML = alert.innerHTML + `
<div class="alert alert-danger alert-dismissible fade show" role="alert">
<i class="bi bi-exclamation-triangle-fill" title="Danger"></i>
${response.responseJSON.error[i]}
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
`;
}
}
}
});
event.preventDefault();
});

View File

@ -0,0 +1,25 @@
{% extends "quiz/components/base.html" %}
{% block content %}
<h1>Privacy Policy</h1>
<ul>
<li>This web app stores data using cookies. The web site only stores the minimum information it needs to function.</li>
<li>Site Administrators</li>
<ul>
<li>For site administrators, this web site uses encrypted cookies to store data from your log-in session,</li>
<li>User information for administrators is encrypted and stored in a secure database, and are expunged when an account is deleted.</li>
</ul>
<li>Test Candidates</li>
<ul>
<li>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.</li>
<li>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.</li>
<li>These records will be kept for HOW MANY?? years and will be expunged securely thereafter.</li>
<li>All identifying information about candidates will be encrypted and stored in a secure database.</li>
</ul>
<li>Requests to Delete Data</li>
<ul>
<li>You can request to have any of your data that is held here deleted by emailing WHOM?</li>
</ul>
</ul>
{% endblock %}

View File

@ -23,8 +23,8 @@
{{ form.club.label }}
</div>
<div class="form-label-group">
{{ form.auth_code(class_="form-control auth-code-input", placeholder="Enter Exam Code") }}
{{ form.auth_code.label }}
{{ form.test_code(class_="form-control test-code-input", placeholder="Enter Exam Code") }}
{{ form.test_code.label }}
</div>
<div class="form-label-group">
{{ form.user_code(class_="form-control", placeholder="Enter User Code") }}

View File

@ -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"""<h1>Privacy Policy</h1>
<ul>
<li>Website stores data using cookies.</li>
<li>Site Administrators</li>
<li>This web site only uses functional cookies to store information on log-in.</li>
<li>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.</li>
<li>Test Candidate</li>
<li>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.</li>
<li>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.</li>
<ul>
"""
return render_template('/quiz/privacy.html')

View File

@ -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():