viveksantayana
350c67ab10
Moved most of app definitions out of guard function to use wsgi Updated configuration files and referencing of .env values. Local version needs dotenv or exporting of env variables. Dockerised version works fine without load_dotenv. Ready to test now!
122 lines
5.5 KiB
Python
122 lines
5.5 KiB
Python
import secrets
|
|
from datetime import datetime
|
|
from uuid import uuid4
|
|
from flask import flash, jsonify
|
|
import secrets
|
|
import os
|
|
from json import dump, loads
|
|
|
|
from common.security import encrypt
|
|
|
|
class Test:
|
|
|
|
def __init__(self, _id=None, start_date=None, expiry_date=None, time_limit=None, creator=None, dataset=None):
|
|
self._id = _id
|
|
self.start_date = start_date
|
|
self.expiry_date = expiry_date
|
|
self.time_limit = None if time_limit == 'none' or time_limit == '' or time_limit == None else int(time_limit)
|
|
self.creator = creator
|
|
self.dataset = dataset
|
|
|
|
def create(self):
|
|
from main import app, db
|
|
test = {
|
|
'_id': self._id,
|
|
'date_created': datetime.today(),
|
|
'start_date': self.start_date,
|
|
'expiry_date': self.expiry_date,
|
|
'time_limit': self.time_limit,
|
|
'creator': encrypt(self.creator),
|
|
'test_code': secrets.token_hex(6).upper(),
|
|
'dataset': self.dataset
|
|
}
|
|
if db.tests.insert_one(test):
|
|
dataset_file_path = os.path.join(app.config["DATA_FILE_DIRECTORY"],self.dataset)
|
|
with open(dataset_file_path, 'r') as dataset_file:
|
|
data = loads(dataset_file.read())
|
|
data['meta']['tests'].append(self._id)
|
|
with open(dataset_file_path, 'w') as dataset_file:
|
|
dump(data, dataset_file, indent=2)
|
|
flash(f'Created a new exam with Exam Code <strong>{self.render_test_code(test["test_code"])}</strong>.', 'success')
|
|
return jsonify({'success': test}), 200
|
|
return jsonify({'error': f'Could not create exam. An error occurred.'}), 400
|
|
|
|
def add_time_adjustment(self, time_adjustment):
|
|
from main import db
|
|
user_code = secrets.token_hex(3).upper()
|
|
adjustment = {
|
|
user_code: time_adjustment
|
|
}
|
|
if db.tests.find_one_and_update({'_id': self._id}, {'$set': {'time_adjustments': adjustment}},upsert=False):
|
|
flash(f'Time adjustment for {time_adjustment} minutes has been added. This can be enabled using the user code {user_code}.')
|
|
return jsonify({'success': adjustment})
|
|
return jsonify({'error': 'Failed to add the time adjustment. An error occurred.'}), 400
|
|
|
|
def remove_time_adjustment(self, user_code):
|
|
from main import db
|
|
if db.tests.find_one_and_update({'_id': self._id}, {'$unset': {f'time_adjustments.{user_code}': {}}}):
|
|
message = 'Time adjustment has been deleted.'
|
|
flash(message, 'success')
|
|
return jsonify({'success': message})
|
|
return jsonify({'error': 'Failed to delete the time adjustment. An error occurred.'}), 400
|
|
|
|
def render_test_code(self, test_code):
|
|
return '—'.join([test_code[:4], test_code[4:8], test_code[8:]])
|
|
|
|
def parse_test_code(self, test_code):
|
|
return test_code.replace('—', '')
|
|
|
|
def delete(self):
|
|
from main import app, db
|
|
test = db.tests.find_one({'_id': self._id})
|
|
if 'entries' in test:
|
|
if test['entries']:
|
|
return jsonify({'error': 'Cannot delete an exam that has entries submitted to it.'}), 400
|
|
if self.dataset is None:
|
|
self.dataset = db.tests.find_one({'_id': self._id})['dataset']
|
|
if db.tests.delete_one({'_id': self._id}):
|
|
dataset_file_path = os.path.join(app.config["DATA_FILE_DIRECTORY"],self.dataset)
|
|
with open(dataset_file_path, 'r') as dataset_file:
|
|
data = loads(dataset_file.read())
|
|
data['meta']['tests'].remove(self._id)
|
|
with open(dataset_file_path, 'w') as dataset_file:
|
|
dump(data, dataset_file, indent=2)
|
|
message = 'Deleted exam.'
|
|
flash(message, 'alert')
|
|
return jsonify({'success': message}), 200
|
|
return jsonify({'error': f'Could not create exam. An error occurred.'}), 400
|
|
|
|
def update(self):
|
|
from main import db
|
|
test = {}
|
|
updated = []
|
|
if not self.start_date == '' and self.start_date is not None:
|
|
test['start_date'] = self.start_date
|
|
updated.append('start date')
|
|
if not self.expiry_date == '' and self.expiry_date is not None:
|
|
test['expiry_date'] = self.expiry_date
|
|
updated.append('expiry date')
|
|
if not self.time_limit == '' and self.time_limit is not None:
|
|
test['time_limit'] = int(self.time_limit)
|
|
updated.append('time limit')
|
|
output = ''
|
|
if len(updated) == 0:
|
|
flash(f'There were no changes requested for your account.', 'alert'), 200
|
|
return jsonify({'success': 'There were no changes requested for your account.'}), 200
|
|
elif len(updated) == 1:
|
|
output = updated[0]
|
|
elif len(updated) == 2:
|
|
output = ' and '.join(updated)
|
|
elif len(updated) > 2:
|
|
output = updated[0]
|
|
for index in range(1,len(updated)):
|
|
if index < len(updated) - 2:
|
|
output = ', '.join([output, updated[index]])
|
|
elif index == len(updated) - 2:
|
|
output = ', and '.join([output, updated[index]])
|
|
else:
|
|
output = ''.join([output, updated[index]])
|
|
db.tests.find_one_and_update({'_id': self._id}, {'$set': test})
|
|
_output = f'The {output} of the test {"has" if len(updated) == 1 else "have"} been updated.'
|
|
flash(_output)
|
|
return jsonify({'success': _output}), 200 |