diff --git a/bottle_oauthlib/oauth2.py b/bottle_oauthlib/oauth2.py index 785e4ac..b3a6372 100644 --- a/bottle_oauthlib/oauth2.py +++ b/bottle_oauthlib/oauth2.py @@ -293,3 +293,28 @@ def wrapper(*args, **kwargs): return bottle.response return wrapper return decorator + + def create_userinfo_response(self): + def decorator(f): + @functools.wraps(f) + def wrapper(*args, **kwargs): + assert self._oauthlib, "BottleOAuth2 not initialized with OAuthLib" + + uri, http_method, body, headers = extract_params(bottle.request) + + try: + resp_headers, resp_body, resp_status = self._oauthlib.create_userinfo_response( + uri, http_method=http_method, body=body, headers=headers + ) + except OAuth2Error as e: + resp_headers, resp_body, resp_status = e.headers, e.json, e.status_code + + set_response(bottle.request, bottle.response, resp_status, resp_headers, + resp_body, force_json=True) + + func_response = f(*args, **kwargs) + if func_response: + return func_response + return bottle.response + return wrapper + return decorator diff --git a/tests/test_oauth2.py b/tests/test_oauth2.py index 5cda748..0c0b272 100644 --- a/tests/test_oauth2.py +++ b/tests/test_oauth2.py @@ -8,6 +8,7 @@ from oauthlib.oauth2 import LegacyApplicationServer from tests import AttrDict from unittest import mock +import unittest class test_not_initialized(ServerTestBase): @@ -47,6 +48,15 @@ def test(): return 'bar' with self.assertRaises(AssertionError): test() + @unittest.skip("remove skip once https://github.com/oauthlib/oauthlib/pull/677 merged") + def test_create_userinfo_response(self): + @self.app.route('/foo') + @self.oauth.create_userinfo_response() + def test(): return 'bar' + + with self.assertRaises(AssertionError): + test() + class test_verify_decorators(ServerTestBase): def setUp(self): @@ -168,6 +178,33 @@ def test(): return "{'valid': false}" mocked.assert_called_once() +class test_create_userinfo_decorators(ServerTestBase): + def setUp(self): + super().setUp() + self.oauth = BottleOAuth2(self.app) + self.validator = mock.MagicMock() + self.server = Server(self.validator) + self.oauth.initialize(self.server) + + self.fake_response = ({ + "Content-Type": "application/json" + }, "{'sub': 'johndoe123', 'foo': 'bar'}", "200 FooOK") + + @unittest.skip("remove skip once https://github.com/oauthlib/oauthlib/pull/677 merged") + def test_valid_response(self): + @self.app.route('/foo') + @self.oauth.create_userinfo_response() + def test(): return None + + with mock.patch("oauthlib.oauth2.Server.create_userinfo_response", return_value=self.fake_response) as mocked: + app_response = self.urlopen("/foo") + self.assertEqual(app_response['code'], 200) + self.assertEqual(app_response['status'], "FooOK") + self.assertEqual(app_response['body'], tob("{'valid': true, 'foo': 'bar'}")) + self.assertEqual(app_response['header']['Content-Type'], "application/json") + mocked.assert_called_once() + + class test_create_authorization_decorators(ServerTestBase): def setUp(self): super().setUp()