diff -r adfbe522c95f -r 05fe0039d952 includes/clientside/static/login.js --- a/includes/clientside/static/login.js Sun Oct 25 00:09:11 2009 -0400 +++ b/includes/clientside/static/login.js Tue Nov 03 22:08:48 2009 -0500 @@ -115,13 +115,14 @@ var title = ( user_level > USER_LEVEL_MEMBER ) ? $lang.get('user_login_ajax_prompt_title_elev') : $lang.get('user_login_ajax_prompt_title'); logindata.mb_object = new MessageBox(MB_OKCANCEL | MB_ICONLOCK, title, ''); + // + // Cancel function: called when the "Cancel" button is clicked + // logindata.mb_object.onclick['Cancel'] = function() { - // Hide the error message and captcha - if ( document.getElementById('ajax_login_error_box') ) - { - document.getElementById('ajax_login_error_box').parentNode.removeChild(document.getElementById('ajax_login_error_box')); - } + // Hide the error message, if any + $('ajax_login_error_box').remove(); + // Hide the captcha, if any if ( document.getElementById('autoCaptcha') ) { var to = fly_out_top(document.getElementById('autoCaptcha'), false, true); @@ -130,7 +131,7 @@ d.parentNode.removeChild(d); }, to); } - // Ask the server to clean our key + // Ask the server to delete the encryption key we're using ajaxLoginPerformRequest({ mode: 'clean_key', key_aes: logindata.key_aes, @@ -138,8 +139,10 @@ }); }; + // Clicking OK will not cause the box to destroy, as this function returns true. logindata.mb_object.onbeforeclick['OK'] = function() { + // Just call the submitter and let it take care of everything ajaxLoginSubmitForm(); return true; } @@ -160,7 +163,8 @@ } /** - * For compatibility only. + * For compatibility only. Really, folks, it's ajaxLoginInit. If you need a + * mnemonic device, use "two 'in's." */ window.ajaxLogonInit = function(call_on_finish, user_level) @@ -170,7 +174,7 @@ /** * Sets the contents of the AJAX login window to the appropriate status message. - * @param int One of AJAX_STATUS_* + * @param int One of AJAX_STATUS_* constants */ window.ajaxLoginSetStatus = function(status) @@ -365,7 +369,7 @@ case null: case undefined: logindata.showing_status = false; - return null; + return; break; } logindata.showing_status = true; @@ -374,6 +378,7 @@ /** * Performs an AJAX logon request to the server and calls ajaxLoginProcessResponse() on the result. * @param object JSON packet to send + * @param function Optional function to call on the response as well. */ window.ajaxLoginPerformRequest = function(json, _hookfunc) @@ -420,12 +425,15 @@ } return false; } + // Main mode switch switch ( response.mode ) { - case 'build_box': + case 'initial': // Rid ourselves of any loading windows ajaxLoginSetStatus(AJAX_STATUS_DESTROY); + // show any errors + ajaxLoginShowFriendlyError(response); // The server wants us to build the login form, all the information is there ajaxLoginBuildForm(response); break; @@ -433,49 +441,33 @@ ajaxLoginSetStatus(AJAX_STATUS_SUCCESS); logindata.successfunc(response.key, response); break; - case 'login_failure': - // Rid ourselves of any loading windows - ajaxLoginSetStatus(AJAX_STATUS_DESTROY); - document.getElementById('messageBox').style.backgroundColor = '#C0C0C0'; - var mb_parent = document.getElementById('messageBox').parentNode; - var do_respawn = ( typeof(response.respawn) == 'boolean' && response.respawn == true ) || typeof(response.respawn) != 'boolean'; - if ( do_respawn ) - { - $(mb_parent).effect("shake", {}, 200); - setTimeout(function() - { - document.getElementById('messageBox').style.backgroundColor = '#FFF'; - - ajaxLoginBuildForm(response.respawn_info); - ajaxLoginShowFriendlyError(response); - }, 2500); - } - else - { - ajaxLoginShowFriendlyError(response); - } - break; - case 'login_success_reset': + case 'reset_pass_used': + // We logged in with a temporary password. Prompt the user to go to the temp password page and + // reset their real password. If they click no, treat it as a login failure, as no session key + // is actually issued when this type of login is performed. + var conf = confirm($lang.get('user_login_ajax_msg_used_temp_pass')); if ( conf ) { var url = makeUrlNS('Special', 'PasswordReset/stage2/' + response.user_id + '/' + response.temp_password); window.location = url; + break; } - else - { - // treat as a failure - ajaxLoginSetStatus(AJAX_STATUS_DESTROY); - document.getElementById('messageBox').style.backgroundColor = '#C0C0C0'; - var mb_parent = document.getElementById('messageBox').parentNode; - $(mb_parent).effect("shake", {}, 1500); - setTimeout(function() - { - document.getElementById('messageBox').style.backgroundColor = '#FFF'; - ajaxLoginBuildForm(response.respawn_info); - // don't show an error here, just silently respawn - }, 2500); - } + // else, treat as a failure + default: + // Rid ourselves of any loading windows + ajaxLoginSetStatus(AJAX_STATUS_DESTROY); + document.getElementById('messageBox').style.backgroundColor = '#C0C0C0'; + var mb_parent = document.getElementById('messageBox').parentNode; + $(mb_parent).effect("shake", {}, 200); + setTimeout(function() + { + document.getElementById('messageBox').style.backgroundColor = '#FFF'; + console.debug(response); + ajaxLoginShowFriendlyError(response); + ajaxLoginBuildForm(response); + }, 2500); + break; case 'logout_success': if ( ENANO_SID ) @@ -512,7 +504,7 @@ var div = document.createElement('div'); div.id = 'ajax_login_form'; - var show_captcha = ( data.locked_out.locked_out && data.locked_out.lockout_policy == 'captcha' ) ? data.locked_out.captcha : false; + var show_captcha = ( data.lockout.active && data.lockout.policy == 'captcha' ) ? data.lockout.captcha : false; // text displayed on re-auth if ( logindata.user_level > USER_LEVEL_MEMBER ) @@ -586,8 +578,6 @@ tr2.appendChild(td2_2); table.appendChild(tr2); - eval(setHook('login_build_form')); - // Field - captcha if ( show_captcha ) { @@ -617,6 +607,14 @@ table.appendChild(tr3); } + // ok, this is a compatibility hack + data.locked_out = { locked_out: data.lockout.active }; + + // hook for the login form + eval(setHook('login_build_form')); + + delete(data.locked_out); + // Done building the main part of the form form.appendChild(table); @@ -696,7 +694,7 @@ lbl_dh.innerHTML = $lang.get('user_login_ajax_check_dh_ie'); boxen.appendChild(lbl_dh); } - else if ( !data.allow_diffiehellman ) + else if ( !data.crypto.dh_enable ) { // create hidden control - server requested that DiffieHellman be disabled (usually means not supported) var check_dh = document.createElement('input'); @@ -769,24 +767,21 @@ // Post operations: show captcha window if ( show_captcha ) + { ajaxShowCaptcha(show_captcha); + } // Post operations: stash encryption keys and All That Jazz(TM) - logindata.key_aes = data.aes_key; - logindata.key_dh = data.dh_public_key; + logindata.key_aes = data.crypto_aes_key; + logindata.key_dh = data.crypto.dh_public_key; logindata.captcha_hash = show_captcha; - logindata.loggedin_username = data.username + logindata.loggedin_username = data.username; - // Are we locked out? If so simulate an error and disable the controls - if ( data.lockout_info.lockout_policy == 'lockout' && data.locked_out.locked_out ) + // If policy is lockout, also disable controls + if ( data.lockout.policy == 'lockout' && data.lockout.active ) { f_username.setAttribute('disabled', 'disabled'); f_password.setAttribute('disabled', 'disabled'); - var fake_packet = { - error_code: 'locked_out', - respawn_info: data - }; - ajaxLoginShowFriendlyError(fake_packet); } } @@ -978,11 +973,10 @@ window.ajaxLoginShowFriendlyError = function(response) { - if ( !response.respawn_info ) - return false; - if ( !response.error_code ) - return false; var text = ajaxLoginGetErrorText(response); + if ( text == false ) + return true; + if ( document.getElementById('ajax_login_error_box') ) { // console.info('Reusing existing error-box'); @@ -1021,85 +1015,53 @@ window.ajaxLoginGetErrorText = function(response) { - if ( !response.error_code.match(/^[a-z0-9]+_[a-z0-9_]+$/) ) + if ( response.lockout ) { - return response.error_code; + // set this pluralality thing + response.lockout.plural = response.lockout.time_rem == 1 ? '' : $lang.get('meta_plural'); } - switch ( response.error_code ) + + if ( response.mode == 'initial' ) { - default: - eval(setHook('ajax_login_process_error')); - if ( !ls ) - { - var ls = $lang.get('user_err_' + response.error_code); - if ( ls == 'user_err_' + response.error_code ) - // Adding response here allows language strings to utilize additional information passed from the error packet - ls = $lang.get(response.error_code, response); - } - - return ls; - break; - case 'locked_out': - if ( response.respawn_info.lockout_info.lockout_policy == 'lockout' ) - { - return $lang.get('user_err_locked_out', { - lockout_threshold: response.respawn_info.lockout_info.lockout_threshold, - lockout_duration: response.respawn_info.lockout_info.lockout_duration, - time_rem: response.respawn_info.lockout_info.time_rem, - plural: ( response.respawn_info.lockout_info.time_rem == 1 ) ? '' : $lang.get('meta_plural'), - captcha_blurb: '' - }); - break; - } - case 'invalid_credentials': - var base = $lang.get('user_err_invalid_credentials'); - if ( response.respawn_info.locked_out.locked_out ) - { - base += ' '; - var captcha_blurb = ''; - switch(response.respawn_info.lockout_info.lockout_policy) + // Just showing the box for the first time. If there's an error now, it's based on a preexisting lockout. + if ( response.lockout.active ) + { + return $lang.get('user_err_locked_out_initial_' + response.lockout.policy, response.lockout); + } + return false; + } + else + { + // An attempt was made. + switch(response.mode) + { + case 'login_failure': + // Generic login user error. + var error = '', x; + if ( (x = $lang.get(response.error)) != response.error ) + error = x; + else + error = $lang.get('user_err_' + response.error); + if ( response.lockout.active && response.lockout.policy == 'lockout' ) { - case 'captcha': - captcha_blurb = $lang.get('user_err_locked_out_captcha_blurb'); - break; - case 'lockout': - break; - default: - base += 'WTF? Shouldn\'t be locked out with lockout policy set to disable. '; - break; + // Lockout enforcement was just activated. + return $lang.get('user_err_locked_out_initial_' + response.lockout.policy, response.lockout); + } + else if ( response.lockout.policy != 'disable' && !response.lockout.active && response.lockout.fails > 0 ) + { + // Lockout is in a warning state. + error += ' ' + $lang.get('user_err_invalid_credentials_' + response.lockout.policy, response.lockout); } - base += $lang.get('user_err_locked_out', { - captcha_blurb: captcha_blurb, - lockout_threshold: response.respawn_info.lockout_info.lockout_threshold, - lockout_duration: response.respawn_info.lockout_info.lockout_duration, - time_rem: response.respawn_info.lockout_info.time_rem, - plural: ( response.respawn_info.lockout_info.time_rem == 1 ) ? '' : $lang.get('meta_plural') - }); - } - else if ( response.respawn_info.lockout_info.lockout_policy == 'lockout' || response.respawn_info.lockout_info.lockout_policy == 'captcha' ) - { - // if we have a lockout policy of captcha or lockout, then warn the user - switch ( response.respawn_info.lockout_info.lockout_policy ) - { - case 'captcha': - base += $lang.get('user_err_invalid_credentials_lockout_captcha', { - fails: response.respawn_info.lockout_info.lockout_fails, - lockout_threshold: response.respawn_info.lockout_info.lockout_threshold, - lockout_duration: response.respawn_info.lockout_info.lockout_duration - }); - break; - case 'lockout': - base += $lang.get('user_err_invalid_credentials_lockout', { - fails: response.respawn_info.lockout_info.lockout_fails, - lockout_threshold: response.respawn_info.lockout_info.lockout_threshold, - lockout_duration: response.respawn_info.lockout_info.lockout_duration - }); - break; - } - } - return base; - break; + return error; + break; + case 'api_error': + // Error in the API. + return $lang.get('user_err_login_generic_title') + ': ' + $lang.get('user_' + response.error.toLowerCase()); + break; + } } + + return typeof(response.error) == 'string' ? response.error : false; } window.ajaxShowCaptcha = function(code) @@ -1302,6 +1264,7 @@ { level = USER_LEVEL_ADMIN; } + ajaxLogonInit(function(k, response) { ajaxLoginReplaceSIDInline(k, old_sid, level);