Esempio n. 1
0
 def children_recursion(parent):
     if not "children" in parent:
         return []
     result = []
     for o in [o for o in parent["children"] if "key" in o]:
         of = _type_dict(o, course.get("exercise_types", {}))
         if "config" in of:
             _, exercise = config.exercise_entry(course["key"], str(of["key"]), '_root')
             of = export.exercise(request, course, exercise, of)
         elif "static_content" in of:
             of = export.chapter(request, course, of)
         of["children"] = children_recursion(o)
         result.append(of)
     return result
Esempio n. 2
0
 def children_recursion(parent):
     if not "children" in parent:
         return []
     result = []
     for o in [o for o in parent["children"] if "key" in o]:
         of = _type_dict(o, course.get("exercise_types", {}))
         if "config" in of:
             _, exercise = config.exercise_entry(course["key"], str(of["key"]), '_root')
             of = export.exercise(request, course, exercise, of)
         elif "static_content" in of:
             of = export.chapter(request, course, of)
         of["children"] = children_recursion(o)
         result.append(of)
     return result
Esempio n. 3
0
def configure(request):
    '''
    Configure a course according to the gitmanager protocol.
    '''
    if request.method != "POST":
        return HttpResponse(status=405)

    if request.POST.get("publish"):
        return publish(request)

    if "exercises" not in request.POST or "course_id" not in request.POST:
        return HttpResponse("Missing exercises or course_id", status=400)

    try:
        exercises = json.loads(request.POST["exercises"])
    except (JSONDecodeError, ValueError) as e:
        LOGGER.info(f"Invalid exercises field: {e}")
        return HttpResponse(f"Invalid exercises field: {e}", status=400)

    course_id = request.POST["course_id"]
    try:
        access_write_check(request, course_id)
    except PermissionDenied as e:
        SecurityLog.reject(request, f"CONFIGURE",
                           f"course_id={course_id}: {e}")
        raise
    except ValueError as e:
        LOGGER.info(f"Invalid course_id field: {e}")
        return HttpResponse(f"Invalid course_id field: {e}", status=400)

    SecurityLog.accept(request, f"CONFIGURE", f"course_id={course_id}")

    root_dir = Path(settings.COURSE_STORE)
    course_path = root_dir / course_id
    if course_path.exists():
        try:
            rmtree(course_path)
        except OSError:
            LOGGER.exception("Failed to remove old stored course files")
            return HttpResponse("Failed to remove old stored course files",
                                status=500)

    course_files_path = course_path / EXTERNAL_FILES_DIR
    course_exercises_path = course_path / EXTERNAL_EXERCISES_DIR
    version_id_path = root_dir / (course_id + ".version")
    course_files_path.mkdir(parents=True, exist_ok=True)
    course_exercises_path.mkdir(parents=True, exist_ok=True)

    if "files" in request.FILES:
        tar_file = request.FILES["files"].file
        tarh = TarFile(fileobj=tar_file)
        tarh.extractall(course_files_path)

    course_config = {
        "name": course_id,
        "exercises": [ex["key"] for ex in exercises],
        "exercise_loader": "access.config._ext_exercise_loader",
    }

    try:
        with open(course_path / "index.json", "w") as f:
            json.dump(course_config, f)

        for info in exercises:
            with open(course_exercises_path / (info["key"] + ".json"),
                      "w") as f:
                json.dump(info["config"], f)
    except OSError as e:
        LOGGER.exception("Failed to dump configuration JSONs to files")
        return HttpResponse("Failed to dump configuration JSONs to files: {e}",
                            status=500)

    if "version_id" in request.POST:
        try:
            with open(version_id_path, "w") as f:
                f.write(request.POST["version_id"])
        except OSError as e:
            LOGGER.exception("Failed to write version id file")
            return HttpResponse("Failed to write version id file: {e}",
                                status=500)
    elif version_id_path.exists():
        try:
            rm_path(version_id_path)
        except OSError as e:
            LOGGER.exception("Failed to remove version id file")
            return HttpResponse("Failed to remove version id file: {e}",
                                status=500)

    course_config = config._course_root_from_root_dir(course_id, root_dir)

    defaults = {}
    for info in exercises:
        of = info["spec"]
        if info.get("config"):
            of["config"] = info["key"] + ".json"
            course, exercise = config.exercise_entry(course_config,
                                                     info["key"], "_root")
            of = export.exercise(request, course, exercise, of)
        defaults[of["key"]] = of

    return JsonResponse(defaults)