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']
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
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
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.")