def get_user_agent(): """ Endpoint to get user agent information. :return: Dictionary with user agent information, or an empty dictionary with 404 HTTP code if access was denied. """ if not check_auth(): return {}, 404 response = { 'platform': request.user_agent.platform, 'browser': request.user_agent.browser, 'version': request.user_agent.version, 'message': 'OK', 'outdated': False, 'supportedPlatforms': list(Config.c.user_agent_platform.__dict__.keys()), 'supportedBrowsers': Config.c.user_agent_browser.__dict__, } if request.user_agent.platform not in Config.c.user_agent_platform.__dict__: response['outdated'] = True browser_found = False for (browser, version) in Config.c.user_agent_browser.__dict__.items(): if request.user_agent.browser == browser: browser_found = True if version_util.parse(request.user_agent.version) < version_util.parse(version): response['outdated'] = True break if not browser_found: response['outdated'] = True return response, 200
def handle_presentation_upload(): """ Route to handle presentation upload. Calls presentation upload, then adds training, then redirects to the 'view_training' page. :return: Redirection to the 'view_training' page, or an empty dictionary with 404 HTTP code if access was denied. """ if not check_auth(): return {}, 404 upload_presentation_response, upload_presentation_response_code = upload_presentation( ) if upload_presentation_response.get('message') != 'OK': return upload_presentation_response, upload_presentation_response_code presentation_file_id = upload_presentation_response['presentation_file_id'] logger.info('Uploaded file with presentation_file_id = {}.'.format( presentation_file_id)) add_training_response, add_training_response_code = add_training( presentation_file_id) if add_training_response.get('message') != 'OK': return add_training_response, add_training_response_code TrainingsDBManager().change_training_status_by_training_id( add_training_response['training_id'], TrainingStatus.IN_PROGRESS) return redirect( url_for( 'routes_trainings.view_training', training_id=add_training_response['training_id'], ))
def view_presentation_upload(): """ Route to view presentation upload. :return: Presentation upload page, or an empty dictionary with 404 HTTP code if access was denied. """ if not check_auth(): return {}, 404 return render_template('upload.html'), 200
def get_session_info(): """ Endpoint to return session information consists of username and full name. :return: Dictionary with username, full name, and 'OK' message, or or an empty dictionary with 404 HTTP code if access was denied. """ username = session.get('session_id') full_name = session.get('full_name') if not check_auth() or username is None: return {}, 404 return {'username': username, 'full_name': full_name, 'message': 'OK'}, 200
def get_pres_formats(): """ Endpoint to get user-allowed presentation formats. If user don't have format-parameter - allow only DEFAULT_EXTENSION ('pdf') :return: Dictionary with formats, or an empty dictionary with 404 HTTP code if access was denied. """ if not check_auth(): return {}, 404 formats = session.get('formats', (DEFAULT_EXTENSION,)) return { 'formats': formats, 'message': 'OK' }, 200
def view_all_trainings(): """ Route to show all trainings. :return: Page with all trainings, or an empty dictionary if access was denied. """ username = request.args.get('username', '') full_name = request.args.get('full_name', '') authorized = check_auth() is not None if not (check_admin() or (authorized and session.get('session_id') == username)): return {}, 404 return render_template('show_all_trainings.html', username=username, full_name=full_name, is_admin="true" if check_admin() else 'false'), 200
def get_presentation(presentation_file_id) -> (dict, int): """ Endpoint to get information about a presentation by its identifier. :param presentation_file_id: Presentation file identifier. :return: Dictionary with information about presentation and 'OK' message, or a dictionary with an explanation and 404 HTTP return code if a presentation record file was not found, or an empty dictionary with 404 HTTP return code if access was denied. #TODO check a presentation was uploaded by the current user? """ if not check_auth(): return {}, 404 presentation_file = PresentationFilesDBManager().get_presentation_file( file_id=presentation_file_id) if presentation_file is None: return { 'message': 'No presentation file with file_id = {}.'.format( presentation_file_id) }, 404 return get_presentation_information(presentation_file), 200
def add_training(presentation_file_id) -> (dict, int): """ Endpoint to add a training based on the presentation file with the given identifier. :param presentation_file_id: Presentation file identifier. :return: Dictionary with training identifier and 'OK' message, or a dictionary with an explanation and 404 HTTP return code if a task attempt or a task was not found, or an empty dictionary with 404 HTTP return code if access was denied. #TODO check a file was uploaded by the current user??? """ if not check_auth(): return {}, 404 username = session.get('session_id') full_name = session.get('full_name') task_attempt_id = session.get('task_attempt_id') task_attempt_db = TaskAttemptsDBManager().get_task_attempt(task_attempt_id) if task_attempt_db is None: return { 'message': 'No task attempt with task_attempt_id = {}.'.format( task_attempt_id) }, 404 task_id = session.get('task_id') task_db = TasksDBManager().get_task(task_id) if task_db is None: return {'message': 'No task with task_id = {}.'.format(task_id)}, 404 criteria_pack_id = task_db.criteria_pack_id feedback_evaluator_id = session.get('feedback_evaluator_id') training_id = TrainingsDBManager().add_training( task_attempt_id=task_attempt_id, username=username, full_name=full_name, presentation_file_id=presentation_file_id, criteria_pack_id=criteria_pack_id, feedback_evaluator_id=feedback_evaluator_id, ).pk TaskAttemptsDBManager().add_training(task_attempt_id, training_id) return {'training_id': str(training_id), 'message': 'OK'}, 200
def get_count_page() -> (dict, int): username = request.args.get('username', None) full_name = request.args.get('full_name', None) countItems = request.args.get('count') if not countItems: countItems = 10 else: countItems = int(countItems) authorized = check_auth() is not None if not (check_admin() or (authorized and session.get('session_id') == username)): return {}, 404 count = TrainingsDBManager().get_count_page( remove_blank_and_none({ 'username': username, 'full_name': full_name }), countItems) result = {"count": count} return result, 200
def get_all_trainings() -> (dict, int): """ Endpoint to get information about all trainings. Can be optionally filtered by username or full name. :return: Dictionary with information about all trainings and 'OK' message, or an empty dictionary with 404 HTTP code if access was denied. """ username = request.args.get('username', None) full_name = request.args.get('full_name', None) numberPage = request.args.get('page') if not numberPage: numberPage = 0 else: numberPage = int(numberPage) countItems = request.args.get('count') if not countItems: countItems = 10 else: countItems = int(countItems) print(numberPage, countItems) authorized = check_auth() is not None if not (check_admin() or (authorized and session.get('session_id') == username)): return {}, 404 trainings = TrainingsDBManager().get_trainings_filtered( remove_blank_and_none({ 'username': username, 'full_name': full_name }), numberPage, countItems) trainings_json = {'trainings': {}} for i, current_training in enumerate(trainings): trainings_json['trainings'][str( current_training.pk)] = get_training_information(current_training) trainings_json['message'] = 'OK' return trainings_json, 200
def upload_presentation() -> (dict, int): """ Endpoint to upload a presentation. :return: Dictionary with presentation file and preview identifiers and 'OK' message, or a dictionary with an explanation and 404 HTTP return code if uploaded file is not a pdf or too large, or an empty dictionary with 404 HTTP return code if access was denied. """ if not check_auth(): return {}, 404 if 'presentation' not in request.files: return { 'message': 'request.files[\'presentation\'] is not filled.' }, 404 if request.content_length > float( Config.c.constants.presentation_file_max_size_in_megabytes ) * BYTES_PER_MEGABYTE: return { 'message': 'Presentation file should not exceed {}MB.'.format( Config.c.constants.presentation_file_max_size_in_megabytes) }, 404 presentation_file = request.files['presentation'] # check extension and mimetype of file extension = presentation_file.filename.rsplit('.', 1)[-1].lower() passed, filemime = check_file_mime(presentation_file, extension) if not passed: msg = 'Presentation file has not allowed extension: {} (mimetype: {}).'.format( extension, filemime) logger.warning( f"{msg} Presentation name: {presentation_file.filename}. task_id={session.get('task_id')} criteria_pack_id={session.get('criteria_pack_id')} username={session.get('session_id')} full_name={session.get('full_name')}" ) return {'message': msg}, 200 nonconverted_file_id = None if is_convertible(extension): # change extension for new file original_name = presentation_file.filename converted_name = 'pdf'.join( presentation_file.filename.rsplit(extension, 1)) # convert to pdf converted_pdf_file = convert_to_pdf(presentation_file) if not converted_pdf_file: msg = f"Cannot convert uploaded presentation file {original_name}." logger.warning( f"{msg} Presentation name: {presentation_file.filename}. task_id={session['task_id']} task_id={session['criteria_pack_id']} username={session.get('session_id')} full_name={session.get('full_name')}" ) return {'message': msg}, 200 # swap converted and nonconverted files for further work presentation_file, non_converted_file = converted_pdf_file, presentation_file presentation_file.filename = converted_name # save nonconverted file with original_name nonconverted_file_id = DBManager().add_file(non_converted_file, original_name) presentation_file_id = DBManager().add_file(presentation_file, presentation_file.filename) presentation_file_preview = get_presentation_file_preview( DBManager().get_file(presentation_file_id)) presentation_file_preview_id = DBManager().read_and_add_file( presentation_file_preview.name, presentation_file_preview.name, ) presentation_file_preview.close() PresentationFilesDBManager().add_presentation_file( presentation_file_id, presentation_file.filename, presentation_file_preview_id, extension, nonconverted_file_id) return { 'presentation_file_id': str(presentation_file_id), 'presentation_file_preview_id': str(presentation_file_preview_id), 'message': 'OK', }, 200
def view_training_greeting(): """ Route to view training greeting page. It shows information about the current task. :return: Training greeting page, or a dictionary with an explanation and 404 HTTP return code if task was not found, or an empty dictionary with 404 HTTP return code if access was denied. """ user_session = check_auth() if not user_session: return {}, 404 username = session.get('session_id') task_id = session.get('task_id') task_db = TasksDBManager().get_task(task_id) if task_db is None: return {'message': 'No task with id {}.'.format(task_id)}, 404 task_description = task_db.task_description required_points = task_db.required_points attempt_count = task_db.attempt_count current_task_attempt = TaskAttemptsDBManager().get_current_task_attempt(username, task_id) if current_task_attempt is not None: training_number = len(current_task_attempt.training_scores) + 1 else: training_number = 1 if current_task_attempt is None or training_number > attempt_count: current_task_attempt = TaskAttemptsDBManager().add_task_attempt( username, task_id, user_session.tasks.get(task_id, {}).get('params_for_passback', ''), attempt_count, ) training_number = 1 task_attempt_count = TaskAttemptsDBManager().get_attempts_count(username, task_id) current_points_sum = \ sum([score if score is not None else 0 for score in current_task_attempt.training_scores.values()]) session['task_attempt_id'] = str(current_task_attempt.pk) criteria_pack_id = session.get('criteria_pack_id') criteria_pack = CriteriaPackFactory().get_criteria_pack(criteria_pack_id) criteria_pack_id = criteria_pack.name maximal_points = attempt_count * 1 criteria_pack_description = criteria_pack.get_criteria_pack_weights_description( CriterionPackDBManager().get_criterion_pack_by_name(criteria_pack_id).criterion_weights, ) # immediately create training if task has presentation presentation_id, training_id = (str(task_db.presentation_id), add_training(str(task_db.presentation_id))[0].get('training_id')) if task_db.presentation_id else (None, None) return render_template( 'training_greeting.html', task_id=task_id, task_description=task_description, current_points_sum='{:.2f}'.format(current_points_sum), required_points=required_points, maximal_points=maximal_points, attempt_number=task_attempt_count, training_number=training_number, attempt_count=attempt_count, criteria_pack_id=criteria_pack_id, criteria_pack_description=criteria_pack_description.replace('\n', '\\n').replace('\'', ''), training_id=training_id, presentation_id=presentation_id )