1class MembershipLogin 2{ 3 $LOGIN_FORM = $('form[name="membershipLoginForm"]'); 4 5 fusionAuthWebAuthnObj = new FusionAuthWebAuthn(); 6 7 initialise() { 8 if (window.location.pathname === '/login') { 9 $('body').addClass('theme-bg'); 10 $(window).on('scroll', this.loadRocketChat); 11 12 if ($('#system-message-container').children().length > 1) { 13 $('._iDld').toggleClass('hasError'); 14 } 15 } 16 17 this.setEventHandlers(); 18 } 19 20 loadRocketChat() { 21 setTimeout(() => { 22 const rocketChatHost = 'https://chat.momentummedia.com.au'; 23 24 // Start of Rocket.Chat Livechat Script 25 (function(w, d, s, u) { 26 w.RocketChat = function(c) { w.RocketChat._.push(c) }; w.RocketChat._ = []; w.RocketChat.url = u; 27 var h = d.getElementsByTagName(s)[0], j = d.createElement(s); 28 j.async = true; j.src = u + '/rocketchat-livechat.min.js?_=201903270000'; 29 h.parentNode.insertBefore(j, h); 30 })(window, document, 'script', `${rocketChatHost}/livechat`); 31 32 RocketChat(function () { 33 this.setDepartment('Memberships'); 34 this.setCustomField('site_domain', 'theadviser.com.au'); 35 36 this.onServiceOffline((data) => { 37 document.querySelector('#rocketchat-iframe').contentWindow.postMessage({fn : 'serviceOffline'}, rocketChatHost); 38 }); 39 }); 40 // End of Rocket.Chat Livechat Script 41 }, 1000); 42 43 $(window).off('scroll', this.loadRocketChat); 44 } 45 46 setEventHandlers() { 47 // Declared to properly access class-level scope. 48 const self = this; 49 50 $('#loginTooltip').on('click', () => { 51 if ($(window).width() < 769) { 52 $('.tooltiptextmobile').fadeToggle(); 53 } 54 }); 55 56 $('#showPassword').on('click', function() { 57 const $passwordElement = $('input[name="password"]'); 58 $passwordElement.attr('type', ($passwordElement.attr('type') === 'password') ? 'text' : 'password'); 59 $(this).find('i').toggleClass('fa-eye-slash fa-eye'); 60 }); 61 62 self.$LOGIN_FORM 63 .on('click', '.btn-submit', function (event) { 64 event.preventDefault(); 65 self.hideInlineErrors(); 66 67 const loginType = $(this).data('login_type'); 68 if (self.validateInputs(loginType) === false) { 69 return; 70 } 71 72 self.$LOGIN_FORM.data('formLoginType', loginType); 73 self.$LOGIN_FORM.get(0).requestSubmit(); 74 }) 75 .on('submit', async function (event) { 76 if ( 77 1 === 1 78 && typeof window.MomentumTurnstileGate !== 'undefined' 79 && window.MomentumTurnstileGate !== null 80 && typeof window.MomentumTurnstileGate.shouldWaitForGate === 'function' 81 && window.MomentumTurnstileGate.shouldWaitForGate(self.$LOGIN_FORM) === true 82 ) { 83 return; 84 } 85 86 event.preventDefault(); 87 88 const loginType = $(this).data('formLoginType'); 89 const $btnSubmit = self.$LOGIN_FORM.find(`.btn-submit[data-login_type="${loginType}"]`); 90 let response = null; 91 92 try { 93 self.toggleLoading($btnSubmit); 94 95 if (loginType === 'fusionauth') { 96 response = await self.doPasskeyLogin(); 97 } else { 98 response = await self.doRegularLogin(); 99 } 100 101 if (response.result === false) { 102 throw response; 103 } 104 105 if (response.hasOwnProperty('paywall_user') === true) { 106 try { 107 localStorage.setItem('paywall_user', JSON.stringify(response.paywall_user)); 108 } catch (exception) { 109 console.error('Error setting paywall_user', exception); 110 } 111 } 112 113 window.location.href = response.redirect; 114 } catch (exception) { 115 console.error(exception); 116 117 self.toggleLoading($btnSubmit); 118 self.toggleMessage(exception); 119 } 120 }); 121 } 122 123 async doPasskeyLogin() { 124 try { 125 this.fusionAuthWebAuthnObj.setExtraPayloadData({ 126 username : this.$LOGIN_FORM.find('input[name="username"]').val() 127 }); 128 129 const publicKeyCredential = await this.fusionAuthWebAuthnObj.startPasskeyAssertion(); 130 if (publicKeyCredential.result === false) { 131 return publicKeyCredential; 132 } 133 134 return await this.executeHttpRequest( 135 'membershipLogin', 136 { 137 captcha_turnstile_response : ( 138 1 === 1 139 && typeof window.MomentumTurnstileGate !== 'undefined' 140 && window.MomentumTurnstileGate !== null 141 && typeof window.MomentumTurnstileGate.getTokenFromForm === 'function' 142 ) ? window.MomentumTurnstileGate.getTokenFromForm(this.$LOGIN_FORM) : '', 143 login_type : 'fusionauth', 144 public_key : await this.fusionAuthWebAuthnObj.preparePasskeyAssertionCompletionPayload(publicKeyCredential), 145 return : this.$LOGIN_FORM.find('input[name="return"]').val(), 146 username : this.$LOGIN_FORM.find('input[name="username"]').val() 147 } 148 ); 149 } catch (error) { 150 throw { 151 result : false, 152 message : 'An error has been encountered while logging in. Please try again.' 153 }; 154 } 155 } 156 157 async doRegularLogin() { 158 const formData = new FormData(this.$LOGIN_FORM.get(0)); 159 formData.append('login_type', 'joomla'); 160 161 return await this.executeHttpRequest( 162 'membershipLogin', 163 Object.fromEntries(formData) 164 ); 165 } 166 167 validateInputs(loginType) { 168 let errorCount = 0; 169 170 if (this.$LOGIN_FORM.find('input[name="username"]').val().trim().length === 0) { 171 this.displayInlineError(this.$LOGIN_FORM.find('input[name="username"]')); 172 errorCount++; 173 } 174 175 if (loginType === 'joomla' && this.$LOGIN_FORM.find('input[name="password"]').val().trim().length === 0) { 176 this.displayInlineError(this.$LOGIN_FORM.find('input[name="password"]')); 177 errorCount++; 178 } 179 180 return errorCount === 0; 181 } 182 183 displayInlineError(elem) { 184 $(elem).parents('._kbtd').find('._6Rpk').addClass('label-error'); 185 $(elem).addClass('border-error'); 186 $(elem).after('<span class="inline-error">This field is required.</span>'); 187 } 188 189 hideInlineErrors() { 190 this.$LOGIN_FORM.find('.no-margin-bottom').removeClass('no-margin-bottom'); 191 this.$LOGIN_FORM.find('.label-error').removeClass('label-error'); 192 this.$LOGIN_FORM.find('.border-error').removeClass('border-error'); 193 this.$LOGIN_FORM.find('.inline-error').remove(); 194 } 195 196 toggleLoading($btnSubmit) { 197 this.$LOGIN_FORM.find('.btn-submit').removeAttr('disabled'); 198 this.$LOGIN_FORM.find('.message-area').hide(); 199 200 $btnSubmit[(($btnSubmit.hasClass('processing') === true) ? 'remove' : 'add') + 'Class']('processing'); 201 if ($btnSubmit.hasClass('processing') === true) { 202 this.$LOGIN_FORM.find('.btn-submit').attr('disabled', true); 203 } 204 } 205 206 toggleMessage(response) { 207 this.$LOGIN_FORM 208 .find('.message-area') 209 .html(response.message) 210 .removeClass('text-danger text-success') 211 .addClass('text-' + ((response.result === true) ? 'success' : 'danger')) 212 .css('display', 'inline-block'); 213 } 214 215 async executeHttpRequest(endpoint, data) { 216 return await $.ajax({ 217 url : '/?' + $.param({ 218 option : 'com_ajax', 219 plugin : endpoint, 220 format : 'json' 221 }), 222 data : data, 223 method : 'POST', 224 dataType : 'json' 225 }) 226 .then((response) => response.data[response.data.length - 1]); 227 } 228} 229 230$(function() { 231 (new MembershipLogin()).initialise(); 232});
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.