/*
* Copyright 2012 Anyware Services
*
* 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.
*/
/**
* Field that displays allows to change a password by double entering it
*/
Ext.define('Ametys.form.field.ChangePassword', {
extend:'Ametys.form.field.Password',
alias: ['widget.changepasswordfield', 'widget.changepassword'],
alternateClassName: ['Ext.form.ChangePasswordField', 'Ext.form.ChangePassword', 'Ext.form.field.ChangePassword'],
/**
* @cfg {Object} confirmConfig The configuration object for the second text field. Note that many configuration can be set directly here and will we broadcasted to underlying field (allowBlank...). Default to {@link #passwordConfig}.
*/
baseCls: ['ametys-changepassword', Ext.baseCSSPrefix + 'container'],
/**
* @cfg {String} modificationBodyCls CSS class used when on mode 0 or 1. Default value is 'ametys-changepassword-body' that display a little connector between the two fields.
*/
// modificationBodyCls: 'ametys-changepassword-body',
// FIXME css rule is defined but modificationBodyCls is not used.
layout: {
type: 'hbox'
},
/**
* @cfg {Boolean} useStrongPassword True to force strong password with minimal requirements
*/
/**
* @cfg {Number} useMinLength Number highter than 0 to force min length for password. Used if #cfg-useStrongPassword is true
*/
/**
* @private
* @property {String} _useMinLengthText The error text to display if #cfg-useMinLengths is higher than 0 and the test fails during validation
*/
/**
* @cfg {String} [specialCharacters='!%&@#$^*?_~'] Special character separated by coma. Used if #cfg-useStrongPassword is true and #cfg-minSpecials is higher than 0
*/
/**
* @cfg {String|Number} minSpecials minimum number of special caracters for password. Used if #cfg-useStrongPassword is true
*/
/**
* @private
* @property {RegExp} _minSpecialsRegex A RegExp object to test password validation on special caracters. Used if #cfg-useStrongPassword is true and #cfg-minSpecials is higher than 0
*/
/**
* @private
* @property {String} _minSpecialsRegexText The error text to display if #cfg-minSpecials is higher than 0 and the test fails during validation
*/
/**
* @cfg {String|Number} minNumbers minimum number of numeric caracters for password. Used if #cfg-useStrongPassword is true
*/
/**
* @private
* @property {RegExp} _minNumbersRegex A RegExp object to test password validation on numeric caracters. Used if #cfg-useStrongPassword is true and #cfg-minNumbers is higher than 0
*/
/**
* @private
* @property {String} _minNumbersRegexText The error text to display if #cfg-minNumbers is higher than 0 and the test fails during validation
*/
/**
* @cfg {String|Number} minLowercase minimum number of lower case caracters for password. Used if #cfg-useStrongPassword is true
*/
/**
* @private
* @property {RegExp} _minLowercaseRegex A RegExp object to test password validation on lowercase caracters. Used if #cfg-useStrongPassword is true and #cfg-minLowercase is higher than 0.
*/
/**
* @private
* @property {String} _minLowercaseRegexText The error text to display if #cfg-minLowercase is higher than 0 and the test fails during validation
*/
/**
* @cfg {String|Number} minUppercase minimum number of upper case caracters for password. Used if #cfg-useStrongPassword is true
*/
/**
* @private
* @property {RegExp} _minUppercaseRegex A RegExp object to test password validation on uppercase caracters. Used if #cfg-useStrongPassword is true and #cfg-minUppercase is higher than 0.
*/
/**
* @private
* @property {String} _minUppercaseRegexText The error text to display #cfg-minUppercase is higher than 0 and the test fails during validation
*/
initComponent: function()
{
this.callParent(arguments);
this.useStrongPassword = Ext.isBoolean(this.useStrongPassword) ? this.useStrongPassword : this.useStrongPassword == 'true';
this.useMinLength = this.useMinLength ? Number(this.useMinLength) : 0;
this._useMinLengthText = Ext.String.format("{{i18n PLUGINS_CORE_UI_CHANGEPASSWORD_USE_MIN_LENGTH_FOR_JS}}", this.useMinLength);
this.minLowercase = this.minLowercase ? Number(this.minLowercase) : 0;
if (this.minLowercase > 0)
{
this._minLowercaseRegex = new RegExp('^(.*[a-z].*){' + this.minLowercase + ',}$');
this._minLowercaseRegexText = this.minLowercase == 1 ? "{{i18n PLUGINS_CORE_UI_CHANGEPASSWORD_USE_LOWERCASE}}" : Ext.String.format("{{i18n PLUGINS_CORE_UI_CHANGEPASSWORD_USE_LOWERCASES_FOR_JS}}", this.minLowercase);
}
this.minUppercase = this.minUppercase ? Number(this.minUppercase) : 0;
if (this.minUppercase > 0)
{
this._minUppercaseRegex = new RegExp('^(.*[A-Z].*){' + this.minUppercase + ',}$');
this._minUppercaseRegexText = this.minUppercase == 1 ? "{{i18n PLUGINS_CORE_UI_CHANGEPASSWORD_USE_UPPERCASE}}" : Ext.String.format("{{i18n PLUGINS_CORE_UI_CHANGEPASSWORD_USE_UPPERCASES_FOR_JS}}", this.minUppercase);
}
this.minNumbers = this.minNumbers ? Number(this.minNumbers) : 0;
if (this.minNumbers > 0)
{
this._minNumbersRegex = new RegExp('^(.*[0-9].*){' + this.minNumbers + ',}$');
this._minNumbersRegexText = this.minNumbers == 1 ? "{{i18n PLUGINS_CORE_UI_CHANGEPASSWORD_USE_NUMBER}}" : Ext.String.format("{{i18n PLUGINS_CORE_UI_CHANGEPASSWORD_USE_NUMBERS_FOR_JS}}", this.minNumbers);
}
this.specialCharacters = this.specialCharacters || '!%&@#$^*?_~';
this.minSpecials = this.minSpecials ? Number(this.minSpecials) : 0;
if (this.minSpecials > 0)
{
var regexpSpecialChars = /([\[\]\^\$\|\(\)\\\+\*\?\{\}\=\!])/gi;
var quotedSpecialCharacters = this.specialCharacters.replace(regexpSpecialChars, '\\$1');
this._minSpecialsRegex = new RegExp('^(.*[' + quotedSpecialCharacters + '].*){' + this.minSpecials + ',}$');
this._minSpecialsRegexText = this.minSpecials == 1 ? Ext.String.format("{{i18n PLUGINS_CORE_UI_CHANGEPASSWORD_USE_SPECIAL_FOR_JS}}", this.specialCharacters) : Ext.String.format("{{i18n PLUGINS_CORE_UI_CHANGEPASSWORD_USE_SPECIALS_FOR_JS}}", this.minSpecials, this.specialCharacters);
}
},
/**
* @protected
* Initialize the password field. This function in called from {@link #initComponent}
*/
_initPasswordField: function()
{
// Password
this.passwordConfig = this.passwordConfig || {};
this.passwordConfig.cls = 'ametys-changepassword-initial';
this.callParent();
// Password confirm
var confirmConfig = this.confirmConfig || this.passwordConfig || {};
confirmConfig.inputType = 'password';
confirmConfig.cls = 'ametys-changepassword-confirmation';
confirmConfig.flex = 1;
var propertiesToCopy = this._getConfigPropertiesToCopy();
this._copyPropIfDefined(confirmConfig, propertiesToCopy, this.initialConfig);
this._confirmField = Ext.create('Ext.form.field.Text', confirmConfig);
},
/**
* @protected
* Returns the items of the component. This function in called from {@link #initComponent}
*/
_getItems: function()
{
return [
{
xtype: 'container',
flex: 1,
layout: {
type: 'vbox',
align: 'stretch'
},
items: [
this._field,
this._confirmField
]
},
this._button
];
},
getErrors: function (value)
{
var errors = [];
if (this._mode != Ametys.form.field.Password.MODE_SEEPASSWORD)
{
if (value === undefined || this._field.getValue() != this._confirmField.getValue())
{
errors.push("{{i18n PLUGINS_CORE_UI_CHANGEPASSWORD_VALIDATOR}}");
}
errors = Ext.Array.merge(errors, this._getStrongPasswordErrors(value));
errors = Ext.Array.merge(errors, this._confirmField.getErrors(value));
}
return Ext.Array.merge(this.callParent(arguments), errors);
},
_getStrongPasswordErrors: function(value)
{
var errors = [];
if (this.useStrongPassword && value !== undefined)
{
if (this.useMinLength > 0 && value.length < this.useMinLength)
{
errors.push(this._useMinLengthText);
}
if (this.minLowercase > 0 && !value.match(this._minLowercaseRegex))
{
errors.push(this._minLowercaseRegexText);
}
if (this.minUppercase > 0 && !value.match(this._minUppercaseRegex))
{
errors.push(this._minUppercaseRegexText);
}
if (this.minNumbers > 0 && !value.match(this._minNumbersRegex))
{
errors.push(this._minNumbersRegexText);
}
if (this.minSpecials > 0 && !value.match(this._minSpecialsRegex))
{
errors.push(this._minSpecialsRegexText);
}
}
return errors;
},
getValue: function()
{
var value = this._field.getValue();
if (this._mode == Ametys.form.field.ChangePassword.MODE_SEEPASSWORD)
{
return null;
}
else if (value == this._confirmField.getValue())
{
return value;
}
else
{
return undefined;
}
},
_onFieldSetValue: function(value)
{
this._confirmField.setValue(value);
},
/**
* @protected
* Internal hook on field set disabled to add specific process in inherited classes
* @param {Boolean} disabled True is disabled
*/
_onFieldSetDisabled: function(disabled)
{
this._confirmField.setDisabled(disabled);
}
});