def complete_upload_for_token(cls, upload_token_id): kaltura_user_id = KalturaCore.user_id() if current_app.config.get('KALTURA_USE_GLOBAL_UNIQUE_IDENTIFIER', False) and current_user and current_user.global_unique_identifier: kaltura_user_id = current_user.global_unique_identifier kaltura_media = KalturaMedia.query \ .filter_by( upload_token_id=upload_token_id, user_id=current_user.id, entry_id=None ) \ .first() if not kaltura_media: abort(400, title="File Not Uploaded", message="The upload token does not exist or is already used. Please contact support for assistance.") with KalturaSession.generate_api_session(kaltura_user_id) as ks: # fetch upload, and update kaltura_media filename upload_token = UploadToken.get_upload_token(ks, upload_token_id) kaltura_media.file_name = upload_token.get('fileName') # create the media entry and associate it with the completed upload entry = Media.generate_media_entry(ks, upload_token_id, kaltura_media.media_type) kaltura_media.entry_id = entry.get('id') kaltura_media.download_url = entry.get('downloadUrl') # delete the upload session KalturaSession._api_end(kaltura_media.upload_ks) db.session.commit() return kaltura_media
def check_valid_pairing_algorithm(pairing_algorithm): pairing_algorithms = [ PairingAlgorithm.adaptive.value, PairingAlgorithm.random.value ] if pairing_algorithm not in pairing_algorithms: abort(400, title="Assignment Not Saved", message="'"+pairing_algorithm+"' is not a valid answer pairing algorithm. Please select one of the pairing algorithm options listed.")
def post(self, user_uuid): user = User.get_by_uuid_or_404(user_uuid) # anyone who passes checking below should be an instructor or admin require( EDIT, user, title="Notifications Not Updated", message= "Sorry, your system role does not allow you to update notification settings for this user." ) if not user.email: abort( 400, title="Notifications Not Updated", message= "Sorry, you cannot update notification settings since this user does not have an email address in ComPAIR." ) params = update_notification_settings_parser.parse_args() email_notification_method = params.get("email_notification_method") check_valid_email_notification_method(email_notification_method) user.email_notification_method = EmailNotificationMethod( email_notification_method) db.session.commit() on_user_notifications_update.send( self, event_name=on_user_notifications_update.name, user=current_user) return marshal(user, dataformat.get_user(is_user_access_restricted(user)))
def delete(self, course_uuid, assignment_uuid, answer_uuid): course = Course.get_active_by_uuid_or_404(course_uuid) assignment = Assignment.get_active_by_uuid_or_404(assignment_uuid) answer = Answer.get_active_by_uuid_or_404(answer_uuid) require(DELETE, answer, title="Answer Not Deleted", message="Sorry, your role in this course does not allow you to delete this answer.") if current_app.config.get('DEMO_INSTALLATION', False): from data.fixtures import DemoDataFixture if assignment.id in DemoDataFixture.DEFAULT_ASSIGNMENT_IDS and answer.user_id in DemoDataFixture.DEFAULT_STUDENT_IDS: abort(400, title="Answer Not Deleted", message="Sorry, you cannot delete the default student demo answers.") answer.active = False db.session.commit() # update course & assignment grade for user if answer was fully submitted if not answer.draft: if answer.user: assignment.calculate_grade(answer.user) course.calculate_grade(answer.user) elif answer.group: assignment.calculate_group_grade(answer.group) course.calculate_group_grade(answer.group) on_answer_delete.send( self, event_name=on_answer_delete.name, user=current_user, course_id=course.id, answer=answer, data={'assignment_id': assignment.id, 'answer_id': answer.id}) return {'id': answer.uuid}
def post(self): params = new_consumer_parser.parse_args() consumer = LTIConsumer() require(CREATE, consumer, title="Consumer Not Saved", message="Sorry, your system role does not allow you to save LTI consumers.") consumer.oauth_consumer_key = params.get("oauth_consumer_key") consumer.oauth_consumer_secret = params.get("oauth_consumer_secret") consumer.global_unique_identifier_param = params.get("global_unique_identifier_param") consumer.student_number_param = params.get("student_number_param") try: db.session.add(consumer) db.session.commit() on_consumer_create.send( self, event_name=on_consumer_create.name, user=current_user, consumer=consumer, data={'consumer': marshal(consumer, dataformat.get_lti_consumer())} ) except exc.IntegrityError: db.session.rollback() abort(409, title="Consumer Not Saved", message="An LTI consumer with the same consumer key already exists. Please double-check the consumer key and try saving again.") return marshal(consumer, dataformat.get_lti_consumer(include_sensitive=True))
def post(self, consumer_uuid): consumer = LTIConsumer.get_by_uuid_or_404(consumer_uuid) require(EDIT, consumer, title="Consumer Not Saved", message="Sorry, your system role does not allow you to save LTI consumers.") params = existing_consumer_parser.parse_args() # make sure the course id in the url and the course id in the params match if params['id'] != consumer_uuid: abort(400, title="Consumer Not Saved", message="The LTI consumer ID does not match the URL, which is required in order to save the LTI consumer.") consumer.oauth_consumer_key = params.get("oauth_consumer_key") consumer.oauth_consumer_secret = params.get("oauth_consumer_secret") consumer.global_unique_identifier_param = params.get("global_unique_identifier_param") consumer.student_number_param = params.get("student_number_param") consumer.active = params.get("active") try: db.session.commit() on_consumer_update.send( self, event_name=on_consumer_update.name, user=current_user, consumer=consumer ) except exc.IntegrityError: db.session.rollback() abort(409, title="Consumer Not Saved", message="An LTI consumer with the same consumer key already exists. Please double-check the consumer key and try saving again.") return marshal(consumer, dataformat.get_lti_consumer(include_sensitive=True))
def complete_upload_for_token(cls, upload_token_id): kaltura_media = KalturaMedia.query \ .filter_by( upload_token_id=upload_token_id, user_id=current_user.id, entry_id=None ) \ .first() if not kaltura_media: abort( 400, title="File Not Uploaded", message= "The upload token does not exist or is already used. Please contact support for assistance." ) with KalturaSession.generate_api_session() as ks: # fetch upload, and update kaltura_media filename upload_token = UploadToken.get_upload_token(ks, upload_token_id) kaltura_media.file_name = upload_token.get('fileName') # create the media entry and associate it with the completed upload entry = Media.generate_media_entry(ks, upload_token_id, kaltura_media.media_type) kaltura_media.entry_id = entry.get('id') kaltura_media.download_url = entry.get('downloadUrl') # delete the upload session KalturaSession._api_end(kaltura_media.upload_ks) db.session.commit() return kaltura_media
def delete(self, course_uuid, assignment_uuid): course = Course.get_active_by_uuid_or_404(course_uuid) assignment = Assignment.get_active_by_uuid_or_404(assignment_uuid) require(DELETE, assignment, title="Assignment Not Deleted", message="Sorry, your role in this course does not allow you to delete assignments.") if current_app.config.get('DEMO_INSTALLATION', False): from data.fixtures import DemoDataFixture if assignment.id in DemoDataFixture.DEFAULT_ASSIGNMENT_IDS: abort(400, title="Assignment Not Deleted", message="Sorry, you cannot remove the default demo assignments.") formatted_assignment = marshal(assignment, dataformat.get_assignment(False)) # delete file when assignment is deleted assignment.active = False assignment.clear_lti_links() db.session.commit() # update course grades course.calculate_grades() on_assignment_delete.send( self, event_name=on_assignment_delete.name, user=current_user, course_id=course.id, assignment=assignment, data=formatted_assignment) return {'id': assignment.uuid}
def post(self): if not CaliperSensor.enabled(): # this should silently fail abort(404) raw_params = request.get_json(force=True) params = {} course_uuid = raw_params.get('course_id') course = _get_valid_course(course_uuid) # add required params for param in ['type', 'action', 'object']: if not raw_params.get(param): abort(400) params[param] = raw_params.get(param) # add optional params for param in [ 'eventTime', 'target', 'generated', 'referrer', 'extensions', 'profile' ]: if raw_params.get(param): params[param] = raw_params.get(param) event = CaliperEvent.generate_from_params(current_user, params, course=course) CaliperSensor.emit(event) return {'success': True}
def delete(self, course_uuid): course = Course.get_active_by_uuid_or_404(course_uuid) require( DELETE, course, title="Course Not Deleted", message= "Sorry, your role in this course does not allow you to delete it.") if current_app.config.get('DEMO_INSTALLATION', False): from data.fixtures import DemoDataFixture if course.id == DemoDataFixture.DEFAULT_COURSE_ID: abort( 400, title="Course Not Deleted", message="Sorry, you cannot remove the default demo course." ) course.active = False course.clear_lti_links() db.session.commit() on_course_delete.send(self, event_name=on_course_delete.name, user=current_user, course=course, data={'id': course.id}) return {'id': course.uuid}
def post(self, consumer_uuid): consumer = LTIConsumer.get_by_uuid_or_404(consumer_uuid) require(EDIT, consumer, title="Consumer Not Saved", message="Sorry, your system role does not allow you to save LTI consumers.") params = existing_consumer_parser.parse_args() # make sure the course id in the url and the course id in the params match if params['id'] != consumer_uuid: abort(400, title="Consumer Not Saved", message="The LTI consumer ID does not match the URL, which is required in order to save the LTI consumer.") consumer.oauth_consumer_key = params.get("oauth_consumer_key") consumer.oauth_consumer_secret = params.get("oauth_consumer_secret") consumer.global_unique_identifier_param = params.get("global_unique_identifier_param") consumer.student_number_param = params.get("student_number_param") consumer.custom_param_regex_sanitizer = params.get("custom_param_regex_sanitizer") consumer.active = params.get("active") try: db.session.commit() on_consumer_update.send( self, event_name=on_consumer_update.name, user=current_user, consumer=consumer ) except exc.IntegrityError: db.session.rollback() abort(409, title="Consumer Not Saved", message="An LTI consumer with the same consumer key already exists. Please double-check the consumer key and try saving again.") return marshal(consumer, dataformat.get_lti_consumer(include_sensitive=True))
def post(self, course_uuid): """ link current session's lti context with a course """ course = Course.get_active_by_uuid_or_404(course_uuid) require(EDIT, course, title="Course Not Linked", message="Sorry, you do not have permission to link this course since you are not enrolled as an instructor in the course.") if not sess.get('LTI'): abort(400, title="Course Not Linked", message="Sorry, your LTI session has expired. Please log in via LTI and try linking again.") if not sess.get('lti_context'): abort(400, title="Course Not Linked", message="Sorry, your LTI link settings have no course context. Please edit your LTI link settings and try linking again.") lti_context = LTIContext.query.get_or_404(sess.get('lti_context')) lti_context.compair_course_id = course.id db.session.commit() # automatically fetch membership if enabled for context if lti_context.membership_enabled: update_lti_course_membership.delay(course.id) on_lti_course_link_create.send( self, event_name=on_lti_course_link_create.name, user=current_user, data={ 'course_id': course.id, 'lti_context_id': lti_context.id }) return { 'success': True }
def _api_start(cls, privileges=None): url = KalturaCore.base_url() + "/service/session/action/start" params = { 'partnerId': KalturaCore.partner_id(), 'userId': KalturaCore.user_id(), 'secret': KalturaCore.secret(), 'type': KalturaCore.SESSION_TYPE_USER, # safer to go with user 'format': 1, # json return value } if privileges: params['privileges'] = privileges result = requests.get(url, params=params, verify=KalturaCore.enforce_ssl()) if result.status_code == 200: return result.json() else: current_app.logger.error(result) abort( 400, title="File Not Uploaded", message= "There was a problem with the Kaltura server. Please try again later." )
def post(self, user_uuid): user = User.get_by_uuid_or_404(user_uuid) # anyone who passes checking below should be an admin or current user if not allow(MANAGE, user) and not user.id == current_user.id and not \ (allow(EDIT, user) and current_app.config.get('EXPOSE_EMAIL_TO_INSTRUCTOR', False)): abort( 403, title="Notifications Not Updated", message= "Sorry, your system role does not allow you to update notification settings for this user." ) if not user.email: abort( 400, title="Notifications Not Updated", message= "Sorry, you cannot update notification settings since this user does not have an email address in ComPAIR." ) params = update_notification_settings_parser.parse_args() email_notification_method = params.get("email_notification_method") check_valid_email_notification_method(email_notification_method) user.email_notification_method = EmailNotificationMethod( email_notification_method) db.session.commit() on_user_notifications_update.send( self, event_name=on_user_notifications_update.name, user=current_user) return marshal_user_data(user)
def post(self): params = new_consumer_parser.parse_args() consumer = LTIConsumer() require(CREATE, consumer, title="Consumer Not Saved", message="Sorry, your system role does not allow you to save LTI consumers.") consumer.oauth_consumer_key = params.get("oauth_consumer_key") consumer.oauth_consumer_secret = params.get("oauth_consumer_secret") consumer.global_unique_identifier_param = params.get("global_unique_identifier_param") consumer.student_number_param = params.get("student_number_param") consumer.custom_param_regex_sanitizer = params.get("custom_param_regex_sanitizer") try: db.session.add(consumer) db.session.commit() on_consumer_create.send( self, event_name=on_consumer_create.name, user=current_user, consumer=consumer, data={'consumer': marshal(consumer, dataformat.get_lti_consumer())} ) except exc.IntegrityError: db.session.rollback() abort(409, title="Consumer Not Saved", message="An LTI consumer with the same consumer key already exists. Please double-check the consumer key and try saving again.") return marshal(consumer, dataformat.get_lti_consumer(include_sensitive=True))
def post(self): if not XAPI.enabled(): # this should silently fail abort(404) raw_params = request.get_json(force=True) params = {} course_uuid = raw_params.get('course_id') course = _get_valid_course(course_uuid) # add required params for param in ['verb', 'object']: if not raw_params.get(param): abort(400) params[param] = raw_params.get(param) # add optional params for param in ['context', 'result', 'timestamp']: if raw_params.get(param): params[param] = raw_params.get(param) statement = XAPIStatement.generate_from_params(current_user, params, course=course) XAPI.emit(statement) return {'success': True}
def check_valid_email_notification_method(email_notification_method): email_notification_methods = [ EmailNotificationMethod.enable.value, EmailNotificationMethod.disable.value ] if email_notification_method not in email_notification_methods: abort(400, title="User Not Saved", message="Please try again with an email notification checked or unchecked.")
def post(self, upload_token_id): if not KalturaAPI.enabled(): abort(400, title="File Not Uploaded", message="Please use a valid upload method to attach files. You are not able to upload with this method based on the current settings.") kaltura_media = KalturaAPI.complete_upload_for_token(upload_token_id) on_save_kaltura_file.send( self, event_name=on_save_kaltura_file.name, user=current_user, data={'upload_token_id': upload_token_id}) try: db_file = File( user_id=current_user.id, name='', alias=kaltura_media.file_name, kaltura_media=kaltura_media ) db.session.add(db_file) db.session.commit() # use uuid generated by file model for name name = db_file.uuid + '.' + kaltura_media.extension # update file record with name db_file.name = name db.session.commit() except Exception as e: db.session.rollback() raise e return {'file': marshal(db_file, dataformat.get_file())}
def delete(self): if not current_app.config.get( 'IMPERSONATION_ENABLED', False) or not impersonation.is_impersonating(): abort(404, title="Cannot stop impersonation", message="Sorry, you can't perform that action") original_user_id = impersonation.get_impersonation_original_user_id() impersonate_as_user_id = impersonation.get_impersonation_act_as_user_id( ) original_user = User.query.get(original_user_id) impersonate_as_user = User.query.get(impersonate_as_user_id) if original_user is None or impersonate_as_user is None: abort(404, title="Cannot stop impersonation", \ message="Cannot find corresponding information to stop impersonation") on_impersonation_stopped.send( self, event_name=on_impersonation_stopped.name, user=original_user, data={'impersonate_as': impersonate_as_user.id}) impersonation.end_impersonation() return {'success': True}
def get_direct_access_url(cls, entry_id, download_url, expiry=300): """ Generate a new Kaltura Session (KS) and return an URL for direct download of Kaltura media file. :param entry_id: the Kaltura entry ID of the file to download :param download_url: URL to download the file :param expiry: optional expiry time of the KS, in seconds. Default is 300 seconds. :return: a URL with KS attached for downloading the given Kaltura media file """ kaltura_user_id = KalturaCore.user_id() if current_app.config.get( 'KALTURA_USE_GLOBAL_UNIQUE_IDENTIFIER', False ) and current_user and current_user.global_unique_identifier: kaltura_user_id = current_user.global_unique_identifier url = download_url if not url: abort( 404, title="File Not Found", message= "The file is not available on Kaltura server yet. Please try again later." ) session = KalturaSession.generate_direct_media_access_ks( kaltura_user_id, entry_id, url, expiry) url = url + "/ks/" + quote_plus(session, '') return url
def delete(self, course_uuid, lti_context_uuid): """ unlink lti context from course """ course = Course.get_active_by_uuid_or_404(course_uuid) lti_context = LTIContext.get_by_uuid_or_404(lti_context_uuid) require(DELETE, lti_context, title="Course Not Unlinked", message="Sorry, your system role does not allow you to unlink LTI courses.") if lti_context.compair_course_id != course.id: abort(400, title="Course Not Unlinked", message="Sorry, The LTI context is already not linked to the course.") lti_context.compair_course_id = None db.session.commit() # automatically refresh membership if it was enabled for the removed context if lti_context.membership_enabled: update_lti_course_membership.delay(course.id) on_lti_course_unlink.send( self, event_name=on_lti_course_unlink.name, user=current_user, data={ 'course_id': course.id, 'lti_context_id': lti_context.id }) return { 'success': True }
def check_valid_system_role(system_role): system_roles = [ SystemRole.sys_admin.value, SystemRole.instructor.value, SystemRole.student.value ] if system_role not in system_roles: abort(400, title="User Not Saved", message="Please try again with a system role from the list of roles provided.")
def check_valid_system_role(system_role): system_roles = [ SystemRole.sys_admin.value, SystemRole.instructor.value, SystemRole.student.value ] if system_role not in system_roles: abort(400, title="Demo Account Not Saved", message="Please try again with a system role from the list of roles provided.")
def check_valid_pairing_algorithm(pairing_algorithm): pairing_algorithms = [ PairingAlgorithm.adaptive.value, PairingAlgorithm.random.value, PairingAlgorithm.adaptive_min_delta.value ] if pairing_algorithm not in pairing_algorithms: abort(400, title="Assignment Not Saved", message="'"+pairing_algorithm+"' is not a valid answer pairing algorithm. Please select one of the pairing algorithm options listed.")
def post(self): uploaded_file = request.files.get('file') if not uploaded_file: abort( 400, title="File Not Uploaded", message= "Sorry, no file was found to upload. Please try uploading again." ) elif not allowed_file( uploaded_file.filename, current_app.config['ATTACHMENT_ALLOWED_EXTENSIONS']): extensions = [ extension.upper() for extension in list( current_app.config['ATTACHMENT_ALLOWED_EXTENSIONS']) ] extensions.sort() extensions = ", ".join(extensions) abort( 400, title="File Not Uploaded", message= "Please try again with an approved file type, which includes: " + extensions + ".") on_save_file.send(self, event_name=on_save_file.name, user=current_user, data={'file': uploaded_file.filename}) try: db_file = File(user_id=current_user.id, name='', alias=uploaded_file.filename) db.session.add(db_file) db.session.commit() # use uuid generated by file model for name name = db_file.uuid + '.' + uploaded_file.filename.lower().rsplit( '.', 1)[1] # create new file with name full_path = os.path.join( current_app.config['ATTACHMENT_UPLOAD_FOLDER'], name) uploaded_file.save(full_path) current_app.logger.debug("Saved attachment {}/{}".format( current_app.config['ATTACHMENT_UPLOAD_FOLDER'], name)) # update file record with name db_file.name = name db.session.commit() except Exception as e: db.session.rollback() raise e return {'file': marshal(db_file, dataformat.get_file())}
def post(self): """ Create new course """ require( CREATE, Course, title="Course Not Saved", message= "Sorry, your role in the system does not allow you to save courses." ) params = new_course_parser.parse_args() new_course = Course(name=params.get("name"), year=params.get("year"), term=params.get("term"), sandbox=params.get("sandbox"), start_date=params.get('start_date'), end_date=params.get('end_date', None)) if new_course.start_date is not None: new_course.start_date = datetime.datetime.strptime( new_course.start_date, '%Y-%m-%dT%H:%M:%S.%fZ') if new_course.end_date is not None: new_course.end_date = datetime.datetime.strptime( new_course.end_date, '%Y-%m-%dT%H:%M:%S.%fZ') if new_course.start_date and new_course.end_date and new_course.start_date > new_course.end_date: abort(400, title="Course Not Saved", message="Course end time must be after course start time.") try: # create the course db.session.add(new_course) # also need to enrol the user as an instructor new_user_course = UserCourse(course=new_course, user_id=current_user.id, course_role=CourseRole.instructor) db.session.add(new_user_course) db.session.commit() except exc.SQLAlchemyError as e: db.session.rollback() current_app.logger.error("Failed to add new course. " + str(e)) raise on_course_create.send(self, event_name=on_course_create.name, user=current_user, course=new_course, data=marshal(new_course, dataformat.get_course())) return marshal(new_course, dataformat.get_course())
def post(self): """ Create new course """ require(CREATE, Course, title="Course Not Saved", message="Sorry, your role in the system does not allow you to save courses.") params = new_course_parser.parse_args() new_course = Course( name=params.get("name"), year=params.get("year"), term=params.get("term"), sandbox=params.get("sandbox"), start_date=params.get('start_date'), end_date=params.get('end_date', None) ) if new_course.start_date is not None: new_course.start_date = datetime.datetime.strptime( new_course.start_date, '%Y-%m-%dT%H:%M:%S.%fZ') if new_course.end_date is not None: new_course.end_date = datetime.datetime.strptime( new_course.end_date, '%Y-%m-%dT%H:%M:%S.%fZ') if new_course.start_date and new_course.end_date and new_course.start_date > new_course.end_date: abort(400, title="Course Not Saved", message="Course end time must be after course start time.") try: # create the course db.session.add(new_course) # also need to enrol the user as an instructor new_user_course = UserCourse( course=new_course, user_id=current_user.id, course_role=CourseRole.instructor ) db.session.add(new_user_course) db.session.commit() except exc.SQLAlchemyError as e: db.session.rollback() current_app.logger.error("Failed to add new course. " + str(e)) raise on_course_create.send( self, event_name=on_course_create.name, user=current_user, course=new_course, data=marshal(new_course, dataformat.get_course())) return marshal(new_course, dataformat.get_course())
def cas_logout(): if not current_app.config.get('CAS_LOGIN_ENABLED'): abort( 403, title="Log Out Failed", message= "Please try an alternate way of logging out. The CWL logout has been disabled by your system administrator." ) return redirect(get_cas_logout_url())
def saml_logout(): if not current_app.config.get('SAML_LOGIN_ENABLED'): abort( 403, title="Not Logged Out", message= "Please use a valid way to log out. You are not able to use CWL logout based on the current settings." ) return redirect(get_saml_logout_url(request))
def get_by_uuid_or_404(cls, model_uuid, joinedloads=[], title=None, message=None): query = cls.query # load relationships if needed for load_string in joinedloads: query.options(joinedload(load_string)) model = query.filter_by(uuid=model_uuid).one_or_none() if model is None: abort(404, title=title, message=message) return model
def post(self, course_uuid, assignment_uuid): course = Course.get_active_by_uuid_or_404(course_uuid) assignment = Assignment.get_active_by_uuid_or_404(assignment_uuid) require( CREATE, ComparisonExample(assignment=Assignment(course_id=course.id)), title="Comparison Example Not Saved", message= "Sorry, your role in this course does not allow you to save practice answers." ) new_comparison_example = ComparisonExample(assignment_id=assignment.id) params = new_comparison_example_parser.parse_args() answer1_uuid = params.get("answer1_id") answer2_uuid = params.get("answer2_id") if answer1_uuid: answer1 = Answer.get_active_by_uuid_or_404(answer1_uuid) answer1.practice = True new_comparison_example.answer1 = answer1 else: abort( 400, title="Comparison Example Not Saved", message= "Please add two answers with content to the practice answers and try again." ) if answer2_uuid: answer2 = Answer.get_active_by_uuid_or_404(answer2_uuid) answer2.practice = True new_comparison_example.answer2 = answer2 else: abort( 400, title="Comparison Example Not Saved", message= "Please add two answers with content to the practice answers and try again." ) on_comparison_example_create.send( self, event_name=on_comparison_example_create.name, user=current_user, course_id=course.id, data=marshal( new_comparison_example, dataformat.get_comparison_example(with_answers=False))) db.session.add(new_comparison_example) db.session.commit() return marshal(new_comparison_example, dataformat.get_comparison_example())
def post(self): if not XAPI.enabled(): # this should silently fail abort(404) params = statement_parser.parse_args() statement = XAPIStatement.generate_from_params(current_user, params) XAPI.send_statement(statement) return {'success': True}
def post(self): if not XAPI.enabled(): # this should silently fail abort(404) params = statement_parser.parse_args() statement = XAPIStatement.generate_from_params(current_user, params) XAPI.send_statement(statement) return { 'success': True }
def post(self, course_uuid, assignment_uuid, comparison_example_uuid): course = Course.get_active_by_uuid_or_404(course_uuid) assignment = Assignment.get_active_by_uuid_or_404(assignment_uuid) comparison_example = ComparisonExample.get_active_by_uuid_or_404( comparison_example_uuid) require( EDIT, comparison_example, title="Comparison Example Not Saved", message= "Sorry, your role in this course does not allow you to save practice answers." ) params = existing_comparison_example_parser.parse_args() answer1_uuid = params.get("answer1_id") answer2_uuid = params.get("answer2_id") if answer1_uuid: answer1 = Answer.get_active_by_uuid_or_404(answer1_uuid) answer1.practice = True comparison_example.answer1 = answer1 else: abort( 400, title="Comparison Example Not Saved", message= "Please add two answers with content to the practice answers and try again." ) if answer2_uuid: answer2 = Answer.get_active_by_uuid_or_404(answer2_uuid) answer2.practice = True comparison_example.answer2 = answer2 else: abort( 400, title="Comparison Example Not Saved", message= "Please add two answers with content to the practice answers and try again." ) model_changes = get_model_changes(comparison_example) db.session.add(comparison_example) db.session.commit() on_comparison_example_modified.send( self, event_name=on_comparison_example_modified.name, user=current_user, course_id=course.id, data=model_changes) return marshal(comparison_example, dataformat.get_comparison_example())
def post(self): if not CaliperSensor.enabled(): # this should silently fail abort(404) params = caliper_event_parser.parse_args() course_uuid = params.pop('course_id') course = _get_valid_course(course_uuid) event = CaliperEvent.generate_from_params(current_user, params, course=course) CaliperSensor.emit(event) return { 'success': True }
def post(self): if not XAPI.enabled(): # this should silently fail abort(404) params = xapi_statement_parser.parse_args() course_uuid = params.pop('course_id') course = _get_valid_course(course_uuid) statement = XAPIStatement.generate_from_params(current_user, params, course=course) XAPI.emit(statement) return { 'success': True }
def post(self, user_uuid): user = User.get_by_uuid_or_404(user_uuid) # anyone who passes checking below should be an instructor or admin require(EDIT, user, title="Password Not Saved", message="Sorry, your system role does not allow you to update passwords for this user.") if not user.uses_compair_login: abort(400, title="Password Not Saved", message="Sorry, you cannot update the password since this user does not use the ComPAIR account login method.") params = update_password_parser.parse_args() oldpassword = params.get('oldpassword') if current_user.id == user.id and not oldpassword: abort(400, title="Password Not Saved", message="Sorry, the old password is required. Please enter the old password and try saving again.") elif current_user.id == user.id and not user.verify_password(oldpassword): abort(400, title="Password Not Saved", message="Sorry, the old password is not correct. Please double-check the old password and try saving again.") elif len(params.get('newpassword')) < 4: abort(400, title="Password Not Saved", message="The new password must be at least 4 characters long.") user.password = params.get('newpassword') db.session.commit() on_user_password_update.send( self, event_name=on_user_password_update.name, user=current_user) return marshal_user_data(user)
def get_active_by_uuid_or_404(cls, model_uuid, joinedloads=[], title=None, message=None): query = cls.query # load relationships if needed for load_string in joinedloads: query.options(joinedload(load_string)) model = query.filter_by(uuid=model_uuid).one_or_none() if model is None or not model.active: abort(404, title=title, message=message) return model
def post(self, course_uuid): """ refresh the course membership if able """ course = Course.get_active_by_uuid_or_404(course_uuid) require(EDIT, course, title="Membership Not Updated", message="Sorry, your role in this course does not allow you to update membership.") if not course.lti_linked: abort(400, title="Membership Not Updated", message="Sorry, your LTI link settings have no course context. Please edit your LTI link settings and try linking again.") try: LTIMembership.update_membership_for_course(course) except MembershipNoValidContextsException as err: abort(400, title="Membership Not Updated", message="The LTI link does not support the membership extension. Please edit your LTI link settings or contact your system administrator and try again.") except MembershipNoResultsException as err: abort(400, title="Membership Not Updated", message="The membership service did not return any users. Please check your LTI course and try again.") except MembershipInvalidRequestException as err: abort(400, title="Membership Not Updated", message="The membership request was invalid. Please relaunch the LTI link and try again.") on_lti_course_membership_update.send( self, event_name=on_lti_course_membership_update.name, user=current_user, data={ 'course_id': course.id }) return { 'imported': True }
def get(self): if not KalturaAPI.enabled(): abort(400, title="File Not Uploaded", message="Please use a valid upload method to attach files. You are not able to upload with this method based on the current settings.") upload_url = KalturaAPI.generate_new_upload_token() on_get_kaltura_token.send( self, event_name=on_get_kaltura_token.name, user=current_user, data={'upload_url': upload_url}) return {'upload_url': upload_url}
def post(self, course_uuid): course = Course.get_active_by_uuid_or_404(course_uuid) require( EDIT, UserCourse(course_id=course.id), title="Group Not Saved", message= "Sorry, your role in this course does not allow you to save groups." ) params = user_list_parser.parse_args() if len(params.get('ids')) == 0: abort( 400, title="Group Not Saved", message= "Please select at least one user below and then try to apply the group again." ) user_courses = UserCourse.query \ .join(User, UserCourse.user_id == User.id) \ .filter(and_( UserCourse.course_id == course.id, User.uuid.in_(params.get('ids')), UserCourse.course_role != CourseRole.dropped )) \ .all() if len(params.get('ids')) != len(user_courses): abort( 400, title="Group Not Saved", message= "One or more users selected are not enrolled in the course yet." ) for user_course in user_courses: user_course.group_name = None db.session.commit() on_course_group_user_list_delete.send( current_app._get_current_object(), event_name=on_course_group_user_list_delete.name, user=current_user, course_id=course.id, data={'user_uuids': params.get('ids')}) return {'course_id': course.uuid}
def _api_get(cls, ks, entry_id): url = KalturaCore.base_url()+"/service/media/action/get" params = { 'entryId': entry_id, 'ks': ks, 'format': 1, # json return value } result = requests.get(url, params=params, verify=KalturaCore.enforce_ssl()) if result.status_code == 200: return result.json() else: current_app.logger.error(result) abort(400, title="File Not Accessible", message="There was a problem with the Kaltura server. Please try again later.")
def get(self): if not current_app.config.get('IMPERSONATION_ENABLED', False) or not impersonation.is_impersonating(): return {'impersonating' : False} original_user = impersonation.get_impersonation_original_user() impersonate_as_user = current_user if original_user is None or impersonate_as_user is None: # something went wrong... abort(503, title="Cannot check impersonation status", \ message="Sorry, cannot find information on impersonation status") # user is impersonating. treat as restrict_user when calling dataformat return { \ 'impersonating' : True, 'original_user' : marshal(original_user, dataformat.get_user(True)) }
def _api_update(cls, ks, entry_id, update_params={}): url = KalturaCore.base_url()+"/service/media/action/update" params = { 'entryId': entry_id, 'ks': ks, 'format': 1, # json return value 'mediaEntry[objectType]': "KalturaMediaEntry" } params.update(update_params) result = requests.get(url, params=params, verify=KalturaCore.enforce_ssl()) if result.status_code == 200: return result.json() else: current_app.logger.error(result) abort(400, title="File Not Updated", message="There was a problem with the Kaltura server. Please try again later.")
def _api_add_content(cls, ks, entry_id, upload_token_id): url = KalturaCore.base_url()+"/service/media/action/addContent" params = { 'entryId': entry_id, 'resource[objectType]': 'KalturaUploadedFileTokenResource', 'resource[token]': upload_token_id, 'ks': ks, 'format': 1, # json return value } result = requests.get(url, params=params, verify=KalturaCore.enforce_ssl()) if result.status_code == 200: return result.json() else: current_app.logger.error(result) abort(400, title="File Not Uploaded", message="There was a problem with the Kaltura server. Please try again later.")
def get(self, course_uuid): """ refresh the course membership if able """ course = Course.get_active_by_uuid_or_404(course_uuid) require(EDIT, course, title="Membership Status Unavailable", message="Sorry, your role in this course does not allow you to view LTI membership status.") if not course.lti_linked: abort(400, title="Membership Status Unavailable", message="The course is not linked to an LTI context yet. Launch an LTI link to link this course first, then check the status.") valid_membership_contexts = [ lti_context for lti_context in course.lti_contexts \ if lti_context.membership_enabled ] pending = 0 enabled = len(valid_membership_contexts) > 0 if enabled: lti_context_ids = [lti_context.id for lti_context in valid_membership_contexts] pending = LTIMembership.query \ .join(LTIUser) \ .filter(and_( LTIUser.compair_user_id == None, LTIMembership.lti_context_id.in_(lti_context_ids) )) \ .count() status = { 'enabled': enabled, 'pending': pending } on_lti_course_membership_status_get.send( self, event_name=on_lti_course_membership_status_get.name, user=current_user, data={ 'course_id': course.id }) return { 'status': status }
def post(self): uploaded_file = request.files.get('file') if not uploaded_file: abort(400, title="File Not Uploaded", message="Sorry, no file was found to upload. Please try uploading again.") elif not allowed_file(uploaded_file.filename, current_app.config['ATTACHMENT_ALLOWED_EXTENSIONS']): extensions = [extension.upper() for extension in list(current_app.config['ATTACHMENT_ALLOWED_EXTENSIONS'])] extensions.sort() extensions = ", ".join(extensions) abort(400, title="File Not Uploaded", message="Please try again with an approved file type, which includes: "+extensions+".") on_save_file.send( self, event_name=on_save_file.name, user=current_user, data={'file': uploaded_file.filename}) try: db_file = File( user_id=current_user.id, name='', alias=uploaded_file.filename ) db.session.add(db_file) db.session.commit() # use uuid generated by file model for name name = db_file.uuid + '.' + uploaded_file.filename.lower().rsplit('.', 1)[1] # create new file with name full_path = os.path.join(current_app.config['ATTACHMENT_UPLOAD_FOLDER'], name) uploaded_file.save(full_path) current_app.logger.debug("Saved attachment {}/{}".format(current_app.config['ATTACHMENT_UPLOAD_FOLDER'], name)) # update file record with name db_file.name = name db.session.commit() except Exception as e: db.session.rollback() raise e return {'file': marshal(db_file, dataformat.get_file())}
def get(self, course_uuid, assignment_uuid): course = Course.get_active_by_uuid_or_404(course_uuid) assignment = Assignment.get_active_by_uuid_or_404(assignment_uuid) require(READ, assignment, title="Assignment Unavailable", message="Assignments can be saved only by those enrolled in the course. Please double-check your enrollment in this course.") now = datetime.datetime.utcnow() if assignment.answer_start and not allow(MANAGE, assignment) and not (assignment.answer_start <= now): abort(403, title="Assignment Unavailable", message="This assignment is not yet open to students. Please check back after the start date the instructor has set.") restrict_user = not allow(MANAGE, assignment) on_assignment_get.send( self, event_name=on_assignment_get.name, user=current_user, course_id=course.id, data={'id': assignment.id}) return marshal(assignment, dataformat.get_assignment(restrict_user))
def delete(self): if not current_app.config.get('IMPERSONATION_ENABLED', False) or not impersonation.is_impersonating(): abort(404, title="Cannot stop impersonation", message="Sorry, you can't perform that action") original_user_id = impersonation.get_impersonation_original_user_id() impersonate_as_user_id = impersonation.get_impersonation_act_as_user_id() original_user = User.query.get(original_user_id) impersonate_as_user = User.query.get(impersonate_as_user_id) if original_user is None or impersonate_as_user is None: abort(404, title="Cannot stop impersonation", \ message="Cannot find corresponding information to stop impersonation") on_impersonation_stopped.send( self, event_name=on_impersonation_stopped.name, user=original_user, data={ 'impersonate_as': impersonate_as_user.id }) impersonation.end_impersonation() return {'success': True}
def delete(self, course_uuid, group_uuid): course = Course.get_active_by_uuid_or_404(course_uuid) group = Group.get_active_by_uuid_or_404(group_uuid) require(DELETE, group, title="Group Not Deleted", message="Sorry, your role in this course does not allow you to delete groups.") # check if group has submitted any answers group_answer_exists = Answer.query \ .filter_by( group_id=group.id, practice=False, active=True, draft=False ) \ .first() if group_answer_exists: abort(400, title="Group Not Deleted", message="Sorry, you cannot remove groups that have submitted answers.") group.active = False # remove members from the group user_courses = UserCourse.query \ .filter_by(group_id=group.id) \ .all() for user_course in user_courses: user_course.group_id = None db.session.commit() on_group_delete.send( current_app._get_current_object(), event_name=on_group_delete.name, user=current_user, course_id=course.id ) return {'id': group.uuid }
def _api_start(cls, kaltura_user_id, privileges=None, expiry=None): url = KalturaCore.base_url()+"/service/session/action/start" params = { 'partnerId': KalturaCore.partner_id(), 'userId': kaltura_user_id, 'secret': KalturaCore.secret(), 'type': KalturaCore.SESSION_TYPE_USER, # safer to go with user 'format': 1, # json return value } if privileges: params['privileges'] = privileges if expiry: params['expiry'] = expiry result = requests.get(url, params=params, verify=KalturaCore.enforce_ssl()) if result.status_code == 200: return result.json() else: current_app.logger.error(result) abort(400, title="File Not Uploaded", message="There was a problem with the Kaltura server. Please try again later.")
def get_direct_access_url(cls, entry_id, download_url, expiry=300): """ Generate a new Kaltura Session (KS) and return an URL for direct download of Kaltura media file. :param entry_id: the Kaltura entry ID of the file to download :param download_url: URL to download the file :param expiry: optional expiry time of the KS, in seconds. Default is 300 seconds. :return: a URL with KS attached for downloading the given Kaltura media file """ kaltura_user_id = KalturaCore.user_id() if current_app.config.get('KALTURA_USE_GLOBAL_UNIQUE_IDENTIFIER', False) and current_user and current_user.global_unique_identifier: kaltura_user_id = current_user.global_unique_identifier url = download_url if not url: abort(404, title="File Not Found", message="The file is not available on Kaltura server yet. Please try again later.") session = KalturaSession.generate_direct_media_access_ks(kaltura_user_id, entry_id, url, expiry) url = url + "/ks/" + quote_plus(session, '') return url