From 85c65f2dc9d843aff0f727b310164b6602d00736 Mon Sep 17 00:00:00 2001 From: Anand Tripathi Date: Sun, 2 Aug 2020 14:26:36 +0530 Subject: [PATCH 1/3] implemented flask-httpauth fixes #191 --- flask_apispec/extension.py | 20 ++++++++++++++++++++ setup.py | 2 ++ tests/test_extension.py | 29 +++++++++++++++++++++++++++++ 3 files changed, 51 insertions(+) diff --git a/flask_apispec/extension.py b/flask_apispec/extension.py index 81404ed..82a99bc 100644 --- a/flask_apispec/extension.py +++ b/flask_apispec/extension.py @@ -2,12 +2,29 @@ import flask import functools import types +from flask_httpauth import HTTPBasicAuth from apispec import APISpec from apispec.ext.marshmallow import MarshmallowPlugin from flask_apispec import ResourceMeta from flask_apispec.apidoc import ViewConverter, ResourceConverter +auth = HTTPBasicAuth() +config = None + + +@auth.verify_password +def verify_password(username=None, password=None): + if "APISPEC_AUTH" not in config or \ + not config.get("APISPEC_AUTH", {}).get("ENABLED"): + return True + + basic_auth = config.get("APISPEC_AUTH") + if username == basic_auth.get("USERNAME") and \ + password == basic_auth.get("PASSWORD"): + return True + return False + class FlaskApiSpec(object): """Flask-apispec extension. @@ -53,6 +70,8 @@ def __init__(self, app=None, document_options=True): def init_app(self, app): self.app = app + global config + config = self.app.config self.spec = self.app.config.get('APISPEC_SPEC') or \ make_apispec(self.app.config.get('APISPEC_TITLE', 'flask-apispec'), self.app.config.get('APISPEC_VERSION', 'v1'), @@ -94,6 +113,7 @@ def add_swagger_routes(self): def swagger_json(self): return flask.jsonify(self.spec.to_dict()) + @auth.login_required def swagger_ui(self): return flask.render_template('swagger-ui.html') diff --git a/setup.py b/setup.py index 2a0ac46..09b6607 100755 --- a/setup.py +++ b/setup.py @@ -11,8 +11,10 @@ 'marshmallow>=2.0.0; python_version>="3"', 'webargs>=0.18.0,<6.0.0', 'apispec>=1.0.0', + 'Flask-HTTPAuth==4.1.0' ] + def find_version(fname): """Attempts to find the version number in the file names fname. Raises RuntimeError if not found. diff --git a/tests/test_extension.py b/tests/test_extension.py index f1f5a7a..a707bda 100644 --- a/tests/test_extension.py +++ b/tests/test_extension.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- import pytest +import base64 from flask import Blueprint from flask_apispec import doc @@ -89,6 +90,34 @@ def test_serve_swagger_ui_custom_url(self, app, client): FlaskApiSpec(app) client.get('/swagger-ui.html') + def test_serve_swagger_ui_invalid_http_auth(self, app, client): + app.config['APISPEC_AUTH'] = dict( + ENABLED=True, + USERNAME="username", + PASSWORD="password" + ) + FlaskApiSpec(app) + res = client.get('/swagger-ui/', expect_errors=True) + assert res.status_code == 401 + + def test_serve_swagger_ui_valid_http_auth(self, app, client): + app.config['APISPEC_AUTH'] = dict( + ENABLED=True, + USERNAME="username", + PASSWORD="password" + ) + FlaskApiSpec(app) + + valid_credentials = base64.b64encode( + b"username:password" + ).decode("utf-8") + res = client.get( + '/swagger-ui/', + headers={"Authorization": "Basic " + valid_credentials}, + expect_errors=True + ) + assert res.status_code == 200 + def test_apispec_config(self, app): app.config['APISPEC_TITLE'] = 'test-extension' app.config['APISPEC_VERSION'] = '2.1' From 8f75c6e106b1bec3ce59b8d4a298d466bd0a5ab4 Mon Sep 17 00:00:00 2001 From: Anand Tripathi Date: Sun, 2 Aug 2020 14:29:50 +0530 Subject: [PATCH 2/3] implemented flask-httpauth with updated readme fixes #191 --- README.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.rst b/README.rst index 89e2356..c54a5b8 100644 --- a/README.rst +++ b/README.rst @@ -98,6 +98,11 @@ Quickstart plugins=[MarshmallowPlugin()], ), 'APISPEC_SWAGGER_URL': '/swagger/', + 'APISPEC_AUTH': { + 'ENABLED': True, + 'USERNAME': '', + 'PASSWORD': '' + } }) docs = FlaskApiSpec(app) From 6a6f3b762e20126d930dacc29164e5b83be88439 Mon Sep 17 00:00:00 2001 From: Anand Tripathi Date: Mon, 3 May 2021 23:38:04 +0530 Subject: [PATCH 3/3] Updated version of flask-httpauth in setup.py --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index e981a49..ed6ee6e 100755 --- a/setup.py +++ b/setup.py @@ -4,7 +4,7 @@ REQUIRES = [ 'flask>=0.10.1', - 'Flask-HTTPAuth==4.1.0' + 'Flask-HTTPAuth>=4.1.0' 'marshmallow>=3.0.0', 'webargs>=6.0.0', 'apispec>=4.0.0',