From 4e56c75f1082de46fb73187cba51b0fc02d4eaf7 Mon Sep 17 00:00:00 2001 From: Hsiaoming Yang Date: Fri, 7 Jun 2013 09:54:38 +0800 Subject: [PATCH 1/6] test works --- Makefile | 4 +-- tests/oauth2_server.py | 12 +++++---- tests/test_oauth2.py | 61 +++++++++++++++++++++++++++++++++++++++--- 3 files changed, 67 insertions(+), 10 deletions(-) diff --git a/Makefile b/Makefile index dafaf824..70ac1ce7 100644 --- a/Makefile +++ b/Makefile @@ -4,11 +4,11 @@ lint: @flake8 flask-oauthlib tests test: - @nosetests -s + @DEBUG=1 nosetests -s coverage: @rm -f .coverage - @nosetests --with-coverage --cover-package=flask-oauthlib --cover-html + @DEBUG=1 nosetests --with-coverage --cover-package=flask_oauthlib --cover-html clean: clean-build clean-pyc clean-docs diff --git a/tests/oauth2_server.py b/tests/oauth2_server.py index a40edb48..ee679498 100644 --- a/tests/oauth2_server.py +++ b/tests/oauth2_server.py @@ -6,7 +6,7 @@ from flask_oauthlib.provider import OAuth2Provider import logging -log = logging.getLogger('oauthlib') +log = logging.getLogger('flask_oauthlib') log.addHandler(logging.StreamHandler()) log.setLevel(logging.DEBUG) @@ -158,6 +158,8 @@ def set_grant(client_id, code, request, *args, **kwargs): @oauth.tokensetter def set_token(token, request, *args, **kwargs): + # In real project, a token is unique bound to user and client. + # Which means, you don't need to create a token every time. tok = Token(**token) tok.user_id = request.user.id tok.client_id = request.client.client_id @@ -191,13 +193,13 @@ def access_token(): @app.route('/api/email') @oauth.require_oauth(['email']) - def email(): - return jsonify(email='me@example.com') + def email(data): + return jsonify(email='me@oauth.net', username=data.user.username) @app.route('/api/address') @oauth.require_oauth(['address']) - def address(): - return jsonify(address='earth') + def address(data): + return jsonify(address='earth', username=data.user.username) return app diff --git a/tests/test_oauth2.py b/tests/test_oauth2.py index b68ab0ad..120f5d1c 100644 --- a/tests/test_oauth2.py +++ b/tests/test_oauth2.py @@ -1,8 +1,63 @@ +# coding: utf-8 + +import os +import tempfile from flask import Flask from .oauth2_server import create_server from .oauth2_client import create_client -app = Flask(__name__) -app.debug = True -app.secret_key = 'development' +class BaseSuite(object): + def setUp(self): + app = Flask(__name__) + app.debug = True + app.testing = True + app.secret_key = 'development' + + self.db_fd, self.db_file = tempfile.mkstemp() + config = { + 'SQLALCHEMY_DATABASE_URI': 'sqlite:///%s' % self.db_file + } + + app = create_server(app) + app = create_client(app) + + self.app = app + self.client = app.test_client() + return app + + def tearDown(self): + os.close(self.db_fd) + os.unlink(self.db_file) + + +class TestAuth(BaseSuite): + def test_login(self): + rv = self.client.get('/login') + assert 'response_type=code' in rv.location + + def test_oauth_authorize_invalid_url(self): + rv = self.client.get('/oauth/authorize') + assert 'invalid_client_id' in rv.location + + #rv = self.client.get('/oauth/authorize?client_id=dev') + #print rv.data + + def test_oauth_authorize_valid_url(self): + url = ('/oauth/authorize?response_type=code&client_id=dev' + '&redirect_uri=http%3A%2F%2Flocalhost%3A8000%2Fauthorized' + '&scope=email') + rv = self.client.get(url) + # valid + assert '' in rv.data + + rv = self.client.post(url, data=dict( + confirm='no' + )) + assert 'access_denied' in rv.location + + rv = self.client.post(url, data=dict( + confirm='yes' + )) + # success + assert 'code=' in rv.location From b37d4035d8de8cf7288739457336a0c7c5f77d54 Mon Sep 17 00:00:00 2001 From: Hsiaoming Yang Date: Fri, 7 Jun 2013 10:17:38 +0800 Subject: [PATCH 2/6] test process to access token --- Makefile | 2 +- flask_oauthlib/client.py | 6 +++++- tests/test_oauth2.py | 22 ++++++++++++++++------ 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/Makefile b/Makefile index 70ac1ce7..272fec53 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ lint: @flake8 flask-oauthlib tests test: - @DEBUG=1 nosetests -s + @DEBUG=1 nosetests -s --nologcapture coverage: @rm -f .coverage diff --git a/flask_oauthlib/client.py b/flask_oauthlib/client.py index 5beb7f7e..576cc812 100644 --- a/flask_oauthlib/client.py +++ b/flask_oauthlib/client.py @@ -14,7 +14,7 @@ import oauthlib.oauth2 from functools import wraps from oauthlib.common import to_unicode -from urlparse import urljoin +from urlparse import urljoin, urlparse from flask import request, redirect, json, session from werkzeug import url_quote, url_decode, url_encode, parse_options_header @@ -140,9 +140,13 @@ def make_request(uri, headers=None, data=None, method=None, if test_client: # test client is a `werkzeug.test.Client` + parsed = urlparse(uri) + uri = '%s?%s' % (parsed.path, parsed.query) resp = test_client.open( uri, headers=headers, data=data, method=method ) + # for compatible + resp.code = resp.status_code return resp, resp.data req = urllib2.Request(uri, headers=headers, data=data) diff --git a/tests/test_oauth2.py b/tests/test_oauth2.py index 120f5d1c..04d21e67 100644 --- a/tests/test_oauth2.py +++ b/tests/test_oauth2.py @@ -31,6 +31,12 @@ def tearDown(self): os.unlink(self.db_file) +authorize_url = ( + '/oauth/authorize?response_type=code&client_id=dev' + '&redirect_uri=http%3A%2F%2Flocalhost%3A8000%2Fauthorized&scope=email' +) + + class TestAuth(BaseSuite): def test_login(self): rv = self.client.get('/login') @@ -44,20 +50,24 @@ def test_oauth_authorize_invalid_url(self): #print rv.data def test_oauth_authorize_valid_url(self): - url = ('/oauth/authorize?response_type=code&client_id=dev' - '&redirect_uri=http%3A%2F%2Flocalhost%3A8000%2Fauthorized' - '&scope=email') - rv = self.client.get(url) + rv = self.client.get(authorize_url) # valid assert '' in rv.data - rv = self.client.post(url, data=dict( + rv = self.client.post(authorize_url, data=dict( confirm='no' )) assert 'access_denied' in rv.location - rv = self.client.post(url, data=dict( + rv = self.client.post(authorize_url, data=dict( confirm='yes' )) # success assert 'code=' in rv.location + + def test_get_access_token(self): + rv = self.client.post(authorize_url, data={'confirm': 'yes'}) + url = rv.location.replace('http://localhost:8000', '') + print url + rv = self.client.get(url) + print rv.data From 940cc4c3ee1d349958a229245b1f808b3126cd11 Mon Sep 17 00:00:00 2001 From: Hsiaoming Yang Date: Fri, 7 Jun 2013 18:04:48 +0800 Subject: [PATCH 3/6] test can get access token now --- flask_oauthlib/client.py | 1 + flask_oauthlib/provider/oauth2.py | 8 ++++++++ tests/oauth2_server.py | 5 ----- tests/test_oauth2.py | 3 +-- 4 files changed, 10 insertions(+), 7 deletions(-) diff --git a/flask_oauthlib/client.py b/flask_oauthlib/client.py index 576cc812..a05a4439 100644 --- a/flask_oauthlib/client.py +++ b/flask_oauthlib/client.py @@ -466,6 +466,7 @@ def handle_oauth2_response(self): 'client_secret': self.consumer_secret, 'redirect_uri': session.get('%s_oauthredir' % self.name) } + log.debug('Prepare oauth2 remote args %r', remote_args) remote_args.update(self.access_token_params) if self.access_token_method == 'POST': body = client.prepare_request_body(**remote_args) diff --git a/flask_oauthlib/provider/oauth2.py b/flask_oauthlib/provider/oauth2.py index 1d063869..418b2cb7 100644 --- a/flask_oauthlib/provider/oauth2.py +++ b/flask_oauthlib/provider/oauth2.py @@ -8,6 +8,7 @@ :copyright: (c) 2013 by Hsiaoming Yang. """ +import os import logging import datetime from functools import wraps @@ -397,6 +398,13 @@ def confirm_redirect_uri(self, client_id, code, redirect_uri, client, return False if hasattr(grant, 'validate_redirect_uri'): return grant.validate_redirect_uri(redirect_uri) + log.debug('Compare redirect uri for grant %r and %r.', + grant.redirect_uri, redirect_uri) + + if os.environ.get('DEBUG') and redirect_uri is None: + # For testing + return True + return grant.redirect_uri == redirect_uri def confirm_scopes(self, refresh_token, scopes, request, *args, **kwargs): diff --git a/tests/oauth2_server.py b/tests/oauth2_server.py index ee679498..b3e3a121 100644 --- a/tests/oauth2_server.py +++ b/tests/oauth2_server.py @@ -5,11 +5,6 @@ from sqlalchemy.orm import relationship from flask_oauthlib.provider import OAuth2Provider -import logging -log = logging.getLogger('flask_oauthlib') -log.addHandler(logging.StreamHandler()) -log.setLevel(logging.DEBUG) - db = SQLAlchemy() diff --git a/tests/test_oauth2.py b/tests/test_oauth2.py index 04d21e67..7702b36b 100644 --- a/tests/test_oauth2.py +++ b/tests/test_oauth2.py @@ -68,6 +68,5 @@ def test_oauth_authorize_valid_url(self): def test_get_access_token(self): rv = self.client.post(authorize_url, data={'confirm': 'yes'}) url = rv.location.replace('http://localhost:8000', '') - print url rv = self.client.get(url) - print rv.data + assert "access_token" in rv.data From ec5581d7db93036da0972153a6f075f77851bf39 Mon Sep 17 00:00:00 2001 From: Hsiaoming Yang Date: Fri, 7 Jun 2013 18:14:41 +0800 Subject: [PATCH 4/6] test process to get resource --- tests/test_oauth2.py | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/tests/test_oauth2.py b/tests/test_oauth2.py index 7702b36b..d8d25f7b 100644 --- a/tests/test_oauth2.py +++ b/tests/test_oauth2.py @@ -2,6 +2,7 @@ import os import tempfile +from urlparse import urlparse from flask import Flask from .oauth2_server import create_server from .oauth2_client import create_client @@ -67,6 +68,15 @@ def test_oauth_authorize_valid_url(self): def test_get_access_token(self): rv = self.client.post(authorize_url, data={'confirm': 'yes'}) - url = rv.location.replace('http://localhost:8000', '') - rv = self.client.get(url) - assert "access_token" in rv.data + rv = self.client.get(clean_url(rv.location)) + assert 'access_token' in rv.data + + def test_full_flow(self): + self.test_get_access_token() + rv = self.client.get('/') + assert 'username' in rv.data + + +def clean_url(location): + ret = urlparse(location) + return '%s?%s' % (ret.path, ret.query) From eea0b2ff4c7aefb417f02f19f701ac96b562a87d Mon Sep 17 00:00:00 2001 From: Hsiaoming Yang Date: Fri, 7 Jun 2013 18:18:23 +0800 Subject: [PATCH 5/6] add travis --- .travis.yml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..9777d0d8 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,15 @@ +language: python + +python: + - "2.7" + +script: + - nosetests -s + +after_success: + - pip install coveralls + - coverage run --source=flask_oauthlib setup.py -q nosetests + - coveralls + +notifications: + email: false From 41a77f9a64b02519840768f8a7305779e0664a04 Mon Sep 17 00:00:00 2001 From: Hsiaoming Yang Date: Fri, 7 Jun 2013 18:23:51 +0800 Subject: [PATCH 6/6] add debug for travis testing --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 9777d0d8..e3af11da 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,7 @@ python: - "2.7" script: - - nosetests -s + - DEBUG=1 nosetests -s after_success: - pip install coveralls