Beispiel #1
0
 def test_upload_pack_already_extracted(self):
     Database.set_meta("admin_token", "totally the real token")
     with self.assertRaises(Forbidden):
         self.admin_handler.upload_pack(file={
             "content": "foobar".encode(),
             "name": "pack.zip.enc"
         })
Beispiel #2
0
    def test_set_meta(self):
        Database.connected = False
        Database.connect_to_database()

        Database.set_meta('random_key', 42)
        value = Database.get_meta('random_key', type=int)
        self.assertEqual(42, value)
Beispiel #3
0
    def test_del_meta(self):
        Database.connected = False
        Database.connect_to_database()

        Database.set_meta('random_key', 4242)
        self.assertTrue(Database.del_meta('random_key'))
        self.assertIsNone(Database.get_meta('random_key'))
Beispiel #4
0
    def test_get_meta_default_not_used(self):
        Database.connected = False
        Database.connect_to_database()

        Database.set_meta("this_key_doesnt_exist", "cool_value")
        meta = Database.get_meta("this_key_doesnt_exist",
                                 "default_value_is_not_cool")
        self.assertEqual("cool_value", meta)
Beispiel #5
0
    def test_set_meta_overwrite(self):
        Database.connected = False
        Database.connect_to_database()

        Database.set_meta("random_key", 4242)
        Database.set_meta("random_key", 42)
        value = Database.get_meta("random_key", type=int)
        self.assertEqual(42, value)
Beispiel #6
0
    def test_get_meta_type_bool(self):
        Database.connected = False
        Database.connect_to_database()

        Database.set_meta('boooool', True)
        self.assertTrue(Database.get_meta('boooool', type=bool))
        Database.set_meta('boooool2', False)
        self.assertFalse(Database.get_meta('boooool2', type=bool))
Beispiel #7
0
    def setUp(self):
        Utils.prepare_test()
        self.admin_handler = AdminHandler()

        Database.set_meta("admin_token", "ADMIN-TOKEN")

        self.log_backup = Logger.LOG_LEVEL
        Logger.LOG_LEVEL = 9001  # disable the logs
Beispiel #8
0
    def test_start_already_started(self):
        Database.set_meta('start_time', 12345)

        with self.assertRaises(Forbidden) as ex:
            self.admin_handler.start(admin_token='ADMIN-TOKEN', _ip='1.2.3.4')

        self.assertIn("Contest has already been started",
                      ex.exception.response.data.decode())
Beispiel #9
0
    def test_get_meta_default_not_used(self):
        Database.connected = False
        Database.connect_to_database()

        Database.set_meta('this_key_doesnt_exist', 'cool_value')
        meta = Database.get_meta('this_key_doesnt_exist',
                                 'default_value_is_not_cool')
        self.assertEqual('cool_value', meta)
Beispiel #10
0
    def test_transaction_commit(self):
        Database.connected = False
        Database.connect_to_database()

        Database.begin()
        Database.set_meta('random_foobar', 123, autocommit=False)
        Database.commit()

        self.assertEqual(123, Database.get_meta('random_foobar', type=int))
Beispiel #11
0
    def test_dictify(self):
        Database.connected = False
        Database.connect_to_database()

        Database.set_meta('random_key', 'random_value')
        Database.c.execute("SELECT * FROM metadata WHERE key = 'random_key'")
        dct = Database.dictify(all=False)

        self.assertDictEqual({'key': 'random_key', 'value': 'random_value'},
                             dct)
Beispiel #12
0
    def test_get_meta_none(self):
        Database.connected = False
        Database.connect_to_database()

        Database.set_meta("test", None)
        Database.set_meta("test2", "None")
        self.assertEqual(Database.get_meta("test"), None)
        self.assertEqual(Database.get_meta("test", type=int), None)
        self.assertEqual(Database.get_meta("test", None, type=int), None)
        self.assertEqual(Database.get_meta("test2", None), "None")
Beispiel #13
0
    def test_transaction_rollback(self):
        Database.connected = False
        Database.connect_to_database()

        Database.begin()
        Database.set_meta('random_foobar', 123, autocommit=False)
        Database.rollback()

        self.assertEqual(42, Database.get_meta('random_foobar', default=42,
                                               type=int))
Beispiel #14
0
    def test_contest_started(self):
        Database.add_task("poldo", "", "", 42, 1)
        Database.set_meta("start_time", 1234)

        res = self.handler.get_contest()
        self.assertTrue(res["has_started"])
        self.assertEqual(
            datetime.datetime.fromtimestamp(1234).isoformat(),
            res["start_time"])
        self.assertEqual(1, len(res["tasks"]))
        self.assertEqual("poldo", res["tasks"][0]["name"])
