diff --git a/setup.cfg b/setup.cfg index 420b9983..85501357 100644 --- a/setup.cfg +++ b/setup.cfg @@ -50,6 +50,7 @@ install_requires = colander ColanderAlchemy cornice + cornice-swagger humanize Mako markdown diff --git a/tailbone/api/common.py b/tailbone/api/common.py index cd663d53..30dfeab1 100644 --- a/tailbone/api/common.py +++ b/tailbone/api/common.py @@ -31,6 +31,8 @@ from rattail.db import model from rattail.mail import send_email from cornice import Service +from cornice.service import get_services +from cornice_swagger import CorniceSwagger import tailbone from tailbone import forms @@ -109,12 +111,22 @@ class CommonView(APIView): return {'error': "Form did not validate!"} + def swagger(self): + doc = CorniceSwagger(get_services()) + app = self.get_rattail_app() + spec = doc.generate(f"{app.get_node_title()} API docs", + app.get_version(), + base_path='/api') # TODO + return spec + @classmethod def defaults(cls, config): cls._common_defaults(config) @classmethod def _common_defaults(cls, config): + rattail_config = config.registry.settings.get('rattail_config') + app = rattail_config.get_app() # about about = Service(name='about', path='/about') @@ -127,6 +139,14 @@ class CommonView(APIView): permission='common.feedback') config.add_cornice_service(feedback) + # swagger + swagger = Service(name='swagger', + path='/swagger.json', + description=f"OpenAPI documentation for {app.get_title()}") + swagger.add_view('GET', 'swagger', klass=cls, + permission='common.api_swagger') + config.add_cornice_service(swagger) + def defaults(config, **kwargs): base = globals() diff --git a/tailbone/views/common.py b/tailbone/views/common.py index e8d37904..7d1cd402 100644 --- a/tailbone/views/common.py +++ b/tailbone/views/common.py @@ -275,6 +275,11 @@ class CommonView(View): config.add_tailbone_permission('common', 'common.edit_help', "Edit help info for *any* page") + # API swagger + if rattail_config.getbool('tailbone', 'expose_api_swagger'): + config.add_tailbone_permission('common', 'common.api_swagger', + "Explore the API with Swagger tools") + # home config.add_route('home', '/') config.add_view(cls, attr='home', route_name='home', renderer='/home.mako')