User and admin pages are working again

This commit is contained in:
Ozzieisaacs 2019-02-09 21:26:17 +01:00
parent 1fc4bc5204
commit c1ef1bcd19
5 changed files with 107 additions and 42 deletions

View File

@ -38,7 +38,7 @@ from sqlalchemy.exc import IntegrityError
from gdriveutils import is_gdrive_ready, gdrive_support, downloadFile, deleteDatabaseOnChange, listRootFolders from gdriveutils import is_gdrive_ready, gdrive_support, downloadFile, deleteDatabaseOnChange, listRootFolders
import helper import helper
from werkzeug.security import generate_password_hash from werkzeug.security import generate_password_hash
from sqlalchemy.sql.expression import text from oauth_bb import oauth_check
try: try:
from goodreads.client import GoodreadsClient from goodreads.client import GoodreadsClient
@ -591,7 +591,7 @@ def new_user():
content.sidebar_view = config.config_default_show content.sidebar_view = config.config_default_show
content.mature_content = bool(config.config_default_show & ub.MATURE_CONTENT) content.mature_content = bool(config.config_default_show & ub.MATURE_CONTENT)
return render_title_template("user_edit.html", new_user=1, content=content, translations=translations, return render_title_template("user_edit.html", new_user=1, content=content, translations=translations,
languages=languages, title=_(u"Add new user"), page="newuser") languages=languages, title=_(u"Add new user"), page="newuser", registered_oauth=oauth_check)
@admi.route("/admin/mailsettings", methods=["GET", "POST"]) @admi.route("/admin/mailsettings", methods=["GET", "POST"])
@ -767,7 +767,7 @@ def edit_user(user_id):
flash(_(u"An unknown error occured."), category="error") flash(_(u"An unknown error occured."), category="error")
return render_title_template("user_edit.html", translations=translations, languages=languages, new_user=0, return render_title_template("user_edit.html", translations=translations, languages=languages, new_user=0,
content=content, downloads=downloads, title=_(u"Edit User %(nick)s", content=content, downloads=downloads, title=_(u"Edit User %(nick)s",
nick=content.nickname), page="edituser") nick=content.nickname), page="edituser", registered_oauth=oauth_check)
@admi.route("/admin/resetpassword/<int:user_id>") @admi.route("/admin/resetpassword/<int:user_id>")

39
cps/ldap.py Normal file
View File

@ -0,0 +1,39 @@
#!/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 Krakinou
#
# 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/>.
import ldap
from cps import ub, app, request
from flask import flash, url_for
from redirect import redirect_back
from flask_login import login_user
from flask_babel import gettext as _
def login(form, user):
try:
ub.User.try_login(form['username'], form['password'])
login_user(user, remember=True)
flash(_(u"you are now logged in as: '%(nickname)s'", nickname=user.nickname), category="success")
return redirect_back(url_for("web.index"))
except ldap.INVALID_CREDENTIALS:
ipAdress = request.headers.get('X-Forwarded-For', request.remote_addr)
app.logger.info('LDAP Login failed for user "' + form['username'] + '" IP-adress: ' + ipAdress)
flash(_(u"Wrong Username or Password"), category="error")
def logout():
pass

View File

@ -25,16 +25,33 @@ from flask_dance.contrib.google import make_google_blueprint, google
from flask_dance.consumer import oauth_authorized, oauth_error from flask_dance.consumer import oauth_authorized, oauth_error
from sqlalchemy.orm.exc import NoResultFound from sqlalchemy.orm.exc import NoResultFound
from oauth import OAuthBackend from oauth import OAuthBackend
from flask import flash, session, redirect, url_for, request from flask import flash, session, redirect, url_for, request, make_response, abort
import json
from cps import config, app from cps import config, app
import ub import ub
from flask_login import login_user, login_required, current_user from flask_login import login_user, login_required, current_user
from flask_babel import gettext as _ from flask_babel import gettext as _
from web import github_oauth_required # from web import github_oauth_required
from functools import wraps
oauth_check = {} oauth_check = {}
def github_oauth_required(f):
@wraps(f)
def inner(*args, **kwargs):
if config.config_use_github_oauth:
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): def register_oauth_blueprint(blueprint, show_name):
if blueprint.name != "": if blueprint.name != "":
oauth_check[blueprint.name] = show_name oauth_check[blueprint.name] = show_name
@ -246,7 +263,7 @@ def github_error(blueprint, error, error_description=None, error_uri=None):
) )
flash(msg, category="error") flash(msg, category="error")
'''
@oauth.route('/github') @oauth.route('/github')
@github_oauth_required @github_oauth_required
def github_login(): def github_login():
@ -277,7 +294,7 @@ def google_login():
return bind_oauth_or_register(google_blueprint.name, account_info_json['id'], 'google.login') return bind_oauth_or_register(google_blueprint.name, account_info_json['id'], 'google.login')
flash(_(u"Google Oauth error, please retry later."), category="error") flash(_(u"Google Oauth error, please retry later."), category="error")
return redirect(url_for('login')) return redirect(url_for('login'))
'''
@oauth_error.connect_via(google_blueprint) @oauth_error.connect_via(google_blueprint)
def google_error(blueprint, error, error_description=None, error_uri=None): def google_error(blueprint, error, error_description=None, error_uri=None):
@ -292,8 +309,8 @@ def google_error(blueprint, error, error_description=None, error_uri=None):
) )
flash(msg, category="error") flash(msg, category="error")
'''
@oauth.route('/unlink/google', methods=["GET"]) @oauth.route('/unlink/google', methods=["GET"])
@login_required @login_required
def google_login_unlink(): def google_login_unlink():
return unlink_oauth(google_blueprint.name) return unlink_oauth(google_blueprint.name)'''

