Example #1
0
def create_team(params):
    """
    Directly inserts team into the database. Assumes all fields have been validated.

    Args:
        team_name: Name of the team
        adviser_name: Full name of the team's adviser
        adviser_email: Adviser's email address
        school: Name of the school
        password: Team's password
        eligible: the teams eligibility
    Returns:
        The newly created team id.
    """

    db = api.common.get_conn()

    if not shell_accounts_available() and api.config.enable_shell:
        raise SevereInternalException("There are no shell accounts available.")

    params['tid'] = api.common.token()
    params['size'] = 0

    db.teams.insert(params)

    if api.config.enable_shell:
        assign_shell_account(params["tid"])

    return params['tid']
Example #2
0
def get_achievement(aid=None, name=None, show_disabled=False):
    """
    Gets a single achievement

    Args:
        aid: the achievement id
        name: the name of the achievement
        show_disabled: Boolean indicating whether or not to show disabled achievements.
    """

    db = api.common.get_conn()

    match = {}

    if aid is not None:
        match.update({'aid': aid})
    elif name is not None:
        match.update({'name': name})
    else:
        raise InternalException("Must supply aid or display name")

    if not show_disabled:
        match.update({"disabled": False})

    db = api.common.get_conn()
    achievement = db.achievements.find_one(match, {"_id":0})

    if achievement is None:
        raise SevereInternalException("Could not find achievement! You gave " + str(match))

    return achievement
Example #3
0
def get_problem(pid=None, name=None, tid=None, show_disabled=True):
    """
    Gets a single problem.

    Args:
        pid: The problem id
        name: The name of the problem
        show_disabled: Boolean indicating whether or not to show disabled problems. Defaults to True
    Returns:
        The problem dictionary from the database
    """

    db = api.common.get_conn()

    match = {}

    if pid is not None:
        match.update({'pid': pid})
    elif name is not None:
        match.update({'name': name})
    else:
        raise InternalException("Must supply pid or display name")

    if tid is not None and pid not in get_unlocked_pids(tid, category=None):
        raise InternalException("You cannot get this problem")

    if not show_disabled:
        match.update({"disabled": False})

    db = api.common.get_conn()
    problem = db.problems.find_one(match, {"_id": 0})

    if problem is None:
        raise SevereInternalException("Could not find problem! You gave " +
                                      str(match))

    return problem
Example #4
0
def grade_problem_instance(pid, tid, key):
    """
    Grades an autogenerated problem. This will invoke
    the particular grader for the instance the team is mapped to.

    Args:
        pid: the problem id
        tid: the team id
        key: the team's attempted solution
    Returns:
        A dict.
        correct: boolean
        points: number of points the problem is worth
        message: a message to be returned to the user
    """

    if not is_autogen_problem(pid):
        raise InternalException("Problem is not autogenerated! {}".format(pid))

    problem = api.problem.get_problem(pid)

    n = get_instance_number(pid, tid)
    grader_problem_instance = GraderProblemInstance(pid, tid, n)

    grader = api.problem.get_grader(pid)

    try:
        correct, message = grader.grade(grader_problem_instance, key)
    except Exception as e:
        raise SevereInternalException("Grader for {} is throwing exceptions.\n{}".format(pid, str(e)))

    return {
        "correct": correct,
        "points": problem["score"],
        "message": message
    }
def run():

    db = api.common.get_conn()

    try:
        shell = spur.SshShell(hostname=api.config.shell_host,
                              username=api.config.shell_username,
                              password=api.config.shell_password,
                              port=api.config.shell_port,
                              missing_host_key=spur.ssh.MissingHostKey.accept)

        result = shell.run(["sudo", "useradd", "--help"])

        if result.return_code != 0:
            raise SevereInternalException("Unable to sudo useradd.")

        account_count = db.ssh.count()
        if account_count >= api.config.shell_max_accounts:
            raise SevereInternalException("Max SSH accounts already created!")

        free_account_count = db.ssh.find({"tid": {"$exists": False}}).count()

        new_accounts = api.config.shell_free_acounts - free_account_count

        print("Checking that all teams have been assigned accounts...")

        print("{}/{} shell accounts allocated adding {}...".format(
            free_account_count, account_count, new_accounts))
        tids = [team["tid"] for team in api.team.get_all_teams(show_ineligible=True) \
                if db.ssh.find({"tid": team["tid"]}).count() == 0]

        if len(tids) > 0:
            print("{} teams without accounts present! Adding these as well.".
                  format(len(tids)))
            new_accounts += len(tids)

        accounts = []
        while new_accounts > 0:
            username = random.choice(api.config.shell_user_prefixes) + \
                    str(random.randint(0, api.config.shell_max_accounts))

            plaintext_password = api.common.token()[:api.config.
                                                    shell_password_length]

            hashed_password = shell.run([
                "bash", "-c", "echo '{}' | openssl passwd -1 -stdin".format(
                    plaintext_password)
            ])
            hashed_password = hashed_password.output.decode("utf-8").strip()

            shell_cmd = api.config.shell_user_creation.format(
                username=username, password=hashed_password)

            result = shell.run(shell_cmd.split(), allow_error=True)

            if result.return_code == 9:
                print("Collision! Retrying.")
                continue
            elif result.return_code != 0:
                raise InternalException(result.stderr)

            print("\t{}:{}".format(username, plaintext_password))

            account = {
                "username": username,
                "password": plaintext_password,
                "hostname": api.config.shell_host,
                "port": api.config.shell_port
            }

            accounts.append(account)

            new_accounts -= 1

        if len(accounts) > 0:
            db.ssh.insert(accounts)
            print("Successfully imported accounts into mongo.")

        for tid in tids:
            api.team.assign_shell_account(tid=tid)

    except spur.ssh.ConnectionError:
        raise SevereInternalException("Could not connect to shell server.")