PluginProbe
Authorizer / 2.9.8
Authorizer v2.9.8
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 2.9.8, at js/authorizer.js

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