def test_register_ip_submission(self):
     self._insert_data()
     Database.add_submission("submissionid", "inputid", "outputid",
                             "sourceid", 42)
     self.register_ip(submission_id="submissionid", _ip="1.1.1.1")
     users = Database.get_users()
     self.assertEqual("1.1.1.1", users[0]["ip"][0]["ip"])
Example #2
0
    def test_submit(self, g_f_s_mock, g_i_mock):
        Utils.start_contest()
        self._insert_data()
        self.handler.generate_input(token='token', task='poldo', _ip='1.1.1.1')

        Database.c.execute(
            "INSERT INTO outputs (id, input, path, size, result) "
            "VALUES ('outputid', 'inputid', '/output', 42,"
            ":result)", {
                "result":
                b'{\"score\":0.5,\"feedback\":{\"a\":1},'
                b'\"validation\":{\"b\":2}}'
            })
        Database.c.execute("INSERT INTO sources (id, input, path, size) "
                           "VALUES ('sourceid', 'inputid', '/source', 42)")

        response = self.handler.submit(output_id='outputid',
                                       source_id='sourceid',
                                       _ip='1.1.1.1')
        self.assertEqual("token", response["token"])
        self.assertEqual("poldo", response["task"])
        self.assertEqual(21, response["score"])
        self.assertEqual("inputid", response["input"]["id"])
        self.assertEqual("sourceid", response["source"]["id"])
        self.assertEqual("outputid", response["output"]["id"])
        self.assertEqual(1, response["feedback"]["a"])
        self.assertEqual(2, response["output"]["validation"]["b"])

        user_task = Database.get_user_task("token", "poldo")
        self.assertEqual(21, user_task["score"])
        self.assertEqual(response["id"],
                         Database.get_submission(response["id"])["id"])
Example #3
0
def analyze_pack(pack, workdir, token, all, source_only, no_group_venue,
                 outdir):
    packname = os.path.basename(pack)[:4]
    if packname[3] == "0":
        packname = packname[:3]
    with common.extract_and_connect(pack, workdir):
        users = Database.get_users()
        if token:
            users = list(filter(lambda u: u["token"] in token, users))
        if not users:
            return False
        for user in users:
            token = user["token"]
            print("Found user %s %s" % (user["name"], user["surname"]))
            tasks = common.get_tasks()
            num_submissions = 0
            for task in tasks:
                submissions = Database.get_submissions(token, task)
                num_submissions += len(submissions)
                if no_group_venue:
                    taskdir = os.path.join(outdir, task, token)
                else:
                    taskdir = os.path.join(outdir, packname, task, token)
                os.makedirs(taskdir, exist_ok=True)
                if not all:
                    best = max(submissions,
                               key=lambda x: x["score"],
                               default=None)
                    if best:
                        submissions = [best]
                for submission in submissions:
                    store_submission(submission, taskdir, workdir, source_only)
            print("    > %d submissions" % num_submissions, file=sys.stderr)
        return len(token) == 1 and num_submissions > 0
Example #4
0
    def test_get_meta_default(self):
        Database.connected = False
        Database.connect_to_database()

        meta = Database.get_meta("this_key_doesnt_exist",
                                 "default_value_is_cool")
        self.assertEqual("default_value_is_cool", meta)
