PluginProbe
Authorizer / 3.14.2
Authorizer v3.14.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.14.2, at js/authorizer.js

1,499 lines 68.2 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 } );
407 // OAuth2 settings below are for any additional OAuth2 servers configured (up to 20).
408 for ( var i = 2; i <= parseInt( $( '#auth_settings_oauth2_num_servers' ).val() ) && i <= 20; i++ ) {
409 auth_settings_external_oauth2_servers.push( {
410 provider: $( '#auth_settings_oauth2_provider_' + i ).closest( 'tr' ),
411 custom_label: $( '#auth_settings_oauth2_custom_label_' + i ).closest( 'tr' ),
412 clientid: $( '#auth_settings_oauth2_clientid_' + i ).closest( 'tr' ),
413 clientsecret: $( '#auth_settings_oauth2_clientsecret_' + i ).closest( 'tr' ),
414 hosteddomain: $( '#auth_settings_oauth2_hosteddomain_' + i ).closest( 'tr' ),
415 tenant_id: $( '#auth_settings_oauth2_tenant_id_' + i ).closest( 'tr' ),
416 url_authorize: $( '#auth_settings_oauth2_url_authorize_' + i ).closest( 'tr' ),
417 url_token: $( '#auth_settings_oauth2_url_token_' + i ).closest( 'tr' ),
418 url_resource: $( '#auth_settings_oauth2_url_resource_' + i ).closest( 'tr' ),
419 attr_username: $( '#auth_settings_oauth2_attr_username_' + i ).closest( 'tr' ),
420 attr_email: $( '#auth_settings_oauth2_attr_email_' + i ).closest( 'tr' ),
421 attr_first_name: $( '#auth_settings_oauth2_attr_first_name_' + i ).closest( 'tr' ),
422 attr_last_name: $( '#auth_settings_oauth2_attr_last_name_' + i ).closest( 'tr' ),
423 attr_update_on_login: $( '#auth_settings_oauth2_attr_update_on_login_' + i ).closest( 'tr' ),
424 } );
425 }
426 var auth_settings_external_google_clientid = $( '#auth_settings_google_clientid' ).closest( 'tr' );
427 var auth_settings_external_google_clientsecret = $( '#auth_settings_google_clientsecret' ).closest( 'tr' );
428 var auth_settings_external_google_hosteddomain = $( '#auth_settings_google_hosteddomain' ).closest( 'tr' );
429 var auth_settings_external_cas_auto_login = $( '#auth_settings_cas_auto_login' ).closest( 'tr' );
430 var auth_settings_external_cas_num_servers = $( '#auth_settings_cas_num_servers' ).closest( 'tr' );
431 var auth_settings_external_cas_servers = [];
432 // CAS settings below are for the first configured CAS server.
433 auth_settings_external_cas_servers.push( {
434 custom_label: $( '#auth_settings_cas_custom_label' ).closest( 'tr' ),
435 host: $( '#auth_settings_cas_host' ).closest( 'tr' ),
436 port: $( '#auth_settings_cas_port' ).closest( 'tr' ),
437 path: $( '#auth_settings_cas_path' ).closest( 'tr' ),
438 method: $( '#auth_settings_cas_method' ).closest( 'tr' ),
439 version: $( '#auth_settings_cas_version' ).closest( 'tr' ),
440 attr_email: $( '#auth_settings_cas_attr_email' ).closest( 'tr' ),
441 attr_first_name: $( '#auth_settings_cas_attr_first_name' ).closest( 'tr' ),
442 attr_last_name: $( '#auth_settings_cas_attr_last_name' ).closest( 'tr' ),
443 attr_update_on_login: $( '#auth_settings_cas_attr_update_on_login' ).closest( 'tr' ),
444 link_on_username: $( '#auth_settings_cas_link_on_username' ).closest( 'tr' ),
445 } );
446 // CAS settings below are for any additional CAS servers configured (up to 10).
447 for ( var i = 2; i <= parseInt( $( '#auth_settings_cas_num_servers' ).val() ) && i <= 10; i++ ) {
448 auth_settings_external_cas_servers.push( {
449 custom_label: $( '#auth_settings_cas_custom_label_' + i ).closest( 'tr' ),
450 host: $( '#auth_settings_cas_host_' + i ).closest( 'tr' ),
451 port: $( '#auth_settings_cas_port_' + i ).closest( 'tr' ),
452 path: $( '#auth_settings_cas_path_' + i ).closest( 'tr' ),
453 method: $( '#auth_settings_cas_method_' + i ).closest( 'tr' ),
454 version: $( '#auth_settings_cas_version_' + i ).closest( 'tr' ),
455 attr_email: $( '#auth_settings_cas_attr_email_' + i ).closest( 'tr' ),
456 attr_first_name: $( '#auth_settings_cas_attr_first_name_' + i ).closest( 'tr' ),
457 attr_last_name: $( '#auth_settings_cas_attr_last_name_' + i ).closest( 'tr' ),
458 attr_update_on_login: $( '#auth_settings_cas_attr_update_on_login_' + i ).closest( 'tr' ),
459 link_on_username: $( '#auth_settings_cas_link_on_username_' + i ).closest( 'tr' ),
460 } );
461 }
462 var auth_settings_external_ldap_host = $( '#auth_settings_ldap_host' ).closest( 'tr' );
463 var auth_settings_external_ldap_port = $( '#auth_settings_ldap_port' ).closest( 'tr' );
464 var auth_settings_external_ldap_search_base = $( '#auth_settings_ldap_search_base' ).closest( 'tr' );
465 var auth_settings_external_ldap_search_filter = $( '#auth_settings_ldap_search_filter' ).closest( 'tr' );
466 var auth_settings_external_ldap_uid = $( '#auth_settings_ldap_uid' ).closest( 'tr' );
467 var auth_settings_external_ldap_attr_email = $( '#auth_settings_ldap_attr_email' ).closest( 'tr' );
468 var auth_settings_external_ldap_user = $( '#auth_settings_ldap_user' ).closest( 'tr' );
469 var auth_settings_external_ldap_password = $( '#auth_settings_ldap_password' ).closest( 'tr' );
470 var auth_settings_external_ldap_tls = $( '#auth_settings_ldap_tls' ).closest( 'tr' );
471 var auth_settings_external_ldap_lostpassword_url = $( '#auth_settings_ldap_lostpassword_url' ).closest( 'tr' );
472 var auth_settings_external_ldap_attr_first_name = $( '#auth_settings_ldap_attr_first_name' ).closest( 'tr' );
473 var auth_settings_external_ldap_attr_last_name = $( '#auth_settings_ldap_attr_last_name' ).closest( 'tr' );
474 var auth_settings_external_ldap_attr_update_on_login = $( '#auth_settings_ldap_attr_update_on_login' ).closest( 'tr' );
475 var auth_settings_external_ldap_test_user = $( '#auth_settings_ldap_test_user' ).closest( 'tr' );
476 var auth_settings_advanced_disable_wp_login_bypass_usernames = $( '#auth_settings_advanced_disable_wp_login_bypass_usernames' ).closest( 'tr' );
477 /* eslint-enable */
478
479 // Hide settings unless "Only approved users" is checked
480 if ( ! $( '#radio_auth_settings_access_who_can_login_approved_users' ).is( ':checked' ) ) {
481 animateOption( 'hide_immediately', auth_settings_access_role_receive_pending_emails );
482 animateOption( 'hide_immediately', auth_settings_access_users_receive_pending_emails );
483 animateOption( 'hide_immediately', auth_settings_access_pending_redirect_to_message );
484 animateOption( 'hide_immediately', auth_settings_access_blocked_redirect_to_message );
485 animateOption( 'hide_immediately', auth_settings_access_should_email_approved_users );
486 }
487
488 // Hide Welcome email body/subject options if "Send welcome email" is off.
489 if ( ! $( '#auth_settings_access_should_email_approved_users' ).is( ':checked' ) ) {
490 animateOption( 'hide_immediately', auth_settings_access_email_approved_users_subject );
491 animateOption( 'hide_immediately', auth_settings_access_email_approved_users_body );
492 }
493
494 // On load: Show/hide public access options if everyone can see site
495 if ( ! $( '#radio_auth_settings_access_who_can_view_logged_in_users' ).is( ':checked' ) ) {
496 animateOption( 'hide_immediately', auth_settings_access_public_pages );
497 animateOption( 'hide_immediately', auth_settings_access_redirect_to_login );
498 animateOption( 'hide_immediately', auth_settings_access_public_warning );
499 animateOption( 'hide_immediately', auth_settings_access_redirect_to_message );
500 }
501
502 // Hide External Service tabs if provider is unchecked.
503 $( '.nav-tab-wrapper .nav-tab-external_oauth2' ).toggle( $( '#auth_settings_oauth2' ).is( ':checked' ) );
504 $( '.nav-tab-wrapper .nav-tab-external_oidc' ).toggle( $( '#auth_settings_oidc' ).is( ':checked' ) );
505 $( '.nav-tab-wrapper .nav-tab-external_google' ).toggle( $( '#auth_settings_google' ).is( ':checked' ) );
506 $( '.nav-tab-wrapper .nav-tab-external_cas' ).toggle( $( '#auth_settings_cas' ).is( ':checked' ) );
507 $( '.nav-tab-wrapper .nav-tab-external_ldap' ).toggle( $( '#auth_settings_ldap' ).is( ':checked' ) );
508
509 // Hide some OAuth2 options based on current settings.
510 auth_settings_external_oauth2_servers.forEach( function( server ) {
511 // Hide OAuth2 generic options if OAuth2 provider is unchecked or generic isn't chosen.
512 if ( 'generic' !== server.provider.find( 'select' ).val() ) {
513 animateOption( 'hide_immediately', server.url_authorize );
514 animateOption( 'hide_immediately', server.url_token );
515 animateOption( 'hide_immediately', server.url_resource );
516 animateOption( 'hide_immediately', server.attr_username );
517 animateOption( 'hide_immediately', server.attr_email );
518 animateOption( 'hide_immediately', server.attr_first_name );
519 animateOption( 'hide_immediately', server.attr_last_name );
520 animateOption( 'hide_immediately', server.attr_update_on_login );
521 }
522 // Hide OAuth2 Tenant ID if OAuth2 provider is unchecked or azure isn't chosen.
523 if ( 'azure' !== server.provider.find( 'select' ).val() ) {
524 animateOption( 'hide_immediately', server.tenant_id );
525 }
526 } );
527
528 // Hide Bypass Usernames if Disable WordPress logins is unchecked.
529 if ( ! $( '#auth_settings_advanced_disable_wp_login' ).is( ':checked' ) ) {
530 animateOption( 'hide_immediately', auth_settings_advanced_disable_wp_login_bypass_usernames );
531 }
532
533 // Event handler: Hide "Handle unauthorized visitors" option if access is granted to "Everyone"
534 $( 'input[name="auth_settings[access_who_can_login]"]' ).on( 'change', function() {
535 // Hide settings unless "Only approved users" is checked
536 var action = $( '#radio_auth_settings_access_who_can_login_approved_users' ).is( ':checked' ) ? 'show' : 'hide';
537 animateOption( action, auth_settings_access_role_receive_pending_emails );
538 animateOption( action, auth_settings_access_users_receive_pending_emails );
539 animateOption( action, auth_settings_access_pending_redirect_to_message );
540 animateOption( action, auth_settings_access_blocked_redirect_to_message );
541 animateOption( action, auth_settings_access_should_email_approved_users );
542 action = action === 'show' && $( '#auth_settings_access_should_email_approved_users' ).is( ':checked' ) ? 'show' : 'hide_immediately';
543 animateOption( action, auth_settings_access_email_approved_users_subject );
544 animateOption( action, auth_settings_access_email_approved_users_body );
545 });
546
547 // Event handler: Hide Welcome email body/subject options if "Send welcome email" is off.
548 $( 'input[name="auth_settings[access_should_email_approved_users]"]' ).on( 'change', function() {
549 var action = $( this ).is( ':checked' ) ? 'show' : 'hide';
550 animateOption( action, auth_settings_access_email_approved_users_subject );
551 animateOption( action, auth_settings_access_email_approved_users_body );
552 });
553
554 // Event handler: Hide "Handle unauthorized visitors" option if access is granted to "Everyone"
555 $( 'input[name="auth_settings[access_who_can_view]"]' ).on( 'change', function() {
556 var action = $( '#radio_auth_settings_access_who_can_view_everyone' ).is( ':checked' ) ? 'hide' : 'show';
557 animateOption( action, auth_settings_access_redirect_to_login );
558 animateOption( action, auth_settings_access_redirect_to_message );
559 animateOption( action, auth_settings_access_public_pages );
560 animateOption( action, auth_settings_access_public_warning );
561 });
562
563 // Event handler: Show/hide OAuth2 tab based on checkbox.
564 $( 'input[name="auth_settings[oauth2]"]' ).on( 'change', function() {
565 $( '.nav-tab-wrapper .nav-tab-external_oauth2' ).toggle( $( this ).is( ':checked' ) );
566 });
567
568 // Event handler: Show/hide OAuth2 generic/azure options based on provider.
569 auth_settings_external_oauth2_servers.forEach( function( server ) {
570 server.provider.find( 'select' ).on( 'change', function() {
571 var action = 'generic' === $( this ).val() ? 'show' : 'hide';
572 animateOption( action, server.url_authorize );
573 animateOption( action, server.url_token );
574 animateOption( action, server.url_resource );
575 animateOption( action, server.attr_username );
576 animateOption( action, server.attr_email );
577 animateOption( action, server.attr_first_name );
578 animateOption( action, server.attr_last_name );
579 animateOption( action, server.attr_update_on_login );
580 action = 'azure' === $( this ).val() ? 'show' : 'hide';
581 animateOption( action, server.tenant_id );
582 });
583 });
584
585 // Event handler: Show/hide OIDC tab based on checkbox
586 $( 'input[name="auth_settings[oidc]"]' ).on( 'change', function() {
587 $( '.nav-tab-wrapper .nav-tab-external_oidc' ).toggle( $( this ).is( ':checked' ) );
588 });
589
590 // Event handler: Show/hide Google tab based on checkbox
591 $( 'input[name="auth_settings[google]"]' ).on( 'change', function() {
592 $( '.nav-tab-wrapper .nav-tab-external_google' ).toggle( $( this ).is( ':checked' ) );
593 });
594
595 // Event handler: Show/hide CAS tab based on checkbox
596 $( 'input[name="auth_settings[cas]"]' ).on( 'change', function() {
597 $( '.nav-tab-wrapper .nav-tab-external_cas' ).toggle( $( this ).is( ':checked' ) );
598 });
599
600 // Event handler: Show/hide LDAP tab based on checkbox
601 $( 'input[name="auth_settings[ldap]"]' ).on( 'change', function() {
602 $( '.nav-tab-wrapper .nav-tab-external_ldap' ).toggle( $( this ).is( ':checked' ) );
603 });
604
605 // Event handler: Show/hide Bypass Usernames based on Disable WordPress Logins checkbox.
606 $( 'input[name="auth_settings[advanced_disable_wp_login]"]' ).on( 'change', function() {
607 var action = $( this ).is( ':checked' ) ? 'show' : 'hide';
608 animateOption( action, auth_settings_advanced_disable_wp_login_bypass_usernames );
609 });
610
611 // Event handler: Test LDAP settings.
612 $( '#ldap_test_user_submit' ).on( 'click', function( event ) {
613 event.preventDefault();
614 $( 'html' ).addClass( 'busy' );
615 $( '#ldap_test_user_spinner' ).addClass( 'is-active' );
616
617 $.post( ajaxurl, {
618 action: 'auth_settings_ldap_test_user',
619 username: $( 'input[name="auth_settings[ldap_test_user]"]' ).val(),
620 password: $( 'input#auth_settings_ldap_test_pass' ).val(),
621 nonce: $( '#nonce_save_auth_settings' ).val(),
622 }).done( function ( data ) {
623 $( '#ldap_test_user_result' ).show().val( data.message );
624 }).always( function () {
625 $( 'html' ).removeClass( 'busy' );
626 $( '#ldap_test_user_spinner' ).removeClass( 'is-active' );
627 });
628 } );
629
630 // Show save button if usermeta field is modified.
631 $( 'form input.auth-usermeta' ).on( 'keyup', function( event ) {
632 // Don't do anything if tab or arrow keys were pressed.
633 if ( event.which === 9 || event.which === 37 || event.which === 38 || event.which === 39 || event.which === 40 ) {
634 return;
635 }
636 $( this ).siblings( '.button' ).css( 'display', 'inline-block' );
637 });
638
639 // List management function: pressing enter in the new approved or new
640 // blocked user (email or role field) adds the user to the list.
641 $( '#new_approved_user_email, #new_approved_user_role, #new_blocked_user_email' ).on( 'keyup', function( event ) {
642 // For textareas, make Enter add the user; for inputs, make enter add the user.
643 if ( $( this ).is( 'textarea' ) ) {
644 // Enter key adds a newline; Enter key with Ctrl, Alt, Shift, or Meta adds the user.
645 if ( event.which === 13 && ( event.ctrlKey || event.altKey || event.metaKey ) ) {
646 $( this ).parent().find( 'a.button-add-user' ).trigger( 'click' );
647 event.preventDefault();
648 }
649 } else if ( event.which === 13 ) { // Enter key on input[type="text"]
650 $( this ).parent().find( 'a.button-add-user' ).trigger( 'click' );
651 event.preventDefault();
652 }
653 });
654
655 // Don't submit form (i.e., save options) when hitting enter in any user list field.
656 $( 'input.auth-email, select.auth-role, input.auth-date-added, input.auth-usermeta' ).on( 'keydown', function( event ) {
657 if ( event.which === 13 ) { // Enter key
658 event.preventDefault();
659 return false;
660 }
661 });
662
663 // Enable the user-friendly multiselect form element on the options page.
664 $( '#auth_settings_access_public_pages' ).multiSelect({
665 selectableOptgroup: true,
666 selectableHeader: '<div class="custom-header">' + authL10n.private_pages + '</div>',
667 selectionHeader: '<div class="custom-header">' + authL10n.public_pages + '</div>',
668 });
669
670 // Switch to the first tab (or the tab indicated in sessionStorage, or the
671 // querystring). Note: only do this on the settings page, not the dashboard
672 // widget.
673 if ( ! $( '#auth_dashboard_widget' ).length ) {
674 var tab = '';
675 if ( getQuerystringValuesByKey( 'tab' ).length > 0 ) {
676 tab = getQuerystringValuesByKey( 'tab' )[0];
677 } else if ( sessionStorage.getItem( 'tab' ) ) {
678 tab = sessionStorage.getItem( 'tab' );
679 }
680 if ( $.inArray( tab, [ 'access_lists', 'access_login', 'access_public', 'external', 'external_oauth2', 'external_oidc', 'external_google', 'external_cas', 'external_ldap', 'advanced' ] ) < 0 ) {
681 tab = 'access_lists';
682 }
683 window.chooseTab( tab, animationSpeed );
684 }
685
686 // Hide/show multisite settings based on override checkbox.
687 $( 'input[name="auth_settings[multisite_override]"]' ).on( 'change', function() {
688 hideMultisiteSettingsIfDisabled();
689 });
690 hideMultisiteSettingsIfDisabled();
691
692 // Wire up pager events on Approved User list (first/last/next/previous
693 // buttons, go to page text input, and search.
694 $( '#current-page-selector, #user-search-input' ).on( 'keydown', function( event ) {
695 if ( event.which === 13 ) { // Enter key
696 var searchTerm = $( '#user-search-input' ).val();
697 var currentPage = parseInt( $( this ).val(), 10 ) || 1;
698 var totalPages = parseInt( $( '.total-pages' ).first().text().replace( /[^0-9]/g, '' ), 10 ) || 1;
699
700 // Make sure current page is between 1 and max pages.
701 if ( currentPage < 1 ) {
702 currentPage = 1;
703 } else if ( currentPage > totalPages ) {
704 currentPage = totalPages;
705 }
706
707 // Update user list with users on next page.
708 refreshApprovedUserList( currentPage, searchTerm );
709
710 // Prevent default behavior.
711 event.preventDefault();
712 return false;
713 }
714 });
715
716 $( '.tablenav' ).on( 'click', '.pagination-links a, #search-submit', function( event ) {
717 var searchTerm = $( '#user-search-input' ).val();
718 var currentPage = parseInt( getParameterByName( 'paged', $( this ).attr( 'href' ) ), 10 ) || 1;
719 var totalPages = parseInt( $( '.total-pages' ).first().text().replace( /[^0-9]/g, '' ), 10 ) || 1;
720 if ( currentPage > totalPages ) {
721 currentPage = totalPages;
722 }
723
724 // Update user list with users on next page.
725 refreshApprovedUserList( currentPage, searchTerm );
726
727 // Remove focus from clicked element.
728 $( this ).blur();
729
730 // Prevent default behavior.
731 event.preventDefault();
732 return false;
733 });
734
735 // Enable growable textarea for new user field.
736 $( 'textarea#new_approved_user_email' ).autogrow();
737
738 // Enable growable textarea for config fields.
739 $( 'textarea#auth_settings_ldap_host' ).autogrow();
740 $( 'textarea#auth_settings_ldap_search_base' ).autogrow();
741 $( 'textarea#auth_settings_ldap_search_filter' ).autogrow();
742 $( 'textarea#auth_settings_oauth2_hosteddomain' ).autogrow();
743 $( 'textarea#auth_settings_google_hosteddomain' ).autogrow();
744 $( 'textarea#auth_settings_advanced_disable_wp_login_bypass_usernames' ).autogrow();
745
746 // Enable select2 new user email notification dropdown.
747 $( 'select#auth_settings_access_users_receive_pending_emails' ).select2({
748 ajax: {
749 url: ajaxurl,
750 dataType: 'json',
751 method: 'POST',
752 data: function ( params ) {
753 return {
754 action: 'auth_settings_search_users',
755 nonce: $( '#nonce_save_auth_settings' ).val(),
756 query: params.term,
757 page: params.page || 1,
758 };
759 },
760 delay: 250, // Delay in milliseconds after user stops typing before sending the request.
761 },
762 closeOnSelect: true, // Controls whether the dropdown is closed after a selection is made.
763 maximumInputLength: 50, // Maximum number of characters that may be provided for a search term.
764 minimumInputLength: 1, // Minimum number of characters required to start a search.
765 placeholder: authL10n.select_users,
766 templateSelection: function( data ) {
767 // Show just the username (data.id); fall back to the full display: username (email).
768 return data.id || data.text;
769 },
770 width: '100%',
771 // minimumResultsForSearch: 10,
772 });
773 });
774
775
776 /**
777 * Globals.
778 */
779
780
781 // Switch between option tabs.
782 window.chooseTab = function( listName, delay ) {
783 // default delay is 0
784 delay = 'undefined' !== typeof delay ? delay : 0;
785
786 // default to the access list tab
787 listName = 'undefined' !== typeof listName ? listName : 'access_lists';
788
789 // Hide all tab content, then show selected tab content
790 $( 'div.section_info, div.section_info + table' ).hide();
791 $( '#section_info_' + listName + ', #section_info_' + listName + ' + table' ).show();
792
793 // Set active tab
794 $( '.nav-tab-wrapper a' ).removeClass( 'nav-tab-active' );
795 $( 'a.nav-tab-' + listName ).addClass( 'nav-tab-active' );
796
797 // Hide site options if they are overridden by a multisite setting.
798 setTimeout( window.hideMultisiteOverriddenOptions, delay );
799
800 // Hide Save Changes button if we're on the access lists page (changing
801 // access lists saves automatically via AJAX).
802 $( 'body:not(.network-admin) #submit' ).toggle( 'access_lists' !== listName );
803
804 // Save user's active tab to sessionStorage (so we can restore it on reload).
805 // Note: session storage persists until the browser tab is closed.
806 sessionStorage.setItem( 'tab', listName );
807
808 // Check whether to fade logo.
809 fadeLogo();
810 };
811
812 // Hide (with overlay) site options if overridden by a multisite option.
813 window.hideMultisiteOverriddenOptions = function() {
814 $( '.auth_multisite_override_overlay' ).each( function() {
815 // Option to hide is stored in the overlay's id with 'overlay-hide-' prefix.
816 var optionContainerToHide = $( this ).closest( 'td' );
817 if ( optionContainerToHide.length > 0 ) {
818 $( this ).css({
819 'background-color': '#f1f1f1',
820 'z-index': 1,
821 opacity: 0.8,
822 position: 'absolute',
823 top: optionContainerToHide.css('padding-top'),
824 width: '100%',
825 height: optionContainerToHide.height(),
826 });
827 $( this ).show();
828 }
829 });
830 };
831
832 // Update user's usermeta field.
833 // @calls php wp_ajax_update_auth_usermeta.
834 window.authUpdateUsermeta = function( caller ) {
835 var $caller = $( caller ),
836 $usermeta = $caller.parent().children( '.auth-usermeta' ),
837 email = $caller.siblings( '.auth-email' ).val(),
838 usermeta = $usermeta.val(),
839 nonce = $( '#nonce_save_auth_settings' ).val();
840
841 // Remove reference to caller if it's the usermeta field itself (not a button triggering the save).
842 if ( $caller.hasClass( 'auth-usermeta' ) ) {
843 $caller = $();
844 }
845
846 // Disable inputs, show spinner.
847 $caller.attr( 'disabled', 'disabled' );
848 $usermeta.attr( 'disabled', 'disabled' );
849 var $row = $usermeta.closest( 'li' );
850 var $spinner = $( '<span class="spinner is-active"></span>' ).css({
851 position: 'absolute',
852 top: $row.position().top,
853 left: $row.position().left + $row.width(),
854 });
855 $usermeta.after( $spinner );
856 $( 'html' ).addClass( 'busy' );
857
858 // Call ajax save function.
859 $.post( ajaxurl, {
860 action: 'update_auth_usermeta',
861 email: email,
862 usermeta: usermeta,
863 nonce: nonce,
864 }, function( response ) {
865 var succeeded = response === 'success';
866 var spinnerText = succeeded ? authL10n.saved + '.' : '<span class="attention">' + authL10n.failed + '.</span>';
867 var spinnerWait = succeeded ? 500 : 2000;
868
869 // Enable inputs, remove spinner.
870 $caller.removeAttr( 'disabled' );
871 $usermeta.removeAttr( 'disabled' );
872 $( 'form .spinner:not(:has(.spinner-text))' ).animate( { width: '60px' }, 'fast' ).append( '<span class="spinner-text">' + spinnerText + '</span>' ).delay( spinnerWait ).hide( animationSpeed, function() {
873 $( this ).remove();
874 });
875 $( 'html' ).removeClass( 'busy' );
876
877 }).fail( function() {
878 var succeeded = false;
879 var spinnerText = succeeded ? authL10n.saved + '.' : '<span class="attention">' + authL10n.failed + '.</span>';
880 var spinnerWait = succeeded ? 500 : 2000;
881
882 // Enable inputs, remove spinner.
883 $caller.removeAttr( 'disabled' );
884 $usermeta.removeAttr( 'disabled' );
885 $( 'form .spinner:not(:has(.spinner-text))' ).animate( { width: '60px' }, 'fast' ).append( '<span class="spinner-text">' + spinnerText + '</span>' ).delay( spinnerWait ).hide( animationSpeed, function() {
886 $( this ).remove();
887 });
888 $( 'html' ).removeClass( 'busy' );
889
890 });
891 };
892
893 // Update user's role.
894 window.authChangeRole = function( caller, isMultisite ) {
895 // Set default for multisite flag (run different save routine if multisite)
896 isMultisite = typeof isMultisite !== 'undefined' ? isMultisite : false;
897
898 var email = $( caller ).parent().find( '.auth-email' );
899 var role = $( caller ).parent().find( '.auth-role' );
900 var dateAdded = $( caller ).parent().find( '.auth-date-added' );
901
902 var user = {
903 email: email.val(),
904 role: role.val(),
905 date_added: dateAdded.val(), // eslint-disable-line camelcase
906 edit_action: 'change_role', // eslint-disable-line camelcase
907 multisite_user: isMultisite, // eslint-disable-line camelcase
908 };
909
910 // Update the options in the database with this change.
911 updateAuthUser( caller, 'access_users_approved', user );
912
913 return true;
914 };
915
916 // Update user's role (multisite options page).
917 window.authMultisiteChangeRole = function( caller ) {
918 var isMultisite = true;
919 window.authChangeRole( caller, isMultisite );
920 };
921
922 // Add user to list (list = blocked or approved).
923 window.authAddUser = function( caller, list, shouldCreateLocalAccount, isMultisite ) {
924 // Skip email address validation if adding from pending list (not user-editable).
925 var skipValidation = $( caller ).parent().parent().attr( 'id' ) === 'list_auth_settings_access_users_pending';
926
927 // Skip email address validation if we're banning an existing user (since they're already in a list).
928 var blockingNewUser = $( caller ).attr( 'id' ).indexOf( 'block_user_new' ) > -1;
929 skipValidation = skipValidation || ( $( caller ).attr( 'id' ).indexOf( 'block_user' ) > -1 && ! blockingNewUser );
930
931 // Set default for multisite flag (run different save routine if multisite)
932 isMultisite = 'undefined' !== typeof isMultisite ? isMultisite : false;
933
934 // Default to the approved list.
935 list = 'undefined' !== typeof list ? list : 'approved';
936
937 // Default to not creating a local account.
938 shouldCreateLocalAccount = 'undefined' !== typeof shouldCreateLocalAccount ? shouldCreateLocalAccount : false;
939
940 var email = $( caller ).parent().find( '.auth-email' );
941 var role = $( caller ).parent().find( '.auth-role' );
942 var dateAdded = $( caller ).parent().find( '.auth-date-added' );
943
944 // Helper variable for disabling buttons while processing. This will be
945 // set differently if our clicked button is nested in a div (below).
946 var buttons = caller;
947
948 // Button (caller) might be nested in a div, so we need to walk up one more level
949 if ( 0 === email.length || 0 === role.length ) {
950 email = $( caller ).parent().parent().find( '.auth-email' );
951 role = $( caller ).parent().parent().find( '.auth-role' );
952 dateAdded = $( caller ).parent().parent().find( '.auth-date-added' );
953 buttons = $( caller ).parent().children();
954 }
955
956 // Support a single email address, or multiple (separated by newlines, commas, semicolons, or spaces).
957 var emails = $.trim( email.val() ).replace( /mailto:/g, '' ).split( /[\s,;]+/ );
958
959 // Remove any invalid email addresses.
960 if ( ! skipValidation ) {
961 // Check if the email(s) being added is well-formed.
962 emails = emails.filter( function( emailToValidate ) {
963 return validEmail( emailToValidate, blockingNewUser );
964 });
965 // Remove any duplicates in the list of emails to add.
966 emails = removeDuplicatesFromArrayOfStrings( emails );
967 }
968
969 // Shake and quit if no valid email addresses exist.
970 if ( 1 > emails.length ) {
971 $( '#new_' + list + '_user_email' ).parent().effect( 'shake', shakeSpeed );
972 return false;
973 }
974
975 $( buttons ).attr( 'disabled', 'disabled' );
976
977 var users = [];
978 for ( var i = 0; i < emails.length; i++ ) {
979 var user = {
980 email: emails[i],
981 role: role.val(),
982 date_added: dateAdded.val(), // eslint-disable-line camelcase
983 edit_action: 'add', // eslint-disable-line camelcase
984 local_user: shouldCreateLocalAccount, // eslint-disable-line camelcase
985 multisite_user: isMultisite, // eslint-disable-line camelcase
986 };
987 users.push( user );
988
989 // Get next highest user ID.
990 var nextId = 1 + Math.max.apply(
991 null,
992 // eslint-disable-next-line no-unused-vars
993 $( '#list_auth_settings_access_users_' + list + ' li .auth-email' ).map( function( el ) { // jshint ignore:line
994 return parseInt( this.id.replace( 'auth_multisite_settings_access_users_' + list + '_', '' ).replace( 'auth_settings_access_users_' + list + '_', '' ), 10 );
995 })
996 );
997
998 // Add the new item.
999 var authJsPrefix = isMultisite ? 'authMultisite' : 'auth';
1000 var multisiteIcon = isMultisite ? '<a title="WordPress Multisite user" class="button disabled auth-multisite-user dashicons-before dashicons-admin-site"></a>' : '';
1001 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>';
1002 var ignoreButton = '<a class="button dashicons-before dashicons-no" id="ignore_user_' + nextId + '" onclick="' + authJsPrefix + 'IgnoreUser( this, \'' + list + '\' );" title="' + authL10n.remove_user + '"></a>';
1003 $( ' \
1004 <li id="new_user_' + nextId + '" class="new-user" style="display: none;"> \
1005 <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" /> \
1006 <select name="auth_settings[access_users_' + list + '][' + nextId + '][role]" class="auth-role" onchange="' + authJsPrefix + 'ChangeRole( this );"> \
1007 </select> \
1008 <input type="text" name="auth_settings[access_users_' + list + '][' + nextId + '][date_added]" value="' + getShortDate() + '" readonly="true" class="auth-date-added" /> \
1009 ' + multisiteIcon + banButton + ignoreButton + ' \
1010 <span class="spinner is-active"></span> \
1011 </li> \
1012 ' ).appendTo( '#list_auth_settings_access_users_' + list ).slideDown( 250 );
1013
1014 // Populate the role dropdown in the new element. Because clone() doesn't
1015 // save selected state on select elements, set that too.
1016 $( 'option', role ).clone().appendTo( '#new_user_' + nextId + ' .auth-role' );
1017 $( '#new_user_' + nextId + ' .auth-role' ).val( role.val() );
1018 }
1019
1020 // Remove the 'empty list' item if it exists.
1021 $( '#list_auth_settings_access_users_' + list + ' li.auth-empty' ).remove();
1022
1023 // Update the options in the database with this change.
1024 updateAuthUser( buttons, 'access_users_' + list, users );
1025
1026 // Reset the new user textboxes
1027 if ( email.hasClass( 'new' ) ) {
1028 email.val( '' ).keydown();
1029 }
1030
1031 // Re-enable the action buttons now that we're done saving.
1032 $( buttons ).removeAttr( 'disabled' );
1033 return true;
1034 };
1035
1036 // Add user to list (multisite options page).
1037 window.authMultisiteAddUser = function( caller, list, shouldCreateLocalAccount ) {
1038 var isMultisite = true;
1039
1040 // Default to the approved list.
1041 list = typeof list !== 'undefined' ? list : 'approved';
1042
1043 // Default to not creating a local account.
1044 shouldCreateLocalAccount = typeof shouldCreateLocalAccount !== 'undefined' ? shouldCreateLocalAccount : false;
1045
1046 // There currently is no multisite blocked list, so do nothing.
1047 if ( list === 'blocked' ) {
1048 return;
1049 }
1050
1051 window.authAddUser( caller, list, shouldCreateLocalAccount, isMultisite );
1052 };
1053
1054 // Remove user from list.
1055 window.authIgnoreUser = function( caller, listName, isMultisite ) {
1056 // Set default for multisite flag (run different save routine if multisite)
1057 isMultisite = typeof isMultisite !== 'undefined' ? isMultisite : false;
1058
1059 // Set default list if not provided.
1060 listName = typeof listName !== 'undefined' ? listName : 'approved';
1061
1062 var email = $( caller ).parent().find( '.auth-email' );
1063
1064 var user = {
1065 email: email.val(),
1066 role: '',
1067 date_added: '', // eslint-disable-line camelcase
1068 edit_action: 'remove', // eslint-disable-line camelcase
1069 multisite_user: isMultisite, // eslint-disable-line camelcase
1070 };
1071
1072 // Show an 'empty list' message if we're deleting the last item
1073 var list = $( caller ).closest( 'ul' );
1074 if ( $( 'li', list ).length <= 1 ) {
1075 $( list ).append( '<li class="auth-empty"><em>' + authL10n.no_users_in + ' ' + listName + '</em></li>' );
1076 }
1077
1078 $( caller ).parent().slideUp( 250, function() {
1079 // Remove the list item.
1080 $( this ).remove();
1081
1082 // Update the options in the database with this change.
1083 updateAuthUser( caller, 'access_users_' + listName, user );
1084 });
1085 };
1086
1087 // Remove user from list (multisite options page).
1088 window.authMultisiteIgnoreUser = function( caller, listName ) {
1089 var isMultisite = true;
1090
1091 // Set default list if not provided.
1092 listName = typeof listName !== 'undefined' ? listName : '';
1093
1094 window.authIgnoreUser( caller, listName, isMultisite );
1095 };
1096
1097 // Save Authorizer Settings (multisite).
1098 // @calls php wp_ajax_save_auth_multisite_settings.
1099 /* eslint-disable camelcase */
1100 window.saveAuthMultisiteSettings = function( caller ) {
1101 // Enable wait cursor.
1102 $( 'html' ).addClass( 'busy' );
1103
1104 // Disable button (prevent duplicate clicks).
1105 $( caller ).attr( 'disabled', 'disabled' );
1106
1107 // Enable spinner by element that triggered this event (caller).
1108 var $spinner = $( '<span class="spinner is-active"></span>' ).css({
1109 position: 'absolute',
1110 top: $( caller ).position().top,
1111 left: $( caller ).position().left + $( caller ).width() + 20,
1112 });
1113 $( caller ).after( $spinner );
1114
1115 // Get form elements to save.
1116 var params = {
1117 action: 'save_auth_multisite_settings',
1118 nonce: $( '#nonce_save_auth_settings' ).val(),
1119 };
1120
1121 params.multisite_override = $( '#auth_settings_multisite_override' ).is( ':checked' ) ? '1' : '';
1122
1123 params.prevent_override_multisite = $( '#auth_settings_prevent_override_multisite' ).is( ':checked' ) ? '1' : '';
1124
1125 params.access_who_can_login = $( 'form input[name="auth_settings[access_who_can_login]"]:checked' ).val();
1126
1127 params.access_who_can_view = $( 'form input[name="auth_settings[access_who_can_view]"]:checked' ).val();
1128
1129 params.access_users_approved = {};
1130 $( '#list_auth_settings_access_users_approved li' ).each( function( index ) {
1131 var user = {};
1132 user.email = $( '.auth-email', this ).val();
1133 user.role = $( '.auth-role', this ).val();
1134 user.date_added = $( '.auth-date-added', this ).val();
1135 user.local_user = $( '.auth-local-user', this ).length !== 0;
1136 params.access_users_approved[index] = user;
1137 });
1138
1139 params.access_default_role = $( '#auth_settings_access_default_role' ).val();
1140
1141 params.oauth2 = $( '#auth_settings_oauth2' ).is( ':checked' ) ? '1' : '';
1142 params.oauth2_auto_login = $( '#auth_settings_oauth2_auto_login' ).val();
1143 params.oauth2_num_servers = parseInt( $( '#auth_settings_oauth2_num_servers' ).val() );
1144 params.oauth2_provider = $( '#auth_settings_oauth2_provider' ).val();
1145 params.oauth2_custom_label = $( '#auth_settings_oauth2_custom_label' ).val();
1146 params.oauth2_clientid = $( '#auth_settings_oauth2_clientid' ).val();
1147 params.oauth2_clientsecret = $( '#auth_settings_oauth2_clientsecret' ).val();
1148 params.oauth2_hosteddomain = $( '#auth_settings_oauth2_hosteddomain' ).val();
1149 params.oauth2_tenant_id = $( '#auth_settings_oauth2_tenant_id' ).val();
1150 params.oauth2_url_authorize = $( '#auth_settings_oauth2_url_authorize' ).val();
1151 params.oauth2_url_token = $( '#auth_settings_oauth2_url_token' ).val();
1152 params.oauth2_url_resource = $( '#auth_settings_oauth2_url_resource' ).val();
1153 params.oauth2_attr_username = $( '#auth_settings_oauth2_attr_username' ).val();
1154 params.oauth2_attr_email = $( '#auth_settings_oauth2_attr_email' ).val();
1155 params.oauth2_attr_first_name = $( '#auth_settings_oauth2_attr_first_name' ).val();
1156 params.oauth2_attr_last_name = $( '#auth_settings_oauth2_attr_last_name' ).val();
1157 params.oauth2_attr_update_on_login = $( '#auth_settings_oauth2_attr_update_on_login' ).val();
1158 if ( params.oauth2_num_servers > 1 ) {
1159 for ( var oauth2_num_server = 2; oauth2_num_server <= params.oauth2_num_servers && oauth2_num_server <= 20; oauth2_num_server++ ) {
1160 params['oauth2_provider_' + oauth2_num_server] = $( '#auth_settings_oauth2_provider_' + oauth2_num_server ).val();
1161 params['oauth2_custom_label_' + oauth2_num_server] = $( '#auth_settings_oauth2_custom_label_' + oauth2_num_server ).val();
1162 params['oauth2_clientid_' + oauth2_num_server] = $( '#auth_settings_oauth2_clientid_' + oauth2_num_server ).val();
1163 params['oauth2_clientsecret_' + oauth2_num_server] = $( '#auth_settings_oauth2_clientsecret_' + oauth2_num_server ).val();
1164 params['oauth2_hosteddomain_' + oauth2_num_server] = $( '#auth_settings_oauth2_hosteddomain_' + oauth2_num_server ).val();
1165 params['oauth2_tenant_id_' + oauth2_num_server] = $( '#auth_settings_oauth2_tenant_id_' + oauth2_num_server ).val();
1166 params['oauth2_url_authorize_' + oauth2_num_server] = $( '#auth_settings_oauth2_url_authorize_' + oauth2_num_server ).val();
1167 params['oauth2_url_token_' + oauth2_num_server] = $( '#auth_settings_oauth2_url_token_' + oauth2_num_server ).val();
1168 params['oauth2_url_resource_' + oauth2_num_server] = $( '#auth_settings_oauth2_url_resource_' + oauth2_num_server ).val();
1169 params['oauth2_attr_username_' + oauth2_num_server] = $( '#auth_settings_oauth2_attr_username_' + oauth2_num_server ).val();
1170 params['oauth2_attr_email_' + oauth2_num_server] = $( '#auth_settings_oauth2_attr_email_' + oauth2_num_server ).val();
1171 params['oauth2_attr_first_name_' + oauth2_num_server] = $( '#auth_settings_oauth2_attr_first_name_' + oauth2_num_server ).val();
1172 params['oauth2_attr_last_name_' + oauth2_num_server] = $( '#auth_settings_oauth2_attr_last_name_' + oauth2_num_server ).val();
1173 params['oauth2_attr_update_on_login_' + oauth2_num_server] = $( '#auth_settings_oauth2_attr_update_on_login_' + oauth2_num_server ).val();
1174 }
1175 }
1176
1177 params.oidc = $( '#auth_settings_oidc' ).is( ':checked' ) ? '1' : '';
1178 params.oidc_auto_login = $( '#auth_settings_oidc_auto_login' ).val();
1179 params.oidc_num_servers = parseInt( $( '#auth_settings_oidc_num_servers' ).val() );
1180 params.oidc_custom_label = $( '#auth_settings_oidc_custom_label' ).val();
1181 params.oidc_issuer = $( '#auth_settings_oidc_issuer' ).val();
1182 params.oidc_client_id = $( '#auth_settings_oidc_client_id' ).val();
1183 params.oidc_client_secret = $( '#auth_settings_oidc_client_secret' ).val();
1184 params.oidc_scopes = $( '#auth_settings_oidc_scopes' ).val();
1185 params.oidc_prompt = $( '#auth_settings_oidc_prompt' ).val();
1186 params.oidc_login_hint = $( '#auth_settings_oidc_login_hint' ).val();
1187 params.oidc_max_age = $( '#auth_settings_oidc_max_age' ).val();
1188 params.oidc_attr_username = $( '#auth_settings_oidc_attr_username' ).val();
1189 params.oidc_attr_email = $( '#auth_settings_oidc_attr_email' ).val();
1190 params.oidc_attr_first_name = $( '#auth_settings_oidc_attr_first_name' ).val();
1191 params.oidc_attr_last_name = $( '#auth_settings_oidc_attr_last_name' ).val();
1192 params.oidc_attr_update_on_login = $( '#auth_settings_oidc_attr_update_on_login' ).val();
1193 params.oidc_require_verified_email = $( '#auth_settings_oidc_require_verified_email' ).is( ':checked' ) ? '1' : '';
1194 params.oidc_link_on_username = $( '#auth_settings_oidc_link_on_username' ).is( ':checked' ) ? '1' : '';
1195 params.oidc_hosteddomain = $( '#auth_settings_oidc_hosteddomain' ).val();
1196 if ( params.oidc_num_servers > 1 ) {
1197 for ( var oidc_num_server = 2; oidc_num_server <= params.oidc_num_servers && oidc_num_server <= 20; oidc_num_server++ ) {
1198 params['oidc_custom_label_' + oidc_num_server] = $( '#auth_settings_oidc_custom_label_' + oidc_num_server ).val();
1199 params['oidc_issuer_' + oidc_num_server] = $( '#auth_settings_oidc_issuer_' + oidc_num_server ).val();
1200 params['oidc_client_id_' + oidc_num_server] = $( '#auth_settings_oidc_client_id_' + oidc_num_server ).val();
1201 params['oidc_client_secret_' + oidc_num_server] = $( '#auth_settings_oidc_client_secret_' + oidc_num_server ).val();
1202 params['oidc_scopes_' + oidc_num_server] = $( '#auth_settings_oidc_scopes_' + oidc_num_server ).val();
1203 params['oidc_prompt_' + oidc_num_server] = $( '#auth_settings_oidc_prompt_' + oidc_num_server ).val();
1204 params['oidc_login_hint_' + oidc_num_server] = $( '#auth_settings_oidc_login_hint_' + oidc_num_server ).val();
1205 params['oidc_max_age_' + oidc_num_server] = $( '#auth_settings_oidc_max_age_' + oidc_num_server ).val();
1206 params['oidc_attr_username_' + oidc_num_server] = $( '#auth_settings_oidc_attr_username_' + oidc_num_server ).val();
1207 params['oidc_attr_email_' + oidc_num_server] = $( '#auth_settings_oidc_attr_email_' + oidc_num_server ).val();
1208 params['oidc_attr_first_name_' + oidc_num_server] = $( '#auth_settings_oidc_attr_first_name_' + oidc_num_server ).val();
1209 params['oidc_attr_last_name_' + oidc_num_server] = $( '#auth_settings_oidc_attr_last_name_' + oidc_num_server ).val();
1210 params['oidc_attr_update_on_login_' + oidc_num_server] = $( '#auth_settings_oidc_attr_update_on_login_' + oidc_num_server ).val();
1211 params['oidc_require_verified_email_' + oidc_num_server] = $( '#auth_settings_oidc_require_verified_email_' + oidc_num_server ).is( ':checked' ) ? '1' : '';
1212 params['oidc_link_on_username_' + oidc_num_server] = $( '#auth_settings_oidc_link_on_username_' + oidc_num_server ).is( ':checked' ) ? '1' : '';
1213 }
1214 }
1215
1216 params.google = $( '#auth_settings_google' ).is( ':checked' ) ? '1' : '';
1217 params.google_clientid = $( '#auth_settings_google_clientid' ).val();
1218 params.google_clientsecret = $( '#auth_settings_google_clientsecret' ).val();
1219 params.google_hosteddomain = $( '#auth_settings_google_hosteddomain' ).val();
1220
1221 params.cas = $( '#auth_settings_cas' ).is( ':checked' ) ? '1' : '';
1222 params.cas_auto_login = $( '#auth_settings_cas_auto_login' ).val();
1223 params.cas_num_servers = parseInt( $( '#auth_settings_cas_num_servers' ).val() );
1224 params.cas_custom_label = $( '#auth_settings_cas_custom_label' ).val();
1225 params.cas_host = $( '#auth_settings_cas_host' ).val();
1226 params.cas_port = $( '#auth_settings_cas_port' ).val();
1227 params.cas_path = $( '#auth_settings_cas_path' ).val();
1228 params.cas_method = $( '#auth_settings_cas_method' ).val();
1229 params.cas_version = $( '#auth_settings_cas_version' ).val();
1230 params.cas_attr_email = $( '#auth_settings_cas_attr_email' ).val();
1231 params.cas_attr_first_name = $( '#auth_settings_cas_attr_first_name' ).val();
1232 params.cas_attr_last_name = $( '#auth_settings_cas_attr_last_name' ).val();
1233 params.cas_attr_update_on_login = $( '#auth_settings_cas_attr_update_on_login' ).val();
1234 params.cas_link_on_username = $( '#auth_settings_cas_link_on_username' ).is( ':checked' ) ? '1' : '';
1235 if ( params.cas_num_servers > 1 ) {
1236 for ( var cas_num_server = 2; cas_num_server <= params.cas_num_servers && cas_num_server <= 10; cas_num_server++ ) {
1237 params['cas_custom_label_' + cas_num_server] = $( '#auth_settings_cas_custom_label_' + cas_num_server ).val();
1238 params['cas_host_' + cas_num_server] = $( '#auth_settings_cas_host_' + cas_num_server ).val();
1239 params['cas_port_' + cas_num_server] = $( '#auth_settings_cas_port_' + cas_num_server ).val();
1240 params['cas_path_' + cas_num_server] = $( '#auth_settings_cas_path_' + cas_num_server ).val();
1241 params['cas_method_' + cas_num_server] = $( '#auth_settings_cas_method_' + cas_num_server ).val();
1242 params['cas_version_' + cas_num_server] = $( '#auth_settings_cas_version_' + cas_num_server ).val();
1243 params['cas_attr_email_' + cas_num_server] = $( '#auth_settings_cas_attr_email_' + cas_num_server ).val();
1244 params['cas_attr_first_name_' + cas_num_server] = $( '#auth_settings_cas_attr_first_name_' + cas_num_server ).val();
1245 params['cas_attr_last_name_' + cas_num_server] = $( '#auth_settings_cas_attr_last_name_' + cas_num_server ).val();
1246 params['cas_attr_update_on_login_' + cas_num_server] = $( '#auth_settings_cas_attr_update_on_login_' + cas_num_server ).val();
1247 params['cas_link_on_username_' + cas_num_server] = $( '#auth_settings_cas_link_on_username_' + cas_num_server ).is( ':checked' ) ? '1' : '';
1248 }
1249 }
1250
1251 params.ldap = $( '#auth_settings_ldap' ).is( ':checked' ) ? '1' : '';
1252 params.ldap_host = $( '#auth_settings_ldap_host' ).val();
1253 params.ldap_port = $( '#auth_settings_ldap_port' ).val();
1254 params.ldap_search_base = $( '#auth_settings_ldap_search_base' ).val();
1255 params.ldap_search_filter = $( '#auth_settings_ldap_search_filter' ).val();
1256 params.ldap_uid = $( '#auth_settings_ldap_uid' ).val();
1257 params.ldap_attr_email = $( '#auth_settings_ldap_attr_email' ).val();
1258 params.ldap_user = $( '#auth_settings_ldap_user' ).val();
1259 params.ldap_password = $( '#auth_settings_ldap_password' ).val();
1260 params.ldap_tls = $( '#auth_settings_ldap_tls' ).is( ':checked' ) ? '1' : '';
1261 params.ldap_lostpassword_url = $( '#auth_settings_ldap_lostpassword_url' ).val();
1262 params.ldap_attr_first_name = $( '#auth_settings_ldap_attr_first_name' ).val();
1263 params.ldap_attr_last_name = $( '#auth_settings_ldap_attr_last_name' ).val();
1264 params.ldap_attr_update_on_login = $( '#auth_settings_ldap_attr_update_on_login' ).val();
1265 params.ldap_test_user = $( '#auth_settings_ldap_test_user' ).val();
1266
1267 params.advanced_lockouts = {
1268 attempts_1: $( '#auth_settings_advanced_lockouts_attempts_1' ).val(),
1269 duration_1: $( '#auth_settings_advanced_lockouts_duration_1' ).val(),
1270 attempts_2: $( '#auth_settings_advanced_lockouts_attempts_2' ).val(),
1271 duration_2: $( '#auth_settings_advanced_lockouts_duration_2' ).val(),
1272 reset_duration: $( '#auth_settings_advanced_lockouts_reset_duration' ).val(),
1273 };
1274 params.advanced_hide_wp_login = $( '#auth_settings_advanced_hide_wp_login' ).is( ':checked' ) ? '1' : '';
1275 params.advanced_disable_wp_login = $( '#auth_settings_advanced_disable_wp_login' ).is( ':checked' ) ? '1' : '';
1276 params.advanced_disable_wp_login_bypass_usernames = $( '#auth_settings_advanced_disable_wp_login_bypass_usernames' ).val();
1277 params.advanced_widget_enabled = $( '#auth_settings_advanced_widget_enabled' ).is( ':checked' ) ? '1' : '';
1278 params.advanced_users_per_page = $( '#auth_settings_advanced_users_per_page' ).val();
1279 params.advanced_users_sort_by = $( '#auth_settings_advanced_users_sort_by' ).val();
1280 params.advanced_users_sort_order = $( '#auth_settings_advanced_users_sort_order' ).val();
1281
1282 $.post( ajaxurl, params, function( response ) {
1283 var succeeded = response === 'success';
1284 var spinnerText = succeeded ? authL10n.saved + '.' : '<span class="attention">' + authL10n.failed + '.</span>';
1285 var spinnerWait = succeeded ? 500 : 2000;
1286 $( 'form .spinner:not(:has(.spinner-text))' ).append( '<span class="spinner-text">' + spinnerText + '</span>' ).delay( spinnerWait ).hide( animationSpeed, function() {
1287 $( this ).remove();
1288 });
1289 $( caller ).removeAttr( 'disabled' );
1290
1291 // Disable wait cursor.
1292 $( 'html' ).removeClass( 'busy' );
1293
1294 // If the save was successful, and we have more than 1 CAS or OAuth2
1295 // servers configured, reload the page to render the additional CAS/Oauth2
1296 // server settings fields.
1297 if ( succeeded && ( params.cas_num_servers > 1 || params.oauth2_num_servers > 1 ) ) {
1298 location.reload();
1299 }
1300 }).fail( function() {
1301 // Fail fires if the server doesn't respond
1302 var succeeded = false;
1303 var spinnerText = succeeded ? authL10n.saved + '.' : '<span class="attention">' + authL10n.failed + '.</span>';
1304 var spinnerWait = succeeded ? 500 : 2000;
1305 $( 'form .spinner:not(:has(.spinner-text))' ).append( '<span class="spinner-text">' + spinnerText + '</span>' ).delay( spinnerWait ).hide( animationSpeed, function() {
1306 $( this ).remove();
1307 });
1308 $( caller ).removeAttr( 'disabled' );
1309
1310 // Disable wait cursor.
1311 $( 'html' ).removeClass( 'busy' );
1312 });
1313 };
1314 /* eslint-enable camelcase */
1315
1316 // Fade in/out Authorizer logo in bottom right on Settings.
1317 $(document).on( 'scroll', function () {
1318 fadeLogo();
1319 });
1320
1321 function fadeLogo() {
1322 if ( getScrollPercent() < 90 ) {
1323 $( '#wpwrap' ).removeClass( 'not-faded' );
1324 } else {
1325 $( '#wpwrap' ).addClass( 'not-faded' );
1326 }
1327 }
1328
1329 function getScrollPercent() {
1330 var h = document.documentElement,
1331 b = document.body,
1332 st = 'scrollTop',
1333 sh = 'scrollHeight';
1334 return ( h[st] || b[st] ) / ( ( h[sh] || b[sh] ) - h.clientHeight ) * 100;
1335 }
1336
1337 /* ========================================================================
1338 * Portions below from Bootstrap.
1339 * ========================================================================
1340 * Bootstrap: dropdown.js v3.1.1
1341 * http://getbootstrap.com/javascript/#dropdowns
1342 * ========================================================================
1343 * Copyright 2011-2014 Twitter, Inc.
1344 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
1345 * ======================================================================== */
1346
1347 // DROPDOWN CLASS DEFINITION
1348 // =========================
1349 var backdrop = '.dropdown-backdrop';
1350 var toggle = '[data-toggle=dropdown]';
1351 var Dropdown = function( element ) { // eslint-disable-line func-style
1352 $( element ).on( 'click.bs.dropdown', this.toggle );
1353 };
1354
1355 Dropdown.prototype.toggle = function( event ) {
1356 var $this = $( this );
1357
1358 if ( $this.is( '.disabled, :disabled' ) ) {
1359 return;
1360 }
1361
1362 var $parent = getParent( $this );
1363 var isActive = $parent.hasClass( 'open' );
1364
1365 clearMenus();
1366
1367 if ( ! isActive ) {
1368 if ( 'ontouchstart' in document.documentElement && ! $parent.closest( '.navbar-nav' ).length ) {
1369 // if mobile we use a backdrop because click events don't delegate
1370 $( '<div class="dropdown-backdrop"/>' ).insertAfter( $( this ) ).on( 'click', clearMenus );
1371 }
1372
1373 var relatedTarget = { relatedTarget: this };
1374 $parent.trigger( event = $.Event( 'show.bs.dropdown', relatedTarget ) );
1375
1376 if ( event.isDefaultPrevented() ) {
1377 return;
1378 }
1379
1380 $parent
1381 .toggleClass( 'open' )
1382 .trigger( 'shown.bs.dropdown', relatedTarget);
1383
1384 $this.focus();
1385 }
1386
1387 return false;
1388 };
1389
1390 Dropdown.prototype.keydown = function( event ) {
1391 if ( ! /(38|40|27)/.test( event.keyCode ) ) {
1392 return;
1393 }
1394
1395 var $this = $( this );
1396
1397 event.preventDefault();
1398 event.stopPropagation();
1399
1400 if ( $this.is( '.disabled, :disabled' ) ) {
1401 return;
1402 }
1403
1404 var $parent = getParent( $this );
1405 var isActive = $parent.hasClass( 'open' );
1406
1407 if ( ! isActive || ( isActive && event.keyCode === 27 ) ) {
1408 if ( event.which === 27 ) {
1409 $parent.find( toggle ).focus();
1410 }
1411 return $this.click();
1412 }
1413
1414 var desc = ' li:not(.divider):visible a';
1415 var $items = $parent.find( '[role=menu]' + desc + ', [role=listbox]' + desc);
1416
1417 if ( ! $items.length ) {
1418 return;
1419 }
1420
1421 var index = $items.index($items.filter( ':focus' ));
1422
1423 if ( event.keyCode === 38 && index > 0 ) {
1424 index--; // up
1425 }
1426 if ( event.keyCode === 40 && index < $items.length - 1 ) {
1427 index++; // down
1428 }
1429 if ( ! ~index ) {
1430 index = 0;
1431 }
1432
1433 $items.eq(index).focus();
1434 };
1435
1436 function clearMenus( event ) {
1437 $(backdrop).remove();
1438 $(toggle).each( function() {
1439 var $parent = getParent($( this ));
1440 var relatedTarget = { relatedTarget: this };
1441 if ( ! $parent.hasClass( 'open' ) ) {
1442 return;
1443 }
1444 $parent.trigger( event = $.Event( 'hide.bs.dropdown', relatedTarget ) );
1445 if ( event.isDefaultPrevented() ) {
1446 return;
1447 }
1448 $parent.removeClass( 'open' ).trigger( 'hidden.bs.dropdown', relatedTarget);
1449 });
1450 }
1451
1452 function getParent( $this ) {
1453 var selector = $this.attr( 'data-target' );
1454
1455 if ( ! selector ) {
1456 selector = $this.attr( 'href' );
1457 selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '' ); // strip for ie7
1458 }
1459
1460 var $parent = selector && $(selector);
1461
1462 return $parent && $parent.length ? $parent : $this.parent();
1463 }
1464
1465 // DROPDOWN PLUGIN DEFINITION
1466 // ==========================
1467 var old = $.fn.dropdown;
1468 $.fn.dropdown = function( option ) {
1469 return this.each( function() {
1470 var $this = $( this );
1471 var data = $this.data( 'bs.dropdown' );
1472
1473 if ( ! data ) {
1474 $this.data( 'bs.dropdown', ( data = new Dropdown( this ) ) );
1475 }
1476 if ( 'string' === typeof option ) {
1477 data[option].call( $this );
1478 }
1479 });
1480 };
1481 $.fn.dropdown.Constructor = Dropdown;
1482
1483 // DROPDOWN NO CONFLICT
1484 // ====================
1485 $.fn.dropdown.noConflict = function() {
1486 $.fn.dropdown = old;
1487 return this;
1488 };
1489
1490 // APPLY TO STANDARD DROPDOWN ELEMENTS
1491 // ===================================
1492 $(document)
1493 .on( 'click.bs.dropdown.data-api', clearMenus)
1494 .on( 'click.bs.dropdown.data-api', '.dropdown form', function( event ) { event.stopPropagation(); })
1495 .on( 'click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle)
1496 .on( 'keydown.bs.dropdown.data-api', toggle + ', [role=menu], [role=listbox]', Dropdown.prototype.keydown);
1497
1498 } )( jQuery );
1499