diff --git a/cps/admin.py b/cps/admin.py index 3e82930c..2c1c0817 100644 --- a/cps/admin.py +++ b/cps/admin.py @@ -56,10 +56,11 @@ feature_support = { # feature_support['rar'] = False try: - from .oauth_bb import oauth_check + from .oauth_bb import oauth_check, oauthblueprints feature_support['oauth'] = True except ImportError: feature_support['oauth'] = False + oauthblueprints = [] oauth_check = {} @@ -410,7 +411,7 @@ def _configuration_result(error_flash=None, gdriveError=None): flash(_(error_flash), category="error") show_login_button = False - return render_title_template("config_edit.html", config=config, + return render_title_template("config_edit.html", config=config, provider=oauthblueprints, show_back_button=show_back_button, show_login_button=show_login_button, show_authenticate_google_drive=gdrive_authenticate, gdriveError=gdriveError, gdrivefolders=gdrivefolders, feature_support=feature_support, diff --git a/cps/config_sql.py b/cps/config_sql.py index f4a97a35..934cb8ab 100644 --- a/cps/config_sql.py +++ b/cps/config_sql.py @@ -84,11 +84,11 @@ class _Settings(_Base): config_login_type = Column(Integer, default=0) - config_oauth_provider = Column(Boolean) - config_github_oauth_client_id = Column(String) - config_github_oauth_client_secret = Column(String) - config_google_oauth_client_id = Column(String) - config_google_oauth_client_secret = Column(String) + config_oauth_provider = Column(Integer) + #config_github_oauth_client_id = Column(String) + #config_github_oauth_client_secret = Column(String) + #config_google_oauth_client_id = Column(String) + #config_google_oauth_client_secret = Column(String) config_ldap_provider_url = Column(String, default='localhost') config_ldap_port = Column(SmallInteger, default=389) @@ -310,3 +310,12 @@ def load_configuration(session): session.commit() return _ConfigSQL(session) + +def load_oauth(session): + #_migrate_database(session) + + if not session.query(OAuthProvider).count(): + session.add(_Settings()) + session.commit() + + return _ConfigSQL(session) diff --git a/cps/helper.py b/cps/helper.py index c94093db..5c01cb97 100644 --- a/cps/helper.py +++ b/cps/helper.py @@ -71,6 +71,7 @@ from .worker import TASK_EMAIL, TASK_CONVERT, TASK_UPLOAD, TASK_CONVERT_ANY log = logger.create() +# ToDo delete duplicate def update_download(book_id, user_id): check = ub.session.query(ub.Downloads).filter(ub.Downloads.user_id == user_id).filter(ub.Downloads.book_id == book_id).first() diff --git a/cps/oauth_bb.py b/cps/oauth_bb.py index 39777911..e1f0bf47 100644 --- a/cps/oauth_bb.py +++ b/cps/oauth_bb.py @@ -45,7 +45,7 @@ oauth = Blueprint('oauth', __name__) log = logger.create() -def github_oauth_required(f): +'''def github_oauth_required(f): @wraps(f) def inner(*args, **kwargs): if config.config_login_type == constants.LOGIN_OAUTH_GITHUB: @@ -72,6 +72,21 @@ def google_oauth_required(f): return response, 404 abort(404) + return inner''' + + +def oauth_required(f): + @wraps(f) + def inner(*args, **kwargs): + if config.config_oauth_provider: + return f(*args, **kwargs) + if request.is_xhr: + data = {'status': 'error', 'message': 'Not Found'} + response = make_response(json.dumps(data, ensure_ascii=False)) + response.headers["Content-Type"] = "application/json; charset=utf-8" + return response, 404 + abort(404) + return inner @@ -115,10 +130,62 @@ def logout_oauth_user(): session.pop(oauth + '_oauth_user_id') if ub.oauth_support: - github_blueprint = make_github_blueprint( + oauthblueprints =[] + if not ub.session.query(ub.OAuthProvider).count(): + oauth = ub.OAuthProvider() + oauth.provider_name = "github" + oauth.active = False + ub.session.add(oauth) + ub.session.commit() + oauth = ub.OAuthProvider() + oauth.provider_name = "google" + oauth.active = False + ub.session.add(oauth) + ub.session.commit() + '''new_scope = ub.OAuthScope(provider_id=oauth.id, scope="https://www.googleapis.com/auth/plus.me") + ub.session.add(new_scope) + ub.session.commit() + new_scope = ub.OAuthScope(provider_id=oauth.id, scope="https://www.googleapis.com/auth/userinfo.email") + ub.session.add(new_scope) + ub.session.commit()''' + + ele1=dict(provider_name='Github', + active=False, + oauth_client_id=None, + scope=None, + oauth_client_secret=None, + obtain_link='https://github.com/settings/developers') + ele2=dict(provider_name='Google', + active=False, + scope=["https://www.googleapis.com/auth/plus.me", "https://www.googleapis.com/auth/userinfo.email"], + oauth_client_id=None, + oauth_client_secret=None, + obtain_link='https://github.com/settings/developers') + oauthblueprints.append(ele1) + oauthblueprints.append(ele2) + + for element in oauthblueprints: + if element['provider_name'] == 'Github': + blueprint_func = make_github_blueprint + else: + blueprint_func = make_google_blueprint + blueprint = blueprint_func( + client_id=element['oauth_client_id'], + client_secret=element['oauth_client_secret'], + redirect_to="oauth."+element['provider_name']+"_login", + scope = element['scope'] + ) + element['blueprint']=blueprint + app.register_blueprint(blueprint, url_prefix="/login") + element['blueprint'].backend = OAuthBackend(ub.OAuth, ub.session, user=current_user, user_required=True) + if element['active']: + register_oauth_blueprint(element['blueprint'], element['provider_name']) + + + '''github_blueprint = make_github_blueprint( client_id=config.config_github_oauth_client_id, client_secret=config.config_github_oauth_client_secret, - redirect_to="oauth.github_login",) + redirect_to="oauth.github_login") google_blueprint = make_google_blueprint( client_id=config.config_google_oauth_client_id, @@ -134,16 +201,15 @@ if ub.oauth_support: app.register_blueprint(github_blueprint, url_prefix='/login') github_blueprint.backend = OAuthBackend(ub.OAuth, ub.session, user=current_user, user_required=True) - google_blueprint.backend = OAuthBackend(ub.OAuth, ub.session, user=current_user, user_required=True) - + google_blueprint.backend = OAuthBackend(ub.OAuth, ub.session, user=current_user, user_required=True)''' - if config.config_login_type == constants.LOGIN_OAUTH_GITHUB: + '''if config.config_login_type == constants.LOGIN_OAUTH_GITHUB: register_oauth_blueprint(github_blueprint, 'GitHub') if config.config_login_type == constants.LOGIN_OAUTH_GOOGLE: - register_oauth_blueprint(google_blueprint, 'Google') + register_oauth_blueprint(google_blueprint, 'Google')''' - @oauth_authorized.connect_via(github_blueprint) + @oauth_authorized.connect_via(oauthblueprints[0]['blueprint']) def github_logged_in(blueprint, token): if not token: flash(_(u"Failed to log in with GitHub."), category="error") @@ -159,7 +225,7 @@ if ub.oauth_support: return oauth_update_token(blueprint, token, github_user_id) - @oauth_authorized.connect_via(google_blueprint) + @oauth_authorized.connect_via(oauthblueprints[1]['blueprint']) def google_logged_in(blueprint, token): if not token: flash(_(u"Failed to log in with Google."), category="error") @@ -278,7 +344,7 @@ if ub.oauth_support: # notify on OAuth provider error - @oauth_error.connect_via(github_blueprint) + @oauth_error.connect_via(oauthblueprints[0]['blueprint']) def github_error(blueprint, error, error_description=None, error_uri=None): msg = ( u"OAuth error from {name}! " @@ -293,14 +359,14 @@ if ub.oauth_support: @oauth.route('/github') - @github_oauth_required + @oauth_required def github_login(): if not github.authorized: return redirect(url_for('github.login')) account_info = github.get('/user') if account_info.ok: account_info_json = account_info.json() - return bind_oauth_or_register(github_blueprint.name, account_info_json['id'], 'github.login') + return bind_oauth_or_register(oauthblueprints[0]['blueprint'].name, account_info_json['id'], 'github.login') flash(_(u"GitHub Oauth error, please retry later."), category="error") return redirect(url_for('web.login')) @@ -308,23 +374,23 @@ if ub.oauth_support: @oauth.route('/unlink/github', methods=["GET"]) @login_required def github_login_unlink(): - return unlink_oauth(github_blueprint.name) + return unlink_oauth(oauthblueprints[0]['blueprint'].name) @oauth.route('/login/google') - @google_oauth_required + @oauth_required def google_login(): if not google.authorized: return redirect(url_for("google.login")) resp = google.get("/oauth2/v2/userinfo") if resp.ok: account_info_json = resp.json() - return bind_oauth_or_register(google_blueprint.name, account_info_json['id'], 'google.login') + return bind_oauth_or_register(oauthblueprints[1]['blueprint'].name, account_info_json['id'], 'google.login') flash(_(u"Google Oauth error, please retry later."), category="error") return redirect(url_for('web.login')) - @oauth_error.connect_via(google_blueprint) + @oauth_error.connect_via(oauthblueprints[1]['blueprint']) def google_error(blueprint, error, error_description=None, error_uri=None): msg = ( u"OAuth error from {name}! " @@ -341,4 +407,4 @@ if ub.oauth_support: @oauth.route('/unlink/google', methods=["GET"]) @login_required def google_login_unlink(): - return unlink_oauth(google_blueprint.name) + return unlink_oauth(oauthblueprints[1]['blueprint'].name) diff --git a/cps/static/js/main.js b/cps/static/js/main.js index 6a59c6b7..2b2716bf 100644 --- a/cps/static/js/main.js +++ b/cps/static/js/main.js @@ -37,10 +37,11 @@ $(document).on("change", "select[data-control]", function() { var showOrHide = parseInt($this.val()); // var showOrHideLast = $("#" + name + " option:last").val() for (var i = 0; i < $(this)[0].length; i++) { - if (parseInt($(this)[0][i].value) === showOrHide) { - $("[data-related=\"" + name + "-" + i + "\"]").show(); + var element = parseInt($(this)[0][i].value); + if (element === showOrHide) { + $("[data-related=" + name + "-" + element + "]").show(); } else { - $("[data-related=\"" + name + "-" + i + "\"]").hide(); + $("[data-related=" + name + "-" + element + "]").hide(); } } }); diff --git a/cps/templates/config_edit.html b/cps/templates/config_edit.html index 0c452bbd..8f9fb29a 100644 --- a/cps/templates/config_edit.html +++ b/cps/templates/config_edit.html @@ -195,8 +195,7 @@ {% endif %} {% if feature_support['oauth'] %} - - + {% endif %} @@ -256,19 +255,22 @@ {% endif %} {% if feature_support['oauth'] %}
+ {% for prov in provider %}
- {{_('Obtain GitHub OAuth Credential')}} + {{_('Obtain %(provider)s OAuth Credential', provider=prov['provider_name'])}}
- - + +
- - + +
+ {% endfor %}
-
+ + {% endif %} {% endif %}
diff --git a/cps/ub.py b/cps/ub.py index d87b5a6a..fec96312 100644 --- a/cps/ub.py +++ b/cps/ub.py @@ -186,6 +186,26 @@ if oauth_support: user_id = Column(Integer, ForeignKey(User.id)) user = relationship(User) +class OAuthProvider(Base): + __tablename__ = 'oauthProvider' + + id = Column(Integer, primary_key=True) + provider_name = Column(String) + oauth_client_id = Column(String) + oauth_client_secret = Column(String) + active = Column(Boolean) + # scope = relationship('OAuthScope', backref='oauthProvider') + + +'''class OAuthScope(Base): + __tablename__ = 'oauthScope' + id = Column(Integer, primary_key=True) + scope = Column(String, unique=True) + provider_id = Column(Integer, ForeignKey('oauthProvider.id')) + + def __repr__(self): + return u"{0}".format(self.scope)''' + # Class for anonymous user is derived from User base and completly overrides methods and properties for the # anonymous user diff --git a/optional-requirements.txt b/optional-requirements.txt index db96fbfb..474dc8be 100644 --- a/optional-requirements.txt +++ b/optional-requirements.txt @@ -18,7 +18,11 @@ python-Levenshtein>=0.12.0 # ldap login python_ldap>=3.0.0 -flask-simpleldap +flask-simpleldap>1.3.0 + +#oauth +flask-dance>=0.13.0 +sqlalchemy_utils>=0.33.5 # extracting metadata lxml>=3.8.0