Example #1
0
        def student_get_course(netid, cid):
            if not verify_student_or_staff(netid, cid):
                return abort(HTTPStatus.FORBIDDEN)

            course = db.get_course(cid)
            if verify_staff(netid, cid):
                assignments = db.get_assignments_for_course(cid)
            else:
                assignments = db.get_assignments_for_course(cid,
                                                            visible_only=True)

            now = util.now_timestamp()

            for assignment in assignments:

                num_available_runs = get_available_runs(
                    cid, assignment["assignment_id"], netid, now)
                active_extensions, num_extension_runs = get_active_extensions(
                    cid, assignment["assignment_id"], netid, now)
                total_available_runs = num_extension_runs + num_available_runs

                if verify_staff(netid, cid):
                    total_available_runs = max(total_available_runs, 1)

                assignment.update(
                    {"total_available_runs": total_available_runs})

            return render_template("student/course.html",
                                   netid=netid,
                                   course=course,
                                   assignments=assignments,
                                   now=now,
                                   tzname=str(TZ))
Example #2
0
        def student_get_assignment(netid, cid, aid):
            if not verify_student_or_staff(netid, cid):
                return abort(HTTPStatus.FORBIDDEN)

            course = db.get_course(cid)
            assignment = db.get_assignment(cid, aid)
            runs = db.get_assignment_runs_for_student(cid, aid, netid)
            now = util.now_timestamp()

            num_available_runs = get_available_runs(cid, aid, netid, now)
            active_extensions, num_extension_runs = get_active_extensions(
                cid, aid, netid, now)

            user = db.get_user(netid)
            commit = get_latest_commit(netid, user["access_token"],
                                       course["github_org"])

            if verify_staff(netid, cid):
                num_available_runs = max(num_available_runs, 1)

            return render_template("student/assignment.html",
                                   netid=netid,
                                   course=course,
                                   assignment=assignment,
                                   commit=commit,
                                   runs=runs,
                                   num_available_runs=num_available_runs,
                                   num_extension_runs=num_extension_runs,
                                   tzname=str(TZ),
                                   broadway_api_url=BROADWAY_API_URL)
Example #3
0
def verify_student(netid, cid):
    """
	Check whether the given NetID is a student in the given course.
	:param netid: a user's NetID.
	:param cid: a course ID.
	:return: a boolean value.
	"""
    return netid in db.get_course(cid)["student_ids"]
Example #4
0
def verify_admin(netid, cid):
    """
	Check whether the given NetID is a course admin in the given course.
	:param netid: a user's NetID.
	:param cid: a course ID.
	:return: a boolean value.
	"""
    staff = db.get_course(cid)["staff"]
    if netid not in staff:
        return False
    else:
        return staff[netid]["is_admin"]
Example #5
0
        def get_course_staff_roster(netid, cid):
            course = db.get_course(cid)

            staff = course["staff"]
            # get all admin_ids by filtering out all non-admins
            admin = dict(
                filter(lambda x: x[1].get("is_admin") == True, staff.items()))
            admin = list(admin.keys())
            # get the entire staff
            total_staff = list(staff.keys())

            return jsonify(admin_ids=admin, staff_ids=total_staff, user=netid)
Example #6
0
        def edit_assignment(netid, cid, aid):
            course = db.get_course(cid)
            assignment = db.get_assignment(cid, aid)
            if course is None or assignment is None:
                return abort(HTTPStatus.NOT_FOUND)

            missing = util.check_missing_fields(
                request.form,
                *["max_runs", "quota", "start", "end", "visibility"])
            if missing:
                return util.error(f"Missing fields ({', '.join(missing)}).")

            try:
                max_runs = int(request.form["max_runs"])
                if max_runs < MIN_PREDEADLINE_RUNS:
                    return util.error(
                        f"Max Runs must be at least {MIN_PREDEADLINE_RUNS}.")
            except ValueError:
                return util.error("Max Runs must be a positive integer.")

            quota = request.form["quota"]
            if not db.Quota.is_valid(quota):
                return util.error("Quota Type is invalid.")

            start = util.parse_form_datetime(request.form["start"]).timestamp()
            end = util.parse_form_datetime(request.form["end"]).timestamp()
            if start is None or end is None:
                return util.error("Missing or invalid Start or End.")
            if start >= end:
                return util.error("Start must be before End.")

            try:
                config_str = request.form.get("config")

                if config_str is not None:  # skip update otherwise
                    config = json.loads(request.form["config"])
                    msg = bw_api.set_assignment_config(cid, aid, config)

                    if msg:
                        return util.error(
                            f"Failed to update assignment config to Broadway: {msg}"
                        )
            except json.decoder.JSONDecodeError:
                return util.error("Failed to decode config JSON")

            visibility = request.form["visibility"]

            if not db.update_assignment(cid, aid, max_runs, quota, start, end,
                                        visibility):
                return util.error("Save failed or no changes were made.")
            return util.success("")
Example #7
0
        def staff_get_course(netid, cid):
            if not verify_staff(netid, cid):
                return abort(HTTPStatus.FORBIDDEN)

            course = db.get_course(cid)
            assignments = db.get_assignments_for_course(cid)
            is_admin = verify_admin(netid, cid)
            now = util.now_timestamp()
            return render_template("staff/course.html",
                                   netid=netid,
                                   course=course,
                                   assignments=assignments,
                                   tzname=str(TZ),
                                   is_admin=is_admin,
                                   now=now,
                                   visibility=db.Visibility,
                                   error=None)