Example #5
0
 def _ensure_contest_running(token=None):
     """
     Makes sure that the contest is running for the user, if any. If the user has a time window it is also checked.
     :param token: The optional token of the user.
     """
     extra_time = None
     start_delay = None
     if token:
         Validators._ensure_window_start(token)
         user = Database.get_user(token)
         if user:
             extra_time = user["extra_time"]
             start_delay = user["contest_start_delay"]
     if Database.get_meta("start_time") is None:
         BaseHandler.raise_exc(Forbidden, "FORBIDDEN",
                               "The contest has not started yet")
     contest_end = BaseHandler.get_end_time(extra_time)
     window_end = BaseHandler.get_window_end_time(extra_time, start_delay)
     now = time.time()
     # check the contest is not finished
     if contest_end < now:
         BaseHandler.raise_exc(Forbidden, "FORBIDDEN",
                               "The contest has ended")
     # if a window is present check it's not finished
     if window_end and window_end < now:
         BaseHandler.raise_exc(Forbidden, "FORBIDDEN",
                               "Your window has ended")
    def prepare_test(load_config=True, connect_database=True,
                     connect_logger=True):
        config_file_name = Utils.new_tmp_file()
        log_file_name = Utils.new_tmp_file()
        db_file_name = Utils.new_tmp_file()
        contest_dir = Utils.new_tmp_dir("contest", create=False)

        with open(config_file_name, 'w') as file:
            file.write("logfile: %s\n"
                       "db: %s\n"
                       "storedir: %s\n"
                       "contest_path: %s\n" % (log_file_name, db_file_name,
                                               Utils.new_tmp_dir(),
                                               contest_dir))

        if load_config:
            Config.loaded = False
            Config.set_config_file(config_file_name)
        if connect_logger:
            Logger.connected = False
            Logger.connect_to_database()
            Logger.set_log_level("WARNING")
        if connect_database:
            Database.connected = False
            Database.connect_to_database()
Example #7
0
    def upload_output(self, input, file):
        """
        POST /upload_output
        """
        output_id = Database.gen_id()
        try:
            path = StorageManager.new_output_file(output_id, file["name"])
        except ValueError:
            BaseHandler.raise_exc(BadRequest, "INVALID_FILENAME",
                                  "The provided file has an invalid name")
        StorageManager.save_file(path, file["content"])
        file_size = StorageManager.get_file_size(path)

        try:
            result = ContestManager.evaluate_output(input["task"],
                                                    input["path"], path)
        except:
            BaseHandler.raise_exc(InternalServerError, "INTERNAL_ERROR",
                                  "Failed to evaluate the output")

        Database.add_output(output_id, input["id"], path, file_size, result)
        Logger.info(
            "UPLOAD",
            "User %s has uploaded the output %s" % (input["token"], output_id))
        return InfoHandler.patch_output(Database.get_output(output_id))
Example #8
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)
    def upload_source(self, input, file):
        """
        POST /upload_source
        """
        alerts = []
        if get_exeflags(file["content"]):
            alerts.append({
                "severity": "warning",
                "message": "You have submitted an executable! Please send the "
                           "source code."
            })
            Logger.info("UPLOAD",
                        "User %s has uploaded an executable" % input["token"])
        if not alerts:
            alerts.append({
                "severity": "success",
                "message": "Source file uploaded correctly."
            })

        source_id = Database.gen_id()
        try:
            path = StorageManager.new_source_file(source_id, file["name"])
        except ValueError:
            BaseHandler.raise_exc(BadRequest, "INVALID_FILENAME",
                                  "The provided file has an invalid name")

        StorageManager.save_file(path, file["content"])
        file_size = StorageManager.get_file_size(path)

        Database.add_source(source_id, input["id"], path, file_size)
        Logger.info("UPLOAD", "User %s has uploaded the source %s" % (
            input["token"], source_id))
        output = BaseHandler.format_dates(Database.get_source(source_id))
        output["validation"] = {"alerts": alerts}
        return output
Example #10
0
    def download_results(self):
        """
        POST /admin/download_pack
        """
        Logger.info("ADMIN", "Creating zip file")
        zip_directory = os.path.join(Config.storedir, "zips",
                                     Database.gen_id())
        os.makedirs(zip_directory, exist_ok=True)
        zipf_name = ("results-" +
                     Database.get_meta("admin_token").split("-", 1)[0] + "-" +
                     time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime()) +
                     ".zip")
        zipf_name = os.path.join(zip_directory, zipf_name)
        command = ("zip -r '" + zipf_name + "' db.sqlite3* log.sqlite3* "
                   "files/input files/output "
                   "files/source /version* "
                   "/proc/cpuinfo* "
                   "/var/log/nginx")

        try:
            gevent.subprocess.check_output(command,
                                           shell=True,
                                           stderr=subprocess.STDOUT)
        except subprocess.CalledProcessError as e:
            Logger.error("ADMIN", "Zip error: %s" % e.output)
            raise e
        return {
            "path": os.path.relpath(zipf_name, Config.storedir)
        }  # pragma: nocover
