diff --git a/c2corg_api/tests/views/test_user.py b/c2corg_api/tests/views/test_user.py index 8f8811808..77d4861d4 100644 --- a/c2corg_api/tests/views/test_user.py +++ b/c2corg_api/tests/views/test_user.py @@ -196,6 +196,35 @@ def test_register_forum_username_unique(self, _send_email): self.assertEqual(json['errors'][0]['description'], 'already used forum_username') + @patch('c2corg_api.emails.email_service.EmailService._send_email') + def test_register_stripped_username(self, _send_email): + request_body = { + 'username': ' contributor ', + 'forum_username': 'Foo', + 'name': 'Max Mustermann', + 'password': 'super secret', + 'email': 'some_user@camptocamp.org' + } + url = self._prefix + '/register' + json = self.app_post_json(url, request_body, status=400).json + self.assertEqual(json['errors'][0]['description'], + 'This username already exists') + + request_body = { + 'username': ' username with spaces ', + 'forum_username': 'Spaceman', + 'name': 'Max Mustermann', + 'password': 'super secret', + 'email': 'space@camptocamp.org' + } + url = self._prefix + '/register' + body = self.app_post_json(url, request_body, status=200).json + self.assertBodyEqual(body, 'username', 'username with spaces') + user_id = body.get('id') + user = self.session.query(User).get(user_id) + self.assertIsNotNone(user) + self.assertEqual(user.username, 'username with spaces') + @patch('c2corg_api.emails.email_service.EmailService._send_email') def test_register_username_email_not_equals_email(self, _send_email): request_body = { diff --git a/c2corg_api/views/user.py b/c2corg_api/views/user.py index 3f569fe66..9f5c9c303 100644 --- a/c2corg_api/views/user.py +++ b/c2corg_api/views/user.py @@ -123,21 +123,36 @@ def validate_forum_username(request, **kwargs): def validate_username(request, **kwargs): + """Checks username is set, strips leading/trailing whitespaces, + checks unicity and if an email, that it matches the provided email. """ - Check that the username is not an email, - or that it is the same as the actual email. - """ - if 'username' in request.json and 'email' in request.json: - value = request.json['username'] + + if 'username' not in request.json: + request.errors.add('body', 'username', 'Required') + return + + username = request.json['username'].strip() + if not username: + request.errors.add('body', 'username', + 'Username cannot be empty or whitespaces') + return + + if not is_unused_user_attribute('username', username, lowercase=True): + request.errors.add('body', 'username', 'This username already exists') + + # Check that the username is not an email, + # or that it is the same as the actual email. + if 'email' in request.json: email = request.json['email'] - if (is_valid_email(value) and email != value): + if (is_valid_email(username) and email != username): request.errors.add( 'body', 'username', 'An email address used as username should be the same as the' + ' one used as the account email address.') return - request.validated['username'] = value + + request.validated['username'] = username def validate_captcha(request, **kwargs): @@ -189,7 +204,6 @@ def __init__(self, request): colander_body_validator, validate_json_password, partial(validate_unique_attribute, "email"), - partial(validate_unique_attribute, "username"), partial(validate_unique_attribute, "forum_username", lowercase=True),