Ejemplo n.º 1
0
class TestEndpointsHandlerWithAuth(AsyncHTTPTestCase):
    @classmethod
    def setUpClass(cls):
        prefix = "__TestEndpointsHandlerWithAuth_"
        # create password file
        cls.pwd_file = tempfile.NamedTemporaryFile(mode="w+t",
                                                   prefix=prefix,
                                                   suffix=".txt",
                                                   delete=False)
        username = "******"
        password = "******"
        cls.pwd_file.write(f"{username} {hash_password(username, password)}")
        cls.pwd_file.close()

        # create state.ini dir and file
        cls.state_dir = tempfile.mkdtemp(prefix=prefix)
        cls.state_file = open(os.path.join(cls.state_dir, "state.ini"), "w+")
        cls.state_file.write("[Service Info]\n"
                             "Name = TabPy Serve\n"
                             "Description = \n"
                             "Creation Time = 0\n"
                             "Access-Control-Allow-Origin = \n"
                             "Access-Control-Allow-Headers = \n"
                             "Access-Control-Allow-Methods = \n"
                             "\n"
                             "[Query Objects Service Versions]\n"
                             "\n"
                             "[Query Objects Docstrings]\n"
                             "\n"
                             "[Meta]\n"
                             "Revision Number = 1\n")
        cls.state_file.close()

        # create config file
        cls.config_file = tempfile.NamedTemporaryFile(mode="w+t",
                                                      prefix=prefix,
                                                      suffix=".conf",
                                                      delete=False)
        cls.config_file.write("[TabPy]\n"
                              f"TABPY_PWD_FILE = {cls.pwd_file.name}\n"
                              f"TABPY_STATE_PATH = {cls.state_dir}")
        cls.config_file.close()

    @classmethod
    def tearDownClass(cls):
        os.remove(cls.pwd_file.name)
        os.remove(cls.state_file.name)
        os.remove(cls.config_file.name)
        os.rmdir(cls.state_dir)

    def get_app(self):
        self.app = TabPyApp(self.config_file.name)
        return self.app._create_tornado_web_app()

    def test_no_creds_required_auth_fails(self):
        response = self.fetch("/endpoints")
        self.assertEqual(401, response.code)

    def test_invalid_creds_fails(self):
        response = self.fetch(
            "/endpoints",
            method="GET",
            headers={
                "Authorization":
                "Basic {}".format(
                    base64.b64encode(
                        "user:wrong_password".encode("utf-8")).decode("utf-8"))
            },
        )
        self.assertEqual(401, response.code)

    def test_valid_creds_pass(self):
        response = self.fetch(
            "/endpoints",
            method="GET",
            headers={
                "Authorization":
                "Basic {}".format(
                    base64.b64encode(
                        "username:password".encode("utf-8")).decode("utf-8"))
            },
        )
        self.assertEqual(200, response.code)
 def get_app(self):
     if hasattr(self, 'config_file') and hasattr(self.config_file, 'name'):
         self.app = TabPyApp(self.config_file.name)
     else:
         self.app = TabPyApp()
     return self.app._create_tornado_web_app()
Ejemplo n.º 3
0
 def get_app(self):
     self.app = TabPyApp(None)
     return self.app._create_tornado_web_app()
Ejemplo n.º 4
0
 def get_app(self):
     self.app = TabPyApp(self.config_file.name)
     return self.app._create_tornado_web_app()
