From b3dac5dbe77b34b64f0c4f19a0338f3743a4eca1 Mon Sep 17 00:00:00 2001 From: Philip Malan Date: Thu, 26 Sep 2024 12:37:36 +0200 Subject: [PATCH 1/5] Test Release of new authorizations --- tina4_python/Auth.py | 8 ++++++- tina4_python/Router.py | 17 +++++++++++++-- tina4_python/Swagger.py | 48 ++++++++++++++++++++++++++++++++++++++--- 3 files changed, 67 insertions(+), 6 deletions(-) diff --git a/tina4_python/Auth.py b/tina4_python/Auth.py index 65768c2..fada6fd 100644 --- a/tina4_python/Auth.py +++ b/tina4_python/Auth.py @@ -174,5 +174,11 @@ def validate(self, token): return False - def valid(self, token): + def valid(self, token, override_method = None): + if override_method is not None: + try: + return override_method(token) + except Exception: + return False + return self.validate(token) diff --git a/tina4_python/Router.py b/tina4_python/Router.py index ac75f78..2e665b9 100644 --- a/tina4_python/Router.py +++ b/tina4_python/Router.py @@ -78,7 +78,11 @@ async def get_result(url, method, request, headers, session): validated = False # check to see if we have an auth ability if "authorization" in headers: - token = headers["authorization"].replace("Bearer", "").strip() + if "Bearer" in headers["authorization"]: + token = headers["authorization"].replace("Bearer", "").strip() + elif "X-API-KEY" in headers["authorization"]: + token = headers["authorization"].replace("X-API-KEY", "").strip() + if tina4_python.tina4_auth.valid(token): validated = True @@ -120,7 +124,16 @@ async def get_result(url, method, request, headers, session): if Router.match(url, route['route']): if "swagger" in route and route["swagger"] is not None and "secure" in route["swagger"]: if route["swagger"]["secure"] and not validated: - return Response(content, Constant.HTTP_FORBIDDEN, Constant.TEXT_HTML) + #Check if we have an override method + if "secureoverride" in route["swagger"]: + override_method = route["swagger"]["secureoverride"] + + if tina4_python.tina4_auth.valid(token, override_method): + validated = True + + # If still not validated + if not validated: + return Response(content, Constant.HTTP_FORBIDDEN, Constant.TEXT_HTML) router_response = route["callback"] diff --git a/tina4_python/Swagger.py b/tina4_python/Swagger.py index 1be42b4..e22a337 100644 --- a/tina4_python/Swagger.py +++ b/tina4_python/Swagger.py @@ -30,6 +30,14 @@ def add_summary(summary, callback): def add_secure(callback): Swagger.set_swagger_value(callback, "secure", True) + @staticmethod + def add_secure_override(method, callback): + Swagger.set_swagger_value(callback, "secureoverride", method) + + @staticmethod + def add_apikey_auth(callback): + Swagger.set_swagger_value(callback, "apikeyauth", True) + @staticmethod def add_tags(tags, callback): Swagger.set_swagger_value(callback, "tags", tags) @@ -62,7 +70,7 @@ def get_path_inputs(route_path): return params @staticmethod - def get_swagger_entry(url, method, tags, summary, description, produces, security, params=None, example=None, + def get_swagger_entry(url, method, tags, summary, description, produces, security, secure_override=None, apikeyauth=None, params=None, example=None, responses=None): if params is None: @@ -74,7 +82,11 @@ def get_swagger_entry(url, method, tags, summary, description, produces, securit secure_annotation = [], if security: - secure_annotation = [{"bearerAuth": []}]; + secure_annotation = [{"bearerAuth": []}] + + # If we can add api key auth as well + if apikeyauth: + secure_annotation = [{"apiKey": []}] new_params = [] for param in params: @@ -101,6 +113,7 @@ def get_swagger_entry(url, method, tags, summary, description, produces, securit } }, "security": secure_annotation, + "secureoverride": secure_override, "responses": responses }; @@ -123,6 +136,10 @@ def parse_swagger(swagger): swagger["example"] = None if not "secure" in swagger: swagger["secure"] = None + if not "secureoverride" in swagger: + swagger["secureoverride"] = None + if not "apikeyauth" in swagger: + swagger["apikeyauth"] = None if isinstance(swagger["tags"], str): swagger["tags"] = [swagger["tags"]] @@ -132,6 +149,7 @@ def parse_swagger(swagger): @staticmethod def get_json(request): paths = {} + apikey_auth = False # If we have any routes that require api key auth for route in tina4_python.tina4_routes.values(): if "swagger" in route: @@ -139,6 +157,9 @@ def get_json(request): swagger = Swagger.parse_swagger(route["swagger"]) produces = {} + if swagger["apikeyauth"]: + apikey_auth = True + responses = { "200": {"description": "Success"}, "400": {"description": "Failed"} @@ -154,6 +175,8 @@ def get_json(request): ["application/json", "html/text"], swagger["secure"], + swagger["secureoverride"], + swagger["apikeyauth"], swagger["params"], swagger["example"], responses) @@ -172,11 +195,18 @@ def get_json(request): "version": os.getenv("SWAGGER_VERSION", "1.0.0(SWAGGER_VERSION)") }, "components": { - "securitySchemes": {"bearerAuth": {"type": "http", "scheme": "bearer", "bearerFormat": "JWT"}}}, + "securitySchemes": {} + }, "basePath": "", "paths": paths } + # Populate the security schemes + if apikey_auth: + json_object["components"]["securitySchemes"]["apiKey"] = {"type": "apiKey", "in": "header", "name": "X-API-KEY"} + + json_object["components"]["securitySchemes"]["bearerAuth"] = {"type": "http", "scheme": "bearer", "bearerFormat": "JWT"} + return json_object @@ -203,6 +233,18 @@ def actual_secure(callback): return actual_secure +def apikeyauth(): + def actual_apikey_auth(callback): + Swagger.add_apikey_auth(callback) + return callback + + return actual_apikey_auth + +def secureoverride(method): + def actual_secure_override(callback): + Swagger.add_secure_override(method, callback) + return callback + def tags(tags): def actual_tags(callback): From 324fbdc504b4b30cddceb313d925b9bee73f216c Mon Sep 17 00:00:00 2001 From: Philip Malan Date: Fri, 27 Sep 2024 04:11:24 +0200 Subject: [PATCH 2/5] Fixes and enhancements to authentication methods --- README.md | 39 ++++++++++ src/Middleware.py | 7 ++ tina4_python/Router.py | 157 +++++++++++++++++++++++++++------------- tina4_python/Swagger.py | 54 ++++++++------ 4 files changed, 183 insertions(+), 74 deletions(-) create mode 100644 src/Middleware.py diff --git a/README.md b/README.md index 909477b..a68917f 100644 --- a/README.md +++ b/README.md @@ -398,3 +398,42 @@ Flake8 Code tests ``` poetry run flake8 ./tina4_python ``` + +### Swagger Authentication Methods & Middleware + +#### Authentication Methods + +Support is added for Token (Bearer) authentication by default + +If there is a need to pass the token in the header or query parameters then you can add the following decorators to your route + +``` +@headerauth() +``` +You then pass it as a header value. The key needs to be X-API-KEY + +``` +@queryauth() +``` +You then pass it as a query parameter. The parameter needs to be api-key + +#### Middleware + +You can execute middleware when a route is called. Here you can authenticate a user before the default authentication or inject values into the header or request + +There is a file called Middleware.py in the src directory. Add all your middleware here + +To authenticate a user simply add the following to the request + +``` +request["validated"] = True +``` + +To run middleware simply add the function name to the @post, @get, @put etc decorator + +``` +@post('/api/user/authenticate', 'authenticate_user') +``` +Then add a authenticate_user function to Middleware.py and do any checks there + + diff --git a/src/Middleware.py b/src/Middleware.py new file mode 100644 index 0000000..26252f3 --- /dev/null +++ b/src/Middleware.py @@ -0,0 +1,7 @@ +''' Middleware class to inject values in headers or request ''' + +class Middleware: + + ''' def sample_inject(self, request, headers): + # Do something here + return request, headers ''' \ No newline at end of file diff --git a/tina4_python/Router.py b/tina4_python/Router.py index 2e665b9..5a13d2a 100644 --- a/tina4_python/Router.py +++ b/tina4_python/Router.py @@ -75,16 +75,80 @@ async def get_result(url, method, request, headers, session): content = Template.render_twig_template( "errors/403.twig", {"server": {"url": url}}) + current_route = None validated = False + + # Get all the route parameters + for route in tina4_python.tina4_routes.values(): + if route["method"] != method: + continue + Debug("Matching route " + route['route'] + " to " + url, Constant.TINA4_LOG_DEBUG) + if Router.match(url, route['route']): + Debug("Route matched: " + route['route'], Constant.TINA4_LOG_DEBUG) + current_route = route + exit + + Debug(current_route, Constant.TINA4_LOG_DEBUG) + + # If the route is not found + if current_route is None: + return Response(content, Constant.HTTP_NOT_FOUND, Constant.TEXT_HTML) + + # if we need to execute middleware + if "middleware" in current_route: + if current_route["middleware"] is not None: + middleware = current_route["middleware"] + Debug("Middleware found: " + middleware, Constant.TINA4_LOG_DEBUG) + + try: + import importlib + + module = importlib.import_module("src.Middleware") + + # Get the Middleware class from the module + middleware_class = getattr(module, 'Middleware') + + # Create an instance of Middleware + middleware_instance = middleware_class() + + # Get the middleware function + middleware_function = getattr(middleware_instance, middleware) + + if callable(middleware_function): + # Execute the middleware - We can pass additional parameters in the request + [request, headers] = middleware_function(request, headers) + Debug("Middleware executed", Constant.TINA4_LOG_DEBUG) + else: + Debug("Middleware function is not callable", Constant.TINA4_LOG_DEBUG) + except (AttributeError, ImportError) as e: + Debug(f"Error: {str(e)}", Constant.TINA4_LOG_DEBUG) + + # If the middleware has validated the user then we can carry on + if "validated" in request: + validated = request["validated"] + # check to see if we have an auth ability if "authorization" in headers: if "Bearer" in headers["authorization"]: token = headers["authorization"].replace("Bearer", "").strip() - elif "X-API-KEY" in headers["authorization"]: - token = headers["authorization"].replace("X-API-KEY", "").strip() - - if tina4_python.tina4_auth.valid(token): - validated = True + if tina4_python.tina4_auth.valid(token): + validated = True + + # check if we can authorize with an API key in the header + if "headerauth" in current_route["swagger"]: + if current_route["swagger"]["headerauth"]: + if "x-api-key" in headers: + token = headers["x-api-key"].strip() + if tina4_python.tina4_auth.valid(token): + validated = True + + # check if we can authorize with an API key in the query string + if "queryauth" in current_route["swagger"]: + if current_route["swagger"]["queryauth"]: + if "api-key" in request["params"]: + token = request["params"]["api-key"] + if tina4_python.tina4_auth.valid(token): + validated = True if request["params"] is not None and "formToken" in request["params"]: token = request["params"]["formToken"] @@ -117,40 +181,28 @@ async def get_result(url, method, request, headers, session): with open(static_file, 'rb') as file: return Response(file.read(), Constant.HTTP_OK, mime_type) - for route in tina4_python.tina4_routes.values(): - if route["method"] != method: - continue - Debug("Matching route " + route['route'] + " to " + url, Constant.TINA4_LOG_DEBUG) - if Router.match(url, route['route']): - if "swagger" in route and route["swagger"] is not None and "secure" in route["swagger"]: - if route["swagger"]["secure"] and not validated: - #Check if we have an override method - if "secureoverride" in route["swagger"]: - override_method = route["swagger"]["secureoverride"] - - if tina4_python.tina4_auth.valid(token, override_method): - validated = True - - # If still not validated - if not validated: - return Response(content, Constant.HTTP_FORBIDDEN, Constant.TEXT_HTML) - - router_response = route["callback"] - - # Add the inline variables & construct a Request variable - request["params"].update(Router.variables) - - Request.request = request # Add the request object - Request.headers = headers # Add the headers - Request.params = request["params"] - Request.body = request["body"] if "body" in request else None - Request.session = session - - tina4_python.tina4_current_request = Request - old_stdout = sys.stdout # Memorize the default stdout stream - sys.stdout = buffer = io.StringIO() - result = await router_response(request=Request, response=Response) - break + # check if we have a current route + if current_route is not None: + if "swagger" in current_route and current_route["swagger"] is not None and "secure" in current_route["swagger"]: + if current_route["swagger"]["secure"] and not validated: + if not validated: + return Response(content, Constant.HTTP_FORBIDDEN, Constant.TEXT_HTML) + + router_response = current_route["callback"] + + # Add the inline variables & construct a Request variable + request["params"].update(Router.variables) + + Request.request = request # Add the request object + Request.headers = headers # Add the headers + Request.params = request["params"] + Request.body = request["body"] if "body" in request else None + Request.session = session + + tina4_python.tina4_current_request = Request + old_stdout = sys.stdout # Memorize the default stdout stream + sys.stdout = buffer = io.StringIO() + result = await router_response(request=Request, response=Response) if result is None: sys.stdout = old_stdout @@ -196,7 +248,7 @@ def clean_url(url): # adds a route to the router @staticmethod - def add(method, route, callback): + def add(method, route, callback, middleware=None): Debug("Adding a route: " + route, Constant.TINA4_LOG_DEBUG) if not callback in tina4_python.tina4_routes: tina4_python.tina4_routes[callback] = {"route": route, "callback": callback, "method": method, "swagger": None} @@ -205,13 +257,17 @@ def add(method, route, callback): tina4_python.tina4_routes[callback]["callback"] = callback tina4_python.tina4_routes[callback]["method"] = method + if middleware is not None: + tina4_python.tina4_routes[callback]["middleware"] = middleware + Debug("Adding Middleware " + middleware, Constant.TINA4_LOG_DEBUG) + if '{' in route: # store the parameters if needed route_variables = re.findall(r'{(.*?)}', route) tina4_python.tina4_routes[callback]["params"] = route_variables -def get(path: str): +def get(path: str, middleware=None): """ Get router :param arguments: @@ -220,13 +276,13 @@ def get(path: str): def actual_get(callback): route_paths = path.split('|') for route_path in route_paths: - Router.add(Constant.TINA4_GET, route_path, callback) + Router.add(Constant.TINA4_GET, route_path, callback, middleware) return callback return actual_get -def post(path): +def post(path, middleware=None): """ Post router :param path: @@ -235,13 +291,12 @@ def post(path): def actual_post(callback): route_paths = path.split('|') for route_path in route_paths: - Router.add(Constant.TINA4_POST, route_path, callback) + Router.add(Constant.TINA4_POST, route_path, callback, middleware) return callback return actual_post - -def put(path): +def put(path, middleware=None): """ Put router :param path: @@ -250,13 +305,13 @@ def put(path): def actual_put(callback): route_paths = path.split('|') for route_path in route_paths: - Router.add(Constant.TINA4_PUT, route_path, callback) + Router.add(Constant.TINA4_PUT, route_path, callback, middleware) return callback return actual_put -def patch(path): +def patch(path, middleware=None): """ Patch router :param path: @@ -265,13 +320,13 @@ def patch(path): def actual_patch(callback): route_paths = path.split('|') for route_path in route_paths: - Router.add(Constant.TINA4_PATCH, route_path, callback) + Router.add(Constant.TINA4_PATCH, route_path, callback, middleware) return callback return actual_patch -def delete(path): +def delete(path, middleware=None): """ Delete router :param path: @@ -280,7 +335,7 @@ def delete(path): def actual_delete(callback): route_paths = path.split('|') for route_path in route_paths: - Router.add(Constant.TINA4_DELETE, route_path, callback) + Router.add(Constant.TINA4_DELETE, route_path, callback, middleware) return callback return actual_delete diff --git a/tina4_python/Swagger.py b/tina4_python/Swagger.py index e22a337..1d7f748 100644 --- a/tina4_python/Swagger.py +++ b/tina4_python/Swagger.py @@ -31,12 +31,12 @@ def add_secure(callback): Swagger.set_swagger_value(callback, "secure", True) @staticmethod - def add_secure_override(method, callback): - Swagger.set_swagger_value(callback, "secureoverride", method) + def add_header_auth(callback): + Swagger.set_swagger_value(callback, "headerauth", True) @staticmethod - def add_apikey_auth(callback): - Swagger.set_swagger_value(callback, "apikeyauth", True) + def add_query_auth(callback): + Swagger.set_swagger_value(callback, "queryauth", True) @staticmethod def add_tags(tags, callback): @@ -70,7 +70,7 @@ def get_path_inputs(route_path): return params @staticmethod - def get_swagger_entry(url, method, tags, summary, description, produces, security, secure_override=None, apikeyauth=None, params=None, example=None, + def get_swagger_entry(url, method, tags, summary, description, produces, security, headerauth=None, queryauth=None, params=None, example=None, responses=None): if params is None: @@ -85,7 +85,7 @@ def get_swagger_entry(url, method, tags, summary, description, produces, securit secure_annotation = [{"bearerAuth": []}] # If we can add api key auth as well - if apikeyauth: + if headerauth or queryauth: secure_annotation = [{"apiKey": []}] new_params = [] @@ -113,7 +113,6 @@ def get_swagger_entry(url, method, tags, summary, description, produces, securit } }, "security": secure_annotation, - "secureoverride": secure_override, "responses": responses }; @@ -136,10 +135,10 @@ def parse_swagger(swagger): swagger["example"] = None if not "secure" in swagger: swagger["secure"] = None - if not "secureoverride" in swagger: - swagger["secureoverride"] = None - if not "apikeyauth" in swagger: - swagger["apikeyauth"] = None + if not "headerauth" in swagger: + swagger["headerauth"] = None + if not "queryauth" in swagger: + swagger["queryauth"] = None if isinstance(swagger["tags"], str): swagger["tags"] = [swagger["tags"]] @@ -157,8 +156,11 @@ def get_json(request): swagger = Swagger.parse_swagger(route["swagger"]) produces = {} - if swagger["apikeyauth"]: - apikey_auth = True + if swagger["headerauth"]: + header_auth = True + + if swagger["queryauth"]: + query_auth = True responses = { "200": {"description": "Success"}, @@ -175,8 +177,8 @@ def get_json(request): ["application/json", "html/text"], swagger["secure"], - swagger["secureoverride"], - swagger["apikeyauth"], + swagger["headerauth"], + swagger["queryauth"], swagger["params"], swagger["example"], responses) @@ -202,9 +204,12 @@ def get_json(request): } # Populate the security schemes - if apikey_auth: + if header_auth: json_object["components"]["securitySchemes"]["apiKey"] = {"type": "apiKey", "in": "header", "name": "X-API-KEY"} + if query_auth: + json_object["components"]["securitySchemes"]["apiKey"] = {"type": "apiKey", "in": "query", "name": "api-key"} + json_object["components"]["securitySchemes"]["bearerAuth"] = {"type": "http", "scheme": "bearer", "bearerFormat": "JWT"} return json_object @@ -233,18 +238,21 @@ def actual_secure(callback): return actual_secure -def apikeyauth(): - def actual_apikey_auth(callback): - Swagger.add_apikey_auth(callback) +# Pass the api key as a header +def headerauth(): + def actual_header_auth(callback): + Swagger.add_header_auth(callback) return callback - return actual_apikey_auth + return actual_header_auth -def secureoverride(method): - def actual_secure_override(callback): - Swagger.add_secure_override(method, callback) +# Pass the api key as a query parameter +def queryauth(): + def actual_query_auth(callback): + Swagger.add_query_auth(callback) return callback + return actual_query_auth def tags(tags): def actual_tags(callback): From ba9e37cca854dda6bc001c4aeb83ffee14a09411 Mon Sep 17 00:00:00 2001 From: Philip Malan Date: Fri, 27 Sep 2024 04:32:16 +0200 Subject: [PATCH 3/5] Bug fix in routes and swagger.json --- tina4_python/Router.py | 33 +++++++++++++++++---------------- tina4_python/Swagger.py | 39 ++++++++++++++++++++++++++++++++------- 2 files changed, 49 insertions(+), 23 deletions(-) diff --git a/tina4_python/Router.py b/tina4_python/Router.py index 5a13d2a..de09a05 100644 --- a/tina4_python/Router.py +++ b/tina4_python/Router.py @@ -88,8 +88,6 @@ async def get_result(url, method, request, headers, session): current_route = route exit - Debug(current_route, Constant.TINA4_LOG_DEBUG) - # If the route is not found if current_route is None: return Response(content, Constant.HTTP_NOT_FOUND, Constant.TEXT_HTML) @@ -133,22 +131,25 @@ async def get_result(url, method, request, headers, session): token = headers["authorization"].replace("Bearer", "").strip() if tina4_python.tina4_auth.valid(token): validated = True + + Debug(current_route, Constant.TINA4_LOG_DEBUG) # check if we can authorize with an API key in the header - if "headerauth" in current_route["swagger"]: - if current_route["swagger"]["headerauth"]: - if "x-api-key" in headers: - token = headers["x-api-key"].strip() - if tina4_python.tina4_auth.valid(token): - validated = True - - # check if we can authorize with an API key in the query string - if "queryauth" in current_route["swagger"]: - if current_route["swagger"]["queryauth"]: - if "api-key" in request["params"]: - token = request["params"]["api-key"] - if tina4_python.tina4_auth.valid(token): - validated = True + if current_route["swagger"] is not None: + if "headerauth" in current_route["swagger"]: + if current_route["swagger"]["headerauth"]: + if "x-api-key" in headers: + token = headers["x-api-key"].strip() + if tina4_python.tina4_auth.valid(token): + validated = True + + # check if we can authorize with an API key in the query string + if "queryauth" in current_route["swagger"]: + if current_route["swagger"]["queryauth"]: + if "api-key" in request["params"]: + token = request["params"]["api-key"] + if tina4_python.tina4_auth.valid(token): + validated = True if request["params"] is not None and "formToken" in request["params"]: token = request["params"]["formToken"] diff --git a/tina4_python/Swagger.py b/tina4_python/Swagger.py index 1d7f748..203526a 100644 --- a/tina4_python/Swagger.py +++ b/tina4_python/Swagger.py @@ -80,13 +80,19 @@ def get_swagger_entry(url, method, tags, summary, description, produces, securit if example is not None: schema = {"type": "object", "example": example} - secure_annotation = [], + secure_annotation = [] + + # If security is defined, add bearerAuth if security: - secure_annotation = [{"bearerAuth": []}] + secure_annotation.append({"bearerAuth": []}) + + # If we can add API key auth from the header + if headerauth: + secure_annotation.append({"ApiKeyHeader": []}) - # If we can add api key auth as well - if headerauth or queryauth: - secure_annotation = [{"apiKey": []}] + # If we can add API key auth from the query + if queryauth: + secure_annotation.append({"ApiKeyQuery": []}) new_params = [] for param in params: @@ -205,10 +211,29 @@ def get_json(request): # Populate the security schemes if header_auth: - json_object["components"]["securitySchemes"]["apiKey"] = {"type": "apiKey", "in": "header", "name": "X-API-KEY"} + json_object["components"]["securitySchemes"]["ApiKeyHeader"] = { + "type": "apiKey", + "in": "header", + "name": "X-API-KEY" + } if query_auth: - json_object["components"]["securitySchemes"]["apiKey"] = {"type": "apiKey", "in": "query", "name": "api-key"} + json_object["components"]["securitySchemes"]["ApiKeyQuery"] = { + "type": "apiKey", + "in": "query", + "name": "api-key" + } + + # Now you can set the security requirements for your API paths + json_object["security"] = [] + + # Example of how to apply both security schemes globally or to specific operations + if header_auth and query_auth: + json_object["security"].append({"ApiKeyHeader": [], "ApiKeyQuery": []}) + elif header_auth: + json_object["security"].append({"ApiKeyHeader": []}) + elif query_auth: + json_object["security"].append({"ApiKeyQuery": []}) json_object["components"]["securitySchemes"]["bearerAuth"] = {"type": "http", "scheme": "bearer", "bearerFormat": "JWT"} From 9df32bc74e1ba0fdda59aa748258d00f16ad3af8 Mon Sep 17 00:00:00 2001 From: Philip Malan Date: Fri, 27 Sep 2024 06:25:53 +0200 Subject: [PATCH 4/5] Moved Middleware.py creation to __init__.py --- src/Middleware.py | 7 ------- tina4_python/__init__.py | 13 +++++++++++++ 2 files changed, 13 insertions(+), 7 deletions(-) delete mode 100644 src/Middleware.py diff --git a/src/Middleware.py b/src/Middleware.py deleted file mode 100644 index 26252f3..0000000 --- a/src/Middleware.py +++ /dev/null @@ -1,7 +0,0 @@ -''' Middleware class to inject values in headers or request ''' - -class Middleware: - - ''' def sample_inject(self, request, headers): - # Do something here - return request, headers ''' \ No newline at end of file diff --git a/tina4_python/__init__.py b/tina4_python/__init__.py index c08f337..7c1e7d5 100644 --- a/tina4_python/__init__.py +++ b/tina4_python/__init__.py @@ -90,6 +90,19 @@ app_file.write('from tina4_python import *') app_file.write('\n') + # Middleware + with open(root_path + os.sep + "src" + os.sep + "Middleware.py", 'w') as middleware_file: + middleware_file.write('# Middleware class to inject values into headers and request') + middleware_file.write('\n') + middleware_file.write('class Middleware:') + middleware_file.write('\n') + middleware_file.write('# def sample_inject(self, request, headers):') + middleware_file.write('\n') + middleware_file.write('# Do something here') + middleware_file.write('\n') + middleware_file.write('# return request, headers') + middleware_file.write('\n') + if not os.path.exists(root_path + os.sep + "src" + os.sep + "app"): os.makedirs(root_path + os.sep + "src" + os.sep + "app") From d490ecf2f55cd456b63e0765dbe8d6118f7a5adc Mon Sep 17 00:00:00 2001 From: Philip Malan Date: Fri, 27 Sep 2024 06:43:44 +0200 Subject: [PATCH 5/5] Fixed bug with header_auth and query_auth not set --- tina4_python/Swagger.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tina4_python/Swagger.py b/tina4_python/Swagger.py index 203526a..6752030 100644 --- a/tina4_python/Swagger.py +++ b/tina4_python/Swagger.py @@ -162,9 +162,13 @@ def get_json(request): swagger = Swagger.parse_swagger(route["swagger"]) produces = {} + header_auth = False + if swagger["headerauth"]: header_auth = True + query_auth = False + if swagger["queryauth"]: query_auth = True