Example #8
0
        def staff_get_assignment(netid, cid, aid):
            if not verify_staff(netid, cid):
                return abort(HTTPStatus.FORBIDDEN)

            course = db.get_course(cid)
            assignment = db.get_assignment(cid, aid)
            student_runs = list(db.get_assignment_runs(cid, aid))
            scheduled_runs = list(db.get_scheduled_runs(cid, aid))
            is_admin = verify_admin(netid, cid)

            return render_template(
                "staff/assignment.html",
                netid=netid,
                course=course,
                assignment=assignment,
                student_runs=student_runs,
                scheduled_runs=scheduled_runs,
                sched_run_status=sched_api.ScheduledRunStatus,
                tzname=str(TZ),
                is_admin=is_admin,
                visibility=db.Visibility,
                broadway_api_url=BROADWAY_API_URL)
Example #9
0
        def trigger_scheduled_run(cid, aid, scheduled_run_id):
            sched_run = db.get_scheduled_run_by_scheduler_id(
                cid, aid, scheduled_run_id)
            if sched_run is None:
                logging.warning(
                    "Received trigger scheduled run request for scheduled_run_id '%s' but cannot find corresponding run.",
                    scheduled_run_id)
                return util.error("")
            if sched_run["status"] != ScheduledRunStatus.SCHEDULED:
                logging.warning(
                    "Received trigger scheduled run for _id '%s' but this run has status '%s', which is not 'scheduled'.",
                    str(sched_run["_id"]), sched_run["status"])
                return util.error("")

            # If roster is not provided, use course roster
            if sched_run["roster"] is None:
                course = db.get_course(cid)
                if course is None:
                    return util.error("")
                netids = course["student_ids"]
            # If a roster is provided, use it
            else:
                netids = sched_run["roster"]

            # Start broadway grading run
            bw_run_id = bw_api.start_grading_run(cid,
                                                 f"{aid}_{sched_run['_id']}",
                                                 netids, sched_run["due_time"])
            if bw_run_id is None:
                logging.warning("Failed to trigger run with broadway")
                db.update_scheduled_run_status(sched_run["_id"],
                                               ScheduledRunStatus.FAILED)
                return util.error("")
            else:
                db.update_scheduled_run_status(sched_run["_id"],
                                               ScheduledRunStatus.RAN)
                db.update_scheduled_run_bw_run_id(sched_run["_id"], bw_run_id)
            return util.success("")
Example #10
0
def build_header(cid):
    token = db.get_course(cid)["token"]
    return {"Authorization": f"Bearer {token}"}
Example #11
0
 def get_course_student_roster(netid, cid):
     course = db.get_course(cid)
     return jsonify(course['student_ids'])
Example #12
0
        def add_or_edit_scheduled_run(cid, aid, run_id, form,
                                      scheduled_run_id):
            # course and assignment name validation
            course = db.get_course(cid)
            assignment = db.get_assignment(cid, aid)
            if course is None or assignment is None:
                return abort(HTTPStatus.NOT_FOUND)

            # form validation
            missing = util.check_missing_fields(request.form, "run_time",
                                                "due_time", "name", "config")
            if missing:
                return util.error(f"Missing fields ({', '.join(missing)}).")
            run_time = util.parse_form_datetime(
                request.form["run_time"]).timestamp()
            if run_time is None:
                return util.error("Missing or invalid run time.")
            if run_time <= util.now_timestamp():
                return util.error("Run time must be in the future.")
            due_time = util.parse_form_datetime(
                request.form["due_time"]).timestamp()
            if due_time is None:
                return util.error("Missing or invalid due time.")
            if "roster" not in request.form or not request.form["roster"]:
                roster = None
            else:
                roster = request.form["roster"].replace(" ",
                                                        "").lower().split(",")
                for student_netid in roster:
                    if not util.valid_id(student_netid) or not verify_student(
                            student_netid, cid):
                        return util.error(
                            f"Invalid or non-existent student NetID: {student_netid}"
                        )
            try:
                config = json.loads(request.form["config"])
                msg = bw_api.set_assignment_config(cid, f"{aid}_{run_id}",
                                                   config)
                if msg:
                    return util.error(
                        f"Failed to upload config to Broadway: {msg}")
            except json.decoder.JSONDecodeError:
                return util.error("Failed to decode config JSON")

            # Schedule a new run with scheduler
            if scheduled_run_id is None:
                scheduled_run_id = sched_api.schedule_run(run_time, cid, aid)
                if scheduled_run_id is None:
                    return util.error("Failed to schedule run with scheduler")
            # Or if the run was already scheduled, update the time
            else:
                if not sched_api.update_scheduled_run(scheduled_run_id,
                                                      run_time):
                    return util.error(
                        "Failed to update scheduled run time with scheduler")

            assert scheduled_run_id is not None

            if not db.add_or_update_scheduled_run(
                    run_id, cid, aid, run_time, due_time, roster,
                    request.form["name"], scheduled_run_id):
                return util.error(
                    "Failed to save the changes, please try again.")
            return util.success("")
Example #13
0
 def get_course_roster_page(netid, cid):
     course = db.get_course(cid)
     return render_template("staff/roster.html",
                            netid=netid,
                            course=course)