Example #11
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"
         })
Example #12
0
 def test_drop_contest_not_deletable(self):
     Utils.setup_encrypted_file()
     Database.del_meta("admin_token")
     with open(Config.encrypted_file, "wb") as f:
         f.write(Utils.build_pack(ruamel.yaml.dump({"deletable": False})))
     with self.assertRaises(Forbidden):
         self.admin_handler.drop_contest(Utils.ZIP_TOKEN)
Example #13
0
    def test_get_meta_default(self):
        Database.connected = False
        Database.connect_to_database()

        meta = Database.get_meta('this_key_doesnt_exist',
                                 'default_value_is_cool')
        self.assertEqual('default_value_is_cool', meta)
Example #14
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
Example #15
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())
Example #16
0
    def test_input_invalid_params(self):
        Database.connected = False
        Database.connect_to_database()

        with self.assertRaises(ValueError) as ex:
            Database.get_input()

        self.assertEqual("Invalid parameters to get_input",
                         ex.exception.args[0])
Example #17
0
 def handle(*args, **kwargs):
     token = Validators._guess_token(**kwargs)
     ip = kwargs["_ip"]
     if token is not None and Database.get_user(token) is not None:
         if Database.register_ip(token, ip):
             Logger.info(
                 "LOGIN", "User %s logged in from %s for the first "
                 "time" % (token, ip))
     del kwargs["_ip"]
     return handler(*args, **kwargs)
Example #18
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)
Example #19
0
    def test_get_submissions_invalid_task(self):
        Utils.start_contest()
        Database.add_user("token", "", "")
        with self.assertRaises(Forbidden) as ex:
            self.handler.get_submissions(token="token",
                                         task="invalid task",
                                         _ip="1.1.1.1")

        response = ex.exception.response.data.decode()
        self.assertIn("No such task", response)
Example #20
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")
Example #21
0
 def test_upload_pack_already_uploaded(self):
     path = os.path.join(Utils.new_tmp_dir(), "pack.zip.enc")
     with open(path, "wb") as f:
         f.write(b"hola!")
     Config.encrypted_file = path
     Database.del_meta("admin_token")
     with self.assertRaises(Forbidden):
         self.admin_handler.upload_pack(file={
             "content": "foobar".encode(),
             "name": "pack.zip.enc"
         })
Example #22
0
    def test_upload_invalid_pack(self):
        enc_path = os.path.join(Utils.new_tmp_dir(), "pack.zip.enc")
        Config.encrypted_file = enc_path

        Database.del_meta("admin_token")
        with self.assertRaises(Forbidden):
            self.admin_handler.upload_pack(file={
                "content": b"totally not a pack",
                "name": "pack.zip.enc"
            })
        self.assertFalse(os.path.exists(enc_path))
Example #23
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"])
Example #24
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))
Example #25
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))
Example #26
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)
Example #27
0
 def test_drop_contest(self):
     Utils.setup_encrypted_file()
     Database.del_meta("admin_token")
     with open(Config.encrypted_file, "wb") as f:
         f.write(Utils.build_pack(ruamel.yaml.dump({"deletable": True})))
     self.admin_handler.drop_contest(Utils.ZIP_TOKEN)
     self.assertFalse(os.path.exists(Config.storedir))
     self.assertFalse(os.path.exists(Config.statementdir))
     self.assertFalse(os.path.exists(Config.contest_path))
     self.assertFalse(os.path.exists(Config.encrypted_file))
     self.assertFalse(os.path.exists(Config.decrypted_file))
     self.assertTrue(os.path.exists(Config.db))
Example #28
0
    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)
Example #29
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))
Example #30
0
    def test_do_write_rollback(self):
        Database.connected = False
        Database.connect_to_database()

        with patch("terry.database.Database.commit",
                   side_effect=ValueError("Ops...")):
            with self.assertRaises(ValueError):
                Database.do_write(True, """
                    INSERT INTO metadata (key, value) 
                    VALUES (:key, :value)
                """, {"key": "ciao", "value": "mondo"})

        self.assertIsNone(Database.get_meta("ciao"))