Skip to content
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
4 changes: 2 additions & 2 deletions corehq/apps/api/tests/test_user_updates.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ def test_update_password_with_strong_passwords_succeeds(self):
self.domain_obj.strong_mobile_passwords = True
self.domain_obj.save()

self.commcare_user_updater.update('password', 'a7d8fhjkdf8d') # should not raise
self.commcare_user_updater.update('password', 'a7d8fhjkdf8d3k') # should not raise

def test_update_email_succeeds(self):
self.user.email = 'initial@dimagi.com'
Expand Down Expand Up @@ -293,7 +293,7 @@ def setUp(self) -> None:
self.commcare_user_updater = CommcareUserUpdates(self.user, self.domain, self.user_change_logger)

def test_update_password_logs_change(self):
self.commcare_user_updater.update('password', 'a7d8fhjkdf8d')
self.commcare_user_updater.update('password', 'a7d8fhjkdf8d3k')
self.assertIn(PASSWORD_FIELD, self.user_change_logger.change_messages.keys())

def test_update_email_logs_change(self):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
+import "hqwebapp/js/bootstrap5/validators.ko"; // email address validation
import "eonasdan-bootstrap-datetimepicker/build/js/bootstrap-datetimepicker.min";

// These are used as css classes, so the values of success/warning/error need to be what they are.
@@ -134,7 +134,7 @@
// Must not be shorter than settings.MINIMUM_PASSWORD_LENGTH, or generated
@@ -139,7 +139,7 @@
url: initialPageData.reverse(urlName, userIdOrName),
data: bodyData,
success: function (data) {
Expand All @@ -22,7 +22,7 @@
if (data.success) {
self.action_error('');
} else {
@@ -142,7 +142,7 @@
@@ -147,7 +147,7 @@
}
},
error: function () {
Expand All @@ -31,7 +31,7 @@
self.action_error(gettext("Issue communicating with server. Try again."));
},
});
@@ -157,7 +157,7 @@
@@ -162,7 +162,7 @@
url: initialPageData.reverse(urlName, self.user_id()),
success: function (data) {
$modal.find(".btn").enableButton();
Expand All @@ -40,7 +40,7 @@
if (data.success) {
self.action_error('');
self.confirmation_sent_at(new Date());
@@ -168,7 +168,7 @@
@@ -173,7 +173,7 @@
},
error: function () {
$modal.find(".btn").enableButton();
Expand All @@ -49,7 +49,7 @@
self.action_error(gettext("Issue communicating with server. Try again."));
},
});
@@ -484,7 +484,7 @@
@@ -489,7 +489,7 @@
}

if (options.show_deactivate_after_date) {
Expand All @@ -58,7 +58,7 @@
format: 'MM-y',
});
}
@@ -533,7 +533,7 @@
@@ -538,7 +538,7 @@
});

self.submitNewUser = function () {
Expand Down
5 changes: 4 additions & 1 deletion corehq/apps/users/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,10 @@
from .util import cc_user_domain, format_username, log_user_change

UNALLOWED_MOBILE_WORKER_NAMES = ('admin', 'demo_user')
STRONG_PASSWORD_LEN = 12
# Must not be shorter than settings.MINIMUM_PASSWORD_LENGTH, or generated
# passwords will be rejected by clean_password(). Kept in sync with
# STRONG_PASSWORD_LEN in users/js/bootstrap{3,5}/mobile_workers.js.
STRONG_PASSWORD_LEN = 14

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this just be STRONG_PASSWORD_LEN = settings.MINIMUM_PASSWORD_LENGTH, and probably skip the comment?



def get_mobile_worker_max_username_length(domain):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ import "hqwebapp/js/components/search_box";
import "hqwebapp/js/bootstrap3/validators.ko"; // email address validation
import "eonasdan-bootstrap-datetimepicker/build/js/bootstrap-datetimepicker.min";

// Must not be shorter than settings.MINIMUM_PASSWORD_LENGTH, or generated
// passwords will be rejected by the server. Kept in sync with
// STRONG_PASSWORD_LEN in corehq/apps/users/forms.py.
var STRONG_PASSWORD_LEN = 14;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a way to pass this in from that constant in forms.py so we're not setting the same thing in two places?

Alternately, we might use initialPageData.get('minimumPasswordLength') (the same as settings.MINIMUM_PASSWORD_LENGTH if the goal is actually to set this the same as the minimum password length setting.


// These are used as css classes, so the values of success/warning/error need to be what they are.
var STATUS = {
NONE: '',
Expand Down Expand Up @@ -408,7 +413,7 @@ var newUserCreationModel = function (options) {
password += pick(lowercase, 1);
password += pick(uppercase, 1);
password += pick(numbers, 1);
password += pick(all, 6, 10);
password += pick(all, STRONG_PASSWORD_LEN - password.length);
return shuffle(password);
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ import "hqwebapp/js/components/search_box";
import "hqwebapp/js/bootstrap5/validators.ko"; // email address validation
import "eonasdan-bootstrap-datetimepicker/build/js/bootstrap-datetimepicker.min";

// Must not be shorter than settings.MINIMUM_PASSWORD_LENGTH, or generated
// passwords will be rejected by the server. Kept in sync with
// STRONG_PASSWORD_LEN in corehq/apps/users/forms.py.
var STRONG_PASSWORD_LEN = 14;

// These are used as css classes, so the values of success/warning/error need to be what they are.
var STATUS = {
NONE: '',
Expand Down Expand Up @@ -408,7 +413,7 @@ var newUserCreationModel = function (options) {
password += pick(lowercase, 1);
password += pick(uppercase, 1);
password += pick(numbers, 1);
password += pick(all, 6, 10);
password += pick(all, STRONG_PASSWORD_LEN - password.length);
return shuffle(password);
};

Expand Down
12 changes: 12 additions & 0 deletions corehq/apps/users/tests/test_forms.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import string

from django.conf import settings
from django.test import SimpleTestCase

from corehq.apps.domain.forms import clean_password

from ..forms import STRONG_PASSWORD_LEN, generate_strong_password


Expand All @@ -26,3 +29,12 @@ def test_contains_digit(self):

def test_contains_punc(self):
self.assertTrue(any(c in string.punctuation for c in self.password))

def test_length_is_not_below_configured_minimum(self):
# Generated passwords are offered to users as-is, so a generator
# shorter than the minimum would suggest a password that then fails
# validation on submit.
assert STRONG_PASSWORD_LEN >= settings.MINIMUM_PASSWORD_LENGTH

def test_passes_password_validation(self):
assert clean_password(self.password) == self.password
2 changes: 1 addition & 1 deletion settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@
SECURE_TIMEOUT = 30
DISABLE_AUTOCOMPLETE_ON_SENSITIVE_FORMS = False
MINIMUM_ZXCVBN_SCORE = 2
MINIMUM_PASSWORD_LENGTH = 8
MINIMUM_PASSWORD_LENGTH = 14
CUSTOM_PASSWORD_STRENGTH_MESSAGE = ''
ADD_CAPTCHA_FIELD_TO_FORMS = False
FORMS_URLFIELD_ASSUME_HTTPS = True
Expand Down
Loading