Skip to content

Commit

Permalink
Removed max_length from username/password fields in login page
Browse files Browse the repository at this point in the history
Fixes bug 959179

The field validation on the login page may lead
to security issues - it should accept any input,
without validation. Not to tell hackers what range to probe..
The validation should be only on create/update User page.

Updates the translation files for the new strings.

Change-Id: Ib3bc72a024fe3e39e06bf948c6aaca8f2b1e60ee
  • Loading branch information
ttrifonov authored and gabrielhurley committed Mar 25, 2012
1 parent 7d3a0f4 commit a7db3bc
Show file tree
Hide file tree
Showing 19 changed files with 609 additions and 449 deletions.
17 changes: 11 additions & 6 deletions horizon/dashboards/syspanel/users/forms.py
Expand Up @@ -22,7 +22,7 @@

from django import shortcuts
from django.contrib import messages
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import force_unicode, ugettext_lazy as _
from django.forms import ValidationError

from horizon import api
Expand Down Expand Up @@ -60,7 +60,7 @@ def clean(self):


class CreateUserForm(BaseUserForm):
name = forms.CharField(label=_("Name"))
name = forms.CharField(label=_("User Name"))
email = forms.EmailField(label=_("Email"))
password = forms.RegexField(
label=_("Password"),
Expand Down Expand Up @@ -105,12 +105,15 @@ class UpdateUserForm(BaseUserForm):
id = forms.CharField(label=_("ID"), widget=forms.HiddenInput)
name = forms.CharField(label=_("User Name"))
email = forms.EmailField(label=_("Email"))
password = forms.CharField(label=_("Password"),
widget=forms.PasswordInput(render_value=False),
required=False)
password = forms.RegexField(label=_("Password"),
widget=forms.PasswordInput(render_value=False),
regex=validators.password_validator(),
required=False,
error_messages={'invalid': validators.password_validator_msg()})
confirm_password = forms.CharField(
label=_("Confirm Password"),
widget=forms.PasswordInput(render_value=False))
widget=forms.PasswordInput(render_value=False),
required=False)
tenant_id = forms.ChoiceField(label=_("Primary Project"))

def handle(self, request, data):
Expand Down Expand Up @@ -151,11 +154,13 @@ def handle(self, request, data):
exceptions.handle(request, ignore=True)

if succeeded:
succeeded = map(force_unicode, succeeded)
messages.success(request,
_('Updated %(attributes)s for "%(user)s".')
% {"user": data["name"],
"attributes": ", ".join(succeeded)})
if failed:
failed = map(force_unicode, failed)
messages.error(request,
_('Unable to update %(attributes)s for "%(user)s".')
% {"user": data["name"],
Expand Down
81 changes: 76 additions & 5 deletions horizon/dashboards/syspanel/users/tests.py
Expand Up @@ -18,16 +18,18 @@
# License for the specific language governing permissions and limitations
# under the License.

from django import http
from django.core.urlresolvers import reverse
from keystoneclient import exceptions as keystone_exceptions
from mox import IgnoreArg
from mox import IgnoreArg, IsA

from horizon import api
from horizon import test


USERS_INDEX_URL = reverse('horizon:syspanel:users:index')
USER_CREATE_URL = reverse('horizon:syspanel:users:create')
USER_UPDATE_URL = reverse('horizon:syspanel:users:update', args=[1])


class UsersViewTests(test.BaseAdminViewTests):
Expand Down Expand Up @@ -84,23 +86,92 @@ def test_create_user_password_mismatch(self):
res = self.client.post(USER_CREATE_URL, formData)
self.assertFormError(res, "form", None, ['Passwords do not match.'])

def test_user_password_validation(self):
def test_create_user_field_validation(self):
user = self.users.get(id="1")
self.mox.StubOutWithMock(api, 'tenant_list')
api.tenant_list(IgnoreArg(), admin=True).AndReturn(self.tenants.list())
api.tenant_list(IgnoreArg(), admin=True).AndReturn(self.tenants.list())
self.mox.ReplayAll()

# check password min-len verification
formData = {'method': 'CreateUserForm',
'name': user.name,
'email': user.email,
'password': 'four',
'tenant_id': self.tenant.id,
'confirm_password': "four"}
'confirm_password': 'four'}

res = self.client.post(USER_CREATE_URL, formData)
self.assertFormError(
res, "form", 'password',
['Password must be between 8 and 18 characters.'])

# check password max-len verification
formData['password'] = 'MoreThanEighteenChars'
formData['confirm_password'] = 'MoreThanEighteenChars'

res = self.client.post(USER_CREATE_URL, formData)
self.assertFormError(
res, "form", 'password',
['Your password must be at least 6 characters long.'])
res, "form", 'password',
['Password must be between 8 and 18 characters.'])

def test_update_user_field_validation(self):
user = self.users.get(id="1")
self.mox.StubOutWithMock(api, 'tenant_list')
self.mox.StubOutWithMock(api, 'user_get')
self.mox.StubOutWithMock(api.keystone, 'user_update')
self.mox.StubOutWithMock(api, 'user_update_tenant')
self.mox.StubOutWithMock(api, 'user_update_password')

api.keystone.user_update(IsA(http.HttpRequest),
user.id,
confirm_password=u'normalpwd',
email=u'test@example.com',
name=u'test_user').AndReturn(None)
api.user_update_tenant(IsA(http.HttpRequest),
user.id,
self.tenant.id).AndReturn(None)
api.user_update_password(IsA(http.HttpRequest),
user.id,
IgnoreArg()).AndReturn(None)
api.user_get(IsA(http.HttpRequest), '1', admin=True).AndReturn(user)
api.tenant_list(IgnoreArg(), admin=True).AndReturn(self.tenants.list())
api.user_get(IsA(http.HttpRequest), '1', admin=True).AndReturn(user)
api.tenant_list(IgnoreArg(), admin=True).AndReturn(self.tenants.list())
api.user_get(IsA(http.HttpRequest), '1', admin=True).AndReturn(user)
api.tenant_list(IgnoreArg(), admin=True).AndReturn(self.tenants.list())
self.mox.ReplayAll()
user.tenantId = 1

formData = {'method': 'UpdateUserForm',
'id': 1,
'name': user.name,
'email': user.email,
'password': 'normalpwd',
'tenant_id': self.tenant.id,
'confirm_password': 'normalpwd'}

# check successful update
res = self.client.post(USER_UPDATE_URL, formData)
self.assertNoFormErrors(res)

# check password min-len verification
formData['password'] = 'four'
formData['confirm_password'] = 'four'

res = self.client.post(USER_UPDATE_URL, formData)
self.assertFormError(
res, "form", 'password',
['Password must be between 8 and 18 characters.'])

# check password max-len verification
formData['password'] = 'MoreThanEighteenChars'
formData['confirm_password'] = 'MoreThanEighteenChars'

res = self.client.post(USER_UPDATE_URL, formData)
self.assertFormError(
res, "form", 'password',
['Password must be between 8 and 18 characters.'])

def test_enable_user(self):
user = self.users.get(id="2")
Expand Down

0 comments on commit a7db3bc

Please sign in to comment.