113 logindata = {}; |
113 logindata = {}; |
114 |
114 |
115 var title = ( user_level > USER_LEVEL_MEMBER ) ? $lang.get('user_login_ajax_prompt_title_elev') : $lang.get('user_login_ajax_prompt_title'); |
115 var title = ( user_level > USER_LEVEL_MEMBER ) ? $lang.get('user_login_ajax_prompt_title_elev') : $lang.get('user_login_ajax_prompt_title'); |
116 logindata.mb_object = new MessageBox(MB_OKCANCEL | MB_ICONLOCK, title, ''); |
116 logindata.mb_object = new MessageBox(MB_OKCANCEL | MB_ICONLOCK, title, ''); |
117 |
117 |
|
118 // |
|
119 // Cancel function: called when the "Cancel" button is clicked |
|
120 // |
118 logindata.mb_object.onclick['Cancel'] = function() |
121 logindata.mb_object.onclick['Cancel'] = function() |
119 { |
122 { |
120 // Hide the error message and captcha |
123 // Hide the error message, if any |
121 if ( document.getElementById('ajax_login_error_box') ) |
124 $('ajax_login_error_box').remove(); |
122 { |
125 // Hide the captcha, if any |
123 document.getElementById('ajax_login_error_box').parentNode.removeChild(document.getElementById('ajax_login_error_box')); |
|
124 } |
|
125 if ( document.getElementById('autoCaptcha') ) |
126 if ( document.getElementById('autoCaptcha') ) |
126 { |
127 { |
127 var to = fly_out_top(document.getElementById('autoCaptcha'), false, true); |
128 var to = fly_out_top(document.getElementById('autoCaptcha'), false, true); |
128 setTimeout(function() { |
129 setTimeout(function() { |
129 var d = document.getElementById('autoCaptcha'); |
130 var d = document.getElementById('autoCaptcha'); |
130 d.parentNode.removeChild(d); |
131 d.parentNode.removeChild(d); |
131 }, to); |
132 }, to); |
132 } |
133 } |
133 // Ask the server to clean our key |
134 // Ask the server to delete the encryption key we're using |
134 ajaxLoginPerformRequest({ |
135 ajaxLoginPerformRequest({ |
135 mode: 'clean_key', |
136 mode: 'clean_key', |
136 key_aes: logindata.key_aes, |
137 key_aes: logindata.key_aes, |
137 key_dh: logindata.key_dh |
138 key_dh: logindata.key_dh |
138 }); |
139 }); |
139 }; |
140 }; |
140 |
141 |
|
142 // Clicking OK will not cause the box to destroy, as this function returns true. |
141 logindata.mb_object.onbeforeclick['OK'] = function() |
143 logindata.mb_object.onbeforeclick['OK'] = function() |
142 { |
144 { |
|
145 // Just call the submitter and let it take care of everything |
143 ajaxLoginSubmitForm(); |
146 ajaxLoginSubmitForm(); |
144 return true; |
147 return true; |
145 } |
148 } |
146 |
149 |
147 // Fetch the inner content area |
150 // Fetch the inner content area |
158 // Request the key |
161 // Request the key |
159 ajaxLoginPerformRequest({ mode: 'getkey' }); |
162 ajaxLoginPerformRequest({ mode: 'getkey' }); |
160 } |
163 } |
161 |
164 |
162 /** |
165 /** |
163 * For compatibility only. |
166 * For compatibility only. Really, folks, it's ajaxLoginInit. If you need a |
|
167 * mnemonic device, use "two 'in's." |
164 */ |
168 */ |
165 |
169 |
166 window.ajaxLogonInit = function(call_on_finish, user_level) |
170 window.ajaxLogonInit = function(call_on_finish, user_level) |
167 { |
171 { |
168 return ajaxLoginInit(call_on_finish, user_level); |
172 return ajaxLoginInit(call_on_finish, user_level); |
169 } |
173 } |
170 |
174 |
171 /** |
175 /** |
172 * Sets the contents of the AJAX login window to the appropriate status message. |
176 * Sets the contents of the AJAX login window to the appropriate status message. |
173 * @param int One of AJAX_STATUS_* |
177 * @param int One of AJAX_STATUS_* constants |
174 */ |
178 */ |
175 |
179 |
176 window.ajaxLoginSetStatus = function(status) |
180 window.ajaxLoginSetStatus = function(status) |
177 { |
181 { |
178 if ( !logindata.mb_inner ) |
182 if ( !logindata.mb_inner ) |
418 { |
423 { |
419 alert(response.error); |
424 alert(response.error); |
420 } |
425 } |
421 return false; |
426 return false; |
422 } |
427 } |
|
428 |
423 // Main mode switch |
429 // Main mode switch |
424 switch ( response.mode ) |
430 switch ( response.mode ) |
425 { |
431 { |
426 case 'build_box': |
432 case 'initial': |
427 // Rid ourselves of any loading windows |
433 // Rid ourselves of any loading windows |
428 ajaxLoginSetStatus(AJAX_STATUS_DESTROY); |
434 ajaxLoginSetStatus(AJAX_STATUS_DESTROY); |
|
435 // show any errors |
|
436 ajaxLoginShowFriendlyError(response); |
429 // The server wants us to build the login form, all the information is there |
437 // The server wants us to build the login form, all the information is there |
430 ajaxLoginBuildForm(response); |
438 ajaxLoginBuildForm(response); |
431 break; |
439 break; |
432 case 'login_success': |
440 case 'login_success': |
433 ajaxLoginSetStatus(AJAX_STATUS_SUCCESS); |
441 ajaxLoginSetStatus(AJAX_STATUS_SUCCESS); |
434 logindata.successfunc(response.key, response); |
442 logindata.successfunc(response.key, response); |
435 break; |
443 break; |
436 case 'login_failure': |
444 case 'reset_pass_used': |
|
445 // We logged in with a temporary password. Prompt the user to go to the temp password page and |
|
446 // reset their real password. If they click no, treat it as a login failure, as no session key |
|
447 // is actually issued when this type of login is performed. |
|
448 |
|
449 var conf = confirm($lang.get('user_login_ajax_msg_used_temp_pass')); |
|
450 if ( conf ) |
|
451 { |
|
452 var url = makeUrlNS('Special', 'PasswordReset/stage2/' + response.user_id + '/' + response.temp_password); |
|
453 window.location = url; |
|
454 break; |
|
455 } |
|
456 // else, treat as a failure |
|
457 default: |
437 // Rid ourselves of any loading windows |
458 // Rid ourselves of any loading windows |
438 ajaxLoginSetStatus(AJAX_STATUS_DESTROY); |
459 ajaxLoginSetStatus(AJAX_STATUS_DESTROY); |
439 document.getElementById('messageBox').style.backgroundColor = '#C0C0C0'; |
460 document.getElementById('messageBox').style.backgroundColor = '#C0C0C0'; |
440 var mb_parent = document.getElementById('messageBox').parentNode; |
461 var mb_parent = document.getElementById('messageBox').parentNode; |
441 var do_respawn = ( typeof(response.respawn) == 'boolean' && response.respawn == true ) || typeof(response.respawn) != 'boolean'; |
462 $(mb_parent).effect("shake", {}, 200); |
442 if ( do_respawn ) |
463 setTimeout(function() |
443 { |
464 { |
444 $(mb_parent).effect("shake", {}, 200); |
465 document.getElementById('messageBox').style.backgroundColor = '#FFF'; |
445 setTimeout(function() |
466 console.debug(response); |
446 { |
467 ajaxLoginShowFriendlyError(response); |
447 document.getElementById('messageBox').style.backgroundColor = '#FFF'; |
468 ajaxLoginBuildForm(response); |
448 |
469 }, 2500); |
449 ajaxLoginBuildForm(response.respawn_info); |
470 |
450 ajaxLoginShowFriendlyError(response); |
|
451 }, 2500); |
|
452 } |
|
453 else |
|
454 { |
|
455 ajaxLoginShowFriendlyError(response); |
|
456 } |
|
457 break; |
|
458 case 'login_success_reset': |
|
459 var conf = confirm($lang.get('user_login_ajax_msg_used_temp_pass')); |
|
460 if ( conf ) |
|
461 { |
|
462 var url = makeUrlNS('Special', 'PasswordReset/stage2/' + response.user_id + '/' + response.temp_password); |
|
463 window.location = url; |
|
464 } |
|
465 else |
|
466 { |
|
467 // treat as a failure |
|
468 ajaxLoginSetStatus(AJAX_STATUS_DESTROY); |
|
469 document.getElementById('messageBox').style.backgroundColor = '#C0C0C0'; |
|
470 var mb_parent = document.getElementById('messageBox').parentNode; |
|
471 $(mb_parent).effect("shake", {}, 1500); |
|
472 setTimeout(function() |
|
473 { |
|
474 document.getElementById('messageBox').style.backgroundColor = '#FFF'; |
|
475 ajaxLoginBuildForm(response.respawn_info); |
|
476 // don't show an error here, just silently respawn |
|
477 }, 2500); |
|
478 } |
|
479 break; |
471 break; |
480 case 'logout_success': |
472 case 'logout_success': |
481 if ( ENANO_SID ) |
473 if ( ENANO_SID ) |
482 { |
474 { |
483 ajaxLoginReplaceSIDInline(false, ENANO_SID, USER_LEVEL_MEMBER); |
475 ajaxLoginReplaceSIDInline(false, ENANO_SID, USER_LEVEL_MEMBER); |
615 td3_2.appendChild(f_captcha); |
605 td3_2.appendChild(f_captcha); |
616 tr3.appendChild(td3_2); |
606 tr3.appendChild(td3_2); |
617 table.appendChild(tr3); |
607 table.appendChild(tr3); |
618 } |
608 } |
619 |
609 |
|
610 // ok, this is a compatibility hack |
|
611 data.locked_out = { locked_out: data.lockout.active }; |
|
612 |
|
613 // hook for the login form |
|
614 eval(setHook('login_build_form')); |
|
615 |
|
616 delete(data.locked_out); |
|
617 |
620 // Done building the main part of the form |
618 // Done building the main part of the form |
621 form.appendChild(table); |
619 form.appendChild(table); |
622 |
620 |
623 // Checkbox container |
621 // Checkbox container |
624 var boxen = document.createElement('div'); |
622 var boxen = document.createElement('div'); |
694 lbl_dh.style.fontSize = 'smaller'; |
692 lbl_dh.style.fontSize = 'smaller'; |
695 lbl_dh.style.textAlign = 'center'; |
693 lbl_dh.style.textAlign = 'center'; |
696 lbl_dh.innerHTML = $lang.get('user_login_ajax_check_dh_ie'); |
694 lbl_dh.innerHTML = $lang.get('user_login_ajax_check_dh_ie'); |
697 boxen.appendChild(lbl_dh); |
695 boxen.appendChild(lbl_dh); |
698 } |
696 } |
699 else if ( !data.allow_diffiehellman ) |
697 else if ( !data.crypto.dh_enable ) |
700 { |
698 { |
701 // create hidden control - server requested that DiffieHellman be disabled (usually means not supported) |
699 // create hidden control - server requested that DiffieHellman be disabled (usually means not supported) |
702 var check_dh = document.createElement('input'); |
700 var check_dh = document.createElement('input'); |
703 check_dh.type = 'hidden'; |
701 check_dh.type = 'hidden'; |
704 check_dh.id = 'ajax_login_field_dh'; |
702 check_dh.id = 'ajax_login_field_dh'; |
767 document.getElementById('ajax_login_field_username').focus(); |
765 document.getElementById('ajax_login_field_username').focus(); |
768 }, 750); |
766 }, 750); |
769 |
767 |
770 // Post operations: show captcha window |
768 // Post operations: show captcha window |
771 if ( show_captcha ) |
769 if ( show_captcha ) |
|
770 { |
772 ajaxShowCaptcha(show_captcha); |
771 ajaxShowCaptcha(show_captcha); |
|
772 } |
773 |
773 |
774 // Post operations: stash encryption keys and All That Jazz(TM) |
774 // Post operations: stash encryption keys and All That Jazz(TM) |
775 logindata.key_aes = data.aes_key; |
775 logindata.key_aes = data.crypto_aes_key; |
776 logindata.key_dh = data.dh_public_key; |
776 logindata.key_dh = data.crypto.dh_public_key; |
777 logindata.captcha_hash = show_captcha; |
777 logindata.captcha_hash = show_captcha; |
778 logindata.loggedin_username = data.username |
778 logindata.loggedin_username = data.username; |
779 |
779 |
780 // Are we locked out? If so simulate an error and disable the controls |
780 // If policy is lockout, also disable controls |
781 if ( data.lockout_info.lockout_policy == 'lockout' && data.locked_out.locked_out ) |
781 if ( data.lockout.policy == 'lockout' && data.lockout.active ) |
782 { |
782 { |
783 f_username.setAttribute('disabled', 'disabled'); |
783 f_username.setAttribute('disabled', 'disabled'); |
784 f_password.setAttribute('disabled', 'disabled'); |
784 f_password.setAttribute('disabled', 'disabled'); |
785 var fake_packet = { |
|
786 error_code: 'locked_out', |
|
787 respawn_info: data |
|
788 }; |
|
789 ajaxLoginShowFriendlyError(fake_packet); |
|
790 } |
785 } |
791 } |
786 } |
792 |
787 |
793 window.ajaxLoginSubmitForm = function(real, username, password, captcha, remember) |
788 window.ajaxLoginSubmitForm = function(real, username, password, captcha, remember) |
794 { |
789 { |
1019 body.appendChild(errbox); |
1013 body.appendChild(errbox); |
1020 } |
1014 } |
1021 |
1015 |
1022 window.ajaxLoginGetErrorText = function(response) |
1016 window.ajaxLoginGetErrorText = function(response) |
1023 { |
1017 { |
1024 if ( !response.error_code.match(/^[a-z0-9]+_[a-z0-9_]+$/) ) |
1018 if ( response.lockout ) |
1025 { |
1019 { |
1026 return response.error_code; |
1020 // set this pluralality thing |
1027 } |
1021 response.lockout.plural = response.lockout.time_rem == 1 ? '' : $lang.get('meta_plural'); |
1028 switch ( response.error_code ) |
1022 } |
1029 { |
1023 |
1030 default: |
1024 if ( response.mode == 'initial' ) |
1031 eval(setHook('ajax_login_process_error')); |
1025 { |
1032 if ( !ls ) |
1026 // Just showing the box for the first time. If there's an error now, it's based on a preexisting lockout. |
1033 { |
1027 if ( response.lockout.active ) |
1034 var ls = $lang.get('user_err_' + response.error_code); |
1028 { |
1035 if ( ls == 'user_err_' + response.error_code ) |
1029 return $lang.get('user_err_locked_out_initial_' + response.lockout.policy, response.lockout); |
1036 // Adding response here allows language strings to utilize additional information passed from the error packet |
1030 } |
1037 ls = $lang.get(response.error_code, response); |
1031 return false; |
1038 } |
1032 } |
1039 |
1033 else |
1040 return ls; |
1034 { |
1041 break; |
1035 // An attempt was made. |
1042 case 'locked_out': |
1036 switch(response.mode) |
1043 if ( response.respawn_info.lockout_info.lockout_policy == 'lockout' ) |
1037 { |
1044 { |
1038 case 'login_failure': |
1045 return $lang.get('user_err_locked_out', { |
1039 // Generic login user error. |
1046 lockout_threshold: response.respawn_info.lockout_info.lockout_threshold, |
1040 var error = '', x; |
1047 lockout_duration: response.respawn_info.lockout_info.lockout_duration, |
1041 if ( (x = $lang.get(response.error)) != response.error ) |
1048 time_rem: response.respawn_info.lockout_info.time_rem, |
1042 error = x; |
1049 plural: ( response.respawn_info.lockout_info.time_rem == 1 ) ? '' : $lang.get('meta_plural'), |
1043 else |
1050 captcha_blurb: '' |
1044 error = $lang.get('user_err_' + response.error); |
1051 }); |
1045 if ( response.lockout.active && response.lockout.policy == 'lockout' ) |
|
1046 { |
|
1047 // Lockout enforcement was just activated. |
|
1048 return $lang.get('user_err_locked_out_initial_' + response.lockout.policy, response.lockout); |
|
1049 } |
|
1050 else if ( response.lockout.policy != 'disable' && !response.lockout.active && response.lockout.fails > 0 ) |
|
1051 { |
|
1052 // Lockout is in a warning state. |
|
1053 error += ' ' + $lang.get('user_err_invalid_credentials_' + response.lockout.policy, response.lockout); |
|
1054 } |
|
1055 return error; |
1052 break; |
1056 break; |
1053 } |
1057 case 'api_error': |
1054 case 'invalid_credentials': |
1058 // Error in the API. |
1055 var base = $lang.get('user_err_invalid_credentials'); |
1059 return $lang.get('user_err_login_generic_title') + ': ' + $lang.get('user_' + response.error.toLowerCase()); |
1056 if ( response.respawn_info.locked_out.locked_out ) |
1060 break; |
1057 { |
1061 } |
1058 base += ' '; |
1062 } |
1059 var captcha_blurb = ''; |
1063 |
1060 switch(response.respawn_info.lockout_info.lockout_policy) |
1064 return typeof(response.error) == 'string' ? response.error : false; |
1061 { |
|
1062 case 'captcha': |
|
1063 captcha_blurb = $lang.get('user_err_locked_out_captcha_blurb'); |
|
1064 break; |
|
1065 case 'lockout': |
|
1066 break; |
|
1067 default: |
|
1068 base += 'WTF? Shouldn\'t be locked out with lockout policy set to disable. '; |
|
1069 break; |
|
1070 } |
|
1071 base += $lang.get('user_err_locked_out', { |
|
1072 captcha_blurb: captcha_blurb, |
|
1073 lockout_threshold: response.respawn_info.lockout_info.lockout_threshold, |
|
1074 lockout_duration: response.respawn_info.lockout_info.lockout_duration, |
|
1075 time_rem: response.respawn_info.lockout_info.time_rem, |
|
1076 plural: ( response.respawn_info.lockout_info.time_rem == 1 ) ? '' : $lang.get('meta_plural') |
|
1077 }); |
|
1078 } |
|
1079 else if ( response.respawn_info.lockout_info.lockout_policy == 'lockout' || response.respawn_info.lockout_info.lockout_policy == 'captcha' ) |
|
1080 { |
|
1081 // if we have a lockout policy of captcha or lockout, then warn the user |
|
1082 switch ( response.respawn_info.lockout_info.lockout_policy ) |
|
1083 { |
|
1084 case 'captcha': |
|
1085 base += $lang.get('user_err_invalid_credentials_lockout_captcha', { |
|
1086 fails: response.respawn_info.lockout_info.lockout_fails, |
|
1087 lockout_threshold: response.respawn_info.lockout_info.lockout_threshold, |
|
1088 lockout_duration: response.respawn_info.lockout_info.lockout_duration |
|
1089 }); |
|
1090 break; |
|
1091 case 'lockout': |
|
1092 base += $lang.get('user_err_invalid_credentials_lockout', { |
|
1093 fails: response.respawn_info.lockout_info.lockout_fails, |
|
1094 lockout_threshold: response.respawn_info.lockout_info.lockout_threshold, |
|
1095 lockout_duration: response.respawn_info.lockout_info.lockout_duration |
|
1096 }); |
|
1097 break; |
|
1098 } |
|
1099 } |
|
1100 return base; |
|
1101 break; |
|
1102 } |
|
1103 } |
1065 } |
1104 |
1066 |
1105 window.ajaxShowCaptcha = function(code) |
1067 window.ajaxShowCaptcha = function(code) |
1106 { |
1068 { |
1107 var mydiv = document.createElement('div'); |
1069 var mydiv = document.createElement('div'); |