Ejemplo n.º 5
0
class TestServiceInfoHandlerWithAuth(AsyncHTTPTestCase):
    @classmethod
    def setUpClass(cls):
        prefix = "__TestServiceInfoHandlerWithAuth_"
        # create password file
        cls.pwd_file = tempfile.NamedTemporaryFile(prefix=prefix,
                                                   suffix=".txt",
                                                   delete=False)
        cls.pwd_file.write(b"username password")
        cls.pwd_file.close()

        # create state.ini dir and file
        cls.state_dir = tempfile.mkdtemp(prefix=prefix)
        cls.state_file = open(os.path.join(cls.state_dir, "state.ini"), "w+")
        cls.state_file.write("[Service Info]\n"
                             "Name = TabPy Serve\n"
                             "Description = \n"
                             "Creation Time = 0\n"
                             "Access-Control-Allow-Origin = \n"
                             "Access-Control-Allow-Headers = \n"
                             "Access-Control-Allow-Methods = \n"
                             "\n"
                             "[Query Objects Service Versions]\n"
                             "\n"
                             "[Query Objects Docstrings]\n"
                             "\n"
                             "[Meta]\n"
                             "Revision Number = 1\n")
        cls.state_file.close()

        # create config file
        cls.config_file = tempfile.NamedTemporaryFile(prefix=prefix,
                                                      suffix=".conf",
                                                      delete=False)
        cls.config_file.write(
            bytes(
                "[TabPy]\n"
                f"TABPY_PWD_FILE = {cls.pwd_file.name}\n"
                f"TABPY_STATE_PATH = {cls.state_dir}",
                "utf-8",
            ))
        cls.config_file.close()

    @classmethod
    def tearDownClass(cls):
        os.remove(cls.pwd_file.name)
        os.remove(cls.state_file.name)
        os.remove(cls.config_file.name)
        os.rmdir(cls.state_dir)

    def get_app(self):
        self.app = TabPyApp(self.config_file.name)
        return self.app._create_tornado_web_app()

    def test_given_tabpy_server_with_auth_expect_correct_info_response(self):
        response = self.fetch("/info")
        self.assertEqual(response.code, 200)
        actual_response = json.loads(response.body)
        expected_response = _create_expected_info_response(
            self.app.settings, self.app.tabpy_state)

        self.assertDictEqual(actual_response, expected_response)
        self.assertTrue("versions" in actual_response)
        versions = actual_response["versions"]
        self.assertTrue("v1" in versions)
        v1 = versions["v1"]
        self.assertTrue("features" in v1)
        features = v1["features"]
        self.assertDictEqual(
            {
                "authentication": {
                    "methods": {
                        "basic-auth": {}
                    },
                    "required": True
                }
            },
            features,
        )
