PluginProbe
Authorizer / 3.9.0
Authorizer v3.9.0
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.9.0, at js/authorizer.js

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