We have implemented a twisted website api.
To deal with auth, we used a decorator with which we port some routes.
@requires_auth(roles=[Roles.Admin]) def get_secret_stuff(request): return 42
The requires_auth
implemented as follows.
def requires_auth(roles): def wrap(f): def wrapped_f(request, *args, **kwargs):
The problem is that with this decorator there are several routes, and then calling any of them leads to the fact that the last route will be called, which will be decorated.
This is obviously not what I wanted, and contradicts my understanding of how decorators should work. I added some printing instructions to the code to try to understand:
def requires_auth(roles): def wrap(f): print(f)
In case this is important, I use twisted inlineCallbacks for some of these routes, as well as the vinyl web decoder @app.route(url, methods)
for all these routes.
Thanks for reading:)
EDIT: I removed the default argument to the constructor since I was told that this is a bad idea :)
EDIT: The following is a minimal example illustrating the problem:
from klein import Klein import json app = Klein() def requires_auth(roles): def wrap(f): print('inside the first clojure with f=%s' % str(f)) def wrapped_f(request, *args, **kwargs): print('inside the second closure with f=%s' % str(f)) return f(request, *args, **kwargs) return wrapped_f return wrap @app.route('/thing_a') @requires_auth(roles=['user']) def get_a(request): return json.dumps({'thing A': 'hello'}) @app.route('/thing_b') @requires_auth(roles=['admin']) def get_b(request): return json.dumps({'thing B': 'goodbye'}) app.run('0.0.0.0', 8080)
Going to route '/ thing_a' leads to json from route_b