Merge pull request #726 from getredash/fix/lazy_load_oauth_app

Fix: lazy load the oauth app
This commit is contained in:
Arik Fraimovich 2015-12-28 15:15:43 +02:00
commit 6e32f5b9f2
4 changed files with 35 additions and 30 deletions

View File

@ -9,7 +9,6 @@ machine:
2.7.3 2.7.3
dependencies: dependencies:
pre: pre:
- make deps
- pip install -r requirements_dev.txt - pip install -r requirements_dev.txt
- pip install -r requirements.txt - pip install -r requirements.txt
cache_directories: cache_directories:
@ -18,12 +17,12 @@ dependencies:
test: test:
override: override:
- nosetests --with-xunit --xunit-file=$CIRCLE_TEST_REPORTS/junit.xml --with-coverage --cover-package=redash tests/ - nosetests --with-xunit --xunit-file=$CIRCLE_TEST_REPORTS/junit.xml --with-coverage --cover-package=redash tests/
post:
- make pack
deployment: deployment:
github_and_docker: github_and_docker:
branch: master branch: master
commands: commands:
- make deps
- make pack
- make upload - make upload
- echo "rd_ui/app" >> .dockerignore - echo "rd_ui/app" >> .dockerignore
- docker build -t redash/redash:$(./manage.py version | sed -e "s/\+/./") . - docker build -t redash/redash:$(./manage.py version | sed -e "s/\+/./") .

View File

@ -6,28 +6,31 @@ from flask_oauthlib.client import OAuth
from redash import models, settings from redash import models, settings
logger = logging.getLogger('google_oauth') logger = logging.getLogger('google_oauth')
oauth = OAuth()
if not settings.GOOGLE_APPS_DOMAIN: if not settings.GOOGLE_APPS_DOMAIN:
logger.warning("No Google Apps domain defined, all Google accounts allowed.") logger.warning("No Google Apps domain defined, all Google accounts allowed.")
google = oauth.remote_app('google', oauth = OAuth()
base_url='https://www.google.com/accounts/',
authorize_url='https://accounts.google.com/o/oauth2/auth',
request_token_url=None,
request_token_params={
'scope': 'https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile',
},
access_token_url='https://accounts.google.com/o/oauth2/token',
access_token_method='POST',
consumer_key=settings.GOOGLE_CLIENT_ID,
consumer_secret=settings.GOOGLE_CLIENT_SECRET)
blueprint = Blueprint('google_oauth', __name__) blueprint = Blueprint('google_oauth', __name__)
def google_remote_app():
if 'google' not in oauth.remote_apps:
oauth.remote_app('google',
base_url='https://www.google.com/accounts/',
authorize_url='https://accounts.google.com/o/oauth2/auth',
request_token_url=None,
request_token_params={
'scope': 'https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile',
},
access_token_url='https://accounts.google.com/o/oauth2/token',
access_token_method='POST',
consumer_key=settings.GOOGLE_CLIENT_ID,
consumer_secret=settings.GOOGLE_CLIENT_SECRET)
return oauth.google
def get_user_profile(access_token): def get_user_profile(access_token):
headers = {'Authorization': 'OAuth {}'.format(access_token)} headers = {'Authorization': 'OAuth {}'.format(access_token)}
response = requests.get('https://www.googleapis.com/oauth2/v1/userinfo', headers=headers) response = requests.get('https://www.googleapis.com/oauth2/v1/userinfo', headers=headers)
@ -63,15 +66,16 @@ def create_and_login_user(name, email):
@blueprint.route('/oauth/google', endpoint="authorize") @blueprint.route('/oauth/google', endpoint="authorize")
def login(): def login():
next = request.args.get('next','/') next = request.args.get('next', '/')
callback=url_for('.callback', _external=True) callback = url_for('.callback', _external=True)
logger.debug("Callback url: %s", callback) logger.debug("Callback url: %s", callback)
return google.authorize(callback=callback, state=next) logger.debug("Next is: %s", next)
return google_remote_app().authorize(callback=callback, state=next)
@blueprint.route('/oauth/google_callback', endpoint="callback") @blueprint.route('/oauth/google_callback', endpoint="callback")
@google.authorized_handler def authorized():
def authorized(resp): resp = google_remote_app().authorized_response()
access_token = resp['access_token'] access_token = resp['access_token']
if access_token is None: if access_token is None:
@ -91,6 +95,6 @@ def authorized(resp):
create_and_login_user(profile['name'], profile['email']) create_and_login_user(profile['name'], profile['email'])
next = request.args.get('state','/') next = request.args.get('state', '/')
return redirect(next) return redirect(next)

View File

@ -7,14 +7,16 @@ from redash.wsgi import app
@app.route('/login', methods=['GET', 'POST']) @app.route('/login', methods=['GET', 'POST'])
def login(): def login():
next_path = request.args.get('next', '/')
if current_user.is_authenticated(): if current_user.is_authenticated():
return redirect(request.args.get('next') or '/') return redirect(next_path)
if not settings.PASSWORD_LOGIN_ENABLED: if not settings.PASSWORD_LOGIN_ENABLED:
if settings.SAML_LOGIN_ENABLED: if settings.SAML_LOGIN_ENABLED:
return redirect(url_for("saml_auth.sp_initiated", next=request.args.get('next'))) return redirect(url_for("saml_auth.sp_initiated", next=next_path))
else: else:
return redirect(url_for("google_oauth.authorize", next=request.args.get('next'))) return redirect(url_for("google_oauth.authorize", next=next_path))
if request.method == 'POST': if request.method == 'POST':
try: try:
@ -22,7 +24,7 @@ def login():
if user and user.verify_password(request.form['password']): if user and user.verify_password(request.form['password']):
remember = ('remember' in request.form) remember = ('remember' in request.form)
login_user(user, remember=remember) login_user(user, remember=remember)
return redirect(request.args.get('next') or '/') return redirect(next_path)
else: else:
flash("Wrong email or password.") flash("Wrong email or password.")
except models.User.DoesNotExist: except models.User.DoesNotExist:
@ -31,7 +33,7 @@ def login():
return render_template("login.html", return render_template("login.html",
name=settings.NAME, name=settings.NAME,
analytics=settings.ANALYTICS, analytics=settings.ANALYTICS,
next=request.args.get('next'), next=next_path,
username=request.form.get('username', ''), username=request.form.get('username', ''),
show_google_openid=settings.GOOGLE_OAUTH_ENABLED, show_google_openid=settings.GOOGLE_OAUTH_ENABLED,
show_saml_login=settings.SAML_LOGIN_ENABLED) show_saml_login=settings.SAML_LOGIN_ENABLED)

View File

@ -318,7 +318,7 @@ class TestLogin(BaseTestCase):
with app.test_client() as c, patch.object(settings, 'PASSWORD_LOGIN_ENABLED', False): with app.test_client() as c, patch.object(settings, 'PASSWORD_LOGIN_ENABLED', False):
rv = c.get('/login') rv = c.get('/login')
self.assertEquals(rv.status_code, 302) self.assertEquals(rv.status_code, 302)
self.assertTrue(rv.location.endswith(url_for('google_oauth.authorize'))) self.assertTrue(rv.location.endswith(url_for('google_oauth.authorize', next='/')))
def test_get_login_form(self): def test_get_login_form(self):
with app.test_client() as c: with app.test_client() as c: