Merge remote-tracking branch 'ldap/master' into Develop
This commit is contained in:
commit
3683e4e7eb
|
@ -171,6 +171,21 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
<div class="form-group">
|
||||||
|
<input type="checkbox" id="config_use_ldap" name="config_use_ldap" data-control="ldap-settings" {% if content.config_use_ldap %}checked{% endif %}>
|
||||||
|
<label for="config_use_ldap">{{_('Use')}} LDAP Authentication</label>
|
||||||
|
</div>
|
||||||
|
<div data-related="ldap-settings">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="config_ldap_provider_url">{{_('LDAP Provider URL')}}</label>
|
||||||
|
<input type="text" class="form-control" id="config_ldap_provider_url" name="config_ldap_provider_url" value="{% if content.config_use_ldap != None %}{{ content.config_ldap_provider_url }}{% endif %}" autocomplete="off">
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="config_ldap_dn">{{_('LDAP Distinguished Name (DN)')}}</label>
|
||||||
|
<input type="text" class="form-control" id="config_ldap_dn" name="config_ldap_dn" value="{% if content.config_use_ldap != None %}{{ content.config_ldap_dn }}{% endif %}" autocomplete="off">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
29
cps/ub.py
29
cps/ub.py
|
@ -169,6 +169,14 @@ class UserBase:
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '<User %r>' % self.nickname
|
return '<User %r>' % self.nickname
|
||||||
|
|
||||||
|
#Login via LDAP method
|
||||||
|
@staticmethod
|
||||||
|
def try_login(username, password):
|
||||||
|
conn = get_ldap_connection()
|
||||||
|
conn.simple_bind_s(
|
||||||
|
config.config_ldap_dn.replace("%s", username),
|
||||||
|
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)
|
||||||
|
@ -326,6 +334,9 @@ class Settings(Base):
|
||||||
config_use_goodreads = Column(Boolean)
|
config_use_goodreads = Column(Boolean)
|
||||||
config_goodreads_api_key = Column(String)
|
config_goodreads_api_key = Column(String)
|
||||||
config_goodreads_api_secret = Column(String)
|
config_goodreads_api_secret = Column(String)
|
||||||
|
config_use_ldap = Column(Boolean)
|
||||||
|
config_ldap_provider_url = Column(String)
|
||||||
|
config_ldap_dn = Column(String)
|
||||||
config_mature_content_tags = Column(String)
|
config_mature_content_tags = Column(String)
|
||||||
config_logfile = Column(String)
|
config_logfile = Column(String)
|
||||||
config_ebookconverter = Column(Integer, default=0)
|
config_ebookconverter = Column(Integer, default=0)
|
||||||
|
@ -400,6 +411,9 @@ class Config:
|
||||||
self.config_use_goodreads = data.config_use_goodreads
|
self.config_use_goodreads = data.config_use_goodreads
|
||||||
self.config_goodreads_api_key = data.config_goodreads_api_key
|
self.config_goodreads_api_key = data.config_goodreads_api_key
|
||||||
self.config_goodreads_api_secret = data.config_goodreads_api_secret
|
self.config_goodreads_api_secret = data.config_goodreads_api_secret
|
||||||
|
self.config_use_ldap = data.config_use_ldap
|
||||||
|
self.config_ldap_provider_url = data.config_ldap_provider_url
|
||||||
|
self.config_ldap_dn = data.config_ldap_dn
|
||||||
if data.config_mature_content_tags:
|
if data.config_mature_content_tags:
|
||||||
self.config_mature_content_tags = data.config_mature_content_tags
|
self.config_mature_content_tags = data.config_mature_content_tags
|
||||||
else:
|
else:
|
||||||
|
@ -687,6 +701,14 @@ def migrate_Database():
|
||||||
conn.execute("ALTER TABLE Settings ADD column `config_converterpath` String DEFAULT ''")
|
conn.execute("ALTER TABLE Settings ADD column `config_converterpath` String DEFAULT ''")
|
||||||
conn.execute("ALTER TABLE Settings ADD column `config_calibre` String DEFAULT ''")
|
conn.execute("ALTER TABLE Settings ADD column `config_calibre` String DEFAULT ''")
|
||||||
session.commit()
|
session.commit()
|
||||||
|
try:
|
||||||
|
session.query(exists().where(Settings.config_use_ldap)).scalar()
|
||||||
|
except exc.OperationalError:
|
||||||
|
conn = engine.connect()
|
||||||
|
conn.execute("ALTER TABLE Settings ADD column `config_use_ldap` INTEGER DEFAULT 0")
|
||||||
|
conn.execute("ALTER TABLE Settings ADD column `config_ldap_provider_url` String DEFAULT ''")
|
||||||
|
conn.execute("ALTER TABLE Settings ADD column `config_ldap_dn` String DEFAULT ''")
|
||||||
|
session.commit()
|
||||||
try:
|
try:
|
||||||
session.query(exists().where(Settings.config_theme)).scalar()
|
session.query(exists().where(Settings.config_theme)).scalar()
|
||||||
except exc.OperationalError: # Database is not compatible, some rows are missing
|
except exc.OperationalError: # Database is not compatible, some rows are missing
|
||||||
|
@ -700,7 +722,6 @@ def migrate_Database():
|
||||||
conn.execute("ALTER TABLE Settings ADD column `config_updatechannel` INTEGER DEFAULT 0")
|
conn.execute("ALTER TABLE Settings ADD column `config_updatechannel` INTEGER DEFAULT 0")
|
||||||
session.commit()
|
session.commit()
|
||||||
|
|
||||||
|
|
||||||
# Remove login capability of user Guest
|
# Remove login capability of user Guest
|
||||||
conn = engine.connect()
|
conn = engine.connect()
|
||||||
conn.execute("UPDATE user SET password='' where nickname = 'Guest' and password !=''")
|
conn.execute("UPDATE user SET password='' where nickname = 'Guest' and password !=''")
|
||||||
|
@ -810,6 +831,12 @@ else:
|
||||||
migrate_Database()
|
migrate_Database()
|
||||||
clean_database()
|
clean_database()
|
||||||
|
|
||||||
|
#get LDAP connection
|
||||||
|
def get_ldap_connection():
|
||||||
|
import ldap
|
||||||
|
conn = ldap.initialize('ldap://{}'.format(config.config_ldap_provider_url))
|
||||||
|
return conn
|
||||||
|
|
||||||
# Generate global Settings Object accessible from every file
|
# Generate global Settings Object accessible from every file
|
||||||
config = Config()
|
config = Config()
|
||||||
searched_ids = {}
|
searched_ids = {}
|
||||||
|
|
28
cps/web.py
28
cps/web.py
|
@ -2288,7 +2288,18 @@ def login():
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
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()).first()
|
user = ub.session.query(ub.User).filter(func.lower(ub.User.nickname) == form['username'].strip().lower()).first()
|
||||||
if user and check_password_hash(user.password, form['password']) and user.nickname is not "Guest":
|
if config.config_use_ldap and user:
|
||||||
|
import ldap
|
||||||
|
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("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")
|
||||||
|
elif 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("index"))
|
return redirect_back(url_for("index"))
|
||||||
|
@ -3044,6 +3055,21 @@ def configuration_helper(origin):
|
||||||
if "config_ebookconverter" in to_save:
|
if "config_ebookconverter" in to_save:
|
||||||
content.config_ebookconverter = int(to_save["config_ebookconverter"])
|
content.config_ebookconverter = int(to_save["config_ebookconverter"])
|
||||||
|
|
||||||
|
#LDAP configuratop,
|
||||||
|
if "config_use_ldap" in to_save and to_save["config_use_ldap"] == "on":
|
||||||
|
if not "config_ldap_provider_url" in to_save or not "config_ldap_dn" in to_save:
|
||||||
|
ub.session.commit()
|
||||||
|
flash(_(u'Please enter a LDAP provider and a DN'), category="error")
|
||||||
|
return render_title_template("config_edit.html", content=config, origin=origin,
|
||||||
|
gdrive=gdriveutils.gdrive_support, gdriveError=gdriveError,
|
||||||
|
goodreads=goodreads_support, title=_(u"Basic Configuration"),
|
||||||
|
page="config")
|
||||||
|
else:
|
||||||
|
content.config_use_ldap = 1
|
||||||
|
content.config_ldap_provider_url = to_save["config_ldap_provider_url"]
|
||||||
|
content.config_ldap_dn = to_save["config_ldap_dn"]
|
||||||
|
db_change = True
|
||||||
|
|
||||||
# Remote login configuration
|
# Remote login configuration
|
||||||
content.config_remote_login = ("config_remote_login" in to_save and to_save["config_remote_login"] == "on")
|
content.config_remote_login = ("config_remote_login" in to_save and to_save["config_remote_login"] == "on")
|
||||||
if not content.config_remote_login:
|
if not content.config_remote_login:
|
||||||
|
|
1
optional-requirements-ldap.txt
Normal file
1
optional-requirements-ldap.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
python_ldap>=3.0.0
|
Loading…
Reference in New Issue
Block a user