if(!dojo._hasResource["dojox.form.PasswordValidator"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. dojo._hasResource["dojox.form.PasswordValidator"] = true; dojo.provide("dojox.form.PasswordValidator"); dojo.require("dijit.form._FormWidget"); dojo.require("dijit.form.ValidationTextBox"); dojo.requireLocalization("dojox.form", "PasswordValidator", null, "ROOT"); dojo.declare("dojox.form._ChildTextBox", dijit.form.ValidationTextBox, { // summary: // A class that is shared between all our children - extends // ValidationTextBox and provides some shared functionality // // containerWidget: widget // Our parent (the PasswordValidator) containerWidget: null, // type: string // Don't override this - we are all "password" types type: "password", reset: function(){ // summary: // Force-set to empty string (we don't save passwords EVER)...and // since _OldPWBox overrides setValue to check for empty string, // call our parent class directly (not this.inherited()) dijit.form.ValidationTextBox.prototype.setValue.call(this, "", true); this._hasBeenBlurred = false; } }); dojo.declare("dojox.form._OldPWBox", dojox.form._ChildTextBox, { // summary: // A class representing our "old password" box. // // _isPWValid: boolean // Whether or not the password is valid _isPWValid: false, setValue: function(/* anything */ newVal, /* boolean? */ priority){ // summary: // Updates _isPWValid if this isn't our initial update by calling // our PasswordValidator's pwCheck function if(newVal === ""){ newVal = dojox.form._OldPWBox.superclass.getValue.call(this); } if(priority !== null){ // Priority is passed in as null, explicitly when this is an // update (not initially set). We want to check our password now. this._isPWValid = this.containerWidget.pwCheck(newVal); } this.inherited("setValue", arguments); }, isValid: function(/* boolean */ isFocused){ // Take into account the isPWValid setting return this.inherited("isValid", arguments) && this._isPWValid; }, _update: function(/* event */ e){ // Only call validate() if we've been blurred or else we get popups // too early. if(this._hasBeenBlurred){ this.validate(true); } this._onMouse(e); }, getValue: function(){ // summary: // Only returns a value if our container widget is valid. This // is to prevent exposure of "oldPW" too early. if(this.containerWidget.isValid()){ return this.inherited("getValue", arguments); }else{ return ""; } } }); dojo.declare("dojox.form._NewPWBox", dojox.form._ChildTextBox, { // summary: // A class representing our new password textbox // required: boolean // Whether or not this widget is required (default: true) required: true, onChange: function(){ // summary: // Validates our verify box - to make sure that a change to me is // reflected there this.containerWidget._inputWidgets[2].validate(false); this.inherited(arguments); } }); dojo.declare("dojox.form._VerifyPWBox", dojox.form._ChildTextBox, { // summary: // A class representing our verify textbox isValid: function(isFocused){ // summary: // Validates that we match the "real" password return this.inherited("isValid", arguments) && (this.getValue() == this.containerWidget._inputWidgets[1].getValue()); } }); dojo.declare("dojox.form.PasswordValidator", dijit.form._FormValueWidget, { // summary: // A password validation widget that simplifies the "old/new/verify" // style of requesting passwords. You will probably want to override // this class and implement your own pwCheck function. // // required: boolean // Whether or not it is required for form submission required: true, // inputWidgets: TextBox[] // An array of text boxes that are our components _inputWidgets: null, // oldName: string? // The name to send our old password as (when form is posted) oldName: "", templateString:"
\n\t\n
\n", _hasBeenBlurred: false, isValid: function(/* boolean */ isFocused){ // summary: we are valid if ALL our children are valid return dojo.every(this._inputWidgets, function(i){ if(i && i._setStateClass){ i._setStateClass(); } return (!i || i.isValid()); }); }, validate: function(/* boolean */ isFocused){ // summary: Validating this widget validates all our children return dojo.every(dojo.map(this._inputWidgets, function(i){ if(i && i.validate){ i._hasBeenBlurred = (i._hasBeenBlurred || this._hasBeenBlurred); return i.validate(); } return true; }, this), "return item;"); }, reset: function(){ // summary: Resetting this widget resets all our children this._hasBeenBlurred = false; dojo.forEach(this._inputWidgets, function(i){ if(i && i.reset){ i.reset(); } }, this); }, _createSubWidgets: function(){ // summary: // Turns the inputs inside this widget into "real" validation // widgets - and sets up the needed connections. var widgets = this._inputWidgets, msg = dojo.i18n.getLocalization("dojox.form", "PasswordValidator", this.lang); dojo.forEach(widgets, function(i, idx){ if(i){ var p = {containerWidget: this}, c; if(idx === 0){ p.name = this.oldName; p.invalidMessage = msg.badPasswordMessage; c = dojox.form._OldPWBox; }else if(idx === 1){ p.required = this.required; c = dojox.form._NewPWBox; }else if(idx === 2){ p.invalidMessage = msg.nomatchMessage; c = dojox.form._VerifyPWBox; } widgets[idx] = new c(p, i); } }, this); }, pwCheck: function(/* string */ password){ // summary: // Overridable function for validation of the old password box. // // This function is called and passed the old password. Return // true if it's OK to continue, and false if it is not. // // IMPORTANT SECURITY NOTE: Do NOT EVER EVER EVER check this in // HTML or JavaScript!!! // // You will probably want to override this function to callback // to a server to verify the password (the callback will need to // be syncronous) - and it's probably a good idea to validate // it again on form submission before actually doing // anything destructive - that's why the "oldName" value // is available. // // And don't just fetch the password from the server // either :) Send the test password (probably hashed, for // security) and return from the server a status instead. // // Again - DON'T BE INSECURE!!! Security is left as an exercise // for the reader :) return false; }, postCreate: function(){ // summary: // Sets up the correct widgets. You *MUST* specify one child // text box (a simple HTML element) with pwType="new" // *and* one child text box with pwType="verify". You *MAY* // specify a third child text box with pwType="old" in order to // prompt the user to enter in their old password before the // widget returns that it is valid. this.inherited(arguments); // Turn my inputs into the correct stuff.... var widgets = this._inputWidgets = []; dojo.forEach(["old","new","verify"], function(i){ widgets.push(dojo.query("input[pwType=" + i + "]", this.containerNode)[0]); }, this); if (!widgets[1] || !widgets[2]){ throw new Error("Need at least pwType=\"new\" and pwType=\"verify\""); } if (this.oldName && !widgets[0]){ throw new Error("Need to specify pwType=\"old\" if using oldName"); } this._createSubWidgets(); }, setAttribute: function(/* string */ attr, /* anything */ value){ this.inherited(arguments); // Disabling (or enabling) the container disables (or enables) all // the subwidgets as well - same for requiring switch(attr){ case "disabled": case "required": dojo.forEach(this._inputWidgets, function(i){ if(i && i.setAttribute){ i.setAttribute(attr, value);} }); break; default: break; } }, getValue: function(){ // summary: overridden to return an empty string if we aren't valid. if (this.isValid()){ return this._inputWidgets[1].getValue(); }else{ return ""; } }, focus: function(){ // summary: // places focus on the first invalid input widget - if all // input widgets are valid, the first widget is focused. var f = false; dojo.forEach(this._inputWidgets, function(i){ if(i && !i.isValid() && !f){ i.focus(); f = true; } }); if(!f){ this._inputWidgets[1].focus(); } } }); }