/* Copyright (c) 2012, Accounting enhancements, Inc and Lee Lofgren. Available via Academic Free License >= 2.1 OR the modified BSD license. see: http://dojotoolkit.org/license for details */ /* * Simple login dialog: A Username and Password popup dialog * Detect whether user is logged in at startup * Detect whether user is logged in at regular intervals (loggedInTestInterval = default 30000) * If user is not logged in, then automatically pop up this dialog. * Keep the last communication with session.php in this.session. This way, if you have session.php return other things such as session.fullName, you can retrieve it and show it on your screen. * this.onChange(isLoggedIn) is fired whenever the status changes. If true then you are logged in else you are logged out. * You can listen to this.onChange(isLoggedIn) and use it to blank the background screen when the user is logged out, or use it to update a displayed user name. * this.value == true if you are logged in. * This class blanks out the this.usr.attr("value") and this.password.attr("value") after a successful login as a security measure so don't bother to use these for anything once the dialog disappears * Backend - session.php * Backend must support session.php * session.php must respond to an empty query with session="valid" or session= * session.php should use a cookie to detect whether the login is still valid (And should update the cookie when user logs in) * session.php?user=&password= should return either session="valid" or msg= * If session!="valid" then msg will be displayed in red above the Username field. * session.php can return other information such as fullName. If it does, the user can use this.session.fullName or whatever else was returned to display login information on the screen * If you do use session.php to return other information. It should be returned whether session.php is called with or without arguments since this.session is updated everytime it talks to the backend. * Obvious Recommendations: * All other backend scripts should also call session.php (Or it's parent class) to test for valid logins. * The aforementioned cookie should contain a [random non-sequential] session id, not the username/password */ if (typeof accountingenhancements == "undefined" || !accountingenhancements._hasResource["accountingenhancements.loginSimple.LoginSimple"]){ dojo.provide("accountingenhancements.loginSimple.LoginSimple"); dojo.require("accountingenhancements.accountingenhancements"); dojo.require("dijit._Widget"); dojo.require("dijit._Templated"); dojo.require("dijit._Container"); dojo.require("dijit.layout.ContentPane"); dojo.require("dijit.form.Button"); dojo.require("dijit.form.TextBox"); dojo.require("dijit.Dialog"); dojo.require("dojox.timing"); dojo.declare("accountingenhancements.loginSimple.LoginSimple", dijit.Dialog, { // summary: // A login dialog that asks for a user name and password // description: // detect when user is and is not logged in. // If the user is not logged in, then pop up a dialog asking user to log in // This frontend relies on session.php on the server. See text at start of file for session.php behavior // Password not encrypted so https should be used to protect the user name and password // test: Associative Array test.user, test.password, test.expireTime // If set then test against test.user and test.password instead of calling backend // login expires after around test.expireTime milliseconds. It is timed against loggedInTestInterval since that is the routine that is causing the countdown test: null, // loggedInTimer: Object // Timer object that is used to periodically test that user is still logged in loggedInTimer: null, // loggedInTestInterval: Integer // Default interval for testing that user is still logged in. loggedInTestInterval: 30000, //test every 30 seconds // templateString: String // template of login popup dialog // Used by _Widget to attach html snippet templateString: dojo.cache('accountingenhancements','loginSimple/resources/LoginSimple.html'), // widgetsInTemplate: Boolean // Inform _Widget that the template contains widgets widgetsInTemplate: true, // value: Boolean // True if user is currently logged in. value: false, // displayNode: Node // Node to which this widget is attached displayNode: null, // session: Associative Array // session.msg = "success" or an eror message // session.session="valid" or anything else including null // anything else you write session.php to return, such as username, or fullName will also be here. It is updated from both testIsLoggedIn and login_onClick session: null, // usr: Widget // Assigned from within LoginSimple.html // password: Widget // Assigned from within LoginSimple.html // loginButton: Widget // Assigned from within LoginSimple.html // onClick event tied to login_onClick from within LoginSimple.html // message:
// Used to display error messages. use this.message.innerHTML onChange: function(value){ // summary: // Set this handler to be notified of changes to value. // tags: // callback // arguments: // value: boolean // true if logged in else false }, postMixInProperties: function(){ this.inherited(arguments); }, startup: function(){ // summary: Piggyback on dijit.Dialog's _setup for load-time options this.session = new Object(); this.session.msg=""; this.session.session=null; this.inherited(arguments); if (this.loggedInTimer==null && this.loggedInTestInterval>0){ this.loggedInTimer = new dojox.timing.Timer(this.loggedInTestInterval);//test whether we are still logged in at a regular interval this.loggedInTimer.onTick = dojo.hitch(this,this.testIsLoggedIn); this.loggedInTimer.start(); this.testIsLoggedIn(); if (this.value==false)this.onChange(this.value); //Fire this the first time we test if we are not logged in since this.value is already false and not being logged in would have detected no change. } }, testIsLoggedIn: function(){ if (this.open==false){ if (this.test!=null){ var session = new Object(); session.session="invalid"; this.test.time += this.loggedInTestInterval; if (this.value==true && this.test.time0 && password && password.length>0 ){ if (this.test!=null){ var session = new Object(); session.msg="Incorrect username or password"; session.session="Invalid"; if (usr==this.test.user && password==this.test.password){session.session="valid";session.msg="";this.test.time=0;} this._load(session); } else { var xhrArgs = { url: "session.php", handleAs: "json", content: {"usr": usr, "password": password}, load: dojo.hitch(this,this._load) } var deferred = dojo.xhrPost(xhrArgs); } } }, _load: function(data){ this.session = data; if (data['session']=="valid"){ this.hide(); if (this.value==false){this.value=true;this.onChange(this.value);} } else { this.message.innerHTML=data['msg']; this.usr.focus(); if (this.value==true){this.value=false;this.onChange(this.value);} } }, show: function(){ if (this.open)return; this.inherited(arguments); this.message.innerHTML=""; this.usr.attr('value',""); this.password.attr('value',""); this.logout(); }, hide: function(){ this.inherited(arguments); this.usr.attr("value",""); //Don't save these things. That way someone inspecting this object in a browser with an active or timed-out session can't retrieve this information. this.password.attr("value",""); }, _onKey: function(/*Event*/ evt){ // summary: Cancel escape key if (evt.charOrCode){ if (evt.charOrCode == dojo.keys.ESCAPE){ this.message.innerHTML=""; this.usr.attr('value',""); this.password.attr('value',""); this.usr.focus(); } else { if (evt.charOrCode==dojo.keys.ENTER){ if (evt.target.id==this.id+"_usr"){ this.password.focus(); } else { this.login_onClick(); } } else { this.inherited(arguments); } } } }, logout: function(){ this.session = new Object(); this.session.msg=""; this.session.session=null; if (this.test != null){ if (this.value==true){this.value=false;this.onChange(this.value);} } else { var xhrArgs = { url: "session.php", handleAs: "json", content: {"Logout": "Logout"}, load: dojo.hitch(this,function(){ if (this.open==false){ this.show(); } if (this.value==true){this.value=false;this.onChange(this.value);} this.usr.focus(); }) } var deferred = dojo.xhrPost(xhrArgs); } } }); }