def _get_user_from_sso(jwt_token, token): try: data = jwt.decode(jwt_token, Config.jwt_secret, algorithms=['HS256']) username = data["username"] name = data.get("firstName", username) surname = data.get("lastName", "") if username != token: BaseHandler.raise_exc(Forbidden, "FORBIDDEN", "Use the same username from the SSO") if Database.get_user(username) is None: Database.begin() Database.add_user(username, name, surname, sso_user=True, autocommit=False) for task in Database.get_tasks(): Database.add_user_task(username, task["name"], autocommit=False) Database.commit() Logger.info("NEW_USER", "User %s created from SSO" % username) return Database.get_user(username) except jwt.exceptions.DecodeError: BaseHandler.raise_exc(Forbidden, "FORBIDDEN", "Please login at %s" % Config.sso_url)
def get_contest(self): """ GET /contest """ start_timestamp = Database.get_meta("start_time", type=int) start_datetime = (datetime.fromtimestamp(start_timestamp, timezone.utc) if start_timestamp is not None else None) now = datetime.now(timezone.utc) if not start_timestamp or now < start_datetime: return { "has_started": False, "start_time": start_datetime.isoformat() if start_datetime else None, "name": Database.get_meta("contest_name"), "description": Database.get_meta("contest_description"), } tasks = Database.get_tasks() return { "has_started": True, "name": Database.get_meta("contest_name"), "description": Database.get_meta("contest_description"), "start_time": start_datetime.isoformat(), "tasks": tasks, "max_total_score": sum(task["max_score"] for task in tasks), }
def test_read_from_disk(self): path = Utils.new_tmp_dir() self._prepare_contest_dir(path) Config.statementdir = Utils.new_tmp_dir() Config.contest_path = path with patch("gevent.spawn") as mock: ContestManager.read_from_disk() mock.assert_has_calls( [call(ContestManager.worker, "poldo")], any_order=True) self.assertEqual(18000, Database.get_meta( "contest_duration", type=int)) tasks = Database.get_tasks() self.assertEqual(1, len(tasks)) self.assertEqual("poldo", tasks[0]["name"]) self.assertEqual("Poldo", tasks[0]["title"]) self.assertEqual(42, tasks[0]["max_score"]) self.assertEqual(0, tasks[0]["num"]) users = Database.get_users() self.assertEqual(1, len(users)) self.assertEqual("token", users[0]["token"]) self.assertEqual("Test", users[0]["name"]) self.assertEqual("User", users[0]["surname"]) self.assertEqual(0, users[0]["extra_time"]) user_tasks = Database.get_user_task("token", "poldo") self.assertEqual("token", user_tasks["token"]) self.assertEqual("poldo", user_tasks["task"]) self.assertEqual(0, user_tasks["score"]) self.assertIsNone(user_tasks["current_attempt"]) self.assertTrue(Database.get_meta("contest_imported", type=bool)) self.assertTrue(ContestManager.has_contest) self.assertIn("poldo", ContestManager.tasks) self.assertIn("poldo", ContestManager.input_queue)
def read_from_disk(remove_enc=True): """ Load a task from the disk and load the data into the database """ try: contest = ContestManager.import_contest(Config.contest_path) except FileNotFoundError as ex: error = ( "Contest not found, you probably need to unzip it. Missing file %s" % ex.filename) Logger.warning("CONTEST", error) shutil.rmtree(Config.statementdir, ignore_errors=True) shutil.rmtree(Config.web_statementdir, ignore_errors=True) shutil.rmtree(Config.contest_path, ignore_errors=True) if remove_enc: with suppress(Exception): os.remove(Config.encrypted_file) with suppress(Exception): os.remove(Config.decrypted_file) Database.del_meta("admin_token") BaseHandler.raise_exc(UnprocessableEntity, "CONTEST", error) if not Database.get_meta("contest_imported", default=False, type=bool): Database.begin() try: Database.set_meta("contest_duration", contest["duration"], autocommit=False) Database.set_meta("contest_name", contest.get("name", "Contest"), autocommit=False) Database.set_meta( "contest_description", contest.get("description", ""), autocommit=False, ) Database.set_meta( "window_duration", # if None the contest is not USACO-style contest.get("window_duration"), autocommit=False, ) count = 0 for task in contest["tasks"]: Database.add_task( task["name"], task["description"], task["statement_path"], task["max_score"], count, autocommit=False, ) count += 1 for user in contest["users"]: Database.add_user(user["token"], user["name"], user["surname"], autocommit=False) for user in Database.get_users(): for task in Database.get_tasks(): Database.add_user_task(user["token"], task["name"], autocommit=False) Database.set_meta("contest_imported", True, autocommit=False) Database.commit() except: Database.rollback() raise else: # TODO: check that the contest is still the same pass # store the task in the ContestManager singleton ContestManager.tasks = dict( (task["name"], task) for task in contest["tasks"]) ContestManager.has_contest = True # create the queues for the task inputs for task in ContestManager.tasks: ContestManager.input_queue[task] = gevent.queue.Queue( Config.queue_size) gevent.spawn(ContestManager.worker, task)
def get_tasks(): from terry.database import Database return [t["name"] for t in Database.get_tasks()]