from flask import Blueprint, render_template, \ redirect, url_for, session, abort from flask import current_app as app from flask_security import login_user from flask_security.confirmable import confirm_user from flask_social import connection_created, login_completed, login_failed from flask_social.utils import get_connection_values_from_oauth_response, \ get_provider_or_404 from flask_social.views import connect_handler from werkzeug.local import LocalProxy from flaskbase.extensions import db from auth.forms import SocialLoginConfirmForm blueprint = Blueprint('auth', __name__) _security = LocalProxy(lambda: app.extensions['security']) @connection_created.connect @login_completed.connect def on_connection_created(app, connection=None, user=None, provider=None): if not connection: connection = provider.get_connection() if not connection.user and user: connection.user = user db.session.commit() @login_failed.connect def on_login_failed(app, provider, oauth_response): session['failed_login_connection'] = \ get_connection_values_from_oauth_response(provider, oauth_response) abort(redirect(url_for('auth.confirm_social'))) @blueprint.route('/confirm_social', methods=['GET', 'POST']) def confirm_social(): connection_values = session.get('failed_login_connection', None) if not connection_values: return redirect('/') form = SocialLoginConfirmForm( email=connection_values.get('email', ''), ) if form.validate_on_submit(): # Prevent Flask-Security form sending confirmation email _security.confirmable = False kwargs = {'email': form.email.data} if connection_values.get('full_name'): kwargs['display_name'] = connection_values['full_name'] # Create and login user user = _security.datastore.create_user(**kwargs) confirm_user(user) _security.datastore.commit() login_user(user) # TODO: possibly move it to user_logged_in signal handler? # Process pending social connection connection_values = session.pop('failed_login_connection', None) connection_values['user_id'] = user.id connect_handler( connection_values, get_provider_or_404(connection_values['provider_id'])) _security.datastore.commit() return redirect('/') return render_template('security/confirm_social.html', form=form)