diff --git a/picasso/api/controllers/runnable.py b/picasso/api/controllers/runnable.py index a183a7d..6ab9610 100644 --- a/picasso/api/controllers/runnable.py +++ b/picasso/api/controllers/runnable.py @@ -18,6 +18,7 @@ from aioservice.http import controller from aioservice.http import requests from ...common import config +from ...models import app as app_model class RunnableMixin(object): @@ -88,9 +89,29 @@ class PublicRunnableV1Controller(controller.ServiceController, description: successful operation. Return "runnable" JSON "404": description: App does not exist - "404": - description: App route does not exist + "403": + description: Unable to execute private route """ + app = request.match_info.get('app') + path = request.match_info.get('route') + routes = await app_model.Routes.find_by(app_name=app, path=path) + + if not routes: + return web.json_response(data={ + "error": { + "message": "Route {0} not found".format(app), + } + }, status=404) + route = routes.pop() + + if not route.public: + return web.json_response(data={ + "error": { + "message": "Unable to execute private " + "route {0}".format(path) + } + }, status=403) + return await super(PublicRunnableV1Controller, self).run(request, **kwargs) diff --git a/picasso/tests/common/routes.py b/picasso/tests/common/routes.py index 89ead7f..d70077b 100644 --- a/picasso/tests/common/routes.py +++ b/picasso/tests/common/routes.py @@ -17,14 +17,19 @@ import json as jsonlib @contextlib.contextmanager -def setup_execute(self, app_name): +def setup_execute(self, app_name, create_public_route=False): app, _ = self.testloop.run_until_complete( self.test_client.apps.create(app_name) ) new_app_name = app["app"]["name"] + route_data = self.route_data + + if create_public_route: + route_data.update(is_public="true") + route, _ = self.testloop.run_until_complete( self.test_client.routes.create( - new_app_name, **self.route_data) + new_app_name, **route_data) ) self.testloop.run_until_complete( self.test_client.routes.update( @@ -199,7 +204,8 @@ class AppRoutesTestSuite(object): self.assertEqual(200, status) def execute_public(self): - with setup_execute(self, "execute_public") as app_name: + with setup_execute(self, "execute_public", + create_public_route=True) as app_name: result, status = self.testloop.run_until_complete( self.test_client.routes.execute_public( app_name, self.route_data["path"] @@ -207,3 +213,13 @@ class AppRoutesTestSuite(object): ) self.assertIsNotNone(result) self.assertEqual(200, status) + + def fail_to_execute_private_as_public(self): + with setup_execute(self, "fail_to_execute_" + "private_as_public") as app_name: + _, status = self.testloop.run_until_complete( + self.test_client.routes.execute_public( + app_name, self.route_data["path"] + ) + ) + self.assertEqual(403, status) diff --git a/picasso/tests/functional/test_routes.py b/picasso/tests/functional/test_routes.py index 62f9954..0869c54 100644 --- a/picasso/tests/functional/test_routes.py +++ b/picasso/tests/functional/test_routes.py @@ -49,3 +49,6 @@ class TestAppRoutes(base.FunctionalTestsBase, def test_public_execution(self): super(TestAppRoutes, self).execute_private() + + def test_fail_to_execute_private_route(self): + super(TestAppRoutes, self).fail_to_execute_private_as_public() diff --git a/picasso/tests/integration/test_routes.py b/picasso/tests/integration/test_routes.py index 52a9fd2..7c76c3c 100644 --- a/picasso/tests/integration/test_routes.py +++ b/picasso/tests/integration/test_routes.py @@ -55,3 +55,7 @@ class TestIntegrationAppRoutes(base.FunctionalTestsBase, def test_public_execution(self): super(TestIntegrationAppRoutes, self).execute_private() + + def test_fail_to_execute_private_route(self): + super(TestIntegrationAppRoutes, + self).fail_to_execute_private_as_public() diff --git a/tox.ini b/tox.ini index c46647b..79e189b 100644 --- a/tox.ini +++ b/tox.ini @@ -32,10 +32,10 @@ commands = flake8 commands = {posargs} [testenv:py35-integration] -commands = pytest --tb=long --capture=sys --cov=picasso --capture=fd {toxinidir}/picasso/tests/integration +commands = pytest -v --tb=long --capture=sys --cov=picasso --capture=fd {toxinidir}/picasso/tests/integration [testenv:py35-functional] -commands = pytest --tb=long --capture=sys --cov=picasso --capture=fd {toxinidir}/picasso/tests/functional +commands = pytest -v --tb=long --capture=sys --cov=picasso --capture=fd {toxinidir}/picasso/tests/functional [testenv:py35-functional-regression] commands = {toxinidir}/scripts/test_regression.sh functional {posargs}