diff --git a/cps/about.py b/cps/about.py index 451b6411..7c61dbd0 100644 --- a/cps/about.py +++ b/cps/about.py @@ -31,7 +31,10 @@ from flask_babel import gettext as _ from . import db, converter, uploader, server, isoLanguages from .web import render_title_template - +try: + from flask_login import __version__ as flask_loginVersion +except ImportError: + from flask_login.__about__ import __version__ as flask_loginVersion about = flask.Blueprint('about', __name__) @@ -40,7 +43,7 @@ _VERSIONS = OrderedDict( Python=sys.version, WebServer=server.VERSION, Flask=flask.__version__, - Flask_Login=flask_login.__version__, + Flask_Login=flask_loginVersion, Flask_Principal=flask_principal.__version__, Werkzeug=werkzeug.__version__, Babel=babel.__version__, diff --git a/cps/admin.py b/cps/admin.py index e25e692f..b6dcf66a 100644 --- a/cps/admin.py +++ b/cps/admin.py @@ -45,7 +45,7 @@ from .gdriveutils import is_gdrive_ready, gdrive_support from .web import admin_required, render_title_template, before_request, unconfigured, login_required_if_no_ano feature_support = { - 'ldap': bool(services.ldap), + 'ldap': False, # bool(services.ldap), 'goodreads': bool(services.goodreads) } @@ -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 = {} @@ -343,18 +344,27 @@ def _configuration_update_helper(): _config_int("config_updatechannel") # GitHub OAuth configuration - if config.config_login_type == constants.LOGIN_OAUTH_GITHUB: - _config_string("config_github_oauth_client_id") - _config_string("config_github_oauth_client_secret") - if not config.config_github_oauth_client_id or not config.config_github_oauth_client_secret: - return _configuration_result('Please enter Github oauth credentials', gdriveError) - - # Google OAuth configuration - if config.config_login_type == constants.LOGIN_OAUTH_GOOGLE: - _config_string("config_google_oauth_client_id") - _config_string("config_google_oauth_client_secret") - if not config.config_google_oauth_client_id or not config.config_google_oauth_client_secret: - return _configuration_result('Please enter Google oauth credentials', gdriveError) + if config.config_login_type == constants.LOGIN_OAUTH: + active_oauths = 0 + + for element in oauthblueprints: + if to_save["config_"+str(element['id'])+"_oauth_client_id"] \ + and to_save["config_"+str(element['id'])+"_oauth_client_secret"]: + active_oauths += 1 + element["active"] = 1 + ub.session.query(ub.OAuthProvider).filter(ub.OAuthProvider.id == element['id']).update( + {"oauth_client_id":to_save["config_"+str(element['id'])+"_oauth_client_id"], + "oauth_client_secret":to_save["config_"+str(element['id'])+"_oauth_client_secret"], + "active":1}) + if to_save["config_" + str(element['id']) + "_oauth_client_id"] != element['oauth_client_id'] \ + or to_save["config_" + str(element['id']) + "_oauth_client_secret"] != element['oauth_client_secret']: + reboot_required = True + element['oauth_client_id'] = to_save["config_"+str(element['id'])+"_oauth_client_id"] + element['oauth_client_secret'] = to_save["config_"+str(element['id'])+"_oauth_client_secret"] + else: + ub.session.query(ub.OAuthProvider).filter(ub.OAuthProvider.id == element['id']).update( + {"active":0}) + element["active"] = 0 _config_int("config_log_level") _config_string("config_logfile") @@ -410,7 +420,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, @@ -653,7 +663,7 @@ def send_logfile(logtype): @admi.route("/get_update_status", methods=['GET']) @login_required_if_no_ano def get_update_status(): - return updater_thread.get_available_updates(request.method) + return updater_thread.get_available_updates(request.method, locale=get_locale()) @admi.route("/get_updater_status", methods=['GET', 'POST']) diff --git a/cps/comic.py b/cps/comic.py index 738b2a89..d642eaf6 100755 --- a/cps/comic.py +++ b/cps/comic.py @@ -31,7 +31,7 @@ try: from comicapi.comicarchive import ComicArchive, MetaDataStyle use_comic_meta = True except ImportError as e: - log.warning('cannot import comicapi, extracting comic metadata will not work: %s', e) + log.debug('cannot import comicapi, extracting comic metadata will not work: %s', e) import zipfile import tarfile use_comic_meta = False diff --git a/cps/config_sql.py b/cps/config_sql.py index 0089ad0f..809e97d8 100644 --- a/cps/config_sql.py +++ b/cps/config_sql.py @@ -20,6 +20,7 @@ from __future__ import division, print_function, unicode_literals import os import json +import sys from sqlalchemy import exc, Column, String, Integer, SmallInteger, Boolean from sqlalchemy.ext.declarative import declarative_base @@ -43,41 +44,48 @@ class _Settings(_Base): mail_login = Column(String, default='mail@example.com') mail_password = Column(String, default='mypassword') mail_from = Column(String, default='automailer ') + config_calibre_dir = Column(String) config_port = Column(Integer, default=constants.DEFAULT_PORT) config_certfile = Column(String) config_keyfile = Column(String) + config_calibre_web_title = Column(String, default=u'Calibre-Web') config_books_per_page = Column(Integer, default=60) config_random_books = Column(Integer, default=4) config_authors_max = Column(Integer, default=0) config_read_column = Column(Integer, default=0) - config_title_regex = Column(String, default=r'^(A|The|An|Der|Die|Das|Den|Ein|Eine|Einen|Dem|Des|Einem|Eines)\s+') + config_title_regex = Column(String, default=u'^(A|The|An|Der|Die|Das|Den|Ein|Eine|Einen|Dem|Des|Einem|Eines)\s+') + config_mature_content_tags = Column(String, default='') + config_theme = Column(Integer, default=0) + config_log_level = Column(SmallInteger, default=logger.DEFAULT_LOG_LEVEL) + config_logfile = Column(String) config_access_log = Column(SmallInteger, default=0) + config_access_logfile = Column(String) + config_uploading = Column(SmallInteger, default=0) config_anonbrowse = Column(SmallInteger, default=0) config_public_reg = Column(SmallInteger, default=0) + config_remote_login = Column(Boolean, default=False) + + config_default_role = Column(SmallInteger, default=0) config_default_show = Column(SmallInteger, default=6143) config_columns_to_ignore = Column(String) + config_use_google_drive = Column(Boolean, default=False) config_google_drive_folder = Column(String) config_google_drive_watch_changes_response = Column(String) - config_remote_login = Column(Boolean, default=False) + config_use_goodreads = Column(Boolean, default=False) config_goodreads_api_key = Column(String) config_goodreads_api_secret = Column(String) + config_login_type = Column(Integer, default=0) - # config_use_ldap = Column(Boolean) - config_ldap_provider_url = Column(String) - config_ldap_dn = Column(String) - # config_use_github_oauth = Column(Boolean) - config_github_oauth_client_id = Column(String) - config_github_oauth_client_secret = Column(String) - # config_use_google_oauth = Column(Boolean) - config_google_oauth_client_id = Column(String) - config_google_oauth_client_secret = Column(String) + + # config_oauth_provider = Column(Integer) + config_ldap_provider_url = Column(String, default='localhost') config_ldap_port = Column(SmallInteger, default=389) config_ldap_schema = Column(String, default='ldap') @@ -90,14 +98,12 @@ class _Settings(_Base): config_ldap_dn = Column(String) config_ldap_user_object = Column(String) config_ldap_openldap = Column(Boolean, default=False) - config_mature_content_tags = Column(String, default='') - config_logfile = Column(String) - config_access_logfile = Column(String) + config_ebookconverter = Column(Integer, default=0) config_converterpath = Column(String) config_calibre = Column(String) config_rarfile_location = Column(String) - config_theme = Column(Integer, default=0) + config_updatechannel = Column(Integer, default=constants.UPDATE_STABLE) def __repr__(self): @@ -106,6 +112,7 @@ class _Settings(_Base): # Class holds all application specific settings in calibre-web class _ConfigSQL(object): + # pylint: disable=no-member def __init__(self, session): self._session = session self._settings = None @@ -264,8 +271,15 @@ def _migrate_table(session, orm_class): session.query(column).first() except exc.OperationalError as err: log.debug("%s: %s", column_name, err) + if column.default is not None: + if sys.version_info < (3, 0): + if isinstance(column.default.arg,unicode): + column.default.arg = column.default.arg.encode('utf-8') column_default = "" if column.default is None else ("DEFAULT %r" % column.default.arg) - alter_table = "ALTER TABLE %s ADD COLUMN `%s` %s %s" % (orm_class.__tablename__, column_name, column.type, column_default) + alter_table = "ALTER TABLE %s ADD COLUMN `%s` %s %s" % (orm_class.__tablename__, + column_name, + column.type, + column_default) log.debug(alter_table) session.execute(alter_table) changed = True @@ -273,6 +287,17 @@ def _migrate_table(session, orm_class): if changed: session.commit() +def autodetect_calibre_binary(): + if sys.platform == "win32": + calibre_path = ["C:\\program files\calibre\calibre-convert.exe", + "C:\\program files(x86)\calibre\calibre-convert.exe"] + else: + calibre_path = ["/opt/calibre/ebook-convert"] + for element in calibre_path: + if os.path.isfile(element) and os.access(element, os.X_OK): + return element + return None + def _migrate_database(session): # make sure the table is created, if it does not exist diff --git a/cps/constants.py b/cps/constants.py index 9d4938b2..97b13403 100644 --- a/cps/constants.py +++ b/cps/constants.py @@ -21,6 +21,7 @@ import sys import os from collections import namedtuple +HOME_CONFIG = False # Base dir is parent of current file, necessary if called from different folder if sys.version_info < (3, 0): @@ -32,7 +33,14 @@ else: STATIC_DIR = os.path.join(BASE_DIR, 'cps', 'static') TEMPLATES_DIR = os.path.join(BASE_DIR, 'cps', 'templates') TRANSLATIONS_DIR = os.path.join(BASE_DIR, 'cps', 'translations') -CONFIG_DIR = os.environ.get('CALIBRE_DBPATH', BASE_DIR) + +if HOME_CONFIG: + home_dir = os.path.join(os.path.expanduser("~"),".calibre-web") + if not os.path.exists(home_dir): + os.makedirs(home_dir) + CONFIG_DIR = os.environ.get('CALIBRE_DBPATH', home_dir) +else: + CONFIG_DIR = os.environ.get('CALIBRE_DBPATH', BASE_DIR) ROLE_USER = 0 << 0 @@ -83,8 +91,8 @@ AUTO_UPDATE_NIGHTLY = 1 << 2 LOGIN_STANDARD = 0 LOGIN_LDAP = 1 -LOGIN_OAUTH_GITHUB = 2 -LOGIN_OAUTH_GOOGLE = 3 +LOGIN_OAUTH = 2 +# LOGIN_OAUTH_GOOGLE = 3 DEFAULT_PASSWORD = "admin123" @@ -116,7 +124,7 @@ def selected_roles(dictionary): BookMeta = namedtuple('BookMeta', 'file_path, extension, title, author, cover, description, tags, series, ' 'series_id, languages') -STABLE_VERSION = {'version': '0.6.4 Beta'} +STABLE_VERSION = {'version': '0.6.5 Beta'} NIGHTLY_VERSION = {} NIGHTLY_VERSION[0] = '$Format:%H$' diff --git a/cps/gdriveutils.py b/cps/gdriveutils.py index 4ec7f68e..4ebbb0c7 100644 --- a/cps/gdriveutils.py +++ b/cps/gdriveutils.py @@ -39,12 +39,12 @@ except ImportError: gdrive_support = False from . import logger, cli, config -from .constants import BASE_DIR as _BASE_DIR +from .constants import CONFIG_DIR as _CONFIG_DIR -SETTINGS_YAML = os.path.join(_BASE_DIR, 'settings.yaml') -CREDENTIALS = os.path.join(_BASE_DIR, 'gdrive_credentials') -CLIENT_SECRETS = os.path.join(_BASE_DIR, 'client_secrets.json') +SETTINGS_YAML = os.path.join(_CONFIG_DIR, 'settings.yaml') +CREDENTIALS = os.path.join(_CONFIG_DIR, 'gdrive_credentials') +CLIENT_SECRETS = os.path.join(_CONFIG_DIR, 'client_secrets.json') log = logger.create() diff --git a/cps/helper.py b/cps/helper.py index c94093db..f2fe7572 100644 --- a/cps/helper.py +++ b/cps/helper.py @@ -71,14 +71,6 @@ from .worker import TASK_EMAIL, TASK_CONVERT, TASK_UPLOAD, TASK_CONVERT_ANY log = logger.create() -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() - if not check: - new_download = ub.Downloads(user_id=user_id, book_id=book_id) - ub.session.add(new_download) - ub.session.commit() - # Convert existing book entry to new format def convert_book_format(book_id, calibrepath, old_book_format, new_book_format, user_id, kindle_mail=None): book = db.session.query(db.Books).filter(db.Books.id == book_id).first() @@ -563,6 +555,7 @@ def check_unrar(unrarLocation): try: if sys.version_info < (3, 0): unrarLocation = unrarLocation.encode(sys.getfilesystemencoding()) + unrarLocation = [unrarLocation] for lines in process_wait(unrarLocation): value = re.search('UNRAR (.*) freeware', lines) if value: diff --git a/cps/logger.py b/cps/logger.py index 50fab983..892dd252 100644 --- a/cps/logger.py +++ b/cps/logger.py @@ -23,7 +23,7 @@ import logging from logging import Formatter, StreamHandler from logging.handlers import RotatingFileHandler -from .constants import BASE_DIR as _BASE_DIR +from .constants import CONFIG_DIR as _CONFIG_DIR ACCESS_FORMATTER_GEVENT = Formatter("%(message)s") @@ -31,8 +31,8 @@ ACCESS_FORMATTER_TORNADO = Formatter("[%(asctime)s] %(message)s") FORMATTER = Formatter("[%(asctime)s] %(levelname)5s {%(name)s:%(lineno)d} %(message)s") DEFAULT_LOG_LEVEL = logging.INFO -DEFAULT_LOG_FILE = os.path.join(_BASE_DIR, "calibre-web.log") -DEFAULT_ACCESS_LOG = os.path.join(_BASE_DIR, "access.log") +DEFAULT_LOG_FILE = os.path.join(_CONFIG_DIR, "calibre-web.log") +DEFAULT_ACCESS_LOG = os.path.join(_CONFIG_DIR, "access.log") LOG_TO_STDERR = '/dev/stderr' logging.addLevelName(logging.WARNING, "WARN") @@ -76,7 +76,7 @@ def is_valid_logfile(file_path): def _absolute_log_file(log_file, default_log_file): if log_file: if not os.path.dirname(log_file): - log_file = os.path.join(_BASE_DIR, log_file) + log_file = os.path.join(_CONFIG_DIR, log_file) return os.path.abspath(log_file) return default_log_file @@ -95,6 +95,11 @@ def setup(log_file, log_level=None): Configure the logging output. May be called multiple times. ''' + # if debugging, start logging to stderr immediately + if os.environ.get('FLASK_DEBUG', None): + log_file = LOG_TO_STDERR + log_level = logging.DEBUG + log_file = _absolute_log_file(log_file, DEFAULT_LOG_FILE) log_level = log_level or DEFAULT_LOG_LEVEL @@ -162,8 +167,3 @@ class StderrLogger(object): self.buffer += message except Exception: self.log.debug("Logging Error") - - -# if debugging, start logging to stderr immediately -if os.environ.get('FLASK_DEBUG', None): - setup(LOG_TO_STDERR, logging.DEBUG) diff --git a/cps/oauth.py b/cps/oauth.py index 35362dbf..f08c66df 100644 --- a/cps/oauth.py +++ b/cps/oauth.py @@ -1,6 +1,22 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- +# This file is part of the Calibre-Web (https://github.com/janeczku/calibre-web) +# Copyright (C) 2018-2019 jim3ma +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see + from __future__ import division, print_function, unicode_literals from flask import session @@ -16,13 +32,14 @@ try: .. _SQLAlchemy: http://www.sqlalchemy.org/ """ - def __init__(self, model, session, + def __init__(self, model, session, provider_id, user=None, user_id=None, user_required=None, anon_user=None, cache=None): + self.provider_id = provider_id super(OAuthBackend, self).__init__(model, session, user, user_id, user_required, anon_user, cache) def get(self, blueprint, user=None, user_id=None): - if blueprint.name + '_oauth_token' in session and session[blueprint.name + '_oauth_token'] != '': + if self.provider_id + '_oauth_token' in session and session[self.provider_id + '_oauth_token'] != '': return session[blueprint.name + '_oauth_token'] # check cache cache_key = self.make_cache_key(blueprint=blueprint, user=user, user_id=user_id) @@ -33,15 +50,15 @@ try: # if not cached, make database queries query = ( self.session.query(self.model) - .filter_by(provider=blueprint.name) + .filter_by(provider=self.provider_id) ) uid = first([user_id, self.user_id, blueprint.config.get("user_id")]) u = first(_get_real_user(ref, self.anon_user) for ref in (user, self.user, blueprint.config.get("user"))) use_provider_user_id = False - if blueprint.name + '_oauth_user_id' in session and session[blueprint.name + '_oauth_user_id'] != '': - query = query.filter_by(provider_user_id=session[blueprint.name + '_oauth_user_id']) + if self.provider_id + '_oauth_user_id' in session and session[self.provider_id + '_oauth_user_id'] != '': + query = query.filter_by(provider_user_id=session[self.provider_id + '_oauth_user_id']) use_provider_user_id = True if self.user_required and not u and not uid and not use_provider_user_id: @@ -78,7 +95,7 @@ try: # if there was an existing model, delete it existing_query = ( self.session.query(self.model) - .filter_by(provider=blueprint.name) + .filter_by(provider=self.provider_id) ) # check for user ID has_user_id = hasattr(self.model, "user_id") @@ -92,7 +109,7 @@ try: existing_query.delete() # create a new model for this token kwargs = { - "provider": blueprint.name, + "provider": self.provider_id, "token": token, } if has_user_id and uid: @@ -110,7 +127,7 @@ try: def delete(self, blueprint, user=None, user_id=None): query = ( self.session.query(self.model) - .filter_by(provider=blueprint.name) + .filter_by(provider=self.provider_id) ) uid = first([user_id, self.user_id, blueprint.config.get("user_id")]) u = first(_get_real_user(ref, self.anon_user) diff --git a/cps/oauth_bb.py b/cps/oauth_bb.py index 39777911..092473da 100644 --- a/cps/oauth_bb.py +++ b/cps/oauth_bb.py @@ -45,10 +45,10 @@ oauth = Blueprint('oauth', __name__) log = logger.create() -def github_oauth_required(f): +def oauth_required(f): @wraps(f) def inner(*args, **kwargs): - if config.config_login_type == constants.LOGIN_OAUTH_GITHUB: + if config.config_login_type == constants.LOGIN_OAUTH: return f(*args, **kwargs) if request.is_xhr: data = {'status': 'error', 'message': 'Not Found'} @@ -60,30 +60,14 @@ def github_oauth_required(f): return inner -def google_oauth_required(f): - @wraps(f) - def inner(*args, **kwargs): - if config.config_use_google_oauth == constants.LOGIN_OAUTH_GOOGLE: - 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 - - -def register_oauth_blueprint(blueprint, show_name): - if blueprint.name != "": - oauth_check[blueprint.name] = show_name +def register_oauth_blueprint(id, show_name): + oauth_check[id] = show_name def register_user_with_oauth(user=None): all_oauth = {} for oauth in oauth_check.keys(): - if oauth + '_oauth_user_id' in session and session[oauth + '_oauth_user_id'] != '': + if str(oauth) + '_oauth_user_id' in session and session[str(oauth) + '_oauth_user_id'] != '': all_oauth[oauth] = oauth_check[oauth] if len(all_oauth.keys()) == 0: return @@ -94,7 +78,7 @@ def register_user_with_oauth(user=None): # Find this OAuth token in the database, or create it query = ub.session.query(ub.OAuth).filter_by( provider=oauth, - provider_user_id=session[oauth + "_oauth_user_id"], + provider_user_id=session[str(oauth) + "_oauth_user_id"], ) try: oauth = query.one() @@ -111,39 +95,61 @@ def register_user_with_oauth(user=None): def logout_oauth_user(): for oauth in oauth_check.keys(): - if oauth + '_oauth_user_id' in session: - session.pop(oauth + '_oauth_user_id') + if str(oauth) + '_oauth_user_id' in session: + session.pop(str(oauth) + '_oauth_user_id') if ub.oauth_support: - 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",) - - google_blueprint = make_google_blueprint( - client_id=config.config_google_oauth_client_id, - client_secret=config.config_google_oauth_client_secret, - redirect_to="oauth.google_login", - scope=[ - "https://www.googleapis.com/auth/plus.me", - "https://www.googleapis.com/auth/userinfo.email", - ] - ) - - app.register_blueprint(google_blueprint, url_prefix="/login") - 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) - - - 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') + 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() + + oauth_ids = ub.session.query(ub.OAuthProvider).all() + ele1=dict(provider_name='github', + id=oauth_ids[0].id, + active=oauth_ids[0].active, + oauth_client_id=oauth_ids[0].oauth_client_id, + scope=None, + oauth_client_secret=oauth_ids[0].oauth_client_secret, + obtain_link='https://github.com/settings/developers') + ele2=dict(provider_name='google', + id=oauth_ids[1].id, + active=oauth_ids[1].active, + scope=["https://www.googleapis.com/auth/plus.me", "https://www.googleapis.com/auth/userinfo.email"], + oauth_client_id=oauth_ids[1].oauth_client_id, + oauth_client_secret=oauth_ids[1].oauth_client_secret, + 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, str(element['id']), + user=current_user, user_required=True) + if element['active']: + register_oauth_blueprint(element['id'], element['provider_name']) - @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") @@ -156,10 +162,10 @@ if ub.oauth_support: github_info = resp.json() github_user_id = str(github_info["id"]) - return oauth_update_token(blueprint, token, github_user_id) + return oauth_update_token(str(oauthblueprints[0]['id']), 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") @@ -172,17 +178,16 @@ if ub.oauth_support: google_info = resp.json() google_user_id = str(google_info["id"]) + return oauth_update_token(str(oauthblueprints[1]['id']), token, google_user_id) - return oauth_update_token(blueprint, token, google_user_id) - - def oauth_update_token(blueprint, token, provider_user_id): - session[blueprint.name + "_oauth_user_id"] = provider_user_id - session[blueprint.name + "_oauth_token"] = token + def oauth_update_token(provider_id, token, provider_user_id): + session[provider_id + "_oauth_user_id"] = provider_user_id + session[provider_id + "_oauth_token"] = token # Find this OAuth token in the database, or create it query = ub.session.query(ub.OAuth).filter_by( - provider=blueprint.name, + provider=provider_id, provider_user_id=provider_user_id, ) try: @@ -191,7 +196,7 @@ if ub.oauth_support: oauth.token = token except NoResultFound: oauth = ub.OAuth( - provider=blueprint.name, + provider=provider_id, provider_user_id=provider_user_id, token=token, ) @@ -206,9 +211,9 @@ if ub.oauth_support: return False - def bind_oauth_or_register(provider, provider_user_id, redirect_url): + def bind_oauth_or_register(provider_id, provider_user_id, redirect_url): query = ub.session.query(ub.OAuth).filter_by( - provider=provider, + provider=provider_id, provider_user_id=provider_user_id, ) try: @@ -245,7 +250,7 @@ if ub.oauth_support: try: oauths = query.all() for oauth in oauths: - status.append(oauth.provider) + status.append(int(oauth.provider)) return status except NoResultFound: return None @@ -278,7 +283,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 +298,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]['id'], account_info_json['id'], 'github.login') flash(_(u"GitHub Oauth error, please retry later."), category="error") return redirect(url_for('web.login')) @@ -308,23 +313,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]['id']) @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]['id'], 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 +346,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/services/simpleldap.py b/cps/services/simpleldap.py index 7feec202..42a9aacd 100644 --- a/cps/services/simpleldap.py +++ b/cps/services/simpleldap.py @@ -47,8 +47,6 @@ def init_app(app, config): app.config['LDAP_USE_TLS'] = bool(config.config_ldap_use_tls) app.config['LDAP_OPENLDAP'] = bool(config.config_ldap_openldap) - # app.config['LDAP_BASE_DN'] = 'ou=users,dc=yunohost,dc=org' - # app.config['LDAP_USER_OBJECT_FILTER'] = '(uid=%s)' _ldap.init_app(app) diff --git a/cps/static/css/style.css b/cps/static/css/style.css index 1880207a..aaa7503e 100644 --- a/cps/static/css/style.css +++ b/cps/static/css/style.css @@ -141,6 +141,7 @@ input.pill:not(:checked) + label .glyphicon { .filterheader { margin-bottom: 20px; } +.errorlink {margin-top: 20px;} .modal-body .comments { max-height:300px; overflow-y: auto; 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 de4063c9..4a5b154d 100644 --- a/cps/templates/config_edit.html +++ b/cps/templates/config_edit.html @@ -19,6 +19,7 @@ + {% if feature_support['gdrive'] %}
@@ -66,6 +67,7 @@ {% endif %} {% endif %}
+ {% endif %} @@ -193,8 +195,7 @@ {% endif %} {% if feature_support['oauth'] %} - - + {% endif %} @@ -254,30 +255,19 @@ {% endif %} {% if feature_support['oauth'] %}
+ {% for prov in provider %} -
- - -
-
- - -
-
-
-
- - + +
- - + +
+ {% endfor %}
{% endif %} {% endif %} diff --git a/cps/templates/http_error.html b/cps/templates/http_error.html index 36471fce..1f09a79d 100644 --- a/cps/templates/http_error.html +++ b/cps/templates/http_error.html @@ -17,10 +17,34 @@ {% endif %} -
-

{{ error_code }}

+
+
+
+

{{ error_code }}

{{ error_name }}

+
+
+
+
+ {% for element in error_stack %} +
{{ element }}
+ {% endfor %} +
+
+ {% if issue %} +
+ +
+ {% endif %} + + + +
diff --git a/cps/templates/languages.html b/cps/templates/languages.html index 548abaec..3c30e4d0 100644 --- a/cps/templates/languages.html +++ b/cps/templates/languages.html @@ -10,9 +10,10 @@ {% endif %}
{{lang_counter[loop.index0].bookcount}}
- +
{% endfor %}
{% endblock %} + diff --git a/cps/templates/read.html b/cps/templates/read.html index 8cb9dd62..88eaba0d 100644 --- a/cps/templates/read.html +++ b/cps/templates/read.html @@ -79,15 +79,6 @@
-