View File

@ -23,6 +23,7 @@ from sqlalchemy import exc
from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import * from sqlalchemy.orm import *
from flask_login import AnonymousUserMixin from flask_login import AnonymousUserMixin
from flask_dance.consumer.backend.sqla import OAuthConsumerMixin
import sys import sys
import os import os
import logging import logging
@ -32,6 +33,11 @@ import datetime
from binascii import hexlify from binascii import hexlify
import cli import cli
try:
import ldap
except ImportError:
pass
engine = create_engine('sqlite:///{0}'.format(cli.settingspath), echo=False) engine = create_engine('sqlite:///{0}'.format(cli.settingspath), echo=False)
Base = declarative_base() Base = declarative_base()
@ -176,13 +182,12 @@ class UserBase:
return '<User %r>' % self.nickname return '<User %r>' % self.nickname
#Login via LDAP method #Login via LDAP method
''''@staticmethod @staticmethod
def try_login(username, password): def try_login(username, password):
conn = get_ldap_connection() conn = get_ldap_connection()
conn.simple_bind_s( conn.simple_bind_s(
config.config_ldap_dn.replace("%s", username), config.config_ldap_dn.replace("%s", username),
password password)
)'''
# Baseclass for Users in Calibre-Web, settings which are depending on certain users are stored here. It is derived from # Baseclass for Users in Calibre-Web, settings which are depending on certain users are stored here. It is derived from
# User Base (all access methods are declared there) # User Base (all access methods are declared there)
@ -202,11 +207,11 @@ class User(UserBase, Base):
default_language = Column(String(3), default="all") default_language = Column(String(3), default="all")
mature_content = Column(Boolean, default=True) mature_content = Column(Boolean, default=True)
'''
class OAuth(OAuthConsumerMixin, Base): class OAuth(OAuthConsumerMixin, Base):
provider_user_id = Column(String(256)) provider_user_id = Column(String(256))
user_id = Column(Integer, ForeignKey(User.id)) user_id = Column(Integer, ForeignKey(User.id))
user = relationship(User)''' user = relationship(User)
# Class for anonymous user is derived from User base and completly overrides methods and properties for the # Class for anonymous user is derived from User base and completly overrides methods and properties for the
@ -776,6 +781,13 @@ def clean_database():
session.query(RemoteAuthToken).filter(now > RemoteAuthToken.expiration).delete() session.query(RemoteAuthToken).filter(now > RemoteAuthToken.expiration).delete()
#get LDAP connection
def get_ldap_connection():
conn = ldap.initialize('ldap://{}'.format(config.config_ldap_provider_url))
return conn
def create_default_config(): def create_default_config():
settings = Settings() settings = Settings()
settings.mail_server = "mail.example.com" settings.mail_server = "mail.example.com"

View File

