new random password generation algorithm to ensure compliance with password rules

bugfix opds login limit
This commit is contained in:
Ozzie Isaacs 2023-02-16 16:23:06 +01:00
parent 73ea18b8ce
commit 89bc72958e
4 changed files with 40 additions and 10 deletions

View File

@ -1961,12 +1961,6 @@ def _handle_edit_user(to_save, content, languages, translations, kobo_support):
log.warning("No admin user remaining, can't remove admin role from {}".format(content.name)) log.warning("No admin user remaining, can't remove admin role from {}".format(content.name))
flash(_("No admin user remaining, can't remove admin role"), category="error") flash(_("No admin user remaining, can't remove admin role"), category="error")
return redirect(url_for('admin.admin')) return redirect(url_for('admin.admin'))
anonymous = content.is_anonymous
content.role = constants.selected_roles(to_save)
if anonymous:
content.role |= constants.ROLE_ANONYMOUS
else:
content.role &= ~constants.ROLE_ANONYMOUS
val = [int(k[5:]) for k in to_save if k.startswith('show_')] val = [int(k[5:]) for k in to_save if k.startswith('show_')]
sidebar, __ = get_sidebar_config() sidebar, __ = get_sidebar_config()
@ -1994,6 +1988,15 @@ def _handle_edit_user(to_save, content, languages, translations, kobo_support):
if to_save.get("locale"): if to_save.get("locale"):
content.locale = to_save["locale"] content.locale = to_save["locale"]
try: try:
anonymous = content.is_anonymous
content.role = constants.selected_roles(to_save)
if anonymous:
content.role |= constants.ROLE_ANONYMOUS
else:
content.role &= ~constants.ROLE_ANONYMOUS
if to_save.get("password", ""):
content.password = generate_password_hash(helper.valid_password(to_save.get["password"]))
new_email = valid_email(to_save.get("email", content.email)) new_email = valid_email(to_save.get("email", content.email))
if not new_email: if not new_email:
raise Exception(_("Email can't be empty and has to be a valid Email")) raise Exception(_("Email can't be empty and has to be a valid Email"))
@ -2006,7 +2009,6 @@ def _handle_edit_user(to_save, content, languages, translations, kobo_support):
content.name = check_username(to_save["name"]) content.name = check_username(to_save["name"])
if to_save.get("kindle_mail") != content.kindle_mail: if to_save.get("kindle_mail") != content.kindle_mail:
content.kindle_mail = valid_email(to_save["kindle_mail"]) if to_save["kindle_mail"] else "" content.kindle_mail = valid_email(to_save["kindle_mail"]) if to_save["kindle_mail"] else ""
content.password = generate_password_hash(helper.valid_password(to_save.get("password", "")))
except Exception as ex: except Exception as ex:
log.error(ex) log.error(ex)
flash(str(ex), category="error") flash(str(ex), category="error")

View File

@ -18,6 +18,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
import os import os
import random
import io import io
import mimetypes import mimetypes
import re import re
@ -621,11 +622,35 @@ def reset_password(user_id):
ub.session.rollback() ub.session.rollback()
return 0, None return 0, None
def generate_random_password(min_length): def generate_random_password(min_length):
min_length = max(8, min_length) - 4
random_source = "abcdefghijklmnopqrstuvwxyz01234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%&*()?"
# select 1 lowercase
s = "abcdefghijklmnopqrstuvwxyz"
password = [s[c % len(s)] for c in os.urandom(1)]
# select 1 uppercase
s = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
password.extend([s[c % len(s)] for c in os.urandom(1)])
# select 1 digit
s = "01234567890"
password.extend([s[c % len(s)] for c in os.urandom(1)])
# select 1 special symbol
s = "!@#$%&*()?"
password.extend([s[c % len(s)] for c in os.urandom(1)])
# generate other characters
password.extend([random_source[c % len(random_source)] for c in os.urandom(min_length)])
# password_list = list(password)
# shuffle all characters
random.SystemRandom().shuffle(password)
return ''.join(password)
'''def generate_random_password(min_length):
s = "abcdefghijklmnopqrstuvwxyz01234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%&*()?" s = "abcdefghijklmnopqrstuvwxyz01234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%&*()?"
passlen = min_length passlen = min_length
return "".join(s[c % len(s)] for c in os.urandom(passlen)) return "".join(s[c % len(s)] for c in os.urandom(passlen))'''
def uniq(inpt): def uniq(inpt):

View File

@ -52,6 +52,7 @@ def requires_basic_auth_if_no_ano(f):
login_result, error = services.ldap.bind_user(auth.username, auth.password) login_result, error = services.ldap.bind_user(auth.username, auth.password)
if login_result: if login_result:
user = _fetch_user_by_name(auth.username) user = _fetch_user_by_name(auth.username)
[limiter.limiter.storage.clear(k.key) for k in limiter.current_limits]
login_user(user) login_user(user)
return f(*args, **kwargs) return f(*args, **kwargs)
elif login_result is not None: elif login_result is not None:
@ -68,6 +69,7 @@ def _load_user_from_auth_header(username, password):
limiter.check() limiter.check()
user = _fetch_user_by_name(username) user = _fetch_user_by_name(username)
if bool(user and check_password_hash(str(user.password), password)) and user.name != "Guest": if bool(user and check_password_hash(str(user.password), password)) and user.name != "Guest":
[limiter.limiter.storage.clear(k.key) for k in limiter.current_limits]
login_user(user) login_user(user)
return user return user
else: else:
@ -102,6 +104,7 @@ def load_user_from_reverse_proxy_header(req):
if rp_header_username: if rp_header_username:
user = _fetch_user_by_name(rp_header_username) user = _fetch_user_by_name(rp_header_username)
if user: if user:
[limiter.limiter.storage.clear(k.key) for k in limiter.current_limits]
login_user(user) login_user(user)
return user return user
return None return None

View File

@ -1256,7 +1256,7 @@ def register_post():
content.name = nickname content.name = nickname
content.email = email content.email = email
password = generate_random_password(config.config_password_min_length) password = generate_random_password(config.config_password_min_length)
content.password = generate_password_hash(valid_password(password)) content.password = generate_password_hash(password)
content.role = config.config_default_role content.role = config.config_default_role
content.locale = config.config_default_locale content.locale = config.config_default_locale
content.sidebar_view = config.config_default_show content.sidebar_view = config.config_default_show