From 7c7a07fb5a91f7157ffb0cec903e5d4b44bb3a0d Mon Sep 17 00:00:00 2001 From: Joseph Schorr Date: Wed, 18 Jan 2017 17:42:27 -0500 Subject: [PATCH] Allow namespaces to be between 2 and 255 characters in length [Delivers #137924329] --- static/directives/signup-form.html | 10 +++----- static/js/app.js | 4 +-- static/js/directives/ui/namespace-input.js | 12 ++++++--- static/partials/new-organization.html | 10 +++----- static/partials/update-user.html | 8 +++--- test/test_api_usage.py | 2 +- test/test_util.py | 30 ++++++++++++---------- util/validation.py | 6 ++--- 8 files changed, 43 insertions(+), 39 deletions(-) diff --git a/static/directives/signup-form.html b/static/directives/signup-form.html index 6430d2e16..e5ec7f75c 100644 --- a/static/directives/signup-form.html +++ b/static/directives/signup-form.html @@ -9,14 +9,12 @@
- + -
diff --git a/static/partials/update-user.html b/static/partials/update-user.html index a6a959acb..d4a2d298d 100644 --- a/static/partials/update-user.html +++ b/static/partials/update-user.html @@ -9,7 +9,7 @@

Please confirm the selected username or enter a different username below:

-
@@ -17,7 +17,7 @@ ng-disabled="usernameForm.$invalid || state != 'confirmed'" value="Confirm Username"> - + Username valid @@ -29,8 +29,8 @@ Usernames must be alphanumeric and be at least four characters in length - - Note: Usernames with dots or dashes are incompatible with Docker version 1.8 or older + + {{ backIncompatMessage }}
diff --git a/test/test_api_usage.py b/test/test_api_usage.py index 31d101c5b..500d0d424 100644 --- a/test/test_api_usage.py +++ b/test/test_api_usage.py @@ -651,7 +651,7 @@ class TestCreateNewUser(ApiTestCase): email='test@example.com'), expected_code=400) - self.assertEquals('Invalid namespace a: Namespace must be between 4 and 30 characters in length', + self.assertEquals('Invalid namespace a: Namespace must be between 2 and 255 characters in length', json['detail']) def test_trycreateregexmismatch(self): diff --git a/test/test_util.py b/test/test_util.py index 42724bb61..f7b6cc6f1 100644 --- a/test/test_util.py +++ b/test/test_util.py @@ -20,6 +20,8 @@ class TestUsernameValidation(unittest.TestCase): self.assertFalse(result) def test_valid(self): + self.assertValid('ja') + self.assertValid('jak') self.assertValid('jake') self.assertValid('ja_ke') self.assertValid('te-st') @@ -27,14 +29,13 @@ class TestUsernameValidation(unittest.TestCase): def test_properlength(self): self.assertValid('z' * 30) + self.assertValid('z' * 255) def test_tooshort(self): self.assertInvalid('j') - self.assertInvalid('ja') - self.assertInvalid('jk') def test_toolong(self): - self.assertInvalid('z' * 31) + self.assertInvalid('z' * 256) def test_invalids(self): self.assertInvalid('_test') @@ -158,20 +159,21 @@ class TestUsernameGenerator(unittest.TestCase): self.assert_generated_output('ja___ke', 'ja_ke') def test_trailing_underscores(self): - self.assert_generated_output('ja__', 'ja00') + self.assert_generated_output('ja__', 'ja') self.assert_generated_output('jake__', 'jake') def test_starting_underscore(self): self.assert_generated_output('_jake', 'jake') def test_short_names(self): - self.assert_generated_output('a', 'a000') - self.assert_generated_output('ab', 'ab00') - self.assert_generated_output('abc', 'abc0') + self.assert_generated_output('a', 'a0') + self.assert_generated_output('ab', 'ab') + self.assert_generated_output('abc', 'abc') def test_long_names(self): self.assert_generated_output('abcdefghijklmnopqrstuvwxyz1234567890', - 'abcdefghijklmnopqrstuvwxyz1234') + 'abcdefghijklmnopqrstuvwxyz1234567890') + self.assert_generated_output('c' * 256, 'c' * 255) def test_unicode_transliteration(self): self.assert_generated_output(u'\xc6neid', 'aeneid') @@ -184,18 +186,18 @@ class TestUsernameGenerator(unittest.TestCase): self.assert_generated_output(u'\u0985\u09ad\u09bf\u099c\u09c0\u09a4', 'abhijiit') self.assert_generated_output(u'\u0d05\u0d2d\u0d3f\u0d1c\u0d40\u0d24', 'abhijiit') self.assert_generated_output(u'\u0d2e\u0d32\u0d2f\u0d3e\u0d32\u0d2e\u0d4d', 'mlyaalm') - self.assert_generated_output(u'\ue000', '0000') - self.assert_generated_output(u'\u03ff', '0000') + self.assert_generated_output(u'\ue000', '00') + self.assert_generated_output(u'\u03ff', '00') self.assert_generated_output(u'\u0d2e\u0d32\u03ff\u03ff\u0d2e\u0d32', 'mlml') def test_multiple_suggestions(self): name_gen = generate_valid_usernames('a') generated_output = list(islice(name_gen, 4)) - self.assertEquals('a000', generated_output[0]) - self.assertEquals('a001', generated_output[1]) - self.assertEquals('a002', generated_output[2]) - self.assertEquals('a003', generated_output[3]) + self.assertEquals('a0', generated_output[0]) + self.assertEquals('a1', generated_output[1]) + self.assertEquals('a2', generated_output[2]) + self.assertEquals('a3', generated_output[3]) class TestDockerVersionParsing(unittest.TestCase): diff --git a/util/validation.py b/util/validation.py index 9be53e43d..92d766159 100644 --- a/util/validation.py +++ b/util/validation.py @@ -9,8 +9,8 @@ INVALID_PASSWORD_MESSAGE = 'Invalid password, password must be at least ' + \ '8 characters and contain no whitespace.' VALID_CHARACTERS = string.digits + string.lowercase -MIN_USERNAME_LENGTH = 4 -MAX_USERNAME_LENGTH = 30 +MIN_USERNAME_LENGTH = 2 +MAX_USERNAME_LENGTH = 255 VALID_LABEL_KEY_REGEX = r'^[a-z0-9](([a-z0-9]|[-.](?![.-]))*[a-z0-9])?$' VALID_USERNAME_REGEX = r'^([a-z0-9]+(?:[._-][a-z0-9]+)*)$' @@ -63,7 +63,7 @@ def _gen_filler_chars(num_filler_chars): def generate_valid_usernames(input_username): normalized = input_username.encode('unidecode', 'ignore').strip().lower() - prefix = re.sub(INVALID_USERNAME_CHARACTERS, '_', normalized)[:30] + prefix = re.sub(INVALID_USERNAME_CHARACTERS, '_', normalized)[:MAX_USERNAME_LENGTH] prefix = re.sub(r'_{2,}', '_', prefix) if prefix.endswith('_'):