Ejemplo n.º 6
0
class TestEvaluationPlainHandlerWithAuth(AsyncHTTPTestCase):
    @classmethod
    def setUpClass(cls):
        cls.patcher = patch(
            "tabpy.tabpy_server.app.app.TabPyApp._parse_cli_arguments",
            return_value=Namespace(config=None),
        )
        cls.patcher.start()

        prefix = "__TestEvaluationPlainHandlerWithAuth_"
        # create password file
        cls.pwd_file = tempfile.NamedTemporaryFile(
            mode="w+t", prefix=prefix, suffix=".txt", delete=False
        )
        username = "******"
        password = "******"
        cls.pwd_file.write(f"{username} {hash_password(username, password)}\n")
        cls.pwd_file.close()

        # create state.ini dir and file
        cls.state_dir = tempfile.mkdtemp(prefix=prefix)
        cls.state_file = open(os.path.join(cls.state_dir, "state.ini"), "w+")
        cls.state_file.write(
            "[Service Info]\n"
            "Name = TabPy Serve\n"
            "Description = \n"
            "Creation Time = 0\n"
            "Access-Control-Allow-Origin = \n"
            "Access-Control-Allow-Headers = \n"
            "Access-Control-Allow-Methods = \n"
            "\n"
            "[Query Objects Service Versions]\n"
            "\n"
            "[Query Objects Docstrings]\n"
            "\n"
            "[Meta]\n"
            "Revision Number = 1\n"
        )
        cls.state_file.close()

        # create config file
        cls.config_file = tempfile.NamedTemporaryFile(
            mode="w+t", prefix=prefix, suffix=".conf", delete=False
        )
        cls.config_file.write(
            "[TabPy]\n"
            f"TABPY_PWD_FILE = {cls.pwd_file.name}\n"
            f"TABPY_STATE_PATH = {cls.state_dir}"
        )
        cls.config_file.close()

        cls.script = (
            '{"data":{"_arg1":[2,3],"_arg2":[3,-1]},'
            '"script":"res=[]\\nfor i in range(len(_arg1)):\\n  '
            'res.append(_arg1[i] * _arg2[i])\\nreturn res"}'
        )

        cls.script_not_present = (
            '{"data":{"_arg1":[2,3],"_arg2":[3,-1]},'
            '"":"res=[]\\nfor i in range(len(_arg1)):\\n  '
            'res.append(_arg1[i] * _arg2[i])\\nreturn res"}'
        )

        cls.args_not_present = (
            '{"script":"res=[]\\nfor i in range(len(_arg1)):\\n  '
            'res.append(_arg1[i] * _arg2[i])\\nreturn res"}'
        )

        cls.args_not_sequential = (
            '{"data":{"_arg1":[2,3],"_arg3":[3,-1]},'
            '"script":"res=[]\\nfor i in range(len(_arg1)):\\n  '
            'res.append(_arg1[i] * _arg3[i])\\nreturn res"}'
        )

        cls.nan_coverts_to_null =\
            '{"data":{"_arg1":[2,3],"_arg2":[3,-1]},'\
            '"script":"return [float(1), float(\\"NaN\\"), float(2)]"}'

        cls.script_returns_none = (
            '{"data":{"_arg1":[2,3],"_arg2":[3,-1]},'
            '"script":"return None"}'
        )

    @classmethod
    def tearDownClass(cls):
        cls.patcher.stop()
        os.remove(cls.pwd_file.name)
        os.remove(cls.state_file.name)
        os.remove(cls.config_file.name)
        os.rmdir(cls.state_dir)

    def get_app(self):
        self.app = TabPyApp(self.config_file.name)
        return self.app._create_tornado_web_app()

    def test_no_creds_required_auth_fails(self):
        response = self.fetch("/evaluate", method="POST", body=self.script)
        self.assertEqual(401, response.code)

    def test_invalid_creds_fails(self):
        response = self.fetch(
            "/evaluate",
            method="POST",
            body=self.script,
            headers={
                "Authorization": "Basic {}".format(
                    base64.b64encode("user:wrong_password".encode("utf-8")).decode(
                        "utf-8"
                    )
                )
            },
        )
        self.assertEqual(401, response.code)

    def test_valid_creds_pass(self):
        response = self.fetch(
            "/evaluate",
            method="POST",
            body=self.script,
            headers={
                "Authorization": "Basic {}".format(
                    base64.b64encode("username:password".encode("utf-8")).decode(
                        "utf-8"
                    )
                )
            },
        )
        self.assertEqual(200, response.code)

    def test_null_request(self):
        response = self.fetch("")
        self.assertEqual(404, response.code)

    def test_script_not_present(self):
        response = self.fetch(
            "/evaluate",
            method="POST",
            body=self.script_not_present,
            headers={
                "Authorization": "Basic {}".format(
                    base64.b64encode("username:password".encode("utf-8")).decode(
                        "utf-8"
                    )
                )
            },
        )
        self.assertEqual(400, response.code)

    def test_arguments_not_present(self):
        response = self.fetch(
            "/evaluate",
            method="POST",
            body=self.args_not_present,
            headers={
                "Authorization": "Basic {}".format(
                    base64.b64encode("username:password".encode("utf-8")).decode(
                        "utf-8"
                    )
                )

            },
        )
        self.assertEqual(500, response.code)

    def test_arguments_not_sequential(self):
        response = self.fetch(
            "/evaluate",
            method="POST",
            body=self.args_not_sequential,
            headers={
                "Authorization": "Basic {}".format(
                    base64.b64encode("username:password".encode("utf-8")).decode(
                        "utf-8"
                    )
                )
            },
        )
        self.assertEqual(400, response.code)

    def test_nan_converts_to_null(self):
        response = self.fetch(
            '/evaluate',
            method='POST',
            body=self.nan_coverts_to_null,
            headers={
                'Authorization': 'Basic {}'.
                format(
                    base64.b64encode('username:password'.encode('utf-8')).
                    decode('utf-8'))
            })
        self.assertEqual(200, response.code)
        self.assertEqual(b'[1.0, null, 2.0]', response.body)

    def test_script_returns_none(self):
        response = self.fetch(
            '/evaluate',
            method='POST',
            body=self.script_returns_none,
            headers={
                'Authorization': 'Basic {}'.
                format(
                    base64.b64encode('username:password'.encode('utf-8')).
                    decode('utf-8'))
            })
        self.assertEqual(200, response.code)
        self.assertEqual(b'null', response.body)
