How to use without decorators
soderluk opened this issue · 6 comments
This is more of a question than an issue.
I'm using bottle in a REST API, and I specify the routes like so: app.route('/auth/login', 'POST', AuthController.login)
Now the issue is, that I'd like to use the bottle-oauthlib without decorators @app.auth.create_token_response()
-> instead use self._app.auth.create_token_response()
is this possible? Or should I just use the oauthlib without the bottle implementation?
Hi @soderluk,
If I understand it correctly, you are creating bottle routes manually (without decorators, by calling app.route()
) and you want to apply a bottle-oauthlib
decorator to this route?
You can replace the decorator programaticaly before declaring the bottle route as below:
AuthController.login = self._app.auth.create_token_response(AuthController.login)
app.route('/auth/login', 'POST', AuthController.login)
Cool, I'll give it a try when I get back to implementing the OAuth part of the API. I'll post back the results of the testing as soon as I've got something.
Hi @JonathanHuot,
I've now got to the situation where I implement the Bottle OAuth library to our API. I got the token endpoint working with the following implementation:
auth = AuthController()
def setup_routing(app: bottle.Bottle) -> None:
decorator = app.auth.create_token_response()
app.route('/login', 'POST', decorator(auth.login))
class AuthController(object):
def login(self):
pass
This works fine, but now I'm interested in how to implement the verify_request()
. We are using web_args for the controller actions, and have a decorator for the controller actions:
@request_args({
'name': fields.Str(required=True),
'type': fields.Str(required=True),
'data': fields.Dict(allow_none=True),
})
def create(self, args: dict) -> responses.JSONResponse:
# Do some stuff here that uses the args dictionary and returns the JSONResponse
If I use the verify_request()
in the same way in the setup_routes()
as with the login, I cannot use the web_args decorator at the same time. I get TypeError: wrapper() takes 0 positional arguments but 1 was given
Do you have any suggestions as to how this should be implemented? Using other decorators with the bottle-oauth decorators would be great!
@JonathanHuot: Tested this by adding to the verify_response()
decorator *args, **kwargs
:
def verify_request(self, scopes=None):
def decorator(f):
@functools.wraps(f)
def wrapper(*args, **kwargs):
assert self._oauthlib, "BottleOAuth2 not initialized with OAuthLib"
# Get the list of scopes
try:
scopes_list = scopes(bottle.request)
except TypeError:
scopes_list = scopes
uri, http_method, body, headers = extract_params(bottle.request)
valid, req = self._oauthlib.verify_request(uri, http_method, body, headers, scopes_list)
# For convenient parameter access in the view
add_params_to_request(bottle.request, {
'client': req.client,
'user': req.user,
'scopes': req.scopes
})
if valid:
return f(*args, **kwargs)
# Framework specific HTTP 403
return HTTPError(403, "Permission denied")
return wrapper
return decorator
Now I can use the verify_request()
decorator function as a function AND the web_args decorator. Would this be something that could be added to all the decorators? So that if the route functions uses anything else as the parameters, it would work without using the @decorator()
part?
@soderluk : Yes that works!
Could you create a PR with this please ?
Sure!