81 lines
2.4 KiB
Python
81 lines
2.4 KiB
Python
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)
|