PluginProbe
Authorizer / 3.15.2
Authorizer v3.15.2
3.15.3 3.15.2 3.15.1 3.15.0 3.14.3 3.14.4 3.14.2 3.14.1 2.8.1 2.8.2 2.8.3 2.8.4 2.8.5 2.8.6 2.8.7 2.8.8 2.9.0 2.9.1 2.9.10 2.9.11 2.9.12 2.9.13 2.9.2 2.9.3 2.9.6 All 126 releases
authorizer / js / authorizer.js

authorizer.js in Authorizer 3.15.2, at js/authorizer.js

1,514 lines 69.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /**
2 * UI wiring for Authorizer Settings page.
3 */
4
5 /* global window, document, setTimeout, sessionStorage, ajaxurl, authL10n, history */
6 ( function( $ ) {
7
8 // Milliseconds for jQuery UI animations to complete.
9 var animationSpeed = 300;
10 // Milliseconds for shake animation (reject email address) to complete.
11 var shakeSpeed = 600;
12
13 /**
14 * Wiring and UI for Authorizer Settings page.
15 */
16
17 // Switch between pages in the Approved User list.
18 // @calls php wp_ajax_refresh_approved_user_list.
19 function refreshApprovedUserList( currentPage, searchTerm ) {
20 var $list = $( '#list_auth_settings_access_users_approved' );
21 var $spinner = $( '<span class="spinner is-active"></span>' ).css({
22 position: 'relative',
23 top: '40%',
24 left: '-240px',
25 });
26 var $overlay = $( '<div id="list_auth_settings_access_users_approved_overlay"></div>' ).css({
27 'background-color': '#f1f1f1',
28 'z-index': 1,
29 opacity: 0.8,
30 position: 'absolute',
31 top: $list.position().top + parseInt( $list.css( 'margin-top' ) ),
32 left: $list.position().left,
33 width: $list.width(),
34 height: $list.height(),
35 });
36 $overlay.append( $spinner );
37
38 // Show overlay and wait cursor.
39 $list.after( $overlay );
40 $( 'html' ).addClass( 'busy' );
41
42 $.post( ajaxurl, {
43 action: 'refresh_approved_user_list',
44 nonce: $( '#nonce_save_auth_settings' ).val(),
45 is_network_admin: authL10n.is_network_admin, // eslint-disable-line camelcase
46 paged: currentPage,
47 search: searchTerm,
48 }, function( response ) {
49 if ( response.success ) {
50 // Update user list and total user and page count.
51 $( '#list_auth_settings_access_users_approved' ).html( response.html );
52 $( '.displaying-num' ).html( response.total_users_html );
53 $( '.total-pages' ).html( response.total_pages_html );
54
55 // Adjust our current page if the query changed the total page count.
56 if ( currentPage > response.total_pages ) {
57 currentPage = response.total_pages;
58 }
59
60 // Update pager elements.
61 refreshApprovedUserPager( currentPage );
62
63 // Update querystring with new paged param value (but don't reload the page).
64 if ( history.pushState ) {
65 var url = window.location.href;
66 url = updateQueryStringParameter( url, 'paged', currentPage );
67 url = updateQueryStringParameter( url, 'search', searchTerm );
68 window.history.pushState( { path: url }, '', url );
69 }
70 }
71 // Remove overlay and wait cursor.
72 $overlay.remove();
73 $( 'html' ).removeClass( 'busy' );
74 }).fail( function() {
75 // Remove overlay and wait cursor.
76 $overlay.remove();
77 $( 'html' ).removeClass( 'busy' );
78 });
79 }
80
81 // Update the pager elements when changing pages.
82 function refreshApprovedUserPager( currentPage ) {
83 var totalPages = parseInt( $( '.total-pages' ).first().text().replace( /[^0-9]/g, '' ), 10 ) || 1;
84
85 // If total number of pages changed (because a search filter reduced it), make
86 // sure current page is not larger than it.
87 if ( currentPage > totalPages ) {
88 currentPage = totalPages;
89 }
90 if ( currentPage < 1 ) {
91 currentPage = 1;
92 }
93 if ( totalPages < 1 ) {
94 totalPages = 1;
95 }
96
97 // Update current page text input.
98 $( '#current-page-selector' ).val( currentPage );
99
100 // Update current page span.
101 $( '#table-paging .current-page-text' ).text( currentPage );
102
103 // Update first page button.
104 var $first = $( '.first-page' );
105 if ( $first.is( 'a' ) && currentPage <= 1 ) {
106 $first.replaceWith( '<span class="button disabled first-page tablenav-pages-navspan" aria-hidden="true">&laquo;</span>' );
107 } else if ( $first.is( 'span' ) && currentPage > 1 ) {
108 $first.replaceWith( '<a class="button first-page" href="' + updateQueryStringParameter( window.location.href, 'paged', '1' ) + '"><span class="screen-reader-text">' + authL10n.first_page + '</span><span aria-hidden="true">&laquo;</span></a>' );
109 }
110
111 // Update prev page button.
112 var $prev = $( '.prev-page' );
113 if ( $prev.is( 'a' ) && currentPage <= 1 ) {
114 $prev.replaceWith( '<span class="button disabled prev-page tablenav-pages-navspan" aria-hidden="true">&lsaquo;</span>' );
115 } else if ( currentPage > 1 ) {
116 $prev.replaceWith( '<a class="button prev-page" href="' + updateQueryStringParameter( window.location.href, 'paged', currentPage - 1 ) + '"><span class="screen-reader-text">' + authL10n.prev_page + '</span><span aria-hidden="true">&lsaquo;</span></a>' );
117 }
118
119 // Update next button.
120 var $next = $( '.next-page' );
121 if ( $next.is( 'a' ) && currentPage >= totalPages ) {
122 $next.replaceWith( '<span class="button disabled next-page tablenav-pages-navspan" aria-hidden="true">&rsaquo;</span>' );
123 } else if ( currentPage < totalPages ) {
124 $next.replaceWith( '<a class="button next-page" href="' + updateQueryStringParameter( window.location.href, 'paged', currentPage + 1 ) + '"><span class="screen-reader-text">' + authL10n.next_page + '</span><span aria-hidden="true">&rsaquo;</span></a>' );
125 }
126
127 // Update last button.
128 var $last = $( '.last-page' );
129 if ( $last.is( 'a' ) && currentPage >= totalPages ) {
130 $last.replaceWith( '<span class="button disabled last-page tablenav-pages-navspan" aria-hidden="true">&raquo;</span>' );
131 } else if ( $last.is( 'span' ) && currentPage < totalPages ) {
132 $last.replaceWith( '<a class="button last-page" href="' + updateQueryStringParameter( window.location.href, 'paged', totalPages ) + '"><span class="screen-reader-text">' + authL10n.next_page + '</span><span aria-hidden="true">&raquo;</span></a>' );
133 }
134 }
135
136 // Make changes to one of the user lists (pending, approved, blocked) via ajax.
137 // @calls php wp_ajax_update_auth_user.
138 function updateAuthUser( caller, setting, usersToEdit ) {
139 var accessUsersPending = [],
140 accessUsersApproved = [],
141 accessUsersBlocked = [],
142 nonce = $( '#nonce_save_auth_settings' ).val();
143
144 // Defaults:
145 // setting = 'access_users_pending' or 'access_users_approved' or 'access_users_blocked',
146 // usersToEdit = [
147 // {
148 // email: 'johndoe@example.com',
149 // role: 'subscriber',
150 // date_added: 'Jun 2014',
151 // edit_action: 'add' or 'remove' or 'change_role',
152 // local_user: true or false,
153 // multisite_user: true or false,
154 // }, {
155 // ...
156 // }
157 // ]
158 setting = typeof setting !== 'undefined' ? setting : 'none';
159
160 // If we are only editing a single user, make that user the only item in the array.
161 usersToEdit = typeof usersToEdit !== 'undefined' ? usersToEdit : [];
162 if ( ! Array.isArray( usersToEdit ) ) {
163 usersToEdit = [ usersToEdit ];
164 }
165
166 // Enable wait cursor.
167 $( 'html' ).addClass( 'busy' );
168
169 // Disable button (prevent duplicate clicks).
170 $( caller ).attr( 'disabled', 'disabled' );
171
172 // Enable spinner by element that triggered this event (caller).
173 var $row = $( caller ).closest( 'li' );
174 if ( $row.length > 0 ) {
175 var $spinner = $( '<span class="spinner is-active"></span>' ).css({
176 position: 'absolute',
177 top: $row.position().top,
178 left: $row.position().left + $row.width(),
179 });
180 $row.append( $spinner );
181 }
182
183 // Grab the value of the setting we are saving.
184 if ( setting === 'access_users_pending' ) {
185 accessUsersPending = usersToEdit;
186 } else if ( setting === 'access_users_approved' ) {
187 accessUsersApproved = usersToEdit;
188 } else if ( setting === 'access_users_blocked' ) {
189 accessUsersBlocked = usersToEdit;
190 }
191
192 $.post( ajaxurl, {
193 action: 'update_auth_user',
194 setting: setting,
195 access_users_pending: accessUsersPending, // eslint-disable-line camelcase
196 access_users_approved: accessUsersApproved, // eslint-disable-line camelcase
197 access_users_blocked: accessUsersBlocked, // eslint-disable-line camelcase
198 nonce: nonce,
199 }, function( response ) {
200 // Server responded, but if success isn't true it failed to save.
201 var succeeded = response.success;
202 var spinnerText = succeeded ? authL10n.saved + '.' : '<span class="attention">' + authL10n.failed + '.</span>';
203 var spinnerWait = succeeded ? 500 : 2000;
204
205 // Remove any new user entries that were rejected by the server.
206 if ( response.invalid_emails.length > 0 ) {
207 for ( var i = 0; i < response.invalid_emails.length; i++ ) {
208 var duplicateEmail = response.invalid_emails[i];
209 $( 'li.new-user .auth-email[value="' + duplicateEmail + '"]' )
210 .siblings( '.spinner' ).addClass( 'duplicate' ).append( '<span class="spinner-text"><span class="attention">' + authL10n.duplicate + '.</span></span>' )
211 .parent().fadeOut( 2000, function() { $( this ).remove(); }); // jshint ignore:line
212 }
213 }
214
215 // Show message ('Saved', 'Failed', or 'Saved, removing duplicates').
216 $( 'form .spinner:not(:has(.spinner-text)):not(.duplicate)' ).append( '<span class="spinner-text">' + spinnerText + '</span>' ).delay( spinnerWait ).hide( animationSpeed, function() {
217 $( this ).remove();
218 });
219 $( caller ).removeAttr( 'disabled' );
220
221 // Disable wait cursor.
222 $( 'html' ).removeClass( 'busy' );
223 }).fail( function() {
224 // Fail fires if the server doesn't respond or responds with 500 codes
225 var succeeded = false;
226 var spinnerText = succeeded ? authL10n.saved + '.' : '<span class="attention">' + authL10n.failed + '.</span>';
227 var spinnerWait = succeeded ? 500 : 2000;
228 $( 'form .spinner:not(:has(.spinner-text))' ).append( '<span class="spinner-text">' + spinnerText + '</span>' ).delay( spinnerWait ).hide( animationSpeed, function() {
229 $( this ).remove();
230 });
231 $( caller ).removeAttr( 'disabled' );
232
233 // Disable wait cursor.
234 $( 'html' ).removeClass( 'busy' );
235 });
236 }
237
238
239 // Hide or show (with overlay) the multisite settings based on the "multisite override" setting.
240 function hideMultisiteSettingsIfDisabled() {
241 if ( $( '#auth_settings_multisite_override' ).length === 0 ) {
242 return;
243 }
244
245 var settings = $( '#auth_multisite_settings' );
246 var overlay = $( '#auth_multisite_settings_disabled_overlay' );
247
248 if ( $( '#auth_settings_multisite_override' ).is( ':checked' ) ) {
249 overlay.hide( animationSpeed );
250 } else {
251 overlay.css({
252 'background-color': '#f1f1f1',
253 'z-index': 1,
254 opacity: 0.8,
255 position: 'absolute',
256 top: settings.position().top,
257 left: settings.position().left,
258 width: settings.width(),
259 height: settings.height() + 50,
260 });
261 overlay.show();
262 }
263 }
264
265 // Helper function to remove duplicate entries from an array of strings.
266 function removeDuplicatesFromArrayOfStrings( arrayOfStrings ) {
267 var seen = {};
268 return arrayOfStrings.filter( function( item ) {
269 return seen.hasOwnProperty( item ) ? false : ( seen[item] = true );
270 });
271 }
272
273 // Helper function to hide/show wordpress option
274 function animateOption( action, option ) {
275 if ( action === 'show' ) {
276 option.fadeIn( animationSpeed );
277 $( 'th, td', option ).removeClass( 'hide-animate hide-no-animate' );
278 } else if ( action === 'hide' ) {
279 option.fadeOut( animationSpeed );
280 $( 'td, th', option ).addClass( 'hide-animate' );
281 } else if ( action === 'hide_immediately' ) {
282 option.hide();
283 $( 'td, th', option ).addClass( 'hide-no-animate' );
284 }
285 }
286
287 // Helper function to grab a querystring param value by name
288 function getParameterByName( needle, haystack ) {
289 needle = needle.replace( /[\[]/, '\\\[').replace(/[\]]/, '\\\]' ); // eslint-disable-line no-useless-escape
290 var regex = new RegExp( '[\\?&]' + needle + '=([^&#]*)' );
291 var results = regex.exec( haystack );
292 if ( results === null ) {
293 return '';
294 } else {
295 return decodeURIComponent( results[1].replace( /\+/g, ' ' ) );
296 }
297 }
298
299 // Helper function to return a short date (e.g., Jul 2013) for today's date
300 function getShortDate( date ) {
301 date = typeof date !== 'undefined' ? date : new Date();
302 var month = '';
303 switch ( date.getMonth() ) {
304 case 0: month = 'Jan'; break;
305 case 1: month = 'Feb'; break;
306 case 2: month = 'Mar'; break;
307 case 3: month = 'Apr'; break;
308 case 4: month = 'May'; break;
309 case 5: month = 'Jun'; break;
310 case 6: month = 'Jul'; break;
311 case 7: month = 'Aug'; break;
312 case 8: month = 'Sep'; break;
313 case 9: month = 'Oct'; break;
314 case 10: month = 'Nov'; break;
315 case 11: month = 'Dec'; break;
316 }
317 return month + ' ' + date.getFullYear();
318 }
319
320 // Helper function to grab a querystring value
321 function getQuerystringValuesByKey( key ) {
322 var re = new RegExp( '(?:\\?|&)' + key + '=(.*?)(?=&|$)', 'gi' );
323 var matchingValues = [];
324 var match;
325 while ( ( match = re.exec( document.location.search ) ) !== null ) {
326 matchingValues.push( match[1] );
327 }
328 return matchingValues;
329 }
330
331 // Helper function to check if an email address is valid. If allowWildcardEmail
332 // is true, then any string starting with an @ is valid.
333 function validEmail( email, allowWildcardEmail ) {
334 allowWildcardEmail = typeof allowWildcardEmail !== 'undefined' ? allowWildcardEmail : false;
335 var re = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
336 return email.length > 0 && ( re.test( email ) || email.startsWith( '@' ) );
337 }
338
339 // Helper function to set or update a querystring value.
340 function updateQueryStringParameter( uri, key, value ) {
341 // Remove the hash before operating on the URI.
342 var i = uri.indexOf( '#' );
343 var hash = i === -1 ? '' : uri.substr( i );
344 uri = i === -1 ? uri : uri.substr( 0, i );
345
346 var re = new RegExp( '([?&])' + key + '=.*?(&|$)', 'i' );
347 var separator = uri.indexOf( '?' ) !== -1 ? '&' : '?';
348
349 if ( ! value ) {
350 // Remove key-value pair if empty.
351 uri = uri.replace( new RegExp( '([?&]?)' + key + '=[^&]*', 'i' ), '' );
352 if ( uri.slice( -1 ) === '?' ) {
353 uri = uri.slice( 0, -1 );
354 }
355 // Replace first occurrence of & by ? if no ? is present.
356 if ( uri.indexOf( '?' ) === -1 ) {
357 uri = uri.replace( /&/, '?' );
358 }
359 } else if ( uri.match( re ) ) {
360 uri = uri.replace( re, '$1' + key + '=' + value + '$2' );
361 } else {
362 uri = uri + separator + key + '=' + value;
363 }
364 return uri + hash;
365 }
366
367
368 /**
369 * Wire up actions when document has loaded.
370 */
371
372
373 $( document ).ready( function() {
374 // Grab references to form elements that we will show/hide on page load
375 /* eslint-disable camelcase */
376 var auth_settings_access_role_receive_pending_emails = $( '#auth_settings_access_role_receive_pending_emails' ).closest( 'tr' );
377 var auth_settings_access_users_receive_pending_emails = $( '#auth_settings_access_users_receive_pending_emails' ).closest( 'tr' );
378 var auth_settings_access_pending_redirect_to_message = $( '#wp-auth_settings_access_pending_redirect_to_message-wrap' ).closest( 'tr' );
379 var auth_settings_access_blocked_redirect_to_message = $( '#wp-auth_settings_access_blocked_redirect_to_message-wrap' ).closest( 'tr' );
380 var auth_settings_access_should_email_approved_users = $( '#auth_settings_access_should_email_approved_users' ).closest( 'tr' );
381 var auth_settings_access_email_approved_users_subject = $( '#auth_settings_access_email_approved_users_subject' ).closest( 'tr' );
382 var auth_settings_access_email_approved_users_body = $( '#wp-auth_settings_access_email_approved_users_body-wrap' ).closest( 'tr' );
383 var auth_settings_access_public_pages = $( '#auth_settings_access_public_pages' ).closest( 'tr' );
384 var auth_settings_access_redirect_to_login = $( '#radio_auth_settings_access_redirect_to_login' ).closest( 'tr' );
385 var auth_settings_access_public_warning = $( '#radio_auth_settings_access_public_warning' ).closest( 'tr' );
386 var auth_settings_access_redirect_to_message = $( '#wp-auth_settings_access_redirect_to_message-wrap' ).closest( 'tr' );
387 var auth_settings_external_oauth2_auto_login = $( '#auth_settings_oauth2_auto_login' ).closest( 'tr' );
388 var auth_settings_external_oauth2_num_servers = $( '#auth_settings_oauth2_num_servers' ).closest( 'tr' );
389 var auth_settings_external_oauth2_servers = [];
390 // OAuth2 settings below are for the first configured OAuth2 server.
391 auth_settings_external_oauth2_servers.push( {
392 provider: $( '#auth_settings_oauth2_provider' ).closest( 'tr' ),
393 custom_label: $( '#auth_settings_oauth2_custom_label' ).closest( 'tr' ),
394 clientid: $( '#auth_settings_oauth2_clientid' ).closest( 'tr' ),
395 clientsecret: $( '#auth_settings_oauth2_clientsecret' ).closest( 'tr' ),
396 hosteddomain: $( '#auth_settings_oauth2_hosteddomain' ).closest( 'tr' ),
397 tenant_id: $( '#auth_settings_oauth2_tenant_id' ).closest( 'tr' ),
398 url_authorize: $( '#auth_settings_oauth2_url_authorize' ).closest( 'tr' ),
399 url_token: $( '#auth_settings_oauth2_url_token' ).closest( 'tr' ),
400 url_resource: $( '#auth_settings_oauth2_url_resource' ).closest( 'tr' ),
401 attr_username: $( '#auth_settings_oauth2_attr_username' ).closest( 'tr' ),
402 attr_email: $( '#auth_settings_oauth2_attr_email' ).closest( 'tr' ),
403 attr_first_name: $( '#auth_settings_oauth2_attr_first_name' ).closest( 'tr' ),
404 attr_last_name: $( '#auth_settings_oauth2_attr_last_name' ).closest( 'tr' ),
405 attr_update_on_login: $( '#auth_settings_oauth2_attr_update_on_login' ).closest( 'tr' ),
406 link_on_username: $( '#auth_settings_oauth2_link_on_username' ).closest( 'tr' ),
407 } );
408 // OAuth2 settings below are for any additional OAuth2 servers configured (up to 20).
409 for ( var i = 2; i <= parseInt( $( '#auth_settings_oauth2_num_servers' ).val() ) && i <= 20; i++ ) {
410 auth_settings_external_oauth2_servers.push( {
411 provider: $( '#auth_settings_oauth2_provider_' + i ).closest( 'tr' ),
412 custom_label: $( '#auth_settings_oauth2_custom_label_' + i ).closest( 'tr' ),
413 clientid: $( '#auth_settings_oauth2_clientid_' + i ).closest( 'tr' ),
414 clientsecret: $( '#auth_settings_oauth2_clientsecret_' + i ).closest( 'tr' ),
415 hosteddomain: $( '#auth_settings_oauth2_hosteddomain_' + i ).closest( 'tr' ),
416 tenant_id: $( '#auth_settings_oauth2_tenant_id_' + i ).closest( 'tr' ),
417 url_authorize: $( '#auth_settings_oauth2_url_authorize_' + i ).closest( 'tr' ),
418 url_token: $( '#auth_settings_oauth2_url_token_' + i ).closest( 'tr' ),
419 url_resource: $( '#auth_settings_oauth2_url_resource_' + i ).closest( 'tr' ),
420 attr_username: $( '#auth_settings_oauth2_attr_username_' + i ).closest( 'tr' ),
421 attr_email: $( '#auth_settings_oauth2_attr_email_' + i ).closest( 'tr' ),
422 attr_first_name: $( '#auth_settings_oauth2_attr_first_name_' + i ).closest( 'tr' ),
423 attr_last_name: $( '#auth_settings_oauth2_attr_last_name_' + i ).closest( 'tr' ),
424 attr_update_on_login: $( '#auth_settings_oauth2_attr_update_on_login_' + i ).closest( 'tr' ),
425 link_on_username: $( '#auth_settings_oauth2_link_on_username_' + i ).closest( 'tr' ),
426 } );
427 }
428 var auth_settings_external_google_clientid = $( '#auth_settings_google_clientid' ).closest( 'tr' );
429 var auth_settings_external_google_clientsecret = $( '#auth_settings_google_clientsecret' ).closest( 'tr' );
430 var auth_settings_external_google_hosteddomain = $( '#auth_settings_google_hosteddomain' ).closest( 'tr' );
431 var auth_settings_external_cas_auto_login = $( '#auth_settings_cas_auto_login' ).closest( 'tr' );
432 var auth_settings_external_cas_num_servers = $( '#auth_settings_cas_num_servers' ).closest( 'tr' );
433 var auth_settings_external_cas_servers = [];
434 // CAS settings below are for the first configured CAS server.
435 auth_settings_external_cas_servers.push( {
436 custom_label: $( '#auth_settings_cas_custom_label' ).closest( 'tr' ),
437 host: $( '#auth_settings_cas_host' ).closest( 'tr' ),
438 port: $( '#auth_settings_cas_port' ).closest( 'tr' ),
439 path: $( '#auth_settings_cas_path' ).closest( 'tr' ),
440 method: $( '#auth_settings_cas_method' ).closest( 'tr' ),
441 version: $( '#auth_settings_cas_version' ).closest( 'tr' ),
442 attr_email: $( '#auth_settings_cas_attr_email' ).closest( 'tr' ),
443 attr_first_name: $( '#auth_settings_cas_attr_first_name' ).closest( 'tr' ),
444 attr_last_name: $( '#auth_settings_cas_attr_last_name' ).closest( 'tr' ),
445 attr_update_on_login: $( '#auth_settings_cas_attr_update_on_login' ).closest( 'tr' ),
446 link_on_username: $( '#auth_settings_cas_link_on_username' ).closest( 'tr' ),
447 } );
448 // CAS settings below are for any additional CAS servers configured (up to 10).
449 for ( var i = 2; i <= parseInt( $( '#auth_settings_cas_num_servers' ).val() ) && i <= 10; i++ ) {
450 auth_settings_external_cas_servers.push( {
451 custom_label: $( '#auth_settings_cas_custom_label_' + i ).closest( 'tr' ),
452 host: $( '#auth_settings_cas_host_' + i ).closest( 'tr' ),
453 port: $( '#auth_settings_cas_port_' + i ).closest( 'tr' ),
454 path: $( '#auth_settings_cas_path_' + i ).closest( 'tr' ),
455 method: $( '#auth_settings_cas_method_' + i ).closest( 'tr' ),
456 version: $( '#auth_settings_cas_version_' + i ).closest( 'tr' ),
457 attr_email: $( '#auth_settings_cas_attr_email_' + i ).closest( 'tr' ),
458 attr_first_name: $( '#auth_settings_cas_attr_first_name_' + i ).closest( 'tr' ),
459 attr_last_name: $( '#auth_settings_cas_attr_last_name_' + i ).closest( 'tr' ),
460 attr_update_on_login: $( '#auth_settings_cas_attr_update_on_login_' + i ).closest( 'tr' ),
461 link_on_username: $( '#auth_settings_cas_link_on_username_' + i ).closest( 'tr' ),
462 } );
463 }
464 var auth_settings_external_ldap_host = $( '#auth_settings_ldap_host' ).closest( 'tr' );
465 var auth_settings_external_ldap_port = $( '#auth_settings_ldap_port' ).closest( 'tr' );
466 var auth_settings_external_ldap_search_base = $( '#auth_settings_ldap_search_base' ).closest( 'tr' );
467 var auth_settings_external_ldap_search_filter = $( '#auth_settings_ldap_search_filter' ).closest( 'tr' );
468 var auth_settings_external_ldap_uid = $( '#auth_settings_ldap_uid' ).closest( 'tr' );
469 var auth_settings_external_ldap_attr_email = $( '#auth_settings_ldap_attr_email' ).closest( 'tr' );
470 var auth_settings_external_ldap_user = $( '#auth_settings_ldap_user' ).closest( 'tr' );
471 var auth_settings_external_ldap_password = $( '#auth_settings_ldap_password' ).closest( 'tr' );
472 var auth_settings_external_ldap_tls = $( '#auth_settings_ldap_tls' ).closest( 'tr' );
473 var auth_settings_external_ldap_lostpassword_url = $( '#auth_settings_ldap_lostpassword_url' ).closest( 'tr' );
474 var auth_settings_external_ldap_attr_first_name = $( '#auth_settings_ldap_attr_first_name' ).closest( 'tr' );
475 var auth_settings_external_ldap_attr_last_name = $( '#auth_settings_ldap_attr_last_name' ).closest( 'tr' );
476 var auth_settings_external_ldap_attr_update_on_login = $( '#auth_settings_ldap_attr_update_on_login' ).closest( 'tr' );
477 var auth_settings_external_ldap_test_user = $( '#auth_settings_ldap_test_user' ).closest( 'tr' );
478 var auth_settings_advanced_disable_wp_login_bypass_usernames = $( '#auth_settings_advanced_disable_wp_login_bypass_usernames' ).closest( 'tr' );
479 /* eslint-enable */
480
481 // Hide settings unless "Only approved users" is checked
482 if ( ! $( '#radio_auth_settings_access_who_can_login_approved_users' ).is( ':checked' ) ) {
483 animateOption( 'hide_immediately', auth_settings_access_role_receive_pending_emails );
484 animateOption( 'hide_immediately', auth_settings_access_users_receive_pending_emails );
485 animateOption( 'hide_immediately', auth_settings_access_pending_redirect_to_message );
486 animateOption( 'hide_immediately', auth_settings_access_blocked_redirect_to_message );
487 animateOption( 'hide_immediately', auth_settings_access_should_email_approved_users );
488 }
489
490 // Hide Welcome email body/subject options if "Send welcome email" is off.
491 if ( ! $( '#auth_settings_access_should_email_approved_users' ).is( ':checked' ) ) {
492 animateOption( 'hide_immediately', auth_settings_access_email_approved_users_subject );
493 animateOption( 'hide_immediately', auth_settings_access_email_approved_users_body );
494 }
495
496 // On load: Show/hide public access options if everyone can see site
497 if ( ! $( '#radio_auth_settings_access_who_can_view_logged_in_users' ).is( ':checked' ) ) {
498 animateOption( 'hide_immediately', auth_settings_access_public_pages );
499 animateOption( 'hide_immediately', auth_settings_access_redirect_to_login );
500 animateOption( 'hide_immediately', auth_settings_access_public_warning );
501 animateOption( 'hide_immediately', auth_settings_access_redirect_to_message );
502 }
503
504 // Hide External Service tabs if provider is unchecked.
505 $( '.nav-tab-wrapper .nav-tab-external_oauth2' ).toggle( $( '#auth_settings_oauth2' ).is( ':checked' ) );
506 $( '.nav-tab-wrapper .nav-tab-external_oidc' ).toggle( $( '#auth_settings_oidc' ).is( ':checked' ) );
507 $( '.nav-tab-wrapper .nav-tab-external_google' ).toggle( $( '#auth_settings_google' ).is( ':checked' ) );
508 $( '.nav-tab-wrapper .nav-tab-external_cas' ).toggle( $( '#auth_settings_cas' ).is( ':checked' ) );
509 $( '.nav-tab-wrapper .nav-tab-external_ldap' ).toggle( $( '#auth_settings_ldap' ).is( ':checked' ) );
510
511 // Hide some OAuth2 options based on current settings.
512 auth_settings_external_oauth2_servers.forEach( function( server ) {
513 // Hide OAuth2 generic options if OAuth2 provider is unchecked or generic isn't chosen.
514 if ( 'generic' !== server.provider.find( 'select' ).val() ) {
515 animateOption( 'hide_immediately', server.url_authorize );
516 animateOption( 'hide_immediately', server.url_token );
517 animateOption( 'hide_immediately', server.url_resource );
518 animateOption( 'hide_immediately', server.attr_username );
519 animateOption( 'hide_immediately', server.attr_email );
520 animateOption( 'hide_immediately', server.attr_first_name );
521 animateOption( 'hide_immediately', server.attr_last_name );
522 animateOption( 'hide_immediately', server.attr_update_on_login );
523 }
524 // Hide OAuth2 Tenant ID if OAuth2 provider is unchecked or azure isn't chosen.
525 if ( 'azure' !== server.provider.find( 'select' ).val() ) {
526 animateOption( 'hide_immediately', server.tenant_id );
527 }
528 } );
529
530 // Hide Bypass Usernames if Disable WordPress logins is unchecked.
531 if ( ! $( '#auth_settings_advanced_disable_wp_login' ).is( ':checked' ) ) {
532 animateOption( 'hide_immediately', auth_settings_advanced_disable_wp_login_bypass_usernames );
533 }
534
535 // Event handler: Hide "Handle unauthorized visitors" option if access is granted to "Everyone"
536 $( 'input[name="auth_settings[access_who_can_login]"]' ).on( 'change', function() {
537 // Hide settings unless "Only approved users" is checked
538 var action = $( '#radio_auth_settings_access_who_can_login_approved_users' ).is( ':checked' ) ? 'show' : 'hide';
539 animateOption( action, auth_settings_access_role_receive_pending_emails );
540 animateOption( action, auth_settings_access_users_receive_pending_emails );
541 animateOption( action, auth_settings_access_pending_redirect_to_message );
542 animateOption( action, auth_settings_access_blocked_redirect_to_message );
543 animateOption( action, auth_settings_access_should_email_approved_users );
544 action = action === 'show' && $( '#auth_settings_access_should_email_approved_users' ).is( ':checked' ) ? 'show' : 'hide_immediately';
545 animateOption( action, auth_settings_access_email_approved_users_subject );
546 animateOption( action, auth_settings_access_email_approved_users_body );
547 });
548
549 // Event handler: Hide Welcome email body/subject options if "Send welcome email" is off.
550 $( 'input[name="auth_settings[access_should_email_approved_users]"]' ).on( 'change', function() {
551 var action = $( this ).is( ':checked' ) ? 'show' : 'hide';
552 animateOption( action, auth_settings_access_email_approved_users_subject );
553 animateOption( action, auth_settings_access_email_approved_users_body );
554 });
555
556 // Event handler: Hide "Handle unauthorized visitors" option if access is granted to "Everyone"
557 $( 'input[name="auth_settings[access_who_can_view]"]' ).on( 'change', function() {
558 var action = $( '#radio_auth_settings_access_who_can_view_everyone' ).is( ':checked' ) ? 'hide' : 'show';
559 animateOption( action, auth_settings_access_redirect_to_login );
560 animateOption( action, auth_settings_access_redirect_to_message );
561 animateOption( action, auth_settings_access_public_pages );
562 animateOption( action, auth_settings_access_public_warning );
563 });
564
565 // Event handler: Show/hide OAuth2 tab based on checkbox.
566 $( 'input[name="auth_settings[oauth2]"]' ).on( 'change', function() {
567 $( '.nav-tab-wrapper .nav-tab-external_oauth2' ).toggle( $( this ).is( ':checked' ) );
568 });
569
570 // Event handler: Show/hide OAuth2 generic/azure options based on provider.
571 auth_settings_external_oauth2_servers.forEach( function( server ) {
572 server.provider.find( 'select' ).on( 'change', function() {
573 var action = 'generic' === $( this ).val() ? 'show' : 'hide';
574 animateOption( action, server.url_authorize );
575 animateOption( action, server.url_token );
576 animateOption( action, server.url_resource );
577 animateOption( action, server.attr_username );
578 animateOption( action, server.attr_email );
579 animateOption( action, server.attr_first_name );
580 animateOption( action, server.attr_last_name );
581 animateOption( action, server.attr_update_on_login );
582 action = 'azure' === $( this ).val() ? 'show' : 'hide';
583 animateOption( action, server.tenant_id );
584 });
585 });
586
587 // Event handler: Show/hide OIDC tab based on checkbox
588 $( 'input[name="auth_settings[oidc]"]' ).on( 'change', function() {
589 $( '.nav-tab-wrapper .nav-tab-external_oidc' ).toggle( $( this ).is( ':checked' ) );
590 });
591
592 // Event handler: Show/hide Google tab based on checkbox
593 $( 'input[name="auth_settings[google]"]' ).on( 'change', function() {
594 $( '.nav-tab-wrapper .nav-tab-external_google' ).toggle( $( this ).is( ':checked' ) );
595 });
596
597 // Event handler: Show/hide CAS tab based on checkbox
598 $( 'input[name="auth_settings[cas]"]' ).on( 'change', function() {
599 $( '.nav-tab-wrapper .nav-tab-external_cas' ).toggle( $( this ).is( ':checked' ) );
600 });
601
602 // Event handler: Show/hide LDAP tab based on checkbox
603 $( 'input[name="auth_settings[ldap]"]' ).on( 'change', function() {
604 $( '.nav-tab-wrapper .nav-tab-external_ldap' ).toggle( $( this ).is( ':checked' ) );
605 });
606
607 // Event handler: Show/hide Bypass Usernames based on Disable WordPress Logins checkbox.
608 $( 'input[name="auth_settings[advanced_disable_wp_login]"]' ).on( 'change', function() {
609 var action = $( this ).is( ':checked' ) ? 'show' : 'hide';
610 animateOption( action, auth_settings_advanced_disable_wp_login_bypass_usernames );
611 });
612
613 // Event handler: Test LDAP settings.
614 $( '#ldap_test_user_submit' ).on( 'click', function( event ) {
615 event.preventDefault();
616 $( 'html' ).addClass( 'busy' );
617 $( '#ldap_test_user_spinner' ).addClass( 'is-active' );
618
619 $.post( ajaxurl, {
620 action: 'auth_settings_ldap_test_user',
621 username: $( 'input[name="auth_settings[ldap_test_user]"]' ).val(),
622 password: $( 'input#auth_settings_ldap_test_pass' ).val(),
623 nonce: $( '#nonce_save_auth_settings' ).val(),
624 }).done( function ( data ) {
625 $( '#ldap_test_user_result' ).show().val( data.message );
626 }).always( function () {
627 $( 'html' ).removeClass( 'busy' );
628 $( '#ldap_test_user_spinner' ).removeClass( 'is-active' );
629 });
630 } );
631
632 // Show save button if usermeta field is modified.
633 $( 'form input.auth-usermeta' ).on( 'keyup', function( event ) {
634 // Don't do anything if tab or arrow keys were pressed.
635 if ( event.which === 9 || event.which === 37 || event.which === 38 || event.which === 39 || event.which === 40 ) {
636 return;
637 }
638 $( this ).siblings( '.button' ).css( 'display', 'inline-block' );
639 });
640
641 // List management function: pressing enter in the new approved or new
642 // blocked user (email or role field) adds the user to the list.
643 $( '#new_approved_user_email, #new_approved_user_role, #new_blocked_user_email' ).on( 'keyup', function( event ) {
644 // For textareas, make Enter add the user; for inputs, make enter add the user.
645 if ( $( this ).is( 'textarea' ) ) {
646 // Enter key adds a newline; Enter key with Ctrl, Alt, Shift, or Meta adds the user.
647 if ( event.which === 13 && ( event.ctrlKey || event.altKey || event.metaKey ) ) {
648 $( this ).parent().find( 'a.button-add-user' ).trigger( 'click' );
649 event.preventDefault();
650 }
651 } else if ( event.which === 13 ) { // Enter key on input[type="text"]
652 $( this ).parent().find( 'a.button-add-user' ).trigger( 'click' );
653 event.preventDefault();
654 }
655 });
656
657 // Don't submit form (i.e., save options) when hitting enter in any user list field.
658 $( 'input.auth-email, select.auth-role, input.auth-date-added, input.auth-usermeta' ).on( 'keydown', function( event ) {
659 if ( event.which === 13 ) { // Enter key
660 event.preventDefault();
661 return false;
662 }
663 });
664
665 // Enable the user-friendly multiselect form element on the options page.
666 $( '#auth_settings_access_public_pages' ).multiSelect({
667 selectableOptgroup: true,
668 selectableHeader: '<div class="custom-header">' + authL10n.private_pages + '</div>',
669 selectionHeader: '<div class="custom-header">' + authL10n.public_pages + '</div>',
670 });
671
672 // Switch to the first tab (or the tab indicated in sessionStorage, or the
673 // querystring). Note: only do this on the settings page, not the dashboard
674 // widget.
675 if ( ! $( '#auth_dashboard_widget' ).length ) {
676 var tab = '';
677 if ( getQuerystringValuesByKey( 'tab' ).length > 0 ) {
678 tab = getQuerystringValuesByKey( 'tab' )[0];
679 // Remove querystring param (to avoid returning to that tab after saving
680 // settings, where the user could have moved to a different tab which
681 // would update the value in sessionStorage).
682 url = new URL( window.location.href );
683 url.searchParams.delete( 'tab' );
684 window.history.replaceState( null, '', url.toString() );
685 } else if ( sessionStorage.getItem( 'tab' ) ) {
686 tab = sessionStorage.getItem( 'tab' );
687 }
688 if ( $.inArray( tab, [ 'access_lists', 'access_login', 'access_public', 'external', 'external_oauth2', 'external_oidc', 'external_google', 'external_cas', 'external_ldap', 'advanced' ] ) < 0 ) {
689 tab = 'access_lists';
690 }
691 window.chooseTab( tab, animationSpeed );
692 }
693
694 // Hide/show multisite settings based on override checkbox.
695 $( 'input[name="auth_settings[multisite_override]"]' ).on( 'change', function() {
696 hideMultisiteSettingsIfDisabled();
697 });
698 hideMultisiteSettingsIfDisabled();
699
700 // Wire up pager events on Approved User list (first/last/next/previous
701 // buttons, go to page text input, and search.
702 $( '#current-page-selector, #user-search-input' ).on( 'keydown', function( event ) {
703 if ( event.which === 13 ) { // Enter key
704 var searchTerm = $( '#user-search-input' ).val();
705 var currentPage = parseInt( $( this ).val(), 10 ) || 1;
706 var totalPages = parseInt( $( '.total-pages' ).first().text().replace( /[^0-9]/g, '' ), 10 ) || 1;
707
708 // Make sure current page is between 1 and max pages.
709 if ( currentPage < 1 ) {
710 currentPage = 1;
711 } else if ( currentPage > totalPages ) {
712 currentPage = totalPages;
713 }
714
715 // Update user list with users on next page.
716 refreshApprovedUserList( currentPage, searchTerm );
717
718 // Prevent default behavior.
719 event.preventDefault();
720 return false;
721 }
722 });
723
724 $( '.tablenav' ).on( 'click', '.pagination-links a, #search-submit', function( event ) {
725 var searchTerm = $( '#user-search-input' ).val();
726 var currentPage = parseInt( getParameterByName( 'paged', $( this ).attr( 'href' ) ), 10 ) || 1;
727 var totalPages = parseInt( $( '.total-pages' ).first().text().replace( /[^0-9]/g, '' ), 10 ) || 1;
728 if ( currentPage > totalPages ) {
729 currentPage = totalPages;
730 }
731
732 // Update user list with users on next page.
733 refreshApprovedUserList( currentPage, searchTerm );
734
735 // Remove focus from clicked element.
736 $( this ).blur();
737
738 // Prevent default behavior.
739 event.preventDefault();
740 return false;
741 });
742
743 // Enable growable textarea for new user field.
744 $( 'textarea#new_approved_user_email' ).autogrow();
745
746 // Enable growable textarea for config fields.
747 $( 'textarea#auth_settings_ldap_host' ).autogrow();
748 $( 'textarea#auth_settings_ldap_search_base' ).autogrow();
749 $( 'textarea#auth_settings_ldap_search_filter' ).autogrow();
750 $( 'textarea#auth_settings_oauth2_hosteddomain' ).autogrow();
751 $( 'textarea#auth_settings_google_hosteddomain' ).autogrow();
752 $( 'textarea#auth_settings_advanced_disable_wp_login_bypass_usernames' ).autogrow();
753
754 // Enable select2 new user email notification dropdown.
755 $( 'select#auth_settings_access_users_receive_pending_emails' ).select2({
756 ajax: {
757 url: ajaxurl,
758 dataType: 'json',
759 method: 'POST',
760 data: function ( params ) {
761 return {
762 action: 'auth_settings_search_users',
763 nonce: $( '#nonce_save_auth_settings' ).val(),
764 query: params.term,
765 page: params.page || 1,
766 };
767 },
768 delay: 250, // Delay in milliseconds after user stops typing before sending the request.
769 },
770 closeOnSelect: true, // Controls whether the dropdown is closed after a selection is made.
771 maximumInputLength: 50, // Maximum number of characters that may be provided for a search term.
772 minimumInputLength: 1, // Minimum number of characters required to start a search.
773 placeholder: authL10n.select_users,
774 templateSelection: function( data ) {
775 // Show just the username (data.id); fall back to the full display: username (email).
776 return data.id || data.text;
777 },
778 width: '100%',
779 // minimumResultsForSearch: 10,
780 });
781 });
782
783
784 /**
785 * Globals.
786 */
787
788
789 // Switch between option tabs.
790 window.chooseTab = function( listName, delay ) {
791 // default delay is 0
792 delay = 'undefined' !== typeof delay ? delay : 0;
793
794 // default to the access list tab
795 listName = 'undefined' !== typeof listName ? listName : 'access_lists';
796
797 // Hide all tab content, then show selected tab content
798 $( 'div.section_info, div.section_info + table' ).hide();
799 $( '#section_info_' + listName + ', #section_info_' + listName + ' + table' ).show();
800
801 // Set active tab
802 $( '.nav-tab-wrapper a' ).removeClass( 'nav-tab-active' );
803 $( 'a.nav-tab-' + listName ).addClass( 'nav-tab-active' );
804
805 // Hide site options if they are overridden by a multisite setting.
806 setTimeout( window.hideMultisiteOverriddenOptions, delay );
807
808 // Hide Save Changes button if we're on the access lists page (changing
809 // access lists saves automatically via AJAX).
810 $( 'body:not(.network-admin) #submit' ).toggle( 'access_lists' !== listName );
811
812 // Save user's active tab to sessionStorage (so we can restore it on reload).
813 // Note: session storage persists until the browser tab is closed.
814 sessionStorage.setItem( 'tab', listName );
815
816 // Check whether to fade logo.
817 fadeLogo();
818 };
819
820 // Hide (with overlay) site options if overridden by a multisite option.
821 window.hideMultisiteOverriddenOptions = function() {
822 $( '.auth_multisite_override_overlay' ).each( function() {
823 // Option to hide is stored in the overlay's id with 'overlay-hide-' prefix.
824 var optionContainerToHide = $( this ).closest( 'td' );
825 if ( optionContainerToHide.length > 0 ) {
826 $( this ).css({
827 'background-color': '#f1f1f1',
828 'z-index': 1,
829 opacity: 0.8,
830 position: 'absolute',
831 top: optionContainerToHide.css('padding-top'),
832 width: '100%',
833 height: optionContainerToHide.height(),
834 });
835 $( this ).show();
836 }
837 });
838 };
839
840 // Update user's usermeta field.
841 // @calls php wp_ajax_update_auth_usermeta.
842 window.authUpdateUsermeta = function( caller ) {
843 var $caller = $( caller ),
844 $usermeta = $caller.parent().children( '.auth-usermeta' ),
845 email = $caller.siblings( '.auth-email' ).val(),
846 usermeta = $usermeta.val(),
847 nonce = $( '#nonce_save_auth_settings' ).val();
848
849 // Remove reference to caller if it's the usermeta field itself (not a button triggering the save).
850 if ( $caller.hasClass( 'auth-usermeta' ) ) {
851 $caller = $();
852 }
853
854 // Disable inputs, show spinner.
855 $caller.attr( 'disabled', 'disabled' );
856 $usermeta.attr( 'disabled', 'disabled' );
857 var $row = $usermeta.closest( 'li' );
858 var $spinner = $( '<span class="spinner is-active"></span>' ).css({
859 position: 'absolute',
860 top: $row.position().top,
861 left: $row.position().left + $row.width(),
862 });
863 $usermeta.after( $spinner );
864 $( 'html' ).addClass( 'busy' );
865
866 // Call ajax save function.
867 $.post( ajaxurl, {
868 action: 'update_auth_usermeta',
869 email: email,
870 usermeta: usermeta,
871 nonce: nonce,
872 }, function( response ) {
873 var succeeded = response === 'success';
874 var spinnerText = succeeded ? authL10n.saved + '.' : '<span class="attention">' + authL10n.failed + '.</span>';
875 var spinnerWait = succeeded ? 500 : 2000;
876
877 // Enable inputs, remove spinner.
878 $caller.removeAttr( 'disabled' );
879 $usermeta.removeAttr( 'disabled' );
880 $( 'form .spinner:not(:has(.spinner-text))' ).animate( { width: '60px' }, 'fast' ).append( '<span class="spinner-text">' + spinnerText + '</span>' ).delay( spinnerWait ).hide( animationSpeed, function() {
881 $( this ).remove();
882 });
883 $( 'html' ).removeClass( 'busy' );
884
885 }).fail( function() {
886 var succeeded = false;
887 var spinnerText = succeeded ? authL10n.saved + '.' : '<span class="attention">' + authL10n.failed + '.</span>';
888 var spinnerWait = succeeded ? 500 : 2000;
889
890 // Enable inputs, remove spinner.
891 $caller.removeAttr( 'disabled' );
892 $usermeta.removeAttr( 'disabled' );
893 $( 'form .spinner:not(:has(.spinner-text))' ).animate( { width: '60px' }, 'fast' ).append( '<span class="spinner-text">' + spinnerText + '</span>' ).delay( spinnerWait ).hide( animationSpeed, function() {
894 $( this ).remove();
895 });
896 $( 'html' ).removeClass( 'busy' );
897
898 });
899 };
900
901 // Update user's role.
902 window.authChangeRole = function( caller, isMultisite ) {
903 // Set default for multisite flag (run different save routine if multisite)
904 isMultisite = typeof isMultisite !== 'undefined' ? isMultisite : false;
905
906 var email = $( caller ).parent().find( '.auth-email' );
907 var role = $( caller ).parent().find( '.auth-role' );
908 var dateAdded = $( caller ).parent().find( '.auth-date-added' );
909
910 var user = {
911 email: email.val(),
912 role: role.val(),
913 date_added: dateAdded.val(), // eslint-disable-line camelcase
914 edit_action: 'change_role', // eslint-disable-line camelcase
915 multisite_user: isMultisite, // eslint-disable-line camelcase
916 };
917
918 // Update the options in the database with this change.
919 updateAuthUser( caller, 'access_users_approved', user );
920
921 return true;
922 };
923
924 // Update user's role (multisite options page).
925 window.authMultisiteChangeRole = function( caller ) {
926 var isMultisite = true;
927 window.authChangeRole( caller, isMultisite );
928 };
929
930 // Add user to list (list = blocked or approved).
931 window.authAddUser = function( caller, list, shouldCreateLocalAccount, isMultisite ) {
932 // Skip email address validation if adding from pending list (not user-editable).
933 var skipValidation = $( caller ).parent().parent().attr( 'id' ) === 'list_auth_settings_access_users_pending';
934
935 // Skip email address validation if we're banning an existing user (since they're already in a list).
936 var blockingNewUser = $( caller ).attr( 'id' ).indexOf( 'block_user_new' ) > -1;
937 skipValidation = skipValidation || ( $( caller ).attr( 'id' ).indexOf( 'block_user' ) > -1 && ! blockingNewUser );
938
939 // Set default for multisite flag (run different save routine if multisite)
940 isMultisite = 'undefined' !== typeof isMultisite ? isMultisite : false;
941
942 // Default to the approved list.
943 list = 'undefined' !== typeof list ? list : 'approved';
944
945 // Default to not creating a local account.
946 shouldCreateLocalAccount = 'undefined' !== typeof shouldCreateLocalAccount ? shouldCreateLocalAccount : false;
947
948 var email = $( caller ).parent().find( '.auth-email' );
949 var role = $( caller ).parent().find( '.auth-role' );
950 var dateAdded = $( caller ).parent().find( '.auth-date-added' );
951
952 // Helper variable for disabling buttons while processing. This will be
953 // set differently if our clicked button is nested in a div (below).
954 var buttons = caller;
955
956 // Button (caller) might be nested in a div, so we need to walk up one more level
957 if ( 0 === email.length || 0 === role.length ) {
958 email = $( caller ).parent().parent().find( '.auth-email' );
959 role = $( caller ).parent().parent().find( '.auth-role' );
960 dateAdded = $( caller ).parent().parent().find( '.auth-date-added' );
961 buttons = $( caller ).parent().children();
962 }
963
964 // Support a single email address, or multiple (separated by newlines, commas, semicolons, or spaces).
965 var emails = $.trim( email.val() ).replace( /mailto:/g, '' ).split( /[\s,;]+/ );
966
967 // Remove any invalid email addresses.
968 if ( ! skipValidation ) {
969 // Check if the email(s) being added is well-formed.
970 emails = emails.filter( function( emailToValidate ) {
971 return validEmail( emailToValidate, blockingNewUser );
972 });
973 // Remove any duplicates in the list of emails to add.
974 emails = removeDuplicatesFromArrayOfStrings( emails );
975 }
976
977 // Shake and quit if no valid email addresses exist.
978 if ( 1 > emails.length ) {
979 $( '#new_' + list + '_user_email' ).parent().effect( 'shake', shakeSpeed );
980 return false;
981 }
982
983 $( buttons ).attr( 'disabled', 'disabled' );
984
985 var users = [];
986 for ( var i = 0; i < emails.length; i++ ) {
987 var user = {
988 email: emails[i],
989 role: role.val(),
990 date_added: dateAdded.val(), // eslint-disable-line camelcase
991 edit_action: 'add', // eslint-disable-line camelcase
992 local_user: shouldCreateLocalAccount, // eslint-disable-line camelcase
993 multisite_user: isMultisite, // eslint-disable-line camelcase
994 };
995 users.push( user );
996
997 // Get next highest user ID.
998 var nextId = 1 + Math.max.apply(
999 null,
1000 // eslint-disable-next-line no-unused-vars
1001 $( '#list_auth_settings_access_users_' + list + ' li .auth-email' ).map( function( el ) { // jshint ignore:line
1002 return parseInt( this.id.replace( 'auth_multisite_settings_access_users_' + list + '_', '' ).replace( 'auth_settings_access_users_' + list + '_', '' ), 10 );
1003 })
1004 );
1005
1006 // Add the new item.
1007 var authJsPrefix = isMultisite ? 'authMultisite' : 'auth';
1008 var multisiteIcon = isMultisite ? '<a title="WordPress Multisite user" class="button disabled auth-multisite-user dashicons-before dashicons-admin-site"></a>' : '';
1009 var banButton = isMultisite || 'approved' !== list ? '' : '<a class="button button-primary dashicons-before dashicons-remove" id="block_user_' + nextId + '" onclick="' + authJsPrefix + 'AddUser( this, \'blocked\', false ); ' + authJsPrefix + 'IgnoreUser( this, \'approved\' );" title="' + authL10n.block_ban_user + '"></a>';
1010 var ignoreButton = '<a class="button dashicons-before dashicons-no" id="ignore_user_' + nextId + '" onclick="' + authJsPrefix + 'IgnoreUser( this, \'' + list + '\' );" title="' + authL10n.remove_user + '"></a>';
1011 $( ' \
1012 <li id="new_user_' + nextId + '" class="new-user" style="display: none;"> \
1013 <input type="text" id="auth_settings_access_users_' + list + '_' + nextId + '" name="auth_settings[access_users_' + list + '][' + nextId + '][email]" value="' + user.email + '" readonly="true" class="auth-email" /> \
1014 <select name="auth_settings[access_users_' + list + '][' + nextId + '][role]" class="auth-role" onchange="' + authJsPrefix + 'ChangeRole( this );"> \
1015 </select> \
1016 <input type="text" name="auth_settings[access_users_' + list + '][' + nextId + '][date_added]" value="' + getShortDate() + '" readonly="true" class="auth-date-added" /> \
1017 ' + multisiteIcon + banButton + ignoreButton + ' \
1018 <span class="spinner is-active"></span> \
1019 </li> \
1020 ' ).appendTo( '#list_auth_settings_access_users_' + list ).slideDown( 250 );
1021
1022 // Populate the role dropdown in the new element. Because clone() doesn't
1023 // save selected state on select elements, set that too.
1024 $( 'option', role ).clone().appendTo( '#new_user_' + nextId + ' .auth-role' );
1025 $( '#new_user_' + nextId + ' .auth-role' ).val( role.val() );
1026 }
1027
1028 // Remove the 'empty list' item if it exists.
1029 $( '#list_auth_settings_access_users_' + list + ' li.auth-empty' ).remove();
1030
1031 // Update the options in the database with this change.
1032 updateAuthUser( buttons, 'access_users_' + list, users );
1033
1034 // Reset the new user textboxes
1035 if ( email.hasClass( 'new' ) ) {
1036 email.val( '' ).keydown();
1037 }
1038
1039 // Re-enable the action buttons now that we're done saving.
1040 $( buttons ).removeAttr( 'disabled' );
1041 return true;
1042 };
1043
1044 // Add user to list (multisite options page).
1045 window.authMultisiteAddUser = function( caller, list, shouldCreateLocalAccount ) {
1046 var isMultisite = true;
1047
1048 // Default to the approved list.
1049 list = typeof list !== 'undefined' ? list : 'approved';
1050
1051 // Default to not creating a local account.
1052 shouldCreateLocalAccount = typeof shouldCreateLocalAccount !== 'undefined' ? shouldCreateLocalAccount : false;
1053
1054 // There currently is no multisite blocked list, so do nothing.
1055 if ( list === 'blocked' ) {
1056 return;
1057 }
1058
1059 window.authAddUser( caller, list, shouldCreateLocalAccount, isMultisite );
1060 };
1061
1062 // Remove user from list.
1063 window.authIgnoreUser = function( caller, listName, isMultisite ) {
1064 // Set default for multisite flag (run different save routine if multisite)
1065 isMultisite = typeof isMultisite !== 'undefined' ? isMultisite : false;
1066
1067 // Set default list if not provided.
1068 listName = typeof listName !== 'undefined' ? listName : 'approved';
1069
1070 var email = $( caller ).parent().find( '.auth-email' );
1071
1072 var user = {
1073 email: email.val(),
1074 role: '',
1075 date_added: '', // eslint-disable-line camelcase
1076 edit_action: 'remove', // eslint-disable-line camelcase
1077 multisite_user: isMultisite, // eslint-disable-line camelcase
1078 };
1079
1080 // Show an 'empty list' message if we're deleting the last item
1081 var list = $( caller ).closest( 'ul' );
1082 if ( $( 'li', list ).length <= 1 ) {
1083 $( list ).append( '<li class="auth-empty"><em>' + authL10n.no_users_in + ' ' + listName + '</em></li>' );
1084 }
1085
1086 $( caller ).parent().slideUp( 250, function() {
1087 // Remove the list item.
1088 $( this ).remove();
1089
1090 // Update the options in the database with this change.
1091 updateAuthUser( caller, 'access_users_' + listName, user );
1092 });
1093 };
1094
1095 // Remove user from list (multisite options page).
1096 window.authMultisiteIgnoreUser = function( caller, listName ) {
1097 var isMultisite = true;
1098
1099 // Set default list if not provided.
1100 listName = typeof listName !== 'undefined' ? listName : '';
1101
1102 window.authIgnoreUser( caller, listName, isMultisite );
1103 };
1104
1105 // Save Authorizer Settings (multisite).
1106 // @calls php wp_ajax_save_auth_multisite_settings.
1107 /* eslint-disable camelcase */
1108 window.saveAuthMultisiteSettings = function( caller ) {
1109 // Enable wait cursor.
1110 $( 'html' ).addClass( 'busy' );
1111
1112 // Disable button (prevent duplicate clicks).
1113 $( caller ).attr( 'disabled', 'disabled' );
1114
1115 // Enable spinner by element that triggered this event (caller).
1116 var $spinner = $( '<span class="spinner is-active"></span>' ).css({
1117 position: 'absolute',
1118 top: $( caller ).position().top,
1119 left: $( caller ).position().left + $( caller ).width() + 20,
1120 });
1121 $( caller ).after( $spinner );
1122
1123 // Get form elements to save.
1124 var params = {
1125 action: 'save_auth_multisite_settings',
1126 nonce: $( '#nonce_save_auth_settings' ).val(),
1127 };
1128
1129 params.multisite_override = $( '#auth_settings_multisite_override' ).is( ':checked' ) ? '1' : '';
1130
1131 params.prevent_override_multisite = $( '#auth_settings_prevent_override_multisite' ).is( ':checked' ) ? '1' : '';
1132
1133 params.access_who_can_login = $( 'form input[name="auth_settings[access_who_can_login]"]:checked' ).val();
1134
1135 params.access_who_can_view = $( 'form input[name="auth_settings[access_who_can_view]"]:checked' ).val();
1136
1137 params.access_users_approved = {};
1138 $( '#list_auth_settings_access_users_approved li' ).each( function( index ) {
1139 var user = {};
1140 user.email = $( '.auth-email', this ).val();
1141 user.role = $( '.auth-role', this ).val();
1142 user.date_added = $( '.auth-date-added', this ).val();
1143 user.local_user = $( '.auth-local-user', this ).length !== 0;
1144 params.access_users_approved[index] = user;
1145 });
1146
1147 params.access_default_role = $( '#auth_settings_access_default_role' ).val();
1148
1149 params.oauth2 = $( '#auth_settings_oauth2' ).is( ':checked' ) ? '1' : '';
1150 params.oauth2_auto_login = $( '#auth_settings_oauth2_auto_login' ).val();
1151 params.oauth2_num_servers = parseInt( $( '#auth_settings_oauth2_num_servers' ).val() );
1152 params.oauth2_provider = $( '#auth_settings_oauth2_provider' ).val();
1153 params.oauth2_custom_label = $( '#auth_settings_oauth2_custom_label' ).val();
1154 params.oauth2_clientid = $( '#auth_settings_oauth2_clientid' ).val();
1155 params.oauth2_clientsecret = $( '#auth_settings_oauth2_clientsecret' ).val();
1156 params.oauth2_hosteddomain = $( '#auth_settings_oauth2_hosteddomain' ).val();
1157 params.oauth2_tenant_id = $( '#auth_settings_oauth2_tenant_id' ).val();
1158 params.oauth2_url_authorize = $( '#auth_settings_oauth2_url_authorize' ).val();
1159 params.oauth2_url_token = $( '#auth_settings_oauth2_url_token' ).val();
1160 params.oauth2_url_resource = $( '#auth_settings_oauth2_url_resource' ).val();
1161 params.oauth2_attr_username = $( '#auth_settings_oauth2_attr_username' ).val();
1162 params.oauth2_attr_email = $( '#auth_settings_oauth2_attr_email' ).val();
1163 params.oauth2_attr_first_name = $( '#auth_settings_oauth2_attr_first_name' ).val();
1164 params.oauth2_attr_last_name = $( '#auth_settings_oauth2_attr_last_name' ).val();
1165 params.oauth2_attr_update_on_login = $( '#auth_settings_oauth2_attr_update_on_login' ).val();
1166 params.oauth2_require_verified_email = $( '#auth_settings_oauth2_require_verified_email' ).is( ':checked' ) ? '1' : '';
1167 params.oauth2_link_on_username = $( '#auth_settings_oauth2_link_on_username' ).is( ':checked' ) ? '1' : '';
1168 if ( params.oauth2_num_servers > 1 ) {
1169 for ( var oauth2_num_server = 2; oauth2_num_server <= params.oauth2_num_servers && oauth2_num_server <= 20; oauth2_num_server++ ) {
1170 params['oauth2_provider_' + oauth2_num_server] = $( '#auth_settings_oauth2_provider_' + oauth2_num_server ).val();
1171 params['oauth2_custom_label_' + oauth2_num_server] = $( '#auth_settings_oauth2_custom_label_' + oauth2_num_server ).val();
1172 params['oauth2_clientid_' + oauth2_num_server] = $( '#auth_settings_oauth2_clientid_' + oauth2_num_server ).val();
1173 params['oauth2_clientsecret_' + oauth2_num_server] = $( '#auth_settings_oauth2_clientsecret_' + oauth2_num_server ).val();
1174 params['oauth2_hosteddomain_' + oauth2_num_server] = $( '#auth_settings_oauth2_hosteddomain_' + oauth2_num_server ).val();
1175 params['oauth2_tenant_id_' + oauth2_num_server] = $( '#auth_settings_oauth2_tenant_id_' + oauth2_num_server ).val();
1176 params['oauth2_url_authorize_' + oauth2_num_server] = $( '#auth_settings_oauth2_url_authorize_' + oauth2_num_server ).val();
1177 params['oauth2_url_token_' + oauth2_num_server] = $( '#auth_settings_oauth2_url_token_' + oauth2_num_server ).val();
1178 params['oauth2_url_resource_' + oauth2_num_server] = $( '#auth_settings_oauth2_url_resource_' + oauth2_num_server ).val();
1179 params['oauth2_attr_username_' + oauth2_num_server] = $( '#auth_settings_oauth2_attr_username_' + oauth2_num_server ).val();
1180 params['oauth2_attr_email_' + oauth2_num_server] = $( '#auth_settings_oauth2_attr_email_' + oauth2_num_server ).val();
1181 params['oauth2_attr_first_name_' + oauth2_num_server] = $( '#auth_settings_oauth2_attr_first_name_' + oauth2_num_server ).val();
1182 params['oauth2_attr_last_name_' + oauth2_num_server] = $( '#auth_settings_oauth2_attr_last_name_' + oauth2_num_server ).val();
1183 params['oauth2_attr_update_on_login_' + oauth2_num_server] = $( '#auth_settings_oauth2_attr_update_on_login_' + oauth2_num_server ).val();
1184 params['oauth2_require_verified_email_' + oauth2_num_server] = $( '#auth_settings_oauth2_require_verified_email_' + oauth2_num_server ).is( ':checked' ) ? '1' : '';
1185 params['oauth2_link_on_username_' + oauth2_num_server] = $( '#auth_settings_oauth2_link_on_username_' + oauth2_num_server ).is( ':checked' ) ? '1' : '';
1186 }
1187 }
1188
1189 params.oidc = $( '#auth_settings_oidc' ).is( ':checked' ) ? '1' : '';
1190 params.oidc_auto_login = $( '#auth_settings_oidc_auto_login' ).val();
1191 params.oidc_num_servers = parseInt( $( '#auth_settings_oidc_num_servers' ).val() );
1192 params.oidc_custom_label = $( '#auth_settings_oidc_custom_label' ).val();
1193 params.oidc_issuer = $( '#auth_settings_oidc_issuer' ).val();
1194 params.oidc_client_id = $( '#auth_settings_oidc_client_id' ).val();
1195 params.oidc_client_secret = $( '#auth_settings_oidc_client_secret' ).val();
1196 params.oidc_scopes = $( '#auth_settings_oidc_scopes' ).val();
1197 params.oidc_prompt = $( '#auth_settings_oidc_prompt' ).val();
1198 params.oidc_login_hint = $( '#auth_settings_oidc_login_hint' ).val();
1199 params.oidc_max_age = $( '#auth_settings_oidc_max_age' ).val();
1200 params.oidc_attr_username = $( '#auth_settings_oidc_attr_username' ).val();
1201 params.oidc_attr_email = $( '#auth_settings_oidc_attr_email' ).val();
1202 params.oidc_attr_first_name = $( '#auth_settings_oidc_attr_first_name' ).val();
1203 params.oidc_attr_last_name = $( '#auth_settings_oidc_attr_last_name' ).val();
1204 params.oidc_attr_update_on_login = $( '#auth_settings_oidc_attr_update_on_login' ).val();
1205 params.oidc_force_auth_method = $( '#auth_settings_oidc_force_auth_method' ).val();
1206 params.oidc_require_verified_email = $( '#auth_settings_oidc_require_verified_email' ).is( ':checked' ) ? '1' : '';
1207 params.oidc_link_on_username = $( '#auth_settings_oidc_link_on_username' ).is( ':checked' ) ? '1' : '';
1208 params.oidc_hosteddomain = $( '#auth_settings_oidc_hosteddomain' ).val();
1209 if ( params.oidc_num_servers > 1 ) {
1210 for ( var oidc_num_server = 2; oidc_num_server <= params.oidc_num_servers && oidc_num_server <= 20; oidc_num_server++ ) {
1211 params['oidc_custom_label_' + oidc_num_server] = $( '#auth_settings_oidc_custom_label_' + oidc_num_server ).val();
1212 params['oidc_issuer_' + oidc_num_server] = $( '#auth_settings_oidc_issuer_' + oidc_num_server ).val();
1213 params['oidc_client_id_' + oidc_num_server] = $( '#auth_settings_oidc_client_id_' + oidc_num_server ).val();
1214 params['oidc_client_secret_' + oidc_num_server] = $( '#auth_settings_oidc_client_secret_' + oidc_num_server ).val();
1215 params['oidc_scopes_' + oidc_num_server] = $( '#auth_settings_oidc_scopes_' + oidc_num_server ).val();
1216 params['oidc_prompt_' + oidc_num_server] = $( '#auth_settings_oidc_prompt_' + oidc_num_server ).val();
1217 params['oidc_login_hint_' + oidc_num_server] = $( '#auth_settings_oidc_login_hint_' + oidc_num_server ).val();
1218 params['oidc_max_age_' + oidc_num_server] = $( '#auth_settings_oidc_max_age_' + oidc_num_server ).val();
1219 params['oidc_attr_username_' + oidc_num_server] = $( '#auth_settings_oidc_attr_username_' + oidc_num_server ).val();
1220 params['oidc_attr_email_' + oidc_num_server] = $( '#auth_settings_oidc_attr_email_' + oidc_num_server ).val();
1221 params['oidc_attr_first_name_' + oidc_num_server] = $( '#auth_settings_oidc_attr_first_name_' + oidc_num_server ).val();
1222 params['oidc_attr_last_name_' + oidc_num_server] = $( '#auth_settings_oidc_attr_last_name_' + oidc_num_server ).val();
1223 params['oidc_attr_update_on_login_' + oidc_num_server] = $( '#auth_settings_oidc_attr_update_on_login_' + oidc_num_server ).val();
1224 params['oidc_force_auth_method_' + oidc_num_server] = $( '#auth_settings_oidc_force_auth_method_' + oidc_num_server ).val();
1225 params['oidc_require_verified_email_' + oidc_num_server] = $( '#auth_settings_oidc_require_verified_email_' + oidc_num_server ).is( ':checked' ) ? '1' : '';
1226 params['oidc_link_on_username_' + oidc_num_server] = $( '#auth_settings_oidc_link_on_username_' + oidc_num_server ).is( ':checked' ) ? '1' : '';
1227 }
1228 }
1229
1230 params.google = $( '#auth_settings_google' ).is( ':checked' ) ? '1' : '';
1231 params.google_clientid = $( '#auth_settings_google_clientid' ).val();
1232 params.google_clientsecret = $( '#auth_settings_google_clientsecret' ).val();
1233 params.google_hosteddomain = $( '#auth_settings_google_hosteddomain' ).val();
1234
1235 params.cas = $( '#auth_settings_cas' ).is( ':checked' ) ? '1' : '';
1236 params.cas_auto_login = $( '#auth_settings_cas_auto_login' ).val();
1237 params.cas_num_servers = parseInt( $( '#auth_settings_cas_num_servers' ).val() );
1238 params.cas_custom_label = $( '#auth_settings_cas_custom_label' ).val();
1239 params.cas_host = $( '#auth_settings_cas_host' ).val();
1240 params.cas_port = $( '#auth_settings_cas_port' ).val();
1241 params.cas_path = $( '#auth_settings_cas_path' ).val();
1242 params.cas_method = $( '#auth_settings_cas_method' ).val();
1243 params.cas_version = $( '#auth_settings_cas_version' ).val();
1244 params.cas_attr_email = $( '#auth_settings_cas_attr_email' ).val();
1245 params.cas_attr_first_name = $( '#auth_settings_cas_attr_first_name' ).val();
1246 params.cas_attr_last_name = $( '#auth_settings_cas_attr_last_name' ).val();
1247 params.cas_attr_update_on_login = $( '#auth_settings_cas_attr_update_on_login' ).val();
1248 params.cas_link_on_username = $( '#auth_settings_cas_link_on_username' ).is( ':checked' ) ? '1' : '';
1249 if ( params.cas_num_servers > 1 ) {
1250 for ( var cas_num_server = 2; cas_num_server <= params.cas_num_servers && cas_num_server <= 10; cas_num_server++ ) {
1251 params['cas_custom_label_' + cas_num_server] = $( '#auth_settings_cas_custom_label_' + cas_num_server ).val();
1252 params['cas_host_' + cas_num_server] = $( '#auth_settings_cas_host_' + cas_num_server ).val();
1253 params['cas_port_' + cas_num_server] = $( '#auth_settings_cas_port_' + cas_num_server ).val();
1254 params['cas_path_' + cas_num_server] = $( '#auth_settings_cas_path_' + cas_num_server ).val();
1255 params['cas_method_' + cas_num_server] = $( '#auth_settings_cas_method_' + cas_num_server ).val();
1256 params['cas_version_' + cas_num_server] = $( '#auth_settings_cas_version_' + cas_num_server ).val();
1257 params['cas_attr_email_' + cas_num_server] = $( '#auth_settings_cas_attr_email_' + cas_num_server ).val();
1258 params['cas_attr_first_name_' + cas_num_server] = $( '#auth_settings_cas_attr_first_name_' + cas_num_server ).val();
1259 params['cas_attr_last_name_' + cas_num_server] = $( '#auth_settings_cas_attr_last_name_' + cas_num_server ).val();
1260 params['cas_attr_update_on_login_' + cas_num_server] = $( '#auth_settings_cas_attr_update_on_login_' + cas_num_server ).val();
1261 params['cas_link_on_username_' + cas_num_server] = $( '#auth_settings_cas_link_on_username_' + cas_num_server ).is( ':checked' ) ? '1' : '';
1262 }
1263 }
1264
1265 params.ldap = $( '#auth_settings_ldap' ).is( ':checked' ) ? '1' : '';
1266 params.ldap_host = $( '#auth_settings_ldap_host' ).val();
1267 params.ldap_port = $( '#auth_settings_ldap_port' ).val();
1268 params.ldap_search_base = $( '#auth_settings_ldap_search_base' ).val();
1269 params.ldap_search_filter = $( '#auth_settings_ldap_search_filter' ).val();
1270 params.ldap_uid = $( '#auth_settings_ldap_uid' ).val();
1271 params.ldap_attr_email = $( '#auth_settings_ldap_attr_email' ).val();
1272 params.ldap_user = $( '#auth_settings_ldap_user' ).val();
1273 params.ldap_password = $( '#auth_settings_ldap_password' ).val();
1274 params.ldap_tls = $( '#auth_settings_ldap_tls' ).is( ':checked' ) ? '1' : '';
1275 params.ldap_lostpassword_url = $( '#auth_settings_ldap_lostpassword_url' ).val();
1276 params.ldap_attr_first_name = $( '#auth_settings_ldap_attr_first_name' ).val();
1277 params.ldap_attr_last_name = $( '#auth_settings_ldap_attr_last_name' ).val();
1278 params.ldap_attr_update_on_login = $( '#auth_settings_ldap_attr_update_on_login' ).val();
1279 params.ldap_test_user = $( '#auth_settings_ldap_test_user' ).val();
1280
1281 params.advanced_lockouts = {
1282 attempts_1: $( '#auth_settings_advanced_lockouts_attempts_1' ).val(),
1283 duration_1: $( '#auth_settings_advanced_lockouts_duration_1' ).val(),
1284 attempts_2: $( '#auth_settings_advanced_lockouts_attempts_2' ).val(),
1285 duration_2: $( '#auth_settings_advanced_lockouts_duration_2' ).val(),
1286 reset_duration: $( '#auth_settings_advanced_lockouts_reset_duration' ).val(),
1287 };
1288 params.advanced_hide_wp_login = $( '#auth_settings_advanced_hide_wp_login' ).is( ':checked' ) ? '1' : '';
1289 params.advanced_disable_wp_login = $( '#auth_settings_advanced_disable_wp_login' ).is( ':checked' ) ? '1' : '';
1290 params.advanced_disable_wp_login_bypass_usernames = $( '#auth_settings_advanced_disable_wp_login_bypass_usernames' ).val();
1291 params.advanced_show_usernames = $( '#auth_settings_advanced_show_usernames' ).is( ':checked' ) ? '1' : '';
1292 params.advanced_widget_enabled = $( '#auth_settings_advanced_widget_enabled' ).is( ':checked' ) ? '1' : '';
1293 params.advanced_users_per_page = $( '#auth_settings_advanced_users_per_page' ).val();
1294 params.advanced_users_sort_by = $( '#auth_settings_advanced_users_sort_by' ).val();
1295 params.advanced_users_sort_order = $( '#auth_settings_advanced_users_sort_order' ).val();
1296
1297 $.post( ajaxurl, params, function( response ) {
1298 var succeeded = response === 'success';
1299 var spinnerText = succeeded ? authL10n.saved + '.' : '<span class="attention">' + authL10n.failed + '.</span>';
1300 var spinnerWait = succeeded ? 500 : 2000;
1301 $( 'form .spinner:not(:has(.spinner-text))' ).append( '<span class="spinner-text">' + spinnerText + '</span>' ).delay( spinnerWait ).hide( animationSpeed, function() {
1302 $( this ).remove();
1303 });
1304 $( caller ).removeAttr( 'disabled' );
1305
1306 // Disable wait cursor.
1307 $( 'html' ).removeClass( 'busy' );
1308
1309 // If the save was successful, and we have more than 1 CAS or OAuth2
1310 // servers configured, reload the page to render the additional CAS/Oauth2
1311 // server settings fields.
1312 if ( succeeded && ( params.cas_num_servers > 1 || params.oauth2_num_servers > 1 ) ) {
1313 location.reload();
1314 }
1315 }).fail( function() {
1316 // Fail fires if the server doesn't respond
1317 var succeeded = false;
1318 var spinnerText = succeeded ? authL10n.saved + '.' : '<span class="attention">' + authL10n.failed + '.</span>';
1319 var spinnerWait = succeeded ? 500 : 2000;
1320 $( 'form .spinner:not(:has(.spinner-text))' ).append( '<span class="spinner-text">' + spinnerText + '</span>' ).delay( spinnerWait ).hide( animationSpeed, function() {
1321 $( this ).remove();
1322 });
1323 $( caller ).removeAttr( 'disabled' );
1324
1325 // Disable wait cursor.
1326 $( 'html' ).removeClass( 'busy' );
1327 });
1328 };
1329 /* eslint-enable camelcase */
1330
1331 // Fade in/out Authorizer logo in bottom right on Settings.
1332 $(document).on( 'scroll', function () {
1333 fadeLogo();
1334 });
1335
1336 function fadeLogo() {
1337 if ( getScrollPercent() < 90 ) {
1338 $( '#wpwrap' ).removeClass( 'not-faded' );
1339 } else {
1340 $( '#wpwrap' ).addClass( 'not-faded' );
1341 }
1342 }
1343
1344 function getScrollPercent() {
1345 var h = document.documentElement,
1346 b = document.body,
1347 st = 'scrollTop',
1348 sh = 'scrollHeight';
1349 return ( h[st] || b[st] ) / ( ( h[sh] || b[sh] ) - h.clientHeight ) * 100;
1350 }
1351
1352 /* ========================================================================
1353 * Portions below from Bootstrap.
1354 * ========================================================================
1355 * Bootstrap: dropdown.js v3.1.1
1356 * http://getbootstrap.com/javascript/#dropdowns
1357 * ========================================================================
1358 * Copyright 2011-2014 Twitter, Inc.
1359 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
1360 * ======================================================================== */
1361
1362 // DROPDOWN CLASS DEFINITION
1363 // =========================
1364 var backdrop = '.dropdown-backdrop';
1365 var toggle = '[data-toggle=dropdown]';
1366 var Dropdown = function( element ) { // eslint-disable-line func-style
1367 $( element ).on( 'click.bs.dropdown', this.toggle );
1368 };
1369
1370 Dropdown.prototype.toggle = function( event ) {
1371 var $this = $( this );
1372
1373 if ( $this.is( '.disabled, :disabled' ) ) {
1374 return;
1375 }
1376
1377 var $parent = getParent( $this );
1378 var isActive = $parent.hasClass( 'open' );
1379
1380 clearMenus();
1381
1382 if ( ! isActive ) {
1383 if ( 'ontouchstart' in document.documentElement && ! $parent.closest( '.navbar-nav' ).length ) {
1384 // if mobile we use a backdrop because click events don't delegate
1385 $( '<div class="dropdown-backdrop"/>' ).insertAfter( $( this ) ).on( 'click', clearMenus );
1386 }
1387
1388 var relatedTarget = { relatedTarget: this };
1389 $parent.trigger( event = $.Event( 'show.bs.dropdown', relatedTarget ) );
1390
1391 if ( event.isDefaultPrevented() ) {
1392 return;
1393 }
1394
1395 $parent
1396 .toggleClass( 'open' )
1397 .trigger( 'shown.bs.dropdown', relatedTarget);
1398
1399 $this.focus();
1400 }
1401
1402 return false;
1403 };
1404
1405 Dropdown.prototype.keydown = function( event ) {
1406 if ( ! /(38|40|27)/.test( event.keyCode ) ) {
1407 return;
1408 }
1409
1410 var $this = $( this );
1411
1412 event.preventDefault();
1413 event.stopPropagation();
1414
1415 if ( $this.is( '.disabled, :disabled' ) ) {
1416 return;
1417 }
1418
1419 var $parent = getParent( $this );
1420 var isActive = $parent.hasClass( 'open' );
1421
1422 if ( ! isActive || ( isActive && event.keyCode === 27 ) ) {
1423 if ( event.which === 27 ) {
1424 $parent.find( toggle ).focus();
1425 }
1426 return $this.click();
1427 }
1428
1429 var desc = ' li:not(.divider):visible a';
1430 var $items = $parent.find( '[role=menu]' + desc + ', [role=listbox]' + desc);
1431
1432 if ( ! $items.length ) {
1433 return;
1434 }
1435
1436 var index = $items.index($items.filter( ':focus' ));
1437
1438 if ( event.keyCode === 38 && index > 0 ) {
1439 index--; // up
1440 }
1441 if ( event.keyCode === 40 && index < $items.length - 1 ) {
1442 index++; // down
1443 }
1444 if ( ! ~index ) {
1445 index = 0;
1446 }
1447
1448 $items.eq(index).focus();
1449 };
1450
1451 function clearMenus( event ) {
1452 $(backdrop).remove();
1453 $(toggle).each( function() {
1454 var $parent = getParent($( this ));
1455 var relatedTarget = { relatedTarget: this };
1456 if ( ! $parent.hasClass( 'open' ) ) {
1457 return;
1458 }
1459 $parent.trigger( event = $.Event( 'hide.bs.dropdown', relatedTarget ) );
1460 if ( event.isDefaultPrevented() ) {
1461 return;
1462 }
1463 $parent.removeClass( 'open' ).trigger( 'hidden.bs.dropdown', relatedTarget);
1464 });
1465 }
1466
1467 function getParent( $this ) {
1468 var selector = $this.attr( 'data-target' );
1469
1470 if ( ! selector ) {
1471 selector = $this.attr( 'href' );
1472 selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '' ); // strip for ie7
1473 }
1474
1475 var $parent = selector && $(selector);
1476
1477 return $parent && $parent.length ? $parent : $this.parent();
1478 }
1479
1480 // DROPDOWN PLUGIN DEFINITION
1481 // ==========================
1482 var old = $.fn.dropdown;
1483 $.fn.dropdown = function( option ) {
1484 return this.each( function() {
1485 var $this = $( this );
1486 var data = $this.data( 'bs.dropdown' );
1487
1488 if ( ! data ) {
1489 $this.data( 'bs.dropdown', ( data = new Dropdown( this ) ) );
1490 }
1491 if ( 'string' === typeof option ) {
1492 data[option].call( $this );
1493 }
1494 });
1495 };
1496 $.fn.dropdown.Constructor = Dropdown;
1497
1498 // DROPDOWN NO CONFLICT
1499 // ====================
1500 $.fn.dropdown.noConflict = function() {
1501 $.fn.dropdown = old;
1502 return this;
1503 };
1504
1505 // APPLY TO STANDARD DROPDOWN ELEMENTS
1506 // ===================================
1507 $(document)
1508 .on( 'click.bs.dropdown.data-api', clearMenus)
1509 .on( 'click.bs.dropdown.data-api', '.dropdown form', function( event ) { event.stopPropagation(); })
1510 .on( 'click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle)
1511 .on( 'keydown.bs.dropdown.data-api', toggle + ', [role=menu], [role=listbox]', Dropdown.prototype.keydown);
1512
1513 } )( jQuery );
1514