
There are cases where leading/trailing spaces are included in passwords We should not touch passwords input in forms and pass them to auth backends without any modifications. The detail was discussed in the mailing list thread [1] referred in the bug comment. [1] http://lists.openstack.org/pipermail/openstack-discuss/2020-January/thread.html#12223 Change-Id: I98de224cc77a98fa216ec3bc032412325e661e14 Closes-Bug: #1861224
82 lines
3.3 KiB
Python
82 lines
3.3 KiB
Python
# Copyright 2013 Centrin Data Systems Ltd.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
|
|
from django.conf import settings
|
|
from django.forms import ValidationError
|
|
from django import http
|
|
from django.utils.translation import ugettext_lazy as _
|
|
from django.views.decorators.debug import sensitive_variables
|
|
|
|
from horizon import exceptions
|
|
from horizon import forms
|
|
from horizon import messages
|
|
from horizon.utils import functions as utils
|
|
from horizon.utils import validators
|
|
|
|
from openstack_dashboard import api
|
|
|
|
|
|
class PasswordForm(forms.SelfHandlingForm):
|
|
current_password = forms.CharField(
|
|
label=_("Current password"),
|
|
strip=False,
|
|
widget=forms.PasswordInput(render_value=False))
|
|
new_password = forms.RegexField(
|
|
label=_("New password"),
|
|
strip=False,
|
|
widget=forms.PasswordInput(render_value=False),
|
|
regex=validators.password_validator(),
|
|
error_messages={'invalid':
|
|
validators.password_validator_msg()})
|
|
confirm_password = forms.CharField(
|
|
label=_("Confirm new password"),
|
|
strip=False,
|
|
widget=forms.PasswordInput(render_value=False))
|
|
no_autocomplete = True
|
|
|
|
def clean(self):
|
|
'''Check to make sure password fields match.'''
|
|
data = super(PasswordForm, self).clean()
|
|
if 'new_password' in data:
|
|
if data['new_password'] != data.get('confirm_password', None):
|
|
raise ValidationError(_('Passwords do not match.'))
|
|
if data.get('confirm_password', None) == \
|
|
data.get('current_password', None):
|
|
raise ValidationError(_('Old password and new password '
|
|
'must be different'))
|
|
return data
|
|
|
|
# We have to protect the entire "data" dict because it contains the
|
|
# oldpassword and newpassword strings.
|
|
@sensitive_variables('data')
|
|
def handle(self, request, data):
|
|
user_is_editable = api.keystone.keystone_can_edit_user()
|
|
|
|
if user_is_editable:
|
|
try:
|
|
api.keystone.user_update_own_password(request,
|
|
data['current_password'],
|
|
data['new_password'])
|
|
response = http.HttpResponseRedirect(settings.LOGOUT_URL)
|
|
msg = _("Password changed. Please log in again to continue.")
|
|
utils.add_logout_reason(request, response, msg)
|
|
return response
|
|
except Exception as ex:
|
|
exceptions.handle(request,
|
|
_('Unable to change password: %s') % ex)
|
|
return False
|
|
else:
|
|
messages.error(request, _('Changing password is not supported.'))
|
|
return False
|