Add generic OAuth support to current
This commit is contained in:
parent
07c67b09db
commit
94f4957c3d
11
cps/admin.py
11
cps/admin.py
@ -1115,6 +1115,17 @@ def _configuration_oauth_helper(to_save):
|
|||||||
{"oauth_client_id": to_save["config_" + str(element['id']) + "_oauth_client_id"],
|
{"oauth_client_id": to_save["config_" + str(element['id']) + "_oauth_client_id"],
|
||||||
"oauth_client_secret": to_save["config_" + str(element['id']) + "_oauth_client_secret"],
|
"oauth_client_secret": to_save["config_" + str(element['id']) + "_oauth_client_secret"],
|
||||||
"active": element["active"]})
|
"active": element["active"]})
|
||||||
|
if element['id'] == 3:
|
||||||
|
ub.session.query(ub.OAuthProvider).filter(ub.OAuthProvider.id == element['id']).update({
|
||||||
|
"oauth_base_url": to_save["config_" + str(element['id']) + "_oauth_base_url"],
|
||||||
|
"oauth_auth_url": to_save["config_" + str(element['id']) + "_oauth_auth_url"],
|
||||||
|
"oauth_token_url": to_save["config_" + str(element['id']) + "_oauth_token_url"],
|
||||||
|
"username_mapper": to_save["config_" + str(element['id']) + "_username_mapper"],
|
||||||
|
"email_mapper": to_save["config_" + str(element['id']) + "_email_mapper"],
|
||||||
|
"login_button": to_save["config_" + str(element['id']) + "_login_button"],
|
||||||
|
"scope": to_save["config_" + str(element['id']) + "_scope"],
|
||||||
|
})
|
||||||
|
|
||||||
return reboot_required
|
return reboot_required
|
||||||
|
|
||||||
|
|
||||||
|
156
cps/oauth_bb.py
156
cps/oauth_bb.py
@ -26,12 +26,13 @@ from functools import wraps
|
|||||||
from flask import session, request, make_response, abort
|
from flask import session, request, make_response, abort
|
||||||
from flask import Blueprint, flash, redirect, url_for
|
from flask import Blueprint, flash, redirect, url_for
|
||||||
from flask_babel import gettext as _
|
from flask_babel import gettext as _
|
||||||
from flask_dance.consumer import oauth_authorized, oauth_error
|
from flask_dance.consumer import oauth_authorized, oauth_error, OAuth2ConsumerBlueprint
|
||||||
from flask_dance.contrib.github import make_github_blueprint, github
|
from flask_dance.contrib.github import make_github_blueprint, github
|
||||||
from flask_dance.contrib.google import make_google_blueprint, google
|
from flask_dance.contrib.google import make_google_blueprint, google
|
||||||
from oauthlib.oauth2 import TokenExpiredError, InvalidGrantError
|
from oauthlib.oauth2 import TokenExpiredError, InvalidGrantError
|
||||||
from flask_login import login_user, current_user, login_required
|
from flask_login import login_user, current_user, login_required
|
||||||
from sqlalchemy.orm.exc import NoResultFound
|
from sqlalchemy.orm.exc import NoResultFound
|
||||||
|
from sqlalchemy.sql.expression import func, and_
|
||||||
|
|
||||||
from . import constants, logger, config, app, ub
|
from . import constants, logger, config, app, ub
|
||||||
|
|
||||||
@ -45,6 +46,7 @@ oauth_check = {}
|
|||||||
oauthblueprints = []
|
oauthblueprints = []
|
||||||
oauth = Blueprint('oauth', __name__)
|
oauth = Blueprint('oauth', __name__)
|
||||||
log = logger.create()
|
log = logger.create()
|
||||||
|
generic = None
|
||||||
|
|
||||||
|
|
||||||
def oauth_required(f):
|
def oauth_required(f):
|
||||||
@ -95,6 +97,7 @@ def logout_oauth_user():
|
|||||||
for oauth_key in oauth_check.keys():
|
for oauth_key in oauth_check.keys():
|
||||||
if str(oauth_key) + '_oauth_user_id' in session:
|
if str(oauth_key) + '_oauth_user_id' in session:
|
||||||
session.pop(str(oauth_key) + '_oauth_user_id')
|
session.pop(str(oauth_key) + '_oauth_user_id')
|
||||||
|
unlink_oauth(oauth_key)
|
||||||
|
|
||||||
|
|
||||||
def oauth_update_token(provider_id, token, provider_user_id):
|
def oauth_update_token(provider_id, token, provider_user_id):
|
||||||
@ -206,8 +209,10 @@ def unlink_oauth(provider):
|
|||||||
return redirect(url_for('web.profile'))
|
return redirect(url_for('web.profile'))
|
||||||
|
|
||||||
def generate_oauth_blueprints():
|
def generate_oauth_blueprints():
|
||||||
|
global generic
|
||||||
|
|
||||||
if not ub.session.query(ub.OAuthProvider).count():
|
if not ub.session.query(ub.OAuthProvider).count():
|
||||||
for provider in ("github", "google"):
|
for provider in ("github", "google", "generic"):
|
||||||
oauthProvider = ub.OAuthProvider()
|
oauthProvider = ub.OAuthProvider()
|
||||||
oauthProvider.provider_name = provider
|
oauthProvider.provider_name = provider
|
||||||
oauthProvider.active = False
|
oauthProvider.active = False
|
||||||
@ -229,20 +234,52 @@ def generate_oauth_blueprints():
|
|||||||
oauth_client_id=oauth_ids[1].oauth_client_id,
|
oauth_client_id=oauth_ids[1].oauth_client_id,
|
||||||
oauth_client_secret=oauth_ids[1].oauth_client_secret,
|
oauth_client_secret=oauth_ids[1].oauth_client_secret,
|
||||||
obtain_link='https://console.developers.google.com/apis/credentials')
|
obtain_link='https://console.developers.google.com/apis/credentials')
|
||||||
|
ele3 = dict(provider_name='generic',
|
||||||
|
id=oauth_ids[2].id,
|
||||||
|
active=oauth_ids[2].active,
|
||||||
|
scope=oauth_ids[2].scope,
|
||||||
|
oauth_client_id=oauth_ids[2].oauth_client_id,
|
||||||
|
oauth_client_secret=oauth_ids[2].oauth_client_secret,
|
||||||
|
oauth_base_url=oauth_ids[2].oauth_base_url,
|
||||||
|
oauth_auth_url=oauth_ids[2].oauth_auth_url,
|
||||||
|
oauth_token_url=oauth_ids[2].oauth_token_url,
|
||||||
|
username_mapper=oauth_ids[2].username_mapper,
|
||||||
|
email_mapper=oauth_ids[2].email_mapper,
|
||||||
|
login_button=oauth_ids[2].login_button)
|
||||||
oauthblueprints.append(ele1)
|
oauthblueprints.append(ele1)
|
||||||
oauthblueprints.append(ele2)
|
oauthblueprints.append(ele2)
|
||||||
|
oauthblueprints.append(ele3)
|
||||||
|
|
||||||
for element in oauthblueprints:
|
for element in oauthblueprints:
|
||||||
if element['provider_name'] == 'github':
|
if element['provider_name'] == 'github':
|
||||||
blueprint_func = make_github_blueprint
|
blueprint_func = make_github_blueprint
|
||||||
else:
|
elif element['provider_name'] == 'google':
|
||||||
blueprint_func = make_google_blueprint
|
blueprint_func = make_google_blueprint
|
||||||
blueprint = blueprint_func(
|
else:
|
||||||
client_id=element['oauth_client_id'],
|
blueprint_func = OAuth2ConsumerBlueprint
|
||||||
client_secret=element['oauth_client_secret'],
|
|
||||||
redirect_to="oauth."+element['provider_name']+"_login",
|
if element['provider_name'] in ('github', 'google'):
|
||||||
scope=element['scope']
|
blueprint = blueprint_func(
|
||||||
)
|
client_id=element['oauth_client_id'],
|
||||||
|
client_secret=element['oauth_client_secret'],
|
||||||
|
redirect_url="oauth."+element['provider_name']+"_login",
|
||||||
|
scope=element['scope']
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
base_url = element.get('oauth_base_url') or ''
|
||||||
|
token_url = element.get('oauth_token_url') or ''
|
||||||
|
auth_url = element.get('oauth_auth_url') or ''
|
||||||
|
blueprint = blueprint_func(
|
||||||
|
"generic",
|
||||||
|
__name__,
|
||||||
|
client_id=element['oauth_client_id'],
|
||||||
|
client_secret=element['oauth_client_secret'],
|
||||||
|
base_url=base_url,
|
||||||
|
authorization_url=base_url + auth_url,
|
||||||
|
token_url=base_url + token_url,
|
||||||
|
redirect_to='oauth.'+element['provider_name']+'_login',
|
||||||
|
)
|
||||||
|
generic = blueprint
|
||||||
element['blueprint'] = blueprint
|
element['blueprint'] = blueprint
|
||||||
element['blueprint'].backend = OAuthBackend(ub.OAuth, ub.session, str(element['id']),
|
element['blueprint'].backend = OAuthBackend(ub.OAuth, ub.session, str(element['id']),
|
||||||
user=current_user, user_required=True)
|
user=current_user, user_required=True)
|
||||||
@ -291,6 +328,55 @@ if ub.oauth_support:
|
|||||||
return oauth_update_token(str(oauthblueprints[1]['id']), token, google_user_id)
|
return oauth_update_token(str(oauthblueprints[1]['id']), token, google_user_id)
|
||||||
|
|
||||||
|
|
||||||
|
@oauth_authorized.connect_via(oauthblueprints[2]['blueprint'])
|
||||||
|
def generic_logged_in(blueprint, token):
|
||||||
|
global generic
|
||||||
|
|
||||||
|
if not token:
|
||||||
|
flash(_(u"Failed to log in with generic OAuth provider."), category="error")
|
||||||
|
log.error("Failed to log in with generic OAuth2 provider")
|
||||||
|
return False
|
||||||
|
|
||||||
|
resp = blueprint.session.get(blueprint.base_url + "/protocol/openid-connect/userinfo")
|
||||||
|
if not resp.ok:
|
||||||
|
flash(_(u"Failed to fetch user info from generic OAuth2 provider."), category="error")
|
||||||
|
log.error("Failed to fetch user info from generic OAuth2 provider")
|
||||||
|
return False
|
||||||
|
|
||||||
|
username_mapper = oauthblueprints[2].get('username_mapper') or 'username'
|
||||||
|
email_mapper = oauthblueprints[2].get('email_mapper') or 'email'
|
||||||
|
|
||||||
|
generic_info = resp.json()
|
||||||
|
generic_user_email = str(generic_info[email_mapper])
|
||||||
|
generic_user_username = str(generic_info[username_mapper])
|
||||||
|
|
||||||
|
user = (
|
||||||
|
ub.session.query(ub.User)
|
||||||
|
.filter(and_(func.lower(ub.User.name) == generic_user_username,
|
||||||
|
func.lower(ub.User.email) == generic_user_email))
|
||||||
|
).first()
|
||||||
|
|
||||||
|
if user is None:
|
||||||
|
user = ub.User()
|
||||||
|
user.name = generic_user_username
|
||||||
|
user.email = generic_user_email
|
||||||
|
user.role = constants.ROLE_USER
|
||||||
|
ub.session.add(user)
|
||||||
|
ub.session_commit()
|
||||||
|
|
||||||
|
result = oauth_update_token(str(oauthblueprints[2]['id']), token, user.id)
|
||||||
|
|
||||||
|
query = ub.session.query(ub.OAuth).filter_by(
|
||||||
|
provider=str(oauthblueprints[2]['id']),
|
||||||
|
provider_user_id=user.id,
|
||||||
|
)
|
||||||
|
oauth_entry = query.first()
|
||||||
|
oauth_entry.user = user
|
||||||
|
ub.session_commit()
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
# notify on OAuth provider error
|
# notify on OAuth provider error
|
||||||
@oauth_error.connect_via(oauthblueprints[0]['blueprint'])
|
@oauth_error.connect_via(oauthblueprints[0]['blueprint'])
|
||||||
def github_error(blueprint, error, error_description=None, error_uri=None):
|
def github_error(blueprint, error, error_description=None, error_uri=None):
|
||||||
@ -319,6 +405,20 @@ if ub.oauth_support:
|
|||||||
flash(msg, category="error")
|
flash(msg, category="error")
|
||||||
|
|
||||||
|
|
||||||
|
@oauth_error.connect_via(oauthblueprints[2]['blueprint'])
|
||||||
|
def generic_error(blueprint, error, error_description=None, error_uri=None):
|
||||||
|
msg = (
|
||||||
|
u"OAuth error from {name}! "
|
||||||
|
u"error={error} description={description} uri={uri}"
|
||||||
|
).format(
|
||||||
|
name=blueprint.name,
|
||||||
|
error=error,
|
||||||
|
description=error_description,
|
||||||
|
uri=error_uri,
|
||||||
|
) # ToDo: Translate
|
||||||
|
flash(msg, category="error")
|
||||||
|
|
||||||
|
|
||||||
@oauth.route('/link/github')
|
@oauth.route('/link/github')
|
||||||
@oauth_required
|
@oauth_required
|
||||||
def github_login():
|
def github_login():
|
||||||
@ -365,3 +465,41 @@ def google_login():
|
|||||||
@login_required
|
@login_required
|
||||||
def google_login_unlink():
|
def google_login_unlink():
|
||||||
return unlink_oauth(oauthblueprints[1]['id'])
|
return unlink_oauth(oauthblueprints[1]['id'])
|
||||||
|
|
||||||
|
|
||||||
|
@oauth.route('/link/generic')
|
||||||
|
@oauth_required
|
||||||
|
def generic_login():
|
||||||
|
global generic
|
||||||
|
|
||||||
|
if not generic.session.authorized:
|
||||||
|
return redirect(url_for("generic.login"))
|
||||||
|
try:
|
||||||
|
resp = generic.session.get(generic.base_url + "/protocol/openid-connect/userinfo")
|
||||||
|
if resp.ok:
|
||||||
|
account_info_json = resp.json()
|
||||||
|
|
||||||
|
username_mapper = oauthblueprints[2].get('username_mapper') or 'username'
|
||||||
|
email_mapper = oauthblueprints[2].get('email_mapper') or 'email'
|
||||||
|
|
||||||
|
email = str(account_info_json[email_mapper])
|
||||||
|
username = str(account_info_json[username_mapper])
|
||||||
|
|
||||||
|
user = (
|
||||||
|
ub.session.query(ub.User)
|
||||||
|
.filter(and_(func.lower(ub.User.name) == username,
|
||||||
|
func.lower(ub.User.email) == email))
|
||||||
|
).first()
|
||||||
|
|
||||||
|
return bind_oauth_or_register(oauthblueprints[2]['id'], user.id, 'generic.login', 'generic')
|
||||||
|
flash(_(u"generic OAuth2 error, please retry later."), category="error")
|
||||||
|
log.error("generic OAuth2 error, please retry later")
|
||||||
|
except (InvalidGrantError, TokenExpiredError) as e:
|
||||||
|
log.error(e)
|
||||||
|
return redirect(url_for("generic.login"))
|
||||||
|
|
||||||
|
|
||||||
|
@oauth.route('/unlink/generic', methods=["GET"])
|
||||||
|
@login_required
|
||||||
|
def generic_login_unlink():
|
||||||
|
return unlink_oauth(oauthblueprints[2]['id'])
|
||||||
|
@ -293,9 +293,12 @@
|
|||||||
{% if feature_support['oauth'] %}
|
{% if feature_support['oauth'] %}
|
||||||
<div data-related="login-settings-2">
|
<div data-related="login-settings-2">
|
||||||
{% for prov in provider %}
|
{% for prov in provider %}
|
||||||
|
<h4> {{prov['provider_name']}} </h4>
|
||||||
|
{% if prov.obtain_link %}
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<a href="{{prov['obtain_link']}}" target="_blank">{{_('Obtain %(provider)s OAuth Credential', provider=prov['provider_name'])}}</a>
|
<a href="{{prov['obtain_link']}}" target="_blank">{{_('Obtain %(provider)s OAuth Credential', provider=prov['provider_name'])}}</a>
|
||||||
</div>
|
</div>
|
||||||
|
{% endif %}
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="config_{{ prov['id'] }}_oauth_client_id">{{_('%(provider)s OAuth Client Id', provider=prov['provider_name'])}}</label>
|
<label for="config_{{ prov['id'] }}_oauth_client_id">{{_('%(provider)s OAuth Client Id', provider=prov['provider_name'])}}</label>
|
||||||
<input type="text" class="form-control" id="config_{{ prov['id'] }}_oauth_client_id" name="config_{{ prov['id'] }}_oauth_client_id" value="{% if prov['oauth_client_id']%}{{ prov['oauth_client_id'] }}{% endif %}" autocomplete="off">
|
<input type="text" class="form-control" id="config_{{ prov['id'] }}_oauth_client_id" name="config_{{ prov['id'] }}_oauth_client_id" value="{% if prov['oauth_client_id']%}{{ prov['oauth_client_id'] }}{% endif %}" autocomplete="off">
|
||||||
@ -304,6 +307,48 @@
|
|||||||
<label for="config_{{ prov['id'] }}_oauth_client_secret">{{_('%(provider)s OAuth Client Secret', provider=prov['provider_name'])}}</label>
|
<label for="config_{{ prov['id'] }}_oauth_client_secret">{{_('%(provider)s OAuth Client Secret', provider=prov['provider_name'])}}</label>
|
||||||
<input type="text" class="form-control" id="config_{{ prov['id'] }}_oauth_client_secret" name="config_{{ prov['id'] }}_oauth_client_secret" value="{% if prov['oauth_client_secret']%}{{ prov['oauth_client_secret'] }}{% endif %}" autocomplete="off">
|
<input type="text" class="form-control" id="config_{{ prov['id'] }}_oauth_client_secret" name="config_{{ prov['id'] }}_oauth_client_secret" value="{% if prov['oauth_client_secret']%}{{ prov['oauth_client_secret'] }}{% endif %}" autocomplete="off">
|
||||||
</div>
|
</div>
|
||||||
|
{% if 'scope' in prov and 'generic' == prov['provider_name'] %}
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="config_{{ prov['id'] }}_scope">{{_('%(provider)s OAuth scope', provider=prov['provider_name'])}}</label>
|
||||||
|
<input type="text" class="form-control" id="config_{{ prov['id'] }}_scope" name="config_{{ prov['id'] }}_scope" value="{% if prov['scope']%}{{ prov['scope'] }}{% endif %}" autocomplete="off">
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% if 'oauth_base_url' in prov %}
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="config_{{ prov['id'] }}_oauth_base_url">{{_('%(provider)s OAuth Base URL', provider=prov['provider_name'])}}</label>
|
||||||
|
<input type="text" class="form-control" id="config_{{ prov['id'] }}_oauth_base_url" name="config_{{ prov['id'] }}_oauth_base_url" value="{% if prov['oauth_base_url']%}{{ prov['oauth_base_url'] }}{% endif %}" autocomplete="off">
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% if 'oauth_auth_url' in prov %}
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="config_{{ prov['id'] }}_oauth_auth_url">{{_('%(provider)s OAuth Auth URL (relative)', provider=prov['provider_name'])}}</label>
|
||||||
|
<input type="text" class="form-control" id="config_{{ prov['id'] }}_oauth_auth_url" name="config_{{ prov['id'] }}_oauth_auth_url" value="{% if prov['oauth_auth_url']%}{{ prov['oauth_auth_url'] }}{% endif %}" autocomplete="off">
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% if 'oauth_token_url' in prov %}
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="config_{{ prov['id'] }}_oauth_token_url">{{_('%(provider)s OAuth Token URL (relative)', provider=prov['provider_name'])}}</label>
|
||||||
|
<input type="text" class="form-control" id="config_{{ prov['id'] }}_oauth_token_url" name="config_{{ prov['id'] }}_oauth_token_url" value="{% if prov['oauth_token_url']%}{{ prov['oauth_token_url'] }}{% endif %}" autocomplete="off">
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% if 'username_mapper' in prov %}
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="config_{{ prov['id'] }}_username_mapper">{{_('%(provider)s OAuth Username mapper', provider=prov['provider_name'])}}</label>
|
||||||
|
<input type="text" class="form-control" id="config_{{ prov['id'] }}_username_mapper" name="config_{{ prov['id'] }}_username_mapper" value="{% if prov['username_mapper']%}{{ prov['username_mapper'] }}{% endif %}" autocomplete="off">
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% if 'email_mapper' in prov %}
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="config_{{ prov['id'] }}_email_mapper">{{_('%(provider)s OAuth Email mapper', provider=prov['provider_name'])}}</label>
|
||||||
|
<input type="text" class="form-control" id="config_{{ prov['id'] }}_email_mapper" name="config_{{ prov['id'] }}_email_mapper" value="{% if prov['email_mapper']%}{{ prov['email_mapper'] }}{% endif %}" autocomplete="off">
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% if 'login_button' in prov %}
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="config_{{ prov['id'] }}_login_button">{{_('%(provider)s OAuth Login Button', provider=prov['provider_name'])}}</label>
|
||||||
|
<input type="text" class="form-control" id="config_{{ prov['id'] }}_login_button" name="config_{{ prov['id'] }}_login_button" value="{% if prov['login_button']%}{{ prov['login_button'] }}{% endif %}" autocomplete="off">
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@ -41,6 +41,9 @@
|
|||||||
style="fill:#000000;"><g id="surface1"><path style=" fill:#FFC107;" d="M 43.609375 20.082031 L 42 20.082031 L 42 20 L 24 20 L 24 28 L 35.304688 28 C 33.652344 32.65625 29.222656 36 24 36 C 17.371094 36 12 30.628906 12 24 C 12 17.371094 17.371094 12 24 12 C 27.058594 12 29.84375 13.152344 31.960938 15.039063 L 37.617188 9.382813 C 34.046875 6.054688 29.269531 4 24 4 C 12.953125 4 4 12.953125 4 24 C 4 35.046875 12.953125 44 24 44 C 35.046875 44 44 35.046875 44 24 C 44 22.660156 43.863281 21.351563 43.609375 20.082031 Z "></path><path style=" fill:#FF3D00;" d="M 6.304688 14.691406 L 12.878906 19.511719 C 14.65625 15.109375 18.960938 12 24 12 C 27.058594 12 29.84375 13.152344 31.960938 15.039063 L 37.617188 9.382813 C 34.046875 6.054688 29.269531 4 24 4 C 16.316406 4 9.65625 8.335938 6.304688 14.691406 Z "></path><path style=" fill:#4CAF50;" d="M 24 44 C 29.164063 44 33.859375 42.023438 37.410156 38.808594 L 31.21875 33.570313 C 29.210938 35.089844 26.714844 36 24 36 C 18.796875 36 14.382813 32.683594 12.71875 28.054688 L 6.195313 33.078125 C 9.503906 39.554688 16.226563 44 24 44 Z "></path><path style=" fill:#1976D2;" d="M 43.609375 20.082031 L 42 20.082031 L 42 20 L 24 20 L 24 28 L 35.304688 28 C 34.511719 30.238281 33.070313 32.164063 31.214844 33.570313 C 31.21875 33.570313 31.21875 33.570313 31.21875 33.570313 L 37.410156 38.808594 C 36.972656 39.203125 44 34 44 24 C 44 22.660156 43.863281 21.351563 43.609375 20.082031 Z "></path></g></svg>
|
style="fill:#000000;"><g id="surface1"><path style=" fill:#FFC107;" d="M 43.609375 20.082031 L 42 20.082031 L 42 20 L 24 20 L 24 28 L 35.304688 28 C 33.652344 32.65625 29.222656 36 24 36 C 17.371094 36 12 30.628906 12 24 C 12 17.371094 17.371094 12 24 12 C 27.058594 12 29.84375 13.152344 31.960938 15.039063 L 37.617188 9.382813 C 34.046875 6.054688 29.269531 4 24 4 C 12.953125 4 4 12.953125 4 24 C 4 35.046875 12.953125 44 24 44 C 35.046875 44 44 35.046875 44 24 C 44 22.660156 43.863281 21.351563 43.609375 20.082031 Z "></path><path style=" fill:#FF3D00;" d="M 6.304688 14.691406 L 12.878906 19.511719 C 14.65625 15.109375 18.960938 12 24 12 C 27.058594 12 29.84375 13.152344 31.960938 15.039063 L 37.617188 9.382813 C 34.046875 6.054688 29.269531 4 24 4 C 16.316406 4 9.65625 8.335938 6.304688 14.691406 Z "></path><path style=" fill:#4CAF50;" d="M 24 44 C 29.164063 44 33.859375 42.023438 37.410156 38.808594 L 31.21875 33.570313 C 29.210938 35.089844 26.714844 36 24 36 C 18.796875 36 14.382813 32.683594 12.71875 28.054688 L 6.195313 33.078125 C 9.503906 39.554688 16.226563 44 24 44 Z "></path><path style=" fill:#1976D2;" d="M 43.609375 20.082031 L 42 20.082031 L 42 20 L 24 20 L 24 28 L 35.304688 28 C 34.511719 30.238281 33.070313 32.164063 31.214844 33.570313 C 31.21875 33.570313 31.21875 33.570313 31.21875 33.570313 L 37.410156 38.808594 C 36.972656 39.203125 44 34 44 24 C 44 22.660156 43.863281 21.351563 43.609375 20.082031 Z "></path></g></svg>
|
||||||
</a>
|
</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% if 3 in oauth_check %}
|
||||||
|
<a href="{{url_for('oauth.generic_login')}}" class="pull-right generic">Log in with <b>{{ login_button }}</b></a>
|
||||||
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
11
cps/ub.py
11
cps/ub.py
@ -260,6 +260,13 @@ class OAuthProvider(Base):
|
|||||||
provider_name = Column(String)
|
provider_name = Column(String)
|
||||||
oauth_client_id = Column(String)
|
oauth_client_id = Column(String)
|
||||||
oauth_client_secret = Column(String)
|
oauth_client_secret = Column(String)
|
||||||
|
oauth_base_url = Column(String)
|
||||||
|
oauth_auth_url = Column(String, default="/protocol/openid-connect/auth")
|
||||||
|
oauth_token_url = Column(String, default="/protocol/openid-connect/token")
|
||||||
|
scope = Column(String, default="openid profile email")
|
||||||
|
username_mapper = Column(String, default="preferred_username")
|
||||||
|
email_mapper = Column(String, default="email")
|
||||||
|
login_button = Column(String)
|
||||||
active = Column(Boolean)
|
active = Column(Boolean)
|
||||||
|
|
||||||
|
|
||||||
@ -722,13 +729,13 @@ def migrate_Database(_session):
|
|||||||
"kindle_mail VARCHAR(120),"
|
"kindle_mail VARCHAR(120),"
|
||||||
"locale VARCHAR(2),"
|
"locale VARCHAR(2),"
|
||||||
"sidebar_view INTEGER,"
|
"sidebar_view INTEGER,"
|
||||||
"default_language VARCHAR(3),"
|
"default_language VARCHAR(3),"
|
||||||
"denied_tags VARCHAR,"
|
"denied_tags VARCHAR,"
|
||||||
"allowed_tags VARCHAR,"
|
"allowed_tags VARCHAR,"
|
||||||
"denied_column_value VARCHAR,"
|
"denied_column_value VARCHAR,"
|
||||||
"allowed_column_value VARCHAR,"
|
"allowed_column_value VARCHAR,"
|
||||||
"view_settings JSON,"
|
"view_settings JSON,"
|
||||||
"kobo_only_shelves_sync SMALLINT,"
|
"kobo_only_shelves_sync SMALLINT,"
|
||||||
"UNIQUE (name),"
|
"UNIQUE (name),"
|
||||||
"UNIQUE (email))"))
|
"UNIQUE (email))"))
|
||||||
conn.execute(text("INSERT INTO user_id(id, name, email, role, password, kindle_mail,locale,"
|
conn.execute(text("INSERT INTO user_id(id, name, email, role, password, kindle_mail,locale,"
|
||||||
|
@ -1331,11 +1331,18 @@ def login():
|
|||||||
next_url = request.args.get('next', default=url_for("web.index"), type=str)
|
next_url = request.args.get('next', default=url_for("web.index"), type=str)
|
||||||
if url_for("web.logout") == next_url:
|
if url_for("web.logout") == next_url:
|
||||||
next_url = url_for("web.index")
|
next_url = url_for("web.index")
|
||||||
|
|
||||||
|
login_button = "generic oauth2 provider"
|
||||||
|
if 3 in oauth_check:
|
||||||
|
from .oauth_bb import oauthblueprints
|
||||||
|
login_button = oauthblueprints[2].get('login_button') or login_button
|
||||||
|
|
||||||
return render_title_template('login.html',
|
return render_title_template('login.html',
|
||||||
title=_(u"Login"),
|
title=_(u"Login"),
|
||||||
next_url=next_url,
|
next_url=next_url,
|
||||||
config=config,
|
config=config,
|
||||||
oauth_check=oauth_check,
|
oauth_check=oauth_check,
|
||||||
|
login_button=login_button,
|
||||||
mail=config.get_mail_server_configured(), page="login")
|
mail=config.get_mail_server_configured(), page="login")
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user