Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

auto create ldap users on first login #2799

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 15 additions & 7 deletions cps/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -1541,7 +1541,6 @@ def get_updater_status():

def ldap_import_create_user(user, user_data):
user_login_field = extract_dynamic_field_from_filter(user, config.config_ldap_user_object)

try:
username = user_data[user_login_field][0].decode('utf-8')
except KeyError as ex:
Expand All @@ -1555,6 +1554,15 @@ def ldap_import_create_user(user, user_data):
log.warning("LDAP User %s Already in Database", user_data)
return 0, None

user, error = ldap_create_user(username, user_data, config.config_default_role)
if user:
return 1, error
else:
return 0, error


def ldap_create_user(username, user_data, role):

ereader_mail = ''
if 'mail' in user_data:
useremail = user_data['mail'][0].decode('utf-8')
Expand All @@ -1569,16 +1577,16 @@ def ldap_import_create_user(user, user_data):
# check for duplicate email
useremail = check_email(useremail)
except Exception as ex:
log.warning("LDAP Email Error: {}, {}".format(user_data, ex))
return 0, None
log.warning("LDAP Email Error: {}, {}".format(username, ex))
return None, None
content = ub.User()
content.name = username
content.password = '' # dummy password which will be replaced by ldap one
content.email = useremail
content.kindle_mail = ereader_mail
content.default_language = config.config_default_language
content.locale = config.config_default_locale
content.role = config.config_default_role
content.role = role
content.sidebar_view = config.config_default_show
content.allowed_tags = config.config_allowed_tags
content.denied_tags = config.config_denied_tags
Expand All @@ -1587,12 +1595,12 @@ def ldap_import_create_user(user, user_data):
ub.session.add(content)
try:
ub.session.commit()
return 1, None # increase no of users
return content, None
except Exception as ex:
log.warning("Failed to create LDAP user: %s - %s", user, ex)
log.warning("Failed to create LDAP user: %s - %s", username, ex)
ub.session.rollback()
message = _(u'Failed to Create at Least One LDAP User')
return 0, message
return None, message


@admi.route('/import_ldap_users', methods=["POST"])
Expand Down
2 changes: 1 addition & 1 deletion cps/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@

LDAP_AUTH_ANONYMOUS = 0
LDAP_AUTH_UNAUTHENTICATE = 1
LDAP_AUTH_SIMPLE = 0
LDAP_AUTH_SIMPLE = 2

DEFAULT_MAIL_SERVER = "mail.example.org"

Expand Down
4 changes: 2 additions & 2 deletions cps/services/simpleldap.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,8 @@ def init_app(app, config):
log.error(e)


def get_object_details(user=None,query_filter=None):
return _ldap.get_object_details(user, query_filter=query_filter)
def get_object_details(user=None, query_filter=None, group=None):
return _ldap.get_object_details(user=user, query_filter=query_filter, group=group)


def bind():
Expand Down
47 changes: 41 additions & 6 deletions cps/web.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
from . import constants, logger, isoLanguages, services
from . import db, ub, config, app
from . import calibre_db, kobo_sync_status
from .admin import ldap_create_user
from .search import render_search_results, render_adv_search_results
from .gdriveutils import getFileFromEbooksFolder, do_gdrive_download
from .helper import check_valid_domain, check_email, check_username, \
Expand Down Expand Up @@ -1352,14 +1353,20 @@ def login_post():
user = ub.session.query(ub.User).filter(func.lower(ub.User.name) == form.get('username', "").strip().lower()) \
.first()
remember_me = bool(form.get('remember_me'))
if config.config_login_type == constants.LOGIN_LDAP and services.ldap and user and form['password'] != "":
if config.config_login_type == constants.LOGIN_LDAP and services.ldap and (user or os.environ.get("CALIBRE_LDAP_AUTO_CREATE", None)) and form['password'] != "":
login_result, error = services.ldap.bind_user(form['username'], form['password'])
if login_result:
log.debug(u"You are now logged in as: '{}'".format(user.name))
return handle_login_user(user,
remember_me,
_(u"you are now logged in as: '%(nickname)s'", nickname=user.name),
"success")
log.debug(u"You are now logged in as: '{}'".format(form['username']))
if not user:
user, error = create_user(form['username'])
if not user:
log.info(error)
flash(_(u"Could not create user from ldap login: %(message)s", message=error), category="error")
else:
return handle_login_user(user,
remember_me,
_(u"you are now logged in as: '%(nickname)s'", nickname=user.name),
"success")
elif login_result is None and user and check_password_hash(str(user.password), form['password']) \
and user.name != "Guest":
log.info("Local Fallback Login as: '{}'".format(user.name))
Expand Down Expand Up @@ -1403,6 +1410,34 @@ def login_post():
return render_login(form.get("username", ""), form.get("password", ""))


def create_user(username):
try:
user_data = services.ldap.get_object_details(user=username)
except Exception as e:
log.error('LDAP user details failed: %s', e)
message = _(u'Failed to get LDAP User details')
return None, message

admin_group_filter = os.environ.get("CALIBRE_LDAP_ADMIN_GROUP_FILTER", None)
role = constants.ROLE_USER
if admin_group_filter:
try:
log.debug(u"LDAP admin group filter: '{}'".format(admin_group_filter))
group_data = services.ldap.get_object_details(user=username, query_filter=admin_group_filter)
if group_data:
log.debug(u"LDAP admin group is found: '{}'".format(group_data))
role = constants.ROLE_ADMIN | constants.ROLE_DELETE_BOOKS | constants.ROLE_DOWNLOAD | constants.ROLE_UPLOAD | constants.ROLE_EDIT | constants.ROLE_EDIT_SHELFS | constants.ROLE_VIEWER
else:
log.debug(u"LDAP admin group is not found")

except Exception as e:
log.error('LDAP admin group lookup failed: %s', e)
message = _(u'Failed to get LDAP admin group details')
return None, message
user, error = ldap_create_user(username, user_data, role)
return user, error


@web.route('/logout')
@login_required
def logout():
Expand Down