Compare commits

..

4 Commits

18 changed files with 80 additions and 96 deletions

3
.gitignore vendored
View File

@ -153,3 +153,6 @@ database/data/
# Ignore Data Dir
**/data/*
# Ignore Logs Dir
logs/*

View File

@ -36,6 +36,7 @@ services:
- 5000
volumes:
- data:/ref-test/data
- ./logs:/ref-test/data/logs
restart: unless-stopped
networks:
- frontend

View File

@ -27,7 +27,7 @@ def create_app():
@login_manager.user_loader
def _load_user(id):
try: return User.query.filter_by(id=id).first()
except SQLAlchemyError as exception:
except (SQLAlchemyError, ConnectionError) as exception:
write('system.log', f'Database error when loading user fo login manager: {exception}')
return abort(500)

View File

@ -31,7 +31,7 @@ def _home():
try:
tests = Test.query.all()
results = Entry.query.all()
except SQLAlchemyError as exception:
except (SQLAlchemyError, ConnectionError) as exception:
write('system.log', f'Database error when processing request \'{request.url}\': {exception}')
return abort(500)
current_tests = [ test for test in tests if test.end_date >= datetime.now() and test.start_date.date() <= date.today() ]
@ -48,7 +48,7 @@ def _settings():
try:
users = User.query.all()
datasets = Dataset.query.all()
except SQLAlchemyError as exception:
except (SQLAlchemyError, ConnectionError) as exception:
write('system.log', f'Database error when processing request \'{request.url}\': {exception}')
return abort(500)
return render_template('/admin/settings/index.html', users=users, datasets=datasets)
@ -61,7 +61,7 @@ def _login():
if request.method == 'POST':
if form.validate_on_submit():
try: users = User.query.all()
except SQLAlchemyError as exception:
except (SQLAlchemyError, ConnectionError) as exception:
write('system.log', f'Database error when processing request \'{request.url}\': {exception}')
return abort(500)
user = None
@ -113,7 +113,7 @@ def _reset():
if form.validate_on_submit():
user = None
try: users = User.query.all()
except SQLAlchemyError as exception:
except (SQLAlchemyError, ConnectionError) as exception:
write('system.log', f'Database error when processing request \'{request.url}\': {exception}')
return abort(500)
for _user in users:
@ -128,7 +128,7 @@ def _reset():
token = request.args.get('token')
if token:
try: user = User.query.filter_by(reset_token=token).first()
except SQLAlchemyError as exception:
except (SQLAlchemyError, ConnectionError) as exception:
write('system.log', f'Database error when processing request \'{request.url}\': {exception}')
return abort(500)
if not user: return redirect(url_for('admin._reset'))
@ -148,7 +148,7 @@ def _update_password():
if form.validate_on_submit():
user = session.pop('user')
try: user = User.query.filter_by(id=user).first()
except SQLAlchemyError as exception:
except (SQLAlchemyError, ConnectionError) as exception:
write('system.log', f'Database error when processing request \'{request.url}\': {exception}')
return abort(500)
user.update(password=request.form.get('password'))
@ -162,7 +162,7 @@ def _update_password():
def _users():
form = CreateUser()
try: users = User.query.all()
except SQLAlchemyError as exception:
except (SQLAlchemyError, ConnectionError) as exception:
write('system.log', f'Database error when processing request \'{request.url}\': {exception}')
return abort(500)
if request.method == 'POST':
@ -182,7 +182,7 @@ def _users():
@login_required
def _delete_user(id:str):
try: user = User.query.filter_by(id=id).first()
except SQLAlchemyError as exception:
except (SQLAlchemyError, ConnectionError) as exception:
write('system.log', f'Database error when processing request \'{request.url}\': {exception}')
return abort(500)
form = DeleteUser()
@ -209,7 +209,7 @@ def _delete_user(id:str):
@login_required
def _update_user(id:str):
try: user = User.query.filter_by(id=id).first()
except SQLAlchemyError as exception:
except (SQLAlchemyError, ConnectionError) as exception:
write('system.log', f'Database error when processing request \'{request.url}\': {exception}')
return abort(500)
form = UpdateUser()
@ -254,7 +254,7 @@ def _questions():
return send_errors_to_client(form=form)
try: data = Dataset.query.all()
except SQLAlchemyError as exception:
except (SQLAlchemyError, ConnectionError) as exception:
write('system.log', f'Database error when processing request \'{request.url}\': {exception}')
return abort(500)
return render_template('/admin/settings/questions.html', form=form, data=data)
@ -266,7 +266,7 @@ def _edit_questions():
action = request.get_json()['action']
if not action == 'delete': return jsonify({'error': 'Invalid action.'}), 400
try: dataset = Dataset.query.filter_by(id=id).first()
except SQLAlchemyError as exception:
except (SQLAlchemyError, ConnectionError) as exception:
write('system.log', f'Database error when processing request \'{request.url}\': {exception}')
return abort(500)
if action == 'delete': success, message = dataset.delete()
@ -277,7 +277,7 @@ def _edit_questions():
@login_required
def _download(id:str):
try: dataset = Dataset.query.filter_by(id=id).first()
except SQLAlchemyError as exception:
except (SQLAlchemyError, ConnectionError) as exception:
write('system.log', f'Database error when processing request \'{request.url}\': {exception}')
return abort(500)
if not dataset: return abort(404)
@ -291,7 +291,7 @@ def _download(id:str):
def _tests(filter:str=None):
tests = None
try: _tests = Test.query.all()
except SQLAlchemyError as exception:
except (SQLAlchemyError, ConnectionError) as exception:
write('system.log', f'Database error when processing request \'{request.url}\': {exception}')
return abort(500)
form = None
@ -340,7 +340,7 @@ def _create_test():
new_test.time_limit = None if request.form.get('time_limit') == 'none' else int(request.form.get('time_limit'))
dataset = request.form.get('dataset')
try: new_test.dataset = Dataset.query.filter_by(id=dataset).first()
except SQLAlchemyError as exception:
except (SQLAlchemyError, ConnectionError) as exception:
write('system.log', f'Database error when processing request \'{request.url}\': {exception}')
return abort(500)
success, message = new_test.create()
@ -357,7 +357,7 @@ def _edit_test():
action = request.get_json()['action']
if action not in ['start', 'delete', 'end']: return jsonify({'error': 'Invalid action.'}), 400
try: test = Test.query.filter_by(id=id).first()
except SQLAlchemyError as exception:
except (SQLAlchemyError, ConnectionError) as exception:
write('system.log', f'Database error when processing request \'{request.url}\': {exception}')
return abort(500)
if not test: return jsonify({'error': 'Could not find the corresponding test to delete.'}), 404
@ -374,7 +374,7 @@ def _edit_test():
def _view_test(id:str=None):
form = AddTimeAdjustment()
try: test = Test.query.filter_by(id=id).first()
except SQLAlchemyError as exception:
except (SQLAlchemyError, ConnectionError) as exception:
write('system.log', f'Database error when processing request \'{request.url}\': {exception}')
return abort(500)
if request.method == 'POST':
@ -394,7 +394,7 @@ def _view_test(id:str=None):
@login_required
def _delete_adjustment(id:str=None):
try: test = Test.query.filter_by(id=id).first()
except SQLAlchemyError as exception:
except (SQLAlchemyError, ConnectionError) as exception:
write('system.log', f'Database error when processing request \'{request.url}\': {exception}')
return abort(500)
if not test: return jsonify({'error': 'Invalid test ID.'}), 404
@ -407,7 +407,7 @@ def _delete_adjustment(id:str=None):
@login_required
def _view_entries():
try: entries = Entry.query.all()
except SQLAlchemyError as exception:
except (SQLAlchemyError, ConnectionError) as exception:
write('system.log', f'Database error when processing request \'{request.url}\': {exception}')
return abort(500)
return render_template('/admin/results.html', entries = entries)
@ -416,7 +416,7 @@ def _view_entries():
@login_required
def _view_entry(id:str=None):
try: entry = Entry.query.filter_by(id=id).first()
except SQLAlchemyError as exception:
except (SQLAlchemyError, ConnectionError) as exception:
write('system.log', f'Database error when processing request \'{request.url}\': {exception}')
return abort(500)
if request.method == 'POST':
@ -450,7 +450,7 @@ def _generate_certificate():
from ..extensions import db
id = request.get_json()['id']
try: entry = Entry.query.filter_by(id=id).first()
except SQLAlchemyError as exception:
except (SQLAlchemyError, ConnectionError) as exception:
write('system.log', f'Database error when processing request \'{request.url}\': {exception}')
return abort(500)
if not entry: return jsonify({'error': 'Invalid entry ID.'}), 404

View File

@ -20,7 +20,7 @@ api = Blueprint(
def _fetch_questions():
id = request.get_json()['id']
try: entry = Entry.query.filter_by(id=id).first()
except SQLAlchemyError as exception:
except (SQLAlchemyError, ConnectionError) as exception:
write('system.log', f'Database error when processing request \'{request.url}\': {exception}')
return abort(500)
if not entry: return jsonify({'error': 'Invalid entry ID.'}), 400
@ -57,7 +57,7 @@ def _submit_quiz():
id = request.get_json()['id']
answers = request.get_json()['answers']
try: entry = Entry.query.filter_by(id=id).first()
except SQLAlchemyError as exception:
except (SQLAlchemyError, ConnectionError) as exception:
write('system.log', f'Database error when processing request \'{request.url}\': {exception}')
return abort(500)
if not entry: return jsonify({'error': 'Unrecognised Entry.'}), 400
@ -80,10 +80,8 @@ def _submit_quiz():
def _editor(id:str=None):
request_data = request.get_json()
id = request_data['id']
try:
dataset = Dataset.query.filter_by(id=id).first()
user = User.query.filter_by(id=creator).first()
except SQLAlchemyError as exception:
try: dataset = Dataset.query.filter_by(id=id).first()
except (SQLAlchemyError, ConnectionError) as exception:
write('system.log', f'Database error when processing request \'{request.url}\': {exception}')
return abort(500)
if not dataset: return jsonify({'error': 'Invalid request. Dataset not found.'}), 404
@ -94,6 +92,10 @@ def _editor(id:str=None):
return jsonify({'success': 'Successfully downloaded dataset', 'data': data}), 200
default = request_data['default']
creator = request_data['creator']
try: user = User.query.filter_by(id=creator).first()
except (SQLAlchemyError, ConnectionError) as exception:
write('system.log', f'Database error when processing request \'{request.url}\': {exception}')
return abort(500)
name = request_data['name']
data = request_data['data']
if not validate_json(data): return jsonify({'error': 'The data you submitted was invalid.'}), 400

View File

@ -37,7 +37,7 @@ def _editor_console(id:str=None):
dataset = Dataset.query.filter_by(id=id).first()
datasets = Dataset.query.count()
users = User.query.all()
except SQLAlchemyError as exception:
except (SQLAlchemyError, ConnectionError) as exception:
write('system.log', f'Database error when processing request \'{request.url}\': {exception}')
return abort(500)
if not dataset:

View File

@ -45,12 +45,12 @@ class Dataset(db.Model):
def make_default(self):
try:
for dataset in Dataset.query.all(): dataset.default = False
except SQLAlchemyError as exception:
except (SQLAlchemyError, ConnectionError) as exception:
write('system.log', f'Database error when setting default dataset {self.id}: {exception}')
return False, f'Database error {exception}.'
self.default = True
try: db.session.commit()
except SQLAlchemyError as exception:
except (SQLAlchemyError, ConnectionError) as exception:
db.session.rollback()
write('system.log', f'Database error when setting default dataset {self.id}: {exception}')
return False, f'Database error {exception}.'
@ -68,7 +68,7 @@ class Dataset(db.Model):
message = 'Cannot delete the only dataset.'
flash(message, 'error')
return False, message
except SQLAlchemyError as exception:
except (SQLAlchemyError, ConnectionError) as exception:
write('system.log', f'Database error when setting default dataset {self.id}: {exception}')
return False, f'Database error {exception}.'
write('system.log', f'Dataset {self.id} deleted by {current_user.get_username()}.')
@ -78,7 +78,7 @@ class Dataset(db.Model):
try:
db.session.delete(self)
db.session.commit()
except SQLAlchemyError as exception:
except (SQLAlchemyError, ConnectionError) as exception:
db.session.rollback()
write('system.log', f'Database error when trying to delete dataset {self.id}: {exception}')
return False, f'Database error: {exception}'
@ -98,7 +98,7 @@ class Dataset(db.Model):
try:
db.session.add(self)
db.session.commit()
except SQLAlchemyError as exception:
except (SQLAlchemyError, ConnectionError) as exception:
db.session.rollback()
write('system.log', f'Database error when trying to crreate dataset {self.id}: {exception}')
return False, f'Database error: {exception}'
@ -128,7 +128,7 @@ class Dataset(db.Model):
try:
db.session.add(self)
db.session.commit()
except SQLAlchemyError as exception:
except (SQLAlchemyError, ConnectionError) as exception:
db.session.rollback()
write('system.log', f'Database error when trying to update dataset {self.id}: {exception}')
return False, f'Database error: {exception}'

View File

@ -1,5 +1,4 @@
from ..extensions import db, mail
from ..tools.forms import JsonEncodedDict
from ..tools.encryption import decrypt, encrypt
from ..tools.logs import write
from .test import Test
@ -8,6 +7,7 @@ from flask_login import current_user
from flask_mail import Message
from smtplib import SMTPException
from sqlalchemy.exc import SQLAlchemyError
from sqlalchemy_json import MutableJson
from datetime import datetime, timedelta
from uuid import uuid4
@ -25,8 +25,8 @@ class Entry(db.Model):
end_time = db.Column(db.DateTime, nullable=True)
status = db.Column(db.String(16), nullable=True)
valid = db.Column(db.Boolean, default=True, nullable=True)
answers = db.Column(JsonEncodedDict, nullable=True)
result = db.Column(JsonEncodedDict, nullable=True)
answers = db.Column(MutableJson, nullable=True)
result = db.Column(MutableJson, nullable=True)
def __repr__(self):
return f'<New entry by {self.first_name} {self.surname}> was added with <id {self.id}>.'
@ -74,7 +74,7 @@ class Entry(db.Model):
try:
db.session.add(self)
db.session.commit()
except SQLAlchemyError as exception:
except (SQLAlchemyError, ConnectionError) as exception:
db.session.rollback()
write('system.log', f'Database error when preparing new entry for {self.get_surname()}, {self.get_first_name()}: {exception}')
return False, f'Database error: {exception}'
@ -85,7 +85,7 @@ class Entry(db.Model):
self.start_time = datetime.now()
self.status = 'started'
try: db.session.commit()
except SQLAlchemyError as exception:
except (SQLAlchemyError, ConnectionError) as exception:
db.session.rollback()
write('system.log', f'Database error when starting test for {self.get_surname()}, {self.get_first_name()}: {exception}')
return False, f'Database error: {exception}'
@ -104,7 +104,7 @@ class Entry(db.Model):
self.status = 'late'
self.valid = False
try: db.session.commit()
except SQLAlchemyError as exception:
except (SQLAlchemyError, ConnectionError) as exception:
db.session.rollback()
write('system.log', f'Database error when submitting entry for {self.get_surname()}, {self.get_first_name()}: {exception}')
return False, f'Database error: {exception}'
@ -117,7 +117,7 @@ class Entry(db.Model):
self.valid = True
self.status = 'completed'
try: db.session.commit()
except SQLAlchemyError as exception:
except (SQLAlchemyError, ConnectionError) as exception:
db.session.rollback()
write('system.log', f'Database error when validating entry {self.id}: {exception}')
return False, f'Database error: {exception}'
@ -130,7 +130,7 @@ class Entry(db.Model):
try:
db.session.delete(self)
db.session.commit()
except SQLAlchemyError as exception:
except (SQLAlchemyError, ConnectionError) as exception:
db.session.rollback()
write('system.log', f'Database error when deleting entry {id}: {exception}')
return False, f'Database error: {exception}'
@ -199,5 +199,4 @@ class Entry(db.Model):
"""
)
try: mail.send(email)
except SMTPException as exception:
write('system.log', f'SMTP Error when trying to notify results to {self.get_surname()}, {self.get_first_name()} with error: {exception}')
except (SMTPException, ConnectionError) as exception: write('system.log', f'SMTP Error when trying to notify results to {self.get_surname()}, {self.get_first_name()} with error: {exception}')

View File

@ -1,9 +1,9 @@
from ..extensions import db
from ..tools.forms import JsonEncodedDict
from ..tools.logs import write
from flask_login import current_user
from sqlalchemy.exc import SQLAlchemyError
from sqlalchemy_json import MutableJson
from datetime import date, datetime
import secrets
@ -18,7 +18,7 @@ class Test(db.Model):
time_limit = db.Column(db.Integer, nullable=True)
creator_id = db.Column(db.String(36), db.ForeignKey('user.id'))
dataset_id = db.Column(db.String(36), db.ForeignKey('dataset.id'))
adjustments = db.Column(JsonEncodedDict, nullable=True)
adjustments = db.Column(MutableJson, nullable=True)
entries = db.relationship('Entry', backref='test')
def __repr__(self):
@ -56,7 +56,7 @@ class Test(db.Model):
try:
db.session.add(self)
db.session.commit()
except SQLAlchemyError as exception:
except (SQLAlchemyError, ConnectionError) as exception:
db.session.rollback()
write('system.log', f'Database error when creating test {self.get_code()}: {exception}')
return False, f'Database error: {exception}'
@ -67,7 +67,7 @@ class Test(db.Model):
if self.entries: return False, f'Cannot delete a test with submitted entries.'
db.session.delete(self)
try: db.session.commit()
except SQLAlchemyError as exception:
except (SQLAlchemyError, ConnectionError) as exception:
db.session.rollback()
write('system.log', f'Database error when deleting test {self.get_code()}: {exception}')
return False, f'Database error: {exception}'
@ -79,7 +79,7 @@ class Test(db.Model):
if self.start_date.date() > now.date():
self.start_date = now
try: db.session.commit()
except SQLAlchemyError as exception:
except (SQLAlchemyError, ConnectionError) as exception:
db.session.rollback()
write('system.log', f'Database error when launching test {self.get_code()}: {exception}')
return False, f'Database error: {exception}'
@ -92,7 +92,7 @@ class Test(db.Model):
if self.end_date >= now:
self.end_date = now
try: db.session.commit()
except SQLAlchemyError as exception:
except (SQLAlchemyError, ConnectionError) as exception:
db.session.rollback()
write('system.log', f'Database error when closing test {self.get_code()}: {exception}')
return False, f'Database error: {exception}'
@ -106,7 +106,7 @@ class Test(db.Model):
adjustments[code] = time
self.adjustments = adjustments
try: db.session.commit()
except SQLAlchemyError as exception:
except (SQLAlchemyError, ConnectionError) as exception:
db.session.rollback()
write('system.log', f'Database error when adding adjustment to test {self.get_code()}: {exception}')
return False, f'Database error: {exception}'
@ -118,7 +118,7 @@ class Test(db.Model):
self.adjustments.pop(code)
if not self.adjustments: self.adjustments = None
try: db.session.commit()
except SQLAlchemyError as exception:
except (SQLAlchemyError, ConnectionError) as exception:
db.session.rollback()
write('system.log', f'Database error when deleting adjustment from test {self.get_code()}: {exception}')
return False, f'Database error: {exception}'
@ -131,7 +131,7 @@ class Test(db.Model):
if end_date: self.end_date = end_date
if time_limit is not None: self.time_limit = time_limit
try: db.session.commit()
except SQLAlchemyError as exception:
except (SQLAlchemyError, ConnectionError) as exception:
db.session.rollback()
write('system.log', f'Database error when updating test {self.get_code()}: {exception}')
return False, f'Database error: {exception}'

View File

@ -58,7 +58,7 @@ class User(UserMixin, db.Model):
def register(self, notify:bool=False, password:str=None):
self.generate_id()
try: users = User.query.all()
except SQLAlchemyError as exception:
except (SQLAlchemyError, ConnectionError) as exception:
write('system.log', f'Database error when setting default dataset {self.id}: {exception}')
return False, f'Database error {exception}.'
for user in users:
@ -68,7 +68,7 @@ class User(UserMixin, db.Model):
try:
db.session.add(self)
db.session.commit()
except SQLAlchemyError as exception:
except (SQLAlchemyError, ConnectionError) as exception:
db.session.rollback()
write('system.log', f'Database error when registering user {self.get_username()}: {exception}')
return False, f'Database error: {exception}'
@ -101,8 +101,7 @@ class User(UserMixin, db.Model):
"""
)
try: mail.send(email)
except SMTPException as exception:
write('system.log', f'SMTP Error while trying to notify new user account creation to {self.get_username()} with error: {exception}')
except (SMTPException, ConnectionError) as exception: write('system.log', f'SMTP Error while trying to notify new user account creation to {self.get_username()} with error: {exception}')
return True, f'User {self.get_username()} was created successfully.'
def login(self, remember:bool=False):
@ -154,12 +153,12 @@ class User(UserMixin, db.Model):
"""
)
try: mail.send(email)
except SMTPException as exception:
except (SMTPException, ConnectionError) as exception:
write('system.log', f'SMTP Error while trying to reset password for {self.get_username()} with error: {exception}')
db.session.rollback()
return jsonify({'error': f'SMTP Error: {exception}'}), 500
try: db.session.commit()
except SQLAlchemyError as exception:
except (SQLAlchemyError, ConnectionError) as exception:
db.session.rollback()
write('system.log', f'Database error when resetting password for user {self.get_username()}: {exception}')
return False, f'Database error: {exception}'
@ -168,7 +167,7 @@ class User(UserMixin, db.Model):
def clear_reset_tokens(self):
self.reset_token = self.verification_token = None
try: db.session.commit()
except SQLAlchemyError as exception:
except (SQLAlchemyError, ConnectionError) as exception:
db.session.rollback()
write('system.log', f'Database error when resetting clearing reset tokens for user {self.get_username()}: {exception}')
return False, f'Database error: {exception}'
@ -179,7 +178,7 @@ class User(UserMixin, db.Model):
try:
db.session.delete(self)
db.session.commit()
except SQLAlchemyError as exception:
except (SQLAlchemyError, ConnectionError) as exception:
db.session.rollback()
write('system.log', f'Database error when deleting user {self.get_username()}: {exception}')
return False, f'Database error: {exception}'
@ -208,8 +207,7 @@ class User(UserMixin, db.Model):
"""
)
try: mail.send(email)
except SMTPException as exception:
write('system.log', f'SMTP Error when trying to delete account {username} with error: {exception}')
except (SMTPException, ConnectionError) as exception: write('system.log', f'SMTP Error when trying to delete account {username} with error: {exception}')
return True, message
def update(self, password:str=None, email:str=None, notify:bool=False):
@ -220,12 +218,12 @@ class User(UserMixin, db.Model):
try:
for entry in User.query.all():
if entry.get_email() == email and not entry == self: return False, f'The email address {email} is already in use.'
except SQLAlchemyError as exception:
except (SQLAlchemyError, ConnectionError) as exception:
write('system.log', f'Database error when setting default dataset {self.id}: {exception}')
return False, f'Database error {exception}.'
self.set_email(email)
try: db.session.commit()
except SQLAlchemyError as exception:
except (SQLAlchemyError, ConnectionError) as exception:
db.session.rollback()
write('system.log', f'Database error when updating user {self.get_username()}: {exception}')
return False, f'Database error: {exception}'
@ -259,6 +257,5 @@ class User(UserMixin, db.Model):
"""
)
try: mail.send(message)
except SMTPException as exception:
write('system.log', f'SMTP Error when trying to update account {self.get_username()} with error: {exception}')
except (SMTPException, ConnectionError) as exception: write('system.log', f'SMTP Error when trying to update account {self.get_username()} with error: {exception}')
return True, f'Account {self.get_username()} has been updated.'

View File

@ -40,7 +40,7 @@ def _start():
entry.set_email(request.form.get('email'))
code = request.form.get('test_code').replace('', '').lower()
try: test = Test.query.filter_by(code=code).first()
except SQLAlchemyError as exception:
except (SQLAlchemyError, ConnectionError) as exception:
write('system.log', f'Database error when processing request \'{request.url}\': {exception}')
return abort(500)
entry.test = test
@ -69,7 +69,7 @@ def _quiz():
flash('Your session was not recognised. Please sign in to the quiz again.', 'error')
session.pop('id', None)
return redirect(url_for('quiz._start'))
except SQLAlchemyError as exception:
except (SQLAlchemyError, ConnectionError) as exception:
write('system.log', f'Database error when processing request \'{request.url}\': {exception}')
return abort(500)
return render_template('/quiz/client.html')
@ -78,7 +78,7 @@ def _quiz():
def _result():
id = session.get('id')
try: entry = Entry.query.filter_by(id=id).first()
except SQLAlchemyError as exception:
except (SQLAlchemyError, ConnectionError) as exception:
write('system.log', f'Database error when processing request \'{request.url}\': {exception}')
return abort(500)
if not entry: return abort(404)

View File

@ -15,7 +15,7 @@ def require_account_creation(function):
if User.query.count() == 0:
flash('Please register a user account.', 'alert')
return redirect(url_for('admin._register'))
except SQLAlchemyError as exception:
except (SQLAlchemyError, ConnectionError) as exception:
write('system.log', f'Database error when checking for existing accounts: {exception}')
return abort(500)
return function(*args, **kwargs)

View File

@ -78,7 +78,7 @@ def check_dataset_exists(function):
@wraps(function)
def wrapper(*args, **kwargs):
try: datasets = Dataset.query.all()
except SQLAlchemyError as exception:
except (SQLAlchemyError, ConnectionError) as exception:
write('system.log', f'Database error when checking existing datasets: {exception}')
return abort(500)
if not datasets:

View File

@ -9,24 +9,6 @@ from wtforms.validators import ValidationError
import json
from sqlalchemy.ext import mutable
class JsonEncodedDict(db.TypeDecorator):
"""Enables JSON storage by encoding and decoding on the fly."""
impl = db.Text
def process_bind_param(self, value, dialect):
if value is None:
return '{}'
else:
return json.dumps(value)
def process_result_value(self, value, dialect):
if value is None:
return {}
else:
return json.loads(value)
mutable.MutableDict.associate_with(JsonEncodedDict)
def value(min:int=0, max:int=None):
if not max:
message = f'Value must be greater than {min}.'
@ -50,7 +32,7 @@ def get_time_options():
def get_dataset_choices():
from ..models import Dataset
try: datasets = Dataset.query.all()
except SQLAlchemyError as exception:
except (SQLAlchemyError, ConnectionError) as exception:
write('system.log', f'Database error when fetching dataset lists: {exception}')
return []
dataset_choices = []

View File

@ -133,7 +133,7 @@ def redirect_if_started(function):
id = session.get('id')
try:
if request.method == 'GET' and id and Entry.query.filter_by(id=id).first(): return redirect(url_for('quiz._quiz'))
except SQLAlchemyError as exception:
except (SQLAlchemyError, ConnectionError) as exception:
write('system.log', f'Database error when checking if test has been started: {exception}')
return abort(500)
return function(*args, **kwargs)

View File

@ -38,7 +38,7 @@ def _view_console(id:str=None):
dataset = Dataset.query.filter_by(id=id).first()
datasets = Dataset.query.count()
users = User.query.all()
except SQLAlchemyError as exception:
except (SQLAlchemyError, ConnectionError) as exception:
write('system.log', f'Database error when processing request \'{request.url}\': {exception}')
return abort(500)
if not dataset:

View File

@ -22,6 +22,7 @@ PyMySQL==1.0.2
python-dotenv==0.20.0
six==1.16.0
SQLAlchemy==1.4.40
sqlalchemy-json==0.5.0
SQLAlchemy-Utils==0.38.3
visitor==0.1.3
Werkzeug==2.2.2

View File

@ -9,8 +9,7 @@ from getpass import getpass
with app.app_context():
try: users = User.query.all()
except SQLAlchemyError as exception:
sys.exit('Database error:', exception)
except (SQLAlchemyError, ConnectionError) as exception: sys.exit('Database error:', exception)
print('')
print('This interface will allow you to override the password for an administrator account.')
print('To exit this interface, press Ctrl + C.')