PageSourceSearch

https://vetiver.org/wp-content/plugins/wp-2fa-premium/extensions/twilio/assets/js/twilio.js?ver=4.1.0

js vetiver.org collected 2026-10-02 05:02:09 UTC 11,682 bytes, 370 lines download raw bytes

1
2/**
3 * Script for 2FA Twilio.
4 *
5 *  @param {jQuery} $        jQuery object.
6 *  @param {Object} window   The window object.
7 */
8
9
10(function ($, window) {
11
12	jQuery(document).on('click', '[data-check-twilio-2fa]', function () {
13		let role_suffix = ('' === jQuery(this).data('role')) ? '' : jQuery(this).data('role');
14		const sid = (jQuery('#wp-2fa-twilio-sid' + role_suffix).length) ? jQuery('#wp-2fa-twilio-sid' + role_suffix).val() : jQuery('#wp-2fa-twilio-sid').val();
15		const auth = (jQuery('#wp-2fa-twilio-auth' + role_suffix).length) ? jQuery('#wp-2fa-twilio-auth' + role_suffix).val() : jQuery('#wp-2fa-twilio-auth').val();
16		const id = (jQuery('#wp-2fa-twilio-id' + role_suffix).length) ? jQuery('#wp-2fa-twilio-id' + role_suffix).val() : jQuery('#wp-2fa-twilio-id').val();
17		const ajaxURL = (typeof wp2faWizardData != "undefined") ? wp2faWizardData.ajaxURL : ajaxurl;
18		const nonceValue = jQuery(this).attr('data-nonce');
19
20		jQuery.ajax({
21			url: ajaxURL,
22			data: {
23				action: 'check_twilio_credentials',
24				twilio_sid: sid,
25				twilio_auth: auth,
26				twilio_id: id,
27				_wpnonce: nonceValue
28			},
29			success: function (data) {
30				if (data.success) {
31					if (jQuery('input#twilio' + role_suffix).length) {
32						storeKey(ajaxURL, sid, auth, id, nonceValue, role_suffix);
33						jQuery('#wizard-sid-key' + role_suffix).fadeIn(1000);
34						displayDialog(wp2faTwilio.keyCheckSuccessful);
35					} else {
36						displayDialog(wp2faTwilio.keyCheckSuccessful);
37					}
38					jQuery("input[id^='twilio']").each(function () {
39						jQuery(this).checked = true;
40					});
41					/* Update sortable-list status dot and unlock checkbox */
42					jQuery('[data-check-twilio-2fa]').each(function() {
43						var li = jQuery(this).closest('.wp2fa-sortable-item');
44						if (li.length) {
45							li.removeAttr('data-needs-setup');
46							li.find('.wp2fa-integration-status-dot')
47								.removeClass('wp2fa-status-not-configured')
48								.addClass('wp2fa-status-configured')
49								.attr('title', wp2faTwilio.configured || 'Configured');
50							li.find('.wp2fa-integration-setup-notice').hide();
51						}
52					});
53				} else {
54					displayDialog(data.data);
55				}
56			},
57		});
58	});
59
60	function displayDialog(msg) {
61		if ( typeof wp2faDialog !== 'undefined' ) {
62			wp2faDialog.alert({
63				title: wp2faTwilio.dialogTitle || '',
64				message: msg
65			});
66		} else {
67			alert( msg );
68		}
69	}
70
71	var iti = jQuery("#wp-2fa-phone-twilio").intlTelInput({
72		initialCountry: "auto",
73		geoIpLookup: function (callback) {
74			jQuery.get("//ipinfo.io", function () { }, "jsonp").always(function (resp) {
75				var countryCode = (resp && resp.country) ? resp.country : "";
76				callback(countryCode);
77			});
78		},
79		placeholderNumberType: "MOBILE",
80		utilsScript: wp2faTwilio.utilsUrl,
81	});
82
83	// Checks and validates the given telephone number
84	jQuery(document).on('click', '#twilio_tel', function (e) {
85		e.preventDefault();
86		const errorWrapper = jQuery('#error-msg-twilio');
87		errorWrapper.addClass('hidden');
88
89		if ('' === jQuery('#wp-2fa-phone-twilio').val().trim()) {
90			errorWrapper.html('No number provided');
91			errorWrapper.removeClass('hidden');
92		} else {
93			if (!iti.intlTelInput("isValidNumber")) {
94				errorWrapper.html(wp2faTwilio.errorMap[iti.intlTelInput("getValidationError")]);
95				errorWrapper.removeClass('hidden');
96			} else {
97				var fullNumber = iti.intlTelInput("getNumber");
98
99				registerUserTwilio(fullNumber, jQuery(this).data('nonce'));
100			}
101		}
102	});
103
104	jQuery( document ).on( 'click', '[data-close-2fa-modal]', function( e ) {
105		e.preventDefault();
106		const errorWrapper = jQuery('#error-msg-twilio');
107		errorWrapper.html('');
108		errorWrapper.addClass('hidden');
109
110		const currentSubStep = jQuery('.twilio-step-setting-wrapper');
111		const nextSubStep = jQuery(currentSubStep).nextAll('.twilio-step-setting-wrapper:not(.hidden)').filter(':first');
112		jQuery(currentSubStep).removeClass('hidden');
113		jQuery(currentSubStep).addClass('active');
114		jQuery(nextSubStep).addClass('hidden');
115		jQuery(nextSubStep).removeClass('active');
116	} );
117
118	/**
119	 * Responds with error
120	 * 
121	 * @param {string} text 
122	 */
123	function displayError(text) {
124		if (jQuery('#error-msg-twilio').length) {
125			const errorWrapper = jQuery('#error-msg-twilio');
126			errorWrapper.html(text);
127			errorWrapper.removeClass('hidden');
128		}
129	}
130
131	/**
132	 * Registers Twilio user.
133	 * 
134	 * @param {string} countryCode 
135	 * @param {string} phone 
136	 */
137	function registerUserTwilio(fullNumber, nonce) {
138		const ajaxURL = (typeof wp2faWizardData != "undefined") ? wp2faWizardData.ajaxURL : ajaxurl;
139		jQuery.ajax({
140			url: ajaxURL,
141			data: {
142				action: 'register_user_twilio',
143				phone: fullNumber,
144				_wpnonce: nonce
145			},
146			success: function (data) {
147				if (data.success) {
148					const currentSubStep = jQuery('.twilio-step-setting-wrapper');
149					const nextSubStep = jQuery(currentSubStep).nextAll('.twilio-step-setting-wrapper:not(.active)').filter(':first');
150					jQuery(currentSubStep).removeClass('active');
151					jQuery(currentSubStep).addClass('hidden');
152					jQuery(nextSubStep).addClass('active');
153					jQuery(nextSubStep).removeClass('hidden');
154				} else {
155					displayError(data.data);
156				}
157			},
158			error: function (data) {
159				displayError(data.responseJSON.data[0].message[0]);
160				console.log(data.responseJSON.data[0].message[1]);
161			}
162		});
163	}
164
165	jQuery(document).on('click', '[data-sid-setup-wizard]', function (e) {
166		e.preventDefault();
167		let role_suffix = ('global' === jQuery(this).data('role')) ? '' : '-' + jQuery(this).data('role');
168		jQuery('#wizard-sid-key' + role_suffix).slideDown(600);
169	});
170
171	/**
172	 * Stores the provided Authy API key
173	 * 
174	 * @param {string} ajaxURL 
175	 * @param {string} key 
176	 */
177	function storeKey(ajaxURL, sid, auth, id, nonce, role_suffix) {
178		jQuery.ajax({
179			url: ajaxURL,
180			data: {
181				action: 'store_twilio_api_key',
182				twilio_sid: sid,
183				twilio_auth: auth,
184				twilio_id: id,
185				_wpnonce: nonce
186			},
187			success: function (data) {
188				if (data.success) {
189					jQuery('#wizard-sid-key' + role_suffix).fadeOut(1000);
190					jQuery('#twilio-links' + role_suffix).fadeIn(1000);
191					jQuery('input#twilio' + role_suffix).removeClass('disabled').removeAttr('data-sid-setup-wizard').prop('checked', true);
192					jQuery('.twilio-sub-wrapping').removeClass('disabled');
193
194					jQuery('[for="all-users"], [for="certain-roles-only"]').removeClass('disabled');
195					jQuery('#backup-codes' + role_suffix).removeClass('disabled');
196					jQuery('label[for="backup-codes' + role_suffix + '"]').removeClass('disabled');
197
198					if (jQuery('a.button[name="next_step_setting"]').length) {
199						jQuery('a.button[name="next_step_setting"]').prop('disabled', false);
200						jQuery('a.button[name="next_step_setting"]').removeClass('disabled');
201					}
202
203				} else {
204					alert(data.data);
205				}
206			},
207		});
208	}
209
210	jQuery(document).on('click', '[data-api-remove-twilio]', function (e) {
211		e.preventDefault();
212		const nonceValue = jQuery(this).attr('data-nonce');
213		let role_suffix = ('' === jQuery(this).data('role')) ? '' : jQuery(this).data('role');
214		removeSettings(nonceValue, role_suffix);
215	});
216
217	/**
218	 * Removes the settings
219	 * 
220	 * @param {string} nonce 
221	 */
222	function removeSettings(nonce, role_suffix) {
223		const ajaxURL = (typeof wp2faWizardData != "undefined") ? wp2faWizardData.ajaxURL : ajaxurl;
224
225		jQuery.ajax({
226			url: ajaxURL,
227			data: {
228				action: 'remove_wp2fa_twilio_settings',
229				_wpnonce: nonce
230			},
231			success: function (data) {
232				if (data.success) {
233					jQuery('#wizard-sid-key' + role_suffix).fadeOut(1000);
234					jQuery('#twilio-links' + role_suffix).fadeOut(1000);
235					jQuery('input#twilio' + role_suffix).addClass('disabled').attr('data-sid-setup-wizard', '').prop('checked', false);
236					jQuery('#wp-2fa-twilio-sid' + role_suffix).val('');
237					jQuery('#wp-2fa-twilio-auth' + role_suffix).val('');
238					jQuery('#wp-2fa-twilio-id' + role_suffix).val('');
239				} else {
240					alert(data.data);
241				}
242			},
243		});
244	}
245
246	/**
247	 * Shows verification messages
248	 * 
249	 * @param {string} type 
250	 * @param {string} text 
251	 */
252	function verificationResponse(type, text) {
253		let wrapper = jQuery('.verification-response-twilio');
254
255		if ('error' === type) {
256			wrapper.html('<span style="color:red">' + text + '</span>');
257		} else {
258			wrapper.html('<span style="color:green">' + text + '</span>');
259		}
260		wrapper.removeClass('hidden');
261	}
262
263	// Twilio validation button
264	jQuery(document).on('click', 'a[data-validate-twilio-ajax]', function (e) {
265		e.preventDefault();
266
267		tokenField = jQuery('#twilio-token');
268		if ('' === tokenField.val().trim()) {
269			verificationResponse('error', 'No token provided');
270		} else {
271			let isValid = false;
272			let regex = /^[0-9\s]*$/;
273			isValid = regex.test(tokenField.val());
274			if (!isValid) {
275				verificationResponse('error', 'Invalid token format');
276			} else {
277				let token = tokenField.val();
278				let nonce = jQuery(this).data('nonce');
279
280				checkToken(token, nonce);
281			}
282		}
283	});
284
285	/**
286	 * Checks token against the Authy API
287	 * 
288	 * @param {string} token 
289	 * @param {string} nonce 
290	 */
291	function checkToken(token, nonce) {
292		const ajaxURL = (typeof wp2faWizardData != "undefined") ? wp2faWizardData.ajaxURL : ajaxurl;
293		let closeButton = jQuery('button[data-close-2fa-modal');
294		let setMethod = (closeButton.length) ? true : false;
295		let fullNumber = iti.intlTelInput("getNumber");
296
297		jQuery.ajax({
298			url: ajaxURL,
299			data: {
300				action: 'check_twilio_token',
301				token: token,
302				phone: fullNumber,
303				method: setMethod,
304				_wpnonce: nonce
305			},
306			success: function (data) {
307				if (data.success) {
308					if (jQuery('a[data-validate-twilio-ajax]').length) {
309						// Called from the profile setup - close the wizard
310
311						let nextSubStep = jQuery('#wp-2fa-wizard-config-backup-codes');
312
313						if (jQuery('#wp-2fa-wizard-backup-methods').length) {
314							nextSubStep = jQuery('#wp-2fa-wizard-backup-methods');
315						} else if (jQuery('#wp-2fa-wizard-email-backup-selected').length) {
316							nextSubStep = jQuery('#wp-2fa-wizard-email-backup-selected');
317						}
318
319						jQuery(this).parent().parent().find('.active').not('.step-setting-wrapper').removeClass('active');
320						jQuery('.wizard-step.active').removeClass('active');
321						jQuery(nextSubStep).addClass('active');
322
323						jQuery(document).on('click', '#select-backup-method', function (e) {
324							e.preventDefault();
325							var backupRadio = jQuery("input[name=backup_method_select]:checked");
326
327							jQuery('.wizard-step.active').removeClass('active');
328							jQuery('#' + backupRadio.data('step')).addClass('active');
329						});
330
331						jQuery(document).on('click', '[name="save_step"], [data-close-2fa-modal]', function () {
332							if ('reLogin' in wp2faWizardData &&
333								wp2faWizardData.reLoginEnabled == jQuery.trim(wp2faWizardData.reLogin)) {
334								jQuery.ajax({
335									type: 'POST',
336									url: wp2faData.ajaxURL,
337									data: {
338										action: 'custom_ajax_logout',
339										_wpnonce: nonceValue,
340									},
341									success: function (r) {
342										if ('loginUrl' in wp2faWizardData && '' != jQuery.trim(wp2faWizardData.loginUrl)) {
343											window.location.replace(wp2faWizardData.loginUrl);
344										} else {
345											window.location.replace('/wp-login.php');
346										}
347									}
348								});
349							} else {
350								if ('redirectToUrl' in wp2faWizardData &&
351									'' != jQuery.trim(wp2faWizardData.redirectToUrl)) {
352									window.location.replace(wp2faWizardData.redirectToUrl);
353								} else {
354									removeShowParam();
355								}
356							}
357						});
358					}
359				} else {
360					alert(data.data);
361				}
362			},
363			error: function (data) {
364				verificationResponse('error', data.responseJSON.data[0].message);
365			}
366		});
367
368	}
369
370}(jQuery, window));

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.