Ejemplo n.º 7
0
 def assertTabPyAppRaisesRuntimeError(self, expected_message):
     with self.assertRaises(RuntimeError) as err:
         TabPyApp(self.fp.name)
     self.assertEqual(err.exception.args[0], expected_message)
Ejemplo n.º 8
0
    def test_http(self):
        self.fp.write("[TabPy]\n" "TABPY_TRANSFER_PROTOCOL = http")
        self.fp.close()

        app = TabPyApp(self.fp.name)
        self.assertEqual(app.settings["transfer_protocol"], "http")
Ejemplo n.º 9
0
class TestEvaluationPlaneHandlerWithoutAuth(AsyncHTTPTestCase):
    @classmethod
    def setUpClass(cls):
        prefix = "__TestEvaluationPlaneHandlerWithoutAuth_"

        # create state.ini dir and file
        cls.state_dir = tempfile.mkdtemp(prefix=prefix)
        cls.state_file = open(os.path.join(cls.state_dir, "state.ini"), "w+")
        cls.state_file.write(
            "[Service Info]\n"
            "Name = TabPy Serve\n"
            "Description = \n"
            "Creation Time = 0\n"
            "Access-Control-Allow-Origin = \n"
            "Access-Control-Allow-Headers = \n"
            "Access-Control-Allow-Methods = \n"
            "\n"
            "[Query Objects Service Versions]\n"
            "\n"
            "[Query Objects Docstrings]\n"
            "\n"
            "[Meta]\n"
            "Revision Number = 1\n"
        )
        cls.state_file.close()

        cls.script = (
            '{"data":{"_arg1":[2,3],"_arg2":[3,-1]},'
            '"script":"res=[]\\nfor i in range(len(_arg1)):\\n  '
            'res.append(_arg1[i] * _arg2[i])\\nreturn res"}'
        )

        cls.script_not_present = (
            '{"data":{"_arg1":[2,3],"_arg2":[3,-1]},'
            '"":"res=[]\\nfor i in range(len(_arg1)):\\n  '
            'res.append(_arg1[i] * _arg2[i])\\nreturn res"}'
        )

        cls.args_not_present = (
            '{"script":"res=[]\\nfor i in range(len(_arg1)):\\n  '
            'res.append(_arg1[i] * _arg2[i])\\nreturn res"}'
        )

        cls.args_not_sequential = (
            '{"data":{"_arg1":[2,3],"_arg3":[3,-1]},'
            '"script":"res=[]\\nfor i in range(len(_arg1)):\\n  '
            'res.append(_arg1[i] * _arg3[i])\\nreturn res"}'
        )

        cls.nan_coverts_to_null =\
            '{"data":{"_arg1":[2,3],"_arg2":[3,-1]},'\
            '"script":"return [float(1), float(\\"NaN\\"), float(2)]"}'

        cls.script_returns_none = (
            '{"data":{"_arg1":[2,3],"_arg2":[3,-1]},'
            '"script":"return None"}'
        )

    @classmethod
    def tearDownClass(cls):
        os.remove(cls.state_file.name)
        os.rmdir(cls.state_dir)

    def get_app(self):
        self.app = TabPyApp(None)
        return self.app._create_tornado_web_app()

    def test_creds_no_auth_fails(self):
        response = self.fetch(
            "/evaluate",
            method="POST",
            body=self.script,
            headers={
                "Authorization": "Basic {}".format(
                    base64.b64encode("username:password".encode("utf-8")).decode(
                        "utf-8"
                    )
                )
            },
        )
        self.assertEqual(406, response.code)