@ -26,8 +26,6 @@ from flask import render_template, request, redirect, url_for, send_from_directo
from werkzeug.exceptions import default_exceptions from werkzeug.exceptions import default_exceptions
import helper import helper
import os import os
# from sqlalchemy.sql.expression import func
# from sqlalchemy.sql.expression import false
from sqlalchemy.exc import IntegrityError from sqlalchemy.exc import IntegrityError
from flask_login import login_user, logout_user, login_required, current_user from flask_login import login_user, logout_user, login_required, current_user
from flask_babel import gettext as _ from flask_babel import gettext as _
@ -36,21 +34,31 @@ from werkzeug.datastructures import Headers
from babel import Locale as LC from babel import Locale as LC
from babel.dates import format_date from babel.dates import format_date
from babel.core import UnknownLocaleError from babel.core import UnknownLocaleError
from functools import wraps
import base64 import base64
from sqlalchemy.sql import * from sqlalchemy.sql import *
import json import json
import datetime import datetime
from iso639 import languages as isoLanguages from iso639 import languages as isoLanguages
import os.path
import re import re
import db import db
import gdriveutils import gdriveutils
from redirect import redirect_back from redirect import redirect_back
from cps import lm, babel, ub, config, get_locale, language_table, app from cps import lm, babel, ub, config, get_locale, language_table, app
from pagination import Pagination from pagination import Pagination
# from admin import check_valid_domain from sqlalchemy.sql.expression import text
# from oauth_bb import oauth_check, register_user_with_oauth
from oauth_bb import oauth_check, register_user_with_oauth, logout_oauth_user, get_oauth_status
'''try:
oauth_support = True
except ImportError:
oauth_support = False'''
try:
import ldap
ldap_support = True
except ImportError:
ldap_support = False
try: try:
from googleapiclient.errors import HttpError from googleapiclient.errors import HttpError
@ -70,7 +78,7 @@ except ImportError:
levenshtein_support = False levenshtein_support = False
try: try:
from functools import reduce from functools import reduce, wraps
except ImportError: except ImportError:
pass # We're not using Python 3 pass # We're not using Python 3
@ -169,21 +177,6 @@ def remote_login_required(f):
return inner return inner
def github_oauth_required(f):
@wraps(f)
def inner(*args, **kwargs):
if config.config_use_github_oauth:
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 google_oauth_required(f): def google_oauth_required(f):
@wraps(f) @wraps(f)
def inner(*args, **kwargs): def inner(*args, **kwargs):
@ -1299,7 +1292,8 @@ def register():
try: try:
ub.session.add(content) ub.session.add(content)
ub.session.commit() ub.session.commit()
# register_user_with_oauth(content) if oauth_support:
register_user_with_oauth(content)
helper.send_registration_mail(to_save["email"], to_save["nickname"], password) helper.send_registration_mail(to_save["email"], to_save["nickname"], password)
except Exception: except Exception:
ub.session.rollback() ub.session.rollback()
@ -1316,7 +1310,8 @@ def register():
flash(_(u"This username or e-mail address is already in use."), category="error") flash(_(u"This username or e-mail address is already in use."), category="error")
return render_title_template('register.html', title=_(u"register"), page="register") return render_title_template('register.html', title=_(u"register"), page="register")
# register_user_with_oauth() if oauth_support:
register_user_with_oauth()
return render_title_template('register.html', config=config, title=_(u"register"), page="register") return render_title_template('register.html', config=config, title=_(u"register"), page="register")
@ -1330,7 +1325,7 @@ def login():
form = request.form.to_dict() form = request.form.to_dict()
user = ub.session.query(ub.User).filter(func.lower(ub.User.nickname) == form['username'].strip().lower())\ user = ub.session.query(ub.User).filter(func.lower(ub.User.nickname) == form['username'].strip().lower())\
.first() .first()
if config.config_use_ldap and user: '''if config.config_use_ldap and user:
import ldap import ldap
try: try:
ub.User.try_login(form['username'], form['password']) ub.User.try_login(form['username'], form['password'])
@ -1341,7 +1336,8 @@ def login():
ipAdress = request.headers.get('X-Forwarded-For', request.remote_addr) ipAdress = request.headers.get('X-Forwarded-For', request.remote_addr)
app.logger.info('LDAP Login failed for user "' + form['username'] + '" IP-adress: ' + ipAdress) app.logger.info('LDAP Login failed for user "' + form['username'] + '" IP-adress: ' + ipAdress)
flash(_(u"Wrong Username or Password"), category="error") flash(_(u"Wrong Username or Password"), category="error")
elif user and check_password_hash(user.password, form['password']) and user.nickname is not "Guest": el'''
if user and check_password_hash(user.password, form['password']) and user.nickname is not "Guest":
login_user(user, remember=True) login_user(user, remember=True)
flash(_(u"you are now logged in as: '%(nickname)s'", nickname=user.nickname), category="success") flash(_(u"you are now logged in as: '%(nickname)s'", nickname=user.nickname), category="success")
return redirect_back(url_for("web.index")) return redirect_back(url_for("web.index"))
@ -1362,7 +1358,8 @@ def login():
def logout(): def logout():
if current_user is not None and current_user.is_authenticated: if current_user is not None and current_user.is_authenticated:
logout_user() logout_user()
# logout_oauth_user() if oauth_support:
logout_oauth_user()
return redirect(url_for('web.login')) return redirect(url_for('web.login'))
@ -1475,7 +1472,7 @@ def profile():
downloads = list() downloads = list()
languages = speaking_language() languages = speaking_language()
translations = babel.list_translations() + [LC('en')] translations = babel.list_translations() + [LC('en')]
oauth_status = None # oauth_status = get_oauth_status() oauth_status = get_oauth_status()
for book in content.downloads: for book in content.downloads:
downloadBook = db.session.query(db.Books).filter(db.Books.id == book.book_id).first() downloadBook = db.session.query(db.Books).filter(db.Books.id == book.book_id).first()
if downloadBook: if downloadBook: