Moved config class into separate file.
Moved Goodreads and LDAP services into separate package.
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# This file is part of the Calibre-Web (https://github.com/janeczku/calibre-web)
|
||||
# Copyright (C) 2019 pwr
|
||||
#
|
||||
# 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
from __future__ import division, print_function, unicode_literals
|
||||
|
||||
from .. import logger
|
||||
|
||||
|
||||
log = logger.create()
|
||||
|
||||
|
||||
try: from . import goodreads
|
||||
except ImportError as err:
|
||||
log.warning("goodreads: %s", err)
|
||||
goodreads = None
|
||||
|
||||
|
||||
try: from . import simpleldap as ldap
|
||||
except ImportError as err:
|
||||
log.warning("simpleldap: %s", err)
|
||||
ldap = None
|
||||
@@ -0,0 +1,106 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# This file is part of the Calibre-Web (https://github.com/janeczku/calibre-web)
|
||||
# Copyright (C) 2018-2019 OzzieIsaacs, pwr
|
||||
#
|
||||
# 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
from __future__ import division, print_function, unicode_literals
|
||||
import time
|
||||
from functools import reduce
|
||||
|
||||
from goodreads.client import GoodreadsClient
|
||||
|
||||
try: import Levenshtein
|
||||
except ImportError: Levenshtein = False
|
||||
|
||||
from .. import logger
|
||||
|
||||
|
||||
log = logger.create()
|
||||
_client = None # type: GoodreadsClient
|
||||
|
||||
# GoodReads TOS allows for 24h caching of data
|
||||
_CACHE_TIMEOUT = 23 * 60 * 60 # 23 hours (in seconds)
|
||||
_AUTHORS_CACHE = {}
|
||||
|
||||
|
||||
def connect(key=None, secret=None, enabled=True):
|
||||
global _client
|
||||
|
||||
if not enabled or not key or not secret:
|
||||
_client = None
|
||||
return
|
||||
|
||||
if _client:
|
||||
# make sure the configuration has not changed since last we used the client
|
||||
if _client.client_key != key or _client.client_secret != secret:
|
||||
_client = None
|
||||
|
||||
if not _client:
|
||||
_client = GoodreadsClient(key, secret)
|
||||
|
||||
|
||||
def get_author_info(author_name):
|
||||
now = time.time()
|
||||
author_info = _AUTHORS_CACHE.get(author_name, None)
|
||||
if author_info:
|
||||
if now < author_info._timestamp + _CACHE_TIMEOUT:
|
||||
return author_info
|
||||
# clear expired entries
|
||||
del _AUTHORS_CACHE[author_name]
|
||||
|
||||
if not _client:
|
||||
log.warning("failed to get a Goodreads client")
|
||||
return
|
||||
|
||||
try:
|
||||
author_info = _client.find_author(author_name=author_name)
|
||||
except Exception as ex:
|
||||
# Skip goodreads, if site is down/inaccessible
|
||||
log.warning('Goodreads website is down/inaccessible? %s', ex)
|
||||
return
|
||||
|
||||
if author_info:
|
||||
author_info._timestamp = now
|
||||
_AUTHORS_CACHE[author_name] = author_info
|
||||
return author_info
|
||||
|
||||
|
||||
def get_other_books(author_info, library_books=None):
|
||||
# Get all identifiers (ISBN, Goodreads, etc) and filter author's books by that list so we show fewer duplicates
|
||||
# Note: Not all images will be shown, even though they're available on Goodreads.com.
|
||||
# See https://www.goodreads.com/topic/show/18213769-goodreads-book-images
|
||||
|
||||
if not author_info:
|
||||
return
|
||||
|
||||
identifiers = []
|
||||
library_titles = []
|
||||
if library_books:
|
||||
identifiers = list(reduce(lambda acc, book: acc + [i.val for i in book.identifiers if i.val], library_books, []))
|
||||
library_titles = [book.title for book in library_books]
|
||||
|
||||
for book in author_info.books:
|
||||
if book.isbn in identifiers:
|
||||
continue
|
||||
if book.gid["#text"] in identifiers:
|
||||
continue
|
||||
|
||||
if Levenshtein and library_titles:
|
||||
goodreads_title = book._book_dict['title_without_series']
|
||||
if any(Levenshtein.ratio(goodreads_title, title) > 0.7 for title in library_titles):
|
||||
continue
|
||||
|
||||
yield book
|
||||
@@ -0,0 +1,77 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# This file is part of the Calibre-Web (https://github.com/janeczku/calibre-web)
|
||||
# Copyright (C) 2018-2019 OzzieIsaacs, pwr
|
||||
#
|
||||
# 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
from __future__ import division, print_function, unicode_literals
|
||||
import base64
|
||||
|
||||
from flask_simpleldap import LDAP
|
||||
from ldap import SERVER_DOWN, INVALID_CREDENTIALS
|
||||
|
||||
from .. import constants, logger
|
||||
|
||||
|
||||
log = logger.create()
|
||||
_ldap = None
|
||||
|
||||
|
||||
def init_app(app, config):
|
||||
global _ldap
|
||||
|
||||
if config.config_login_type != constants.LOGIN_LDAP:
|
||||
_ldap = None
|
||||
return
|
||||
|
||||
app.config['LDAP_HOST'] = config.config_ldap_provider_url
|
||||
app.config['LDAP_PORT'] = config.config_ldap_port
|
||||
app.config['LDAP_SCHEMA'] = config.config_ldap_schema
|
||||
app.config['LDAP_USERNAME'] = config.config_ldap_user_object.replace('%s', config.config_ldap_serv_username)\
|
||||
+ ',' + config.config_ldap_dn
|
||||
app.config['LDAP_PASSWORD'] = base64.b64decode(config.config_ldap_serv_password)
|
||||
app.config['LDAP_REQUIRE_CERT'] = bool(config.config_ldap_require_cert)
|
||||
if config.config_ldap_require_cert:
|
||||
app.config['LDAP_CERT_PATH'] = config.config_ldap_cert_path
|
||||
app.config['LDAP_BASE_DN'] = config.config_ldap_dn
|
||||
app.config['LDAP_USER_OBJECT_FILTER'] = config.config_ldap_user_object
|
||||
app.config['LDAP_USE_SSL'] = bool(config.config_ldap_use_ssl)
|
||||
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 = LDAP(app)
|
||||
|
||||
|
||||
def basic_auth_required(func):
|
||||
return _ldap.basic_auth_required(func)
|
||||
|
||||
|
||||
def bind_user(username, password):
|
||||
'''Attempts a LDAP login.
|
||||
|
||||
:returns: True if login succeeded, False if login failed, None if server unavailable.
|
||||
'''
|
||||
try:
|
||||
result = _ldap.bind_user(username, password)
|
||||
log.debug("LDAP login '%s': %r", username, result)
|
||||
return result is not None
|
||||
except SERVER_DOWN as ex:
|
||||
log.warning('LDAP Server down: %s', ex)
|
||||
return None
|
||||
except INVALID_CREDENTIALS as ex:
|
||||
log.info("LDAP login '%s' failed: %s", username, ex)
|
||||
return False
|
||||
Reference in New Issue
Block a user