Ejemplo n.º 10
0
class TestEvaluationPlaneHandlerDisabledWithAuth(AsyncHTTPTestCase):
    @classmethod
    def setUpClass(cls):
        prefix = "__TestEvaluationPlaneHandlerDisabledWithAuth_"

        # create password file
        cls.pwd_file = tempfile.NamedTemporaryFile(
            mode="w+t", prefix=prefix, suffix=".txt", delete=False
        )
        username = "******"
        password = "******"
        cls.pwd_file.write(f"{username} {hash_password(username, password)}\n")
        cls.pwd_file.close()

        # create state.ini dir and file
        cls.state_dir = tempfile.mkdtemp(prefix=prefix)
        cls.state_file = open(os.path.join(cls.state_dir, "state.ini"), "w+")
        cls.state_file.write(
            "[Service Info]\n"
            "Name = TabPy Serve\n"
            "Description = \n"
            "Creation Time = 0\n"
            "Access-Control-Allow-Origin = \n"
            "Access-Control-Allow-Headers = \n"
            "Access-Control-Allow-Methods = \n"
            "\n"
            "[Query Objects Service Versions]\n"
            "\n"
            "[Query Objects Docstrings]\n"
            "\n"
            "[Meta]\n"
            "Revision Number = 1\n"
        )
        cls.state_file.close()

        # create config file
        cls.config_file = tempfile.NamedTemporaryFile(
            mode="w+t", prefix=prefix, suffix=".conf", delete=False
        )
        cls.config_file.write(
            "[TabPy]\n"
            f"TABPY_PWD_FILE = {cls.pwd_file.name}\n"
            f"TABPY_STATE_PATH = {cls.state_dir}\n"
            f"TABPY_EVALUATE_ENABLE = false"
        )
        cls.config_file.close()

        cls.script = (
            '{"data":{"_arg1":[2,3],"_arg2":[3,-1]},'
            '"script":"res=[]\\nfor i in range(len(_arg1)):\\n  '
            'res.append(_arg1[i] * _arg2[i])\\nreturn res"}'
        )

    @classmethod
    def tearDownClass(cls):
        os.remove(cls.pwd_file.name)
        os.remove(cls.state_file.name)
        os.remove(cls.config_file.name)
        os.rmdir(cls.state_dir)

    def get_app(self):
        self.app = TabPyApp(self.config_file.name)
        return self.app._create_tornado_web_app()

    def test_evaluation_disabled_fails_with_invalid_creds(self):
        response = self.fetch(
            "/evaluate",
            method="POST",
            body=self.script,
            headers={
                "Authorization": "Basic {}".format(
                    base64.b64encode("user:wrong_password".encode("utf-8")).decode(
                        "utf-8"
                    )
                )
            },
        )
        self.assertEqual(401, response.code)

    def test_evaluation_disabled_fails_with_valid_creds(self):
        response = self.fetch(
            "/evaluate",
            method="POST",
            body=self.script,
            headers={
                "Authorization": "Basic {}".format(
                    base64.b64encode("username:password".encode("utf-8")).decode(
                        "utf-8"
                    )
                )
            },
        )
        self.assertEqual(404, response.code)
Ejemplo n.º 11
0
def main():
    from tabpy.tabpy_server.app.app import TabPyApp
    app = TabPyApp()
    app.run()
