Compare commits
10 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
b1c70d5b4a | ||
|
c5fc30a1be | ||
|
29fd4ae4a2 | ||
|
4ef8c35fb7 | ||
|
04326af2da | ||
|
d6a31e5db8 | ||
|
73d48e4ac1 | ||
|
b206b7a5d8 | ||
|
909797dc49 | ||
|
07d4e60655 |
@ -98,10 +98,6 @@ updater_thread = Updater()
|
||||
|
||||
|
||||
def create_app():
|
||||
lm.login_view = 'web.login'
|
||||
lm.anonymous_user = ub.Anonymous
|
||||
lm.session_protection = 'strong'
|
||||
|
||||
if csrf:
|
||||
csrf.init_app(app)
|
||||
|
||||
@ -112,6 +108,10 @@ def create_app():
|
||||
# pylint: disable=no-member
|
||||
config_sql.load_configuration(config, ub.session, cli_param)
|
||||
|
||||
lm.login_view = 'web.login'
|
||||
lm.anonymous_user = ub.Anonymous
|
||||
lm.session_protection = 'strong' if config.config_session == 1 else "basic"
|
||||
|
||||
db.CalibreDB.update_config(config)
|
||||
db.CalibreDB.setup_db(config.config_calibre_dir, cli_param.settings_path)
|
||||
calibre_db.init_db()
|
||||
|
17
cps/admin.py
17
cps/admin.py
@ -1765,10 +1765,21 @@ def _configuration_update_helper():
|
||||
if config.config_login_type == constants.LOGIN_OAUTH:
|
||||
reboot_required |= _configuration_oauth_helper(to_save)
|
||||
|
||||
# logfile configuration
|
||||
reboot, message = _configuration_logfile_helper(to_save)
|
||||
if message:
|
||||
return message
|
||||
reboot_required |= reboot
|
||||
|
||||
# security configuration
|
||||
_config_checkbox(to_save, "config_password_policy")
|
||||
_config_checkbox(to_save, "config_password_number")
|
||||
_config_checkbox(to_save, "config_password_lower")
|
||||
_config_checkbox(to_save, "config_password_upper")
|
||||
_config_checkbox(to_save, "config_password_special")
|
||||
_config_int(to_save, "config_password_min_length")
|
||||
reboot_required |= _config_int(to_save, "config_session")
|
||||
|
||||
# Rarfile Content configuration
|
||||
_config_string(to_save, "config_rarfile_location")
|
||||
if "config_rarfile_location" in to_save:
|
||||
@ -1837,11 +1848,11 @@ def _handle_new_user(to_save, content, languages, translations, kobo_support):
|
||||
content.sidebar_view |= constants.DETAIL_RANDOM
|
||||
|
||||
content.role = constants.selected_roles(to_save)
|
||||
content.password = generate_password_hash(to_save["password"])
|
||||
try:
|
||||
if not to_save["name"] or not to_save["email"] or not to_save["password"]:
|
||||
log.info("Missing entries on new user")
|
||||
raise Exception(_(u"Please fill out all fields!"))
|
||||
content.password = generate_password_hash(helper.valid_password(to_save.get("password", "")))
|
||||
content.email = check_email(to_save["email"])
|
||||
# Query username, if not existing, change
|
||||
content.name = check_username(to_save["name"])
|
||||
@ -1925,8 +1936,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))
|
||||
flash(_("No admin user remaining, can't remove admin role"), category="error")
|
||||
return redirect(url_for('admin.admin'))
|
||||
if to_save.get("password"):
|
||||
content.password = generate_password_hash(to_save["password"])
|
||||
anonymous = content.is_anonymous
|
||||
content.role = constants.selected_roles(to_save)
|
||||
if anonymous:
|
||||
@ -1960,6 +1969,8 @@ def _handle_edit_user(to_save, content, languages, translations, kobo_support):
|
||||
if to_save.get("locale"):
|
||||
content.locale = to_save["locale"]
|
||||
try:
|
||||
if to_save.get('password', "") != "":
|
||||
content.password = generate_password_hash(helper.valid_password(to_save['password']))
|
||||
if to_save.get("email", content.email) != content.email:
|
||||
content.email = check_email(to_save["email"])
|
||||
# Query username, if not existing, change
|
||||
|
@ -75,7 +75,6 @@ class _Settings(_Base):
|
||||
config_authors_max = Column(Integer, default=0)
|
||||
config_read_column = Column(Integer, default=0)
|
||||
config_title_regex = Column(String, default=r'^(A|The|An|Der|Die|Das|Den|Ein|Eine|Einen|Dem|Des|Einem|Eines)\s+')
|
||||
# config_mature_content_tags = Column(String, default='')
|
||||
config_theme = Column(Integer, default=0)
|
||||
|
||||
config_log_level = Column(SmallInteger, default=logger.DEFAULT_LOG_LEVEL)
|
||||
@ -148,6 +147,14 @@ class _Settings(_Base):
|
||||
schedule_generate_series_covers = Column(Boolean, default=False)
|
||||
schedule_reconnect = Column(Boolean, default=False)
|
||||
|
||||
config_password_policy = Column(Boolean, default=True)
|
||||
config_password_min_length = Column(Integer, default=8)
|
||||
config_password_number = Column(Boolean, default=True)
|
||||
config_password_lower = Column(Boolean, default=True)
|
||||
config_password_upper = Column(Boolean, default=True)
|
||||
config_password_special = Column(Boolean, default=True)
|
||||
config_session = Column(Integer, default=1)
|
||||
|
||||
def __repr__(self):
|
||||
return self.__class__.__name__
|
||||
|
||||
|
@ -661,6 +661,23 @@ def valid_email(email):
|
||||
raise Exception(_(u"Invalid e-mail address format"))
|
||||
return email
|
||||
|
||||
def valid_password(check_password):
|
||||
if config.config_password_policy:
|
||||
verify = ""
|
||||
if config.config_password_min_length > 0:
|
||||
verify += "^(?=.{" + str(config.config_password_min_length) + ",}$)"
|
||||
if config.config_password_number:
|
||||
verify += "(?=.*?\d)"
|
||||
if config.config_password_lower:
|
||||
verify += "(?=.*?[a-z])"
|
||||
if config.config_password_upper:
|
||||
verify += "(?=.*?[A-Z])"
|
||||
if config.config_password_special:
|
||||
verify += "(?=.*?[^A-Za-z\s0-9])"
|
||||
match = re.match(verify, check_password)
|
||||
if not match:
|
||||
raise Exception(_("Password doesn't comply with password validation rules"))
|
||||
return check_password
|
||||
# ################################# External interface #################################
|
||||
|
||||
|
||||
|
@ -17,12 +17,12 @@
|
||||
import json
|
||||
from datetime import datetime
|
||||
|
||||
from flask import Blueprint, request, redirect, url_for, flash
|
||||
from flask import Blueprint, request, redirect, url_for, flash, get_flashed_messages
|
||||
from flask import session as flask_session
|
||||
from flask_login import current_user
|
||||
from flask_babel import format_date
|
||||
from flask_babel import gettext as _
|
||||
from sqlalchemy.sql.expression import func, not_, and_, or_, text, true
|
||||
from sqlalchemy.sql.expression import func, not_, and_, or_, text, false
|
||||
from sqlalchemy.sql.functions import coalesce
|
||||
|
||||
from . import logger, db, calibre_db, config, ub
|
||||
@ -134,7 +134,9 @@ def adv_search_read_status(read_status):
|
||||
db_filter = coalesce(db.cc_classes[config.config_read_column].value, False) != True
|
||||
except (KeyError, AttributeError, IndexError):
|
||||
log.error("Custom Column No.{} does not exist in calibre database".format(config.config_read_column))
|
||||
return true()
|
||||
flash(_("Custom Column No.{} does not exist in calibre database".format(config.config_read_column)),
|
||||
category="error")
|
||||
return false()
|
||||
return db_filter
|
||||
|
||||
|
||||
|
@ -433,3 +433,7 @@ div.log {
|
||||
#detailcover:-moz-full-screen { cursor:zoom-out; border: 0; }
|
||||
#detailcover:-ms-fullscreen { cursor:zoom-out; border: 0; }
|
||||
#detailcover:fullscreen { cursor:zoom-out; border: 0; }
|
||||
|
||||
.error-list {
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
1
cps/static/js/libs/pwstrength/i18next.min.js
vendored
Normal file
1
cps/static/js/libs/pwstrength/i18next.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
cps/static/js/libs/pwstrength/i18nextHttpBackend.min.js
vendored
Normal file
1
cps/static/js/libs/pwstrength/i18nextHttpBackend.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
17
cps/static/js/libs/pwstrength/locales/ar.json
Normal file
17
cps/static/js/libs/pwstrength/locales/ar.json
Normal file
@ -0,0 +1,17 @@
|
||||
{
|
||||
"wordMinLength": "كلمة المرور قصيرة جداً",
|
||||
"wordMaxLength": "كلمة المرور طويلة جدا",
|
||||
"wordInvalidChar": "تحتوي كلمة المرور على رموز غير صالحة",
|
||||
"wordNotEmail": "لا تستخدم بريدك الإلكتروني ككلمة مرور",
|
||||
"wordSimilarToUsername": "لا يمكن ان تحتوي كلمة المرور على إسم المستخدم",
|
||||
"wordTwoCharacterClasses": "إستخدم فئات أحرف مختلفة",
|
||||
"wordRepetitions": "تكرارات كثيرة",
|
||||
"wordSequences": "تحتوي كلمة المرور على أنماط متتابعة",
|
||||
"errorList": "الأخطاء:",
|
||||
"veryWeak": "ضعيفة جداً",
|
||||
"weak": "ضعيفة",
|
||||
"normal": "عادية",
|
||||
"medium": "متوسطة",
|
||||
"strong": "قوية",
|
||||
"veryStrong": "قوية جداً"
|
||||
}
|
17
cps/static/js/libs/pwstrength/locales/cs.json
Normal file
17
cps/static/js/libs/pwstrength/locales/cs.json
Normal file
@ -0,0 +1,17 @@
|
||||
{
|
||||
"wordMinLength": "Vaše heslo je příliš krátké",
|
||||
"wordMaxLength": "Vaše heslo je příliš dlouhé",
|
||||
"wordInvalidChar": "Vaše heslo obsahuje neplatný znak",
|
||||
"wordNotEmail": "Nepoužívejte Váš email jako Vaše heslo",
|
||||
"wordSimilarToUsername": "Vaše heslo nesmí obsahovat přihlašovací jméno",
|
||||
"wordTwoCharacterClasses": "Použijte různé druhy znaků",
|
||||
"wordRepetitions": "Příliš mnoho opakování",
|
||||
"wordSequences": "Vaše heslo obsahuje postupnost",
|
||||
"errorList": "Chyby:",
|
||||
"veryWeak": "Velmi slabé",
|
||||
"weak": "Slabé",
|
||||
"normal": "Normální",
|
||||
"medium": "Středně silné",
|
||||
"strong": "Silné",
|
||||
"veryStrong": "Velmi silné"
|
||||
}
|
21
cps/static/js/libs/pwstrength/locales/de.json
Normal file
21
cps/static/js/libs/pwstrength/locales/de.json
Normal file
@ -0,0 +1,21 @@
|
||||
{
|
||||
"wordMinLength": "Das Passwort ist zu kurz",
|
||||
"wordMaxLength": "Das Passwort ist zu lang",
|
||||
"wordInvalidChar": "Das Passwort enthält ein ungültiges Zeichen",
|
||||
"wordNotEmail": "Das Passwort darf die E-Mail Adresse nicht enthalten",
|
||||
"wordSimilarToUsername": "Das Passwort darf den Benutzernamen nicht enthalten",
|
||||
"wordTwoCharacterClasses": "Bitte Buchstaben und Ziffern verwenden",
|
||||
"wordRepetitions": "Zu viele Wiederholungen",
|
||||
"wordSequences": "Das Passwort enthält Buchstabensequenzen",
|
||||
"wordLowercase": "Bitte mindestens einen Kleinbuchstaben verwenden",
|
||||
"wordUppercase": "Bitte mindestens einen Großbuchstaben verwenden",
|
||||
"wordOneNumber": "Bitte mindestens eine Ziffern verwenden",
|
||||
"wordOneSpecialChar": "Bitte mindestens ein Sonderzeichen verwenden",
|
||||
"errorList": "Fehler:",
|
||||
"veryWeak": "Sehr schwach",
|
||||
"weak": "Schwach",
|
||||
"normal": "Normal",
|
||||
"medium": "Mittel",
|
||||
"strong": "Stark",
|
||||
"veryStrong": "Sehr stark"
|
||||
}
|
17
cps/static/js/libs/pwstrength/locales/el.json
Normal file
17
cps/static/js/libs/pwstrength/locales/el.json
Normal file
@ -0,0 +1,17 @@
|
||||
{
|
||||
"wordMinLength": "Ο κωδικός πρόσβασης δεν έχει τον ελάχιστο αριθμό χαρακτήρων",
|
||||
"wordMaxLength": "Ο κωδικός πρόσβασής σας είναι πολύ μεγάλος",
|
||||
"wordInvalidChar": "Ο κωδικός πρόσβασής σας περιέχει έναν μη έγκυρο χαρακτήρα",
|
||||
"wordNotEmail": "Μη χρησιμοποιείτε το email ως κωδικό",
|
||||
"wordSimilarToUsername": "Ο κωδικός πρόσβασης δεν πρέπει να περιέχει το username",
|
||||
"wordTwoCharacterClasses": "Χρησιμοποιήστε διαφορετικές κλάσεις χαρακτήρων",
|
||||
"wordRepetitions": "Πολλές επαναλήψεις",
|
||||
"wordSequences": "Ο κωδικός πρόσβασης περιέχει επαναλήψεις",
|
||||
"errorList": "Σφάλματα:",
|
||||
"veryWeak": "Πολύ Αδύνατος",
|
||||
"weak": "Αδύνατος",
|
||||
"normal": "Κανονικός",
|
||||
"medium": "Μέτριος",
|
||||
"strong": "Δυνατός",
|
||||
"veryStrong": "Πολύ Δυνατός"
|
||||
}
|
21
cps/static/js/libs/pwstrength/locales/en.json
Normal file
21
cps/static/js/libs/pwstrength/locales/en.json
Normal file
@ -0,0 +1,21 @@
|
||||
{
|
||||
"wordMinLength": "Your password is too short",
|
||||
"wordMaxLength": "Your password is too long",
|
||||
"wordInvalidChar": "Your password contains an invalid character",
|
||||
"wordNotEmail": "Do not use your email as your password",
|
||||
"wordSimilarToUsername": "Your password cannot contain your username",
|
||||
"wordTwoCharacterClasses": "Use different character classes",
|
||||
"wordRepetitions": "Too many repetitions",
|
||||
"wordSequences": "Your password contains sequences",
|
||||
"wordLowercase": "Use at least one lowercase character",
|
||||
"wordUppercase": "Use at least one uppercase character",
|
||||
"wordOneNumber": "Use at least one number",
|
||||
"wordOneSpecialChar": "Use at least one special character",
|
||||
"errorList": "Errors:",
|
||||
"veryWeak": "Very Weak",
|
||||
"weak": "Weak",
|
||||
"normal": "Normal",
|
||||
"medium": "Medium",
|
||||
"strong": "Strong",
|
||||
"veryStrong": "Very Strong"
|
||||
}
|
17
cps/static/js/libs/pwstrength/locales/eo.json
Normal file
17
cps/static/js/libs/pwstrength/locales/eo.json
Normal file
@ -0,0 +1,17 @@
|
||||
{
|
||||
"wordMinLength": "Via pasvorto estas tro mallonga",
|
||||
"wordMaxLength": "Via pasvorto estas tro longa",
|
||||
"wordInvalidChar": "Via pasvorto enhavas nevalidan karaktero",
|
||||
"wordNotEmail": "Ne uzu vian retpoŝtadreson kiel la pasvorton",
|
||||
"wordSimilarToUsername": "Via pasvorto enhavas vian uzanto-nomon",
|
||||
"wordTwoCharacterClasses": "Uzu signojn de diversaj tipoj (ekz., literoj kaj ciferoj)",
|
||||
"wordRepetitions": "Tro multaj ripetiĝantaj signoj",
|
||||
"wordSequences": "Via pasvorto enhavas simplan sinsekvon de signoj",
|
||||
"errorList": "Eraroj:",
|
||||
"veryWeak": "Trosimpla",
|
||||
"weak": "Malforta",
|
||||
"normal": "Mezforta",
|
||||
"medium": "Akceptebla",
|
||||
"strong": "Forta",
|
||||
"veryStrong": "Elstare Forta"
|
||||
}
|
17
cps/static/js/libs/pwstrength/locales/es.json
Normal file
17
cps/static/js/libs/pwstrength/locales/es.json
Normal file
@ -0,0 +1,17 @@
|
||||
{
|
||||
"wordMinLength": "Tu contraseña es demasiado corta",
|
||||
"wordMaxLength": "Tu contraseña es muy larga",
|
||||
"wordInvalidChar": "Tu contraseña contiene un carácter no válido",
|
||||
"wordNotEmail": "No uses tu email como tu contraseña",
|
||||
"wordSimilarToUsername": "Tu contraseña no puede contener tu nombre de usuario",
|
||||
"wordTwoCharacterClasses": "Mezcla diferentes clases de caracteres",
|
||||
"wordRepetitions": "Demasiadas repeticiones",
|
||||
"wordSequences": "Tu contraseña contiene secuencias",
|
||||
"errorList": "Errores:",
|
||||
"veryWeak": "Muy Débil",
|
||||
"weak": "Débil",
|
||||
"normal": "Normal",
|
||||
"medium": "Media",
|
||||
"strong": "Fuerte",
|
||||
"veryStrong": "Muy Fuerte"
|
||||
}
|
17
cps/static/js/libs/pwstrength/locales/fr.json
Normal file
17
cps/static/js/libs/pwstrength/locales/fr.json
Normal file
@ -0,0 +1,17 @@
|
||||
{
|
||||
"wordMinLength": "Votre mot de passe est trop court",
|
||||
"wordMaxLength": "Votre mot de passe est trop long",
|
||||
"wordInvalidChar": "Votre mot de passe contient un caractère invalide",
|
||||
"wordNotEmail": "Ne pas utiliser votre adresse e-mail comme mot de passe",
|
||||
"wordSimilarToUsername": "Votre mot de passe ne peut pas contenir votre nom d'utilisateur",
|
||||
"wordTwoCharacterClasses": "Utilisez différents type de caractères",
|
||||
"wordRepetitions": "Trop de répétitions",
|
||||
"wordSequences": "Votre mot de passe contient des séquences",
|
||||
"errorList": "Erreurs:",
|
||||
"veryWeak": "Très Faible",
|
||||
"weak": "Faible",
|
||||
"normal": "Normal",
|
||||
"medium": "Moyen",
|
||||
"strong": "Fort",
|
||||
"veryStrong": "Très Fort"
|
||||
}
|
17
cps/static/js/libs/pwstrength/locales/it.json
Normal file
17
cps/static/js/libs/pwstrength/locales/it.json
Normal file
@ -0,0 +1,17 @@
|
||||
{
|
||||
"wordMinLength": "La tua password è troppo corta",
|
||||
"wordMaxLength": "La tua password è troppo lunga",
|
||||
"wordInvalidChar": "La tua password contiene un carattere non valido",
|
||||
"wordNotEmail": "Non usare la tua e-mail come password",
|
||||
"wordSimilarToUsername": "La tua password non può contenere il tuo nome",
|
||||
"wordTwoCharacterClasses": "Usa classi di caratteri diversi",
|
||||
"wordRepetitions": "Troppe ripetizioni",
|
||||
"wordSequences": "La tua password contiene sequenze",
|
||||
"errorList": "Errori:",
|
||||
"veryWeak": "Molto debole",
|
||||
"weak": "Debole",
|
||||
"normal": "Normale",
|
||||
"medium": "Media",
|
||||
"strong": "Forte",
|
||||
"veryStrong": "Molto forte"
|
||||
}
|
17
cps/static/js/libs/pwstrength/locales/no.json
Normal file
17
cps/static/js/libs/pwstrength/locales/no.json
Normal file
@ -0,0 +1,17 @@
|
||||
{
|
||||
"wordMinLength": "Ditt passord er for kort",
|
||||
"wordMaxLength": "Ditt passord er for langt",
|
||||
"wordInvalidChar": "Ditt passord inneholder et ugyldig tegn",
|
||||
"wordNotEmail": "Ikke bruk din epost som ditt passord",
|
||||
"wordSimilarToUsername": "Ditt passord er for likt ditt brukernavn",
|
||||
"wordTwoCharacterClasses": "Bruk en kombinasjon av bokstaver, tall og andre tegn",
|
||||
"wordRepetitions": "For mange repitisjoner",
|
||||
"wordSequences": "Ditt passord inneholder repeterende tegn",
|
||||
"errorList": "Feil:",
|
||||
"veryWeak": "Veldig Svakt",
|
||||
"weak": "Svakt",
|
||||
"normal": "Normal",
|
||||
"medium": "Medium",
|
||||
"strong": "Sterkt",
|
||||
"veryStrong": "Veldig Sterkt"
|
||||
}
|
17
cps/static/js/libs/pwstrength/locales/pl.json
Normal file
17
cps/static/js/libs/pwstrength/locales/pl.json
Normal file
@ -0,0 +1,17 @@
|
||||
{
|
||||
"wordMinLength": "Hasło jest zbyt krótkie",
|
||||
"wordMaxLength": "Hasło jest za długie",
|
||||
"wordInvalidChar": "Hasło zawiera nieprawidłowy znak",
|
||||
"wordNotEmail": "Hasło nie może być Twoim emailem",
|
||||
"wordSimilarToUsername": "Hasło nie może zawierać nazwy użytkownika",
|
||||
"wordTwoCharacterClasses": "Użyj innych klas znaków",
|
||||
"wordRepetitions": "Zbyt wiele powtórzeń",
|
||||
"wordSequences": "Hasło zawiera sekwencje",
|
||||
"errorList": "Błędy:",
|
||||
"veryWeak": "Bardzo słabe",
|
||||
"weak": "Słabe",
|
||||
"normal": "Normalne",
|
||||
"medium": "Średnie",
|
||||
"strong": "Silne",
|
||||
"veryStrong": "Bardzo silne"
|
||||
}
|
17
cps/static/js/libs/pwstrength/locales/pt.json
Normal file
17
cps/static/js/libs/pwstrength/locales/pt.json
Normal file
@ -0,0 +1,17 @@
|
||||
{
|
||||
"wordMinLength": "Sua senha é muito curta",
|
||||
"wordMaxLength": "Sua senha é muito longa",
|
||||
"wordInvalidChar": "Sua senha contém um caractere inválido",
|
||||
"wordNotEmail": "Não use seu e-mail como senha",
|
||||
"wordSimilarToUsername": "Sua senha não pode conter o seu nome de usuário",
|
||||
"wordTwoCharacterClasses": "Use diferentes classes de caracteres",
|
||||
"wordRepetitions": "Muitas repetições",
|
||||
"wordSequences": "Sua senha contém sequências",
|
||||
"errorList": "Erros:",
|
||||
"veryWeak": "Muito Fraca",
|
||||
"weak": "Fraca",
|
||||
"normal": "Normal",
|
||||
"medium": "Média",
|
||||
"strong": "Forte",
|
||||
"veryStrong": "Muito Forte"
|
||||
}
|
17
cps/static/js/libs/pwstrength/locales/ru.json
Normal file
17
cps/static/js/libs/pwstrength/locales/ru.json
Normal file
@ -0,0 +1,17 @@
|
||||
{
|
||||
"wordMinLength": "Слишком короткий пароль",
|
||||
"wordMaxLength": "Ваш пароль слишком длинный",
|
||||
"wordInvalidChar": "Ваш пароль содержит недопустимый символ",
|
||||
"wordNotEmail": "Не используйте e-mail в качестве пароля",
|
||||
"wordSimilarToUsername": "Пароль не должен содержать логин",
|
||||
"wordTwoCharacterClasses": "Используйте разные классы символов",
|
||||
"wordRepetitions": "Слишком много повторений",
|
||||
"wordSequences": "Пароль содержит последовательности",
|
||||
"errorList": "Ошибки:",
|
||||
"veryWeak": "Очень слабый",
|
||||
"weak": "Слабый",
|
||||
"normal": "Нормальный",
|
||||
"medium": "Средний",
|
||||
"strong": "Сильный",
|
||||
"veryStrong": "Очень сильный"
|
||||
}
|
17
cps/static/js/libs/pwstrength/locales/sk.json
Normal file
17
cps/static/js/libs/pwstrength/locales/sk.json
Normal file
@ -0,0 +1,17 @@
|
||||
{
|
||||
"wordMinLength": "Vaše heslo je príliž krátke",
|
||||
"wordMaxLength": "Vaše heslo je príliš dlhé",
|
||||
"wordInvalidChar": "Vaše heslo obsahuje neplatný znak",
|
||||
"wordNotEmail": "Nepoužívajte Váš email ako Vaše heslo",
|
||||
"wordSimilarToUsername": "Vaše heslo nesmie obsahovať prihlasovacie meno",
|
||||
"wordTwoCharacterClasses": "Použite rôzne druhy znakov",
|
||||
"wordRepetitions": "Príliš veľa opakovaní",
|
||||
"wordSequences": "Vaše heslo obsahuje postupnosť",
|
||||
"errorList": "Chyby:",
|
||||
"veryWeak": "Veľmi slabé",
|
||||
"weak": "Slabé",
|
||||
"normal": "Normálne",
|
||||
"medium": "Stredne silné",
|
||||
"strong": "Silné",
|
||||
"veryStrong": "Veľmi silné"
|
||||
}
|
17
cps/static/js/libs/pwstrength/locales/th.json
Normal file
17
cps/static/js/libs/pwstrength/locales/th.json
Normal file
@ -0,0 +1,17 @@
|
||||
{
|
||||
"wordMinLength": "รหัสผ่านของคุณสั้นเกินไป",
|
||||
"wordMaxLength": "รหัสผ่านของคุณยาวเกินไป",
|
||||
"wordInvalidChar": "รหัสผ่านของคุณมีอักษรที่ไม่ถูกต้อง",
|
||||
"wordNotEmail": "คุณไม่สามารถใช้รหัสผ่านเหมือนกับอีเมล์ของคุณได้",
|
||||
"wordSimilarToUsername": "รหัสผ่านไม่ควรประกอบด้วยคำที่เป็น username",
|
||||
"wordTwoCharacterClasses": "ลองเป็นกลุ่มคำใหม่",
|
||||
"wordRepetitions": "มีอักษรซ้ำเยอะเกินไป",
|
||||
"wordSequences": "รหัสผ่านของคุณเดาง่ายเกินไป",
|
||||
"errorList": "Errors:",
|
||||
"veryWeak": "เดาง่ายมาก",
|
||||
"weak": "เดาง่าย",
|
||||
"normal": "พอใช้",
|
||||
"medium": "กำลังดี",
|
||||
"strong": "ค่อนข้างดี",
|
||||
"veryStrong": "ดีมาก"
|
||||
}
|
17
cps/static/js/libs/pwstrength/locales/tr.json
Normal file
17
cps/static/js/libs/pwstrength/locales/tr.json
Normal file
@ -0,0 +1,17 @@
|
||||
{
|
||||
"wordMinLength": "Girdiğiniz şifre çok Kısa",
|
||||
"wordMaxLength": "Parolanız çok uzun",
|
||||
"wordInvalidChar": "Şifreniz geçersiz bir karakter içeriyor",
|
||||
"wordNotEmail": "E-mail adresinizi şifreniz içerisinde kullanmayınız",
|
||||
"wordSimilarToUsername": "Kullanıcı Adınızı şifreniz içerisinde kullanmayınız",
|
||||
"wordTwoCharacterClasses": "Başka karakter sınıfı kullanınız",
|
||||
"wordRepetitions": "Çok fazla tekrar var",
|
||||
"wordSequences": "Şifreniz Dizi içermektedir",
|
||||
"errorList": "Hatalar:",
|
||||
"veryWeak": "Çok Zayıf",
|
||||
"weak": "Zayıf",
|
||||
"normal": "Normal",
|
||||
"medium": "Orta",
|
||||
"strong": "Güçlü",
|
||||
"veryStrong": "Çok Güçlü"
|
||||
}
|
17
cps/static/js/libs/pwstrength/locales/zh-TW.json
Normal file
17
cps/static/js/libs/pwstrength/locales/zh-TW.json
Normal file
@ -0,0 +1,17 @@
|
||||
{
|
||||
"wordMinLength": "您的密碼太短",
|
||||
"wordMaxLength": "您的密碼太長",
|
||||
"wordInvalidChar": "您的密碼包含無效字符",
|
||||
"wordNotEmail": "不要使用電子郵件作為密碼",
|
||||
"wordSimilarToUsername": "您的密碼不能包含您的用戶名",
|
||||
"wordTwoCharacterClasses": "使用不同的字元類型 例如: 大小寫混合",
|
||||
"wordRepetitions": "太多的重複。例如:1111",
|
||||
"wordSequences": "你的密碼包含連續英/數字 例如:123 or abc",
|
||||
"errorList": "錯誤:",
|
||||
"veryWeak": "非常弱",
|
||||
"weak": "弱",
|
||||
"normal": "普通",
|
||||
"medium": "中等",
|
||||
"strong": "強",
|
||||
"veryStrong": "非常強"
|
||||
}
|
1223
cps/static/js/libs/pwstrength/pwstrength-bootstrap.js
Normal file
1223
cps/static/js/libs/pwstrength/pwstrength-bootstrap.js
Normal file
File diff suppressed because it is too large
Load Diff
4
cps/static/js/libs/pwstrength/pwstrength-bootstrap.min.js
vendored
Normal file
4
cps/static/js/libs/pwstrength/pwstrength-bootstrap.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@ -151,13 +151,13 @@ $("#form-upload").uploadprogress({
|
||||
});
|
||||
|
||||
$(document).ready(function() {
|
||||
var inp = $('#query').first()
|
||||
if (inp.length) {
|
||||
var val = inp.val()
|
||||
if (val.length) {
|
||||
inp.val('').blur().focus().val(val)
|
||||
var inp = $('#query').first()
|
||||
if (inp.length) {
|
||||
var val = inp.val()
|
||||
if (val.length) {
|
||||
inp.val('').blur().focus().val(val)
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$(".session").click(function() {
|
||||
|
65
cps/static/js/password.js
Normal file
65
cps/static/js/password.js
Normal file
@ -0,0 +1,65 @@
|
||||
/* This file is part of the Calibre-Web (https://github.com/janeczku/calibre-web)
|
||||
* Copyright (C) 2022 OzzieIsaacs
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
$(document).ready(function() {
|
||||
i18next.use(i18nextHttpBackend).init({
|
||||
lng: $('#password').data("lang"),
|
||||
debug: false,
|
||||
fallbackLng: 'en',
|
||||
backend: {
|
||||
loadPath: getPath() + "/static/js/libs/pwstrength/locales/{{lng}}.json",
|
||||
},
|
||||
|
||||
}, function () {
|
||||
if ($('#password').data("verify")) {
|
||||
// Initialized and ready to go
|
||||
var options = {};
|
||||
options.common = {
|
||||
minChar: $('#password').data("min"),
|
||||
maxChar: -1
|
||||
}
|
||||
options.ui = {
|
||||
bootstrap3: true,
|
||||
showProgressBar: false,
|
||||
showErrors: true,
|
||||
showVerdicts: false,
|
||||
}
|
||||
options.rules= {
|
||||
specialCharClass: "(?=.*?[^A-Za-z\\s0-9])",
|
||||
activated: {
|
||||
wordNotEmail: false,
|
||||
wordMinLength: $('#password').data("min"),
|
||||
// wordMaxLength: false,
|
||||
// wordInvalidChar: true,
|
||||
wordSimilarToUsername: false,
|
||||
wordSequences: false,
|
||||
wordTwoCharacterClasses: false,
|
||||
wordRepetitions: false,
|
||||
wordLowercase: $('#password').data("lower") === "True" ? true : false,
|
||||
wordUppercase: $('#password').data("upper") === "True" ? true : false,
|
||||
wordOneNumber: $('#password').data("number") === "True" ? true : false,
|
||||
wordThreeNumbers: false,
|
||||
wordOneSpecialChar: $('#password').data("special") === "True" ? true : false,
|
||||
// wordTwoSpecialChar: true,
|
||||
wordUpperLowerCombo: false,
|
||||
wordLetterNumberCombo: false,
|
||||
wordLetterNumberCharCombo: false
|
||||
}
|
||||
}
|
||||
$('#password').pwstrength(options);
|
||||
}
|
||||
});
|
||||
});
|
@ -353,6 +353,53 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title">
|
||||
<a class="accordion-toggle" data-toggle="collapse" href="#collapsesix">
|
||||
<span class="glyphicon glyphicon-plus"></span>
|
||||
{{_('Securitiy Settings')}}
|
||||
</a>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="collapsesix" class="panel-collapse collapse">
|
||||
<div class="panel-body">
|
||||
<div class="form-group">
|
||||
<label for="config_session">{{_('Session protection')}}</label>
|
||||
<select name="config_session" id="config_session" class="form-control">
|
||||
<option value="0" {% if config.config_session == 0 %}selected{% endif %}>{{_('Basic')}}</option>
|
||||
<option value="1" {% if config.config_session == 1 %}selected{% endif %}>{{_('Strong')}}</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="checkbox" id="config_password_policy" data-control="password_settings" name="config_password_policy" {% if config.config_password_policy %}checked{% endif %}>
|
||||
<label for="config_password_policy">{{_('User Password policy')}}</label>
|
||||
</div>
|
||||
<div data-related="password_settings">
|
||||
<div class="form-group" style="margin-left:10px;">
|
||||
<label for="config_password_min_length">{{_('Minimum password length')}}</label>
|
||||
<input type="number" min="0" max="40" class="form-control" name="config_password_min_length" id="config_password_min_length" value="{% if config.config_password_min_length != None %}{{ config.config_password_min_length }}{% endif %}" autocomplete="off" required>
|
||||
</div>
|
||||
<div class="form-group" style="margin-left:10px;">
|
||||
<input type="checkbox" id="config_password_number" name="config_password_number" {% if config.config_password_number %}checked{% endif %}>
|
||||
<label for="config_password_number">{{_('Enforce number')}}</label>
|
||||
</div>
|
||||
<div class="form-group" style="margin-left:10px;">
|
||||
<input type="checkbox" id="config_password_lower" name="config_password_lower" {% if config.config_password_lower %}checked{% endif %}>
|
||||
<label for="config_password_lower">{{_('Enforce lowercase characters')}}</label>
|
||||
</div>
|
||||
<div class="form-group" style="margin-left:10px;">
|
||||
<input type="checkbox" id="config_password_upper" name="config_password_upper" {% if config.config_password_upper %}checked{% endif %}>
|
||||
<label for="config_password_upper">{{_('Enforce uppercase characters')}}</label>
|
||||
</div>
|
||||
<div class="form-group" style="margin-left:10px;">
|
||||
<input type="checkbox" id="config_password_special" name="config_password_special" {% if config.config_password_special %}checked{% endif %}>
|
||||
<label for="config_password_special">{{_('Enforce special characters')}}</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-12">
|
||||
<button type="button" name="submit" id="config_submit" class="btn btn-default">{{_('Save')}}</button>
|
||||
|
10
cps/templates/locales/en/translation.json
Normal file
10
cps/templates/locales/en/translation.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"input": {
|
||||
"placeholder": "a placeholder"
|
||||
},
|
||||
"nav": {
|
||||
"home": "Home",
|
||||
"page1": "Page One",
|
||||
"page2": "Page Two"
|
||||
}
|
||||
}
|
@ -21,7 +21,7 @@
|
||||
{% endif %}
|
||||
<div class="form-group">
|
||||
<label for="password">{{_('Password')}}</label>
|
||||
<input type="password" class="form-control" name="password" id="password" value="" autocomplete="off">
|
||||
<input type="password" class="form-control" name="password" id="password" data-lang="{{ g.user.locale }}" data-verify="{{ config.config_password_policy }}" {% if config.config_password_policy %} data-min={{ config.config_password_min_length }} data-special={{ config.config_password_special }} data-upper={{ config.config_password_upper }} data-lower={{ config.config_password_lower }} data-number={{ config.config_password_number }}{% endif %} value="" autocomplete="off">
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="form-group">
|
||||
@ -175,5 +175,9 @@
|
||||
<script src="{{ url_for('static', filename='js/libs/bootstrap-table/bootstrap-table.min.js') }}"></script>
|
||||
<script src="{{ url_for('static', filename='js/libs/bootstrap-table/bootstrap-table-editable.min.js') }}"></script>
|
||||
<script src="{{ url_for('static', filename='js/libs/bootstrap-table/bootstrap-editable.min.js') }}"></script>
|
||||
<script src="{{ url_for('static', filename='js/libs/pwstrength/i18next.min.js') }}"></script>
|
||||
<script src="{{ url_for('static', filename='js/libs/pwstrength/i18nextHttpBackend.min.js') }}"></script>
|
||||
<script src="{{ url_for('static', filename='js/libs/pwstrength/pwstrength-bootstrap.min.js') }}"></script>
|
||||
<script src="{{ url_for('static', filename='js/password.js') }}"></script>
|
||||
<script src="{{ url_for('static', filename='js/table.js') }}"></script>
|
||||
{% endblock %}
|
||||
|
11
cps/web.py
11
cps/web.py
@ -46,7 +46,7 @@ from .gdriveutils import getFileFromEbooksFolder, do_gdrive_download
|
||||
from .helper import check_valid_domain, check_email, check_username, \
|
||||
get_book_cover, get_series_cover_thumbnail, get_download_link, send_mail, generate_random_password, \
|
||||
send_registration_mail, check_send_to_ereader, check_read_formats, tags_filters, reset_password, valid_email, \
|
||||
edit_book_read_status
|
||||
edit_book_read_status, valid_password
|
||||
from .pagination import Pagination
|
||||
from .redirect import redirect_back
|
||||
from .babel import get_available_locale
|
||||
@ -55,6 +55,7 @@ from .kobo_sync_status import remove_synced_book
|
||||
from .render_template import render_title_template
|
||||
from .kobo_sync_status import change_archived_books
|
||||
|
||||
|
||||
feature_support = {
|
||||
'ldap': bool(services.ldap),
|
||||
'goodreads': bool(services.goodreads_support),
|
||||
@ -1355,10 +1356,10 @@ def logout():
|
||||
def change_profile(kobo_support, local_oauth_check, oauth_status, translations, languages):
|
||||
to_save = request.form.to_dict()
|
||||
current_user.random_books = 0
|
||||
if current_user.role_passwd() or current_user.role_admin():
|
||||
if to_save.get("password"):
|
||||
current_user.password = generate_password_hash(to_save.get("password"))
|
||||
try:
|
||||
if current_user.role_passwd() or current_user.role_admin():
|
||||
if to_save.get('password', "") != "":
|
||||
current_user.password = generate_password_hash(valid_password(to_save['password']))
|
||||
if to_save.get("kindle_mail", current_user.kindle_mail) != current_user.kindle_mail:
|
||||
current_user.kindle_mail = valid_email(to_save.get("kindle_mail"))
|
||||
if to_save.get("email", current_user.email) != current_user.email:
|
||||
@ -1382,6 +1383,7 @@ def change_profile(kobo_support, local_oauth_check, oauth_status, translations,
|
||||
flash(str(ex), category="error")
|
||||
return render_title_template("user_edit.html",
|
||||
content=current_user,
|
||||
config=config,
|
||||
translations=translations,
|
||||
profile=1,
|
||||
languages=languages,
|
||||
@ -1433,6 +1435,7 @@ def profile():
|
||||
profile=1,
|
||||
languages=languages,
|
||||
content=current_user,
|
||||
config=config,
|
||||
kobo_support=kobo_support,
|
||||
title=_(u"%(name)s's profile", name=current_user.name),
|
||||
page="me",
|
||||
|
@ -5,7 +5,7 @@ Flask-Babel>=0.11.1,<2.1.0
|
||||
Flask-Login>=0.3.2,<0.6.2
|
||||
Flask-Principal>=0.3.2,<0.5.1
|
||||
backports_abc>=0.4
|
||||
Flask>=1.0.2,<2.1.0
|
||||
Flask>=1.0.2,<2.2.0
|
||||
iso-639>=0.4.5,<0.5.0
|
||||
PyPDF3>=1.0.0,<1.0.7
|
||||
pytz>=2016.10
|
||||
|
@ -45,7 +45,7 @@ install_requires =
|
||||
Flask-Login>=0.3.2,<0.6.2
|
||||
Flask-Principal>=0.3.2,<0.5.1
|
||||
backports_abc>=0.4
|
||||
Flask>=1.0.2,<2.1.0
|
||||
Flask>=1.0.2,<2.2.0
|
||||
iso-639>=0.4.5,<0.5.0
|
||||
PyPDF3>=1.0.0,<1.0.7
|
||||
pytz>=2016.10
|
||||
@ -97,5 +97,5 @@ comics =
|
||||
natsort>=2.2.0,<8.2.0
|
||||
comicapi>=2.2.0,<2.3.0
|
||||
kobo =
|
||||
jsonschema>=3.2.0,<4.6.0
|
||||
jsonschema>=3.2.0,<4.7.0
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user