1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-09-01 15:09:14 +00:00

change password check (#6656)

* change password check

* update

* Update views.py

* optimize-code

* remove min_len and level when frontend check password

* remove too short level

---------

Co-authored-by: r350178982 <32759763+r350178982@users.noreply.github.com>
This commit is contained in:
Michael An
2024-08-28 17:52:54 +08:00
committed by GitHub
parent 0aa7c7da00
commit fedfbf9bf4
13 changed files with 48 additions and 103 deletions

View File

@@ -10,7 +10,6 @@ const propTypes = {
const PASSWORD_STRENGTH_VALUES = { const PASSWORD_STRENGTH_VALUES = {
empty: { classNames: ['default', 'default', 'default', 'default'], textValue: '' }, empty: { classNames: ['default', 'default', 'default', 'default'], textValue: '' },
too_short: { classNames: ['too-short', 'default', 'default', 'default'], textValue: 'too short' },
weak: { classNames: ['weak', 'default', 'default', 'default'], textValue: 'weak' }, weak: { classNames: ['weak', 'default', 'default', 'default'], textValue: 'weak' },
medium: { classNames: ['medium', 'medium', 'default', 'default'], textValue: 'medium' }, medium: { classNames: ['medium', 'medium', 'default', 'default'], textValue: 'medium' },
strong: { classNames: ['strong', 'strong', 'strong', 'default'], textValue: 'strong' }, strong: { classNames: ['strong', 'strong', 'strong', 'default'], textValue: 'strong' },

View File

@@ -1689,7 +1689,6 @@ export const evaluatePasswordStrength = (password) => {
else if (length >= 12) strength += 3; else if (length >= 12) strength += 3;
else if (length >= 8) strength += 2; else if (length >= 8) strength += 2;
else if (length >= 6) strength += 1; else if (length >= 6) strength += 1;
else if (length < 6) return 'too_short';
// Increased strength based on character type // Increased strength based on character type
if (hasUppercase) strength += 1; if (hasUppercase) strength += 1;

View File

@@ -38,7 +38,6 @@ from seahub.utils import render_error, get_site_name, is_valid_email, get_servic
from seahub.utils.http import rate_limit from seahub.utils.http import rate_limit
from seahub.utils.ip import get_remote_ip from seahub.utils.ip import get_remote_ip
from seahub.utils.file_size import get_quota_from_string from seahub.utils.file_size import get_quota_from_string
from seahub.utils.password import get_password_strength_requirements
from seahub.utils.two_factor_auth import two_factor_auth_enabled, handle_two_factor_auth from seahub.utils.two_factor_auth import two_factor_auth_enabled, handle_two_factor_auth
from seahub.utils.user_permissions import get_user_role from seahub.utils.user_permissions import get_user_role
from seahub.utils.auth import get_login_bg_image_path from seahub.utils.auth import get_login_bg_image_path
@@ -439,9 +438,8 @@ def password_reset_confirm(request, uidb36=None, token=None, template_name='regi
context_instance['validlink'] = False context_instance['validlink'] = False
form = None form = None
context_instance['form'] = form context_instance['form'] = form
password_strength_requirements = get_password_strength_requirements()
context_instance['min_len'] = password_strength_requirements.get('min_len') context_instance['strong_pwd_required'] = config.USER_STRONG_PASSWORD_REQUIRED
context_instance['level'] = len(password_strength_requirements.get('char_types'))
return render(request, template_name, context_instance) return render(request, template_name, context_instance)
def password_reset_complete(request, template_name='registration/password_reset_complete.html'): def password_reset_complete(request, template_name='registration/password_reset_complete.html'):

View File

@@ -87,16 +87,15 @@ $('#signup-form').on('submit', function(){
$('.error').html("{% trans "Passwords don't match" %}").removeClass('hide'); $('.error').html("{% trans "Passwords don't match" %}").removeClass('hide');
return false; return false;
} }
var level = getStrengthLevel(pwd1); if (!checkPasswordStrength(pwd1, {{strong_pwd_required}})) {
if (level < {{level}}) {
$('.error').html(passwd_tip).removeClass('hide'); $('.error').html(passwd_tip).removeClass('hide');
return false; return false;
} }
}); });
$(function () { $(function () {
// Assuming passwd_tip and template are defined somewhere in your script. // Assuming passwd_tip and template are defined somewhere in your script.
setupPasswordField("password1", 'password-input1', passwd_tip, template); setupPasswordField("password1", passwd_tip, template);
setupPasswordField("password2", 'password-input2', passwd_tip, template); setupPasswordField("password2", passwd_tip, template);
}); });
</script> </script>
{% endblock %} {% endblock %}

View File

@@ -36,9 +36,9 @@ from seahub.organizations.settings import ORG_AUTO_URL_PREFIX, \
ORG_ENABLE_ADMIN_INVITE_USER ORG_ENABLE_ADMIN_INVITE_USER
from seahub.organizations.utils import get_or_create_invitation_link from seahub.organizations.utils import get_or_create_invitation_link
from seahub.subscription.utils import subscription_check from seahub.subscription.utils import subscription_check
from constance import config
# Get an instance of a logger # Get an instance of a logger
from seahub.utils.password import get_password_strength_requirements
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -236,17 +236,13 @@ def org_register(request):
up = urlparse(service_url) up = urlparse(service_url)
service_url_scheme = up.scheme service_url_scheme = up.scheme
service_url_remaining = up.netloc + up.path service_url_remaining = up.netloc + up.path
password_strength_requirements = get_password_strength_requirements()
level = len(password_strength_requirements.get('char_types'))
return render(request, 'organizations/org_register.html', { return render(request, 'organizations/org_register.html', {
'form': form, 'form': form,
'login_bg_image_path': login_bg_image_path, 'login_bg_image_path': login_bg_image_path,
'service_url_scheme': service_url_scheme, 'service_url_scheme': service_url_scheme,
'service_url_remaining': service_url_remaining, 'service_url_remaining': service_url_remaining,
'org_auto_url_prefix': ORG_AUTO_URL_PREFIX, 'org_auto_url_prefix': ORG_AUTO_URL_PREFIX,
'min_len': password_strength_requirements.get('min_len'), 'strong_pwd_required': config.USER_STRONG_PASSWORD_REQUIRED
'level': level
}) })

View File

@@ -25,7 +25,7 @@ window.app.pageOptions = {
passwordOperationText: {% if user_unusable_password %}"{% trans "Set Password" %}"{% else %}"{% trans "Update" %}"{% endif %}, passwordOperationText: {% if user_unusable_password %}"{% trans "Set Password" %}"{% else %}"{% trans "Update" %}"{% endif %},
{% endif %} {% endif %}
userUnusablePassword: {% if user_unusable_password %} true {% else %} false {% endif %}, userUnusablePassword: {% if user_unusable_password %} true {% else %} false {% endif %},
userStrongPasswordRequired: {% if user_strong_password_required %} true {% else %} false {% endif %}, userStrongPasswordRequired: {% if strong_pwd_required %} true {% else %} false {% endif %},
enableGetAuthToken: {% if ENABLE_GET_AUTH_TOKEN_BY_SESSION %} true {% else %} false {% endif %}, enableGetAuthToken: {% if ENABLE_GET_AUTH_TOKEN_BY_SESSION %} true {% else %} false {% endif %},

View File

@@ -171,7 +171,7 @@ def edit_profile(request):
'enable_multi_adfs': enable_multi_adfs, 'enable_multi_adfs': enable_multi_adfs,
'org_saml_connected': org_saml_connected, 'org_saml_connected': org_saml_connected,
'org_id': request.user.org and request.user.org.org_id or None, 'org_id': request.user.org and request.user.org.org_id or None,
'user_strong_password_required': bool(config.USER_STRONG_PASSWORD_REQUIRED), 'strong_pwd_required': bool(config.USER_STRONG_PASSWORD_REQUIRED),
} }
if show_two_factor_auth: if show_two_factor_auth:

View File

@@ -34,27 +34,13 @@
$('[type="password"]').addClass('input'); $('[type="password"]').addClass('input');
$('.new-narrow-panel').removeClass('vh'); $('.new-narrow-panel').removeClass('vh');
{% if strong_pwd_required %}
{% include "snippets/password_strength_js.html" %} {% include "snippets/password_strength_js.html" %}
var passwd_tip = "{% blocktrans %}Passwords must have at least {{min_len}} characters and contain {{level}} of the following: uppercase letters, lowercase letters, numbers, and symbols.{% endblocktrans%}";
var element = document.getElementById('id_new_password1') $(function () {
var popover = new bootstrap.Popover(element, { // Assuming passwd_tip and template are defined somewhere in your script.
container: 'body', setupPasswordField("id_new_password1", passwd_tip, template);
animation: false, setupPasswordField("id_new_password2", passwd_tip, template);
content: passwd_tip,
template: `<div class="popover" role="popover"><div class="popover-arrow"></div><div class="popover-inner">${passwd_tip}</div></div>`,
trigger: 'focus'
}); });
element.addEventListener('keyup', () => {
var pwd = $('#id_new_password1').val();
if (pwd.trim()) {
var level = getStrengthLevel(pwd);
showStrength(level);
} else {
$("#pwd_strength").html("");
}
})
{% endif %}
$('form').on('submit', function(){ $('form').on('submit', function(){
var old_pwd = $('input[name="old_password"]').val().trim(), var old_pwd = $('input[name="old_password"]').val().trim(),
@@ -77,14 +63,10 @@ $('form').on('submit', function(){
$('.error').html("{% trans "Passwords don't match" %}").removeClass('hide'); $('.error').html("{% trans "Passwords don't match" %}").removeClass('hide');
return false; return false;
} }
if (!checkPasswordStrength(pwd1, {{strong_pwd_required}})) {
{% if strong_pwd_required %}
var level = getStrengthLevel(pwd1);
if (level < {{level}}) {
$('.error').html(passwd_tip).removeClass('hide'); $('.error').html(passwd_tip).removeClass('hide');
return false; return false;
} }
{% endif %}
}); });
</script> </script>
{% endblock %} {% endblock %}

View File

@@ -46,8 +46,8 @@ $('[type="password"]').addClass('input');
{% include "snippets/password_strength_js.html" %} {% include "snippets/password_strength_js.html" %}
$(function () { $(function () {
// Assuming passwd_tip and template are defined somewhere in your script. // Assuming passwd_tip and template are defined somewhere in your script.
setupPasswordField("id_new_password1", 'password-input1', passwd_tip, template); setupPasswordField("id_new_password1", passwd_tip, template);
setupPasswordField("id_new_password2", 'password-input2', passwd_tip, template); setupPasswordField("id_new_password2", passwd_tip, template);
}); });
$('#signup-form').on('submit', function(){ $('#signup-form').on('submit', function(){
@@ -66,8 +66,7 @@ $('#signup-form').on('submit', function(){
$('.error').html("{% trans "Passwords don't match" %}").removeClass('hide'); $('.error').html("{% trans "Passwords don't match" %}").removeClass('hide');
return false; return false;
} }
var level = getStrengthLevel(pwd1); if (!checkPasswordStrength(pwd1, {{strong_pwd_required}})) {
if (level < {{level}}) {
$('.error').html(passwd_tip).removeClass('hide'); $('.error').html(passwd_tip).removeClass('hide');
return false; return false;
} }

View File

@@ -37,27 +37,13 @@
$('[type="email"], [type="password"]').addClass('input'); $('[type="email"], [type="password"]').addClass('input');
$('.new-narrow-panel').removeClass('vh'); $('.new-narrow-panel').removeClass('vh');
{% if strong_pwd_required %}
{% include "snippets/password_strength_js.html" %} {% include "snippets/password_strength_js.html" %}
var passwd_tip = "{% blocktrans %}Passwords must have at least {{min_len}} characters and contain {{level}} of the following: uppercase letters, lowercase letters, numbers, and symbols.{% endblocktrans%}";
var element = document.getElementById('id_new_password1') $(function () {
var popover = new bootstrap.Popover(element, { // Assuming passwd_tip and template are defined somewhere in your script.
container: 'body', setupPasswordField("id_new_password1", passwd_tip, template);
animation: false, setupPasswordField("id_new_password2", passwd_tip, template);
content: passwd_tip,
template: `<div class="popover" role="popover"><div class="popover-arrow"></div><div class="popover-inner">${passwd_tip}</div></div>`,
trigger: 'focus'
}); });
element.addEventListener('keyup', () => {
var pwd = $('#id_new_password1').val();
if (pwd.trim()) {
var level = getStrengthLevel(pwd);
showStrength(level);
} else {
$("#pwd_strength").html("");
}
})
{% endif %}
$('form').on('submit', function(){ $('form').on('submit', function(){
var pwd1 = $('input[name="new_password1"]').val().trim(), var pwd1 = $('input[name="new_password1"]').val().trim(),
@@ -76,13 +62,10 @@ $('form').on('submit', function(){
return false; return false;
} }
{% if strong_pwd_required %} if (!checkPasswordStrength(pwd1, {{strong_pwd_required}})) {
var level = getStrengthLevel(pwd1);
if (level < {{level}}) {
$('.error').html(passwd_tip).removeClass('hide'); $('.error').html(passwd_tip).removeClass('hide');
return false; return false;
} }
{% endif %}
}); });
</script> </script>
{% endblock %} {% endblock %}

View File

@@ -68,8 +68,8 @@
$(function () { $(function () {
// Assuming passwd_tip and template are defined somewhere in your script. // Assuming passwd_tip and template are defined somewhere in your script.
setupPasswordField("id_password1", 'password-input1', passwd_tip, template); setupPasswordField("id_password1", passwd_tip, template);
setupPasswordField("id_password2", 'password-input2', passwd_tip, template); setupPasswordField("id_password2", passwd_tip, template);
}); });
@@ -94,8 +94,7 @@ $('#signup-form').on('submit', function(){
$('.error').html("{% trans "Passwords don't match" %}").removeClass('hide'); $('.error').html("{% trans "Passwords don't match" %}").removeClass('hide');
return false; return false;
} }
var level = getStrengthLevel(pwd1); if (!checkPasswordStrength(pwd1, {{strong_pwd_required}})) {
if (level < {{level}}) {
$('.error').html(passwd_tip).removeClass('hide'); $('.error').html(passwd_tip).removeClass('hide');
return false; return false;
} }

View File

@@ -19,7 +19,7 @@ var template = `
</div> </div>
`; `;
function setupPasswordField(selector, container, passwdTip, baseTemplate) { function setupPasswordField(selector, passwdTip, baseTemplate) {
var template = baseTemplate.replace('registration-form-popover', `registration-form-popover ${isMobile() ? 'mobile' : ''}`); var template = baseTemplate.replace('registration-form-popover', `registration-form-popover ${isMobile() ? 'mobile' : ''}`);
var element = document.getElementById(selector); var element = document.getElementById(selector);
var popover = new bootstrap.Popover(element, { var popover = new bootstrap.Popover(element, {
@@ -33,35 +33,33 @@ function setupPasswordField(selector, container, passwdTip, baseTemplate) {
element.addEventListener('keyup', () => { element.addEventListener('keyup', () => {
var pwd = element.value; var pwd = element.value;
if (pwd.trim()) { if (pwd.trim()) {
var level = getStrengthLevel(pwd.trim()); var level = strengthLevelMap[evaluatePasswordStrength(pwd.trim())];
showStrength(level); showStrength(level);
} }
}); });
} }
const passwordConfig = { const passwordConfig = {
minLen: {{min_len}},
labelColors: { labelColors: {
1: "#E43C44", // too short 1: "#E43C44", // weak
2: "#E43C44", // weak 2: "#FFA800", // medium
3: "#FFA800", // medium 3: "#26B20E", // strong
4: "#26B20E", // strong 4: "#26B20E" // very strong
5: "#26B20E" // very strong
}, },
strengthLevels: ['too short', 'weak', 'medium', 'strong', 'very strong'] strengthLevels: ['', 'weak', 'medium', 'strong', 'very strong']
}; };
const strengthLevelMap = { const strengthLevelMap = {
too_short: 1, weak: 1,
weak: 2, medium: 2,
medium: 3, strong: 3,
strong: 4, very_strong: 4,
very_strong: 5
}; };
function getStrengthLevel(pwd) { function checkPasswordStrength(pwd, strong_pwd_required) {
if (pwd.length === 0) return 0; if (pwd.length === 0) return false;
return pwd.length < passwordConfig.minLen ? 1 : strengthLevelMap[evaluatePasswordStrength(pwd)]; const support_strength_types = strong_pwd_required ? ['strong', 'very_strong'] : ['medium', 'strong', 'very_strong'];
return support_strength_types.includes(evaluatePasswordStrength(pwd));
} }
function evaluatePasswordStrength(password) { function evaluatePasswordStrength(password) {
@@ -73,7 +71,6 @@ function evaluatePasswordStrength(password) {
let strength = 0; let strength = 0;
strength += length >= 16 ? 4 : length >= 12 ? 3 : length >= 8 ? 2 : length >= 6 ? 1 : 0; strength += length >= 16 ? 4 : length >= 12 ? 3 : length >= 8 ? 2 : length >= 6 ? 1 : 0;
if (length < 6) return 'too_short';
strength += hasUppercase + hasLowercase + hasNumbers + hasSpecialChars; strength += hasUppercase + hasLowercase + hasNumbers + hasSpecialChars;
@@ -89,11 +86,10 @@ function showStrength(level) {
const processList = document.querySelectorAll('.progress-bar'); const processList = document.querySelectorAll('.progress-bar');
const { labelColors, strengthLevels } = passwordConfig; const { labelColors, strengthLevels } = passwordConfig;
const colors = { const colors = {
1: ["#E43C44", "#DBDBDB", "#DBDBDB", "#DBDBDB"], // too short 1: ["#E43C44", "#DBDBDB", "#DBDBDB", "#DBDBDB"], // weak
2: ["#E43C44", "#DBDBDB", "#DBDBDB", "#DBDBDB"], // weak 2: ["#FFA800", "#FFA800", "#DBDBDB", "#DBDBDB"], // medium
3: ["#FFA800", "#FFA800", "#DBDBDB", "#DBDBDB"], // medium 3: ["#26B20E", "#26B20E", "#26B20E", "#DBDBDB"], // strong
4: ["#26B20E", "#26B20E", "#26B20E", "#DBDBDB"], // strong 4: ["#26B20E", "#26B20E", "#26B20E", "#26B20E"] // very strong
5: ["#26B20E", "#26B20E", "#26B20E", "#26B20E"] // very strong
}; };
// Set default color if level is out of bounds // Set default color if level is out of bounds
@@ -104,6 +100,6 @@ function showStrength(level) {
processList.forEach((bar, index) => { processList.forEach((bar, index) => {
bar.style.backgroundColor = colorScheme[index]; bar.style.backgroundColor = colorScheme[index];
}); });
const strengthLevel = strengthLevels[level - 1] || '' const strengthLevel = strengthLevels[level] || '';
popoverHead.html(`${passwordStrength} : <span style="color: ${labelColors[level]}">${strengthLevel}</span>`); popoverHead.html(`${passwordStrength} : <span style="color: ${labelColors[level]}">${strengthLevel}</span>`);
} }

View File

@@ -14,7 +14,6 @@ from constance import config
from seahub import settings from seahub import settings
from seahub.utils.auth import get_login_bg_image_path from seahub.utils.auth import get_login_bg_image_path
from seahub.utils.password import get_password_strength_requirements
def activate(request, backend, def activate(request, backend,
@@ -220,9 +219,5 @@ def register(request, backend, success_url=None, form_class=None,
context['form'] = form context['form'] = form
login_bg_image_path = get_login_bg_image_path() login_bg_image_path = get_login_bg_image_path()
context['login_bg_image_path'] = login_bg_image_path context['login_bg_image_path'] = login_bg_image_path
context['strong_pwd_required'] = config.USER_STRONG_PASSWORD_REQUIRED
password_strength_requirements = get_password_strength_requirements()
context['min_len'] = password_strength_requirements.get('min_len')
context['level'] = len(password_strength_requirements.get('char_types'))
return render(request, template_name, context) return render(request, template_name, context)