Ejemplo n.º 12
0
class TestServiceInfoHandlerWithAuth(AsyncHTTPTestCase):
    @classmethod
    def setUpClass(cls):
        prefix = '__TestServiceInfoHandlerWithAuth_'
        # create password file
        cls.pwd_file = tempfile.NamedTemporaryFile(prefix=prefix,
                                                   suffix='.txt',
                                                   delete=False)
        cls.pwd_file.write(b'username password')
        cls.pwd_file.close()

        # create state.ini dir and file
        cls.state_dir = tempfile.mkdtemp(prefix=prefix)
        cls.state_file = open(os.path.join(cls.state_dir, 'state.ini'), 'w+')
        cls.state_file.write('[Service Info]\n'
                             'Name = TabPy Serve\n'
                             'Description = \n'
                             'Creation Time = 0\n'
                             'Access-Control-Allow-Origin = \n'
                             'Access-Control-Allow-Headers = \n'
                             'Access-Control-Allow-Methods = \n'
                             '\n'
                             '[Query Objects Service Versions]\n'
                             '\n'
                             '[Query Objects Docstrings]\n'
                             '\n'
                             '[Meta]\n'
                             'Revision Number = 1\n')
        cls.state_file.close()

        # create config file
        cls.config_file = tempfile.NamedTemporaryFile(prefix=prefix,
                                                      suffix='.conf',
                                                      delete=False)
        cls.config_file.write(
            bytes(
                '[TabPy]\n'
                f'TABPY_PWD_FILE = {cls.pwd_file.name}\n'
                f'TABPY_STATE_PATH = {cls.state_dir}', 'utf-8'))
        cls.config_file.close()

    @classmethod
    def tearDownClass(cls):
        os.remove(cls.pwd_file.name)
        os.remove(cls.state_file.name)
        os.remove(cls.config_file.name)
        os.rmdir(cls.state_dir)

    def get_app(self):
        self.app = TabPyApp(self.config_file.name)
        return self.app._create_tornado_web_app()

    def test_given_tabpy_server_with_auth_expect_correct_info_response(self):
        response = self.fetch('/info')
        self.assertEqual(response.code, 200)
        actual_response = json.loads(response.body)
        expected_response = _create_expected_info_response(
            self.app.settings, self.app.tabpy_state)

        self.assertDictEqual(actual_response, expected_response)
        self.assertTrue('versions' in actual_response)
        versions = actual_response['versions']
        self.assertTrue('v1' in versions)
        v1 = versions['v1']
        self.assertTrue('features' in v1)
        features = v1['features']
        self.assertDictEqual(
            {
                'authentication': {
                    'methods': {
                        'basic-auth': {}
                    },
                    'required': True,
                }
            }, features)
Ejemplo n.º 13
0
 def test_no_state_ini_file_or_state_dir(self, mock_os, mock_path_exists,
                                         mock_psws, mock_management_util,
                                         mock_tabpy_state,
                                         mock_parse_arguments):
     TabPyApp(None)
     self.assertEqual(len(mock_os.makedirs.mock_calls), 1)