Beispiel #15
0
    def test_status(self):
        Database.set_meta("start_time", 1234)
        res = self.admin_handler.status(admin_token="ADMIN-TOKEN",
                                        _ip="1.2.3.4")

        start_time = dateutil.parser.parse(res["start_time"])

        start_time_db = datetime.fromtimestamp(
            Database.get_meta("start_time", type=int), timezone.utc)
        self.assertEqual(start_time, start_time_db)
        self.assertEqual(0, Database.get_meta("extra_time", default=0))
Beispiel #16
0
    def test_status(self):
        Database.set_meta('start_time', 1234)
        res = self.admin_handler.status(admin_token='ADMIN-TOKEN',
                                        _ip='1.2.3.4')

        start_time = int(
            datetime.datetime.strptime(res["start_time"],
                                       "%Y-%m-%dT%H:%M:%S").timestamp())

        self.assertEqual(start_time, Database.get_meta('start_time', type=int))
        self.assertEqual(0, Database.get_meta('extra_time', default=0))
Beispiel #17
0
    def test_dictify(self):
        Database.connected = False
        Database.connect_to_database()

        Database.set_meta("random_key", "random_value")
        Database.c.execute("SELECT * FROM metadata WHERE key = 'random_key'")
        dct = Database.dictify(all=False)

        self.assertDictEqual({
            "key": "random_key",
            "value": "random_value"
        }, dct)
    def extract_contest(token):
        """
        Decrypt and extract the contest and store the used admin token in the
        database
        """

        if "-" not in token:
            BaseHandler.raise_exc(Forbidden, "WRONG_PASSWORD",
                                  "The provided password is malformed")

        try:
            username, password = token.split("-", 1)
            secret, scrambled_password = decode_data(password, SECRET_LEN)
            file_password = recover_file_password(username, secret,
                                                  scrambled_password)
        except ValueError:
            BaseHandler.raise_exc(Forbidden, "WRONG_PASSWORD",
                                  "The provided password is malformed")
        try:
            with open(Config.encrypted_file, "rb") as encrypted_file:
                encrypted_data = encrypted_file.read()
                decrypted_data = decode(file_password, encrypted_data)
                with open(Config.decrypted_file, "wb") as decrypted_file:
                    decrypted_file.write(decrypted_data)
        except FileNotFoundError:
            BaseHandler.raise_exc(NotFound, "NOT_FOUND",
                                  "The contest pack was not uploaded yet")
        except nacl.exceptions.CryptoError:
            BaseHandler.raise_exc(Forbidden, "WRONG_PASSWORD",
                                  "The provided password is wrong")
        except OSError as ex:
            BaseHandler.raise_exc(InternalServerError, "FAILED", str(ex))

        zip_abs_path = os.path.realpath(Config.decrypted_file)
        wd = os.getcwd()
        try:
            os.makedirs(Config.contest_path, exist_ok=True)
            os.chdir(Config.contest_path)
            with zipfile.ZipFile(zip_abs_path) as f:
                f.extractall()
            real_yaml = os.path.join("__users__", username + ".yaml")
            if not os.path.exists(real_yaml):
                BaseHandler.raise_exc(Forbidden, "WRONG_PASSWORD",
                                      "Invalid username for the given pack")
            os.symlink(real_yaml, "contest.yaml")
            Logger.info("CONTEST", "Contest extracted")
        except zipfile.BadZipFile as ex:
            BaseHandler.raise_exc(Forbidden, "FAILED", str(ex))
        finally:
            os.chdir(wd)

        Database.set_meta("admin_token", token)
Beispiel #19
0
 def set_extra_time(self, extra_time: int, user):
     """
     POST /admin/set_extra_time
     """
     if user is None:
         Database.set_meta("extra_time", extra_time)
         Logger.info("ADMIN", "Global extra time set to %d" % extra_time)
     else:
         Logger.info(
             "ADMIN", "Extra time for user %s set to %d" %
             (user["token"], extra_time))
         Database.set_extra_time(user["token"], extra_time)
     return {}
