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