Ejemplo n.º 14
0
class TestEndpointHandlerWithAuth(AsyncHTTPTestCase):
    @classmethod
    def setUpClass(cls):
        cls.patcher = patch(
            'tabpy.tabpy_server.app.app.TabPyApp._parse_cli_arguments',
            return_value=Namespace(config=None))
        cls.patcher.start()

        prefix = '__TestEndpointHandlerWithAuth_'
        # create password file
        cls.pwd_file = tempfile.NamedTemporaryFile(mode='w+t',
                                                   prefix=prefix,
                                                   suffix='.txt',
                                                   delete=False)
        username = '******'
        password = '******'
        cls.pwd_file.write(f'{username} {hash_password(username, password)}')
        cls.pwd_file.close()

        # create state.ini dir and file
        cls.state_dir = tempfile.mkdtemp(prefix=prefix)
        cls.state_file = open(os.path.join(cls.state_dir, 'state.ini'), 'w+')
        cls.state_file.write('[Service Info]\n'
                             'Name = TabPy Serve\n'
                             'Description = \n'
                             'Creation Time = 0\n'
                             'Access-Control-Allow-Origin = \n'
                             'Access-Control-Allow-Headers = \n'
                             'Access-Control-Allow-Methods = \n'
                             '\n'
                             '[Query Objects Service Versions]\n'
                             '\n'
                             '[Query Objects Docstrings]\n'
                             '\n'
                             '[Meta]\n'
                             'Revision Number = 1\n')
        cls.state_file.close()

        # create config file
        cls.config_file = tempfile.NamedTemporaryFile(mode='w+t',
                                                      prefix=prefix,
                                                      suffix='.conf',
                                                      delete=False)
        cls.config_file.write('[TabPy]\n'
                              f'TABPY_PWD_FILE = {cls.pwd_file.name}\n'
                              f'TABPY_STATE_PATH = {cls.state_dir}')
        cls.config_file.close()

    @classmethod
    def tearDownClass(cls):
        cls.patcher.stop()
        os.remove(cls.pwd_file.name)
        os.remove(cls.state_file.name)
        os.remove(cls.config_file.name)
        os.rmdir(cls.state_dir)

    def get_app(self):
        self.app = TabPyApp(self.config_file.name)
        return self.app._create_tornado_web_app()

    def test_no_creds_required_auth_fails(self):
        response = self.fetch('/endpoints/anything')
        self.assertEqual(401, response.code)

    def test_invalid_creds_fails(self):
        response = self.fetch(
            '/endpoints/anything',
            method='GET',
            headers={
                'Authorization':
                'Basic {}'.format(
                    base64.b64encode(
                        'user:wrong_password'.encode('utf-8')).decode('utf-8'))
            })
        self.assertEqual(401, response.code)

    def test_valid_creds_pass(self):
        response = self.fetch(
            '/endpoints/',
            method='GET',
            headers={
                'Authorization':
                'Basic {}'.format(
                    base64.b64encode(
                        'username:password'.encode('utf-8')).decode('utf-8'))
            })
        self.assertEqual(200, response.code)

    def test_valid_creds_unknown_endpoint_fails(self):
        response = self.fetch(
            '/endpoints/unknown_endpoint',
            method='GET',
            headers={
                'Authorization':
                'Basic {}'.format(
                    base64.b64encode(
                        'username:password'.encode('utf-8')).decode('utf-8'))
            })
        self.assertEqual(404, response.code)