Beispiel #20
0
    def start(self):
        """
        POST /admin/start
        """
        if Database.get_meta("start_time", default=None, type=int) is not None:
            BaseHandler.raise_exc(Forbidden, "FORBIDDEN",
                                  "Contest has already been started!")

        start_time = int(time.time())
        Database.set_meta("start_time", start_time)
        Logger.info("CONTEST", "Contest started")
        return BaseHandler.format_dates({"start_time": start_time},
                                        fields=["start_time"])
    def test_window_end_time(self):
        Database.set_meta("start_time", 1000)
        Database.set_meta("contest_duration", 150)
        Database.set_meta("window_duration", 100)
        Database.set_meta("extra_time", 20)

        self.assertEqual(BaseHandler.get_window_end_time(10, 20), 1130)
        self.assertEqual(BaseHandler.get_window_end_time(0, 0), 1100)
    def test_end_time(self):
        Database.set_meta("start_time", 1000)
        Database.set_meta("contest_duration", 150)
        Database.set_meta("extra_time", 20)

        self.assertEqual(BaseHandler.get_end_time(20), 1190)
        self.assertEqual(BaseHandler.get_end_time(0), 1170)
    def test_window_end_time_no_window(self):
        Database.set_meta("start_time", 1000)
        Database.set_meta("contest_duration", 150)
        # Database.set_meta("window_duration", nope)
        Database.set_meta("extra_time", 20)

        self.assertEqual(BaseHandler.get_window_end_time(20, 42), None)
Beispiel #24
0
    def start(self, start_time: str):
        """
        POST /admin/start
        """
        previous_start = Database.get_meta("start_time", type=int)
        now = int(time.time())
        if previous_start and now > previous_start:
            BaseHandler.raise_exc(Forbidden, "FORBIDDEN",
                                  "Contest has already been started!")

        actual_start = None
        if start_time == "reset":
            Database.del_meta("start_time")
            return {"start_time": None}
        elif start_time == "now":
            actual_start = now
        else:
            actual_start = dateutil.parser.parse(start_time).timestamp()
        Database.set_meta("start_time", int(actual_start))
        Logger.info("CONTEST", "Contest starts at " + str(actual_start))
        return BaseHandler.format_dates({"start_time": actual_start},
                                        fields=["start_time"])
    def test_get_user_windowed_partial_window(self):
        now = int(datetime.utcnow().timestamp())
        Database.set_meta("start_time", now)
        Database.set_meta("contest_duration", 1000)
        Database.set_meta("window_duration", 100)

        Database.add_user("token", "", "")
        Database.set_start_delay("token", 990)
        Database.add_task("poldo", "", "", 42, 1)
        Database.add_user_task("token", "poldo")
        Database.add_input("inputid", "token", "poldo", 1, "/path", 42)
        Database.set_user_attempt("token", "poldo", 1)

        res = self.handler.get_user(token="token", _ip="1.1.1.1")
        end_time = datetime.fromtimestamp(now + 1000, timezone.utc).isoformat()
        self.assertEqual(end_time, res["end_time"])
Beispiel #26
0
    def test_get_user_windowed_almost_finished(self):
        now = int(datetime.datetime.now().timestamp())
        Database.set_meta("start_time", now - 90)
        Database.set_meta("contest_duration", 1000)
        Database.set_meta("window_duration", 100)

        Database.add_user("token", "", "")
        Database.set_start_delay("token", 10)
        Database.add_task("poldo", "", "", 42, 1)
        Database.add_user_task("token", "poldo")
        Database.add_input("inputid", "token", "poldo", 1, "/path", 42)
        Database.set_user_attempt("token", "poldo", 1)

        res = self.handler.get_user(token="token", _ip="1.1.1.1")
        end_time = datetime.datetime.fromtimestamp(now + 20).strftime(
            '%Y-%m-%dT%H:%M:%S')
        self.assertEqual(end_time, res["end_time"])
    def test_get_user(self):
        now = int(datetime.utcnow().timestamp())
        Database.set_meta("start_time", now)
        Database.set_meta("contest_duration", 1000)

        Database.set_meta("extra_time", 50)
        Database.add_user("token", "", "")
        Database.set_extra_time("token", 30)
        Database.add_task("poldo", "", "", 42, 1)
        Database.add_user_task("token", "poldo")
        Database.add_input("inputid", "token", "poldo", 1, "/path", 42)
        Database.set_user_attempt("token", "poldo", 1)

        res = self.handler.get_user(token="token", _ip="1.1.1.1")
        end_time = datetime.fromtimestamp(now + 1080, timezone.utc).isoformat()
        self.assertEqual(end_time, res["end_time"])
        self.assertEqual("poldo", res["tasks"]["poldo"]["name"])
        self.assertEqual("inputid",
                         res["tasks"]["poldo"]["current_input"]["id"])
    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)
Beispiel #29
0
 def test_drop_contest_loaded_wrong_token(self):
     Utils.setup_encrypted_file()
     Database.set_meta("admin_token", "UHUHU-HUHU")
     with self.assertRaises(Forbidden):
         self.admin_handler.drop_contest("LALLA-BALALLA")
 def start_contest(since=5, duration=100):
     Database.set_meta("start_time",
                       int(datetime.datetime.now().timestamp()) - since)
     Database.set_meta("contest_duration", duration)