Tengo una aplicación Flask que usa flask-restx y flask-login . Me gustaría que todas las rutas requieran inicio de sesión de forma predeterminada y definan explícitamente rutas públicas que no requieran autenticación. He comenzado a usar decoradores siguiendo el ejemplo dado en esta pregunta:
La mejor manera de hacer que el login_required de Flask-Login sea el predeterminado
Funciona para puntos finales de funciones, pero no para puntos finales de recursos restx .
Intenté agregar la función como decorador y usar el campo method_decorators . Por ejemplo:
def public_route(decorated_function): """ This is a decorator to specify public endpoints in our flask routes :param decorated_function: :return: """ decorated_function.is_public = True return decorated_function class HelloWorld(ConfigurableResource): method_decorators = {"get": [public_route]} @public_route @api.doc('Welcome message') def get(self): return {'hello': 'world'}Y esta prueba pasa:
def test_hello_world_is_public(): api = Namespace('health', description='Health related operations') hello = HelloWorld(api, config=None, logger=None) is_public_endpoint = getattr(hello.get, 'is_public', False) assert is_public_endpointMi desafío es que no puedo ver cómo acceder a este atributo en mi lógica de autenticación:
@app.before_request def check_route_access(): """ This function decides whethere access should be granted to an endpoint. This function runs before all requests. :return: """ is_public_endpoint = getattr(app.view_functions[request.endpoint], 'is_public', False) if person_authorized_for_path(current_user, request.path, is_public_endpoint): return # Otherwise access not granted return redirect(url_for("auth.index"))Esto funciona para puntos finales de función simple, pero no para recursos restx.
Entiendo que restx está envolviendo mi clase de recurso en una función para que el matraz pueda enviar, pero no puedo entender cómo acceder al decorador desde aquí. Así que tengo algunas preguntas:
¿Es posible llegar al decorador desde view_function?
Bueno... es posible , pero no lo recomendaría. aquí hay un ejemplo
¿Es posible saber si el punto final es un recurso restx o una función de descanso simple?
Probablemente pueda inspeccionar la función y averiguar si es de restx, tal vez mirando __qualname__ , pero, de nuevo, no lo recomendaría.
¿Hay una mejor manera de hacer lo que estoy tratando de lograr?
Yo iría a una de estas soluciones:
before_request para autorizaciónBasado en this y this , la variable method_decorators debe ser una lista de funciones, por lo que debe usarla como:
def _perform_auth(method): is_public_endpoint = getattr(method, 'is_public', False) # place the validation here class Resource(flask_restx.Resource): method_decorators = [_perform_auth]