Ejemplo n.º 15
0
class TestEvaluationPlainHandlerWithAuth(AsyncHTTPTestCase):
    @classmethod
    def setUpClass(cls):
        cls.patcher = patch(
            'tabpy.tabpy_server.app.app.TabPyApp._parse_cli_arguments',
            return_value=Namespace(
                config=None))
        cls.patcher.start()

        prefix = '__TestEvaluationPlainHandlerWithAuth_'
        # create password file
        cls.pwd_file = tempfile.NamedTemporaryFile(
            mode='w+t', prefix=prefix, suffix='.txt', delete=False)
        username = '******'
        password = '******'
        cls.pwd_file.write(f'{username} {hash_password(username, password)}\n')
        cls.pwd_file.close()

        # create state.ini dir and file
        cls.state_dir = tempfile.mkdtemp(prefix=prefix)
        cls.state_file = open(os.path.join(cls.state_dir, 'state.ini'), 'w+')
        cls.state_file.write('[Service Info]\n'
                             'Name = TabPy Serve\n'
                             'Description = \n'
                             'Creation Time = 0\n'
                             'Access-Control-Allow-Origin = \n'
                             'Access-Control-Allow-Headers = \n'
                             'Access-Control-Allow-Methods = \n'
                             '\n'
                             '[Query Objects Service Versions]\n'
                             '\n'
                             '[Query Objects Docstrings]\n'
                             '\n'
                             '[Meta]\n'
                             'Revision Number = 1\n')
        cls.state_file.close()

        # create config file
        cls.config_file = tempfile.NamedTemporaryFile(
            mode='w+t', prefix=prefix, suffix='.conf', delete=False)
        cls.config_file.write(
            '[TabPy]\n'
            f'TABPY_PWD_FILE = {cls.pwd_file.name}\n'
            f'TABPY_STATE_PATH = {cls.state_dir}')
        cls.config_file.close()

        cls.script =\
            '{"data":{"_arg1":[2,3],"_arg2":[3,-1]},'\
            '"script":"res=[]\\nfor i in range(len(_arg1)):\\n  '\
            'res.append(_arg1[i] * _arg2[i])\\nreturn res"}'

        cls.script_not_present =\
            '{"data":{"_arg1":[2,3],"_arg2":[3,-1]},'\
            '"":"res=[]\\nfor i in range(len(_arg1)):\\n  '\
            'res.append(_arg1[i] * _arg2[i])\\nreturn res"}'

        cls.args_not_present =\
            '{"script":"res=[]\\nfor i in range(len(_arg1)):\\n  '\
            'res.append(_arg1[i] * _arg2[i])\\nreturn res"}'

        cls.args_not_sequential =\
            '{"data":{"_arg1":[2,3],"_arg3":[3,-1]},'\
            '"script":"res=[]\\nfor i in range(len(_arg1)):\\n  '\
            'res.append(_arg1[i] * _arg3[i])\\nreturn res"}'

    @classmethod
    def tearDownClass(cls):
        cls.patcher.stop()
        os.remove(cls.pwd_file.name)
        os.remove(cls.state_file.name)
        os.remove(cls.config_file.name)
        os.rmdir(cls.state_dir)

    def get_app(self):
        self.app = TabPyApp(self.config_file.name)
        return self.app._create_tornado_web_app()

    def test_no_creds_required_auth_fails(self):
        response = self.fetch(
            '/evaluate',
            method='POST',
            body=self.script)
        self.assertEqual(401, response.code)

    def test_invalid_creds_fails(self):
        response = self.fetch(
            '/evaluate',
            method='POST',
            body=self.script,
            headers={
                'Authorization': 'Basic {}'.
                format(
                    base64.b64encode('user:wrong_password'.encode('utf-8')).
                    decode('utf-8'))
            })
        self.assertEqual(401, response.code)

    def test_valid_creds_pass(self):
        response = self.fetch(
            '/evaluate',
            method='POST',
            body=self.script,
            headers={
                'Authorization': 'Basic {}'.
                format(
                    base64.b64encode('username:password'.encode('utf-8')).
                    decode('utf-8'))
            })
        self.assertEqual(200, response.code)

    def test_null_request(self):
        response = self.fetch('')
        self.assertEqual(404, response.code)

    def test_script_not_present(self):
        response = self.fetch(
            '/evaluate',
            method='POST',
            body=self.script_not_present,
            headers={
                'Authorization': 'Basic {}'.
                format(
                    base64.b64encode('username:password'.encode('utf-8')).
                    decode('utf-8'))
            })
        self.assertEqual(400, response.code)

    def test_arguments_not_present(self):
        response = self.fetch(
            '/evaluate',
            method='POST',
            body=self.args_not_present,
            headers={
                'Authorization': 'Basic {}'.
                format(
                    base64.b64encode('username:password'.encode('utf-8')).
                    decode('utf-8'))
            })
        self.assertEqual(500, response.code)

    def test_arguments_not_sequential(self):
        response = self.fetch(
            '/evaluate',
            method='POST',
            body=self.args_not_sequential,
            headers={
                'Authorization': 'Basic {}'.
                format(
                    base64.b64encode('username:password'.encode('utf-8')).
                    decode('utf-8'))
            })
        self.assertEqual(400, response.code)