def test_course_shortname_get_multiple_found(self): # add a temp course with same shortname as another course = Course() course.shortname = 'anc1-all' course.version = 123456789 course.save() resp = self.perform_request('anc1-all', self.user_auth) self.assertRaises(MultipleObjectsReturned) self.assertEqual(300, resp.status_code)
def test_course_shortname_get_multiple_found(self): # add a temp course with same shortname as another course = Course() course.shortname = 'anc1-all' course.version = 123456789 course.save() resource_url = get_api_url('v2', 'course', 'anc1-all') resp = self.api_client.get( resource_url, format='json', data=self.user_auth) self.assertRaises(MultipleObjectsReturned) self.assertEqual(300, resp.status_code)
def process_course(extract_path, f, mod_name, request, user): xml_path = os.path.join(extract_path, mod_name, "module.xml") # check that the module.xml file exists if not os.path.isfile(xml_path): messages.info(request, _("Zip file does not contain a module.xml file"), extra_tags="danger") return False, 400 # parse the module.xml file doc = xml.dom.minidom.parse(xml_path) meta_info = parse_course_meta(doc) new_course = False oldsections = [] old_course_filename = None # Find if course already exists try: course = Course.objects.get(shortname=meta_info['shortname']) # check that the current user is allowed to wipe out the other course if course.user != user: messages.info(request, _("Sorry, only the original owner may update this course")) return False, 401 # check if course version is older if course.version > meta_info['versionid']: messages.info(request, _("A newer version of this course already exists")) return False, 400 # obtain the old sections oldsections = list(Section.objects.filter(course=course).values_list('pk', flat=True)) # wipe out old media oldmedia = Media.objects.filter(course=course) oldmedia.delete() old_course_filename = course.filename course.lastupdated_date = timezone.now() except Course.DoesNotExist: course = Course() course.is_draft = True new_course = True course.shortname = meta_info['shortname'] course.title = meta_info['title'] course.description = meta_info['description'] course.version = meta_info['versionid'] course.user = user course.filename = f.name course.save() # save gamification events if 'gamification' in meta_info: events = parse_gamification_events(meta_info['gamification']) # remove anything existing for this course CourseGamificationEvent.objects.filter(course=course).delete() # add new for event in events: e = CourseGamificationEvent(user=user, course=course, event=event['name'], points=event['points']) e.save() process_quizzes_locally = False if 'exportversion' in meta_info and meta_info['exportversion'] >= settings.OPPIA_EXPORT_LOCAL_MINVERSION: process_quizzes_locally = True print('processing course\'s quizzes locally') parse_course_contents(request, doc, course, user, new_course, process_quizzes_locally) clean_old_course(request, oldsections, old_course_filename, course) tmp_path = replace_zip_contents(xml_path, doc, mod_name, extract_path) # Extract the final file into the courses area for preview zipfilepath = settings.COURSE_UPLOAD_DIR + f.name shutil.copy(tmp_path + ".zip", zipfilepath) course_preview_path = settings.MEDIA_ROOT + "courses/" ZipFile(zipfilepath).extractall(path=course_preview_path) return course, 200
def process_course(extract_path, f, mod_name, request, user): xml_path = os.path.join(extract_path, mod_name, "module.xml") # check that the module.xml file exists if not os.path.isfile(xml_path): msg_text = _(u"Zip file does not contain a module.xml file") messages.info(request, msg_text, extra_tags="danger") CoursePublishingLog(user=user, action="no_module_xml", data=msg_text).save() return False, 400, False # parse the module.xml file doc = ET.parse(xml_path) meta_info = parse_course_meta(doc) is_new_course = False oldsections = [] old_course_filename = None # Find if course already exists try: course = Course.objects.get(shortname=meta_info['shortname']) course_manager = CoursePermissions.objects.filter( user=user, course=course, role=CoursePermissions.MANAGER).count() # check that the current user is allowed to wipe out the other course if course.user != user and course_manager == 0: msg_text = \ _(u"Sorry, you do not have permissions to update this course.") messages.info(request, msg_text) CoursePublishingLog(course=course, new_version=meta_info['versionid'], old_version=course.version, user=user, action="permissions_error", data=msg_text).save() return False, 401, is_new_course # check if course version is older if course.version > meta_info['versionid']: msg_text = _(u"A newer version of this course already exists") messages.info(request, msg_text) CoursePublishingLog(course=course, new_version=meta_info['versionid'], old_version=course.version, user=user, action="newer_version_exists", data=msg_text).save() return False, 400, is_new_course # obtain the old sections oldsections = list( Section.objects.filter(course=course).values_list('pk', flat=True)) # wipe out old media oldmedia = Media.objects.filter(course=course) oldmedia.delete() old_course_filename = course.filename course.lastupdated_date = timezone.now() except Course.DoesNotExist: course = Course() course.status = CourseStatus.DRAFT is_new_course = True old_course_version = course.version course.shortname = meta_info['shortname'] course.title = meta_info['title'] course.description = meta_info['description'] course.version = meta_info['versionid'] course.priority = int(meta_info['priority']) course.user = user course.filename = f.name course.save() if not parse_course_contents(request, doc, course, user, is_new_course): return False, 500, is_new_course clean_old_course(request, user, oldsections, old_course_filename, course) # save gamification events if 'gamification' in meta_info: events = parse_gamification_events(meta_info['gamification']) for event in events: # Only add events if the didn't exist previously e, created = CourseGamificationEvent.objects.get_or_create( course=course, event=event['name'], defaults={ 'points': event['points'], 'user': user }) if created: msg_text = \ _(u'Gamification for "%(event)s" at course level added') \ % {'event': e.event} messages.info(request, msg_text) CoursePublishingLog(course=course, new_version=meta_info['versionid'], old_version=old_course_version, user=user, action="gamification_added", data=msg_text).save() tmp_path = replace_zip_contents(xml_path, doc, mod_name, extract_path) # Extract the final file into the courses area for preview zipfilepath = os.path.join(settings.COURSE_UPLOAD_DIR, f.name) shutil.copy(tmp_path + ".zip", zipfilepath) course_preview_path = os.path.join(settings.MEDIA_ROOT, "courses") ZipFile(zipfilepath).extractall(path=course_preview_path) writer = GamificationXMLWriter(course) writer.update_gamification(request.user) return course, 200, is_new_course
def handle_uploaded_file(f, extract_path, request, user): zipfilepath = settings.COURSE_UPLOAD_DIR + f.name with open(zipfilepath, 'wb+') as destination: for chunk in f.chunks(): destination.write(chunk) zip = zipfile.ZipFile(zipfilepath) zip.extractall(path=extract_path) mod_name = '' for dir in os.listdir(extract_path)[:1]: mod_name = dir # check there is at least a sub dir if mod_name == '': messages.info(request, _("Invalid course zip file")) return False # check that the if not os.path.isfile(os.path.join(extract_path, mod_name, "module.xml")): messages.info(request, _("Zip file does not contain a module.xml file")) return False # parse the module.xml file print extract_path print mod_name doc = xml.dom.minidom.parse( os.path.join(extract_path, mod_name, "module.xml")) for meta in doc.getElementsByTagName("meta")[:1]: versionid = 0 for v in meta.getElementsByTagName("versionid")[:1]: versionid = int(v.firstChild.nodeValue) temp_title = {} for t in meta.childNodes: if t.nodeName == "title": temp_title[t.getAttribute('lang')] = t.firstChild.nodeValue title = json.dumps(temp_title) temp_description = {} for t in meta.childNodes: if t.nodeName == "description": if t.firstChild is not None: temp_description[t.getAttribute( 'lang')] = t.firstChild.nodeValue else: temp_description[t.getAttribute('lang')] = None description = json.dumps(temp_description) shortname = '' for sn in meta.getElementsByTagName("shortname")[:1]: shortname = sn.firstChild.nodeValue old_course_filename = None # Find if course already exists try: print shortname course = Course.objects.get(shortname=shortname) old_course_filename = course.filename # check that the current user is allowed to wipe out the other course if course.user != user: messages.info( request, _("Sorry, only the original owner may update this course")) return False # check if course version is older if course.version > versionid: messages.info(request, _("A newer version of this course already exists")) return False # wipe out the old sections/activities/media oldsections = Section.objects.filter(course=course) oldsections.delete() oldmedia = Media.objects.filter(course=course) oldmedia.delete() course.shortname = shortname course.title = title course.description = description course.version = versionid course.user = user course.filename = f.name course.lastupdated_date = timezone.now() course.save() except Course.DoesNotExist: course = Course() course.shortname = shortname course.title = title course.description = description course.version = versionid course.user = user course.filename = f.name course.is_draft = True course.save() # add in any baseline activities for meta in doc.getElementsByTagName("meta")[:1]: if meta.getElementsByTagName("activity").length > 0: section = Section() section.course = course section.title = '{"en": "Baseline"}' section.order = 0 section.save() for a in meta.getElementsByTagName("activity"): parse_and_save_activity(section, a, True) # add all the sections for structure in doc.getElementsByTagName("structure")[:1]: if structure.getElementsByTagName("section").length == 0: messages.info( request, _("There don't appear to be any activities in this upload file." )) course.delete() return False for s in structure.getElementsByTagName("section"): temp_title = {} for t in s.childNodes: if t.nodeName == 'title': temp_title[t.getAttribute('lang')] = t.firstChild.nodeValue title = json.dumps(temp_title) section = Section() section.course = course section.title = title section.order = s.getAttribute("order") section.save() # add all the activities for activities in s.getElementsByTagName("activities")[:1]: for a in activities.getElementsByTagName("activity"): parse_and_save_activity(section, a, False) # add all the media for file in doc.lastChild.lastChild.childNodes: if file.nodeName == 'file': media = Media() media.course = course media.filename = file.getAttribute("filename") media.download_url = file.getAttribute("download_url") media.digest = file.getAttribute("digest") # get any optional attributes for attrName, attrValue in file.attributes.items(): if attrName == "length": media.media_length = attrValue if attrName == "filesize": media.filesize = attrValue media.save() if old_course_filename is not None and old_course_filename != course.filename: try: os.remove(settings.COURSE_UPLOAD_DIR + old_course_filename) except OSError: pass # Extract the final file into the courses area for preview zipfilepath = settings.COURSE_UPLOAD_DIR + f.name with open(zipfilepath, 'wb+') as destination: for chunk in f.chunks(): destination.write(chunk) zip = zipfile.ZipFile(zipfilepath) course_preview_path = settings.MEDIA_ROOT + "courses/" zip.extractall(path=course_preview_path) # remove the temp upload files shutil.rmtree(extract_path, ignore_errors=True) return course
def handle_uploaded_file(f, extract_path, request): zipfilepath = settings.COURSE_UPLOAD_DIR + f.name with open(zipfilepath, 'wb+') as destination: for chunk in f.chunks(): destination.write(chunk) zip = zipfile.ZipFile(zipfilepath) zip.extractall(path=extract_path) mod_name = '' for dir in os.listdir(extract_path)[:1]: mod_name = dir # check there is at least a sub dir if mod_name == '': messages.info(request,_("Invalid course zip file")) return False # check that the if not os.path.isfile(extract_path + mod_name + "/module.xml"): messages.info(request,_("Zip file does not contain a module.xml file")) return False # parse the module.xml file doc = xml.dom.minidom.parse(extract_path + mod_name + "/module.xml") for meta in doc.getElementsByTagName("meta")[:1]: versionid = 0 for v in meta.getElementsByTagName("versionid")[:1]: versionid = int(v.firstChild.nodeValue) temp_title = {} for t in meta.childNodes: if t.nodeName == "title": temp_title[t.getAttribute('lang')] = t.firstChild.nodeValue title = json.dumps(temp_title) temp_description = {} for t in meta.childNodes: if t.nodeName == "description": if t.firstChild is not None: temp_description[t.getAttribute('lang')] = t.firstChild.nodeValue else: temp_description[t.getAttribute('lang')] = None description = json.dumps(temp_description) shortname = '' for sn in meta.getElementsByTagName("shortname")[:1]: shortname = sn.firstChild.nodeValue old_course_filename = None # Find if course already exists try: course = Course.objects.get(shortname = shortname) old_course_filename = course.filename old_course_version = course.version # check that the current user is allowed to wipe out the other course if course.user != request.user: messages.info(request,_("Sorry, only the original owner may update this course")) return False # check if course version is older if course.version > versionid: messages.info(request,_("A newer version of this course already exists")) return False # wipe out the old sections/activities/media oldsections = Section.objects.filter(course = course) oldsections.delete() oldmedia = Media.objects.filter(course = course) oldmedia.delete() course.shortname = shortname course.title = title course.description = description course.version = versionid course.user = request.user course.filename = f.name course.lastupdated_date = datetime.datetime.now() course.save() except Course.DoesNotExist: course = Course() course.shortname = shortname course.title = title course.description = description course.version = versionid course.user = request.user course.filename = f.name course.is_draft = True course.save() # add in any baseline activities for meta in doc.getElementsByTagName("meta")[:1]: if meta.getElementsByTagName("activity").length > 0: section = Section() section.course = course section.title = '{"en": "Baseline"}' section.order = 0 section.save() for a in meta.getElementsByTagName("activity"): activity_create(section, a,True) # add all the sections for structure in doc.getElementsByTagName("structure")[:1]: if structure.getElementsByTagName("section").length == 0: messages.info(request,_("There don't appear to be any activities in this upload file.")) course.delete() return False for s in structure.getElementsByTagName("section"): temp_title = {} for t in s.childNodes: if t.nodeName == 'title': temp_title[t.getAttribute('lang')] = t.firstChild.nodeValue title = json.dumps(temp_title) section = Section() section.course = course section.title = title section.order = s.getAttribute("order") section.save() # add all the activities for activities in s.getElementsByTagName("activities")[:1]: for a in activities.getElementsByTagName("activity"): activity_create(section, a,False) # add all the media for file in doc.lastChild.lastChild.childNodes: if file.nodeName == 'file': media = Media() media.course = course media.filename = file.getAttribute("filename") media.download_url = file.getAttribute("download_url") media.digest = file.getAttribute("digest") # get any optional attributes for attrName, attrValue in file.attributes.items(): if attrName == "length": media.media_length = attrValue if attrName == "filesize": media.filesize = attrValue media.save() if old_course_filename is not None and old_course_filename != course.filename: os.remove(settings.COURSE_UPLOAD_DIR + old_course_filename) #Extract the final file into the courses area for preview zipfilepath = settings.COURSE_UPLOAD_DIR + f.name with open(zipfilepath, 'wb+') as destination: for chunk in f.chunks(): destination.write(chunk) zip = zipfile.ZipFile(zipfilepath) course_preview_path = settings.MEDIA_ROOT + "courses/" zip.extractall(path=course_preview_path) return course
def handle_uploaded_file(f, extract_path, request): zipfilepath = settings.COURSE_UPLOAD_DIR + f.name with open(zipfilepath, 'wb+') as destination: for chunk in f.chunks(): destination.write(chunk) zip = zipfile.ZipFile(zipfilepath) zip.extractall(path=extract_path) mod_name = '' for dir in os.listdir(extract_path)[:1]: mod_name = dir # check there is at least a sub dir if mod_name == '': messages.info(request, _("Invalid course zip file")) return False # check that the if not os.path.isfile(extract_path + mod_name + "/module.xml"): messages.info(request, _("Zip file does not contain a module.xml file")) return False # parse the module.xml file doc = xml.dom.minidom.parse(extract_path + mod_name + "/module.xml") for meta in doc.getElementsByTagName("meta")[:1]: versionid = 0 for v in meta.getElementsByTagName("versionid")[:1]: versionid = int(v.firstChild.nodeValue) temp_title = {} for t in meta.childNodes: if t.nodeName == "title": temp_title[t.getAttribute('lang')] = t.firstChild.nodeValue title = json.dumps(temp_title) shortname = '' for sn in meta.getElementsByTagName("shortname")[:1]: shortname = sn.firstChild.nodeValue old_course_filename = None # Find if course already exists try: course = Course.objects.get(shortname=shortname) old_course_filename = course.filename # check that the current user is allowed to wipe out the other course if course.user != request.user: messages.info( request, _("Sorry, only the original owner may update this course")) return False # check if course version is older if course.version > versionid: messages.info(request, _("A newer version of this course already exists")) return False # wipe out the old sections/activities/media oldsections = Section.objects.filter(course=course) oldsections.delete() oldmedia = Media.objects.filter(course=course) oldmedia.delete() course.shortname = shortname course.title = title course.version = versionid course.user = request.user course.filename = f.name course.lastupdated_date = datetime.datetime.now() course.save() except Course.DoesNotExist: course = Course() course.shortname = shortname course.title = title course.version = versionid course.user = request.user course.filename = f.name course.save() # add all the sections for structure in doc.getElementsByTagName("structure")[:1]: if structure.getElementsByTagName("section").length == 0: messages.info( request, _("There don't appear to be any activities in this upload file." )) course.delete() return False for s in structure.getElementsByTagName("section"): temp_title = {} for t in s.childNodes: if t.nodeName == 'title': temp_title[t.getAttribute('lang')] = t.firstChild.nodeValue title = json.dumps(temp_title) section = Section() section.course = course section.title = title section.order = s.getAttribute("order") section.save() # add all the activities for activities in s.getElementsByTagName("activities")[:1]: for a in activities.getElementsByTagName("activity"): temp_title = {} for t in a.getElementsByTagName("title"): temp_title[t.getAttribute( 'lang')] = t.firstChild.nodeValue title = json.dumps(temp_title) activity = Activity() activity.section = section activity.order = a.getAttribute("order") activity.title = title activity.type = a.getAttribute("type") activity.digest = a.getAttribute("digest") activity.save() # add all the media for files in doc.lastChild.lastChild.childNodes: if files.nodeName == 'file': media = Media() media.course = course media.filename = files.getAttribute("filename") media.download_url = files.getAttribute("download_url") media.digest = files.getAttribute("digest") media.save() if old_course_filename is not None and course.version != versionid: os.remove(settings.COURSE_UPLOAD_DIR + old_course_filename) return course