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

authorizer.php in Authorizer 2.3.0, at authorizer.php

4,177 lines 194.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /*
3 Plugin Name: Authorizer
4 Plugin URI: https://github.com/figureone/authorizer
5 Description: Authorizer limits login attempts, restricts access to specified users, and authenticates against external sources (e.g., Google, LDAP, or CAS).
6 Version: 2.3.0
7 Author: Paul Ryan
8 Author URI: http://www.linkedin.com/in/paulrryan/
9 License: GPL2
10 */
11
12 /*
13 Copyright 2014 Paul Ryan (email: prar@hawaii.edu)
14
15 This program is free software; you can redistribute it and/or modify
16 it under the terms of the GNU General Public License, version 2, as
17 published by the Free Software Foundation.
18
19 This program is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 GNU General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27 */
28
29 /*
30 Portions forked from Restricted Site Access plugin: http://wordpress.org/plugins/restricted-site-access/
31 Portions forked from wpCAS plugin: http://wordpress.org/extend/plugins/cas-authentication/
32 Portions forked from Limit Login Attempts: http://wordpress.org/plugins/limit-login-attempts/
33 */
34
35 // Add phpCAS library if it's not included.
36 // @see https://wiki.jasig.org/display/CASC/phpCAS+installation+guide
37 if ( ! defined( 'PHPCAS_VERSION' ) ) {
38 require_once dirname( __FILE__ ) . '/inc/CAS-1.3.3/CAS.php';
39 }
40
41 // Add Google API PHP Client if it's not included.
42 // @see https://github.com/google/google-api-php-client
43 if ( ! class_exists( 'Google_Client' ) ) {
44 set_include_path( get_include_path() . PATH_SEPARATOR . dirname( __FILE__ ) . '/inc/google-api-php-client/src' );
45 require_once dirname( __FILE__ ) . '/inc/google-api-php-client/src/Google/Client.php';
46 }
47
48 if ( ! class_exists( 'WP_Plugin_Authorizer' ) ) {
49 /**
50 * Define class for plugin: Authorizer.
51 *
52 * @category Authentication
53 * @package Authorizer
54 * @author Paul Ryan <prar@hawaii.edu>
55 * @license http://www.gnu.org/licenses/gpl-2.0.html GPL2
56 * @link http://hawaii.edu/coe/dcdc/wordpress/authorizer/doc/
57 */
58 class WP_Plugin_Authorizer {
59
60 /**
61 * Constructor.
62 */
63 public function __construct() {
64 // Installation and uninstallation hooks.
65 register_activation_hook( __FILE__, array( $this, 'activate' ) );
66 register_deactivation_hook( __FILE__, array( $this, 'deactivate' ) );
67
68 // Register filters.
69
70 // Custom wp authentication routine using external service.
71 add_filter( 'authenticate', array( $this, 'custom_authenticate' ), 1, 3 );
72
73 // Custom logout action using external service.
74 add_action( 'wp_logout', array( $this, 'custom_logout' ) );
75
76 // Removing this bypasses Wordpress authentication (so if external auth fails,
77 // no one can log in); with it enabled, it will run if external auth fails.
78 //remove_filter('authenticate', 'wp_authenticate_username_password', 20, 3);
79
80 // Create settings link on Plugins page
81 add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), array( $this, 'plugin_settings_link' ) );
82 add_filter( 'network_admin_plugin_action_links_' . plugin_basename( __FILE__ ), array( $this, 'network_admin_plugin_settings_link' ) );
83
84 // Modify login page with a custom password url (if option is set).
85 add_filter( 'lostpassword_url', array( $this, 'custom_lostpassword_url' ) );
86
87 // If we have a custom login error, add the filter to show it.
88 $error = get_option( 'auth_settings_advanced_login_error' );
89 if ( $error && strlen( $error ) > 0 ) {
90 add_filter( 'login_errors', array( $this, 'show_advanced_login_error' ) );
91 }
92
93 // Register actions.
94
95 // Perform plugin updates if newer version installed.
96 add_action( 'plugins_loaded', array( $this, 'auth_update_check' ) );
97
98 // Update the user meta with this user's failed login attempt.
99 add_action( 'wp_login_failed', array( $this, 'update_login_failed_count' ) );
100
101 // Create menu item in Settings
102 add_action( 'admin_menu', array( $this, 'add_plugin_page' ) );
103
104 // Create options page
105 add_action( 'admin_init', array( $this, 'page_init' ) );
106
107 // Update user role in approved list if it's changed in the WordPress edit user page.
108 add_action( 'edit_user_profile_update', array( $this, 'edit_user_profile_update_role' ) );
109
110 // Enqueue javascript and css on the plugin's options page, the
111 // dashboard (for the widget), and the network admin.
112 add_action( 'load-settings_page_authorizer', array( $this, 'load_options_page' ) );
113 add_action( 'admin_head-index.php', array( $this, 'load_options_page' ) );
114 add_action( 'load-toplevel_page_authorizer', array( $this, 'load_options_page' ) );
115
116 // Add custom css and js to wp-login.php
117 add_action( 'login_enqueue_scripts', array( $this, 'login_enqueue_scripts_and_styles' ) );
118 add_action( 'login_footer', array( $this, 'load_login_footer_js' ) );
119
120 // Modify login page with external auth links (if enabled; e.g., google or cas)
121 add_action( 'login_form', array( $this, 'login_form_add_external_service_links' ) );
122
123 // Verify current user has access to page they are visiting
124 add_action( 'parse_request', array( $this, 'restrict_access' ), 1 );
125
126 // ajax save options from dashboard widget
127 add_action( 'wp_ajax_update_auth_user', array( $this, 'ajax_update_auth_user' ) );
128
129 // ajax save options from multisite options page
130 add_action( 'wp_ajax_save_auth_multisite_settings', array( $this, 'ajax_save_auth_multisite_settings' ) );
131
132 // ajax save usermeta from options page
133 add_action( 'wp_ajax_update_auth_usermeta', array( $this, 'ajax_update_auth_usermeta' ) );
134
135 // ajax verify google login
136 add_action( 'wp_ajax_process_google_login', array( $this, 'ajax_process_google_login' ) );
137 add_action( 'wp_ajax_nopriv_process_google_login', array( $this, 'ajax_process_google_login' ) );
138
139 // Add dashboard widget so instructors can add/edit users with access.
140 // Hint: For Multisite Network Admin Dashboard use wp_network_dashboard_setup instead of wp_dashboard_setup.
141 add_action( 'wp_dashboard_setup', array( $this, 'add_dashboard_widgets' ) );
142
143 // If we have a custom admin message, add the action to show it.
144 $notice = get_option( 'auth_settings_advanced_admin_notice' );
145 if ( $notice && strlen( $notice ) > 0 ) {
146 add_action( 'admin_notices', array( $this, 'show_advanced_admin_notice' ) );
147 add_action( 'network_admin_notices', array( $this, 'show_advanced_admin_notice' ) );
148 }
149
150 // Load custom javascript for the main site (e.g., for displaying alerts).
151 add_action( 'wp_enqueue_scripts', array( $this, 'auth_public_scripts' ), 20 );
152
153 // If multisite, add network admin options page (global settings for all sites)
154 if ( is_multisite() ) {
155 add_action( 'network_admin_menu', array( $this, 'network_admin_menu' ) );
156 }
157
158 // Create login cookie (used by google login)
159 if ( ! isset( $_COOKIE['login_unique'] ) ) {
160 setcookie( 'login_unique', $this->get_cookie_value(), time()+1800, '/', defined( COOKIE_DOMAIN ) ? COOKIE_DOMAIN : '' );
161 }
162
163 } // END __construct()
164
165
166 /**
167 * Plugin activation hook.
168 * Will also activate the plugin for all sites/blogs if this is a "Network enable."
169 *
170 * @return void
171 */
172 public function activate() {
173 global $wpdb;
174
175 // If we're in a multisite environment, run the plugin activation for each site when network enabling
176 if ( is_multisite() && isset( $_GET['networkwide'] ) && $_GET['networkwide'] == 1 ) {
177 $old_blog = $wpdb->blogid;
178 // Get all blog ids
179 $blogs = wp_get_sites( array( 'limit' => 999999 ) );
180 foreach ( $blogs as $blog ) {
181 switch_to_blog( $blog['blog_id'] );
182 // Set meaningful defaults for other sites in the network.
183 $this->set_default_options();
184 // Add current WordPress users to the approved list.
185 $this->add_wp_users_to_approved_list();
186 }
187 switch_to_blog( $old_blog );
188 } else {
189 // Set meaningful defaults for this site.
190 $this->set_default_options();
191 // Add current WordPress users to the approved list.
192 $this->add_wp_users_to_approved_list();
193 }
194
195 } // END activate()
196
197 /**
198 * Adds all WordPress users in the current site to the approved list,
199 * unless they are already in the blocked list. Also removes them
200 * from the pending list if they are there.
201 *
202 * Runs in plugin activation hook.
203 *
204 * @return void
205 */
206 private function add_wp_users_to_approved_list() {
207 // Add current WordPress users to the approved list.
208 $auth_multisite_settings_access_users_approved = is_multisite() ? get_blog_option( BLOG_ID_CURRENT_SITE, 'auth_multisite_settings_access_users_approved', array() ) : array();
209 $auth_settings_access_users_pending = $this->get_plugin_option( 'access_users_pending', 'single admin' );
210 $auth_settings_access_users_approved = $this->get_plugin_option( 'access_users_approved', 'single admin' );
211 $auth_settings_access_users_blocked = $this->get_plugin_option( 'access_users_blocked', 'single admin' );
212 $default_role = $this->get_plugin_option( 'access_default_role', 'single admin', 'allow override' );
213 $updated = false;
214 foreach ( get_users() as $user ) {
215 // Skip if user is in blocked list.
216 if ( $this->in_multi_array( $user->user_email, $auth_settings_access_users_blocked ) ) {
217 continue;
218 }
219 // Skip if user is in multisite approved list.
220 if ( $this->in_multi_array( $user->user_email, $auth_multisite_settings_access_users_approved ) ) {
221 continue;
222 }
223 // Add to approved list if not there.
224 if ( ! $this->in_multi_array( $user->user_email, $auth_settings_access_users_approved ) ) {
225 $approved_user = array(
226 'email' => $user->user_email,
227 'role' => count( $user->roles ) > 0 ? $user->roles[0] : $default_role,
228 'date_added' => date( 'M Y', strtotime( $user->user_registered ) ),
229 'local_user' => true,
230 );
231 array_push( $auth_settings_access_users_approved, $approved_user );
232 $updated = true;
233 }
234 // Remove from pending list if there.
235 foreach ( $auth_settings_access_users_pending as $key => $pending_user ) {
236 if ( $pending_user['email'] == $user->user_email ) {
237 unset( $auth_settings_access_users_pending[$key] );
238 $updated = true;
239 }
240 }
241 }
242 if ( $updated ) {
243 update_option( 'auth_settings_access_users_pending', $auth_settings_access_users_pending );
244 update_option( 'auth_settings_access_users_approved', $auth_settings_access_users_approved );
245 }
246 }
247
248
249 /**
250 * Plugin deactivation.
251 *
252 * @return void
253 */
254 public function deactivate() {
255 // Do nothing.
256 } // END deactivate()
257
258
259
260 /**
261 * ***************************
262 * External Authentication
263 * ***************************
264 */
265
266
267
268 /**
269 * Authenticate against an external service.
270 *
271 * @param WP_User $user user to authenticate
272 * @param string $username optional username to authenticate.
273 * @param string $password optional password to authenticate.
274 *
275 * @return WP_User or WP_Error
276 */
277 public function custom_authenticate( $user, $username, $password ) {
278 // Pass through if already authenticated.
279 if ( is_a( $user, 'WP_User' ) ) {
280 return $user;
281 } else {
282 $user = null;
283 }
284
285 // If username and password are blank, this isn't a log in attempt
286 $is_login_attempt = strlen( $username ) > 0 && strlen( $password ) > 0;
287
288 // Check to make sure that $username is not locked out due to too
289 // many invalid login attempts. If it is, tell the user how much
290 // time remains until they can try again.
291 $unauthenticated_user = $is_login_attempt ? get_user_by( 'login', $username ) : false;
292 $unauthenticated_user_is_blocked = false;
293 if ( $is_login_attempt && $unauthenticated_user !== false ) {
294 $last_attempt = get_user_meta( $unauthenticated_user->ID, 'auth_settings_advanced_lockouts_time_last_failed', true );
295 $num_attempts = get_user_meta( $unauthenticated_user->ID, 'auth_settings_advanced_lockouts_failed_attempts', true );
296 // Also check the auth_blocked user_meta flag (users in blocked list will get this flag)
297 $unauthenticated_user_is_blocked = get_user_meta( $unauthenticated_user->ID, 'auth_blocked', true ) === 'yes';
298 } else {
299 $last_attempt = get_option( 'auth_settings_advanced_lockouts_time_last_failed' );
300 $num_attempts = get_option( 'auth_settings_advanced_lockouts_failed_attempts' );
301 }
302
303 // Inactive users should be treated like deleted users (we just
304 // do this to preserve any content they created, but here we should
305 // pretend they don't exist).
306 if ( $unauthenticated_user_is_blocked ) {
307 remove_filter( 'authenticate', 'wp_authenticate_username_password', 20, 3 );
308 return new WP_Error( 'empty_password', __( '<strong>ERROR</strong>: Incorrect username or password.' ) );
309 }
310
311 // Grab plugin settings.
312 $auth_settings = $this->get_plugin_options( 'single admin', 'allow override' );
313
314 // Make sure $last_attempt (time) and $num_attempts are positive integers.
315 // Note: this addresses resetting them if either is unset from above.
316 $last_attempt = abs( intval( $last_attempt ) );
317 $num_attempts = abs( intval( $num_attempts ) );
318
319 // Create semantic lockout variables.
320 $lockouts = $auth_settings['advanced_lockouts'];
321 $time_since_last_fail = time() - $last_attempt;
322 $reset_duration = $lockouts['reset_duration'] * 60; // minutes to seconds
323 $num_attempts_long_lockout = $lockouts['attempts_1'] + $lockouts['attempts_2'];
324 $num_attempts_short_lockout = $lockouts['attempts_1'];
325 $seconds_remaining_long_lockout = $lockouts['duration_2'] * 60 - $time_since_last_fail;
326 $seconds_remaining_short_lockout = $lockouts['duration_1'] * 60 - $time_since_last_fail;
327
328 // Check if we need to institute a lockout delay
329 if ( $is_login_attempt && $time_since_last_fail > $reset_duration ) {
330 // Enough time has passed since the last invalid attempt and
331 // now that we can reset the failed attempt count, and let this
332 // login attempt go through.
333 $num_attempts = 0; // This does nothing, but include it for semantic meaning.
334 } elseif ( $is_login_attempt && $num_attempts > $num_attempts_long_lockout && $seconds_remaining_long_lockout > 0 ) {
335 // Stronger lockout (1st/2nd round of invalid attempts reached)
336 // Note: set the error code to 'empty_password' so it doesn't
337 // trigger the wp_login_failed hook, which would continue to
338 // increment the failed attempt count.
339 remove_filter( 'authenticate', 'wp_authenticate_username_password', 20, 3 );
340 return new WP_Error( 'empty_password', sprintf( __( '<strong>ERROR</strong>: There have been too many invalid login attempts for the username <strong>%1$s</strong>. Please wait <strong id="seconds_remaining" data-seconds="%2$s">%3$s</strong> before trying again. <a href="%4$s" title="Password Lost and Found">Lost your password</a>?' ), $username, $seconds_remaining_long_lockout, $this->seconds_as_sentence( $seconds_remaining_long_lockout ), wp_lostpassword_url() ) );
341 } elseif ( $is_login_attempt && $num_attempts > $num_attempts_short_lockout && $seconds_remaining_short_lockout > 0 ) {
342 // Normal lockout (1st round of invalid attempts reached)
343 // Note: set the error code to 'empty_password' so it doesn't
344 // trigger the wp_login_failed hook, which would continue to
345 // increment the failed attempt count.
346 remove_filter( 'authenticate', 'wp_authenticate_username_password', 20, 3 );
347 return new WP_Error( 'empty_password', sprintf( __( '<strong>ERROR</strong>: There have been too many invalid login attempts for the username <strong>%1$s</strong>. Please wait <strong id="seconds_remaining" data-seconds="%2$s">%3$s</strong> before trying again. <a href="%4$s" title="Password Lost and Found">Lost your password</a>?' ), $username, $seconds_remaining_short_lockout, $this->seconds_as_sentence( $seconds_remaining_short_lockout ), wp_lostpassword_url() ) );
348 }
349
350 // Start external authentication.
351 $externally_authenticated_email = '';
352 $authenticated_by = '';
353
354 // Try Google authentication if it's enabled and we don't have a
355 // successful login yet.
356 if ( $auth_settings['google'] === '1' ) {
357 $result = $this->custom_authenticate_google( $auth_settings );
358 if ( ! is_wp_error( $result ) ) {
359 $externally_authenticated_email = $result['email'];
360 $authenticated_by = $result['authenticated_by'];
361 }
362 }
363
364 // Try CAS authentication if it's enabled and we don't have a
365 // successful login yet.
366 if ( $auth_settings['cas'] === '1' && strlen( $externally_authenticated_email ) === 0 ) {
367 $result = $this->custom_authenticate_cas( $auth_settings );
368 if ( ! is_wp_error( $result ) ) {
369 $externally_authenticated_email = $result['email'];
370 $authenticated_by = $result['authenticated_by'];
371 }
372 }
373
374 // Try LDAP authentication if it's enabled and we don't have an
375 // authenticated user yet.
376 if ( $auth_settings['ldap'] === '1' && strlen( $externally_authenticated_email ) === 0 ) {
377 $result = $this->custom_authenticate_ldap( $auth_settings, $username, $password );
378 if ( ! is_wp_error( $result ) ) {
379 $externally_authenticated_email = $result['email'];
380 $authenticated_by = $result['authenticated_by'];
381 }
382 }
383
384 // Skip to WordPress authentication if we don't have an externally
385 // authenticated user.
386 if ( strlen( $externally_authenticated_email ) < 1 ) {
387 return null;
388 }
389
390 // If we've made it this far, we should have an externally
391 // authenticated user. The following should be set:
392 // $externally_authenticated_email
393 // $authenticated_by
394
395 // Get the external user's WordPress account by email address.
396 $user = get_user_by( 'email', $externally_authenticated_email );
397
398 // Check this external user's access against the access lists
399 // (pending, approved, blocked)
400 $result = $this->check_user_access( $user, $externally_authenticated_email );
401
402 // Fail with message if error.
403 if ( is_wp_error( $result ) ) {
404 return $result;
405 }
406
407 // If we created a new user in check_user_access(), log that user in.
408 if ( get_class( $result ) === 'WP_User' ) {
409 $user = $result;
410 }
411
412 // We'll track how this user was authenticated in user meta.
413 if ( $user ) {
414 update_user_meta( $user->ID, 'authenticated_by', $authenticated_by );
415 }
416
417 // If we haven't exited yet, we have a valid/approved user, so authenticate them.
418 return $user;
419 } // END custom_authenticate()
420
421
422 /**
423 * This function will fail with a wp_die() message to the user if they
424 * don't have access.
425 *
426 * @param WP_User $user User to check
427 * @param [type] $user_email User's plaintext email (in case current user doesn't have a WP account)
428 * @return WP_Error if there was an error on user creation / adding user to blog
429 * wp_die() if user does not have access
430 * null if user has access (success)
431 */
432 private function check_user_access( $user, $user_email ) {
433 // Grab plugin settings.
434 $auth_settings = $this->get_plugin_options( 'single admin', 'allow override' );
435 $auth_settings_access_users_pending = $this->sanitize_user_list(
436 $this->get_plugin_option( 'access_users_pending', 'single admin' )
437 );
438 $auth_settings_access_users_approved = $this->sanitize_user_list(
439 array_merge(
440 $this->get_plugin_option( 'access_users_approved', 'single admin' ),
441 $this->get_plugin_option( 'access_users_approved', 'multisite admin' )
442 )
443 );
444
445 // Check our externally authenticated user against the block list.
446 // If they are blocked, set the relevant user meta field, and show
447 // them an error screen.
448 if ( $this->is_email_in_list( $user_email, 'blocked' ) ) {
449 // If the blocked external user has a WordPress account, change
450 // its password and mark it as blocked.
451 if ( $user ) {
452 // Mark user as blocked (enforce block in this->authenticate()).
453 update_user_meta( $user->ID, 'auth_blocked', 'yes' );
454 }
455
456 // Notify user about blocked status and return without authenticating them.
457 $redirect_to = ! empty( $_REQUEST['redirect_to'] ) ? $_REQUEST['redirect_to'] : home_url();
458 $page_title = get_bloginfo( 'name' ) . ' - Access Restricted';
459 $error_message = apply_filters( 'the_content', $auth_settings['access_blocked_redirect_to_message'] );
460 $error_message .= '<hr /><p style="text-align: center;"><a class="button" href="' . wp_logout_url( $redirect_to ) . '">Back</a></p>';
461 update_option( 'auth_settings_advanced_login_error', $error_message );
462 wp_die( $error_message, $page_title );
463 }
464
465 // If this externally authenticated user isn't in the approved list
466 // and login access is set to "All authenticated users," add them
467 // to the approved list (they'll get an account created below if
468 // they don't have one yet).
469 if ( ! $this->is_email_in_list( $user_email, 'approved' ) && $auth_settings['access_who_can_login'] === 'external_users' ) {
470 // If this user happens to be in the pending list (rare),
471 // remove them from pending before adding them to approved.
472 if ( $this->is_email_in_list( $user_email, 'pending' ) ) {
473 foreach ( $auth_settings_access_users_pending as $key => $pending_user ) {
474 if ( $pending_user['email'] === $user_email ) {
475 unset( $auth_settings_access_users_pending[ $key ] );
476 break;
477 }
478 }
479 }
480
481 // Add this user to the approved list.
482 $approved_role = $user && is_array( $user->roles ) && count( $user->roles ) > 0 ? $user->roles[0] : $auth_settings['access_default_role'];
483 $approved_user = array(
484 'email' => $user_email,
485 'role' => $approved_role,
486 'date_added' => date( "Y-m-d H:i:s" ),
487 );
488 array_push( $auth_settings_access_users_approved, $approved_user );
489 update_option( 'auth_settings_access_users_approved', $auth_settings_access_users_approved );
490 }
491
492 // Check our externally authenticated user against the approved
493 // list. If they are approved, log them in (and create their account
494 // if necessary)
495 if ( $this->is_email_in_list( $user_email, 'approved' ) ) {
496 $user_info = $this->get_user_info_from_list( $user_email, $auth_settings_access_users_approved );
497
498 // If the approved external user does not have a WordPress account, create it
499 if ( ! $user ) {
500 // If there's already a user with this username (e.g.,
501 // johndoe/johndoe@gmail.com exists, and we're trying to add
502 // johndoe/johndoe@example.com), use the full email address
503 // as the username.
504 $username = explode( "@", $user_info['email'] );
505 $username = $username[0];
506 if ( get_user_by( 'login', $username ) !== false ) {
507 $username = $approved_user['email'];
508 }
509 $result = wp_insert_user(
510 array(
511 'user_login' => strtolower( $username ),
512 'user_pass' => wp_generate_password(), // random password
513 'first_name' => '',
514 'last_name' => '',
515 'user_email' => strtolower( $user_info['email'] ),
516 'user_registered' => date( 'Y-m-d H:i:s' ),
517 'role' => $user_info['role'],
518 )
519 );
520
521 // Fail with message if error.
522 if ( is_wp_error( $result ) ) {
523 return $result;
524 }
525
526 // Authenticate as new user
527 $user = new WP_User( $result );
528 }
529
530 // If this is multisite, add new user to current blog.
531 if ( is_multisite() && ! is_user_member_of_blog( $user->ID ) ) {
532 $result = add_user_to_blog( get_current_blog_id(), $user->ID, $user_info['role'] );
533
534 // Fail with message if error.
535 if ( is_wp_error( $result ) ) {
536 return $result;
537 }
538 }
539
540 // Ensure user has the same role as their entry in the approved list.
541 // (This is just a precaution, the role should already be set when
542 // saving admin options in the sanitizing function.)
543 if ( $user_info && ! array_key_exists( $user_info['role'], $user->roles ) ) {
544 $user->set_role( $user_info['role'] );
545 }
546
547 return $user;
548
549 } elseif ( $user && in_array( 'administrator', $user->roles ) ) {
550 // User has a WordPress account, but is not in the blocked or approved
551 // list. If they are an administrator, let them in.
552 return;
553 } else {
554 // User isn't an admin, is not blocked, and is not approved.
555 // Add them to the pending list and notify them and their instructor.
556 if ( strlen( $user_email ) > 0 && ! $this->is_email_in_list( $user_email, 'pending' ) ) {
557 $pending_user = array();
558 $pending_user['email'] = $user_email;
559 $pending_user['role'] = $auth_settings['access_default_role'];
560 $pending_user['date_added'] = '';
561 array_push( $auth_settings_access_users_pending, $pending_user );
562 update_option( 'auth_settings_access_users_pending', $auth_settings_access_users_pending );
563
564 // Create strings used in the email notification.
565 $site_name = get_bloginfo( 'name' );
566 $site_url = get_bloginfo( 'url' );
567 $authorizer_options_url = $auth_settings['advanced_admin_menu'] === 'settings' ? admin_url( 'options-general.php?page=authorizer' ) : admin_url( '?page=authorizer' );
568
569 // Notify instructor about new pending user if that option is set.
570 foreach ( get_users( array( 'role' => $auth_settings['access_role_receive_pending_emails'] ) ) as $user_recipient ) {
571 wp_mail(
572 $user_recipient->user_email,
573 "Action required: Pending user {$pending_user['email']} at $site_name",
574 "A new user has tried to access the $site_name site you manage at:\n$site_url\n\n" .
575 "Please log in to approve or deny their request:\n$authorizer_options_url\n"
576 );
577 }
578 }
579
580 // Notify user about pending status and return without authenticating them.
581 $redirect_to = ! empty( $_REQUEST['redirect_to'] ) ? $_REQUEST['redirect_to'] : home_url();
582 $page_title = get_bloginfo( 'name' ) . ' - Access Pending';
583 $error_message = apply_filters( 'the_content', $auth_settings['access_pending_redirect_to_message'] );
584 $error_message .= '<hr /><p style="text-align: center;"><a class="button" href="' . wp_logout_url( $redirect_to ) . '">Back</a></p>';
585 update_option( 'auth_settings_advanced_login_error', $error_message );
586 wp_die( $error_message, $page_title );
587 }
588
589 } // END check_user_access()
590
591
592 /**
593 * Verify the Google login and set a session token.
594 *
595 * Flow: "Sign in with Google" button clicked; JS Google library
596 * called; JS function signInCallback() fired with results from Google;
597 * signInCallback() posts code and nonce (via AJAX) to this function;
598 * This function checks the token using the Google PHP library, and
599 * saves it to a session variable if it's authentic; control passes
600 * back to signInCallback(), which will reload the current page
601 * (wp-login.php) on success; wp-login.php reloads; custom_authenticate
602 * hooked into authenticate action fires again, and
603 * custom_authenticate_google() runs to verify the token; once verified
604 * custom_authenticate proceeds as normal with the google email address
605 * as a successfully authenticated external user.
606 *
607 * @return void, but die with the value to return to the success() function in AJAX call signInCallback()
608 */
609 function ajax_process_google_login() {
610 $nonce = array_key_exists( 'nonce', $_POST ) ? $_POST['nonce'] : '';
611 $code = array_key_exists( 'code', $_POST ) ? $_POST['code'] : null;
612
613 // Nonce check.
614 if ( ! wp_verify_nonce( $nonce, 'google_csrf_nonce' ) ) {
615 return '';
616 }
617
618 // Grab plugin settings.
619 $auth_settings = $this->get_plugin_options( 'single admin', 'allow override' );
620
621 // Build the Google Client.
622 $client = new Google_Client();
623 $client->setApplicationName( 'WordPress' );
624 $client->setClientId( $auth_settings['google_clientid'] );
625 $client->setClientSecret( $auth_settings['google_clientsecret'] );
626 $client->setRedirectUri( 'postmessage' );
627
628 // Get one time use token (if it doesn't exist, we'll create one below)
629 session_start();
630 $token = array_key_exists( 'token', $_SESSION ) ? json_decode( $_SESSION['token'] ) : null;
631
632 if ( empty( $token ) ) {
633 // Exchange the OAuth 2.0 authorization code for user credentials.
634 $client->authenticate( $code );
635 $token = json_decode( $client->getAccessToken() );
636
637 // Store the token in the session for later use.
638 $_SESSION['token'] = json_encode( $token );
639
640 $response = "Successfully authenticated.";
641 } else {
642 $client->setAccessToken( json_encode( $token ) );
643
644 $response = 'Already authenticated.';
645 }
646
647 die( $response );
648 } // END ajax_process_google_login()
649
650
651 /**
652 * Validate this user's credentials against Google.
653 *
654 * @param array $auth_settings Plugin settings
655 * @return [mixed] Array containing 'email' and 'authenticated_by'
656 * strings for the successfully authenticated
657 * user, or WP_Error() object on failure.
658 */
659 private function custom_authenticate_google( $auth_settings ) {
660 // Get one time use token
661 session_start();
662 $token = array_key_exists( 'token', $_SESSION ) ? json_decode( $_SESSION['token'] ) : null;
663
664 // No token, so this is not a succesful Google login.
665 if ( is_null( $token ) ) {
666 return new WP_Error( 'no_google_login', 'No Google credentials provided.' );
667 }
668
669 // Build the Google Client.
670 $client = new Google_Client();
671 $client->setApplicationName( 'WordPress' );
672 $client->setClientId( $auth_settings['google_clientid'] );
673 $client->setClientSecret( $auth_settings['google_clientsecret'] );
674 $client->setRedirectUri( 'postmessage' );
675
676 // Verify this is a successful Google authentication
677 $ticket = $client->verifyIdToken( $token->id_token, $auth_settings['google_clientid'] );
678
679 // Invalid ticket, so this in not a successful Google login.
680 if ( ! $ticket ) {
681 return new WP_Error( 'invalid_google_login', 'Invalid Google credentials provided.' );
682 }
683
684 // Get email address
685 $attributes = $ticket->getAttributes();
686 $email = $attributes['payload']['email'];
687
688 return array(
689 'email' => $email,
690 'authenticated_by' => 'google',
691 );
692 } // END custom_authenticate_google()
693
694
695 /**
696 * Validate this user's credentials against CAS.
697 *
698 * @param array $auth_settings Plugin settings
699 * @return [mixed] Array containing 'email' and 'authenticated_by'
700 * strings for the successfully authenticated
701 * user, or WP_Error() object on failure.
702 */
703 private function custom_authenticate_cas( $auth_settings ) {
704 // Move on if CAS hasn't been requested here.
705 if ( empty( $_GET['external'] ) || $_GET['external'] !== 'cas' ) {
706 return new WP_Error( 'cas_not_available', 'CAS is not enabled.' );
707 }
708
709 // Set the CAS client configuration
710 phpCAS::client( SAML_VERSION_1_1, $auth_settings['cas_host'], intval( $auth_settings['cas_port'] ), $auth_settings['cas_path'] );
711
712 // Update server certificate bundle if it doesn't exist or is older
713 // than 3 months, then use it to ensure CAS server is legitimate.
714 $cacert_path = plugin_dir_path( __FILE__ ) . 'inc/cacert.pem';
715 $time_90_days = 90 * 24 * 60 * 60; // days * hours * minutes * seconds
716 $time_90_days_ago = time() - $time_90_days;
717 if ( ! file_exists( $cacert_path ) || filemtime( $cacert_path ) < $time_90_days_ago ) {
718 $cacert_contents = file_get_contents( 'http://curl.haxx.se/ca/cacert.pem' );
719 if ( $cacert_contents !== false ) {
720 file_put_contents( $cacert_path, $cacert_contents );
721 } else {
722 return new WP_Error( 'cannot_update_cacert', 'Unable to update outdated server certificates from http://curl.haxx.se/ca/cacert.pem.' );
723 }
724 }
725 phpCAS::setCasServerCACert( $cacert_path );
726
727 // Authenticate against CAS
728 if ( ! phpCAS::isAuthenticated() ) {
729 phpCAS::forceAuthentication();
730 die();
731 }
732
733 // Get the TLD from the CAS host for use in matching email addresses
734 // For example: example.edu is the TLD for authn.example.edu, so user
735 // 'bob' will have the following email address: bob@example.edu.
736 $tld = preg_match( '/[^.]*\.[^.]*$/', $auth_settings['cas_host'], $matches ) === 1 ? $matches[0] : '';
737
738 // Get username that successfully authenticated against the external service (CAS).
739 $externally_authenticated_email = strtolower( phpCAS::getUser() ) . '@' . $tld;
740
741 // We'll track how this user was authenticated in user meta.
742 $authenticated_by = 'cas';
743
744 return array(
745 'email' => $externally_authenticated_email,
746 'authenticated_by' => $authenticated_by,
747 );
748 } // END custom_authenticate_cas()
749
750
751 /**
752 * Validate this user's credentials against LDAP.
753 *
754 * @param array $auth_settings Plugin settings
755 * @param string $username Attempted username from authenticate action
756 * @param string $password Attempted password from authenticate action
757 * @return [mixed] Array containing 'email' and 'authenticated_by'
758 * strings for the successfully authenticated
759 * user, or WP_Error() object on failure.
760 */
761 private function custom_authenticate_ldap( $auth_settings, $username, $password ) {
762 // Get the TLD from the LDAP host for use in matching email addresses
763 // For example: example.edu is the TLD for ldap.example.edu, so user
764 // 'bob' will have the following email address: bob@example.edu.
765 $tld = preg_match( '/[^.]*\.[^.]*$/', $auth_settings['ldap_host'], $matches ) === 1 ? $matches[0] : '';
766
767 // remove top level domain if it exists in the username (i.e., if user entered their email)
768 $username = str_replace( '@' . $tld, '', $username );
769
770 // Fail with error message if username or password is blank.
771 if ( empty( $username ) ) {
772 return null;
773 }
774 if ( empty( $password ) ) {
775 return new WP_Error( 'empty_password', 'You must provide a password.' );
776 }
777
778 // Make sure php5-ldap extension is installed on server.
779 if ( ! function_exists( 'ldap_connect' ) ) {
780 // Note: this error message won't get shown to the user because
781 // authenticate will fall back to WP auth when this fails.
782 return new WP_Error( 'ldap_not_installed', 'LDAP logins are disabled because this server does not support them.' );
783 }
784
785 // Authenticate against LDAP using options provided in plugin settings.
786 $result = false;
787 $ldap_user_dn = '';
788
789 $ldap = ldap_connect( $auth_settings['ldap_host'], $auth_settings['ldap_port'] );
790 ldap_set_option( $ldap, LDAP_OPT_PROTOCOL_VERSION, 3 );
791 if ( $auth_settings['ldap_tls'] == 1 ) {
792 ldap_start_tls( $ldap );
793 }
794 $result = @ldap_bind( $ldap, $auth_settings['ldap_user'], $this->decrypt( base64_decode( $auth_settings['ldap_password'] ) ) );
795 if ( ! $result ) {
796 // Can't connect to LDAP, so fall back to WordPress authentication.
797 return new WP_Error( 'ldap_error', 'Could not authenticate using LDAP.' );
798 }
799 // Look up the bind DN of the user trying to log in by
800 // performing an LDAP search for the login username in the
801 // field specified in the LDAP settings. This setup is common.
802 $ldap_search = ldap_search(
803 $ldap,
804 $auth_settings['ldap_search_base'],
805 "(" . $auth_settings['ldap_uid'] . "=" . $username . ")",
806 array( 'dn' ) // Just get the dn (no other attributes)
807 );
808 $ldap_entries = ldap_get_entries( $ldap, $ldap_search );
809
810 // If we didn't find any users in ldap, exit with error (rely on default wordpress authentication)
811 if ( $ldap_entries['count'] < 1 ) {
812 return new WP_Error( 'no_ldap', 'No LDAP user found.' );
813 }
814
815 // Get the bind dn; if there are multiple results returned, just get the last one.
816 for ( $i = 0; $i < $ldap_entries['count']; $i++ ) {
817 $ldap_user_dn = $ldap_entries[$i]['dn'];
818 }
819
820 $result = @ldap_bind( $ldap, $ldap_user_dn, $password );
821 if ( ! $result ) {
822 // We have a real ldap user, but an invalid password. Pass
823 // through to wp authentication after failing LDAP (since
824 // this could be a local account that happens to be the
825 // same name as an LDAP user).
826 return new WP_Error( 'using_wp_authentication', 'Moving on to WordPress authentication...' );
827 }
828
829 // User successfully authenticated against LDAP, so set the relevant variables.
830 $externally_authenticated_email = $username . '@' . $tld;
831
832 // We'll track how this user was authenticated in user meta.
833 $authenticated_by = 'ldap';
834
835 return array(
836 'email' => $externally_authenticated_email,
837 'authenticated_by' => 'ldap',
838 );
839 } // END custom_authenticate_ldap()
840
841
842 /**
843 * Log out of the attached external service.
844 *
845 * @return void
846 */
847 public function custom_logout() {
848 // Grab plugin settings.
849 $auth_settings = $this->get_plugin_options( 'single admin', 'allow override' );
850
851 // Reset option containing old error messages.
852 delete_option( 'auth_settings_advanced_login_error' );
853
854 if ( session_id() == '' ) {
855 session_start();
856 }
857
858 $current_user_authenticated_by = get_user_meta( get_current_user_id(), 'authenticated_by', true );
859
860 // If logged in to CAS, Log out of CAS.
861 if ( $current_user_authenticated_by === 'cas' && $auth_settings['cas'] === '1' ) {
862 if ( ! array_key_exists( 'PHPCAS_CLIENT', $GLOBALS ) || ! array_key_exists( 'phpCAS', $_SESSION ) ) {
863 // Set the CAS client configuration if it hasn't been set already.
864 phpCAS::client( SAML_VERSION_1_1, $auth_settings['cas_host'], intval( $auth_settings['cas_port'] ), $auth_settings['cas_path'] );
865 // Restrict logout request origin to the CAS server only (prevent DDOS).
866 phpCAS::handleLogoutRequests( true, array( $auth_settings['cas_host'] ) );
867 }
868 if ( phpCAS::isAuthenticated() ) {
869 phpCAS::logoutWithRedirectService( get_option( 'siteurl' ) );
870 }
871 }
872
873 // If session token set, log out of Google.
874 if ( $current_user_authenticated_by === 'google' && array_key_exists( 'token', $_SESSION ) ) {
875 $token = json_decode( $_SESSION['token'] )->access_token;
876
877 // Build the Google Client.
878 $client = new Google_Client();
879 $client->setApplicationName( 'WordPress' );
880 $client->setClientId( $auth_settings['google_clientid'] );
881 $client->setClientSecret( $auth_settings['google_clientsecret'] );
882 $client->setRedirectUri( 'postmessage' );
883
884 // Revoke the token
885 $client->revokeToken( $token );
886
887 // Remove the credentials from the user's session.
888 $_SESSION['token'] = '';
889 }
890
891 } // END custom_logout()
892
893
894
895 /**
896 * ***************************
897 * Access Restriction
898 * ***************************
899 */
900
901
902
903 /**
904 * Restrict access to WordPress site based on settings (everyone, logged_in_users).
905 * Hook: parse_request http://codex.wordpress.org/Plugin_API/Action_Reference/parse_request
906 *
907 * @param array $wp WordPress object.
908 *
909 * @return void
910 */
911 public function restrict_access( $wp ) {
912 remove_action( 'parse_request', array( $this, 'restrict_access' ), 1 ); // only need it the first time
913
914 // Grab plugin settings.
915 $auth_settings = $this->get_plugin_options( 'single admin', 'allow override' );
916
917 $has_access = (
918 // Always allow access if WordPress is installing
919 ( defined( 'WP_INSTALLING' ) && isset( $_GET['key'] ) ) ||
920 // Always allow access to admins
921 ( is_admin() ) ||
922 // Allow access if option is set to 'everyone'
923 ( $auth_settings['access_who_can_view'] == 'everyone' ) ||
924 // Allow access to approved external users and logged in users if option is set to 'logged_in_users'
925 ( $auth_settings['access_who_can_view'] == 'logged_in_users' && $this->is_user_logged_in_and_blog_user() )
926 );
927
928 /**
929 * Developers can use the `authorizer_has_access` filter
930 * to override restricted access on certain pages. Note that the
931 * restriction checks happens before WordPress executes any queries, so
932 * use the global `$wp` variable to investigate what the visitor is
933 * trying to load.
934 *
935 * For example, to unblock an RSS feed, place the following PHP code in
936 * the theme's functions.php file or in a simple plug-in:
937 *
938 * function my_rsa_feed_access_override( $has_access ) {
939 * global $wp;
940 * // check query variables to see if this is the feed
941 * if ( ! empty( $wp->query_vars['feed'] ) )
942 * $has_access = true;
943 * return $has_access;
944 * }
945 * add_filter( 'authorizer_has_access', 'my_rsa_feed_access_override' );
946 */
947 if ( apply_filters( 'authorizer_has_access', $has_access, $wp ) === true ) {
948 // Turn off the public notice about browsing anonymously
949 update_option( 'auth_settings_advanced_public_notice', false );
950
951 // We've determined that the current user has access, so simply return to grant access.
952 return;
953 }
954
955 // We've determined that the current user doesn't have access, so we deal with them now.
956
957 // Fringe case: In a multisite, a user of a different blog can
958 // successfully log in, but they aren't on the 'approved' whitelist
959 // for this blog. Flag these users, and redirect them to their
960 // profile page with a message (so we don't get into a redirect
961 // loop on the wp-login.php page).
962 if ( is_multisite() && is_user_logged_in() && ! $has_access ) {
963 $current_user = wp_get_current_user();
964
965 // Check user access; block if not, add them to pending list if open, let them through otherwise.
966 $result = $this->check_user_access( $current_user, $current_user->user_email );
967 }
968
969 // Check to see if the requested page is public. If so, show it.
970 $current_page_id = empty( $wp->request ) ? 'home' : $this->get_id_from_pagename( $wp->query_vars['pagename'] );
971 if ( ! is_array( $auth_settings['access_public_pages'] ) ) {
972 $auth_settings['access_public_pages'] = array();
973 }
974 if ( in_array( $current_page_id, $auth_settings['access_public_pages'] ) ) {
975 if ( $auth_settings['access_public_warning'] === 'no_warning' ) {
976 update_option( 'auth_settings_advanced_public_notice', false );
977 } else {
978 update_option( 'auth_settings_advanced_public_notice', true );
979 }
980 return;
981 }
982
983 $current_path = empty( $_SERVER['REQUEST_URI'] ) ? home_url() : $_SERVER['REQUEST_URI'];
984 if ( $auth_settings['access_redirect'] === 'message' ) {
985 $page_title = get_bloginfo( 'name' ) . ' - Access Restricted';
986 $error_message = apply_filters( 'the_content', $auth_settings['access_redirect_to_message'] );
987 $error_message .= '<hr /><p style="text-align:center;margin-bottom:-15px;"><a class="button" href="' . wp_login_url( $current_path ) . '">Log In</a></p>';
988 wp_die( $error_message, $page_title );
989 } else { // if ( $auth_settings['access_redirect'] === 'login' ) {
990 wp_redirect( wp_login_url( $current_path ), 302 );
991 exit;
992 }
993
994 // Sanity check: we should never get here
995 wp_die( '<p>Access denied.</p>', 'Site Access Restricted' );
996 } // END restrict_access()
997
998
999
1000 /**
1001 * ***************************
1002 * Login page (wp-login.php)
1003 * ***************************
1004 */
1005
1006
1007
1008 /**
1009 * Add custom error message to login screen.
1010 * Filter: login_errors
1011 */
1012 function show_advanced_login_error( $errors ) {
1013 $error = get_option( 'auth_settings_advanced_login_error' );
1014 delete_option( 'auth_settings_advanced_login_error' );
1015
1016 //$errors .= ' ' . $error . "<br />\n";
1017 $errors = ' ' . $error . "<br />\n";
1018 return $errors;
1019 } // END show_advance_login_error()
1020
1021
1022 /**
1023 * Load external resources for the public-facing site.
1024 */
1025 function auth_public_scripts() {
1026 // Load (and localize) public scripts
1027 $current_path = empty( $_SERVER['REQUEST_URI'] ) ? home_url() : $_SERVER['REQUEST_URI'];
1028 wp_enqueue_script( 'auth_public_scripts', plugins_url( '/js/authorizer-public.js', __FILE__ ) );
1029 $auth_localized = array(
1030 'wp_login_url' => wp_login_url( $current_path ),
1031 'public_warning' => get_option( 'auth_settings_advanced_public_notice' )
1032 );
1033 wp_localize_script( 'auth_public_scripts', 'auth', $auth_localized );
1034 //update_option( 'auth_settings_advanced_public_notice', false);
1035
1036 // Load public css
1037 wp_register_style( 'authorizer-public-css', plugins_url( 'css/authorizer-public.css', __FILE__ ) );
1038 wp_enqueue_style( 'authorizer-public-css' );
1039 } // END auth_public_scripts()
1040
1041
1042 /**
1043 * Enqueue JS scripts and CSS styles appearing on wp-login.php.
1044 *
1045 * @return void
1046 */
1047 function login_enqueue_scripts_and_styles() {
1048 // Grab plugin settings.
1049 $auth_settings = $this->get_plugin_options( 'single admin', 'allow override' );
1050
1051 // Enqueue scripts appearing on wp-login.php.
1052 wp_enqueue_script( 'auth_login_scripts', plugins_url( '/js/authorizer-login.js', __FILE__ ), array( 'jquery' ) );
1053
1054 // Enqueue styles appearing on wp-login.php.
1055 wp_register_style( 'authorizer-login-css', plugins_url( '/css/authorizer-login.css', __FILE__ ) );
1056 wp_enqueue_style( 'authorizer-login-css' );
1057
1058 /**
1059 * Developers can use the `authorizer_add_branding_option` filter
1060 * to add a radio button for "Custom WordPress login branding"
1061 * under the "Advanced" tab in Authorizer options. Example:
1062 *
1063 * function my_authorizer_add_branding_option( $branding_options ) {
1064 * $new_branding_option = array(
1065 * 'value' => 'your_brand'
1066 * 'description' => 'Custom Your Brand Login Screen',
1067 * 'css_url' => 'http://url/to/your_brand.css',
1068 * 'js_url' => 'http://url/to/your_brand.js',
1069 * );
1070 * array_push( $branding_options, $new_branding_option );
1071 * return $branding_options;
1072 * }
1073 * add_filter( 'authorizer_add_branding_option', 'my_authorizer_add_branding_option' );
1074 */
1075 $branding_options = array();
1076 $branding_options = apply_filters( 'authorizer_add_branding_option', $branding_options );
1077 foreach ( $branding_options as $branding_option ) {
1078 // Make sure the custom brands have the required values
1079 if ( ! ( is_array( $branding_option ) && array_key_exists( 'value', $branding_option ) && array_key_exists( 'css_url', $branding_option ) && array_key_exists( 'js_url', $branding_option ) ) ) {
1080 continue;
1081 }
1082 if ( $auth_settings['advanced_branding'] === $branding_option['value'] ) {
1083 wp_enqueue_script( 'auth_login_custom_scripts-' . sanitize_title( $branding_option['value'] ), $branding_option['js_url'], array( 'jquery' ) );
1084 wp_register_style( 'authorizer-login-custom-css-' . sanitize_title( $branding_option['value'] ), $branding_option['css_url'] );
1085 wp_enqueue_style( 'authorizer-login-custom-css-' . sanitize_title( $branding_option['value'] ) );
1086 }
1087 }
1088
1089 // If we're using Google logins, load those resources.
1090 if ( $auth_settings['google'] === '1' ) {
1091 wp_enqueue_script( 'authorizer-login-custom-google', plugins_url( '/js/authorizer-login-custom_google.js', __FILE__ ), array( 'jquery' ) ); ?>
1092 <meta name="google-signin-clientid" content="<?php echo $auth_settings['google_clientid']; ?>" />
1093 <meta name="google-signin-scope" content="email" />
1094 <meta name="google-signin-cookiepolicy" content="single_host_origin" />
1095 <?php
1096 }
1097 } // END login_enqueue_scripts_and_styles()
1098
1099
1100 /**
1101 * Load external resources in the footer of the wp-login.php page.
1102 * Run on action hook: login_footer
1103 */
1104 function load_login_footer_js() {
1105 // Grab plugin settings.
1106 $auth_settings = $this->get_plugin_options( 'single admin', 'allow override' ); ?>
1107 <?php if ( $auth_settings['google'] === '1' ): ?>
1108 <script type="text/javascript">
1109 // Reload login page if reauth querystring param exists,
1110 // since reauth interrupts external logins (e.g., google).
1111 if ( location.search.indexOf( 'reauth=1' ) >= 0 ) {
1112 location.href = location.href.replace( 'reauth=1', '' );
1113 }
1114
1115 function signInCallback( authResult ) {
1116 var $ = jQuery;
1117 if ( authResult['status'] && authResult['status']['signed_in'] ) {
1118 // Hide the sign-in button now that the user is authorized, for example:
1119 $( '#googleplus_button' ).attr( 'style', 'display: none' );
1120
1121 // Send the code to the server
1122 var ajaxurl = '<?php echo admin_url( "admin-ajax.php" ); ?>';
1123 $.post(ajaxurl, {
1124 action: 'process_google_login',
1125 'code': authResult['code'],
1126 'nonce': $('#nonce_google_auth-<?php echo $this->get_cookie_value(); ?>').val(),
1127 }, function( response ) {
1128 // Handle or verify the server response if necessary.
1129 //console.log( response );
1130
1131 // Reload wp-login.php to continue the authentication process.
1132 location.reload();
1133 });
1134 } else {
1135 // Update the app to reflect a signed out user
1136 // Possible error values:
1137 // "user_signed_out" - User is signed-out
1138 // "access_denied" - User denied access to your app
1139 // "immediate_failed" - Could not automatically log in the user
1140 //console.log('Sign-in state: ' + authResult['error']);
1141 }
1142 }
1143 </script>
1144 <?php endif;
1145 } // END load_login_footer_js()
1146
1147
1148 /**
1149 * Create links for any external authentication services that are enabled.
1150 */
1151 function login_form_add_external_service_links() {
1152 // Grab plugin settings.
1153 $auth_settings = $this->get_plugin_options( 'single admin', 'allow override' );
1154
1155 $auth_url_cas = '';
1156 if ( $auth_settings['cas'] === '1' ) {
1157 $auth_url_cas = 'http' . ( isset( $_SERVER['HTTPS'] ) ? 's' : '' ) . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
1158 // Remove force reauth param if it exists so this
1159 // authentication attempt doesn't get stopped by WordPress.
1160 if ( strpos( $auth_url_cas, 'reauth=1' ) !== false ) {
1161 if ( strpos( $auth_url_cas, '&reauth=1' ) !== false ) {
1162 // There are parames before reauth, so just remove reauth
1163 $auth_url_cas = str_replace( '&reauth=1', '', $auth_url_cas );
1164 } elseif ( strpos( $auth_url_cas, '?reauth=1&' ) !== false ) {
1165 // Reauth is first param with others behind it, so remove it and next delimiter.
1166 $auth_url_cas = str_replace( 'reauth=1&', '', $auth_url_cas );
1167 } else {
1168 // Reauth is first and only param, so remove it and '?'
1169 $auth_url_cas = str_replace( '?reauth=1', '', $auth_url_cas );
1170 }
1171
1172 }
1173 // Add special param indicating this is CAS authentication attempt.
1174 if ( strpos( $auth_url_cas, 'external=cas' ) === false ) {
1175 $auth_url_cas .= strpos( $auth_url_cas, '?' ) !== false ? '&external=cas' : '?external=cas';
1176 }
1177 } ?>
1178 <div id="auth-external-service-login">
1179 <?php if ( $auth_settings['google'] === '1' ): ?>
1180 <p><a id="googleplus_button" class="button button-primary button-external button-google"><span class="dashicons dashicons-googleplus"></span><span class="label">Sign in with Google</span></a></p>
1181 <?php wp_nonce_field( 'google_csrf_nonce', 'nonce_google_auth-' . $this->get_cookie_value() ); ?>
1182 <?php endif; ?>
1183
1184 <?php if ( $auth_settings['cas'] === '1' ): ?>
1185 <p><a class="button button-primary button-external button-cas" href="<?php echo $auth_url_cas; ?>"><span class="dashicons dashicons-lock"></span><span class="label">Sign in with <?php echo $auth_settings['cas_custom_label']; ?></span></a></p>
1186 <?php endif; ?>
1187
1188 <?php if ( $auth_settings['advanced_hide_wp_login'] === '1' && strpos( $_SERVER['QUERY_STRING'], 'external=wordpress' ) === false ): ?>
1189 <style type="text/css">
1190 #loginform {
1191 padding-bottom: 8px;
1192 }
1193 #loginform p>label, #loginform p.forgetmenot, #loginform p.submit, p#nav {
1194 display: none;
1195 }
1196 </style>
1197 <?php elseif ( $auth_settings['cas'] === '1' || $auth_settings['google'] === '1' ): ?>
1198 <h3> &mdash; or &mdash; </h3>
1199 <?php endif; ?>
1200 </div>
1201 <?php
1202
1203 } // END login_form_add_external_service_links()
1204
1205
1206 /**
1207 * Implements hook: do_action( 'wp_login_failed', $username );
1208 * Update the user meta for the user that just failed logging in.
1209 * Keep track of time of last failed attempt and number of failed attempts.
1210 */
1211 function update_login_failed_count( $username ) {
1212 // Grab plugin settings.
1213 $auth_settings = $this->get_plugin_options( 'single admin', 'allow override' );
1214
1215 // Get user trying to log in.
1216 // If this isn't a real user, update the global failed attempt
1217 // variables. We'll use these global variables to institute the
1218 // lockouts on nonexistent accounts. We do this so an attacker
1219 // won't be able to determine which accounts are real by which
1220 // accounts get locked out on multiple invalid attempts.
1221 $user = get_user_by( 'login', $username );
1222
1223 if ( $user !== FALSE ) {
1224 $last_attempt = get_user_meta( $user->ID, 'auth_settings_advanced_lockouts_time_last_failed', true );
1225 $num_attempts = get_user_meta( $user->ID, 'auth_settings_advanced_lockouts_failed_attempts', true );
1226 } else {
1227 $last_attempt = get_option( 'auth_settings_advanced_lockouts_time_last_failed' );
1228 $num_attempts = get_option( 'auth_settings_advanced_lockouts_failed_attempts' );
1229 }
1230
1231 // Make sure $last_attempt (time) and $num_attempts are positive integers.
1232 // Note: this addresses resetting them if either is unset from above.
1233 $last_attempt = abs( intval( $last_attempt ) );
1234 $num_attempts = abs( intval( $num_attempts ) );
1235
1236 // Reset the failed attempt count if the time since the last
1237 // failed attempt is greater than the reset duration.
1238 $time_since_last_fail = time() - $last_attempt;
1239 $reset_duration = $auth_settings['advanced_lockouts']['reset_duration'] * 60; // minutes to seconds
1240 if ( $time_since_last_fail > $reset_duration ) {
1241 $num_attempts = 0;
1242 }
1243
1244 // Set last failed time to now and increment last failed count.
1245 if ( $user !== FALSE ) {
1246 update_user_meta( $user->ID, 'auth_settings_advanced_lockouts_time_last_failed', time() );
1247 update_user_meta( $user->ID, 'auth_settings_advanced_lockouts_failed_attempts', $num_attempts + 1 );
1248 } else {
1249 update_option( 'auth_settings_advanced_lockouts_time_last_failed', time() );
1250 update_option( 'auth_settings_advanced_lockouts_failed_attempts', $num_attempts + 1 );
1251 }
1252 } // END update_login_failed_count()
1253
1254 /**
1255 * Overwrite the URL for the lost password link on the login form.
1256 * If we're authenticating against an external service, standard
1257 * WordPress password resets won't work.
1258 */
1259 function custom_lostpassword_url( $lostpassword_url ) {
1260 // Grab plugin settings.
1261 $auth_settings = $this->get_plugin_options( 'single admin', 'allow override' );
1262
1263 if (
1264 array_key_exists( 'ldap_lostpassword_url', $auth_settings ) &&
1265 filter_var( $auth_settings['ldap_lostpassword_url'], FILTER_VALIDATE_URL )
1266 ) {
1267 $lostpassword_url = $auth_settings['ldap_lostpassword_url'];
1268 }
1269 return $lostpassword_url;
1270 } // END custom_lostpassword_url()
1271
1272
1273
1274 /**
1275 * ***************************
1276 * Options page
1277 * ***************************
1278 */
1279
1280
1281
1282 /**
1283 * Add a link to this plugin's settings page from the WordPress Plugins page.
1284 * Called from "plugin_action_links" filter in __construct() above.
1285 *
1286 * @param array $links array of links in the admin sidebar
1287 *
1288 * @return array of links to show in the admin sidebar.
1289 */
1290 public function plugin_settings_link( $links ) {
1291 $admin_menu = $this->get_plugin_option( 'advanced_admin_menu' );
1292 $settings_url = $admin_menu === 'settings' ? admin_url( 'options-general.php?page=authorizer' ) : admin_url( 'admin.php?page=authorizer' );
1293 array_unshift( $links, '<a href="' . $settings_url . '">Settings</a>' );
1294 return $links;
1295 } // END plugin_settings_link()
1296
1297
1298
1299 /**
1300 * Add a link to this plugin's network settings page from the WordPress Plugins page.
1301 * Called from "network_admin_plugin_action_links" filter in __construct() above.
1302 *
1303 * @param array $links array of links in the network admin sidebar
1304 *
1305 * @return array of links to show in the network admin sidebar.
1306 */
1307 public function network_admin_plugin_settings_link( $links ) {
1308 $settings_link = '<a href="admin.php?page=authorizer">Network Settings</a>';
1309 array_unshift( $links, $settings_link );
1310 return $links;
1311 } // END network_admin_plugin_settings_link()
1312
1313
1314
1315 /**
1316 * Create the options page under Dashboard > Settings
1317 * Run on action hook: admin_menu
1318 */
1319 public function add_plugin_page() {
1320 $admin_menu = $this->get_plugin_option( 'advanced_admin_menu' );
1321 if ( $admin_menu === 'settings' ) {
1322 // @see http://codex.wordpress.org/Function_Reference/add_options_page
1323 add_options_page(
1324 'Authorizer', // Page title
1325 'Authorizer', // Menu title
1326 'create_users', // Capability
1327 'authorizer', // Menu slug
1328 array( $this, 'create_admin_page' ) // function
1329 );
1330 } else {
1331 // @see http://codex.wordpress.org/Function_Reference/add_menu_page
1332 add_menu_page(
1333 'Authorizer', // Page title
1334 'Authorizer', // Menu title
1335 'create_users', // Capability
1336 'authorizer', // Menu slug
1337 array( $this, 'create_admin_page' ), // callback
1338 'dashicons-groups', // icon
1339 '99.0018465' // position (decimal is to make overlap with other plugins less likely)
1340 );
1341 }
1342 } // END add_plugin_page()
1343
1344
1345 /**
1346 * Output the HTML for the options page
1347 */
1348 public function create_admin_page() { ?>
1349 <div class="wrap">
1350 <h2>Authorizer Settings</h2>
1351 <form method="post" action="options.php" autocomplete="off"><?php
1352 // This prints out all hidden settings fields
1353 // @see http://codex.wordpress.org/Function_Reference/settings_fields
1354 settings_fields( 'auth_settings_group' );
1355 // This prints out all the sections
1356 // @see http://codex.wordpress.org/Function_Reference/do_settings_sections
1357 do_settings_sections( 'authorizer' );
1358 submit_button(); ?>
1359 </form>
1360 </div><?php
1361 } // END create_admin_page()
1362
1363
1364
1365 /**
1366 * Load external resources on this plugin's options page.
1367 * Run on action hooks: load-settings_page_authorizer, load-toplevel_page_authorizer, admin_head-index.php
1368 */
1369 public function load_options_page() {
1370 wp_enqueue_script(
1371 'authorizer',
1372 plugins_url( 'js/authorizer.js', __FILE__ ),
1373 array( 'jquery-effects-shake' ), '5.0', true
1374 );
1375 $js_auth_config = array( 'baseurl' => get_bloginfo( 'url' ) );
1376 wp_localize_script( 'authorizer', 'auth_config', $js_auth_config );
1377
1378 wp_enqueue_script(
1379 'jquery.multi-select',
1380 plugins_url( 'inc/jquery.multi-select/js/jquery.multi-select.js', __FILE__ ),
1381 array( 'jquery' ), '1.8', true
1382 );
1383
1384 wp_register_style( 'authorizer-css', plugins_url( 'css/authorizer.css', __FILE__ ) );
1385 wp_enqueue_style( 'authorizer-css' );
1386
1387 wp_register_style( 'jquery-multi-select-css', plugins_url( 'inc/jquery.multi-select/css/multi-select.css', __FILE__ ) );
1388 wp_enqueue_style( 'jquery-multi-select-css' );
1389
1390 add_action( 'admin_notices', array( $this, 'admin_notices' ) ); // Add any notices to the top of the options page.
1391 add_action( 'admin_head', array( $this, 'admin_head' ) ); // Add help documentation to the options page.
1392 } // END load_options_page()
1393
1394
1395
1396 /**
1397 * Show custom admin notice.
1398 * Filter: admin_notice
1399 */
1400 function show_advanced_admin_notice() {
1401 $notice = get_option( 'auth_settings_advanced_admin_notice' );
1402 delete_option( 'auth_settings_advanced_admin_notice' );
1403
1404 if ( $notice && strlen( $notice ) > 0 ) { ?>
1405 <div class="error">
1406 <p><?php _e( $notice ); ?></p>
1407 </div><?php
1408 }
1409 } // END show_advanced_admin_notice()
1410
1411
1412 /**
1413 * Add notices to the top of the options page.
1414 * Run on action hook chain: load-settings_page_authorizer > admin_notices
1415 * Description: Check for invalid settings combinations and show a warning message, e.g.:
1416 * if (cas url inaccessible) {
1417 * echo "<div class='updated settings-error'><p>Can't reach Sakai.</p></div>";
1418 * }
1419 */
1420 public function admin_notices() {
1421 // Grab plugin settings.
1422 $auth_settings = $this->get_plugin_options( 'single admin', 'allow override' );
1423
1424 if ( $auth_settings['cas'] === '1' ) {
1425 // Check if provided CAS URL is accessible.
1426 $protocol = $auth_settings['cas_port'] == '80' ? 'http' : 'https';
1427 if ( ! $this->url_is_accessible( $protocol . '://' . $auth_settings['cas_host'] . $auth_settings['cas_path'] ) ) {
1428 echo "<div class='updated settings-error'><p>Can't reach CAS server. Please provide <a href='javascript:choose_tab(\"external\");'>accurate CAS settings</a> if you intend to use it.</p></div>";
1429 }
1430 }
1431 } // END admin_notices()
1432
1433
1434 /**
1435 * Create sections and options
1436 * Run on action hook: admin_init
1437 */
1438 public function page_init() {
1439 // Create one setting that holds all the options (array)
1440 // @see http://codex.wordpress.org/Function_Reference/register_setting
1441 // @see http://codex.wordpress.org/Function_Reference/add_settings_section
1442 // @see http://codex.wordpress.org/Function_Reference/add_settings_field
1443 register_setting(
1444 'auth_settings_group', // Option group
1445 'auth_settings', // Option name
1446 array( $this, 'sanitize_options' ) // Sanitize callback
1447 );
1448
1449 add_settings_section(
1450 'auth_settings_tabs', // HTML element ID
1451 '', // HTML element Title
1452 array( $this, 'print_section_info_tabs' ), // Callback (echos section content)
1453 'authorizer' // Page this section is shown on (slug)
1454 );
1455
1456 // Create Access Lists section
1457 add_settings_section(
1458 'auth_settings_lists', // HTML element ID
1459 '', // HTML element Title
1460 array( $this, 'print_section_info_access_lists' ), // Callback (echos section content)
1461 'authorizer' // Page this section is shown on (slug)
1462 );
1463
1464 // Create Login Access section
1465 add_settings_section(
1466 'auth_settings_access_login', // HTML element ID
1467 '', // HTML element Title
1468 array( $this, 'print_section_info_access_login' ), // Callback (echos section content)
1469 'authorizer' // Page this section is shown on (slug)
1470 );
1471 add_settings_field(
1472 'auth_settings_access_who_can_login', // HTML element ID
1473 'Who can log into the site?', // HTML element Title
1474 array( $this, 'print_radio_auth_access_who_can_login' ), // Callback (echos form element)
1475 'authorizer', // Page this setting is shown on (slug)
1476 'auth_settings_access_login' // Section this setting is shown on
1477 );
1478 add_settings_field(
1479 'auth_settings_access_role_receive_pending_emails', // HTML element ID
1480 'Which role should receive email notifications about pending users?', // HTML element Title
1481 array( $this, 'print_select_auth_access_role_receive_pending_emails' ), // Callback (echos form element)
1482 'authorizer', // Page this setting is shown on (slug)
1483 'auth_settings_access_login' // Section this setting is shown on
1484 );
1485 add_settings_field(
1486 'auth_settings_access_pending_redirect_to_message', // HTML element ID
1487 'What message should pending users see after attempting to log in?', // HTML element Title
1488 array( $this, 'print_wysiwyg_auth_access_pending_redirect_to_message' ), // Callback (echos form element)
1489 'authorizer', // Page this setting is shown on (slug)
1490 'auth_settings_access_login' // Section this setting is shown on
1491 );
1492 add_settings_field(
1493 'auth_settings_access_blocked_redirect_to_message', // HTML element ID
1494 'What message should blocked users see after attempting to log in?', // HTML element Title
1495 array( $this, 'print_wysiwyg_auth_access_blocked_redirect_to_message' ), // Callback (echos form element)
1496 'authorizer', // Page this setting is shown on (slug)
1497 'auth_settings_access_login' // Section this setting is shown on
1498 );
1499 add_settings_field(
1500 'auth_settings_access_should_email_approved_users', // HTML element ID
1501 'Send welcome email to new approved users?', // HTML element Title
1502 array( $this, 'print_checkbox_auth_access_should_email_approved_users' ), // Callback (echos form element)
1503 'authorizer', // Page this setting is shown on (slug)
1504 'auth_settings_access_login' // Section this setting is shown on
1505 );
1506 add_settings_field(
1507 'auth_settings_access_email_approved_users_subject', // HTML element ID
1508 'Welcome email subject', // HTML element Title
1509 array( $this, 'print_text_auth_access_email_approved_users_subject' ), // Callback (echos form element)
1510 'authorizer', // Page this setting is shown on (slug)
1511 'auth_settings_access_login' // Section this setting is shown on
1512 );
1513 add_settings_field(
1514 'auth_settings_access_email_approved_users_body', // HTML element ID
1515 'Welcome email body', // HTML element Title
1516 array( $this, 'print_wysiwyg_auth_access_email_approved_users_body' ), // Callback (echos form element)
1517 'authorizer', // Page this setting is shown on (slug)
1518 'auth_settings_access_login' // Section this setting is shown on
1519 );
1520
1521
1522 // Create Public Access section
1523 add_settings_section(
1524 'auth_settings_access_public', // HTML element ID
1525 '', // HTML element Title
1526 array( $this, 'print_section_info_access_public' ), // Callback (echos section content)
1527 'authorizer' // Page this section is shown on (slug)
1528 );
1529 add_settings_field(
1530 'auth_settings_access_who_can_view', // HTML element ID
1531 'Who can view the site?', // HTML element Title
1532 array( $this, 'print_radio_auth_access_who_can_view' ), // Callback (echos form element)
1533 'authorizer', // Page this setting is shown on (slug)
1534 'auth_settings_access_public' // Section this setting is shown on
1535 );
1536 add_settings_field(
1537 'auth_settings_access_public_pages', // HTML element ID
1538 'What pages (if any) should be available to everyone?', // HTML element Title
1539 array( $this, 'print_multiselect_auth_access_public_pages' ), // Callback (echos form element)
1540 'authorizer', // Page this setting is shown on (slug)
1541 'auth_settings_access_public' // Section this setting is shown on
1542 );
1543 add_settings_field(
1544 'auth_settings_access_redirect', // HTML element ID
1545 'What happens to people without access when they visit a private page?', // HTML element Title
1546 array( $this, 'print_radio_auth_access_redirect' ), // Callback (echos form element)
1547 'authorizer', // Page this setting is shown on (slug)
1548 'auth_settings_access_public' // Section this setting is shown on
1549 );
1550 add_settings_field(
1551 'auth_settings_access_public_warning', // HTML element ID
1552 'What happens to people without access when they visit a public page?', // HTML element Title
1553 array( $this, 'print_radio_auth_access_public_warning' ), // Callback (echos form element)
1554 'authorizer', // Page this setting is shown on (slug)
1555 'auth_settings_access_public' // Section this setting is shown on
1556 );
1557 add_settings_field(
1558 'auth_settings_access_redirect_to_message', // HTML element ID
1559 'What message should people without access see?', // HTML element Title
1560 array( $this, 'print_wysiwyg_auth_access_redirect_to_message' ), // Callback (echos form element)
1561 'authorizer', // Page this setting is shown on (slug)
1562 'auth_settings_access_public' // Section this setting is shown on
1563 );
1564
1565 // Create External Service Settings section
1566 add_settings_section(
1567 'auth_settings_external', // HTML element ID
1568 '', // HTML element Title
1569 array( $this, 'print_section_info_external' ), // Callback (echos section content)
1570 'authorizer' // Page this section is shown on (slug)
1571 );
1572 add_settings_field(
1573 'auth_settings_access_default_role', // HTML element ID
1574 'Default role for new users', // HTML element Title
1575 array( $this, 'print_select_auth_access_default_role' ), // Callback (echos form element)
1576 'authorizer', // Page this setting is shown on (slug)
1577 'auth_settings_external' // Section this setting is shown on
1578 );
1579 add_settings_field(
1580 'auth_settings_external_google', // HTML element ID
1581 'Google Logins', // HTML element Title
1582 array( $this, 'print_checkbox_auth_external_google' ), // Callback (echos form element)
1583 'authorizer', // Page this setting is shown on (slug)
1584 'auth_settings_external' // Section this setting is shown on
1585 );
1586 add_settings_field(
1587 'auth_settings_google_clientid', // HTML element ID
1588 'Google Client ID', // HTML element Title
1589 array( $this, 'print_text_google_clientid' ), // Callback (echos form element)
1590 'authorizer', // Page this setting is shown on (slug)
1591 'auth_settings_external' // Section this setting is shown on
1592 );
1593 add_settings_field(
1594 'auth_settings_google_clientsecret', // HTML element ID
1595 'Google Client Secret', // HTML element Title
1596 array( $this, 'print_text_google_clientsecret' ), // Callback (echos form element)
1597 'authorizer', // Page this setting is shown on (slug)
1598 'auth_settings_external' // Section this setting is shown on
1599 );
1600 add_settings_field(
1601 'auth_settings_external_cas', // HTML element ID
1602 'CAS Logins', // HTML element Title
1603 array( $this, 'print_checkbox_auth_external_cas' ), // Callback (echos form element)
1604 'authorizer', // Page this setting is shown on (slug)
1605 'auth_settings_external' // Section this setting is shown on
1606 );
1607 add_settings_field(
1608 'auth_settings_cas_custom_label', // HTML element ID
1609 'CAS custom label', // HTML element Title
1610 array( $this, 'print_text_cas_custom_label' ), // Callback (echos form element)
1611 'authorizer', // Page this setting is shown on (slug)
1612 'auth_settings_external' // Section this setting is shown on
1613 );
1614 add_settings_field(
1615 'auth_settings_cas_host', // HTML element ID
1616 'CAS server hostname', // HTML element Title
1617 array( $this, 'print_text_cas_host' ), // Callback (echos form element)
1618 'authorizer', // Page this setting is shown on (slug)
1619 'auth_settings_external' // Section this setting is shown on
1620 );
1621 add_settings_field(
1622 'auth_settings_cas_port', // HTML element ID
1623 'CAS server port', // HTML element Title
1624 array( $this, 'print_text_cas_port' ), // Callback (echos form element)
1625 'authorizer', // Page this setting is shown on (slug)
1626 'auth_settings_external' // Section this setting is shown on
1627 );
1628 add_settings_field(
1629 'auth_settings_cas_path', // HTML element ID
1630 'CAS server path/context', // HTML element Title
1631 array( $this, 'print_text_cas_path' ), // Callback (echos form element)
1632 'authorizer', // Page this setting is shown on (slug)
1633 'auth_settings_external' // Section this setting is shown on
1634 );
1635 add_settings_field(
1636 'auth_settings_external_ldap', // HTML element ID
1637 'LDAP Logins', // HTML element Title
1638 array( $this, 'print_checkbox_auth_external_ldap' ), // Callback (echos form element)
1639 'authorizer', // Page this setting is shown on (slug)
1640 'auth_settings_external' // Section this setting is shown on
1641 );
1642 add_settings_field(
1643 'auth_settings_ldap_host', // HTML element ID
1644 'LDAP Host', // HTML element Title
1645 array( $this, 'print_text_ldap_host' ), // Callback (echos form element)
1646 'authorizer', // Page this setting is shown on (slug)
1647 'auth_settings_external' // Section this setting is shown on
1648 );
1649 add_settings_field(
1650 'auth_settings_ldap_port', // HTML element ID
1651 'LDAP Port', // HTML element Title
1652 array( $this, 'print_text_ldap_port' ), // Callback (echos form element)
1653 'authorizer', // Page this setting is shown on (slug)
1654 'auth_settings_external' // Section this setting is shown on
1655 );
1656 add_settings_field(
1657 'auth_settings_ldap_search_base', // HTML element ID
1658 'LDAP Search Base', // HTML element Title
1659 array( $this, 'print_text_ldap_search_base' ), // Callback (echos form element)
1660 'authorizer', // Page this setting is shown on (slug)
1661 'auth_settings_external' // Section this setting is shown on
1662 );
1663 add_settings_field(
1664 'auth_settings_ldap_uid', // HTML element ID
1665 'LDAP attribute containing username', // HTML element Title
1666 array( $this, 'print_text_ldap_uid' ), // Callback (echos form element)
1667 'authorizer', // Page this setting is shown on (slug)
1668 'auth_settings_external' // Section this setting is shown on
1669 );
1670 add_settings_field(
1671 'auth_settings_ldap_user', // HTML element ID
1672 'LDAP Directory User', // HTML element Title
1673 array( $this, 'print_text_ldap_user' ), // Callback (echos form element)
1674 'authorizer', // Page this setting is shown on (slug)
1675 'auth_settings_external' // Section this setting is shown on
1676 );
1677 add_settings_field(
1678 'auth_settings_ldap_password', // HTML element ID
1679 'LDAP Directory User Password', // HTML element Title
1680 array( $this, 'print_password_ldap_password' ), // Callback (echos form element)
1681 'authorizer', // Page this setting is shown on (slug)
1682 'auth_settings_external' // Section this setting is shown on
1683 );
1684 add_settings_field(
1685 'auth_settings_ldap_tls', // HTML element ID
1686 'Secure Connection (TLS)', // HTML element Title
1687 array( $this, 'print_checkbox_ldap_tls' ), // Callback (echos form element)
1688 'authorizer', // Page this setting is shown on (slug)
1689 'auth_settings_external' // Section this setting is shown on
1690 );
1691 add_settings_field(
1692 'auth_settings_ldap_lostpassword_url', // HTML element ID
1693 'Custom lost password URL', // HTML element Title
1694 array( $this, 'print_text_ldap_lostpassword_url' ), // Callback (echos form element)
1695 'authorizer', // Page this setting is shown on (slug)
1696 'auth_settings_external' // Section this setting is shown on
1697 );
1698
1699 // Create Advanced Settings section
1700 add_settings_section(
1701 'auth_settings_advanced', // HTML element ID
1702 '', // HTML element Title
1703 array( $this, 'print_section_info_advanced' ), // Callback (echos section content)
1704 'authorizer' // Page this section is shown on (slug)
1705 );
1706 add_settings_field(
1707 'auth_settings_advanced_lockouts', // HTML element ID
1708 'Limit invalid login attempts', // HTML element Title
1709 array( $this, 'print_text_auth_advanced_lockouts' ), // Callback (echos form element)
1710 'authorizer', // Page this setting is shown on (slug)
1711 'auth_settings_advanced' // Section this setting is shown on
1712 );
1713 add_settings_field(
1714 'auth_settings_advanced_hide_wp_login', // HTML element ID
1715 'Hide WordPress Login', // HTML element Title
1716 array( $this, 'print_checkbox_auth_advanced_hide_wp_login' ), // Callback (echos form element)
1717 'authorizer', // Page this setting is shown on (slug)
1718 'auth_settings_advanced' // Section this setting is shown on
1719 );
1720 add_settings_field(
1721 'auth_settings_advanced_branding', // HTML element ID
1722 'Custom WordPress login branding', // HTML element Title
1723 array( $this, 'print_radio_auth_advanced_branding' ), // Callback (echos form element)
1724 'authorizer', // Page this setting is shown on (slug)
1725 'auth_settings_advanced' // Section this setting is shown on
1726 );
1727 add_settings_field(
1728 'auth_settings_advanced_admin_menu', // HTML element ID
1729 'Authorizer admin menu item location', // HTML element Title
1730 array( $this, 'print_radio_auth_advanced_admin_menu' ), // Callback (echos form element)
1731 'authorizer', // Page this setting is shown on (slug)
1732 'auth_settings_advanced' // Section this setting is shown on
1733 );
1734 add_settings_field(
1735 'auth_settings_advanced_usermeta', // HTML element ID
1736 'Show custom usermeta in user list', // HTML element Title
1737 array( $this, 'print_select_auth_advanced_usermeta' ), // Callback (echos form element)
1738 'authorizer', // Page this setting is shown on (slug)
1739 'auth_settings_advanced' // Section this setting is shown on
1740 );
1741 } // END page_init()
1742
1743
1744 /**
1745 * Set meaningful defaults for the plugin options.
1746 * Note: This function is called on plugin activation.
1747 */
1748 function set_default_options() {
1749 global $wp_roles;
1750
1751 $auth_settings = get_option( 'auth_settings' );
1752 if ( $auth_settings === FALSE ) {
1753 $auth_settings = array();
1754 }
1755
1756 // Access Lists Defaults.
1757 $auth_settings_access_users_pending = get_option( 'auth_settings_access_users_pending' );
1758 if ( $auth_settings_access_users_pending === FALSE ) {
1759 $auth_settings_access_users_pending = array();
1760 }
1761 $auth_settings_access_users_approved = get_option( 'auth_settings_access_users_approved' );
1762 if ( $auth_settings_access_users_approved === FALSE ) {
1763 $auth_settings_access_users_approved = array();
1764 }
1765 $auth_settings_access_users_blocked = get_option( 'auth_settings_access_users_blocked' );
1766 if ( $auth_settings_access_users_blocked === FALSE ) {
1767 $auth_settings_access_users_blocked = array();
1768 }
1769
1770 // Login Access Defaults.
1771 if ( ! array_key_exists( 'access_who_can_login', $auth_settings ) ) {
1772 $auth_settings['access_who_can_login'] = 'approved_users';
1773 }
1774 if ( ! array_key_exists( 'access_role_receive_pending_emails', $auth_settings ) ) {
1775 $auth_settings['access_role_receive_pending_emails'] = '---';
1776 }
1777 if ( ! array_key_exists( 'access_pending_redirect_to_message', $auth_settings ) ) {
1778 $auth_settings['access_pending_redirect_to_message'] = '<p>You\'re not currently allowed to view this site. Your administrator has been notified, and once he/she has approved your request, you will be able to log in. If you need any other help, please contact your administrator.</p>';
1779 }
1780 if ( ! array_key_exists( 'access_blocked_redirect_to_message', $auth_settings ) ) {
1781 $auth_settings['access_blocked_redirect_to_message'] = '<p>You\'re not currently allowed to log into this site. If you think this is a mistake, please contact your administrator.</p>';
1782 }
1783 if ( ! array_key_exists( 'access_should_email_approved_users', $auth_settings ) ) {
1784 $auth_settings['access_should_email_approved_users'] = '';
1785 }
1786 if ( ! array_key_exists( 'access_email_approved_users_subject', $auth_settings ) ) {
1787 $auth_settings['access_email_approved_users_subject'] = 'Welcome to [site_name]!';
1788 }
1789 if ( ! array_key_exists( 'access_email_approved_users_body', $auth_settings ) ) {
1790 $auth_settings['access_email_approved_users_body'] =
1791 'Hello [user_email],' . PHP_EOL .
1792 'Welcome to [site_name]! You now have access to all content on the site. Please visit us here:' . PHP_EOL .
1793 '[site_url]';
1794 }
1795
1796 // Public Access to Private Page Defaults.
1797 if ( ! array_key_exists( 'access_who_can_view', $auth_settings ) ) {
1798 $auth_settings['access_who_can_view'] = 'everyone';
1799 }
1800 if ( ! array_key_exists( 'access_public_pages', $auth_settings ) ) {
1801 $auth_settings['access_public_pages'] = array();
1802 }
1803 if ( ! array_key_exists( 'access_redirect', $auth_settings ) ) {
1804 $auth_settings['access_redirect'] = 'login';
1805 }
1806 if ( ! array_key_exists( 'access_public_warning', $auth_settings ) ) {
1807 $auth_settings['access_public_warning'] = 'no_warning';
1808 }
1809 if ( ! array_key_exists( 'access_redirect_to_message', $auth_settings ) ) {
1810 $auth_settings['access_redirect_to_message'] = '<p><strong>Notice</strong>: You are browsing this site anonymously, and only have access to a portion of its content.</p>';
1811 }
1812
1813
1814 // External Service Defaults.
1815 if ( ! array_key_exists( 'access_default_role', $auth_settings ) ) {
1816 // Set default role to 'student' if that role exists, 'subscriber' otherwise.
1817 $all_roles = $wp_roles->roles;
1818 $editable_roles = apply_filters( 'editable_roles', $all_roles );
1819 if ( array_key_exists( 'student', $editable_roles ) ) {
1820 $auth_settings['access_default_role'] = 'student';
1821 } else {
1822 $auth_settings['access_default_role'] = 'subscriber';
1823 }
1824 }
1825
1826 if ( ! array_key_exists( 'google', $auth_settings ) ) {
1827 $auth_settings['google'] = '';
1828 }
1829 if ( ! array_key_exists( 'cas', $auth_settings ) ) {
1830 $auth_settings['cas'] = '';
1831 }
1832 if ( ! array_key_exists( 'ldap', $auth_settings ) ) {
1833 $auth_settings['ldap'] = '';
1834 }
1835
1836 if ( ! array_key_exists( 'google_clientid', $auth_settings ) ) {
1837 $auth_settings['google_clientid'] = '';
1838 }
1839 if ( ! array_key_exists( 'google_clientsecret', $auth_settings ) ) {
1840 $auth_settings['google_clientsecret'] = '';
1841 }
1842
1843 if ( ! array_key_exists( 'cas_custom_label', $auth_settings ) ) {
1844 $auth_settings['cas_custom_label'] = 'CAS';
1845 }
1846 if ( ! array_key_exists( 'cas_host', $auth_settings ) ) {
1847 $auth_settings['cas_host'] = '';
1848 }
1849 if ( ! array_key_exists( 'cas_port', $auth_settings ) ) {
1850 $auth_settings['cas_port'] = '';
1851 }
1852 if ( ! array_key_exists( 'cas_path', $auth_settings ) ) {
1853 $auth_settings['cas_path'] = '';
1854 }
1855
1856 if ( ! array_key_exists( 'ldap_host', $auth_settings ) ) {
1857 $auth_settings['ldap_host'] = '';
1858 }
1859 if ( ! array_key_exists( 'ldap_port', $auth_settings ) ) {
1860 $auth_settings['ldap_port'] = '';
1861 }
1862 if ( ! array_key_exists( 'ldap_search_base', $auth_settings ) ) {
1863 $auth_settings['ldap_search_base'] = '';
1864 }
1865 if ( ! array_key_exists( 'ldap_uid', $auth_settings ) ) {
1866 $auth_settings['ldap_uid'] = '';
1867 }
1868 if ( ! array_key_exists( 'ldap_user', $auth_settings ) ) {
1869 $auth_settings['ldap_user'] = '';
1870 }
1871 if ( ! array_key_exists( 'ldap_password', $auth_settings ) ) {
1872 $auth_settings['ldap_password'] = '';
1873 }
1874 if ( ! array_key_exists( 'ldap_tls', $auth_settings ) ) {
1875 $auth_settings['ldap_tls'] = '1';
1876 }
1877 if ( ! array_key_exists( 'ldap_lostpassword_url', $auth_settings ) ) {
1878 $auth_settings['ldap_lostpassword_url'] = '';
1879 }
1880
1881 // Advanced defaults.
1882 if ( ! array_key_exists( 'advanced_lockouts', $auth_settings ) ) {
1883 $auth_settings['advanced_lockouts'] = array(
1884 'attempts_1' => 10,
1885 'duration_1' => 1,
1886 'attempts_2' => 10,
1887 'duration_2' => 10,
1888 'reset_duration' => 120,
1889 );
1890 }
1891 if ( ! array_key_exists( 'advanced_hide_wp_login', $auth_settings ) ) {
1892 $auth_settings['advanced_hide_wp_login'] = '';
1893 }
1894 if ( ! array_key_exists( 'advanced_branding', $auth_settings ) ) {
1895 $auth_settings['advanced_branding'] = 'default';
1896 }
1897 if ( ! array_key_exists( 'advanced_admin_menu', $auth_settings ) ) {
1898 $auth_settings['advanced_admin_menu'] = 'top';
1899 }
1900 if ( ! array_key_exists( 'advanced_usermeta', $auth_settings ) ) {
1901 $auth_settings['advanced_usermeta'] = '';
1902 }
1903
1904 // Save default options to database.
1905 update_option( 'auth_settings', $auth_settings );
1906 update_option( 'auth_settings_access_users_pending', $auth_settings_access_users_pending );
1907 update_option( 'auth_settings_access_users_approved', $auth_settings_access_users_approved );
1908 update_option( 'auth_settings_access_users_blocked', $auth_settings_access_users_blocked );
1909
1910 // Multisite defaults.
1911 if ( is_multisite() ) {
1912 $auth_multisite_settings = get_blog_option( BLOG_ID_CURRENT_SITE, 'auth_multisite_settings', array() );
1913
1914 if ( $auth_multisite_settings === FALSE ) {
1915 $auth_multisite_settings = array();
1916 }
1917 // Global switch for enabling multisite options.
1918 if ( ! array_key_exists( 'multisite_override', $auth_multisite_settings ) ) {
1919 $auth_multisite_settings['multisite_override'] = '';
1920 }
1921 // Access Lists Defaults.
1922 $auth_multisite_settings_access_users_approved = get_blog_option( BLOG_ID_CURRENT_SITE, 'auth_multisite_settings_access_users_approved' );
1923 if ( $auth_multisite_settings_access_users_approved === FALSE ) {
1924 $auth_multisite_settings_access_users_approved = array();
1925 }
1926 // Login Access Defaults.
1927 if ( ! array_key_exists( 'access_who_can_login', $auth_multisite_settings ) ) {
1928 $auth_multisite_settings['access_who_can_login'] = 'approved_users';
1929 }
1930 // View Access Defaults.
1931 if ( ! array_key_exists( 'access_who_can_view', $auth_multisite_settings ) ) {
1932 $auth_multisite_settings['access_who_can_view'] = 'everyone';
1933 }
1934 // External Service Defaults.
1935 if ( ! array_key_exists( 'access_default_role', $auth_multisite_settings ) ) {
1936 // Set default role to 'student' if that role exists, 'subscriber' otherwise.
1937 $all_roles = $wp_roles->roles;
1938 $editable_roles = apply_filters( 'editable_roles', $all_roles );
1939 if ( array_key_exists( 'student', $editable_roles ) ) {
1940 $auth_multisite_settings['access_default_role'] = 'student';
1941 } else {
1942 $auth_multisite_settings['access_default_role'] = 'subscriber';
1943 }
1944 }
1945 if ( ! array_key_exists( 'google', $auth_multisite_settings ) ) {
1946 $auth_multisite_settings['google'] = '';
1947 }
1948 if ( ! array_key_exists( 'cas', $auth_multisite_settings ) ) {
1949 $auth_multisite_settings['cas'] = '';
1950 }
1951 if ( ! array_key_exists( 'ldap', $auth_multisite_settings ) ) {
1952 $auth_multisite_settings['ldap'] = '';
1953 }
1954 if ( ! array_key_exists( 'google_clientid', $auth_multisite_settings ) ) {
1955 $auth_multisite_settings['google_clientid'] = '';
1956 }
1957 if ( ! array_key_exists( 'google_clientsecret', $auth_multisite_settings ) ) {
1958 $auth_multisite_settings['google_clientsecret'] = '';
1959 }
1960 if ( ! array_key_exists( 'cas_custom_label', $auth_multisite_settings ) ) {
1961 $auth_multisite_settings['cas_custom_label'] = 'CAS';
1962 }
1963 if ( ! array_key_exists( 'cas_host', $auth_multisite_settings ) ) {
1964 $auth_multisite_settings['cas_host'] = '';
1965 }
1966 if ( ! array_key_exists( 'cas_port', $auth_multisite_settings ) ) {
1967 $auth_multisite_settings['cas_port'] = '';
1968 }
1969 if ( ! array_key_exists( 'cas_path', $auth_multisite_settings ) ) {
1970 $auth_multisite_settings['cas_path'] = '';
1971 }
1972 if ( ! array_key_exists( 'ldap_host', $auth_multisite_settings ) ) {
1973 $auth_multisite_settings['ldap_host'] = '';
1974 }
1975 if ( ! array_key_exists( 'ldap_port', $auth_multisite_settings ) ) {
1976 $auth_multisite_settings['ldap_port'] = '';
1977 }
1978 if ( ! array_key_exists( 'ldap_search_base', $auth_multisite_settings ) ) {
1979 $auth_multisite_settings['ldap_search_base'] = '';
1980 }
1981 if ( ! array_key_exists( 'ldap_uid', $auth_multisite_settings ) ) {
1982 $auth_multisite_settings['ldap_uid'] = '';
1983 }
1984 if ( ! array_key_exists( 'ldap_user', $auth_multisite_settings ) ) {
1985 $auth_multisite_settings['ldap_user'] = '';
1986 }
1987 if ( ! array_key_exists( 'ldap_password', $auth_multisite_settings ) ) {
1988 $auth_multisite_settings['ldap_password'] = '';
1989 }
1990 if ( ! array_key_exists( 'ldap_tls', $auth_multisite_settings ) ) {
1991 $auth_multisite_settings['ldap_tls'] = '1';
1992 }
1993 if ( ! array_key_exists( 'ldap_lostpassword_url', $auth_multisite_settings ) ) {
1994 $auth_multisite_settings['ldap_lostpassword_url'] = '';
1995 }
1996 // Advanced defaults.
1997 if ( ! array_key_exists( 'advanced_lockouts', $auth_multisite_settings ) ) {
1998 $auth_multisite_settings['advanced_lockouts'] = array(
1999 'attempts_1' => 10,
2000 'duration_1' => 1,
2001 'attempts_2' => 10,
2002 'duration_2' => 10,
2003 'reset_duration' => 120,
2004 );
2005 }
2006 if ( ! array_key_exists( 'advanced_hide_wp_login', $auth_multisite_settings ) ) {
2007 $auth_multisite_settings['advanced_hide_wp_login'] = '';
2008 }
2009 // Save default network options to database.
2010 update_blog_option( BLOG_ID_CURRENT_SITE, 'auth_multisite_settings', $auth_multisite_settings );
2011 update_blog_option( BLOG_ID_CURRENT_SITE, 'auth_multisite_settings_access_users_approved', $auth_multisite_settings_access_users_approved );
2012 }
2013 } // END set_default_options()
2014
2015
2016 /**
2017 * List sanitizer.
2018 * $side_effect = 'none' or 'update roles' to make sure WP user roles match
2019 * $multisite_mode = 'single' or 'multisite' to indicate which user roles to change (this site or all sites)
2020 */
2021 function sanitize_user_list( $list, $side_effect = 'none', $multisite_mode = 'single' ) {
2022 // If it's not a list, make it so.
2023 if ( ! is_array( $list ) ) {
2024 $list = array();
2025 }
2026 foreach ( $list as $key => $user_info ) {
2027 if ( strlen( $user_info['email'] ) < 1 ) {
2028 // Make sure there are no empty entries in the list
2029 unset( $list[$key] );
2030 } elseif ( $side_effect === 'update roles' ) {
2031 // Make sure the WordPress user accounts have the same role
2032 // as that indicated in the list.
2033 $wp_user = get_user_by( 'email', $user_info['email'] );
2034 if ( $wp_user ) {
2035 if ( is_multisite() && $multisite_mode === 'multisite' ) {
2036 foreach ( get_blogs_of_user( $wp_user->ID ) as $blog ) {
2037 add_user_to_blog( $blog->userblog_id, $wp_user->ID, $user_info['role'] );
2038 }
2039 } else {
2040 $wp_user->set_role( $user_info['role'] );
2041 }
2042 }
2043 }
2044 }
2045 return $list;
2046 }
2047
2048 /**
2049 * Settings sanitizer callback
2050 */
2051 function sanitize_options( $auth_settings, $multisite_mode = 'single' ) {
2052 // Default to "Approved Users" login access restriction.
2053 if ( ! in_array( $auth_settings['access_who_can_login'], array( 'external_users', 'approved_users' ) ) ) {
2054 $auth_settings['access_who_can_login'] = 'approved_users';
2055 }
2056
2057 // Default to "Everyone" view access restriction.
2058 if ( ! in_array( $auth_settings['access_who_can_view'], array( 'everyone', 'logged_in_users' ) ) ) {
2059 $auth_settings['access_who_can_view'] = 'everyone';
2060 }
2061
2062 // Default to WordPress login access redirect.
2063 if ( ! in_array( $auth_settings['access_redirect'], array( 'login', 'page', 'message' ) ) ) {
2064 $auth_settings['access_redirect'] = 'login';
2065 }
2066
2067 // Default to warning message for anonymous users on public pages.
2068 if ( ! in_array( $auth_settings['access_public_warning'], array( 'no_warning', 'warning' ) ) ) {
2069 $auth_settings['access_public_warning'] = 'no_warning';
2070 }
2071
2072 // Sanitize Enable Google Logins (checkbox: value can only be '1' or empty string)
2073 if ( array_key_exists( 'google', $auth_settings ) && strlen( $auth_settings['google'] ) > 0 ) {
2074 $auth_settings['google'] = '1';
2075 }
2076
2077 // Sanitize Enable CAS Logins (checkbox: value can only be '1' or empty string)
2078 if ( array_key_exists( 'cas', $auth_settings ) && strlen( $auth_settings['cas'] ) > 0 ) {
2079 $auth_settings['cas'] = '1';
2080 }
2081
2082 // Sanitize Enable LDAP Logins (checkbox: value can only be '1' or empty string)
2083 if ( array_key_exists( 'ldap', $auth_settings ) && strlen( $auth_settings['ldap'] ) > 0 ) {
2084 $auth_settings['ldap'] = '1';
2085 }
2086
2087 // Sanitize CAS Host setting
2088 $auth_settings['cas_host'] = filter_var( $auth_settings['cas_host'], FILTER_SANITIZE_URL );
2089
2090 // Sanitize CAS Port (int)
2091 $auth_settings['cas_port'] = filter_var( $auth_settings['cas_port'], FILTER_SANITIZE_NUMBER_INT );
2092
2093 // Sanitize LDAP Host setting
2094 $auth_settings['ldap_host'] = filter_var( $auth_settings['ldap_host'], FILTER_SANITIZE_URL );
2095
2096 // Sanitize LDAP Port (int)
2097 $auth_settings['ldap_port'] = filter_var( $auth_settings['ldap_port'], FILTER_SANITIZE_NUMBER_INT );
2098
2099 // Sanitize LDAP attributes (basically make sure they don't have any parantheses)
2100 $auth_settings['ldap_uid'] = filter_var( $auth_settings['ldap_uid'], FILTER_SANITIZE_EMAIL );
2101
2102 // Sanitize LDAP TLS (checkbox: value can only be '1' or empty string)
2103 if ( array_key_exists( 'ldap_tls', $auth_settings ) && strlen( $auth_settings['ldap_tls'] ) > 0 ) {
2104 $auth_settings['ldap_tls'] = '1';
2105 }
2106
2107 // Sanitize LDAP Lost Password URL
2108 $auth_settings['ldap_lostpassword_url'] = filter_var( $auth_settings['ldap_lostpassword_url'], FILTER_SANITIZE_URL );
2109
2110 // Obfuscate LDAP directory user password
2111 if ( strlen( $auth_settings['ldap_password'] ) > 0 ) {
2112 // encrypt the directory user password for some minor obfuscation in the database.
2113 $auth_settings['ldap_password'] = base64_encode( $this->encrypt( $auth_settings['ldap_password'] ) );
2114 }
2115
2116 // Make sure public pages is an empty array if it's empty
2117 if ( ! is_array( $auth_settings['access_public_pages'] ) ) {
2118 $auth_settings['access_public_pages'] = array();
2119 }
2120
2121 // Make sure all lockout options are integers (attempts_1,
2122 // duration_1, attempts_2, duration_2, reset_duration).
2123 foreach ( $auth_settings['advanced_lockouts'] as $key => $value ) {
2124 $auth_settings['advanced_lockouts'][$key] = filter_var( $value, FILTER_SANITIZE_NUMBER_INT );
2125 }
2126
2127 // Sanitize Hide WordPress logins (checkbox: value can only be '1' or empty string)
2128 if ( array_key_exists( 'advanced_hide_wp_login', $auth_settings ) && strlen( $auth_settings['advanced_hide_wp_login'] ) > 0 ) {
2129 $auth_settings['advanced_hide_wp_login'] = '1';
2130 }
2131
2132 return $auth_settings;
2133 } // END sanitize_options()
2134
2135
2136 /**
2137 * Keep authorizer approved users' roles in sync with WordPress roles
2138 * if someone changes the role via the WordPress Edit User options page.
2139 *
2140 * @action edit_user_profile_update
2141 * @ref https://codex.wordpress.org/Plugin_API/Action_Reference/edit_user_profile_update
2142 * @param int $user_id The user ID of the user being edited
2143 */
2144 function edit_user_profile_update_role( $user_id ) {
2145 if ( ! current_user_can( 'edit_user', $user_id ) ) {
2146 return;
2147 }
2148
2149 // If user is in approved list, update his/her associated role.
2150 $wp_user = get_user_by( 'id', $user_id );
2151 if ( $this->is_email_in_list( $wp_user->get( 'user_email' ), 'approved' ) ) {
2152 $auth_settings_access_users_approved = $this->sanitize_user_list(
2153 $this->get_plugin_option( 'access_users_approved', 'single admin' )
2154 );
2155 // Find approved user and update their role.
2156 foreach ( $auth_settings_access_users_approved as $key => $user ) {
2157 if ( $user['email'] === $wp_user->get( 'user_email' ) ) {
2158 $auth_settings_access_users_approved[$key]['role'] = $_REQUEST['role'];
2159 }
2160 }
2161
2162 update_option( 'auth_settings_access_users_approved', $auth_settings_access_users_approved );
2163 }
2164 }
2165
2166 /**
2167 * Settings print callbacks
2168 */
2169 function print_section_info_tabs( $args = '' ) {
2170 if ( is_array( $args ) && array_key_exists( 'multisite_admin', $args ) && $args['multisite_admin'] === true ): ?>
2171 <h2 class="nav-tab-wrapper">
2172 <a class="nav-tab nav-tab-access_lists nav-tab-active" href="javascript:choose_tab('access_lists');">Access Lists</a>
2173 <a class="nav-tab nav-tab-external" href="javascript:choose_tab('external');">External Service</a>
2174 <a class="nav-tab nav-tab-advanced" href="javascript:choose_tab('advanced');">Advanced</a>
2175 </h2>
2176 <?php else: ?>
2177 <h2 class="nav-tab-wrapper">
2178 <a class="nav-tab nav-tab-access_lists nav-tab-active" href="javascript:choose_tab('access_lists');">Access Lists</a>
2179 <a class="nav-tab nav-tab-access_login" href="javascript:choose_tab('access_login');">Login Access</a>
2180 <a class="nav-tab nav-tab-access_public" href="javascript:choose_tab('access_public');">Public Access</a>
2181 <a class="nav-tab nav-tab-external" href="javascript:choose_tab('external');">External Service</a>
2182 <a class="nav-tab nav-tab-advanced" href="javascript:choose_tab('advanced');">Advanced</a>
2183 </h2>
2184 <?php endif;
2185 } // END print_section_info_tabs()
2186
2187
2188 function print_section_info_access_lists( $args = '' ) {
2189 ?><div id="section_info_access_lists" class="section_info">
2190 <p>Manage who has access to this site using these lists.</p>
2191 <ol>
2192 <li><strong>Pending</strong> users are users who have successfully logged in to the site, but who haven't yet been approved (or blocked) by you.</li>
2193 <li><strong>Approved</strong> users have access to the site once they successfully log in.</li>
2194 <li><strong>Blocked</strong> users will receive an error message when they try to visit the site after authenticating.</li>
2195 </ol>
2196 </div>
2197 <table class="form-table">
2198 <tbody>
2199 <tr>
2200 <th scope="row">Pending Users</th>
2201 <td><?php $this->print_combo_auth_access_users_pending(); ?></td>
2202 </tr>
2203 <tr>
2204 <th scope="row">Approved Users</th>
2205 <td><?php $this->print_combo_auth_access_users_approved(); ?></td>
2206 </tr>
2207 <tr>
2208 <th scope="row">Blocked Users</th>
2209 <td><?php $this->print_combo_auth_access_users_blocked(); ?></td>
2210 </tr>
2211 </tbody>
2212 </table>
2213 <?php
2214 } // END print_section_info_access_lists()
2215
2216 function print_combo_auth_access_users_pending( $args = '' ) {
2217 // Get plugin option.
2218 $option = 'access_users_pending';
2219 $auth_settings_option = $this->get_plugin_option( $option );
2220 $auth_settings_option = is_array( $auth_settings_option ) ? $auth_settings_option : array();
2221
2222 // Print option elements.
2223 ?><ul id="list_auth_settings_access_users_pending" style="margin:0;">
2224 <?php if ( count( $auth_settings_option ) > 0 ) : ?>
2225 <?php foreach ( $auth_settings_option as $key => $pending_user ): ?>
2226 <?php if ( empty( $pending_user ) || count( $pending_user ) < 1 ) continue; ?>
2227 <?php $pending_user['is_wp_user'] = false; ?>
2228 <li>
2229 <input type="text" id="auth_settings_<?php echo $option; ?>_<?php echo $key; ?>" name="auth_settings_<?php echo $option; ?>[<?php echo $key; ?>][email]" value="<?php echo $pending_user['email']; ?>" readonly="true" class="auth-email" />
2230 <select name="auth_settings_<?php echo $option; ?>[<?php echo $key; ?>][role]" class="auth-role">
2231 <?php $this->wp_dropdown_permitted_roles( $pending_user['role'] ); ?>
2232 </select>
2233 <input type="button" class="button-primary" id="approve_user_<?php echo $key; ?>" onclick="auth_add_user( this, 'approved', false ); auth_ignore_user( this, 'pending' );" value="Approve" />
2234 <input type="button" class="button-primary" id="block_user_<?php echo $key; ?>" onclick="auth_add_user( this, 'blocked', false ); auth_ignore_user( this, 'pending' );" value="Block" />
2235 <a class="button" id="ignore_user_<?php echo $key; ?>" onclick="auth_ignore_user( this, 'pending' );" title="Remove user"><span class="glyphicon glyphicon-remove"></span></a>
2236 </li>
2237 <?php endforeach; ?>
2238 <?php else: ?>
2239 <li class="auth-empty"><em>No pending users</em></li>
2240 <?php endif; ?>
2241 </ul>
2242 <?php
2243 } // END print_combo_auth_access_users_pending()
2244
2245 function print_combo_auth_access_users_approved( $args = '' ) {
2246 // Get plugin option.
2247 $option = 'access_users_approved';
2248 $admin_mode = ( is_array( $args ) && array_key_exists( 'multisite_admin', $args ) && $args['multisite_admin'] === true ) ? 'multisite admin' : 'single admin';
2249 $auth_settings_option = $this->get_plugin_option( $option, $admin_mode, 'no override' );
2250 $auth_settings_option = is_array( $auth_settings_option ) ? $auth_settings_option : array();
2251
2252 // Get multisite approved users (add them to top of list, greyed out).
2253 $auth_multisite_settings = $this->get_plugin_options( 'multisite admin' );
2254 $option_multisite = 'access_users_approved';
2255 $auth_settings_option_multisite = array();
2256 if (
2257 is_multisite() &&
2258 array_key_exists( 'multisite_override', $auth_multisite_settings ) &&
2259 $auth_multisite_settings['multisite_override'] === '1'
2260 ) {
2261 $auth_settings_option_multisite = $this->get_plugin_option( $option, 'multisite admin', 'allow override' );
2262 $auth_settings_option_multisite = is_array( $auth_settings_option_multisite ) ? $auth_settings_option_multisite : array();
2263 }
2264
2265 // Get default role for new user dropdown.
2266 $access_default_role = $this->get_plugin_option( 'access_default_role', 'single admin', 'allow override' );
2267
2268 // Get custom usermeta field to show.
2269 $advanced_usermeta = $this->get_plugin_option( 'advanced_usermeta' );
2270
2271 // Adjust javascript function prefixes if multisite.
2272 $js_function_prefix = $admin_mode === 'multisite admin' ? 'auth_multisite_' : 'auth_';
2273 $multisite_admin_page = $admin_mode === 'multisite admin';
2274
2275 ?><ul id="list_auth_settings_access_users_approved" style="margin:0;">
2276 <?php if ( ! $multisite_admin_page ) :
2277 foreach ( $auth_settings_option_multisite as $key => $approved_user ) :
2278 if ( empty( $approved_user ) || count( $approved_user ) < 1 ) :
2279 continue;
2280 endif;
2281 if ( $approved_wp_user = get_user_by( 'email', $approved_user['email'] ) ) :
2282 $approved_user['email'] = $approved_wp_user->user_email;
2283 $approved_user['role'] = $multisite_admin_page || count( $approved_wp_user->roles ) === 0 ? $approved_user['role'] : array_shift( $approved_wp_user->roles );
2284 $approved_user['date_added'] = $approved_wp_user->user_registered;
2285 endif;
2286 if ( $approved_wp_user && strlen( $advanced_usermeta ) > 0 ) :
2287 $approved_user['usermeta'] = get_user_meta( $approved_wp_user->ID, $advanced_usermeta, true );
2288 if ( is_array( $approved_user['usermeta'] ) || is_object( $approved_user['usermeta'] ) ) :
2289 $approved_user['usermeta'] = serialize( $approved_user['usermeta'] );
2290 endif;
2291 else :
2292 $approved_user['usermeta'] = '';
2293 endif; ?>
2294 <li>
2295 <input type="text" id="auth_multisite_settings_<?php echo $option; ?>_<?php echo $key; ?>" name="auth_multisite_settings_<?php echo $option; ?>[<?php echo $key; ?>][email]" value="<?php echo $approved_user['email']; ?>" readonly="true" class="auth-email auth-multisite-email" />
2296 <select name="auth_multisite_settings_<?php echo $option; ?>[<?php echo $key; ?>][role]" class="auth-role auth-multisite-role" disabled="disabled">
2297 <?php $this->wp_dropdown_permitted_roles( $approved_user['role'] ); ?>
2298 </select>
2299 <input type="text" name="auth_multisite_settings_<?php echo $option; ?>[<?php echo $key; ?>][date_added]" value="<?php echo date( 'M Y', strtotime( $approved_user['date_added'] ) ); ?>" readonly="true" class="auth-date-added auth-multisite-date-added" disabled="disabled" />
2300 <?php if ( strlen( $advanced_usermeta ) > 0 ) : ?>
2301 <input type="text" name="auth_multisite_settings_<?php echo $option; ?>[<?php echo $key; ?>][usermeta]" value="<?php echo htmlspecialchars( $approved_user['usermeta'], ENT_COMPAT ); ?>" readonly="true" class="auth-usermeta auth-multisite-usermeta" disabled="disabled" />
2302 <?php endif; ?>
2303 &nbsp;&nbsp;<a title="WordPress Multisite user" class="auth-multisite-user"><span class="glyphicon glyphicon-globe"></span></a>
2304 </li>
2305 <?php endforeach;
2306 endif;
2307 foreach ( $auth_settings_option as $key => $approved_user ):
2308 $is_current_user = false;
2309 $local_user_icon = array_key_exists( 'local_user', $approved_user ) && $approved_user['local_user'] === 'true' ? '&nbsp;<a title="Local WordPress user" class="auth-local-user"><span class="glyphicon glyphicon-user"></span></a>' : '';
2310 if ( empty( $approved_user ) || count( $approved_user ) < 1 ) :
2311 continue;
2312 endif;
2313 $approved_user['usermeta'] = '';
2314 if ( $approved_wp_user = get_user_by( 'email', $approved_user['email'] ) ) :
2315 $approved_user['email'] = $approved_wp_user->user_email;
2316 $approved_user['role'] = $multisite_admin_page || count( $approved_wp_user->roles ) === 0 ? $approved_user['role'] : array_shift( $approved_wp_user->roles );
2317 $approved_user['date_added'] = $approved_wp_user->user_registered;
2318 $approved_user['is_wp_user'] = true;
2319 $is_current_user = $approved_wp_user->ID === get_current_user_id();
2320 else :
2321 $approved_user['is_wp_user'] = false;
2322 endif;
2323 if ( $approved_wp_user && strlen( $advanced_usermeta ) > 0 ) :
2324 $approved_user['usermeta'] = get_user_meta( $approved_wp_user->ID, $advanced_usermeta, true );
2325 if ( is_array( $approved_user['usermeta'] ) || is_object( $approved_user['usermeta'] ) ) :
2326 $approved_user['usermeta'] = serialize( $approved_user['usermeta'] );
2327 endif;
2328 else :
2329 $approved_user['usermeta'] = '';
2330 endif; ?>
2331 <li>
2332 <input type="text" id="auth_settings_<?php echo $option; ?>_<?php echo $key; ?>" name="auth_settings_<?php echo $option; ?>[<?php echo $key; ?>][email]" value="<?php echo $approved_user['email']; ?>" readonly="true" class="auth-email" />
2333 <select name="auth_settings_<?php echo $option; ?>[<?php echo $key; ?>][role]" class="auth-role" onchange="<?php echo $js_function_prefix; ?>change_role( this );">
2334 <?php $disable_input = $is_current_user ? 'disabled' : null; ?>
2335 <?php $this->wp_dropdown_permitted_roles( $approved_user['role'], $disable_input ); ?>
2336 </select>
2337 <input type="text" name="auth_settings_<?php echo $option; ?>[<?php echo $key; ?>][date_added]" value="<?php echo date( 'M Y', strtotime( $approved_user['date_added'] ) ); ?>" readonly="true" class="auth-date-added" />
2338 <?php if ( strlen( $advanced_usermeta ) > 0 ) : ?>
2339 <input type="text" name="auth_settings_<?php echo $option; ?>[<?php echo $key; ?>][usermeta]" value="<?php echo htmlspecialchars( $approved_user['usermeta'], ENT_COMPAT ); ?>" class="auth-usermeta" />
2340 <a class="button button-small button-primary" id="update_usermeta_<?php echo $key; ?>" onclick="<?php echo $js_function_prefix; ?>update_usermeta( this );" title="Update usermeta"><span class="glyphicon glyphicon-floppy-saved"></span></a>
2341 <?php endif; ?>
2342 <?php if ( ! $is_current_user ): ?>
2343 <?php if ( ! $multisite_admin_page ) : ?>
2344 <a class="button" id="block_user_<?php echo $key; ?>" onclick="<?php echo $js_function_prefix; ?>add_user( this, 'blocked', false ); <?php echo $js_function_prefix; ?>ignore_user( this, 'approved' );" title="Block/Ban user"><span class="glyphicon glyphicon-ban-circle"></span></a>
2345 <?php endif; ?>
2346 <a class="button" id="ignore_user_<?php echo $key; ?>" onclick="<?php echo $js_function_prefix; ?>ignore_user(this, 'approved');" title="Remove user"><span class="glyphicon glyphicon-remove"></span></a>
2347 <?php endif; ?>
2348 <?php echo $local_user_icon; ?>
2349 </li>
2350 <?php endforeach; ?>
2351 </ul>
2352 <div id="new_auth_settings_<?php echo $option; ?>">
2353 <input type="text" name="new_approved_user_email" id="new_approved_user_email" placeholder="email address" class="auth-email new" />
2354 <select name="new_approved_user_role" id="new_approved_user_role" class="auth-role">
2355 <?php $this->wp_dropdown_permitted_roles( $access_default_role ); ?>
2356 </select>
2357 <div class="btn-group">
2358 <input type="button" class="btn button-primary dropdown-toggle" id="approve_user_new" onclick="<?php echo $js_function_prefix; ?>add_user(this, 'approved');" value="Approve" />
2359 <button type="button" class="btn button-primary dropdown-toggle" data-toggle="dropdown">
2360 <span class="caret"></span>
2361 <span class="sr-only">Toggle Dropdown</span>
2362 </button>
2363 <ul class="dropdown-menu" role="menu">
2364 <li><a href="javascript:void(0);" onclick="<?php echo $js_function_prefix; ?>add_user( document.getElementById('approve_user_new'), 'approved', true);">Create a local WordPress <br />account instead, and email <br />the user their password.</a></li>
2365 </ul>
2366 </div>
2367 </div>
2368 <?php
2369 } // END print_combo_auth_access_users_approved()
2370
2371 function print_combo_auth_access_users_blocked( $args = '' ) {
2372 // Get plugin option.
2373 $option = 'access_users_blocked';
2374 $auth_settings_option = $this->get_plugin_option( $option );
2375 $auth_settings_option = is_array( $auth_settings_option ) ? $auth_settings_option : array();
2376
2377 // Get default role for new blocked user dropdown.
2378 $access_default_role = $this->get_plugin_option( 'access_default_role', 'single admin', 'allow override' );
2379
2380 // Print option elements.
2381 ?><ul id="list_auth_settings_<?php echo $option; ?>" style="margin:0;">
2382 <?php foreach ( $auth_settings_option as $key => $blocked_user ): ?>
2383 <?php if ( empty( $blocked_user ) || count( $blocked_user ) < 1 ) continue; ?>
2384 <?php if ( $blocked_wp_user = get_user_by( 'email', $blocked_user['email'] ) ): ?>
2385 <?php $blocked_user['email'] = $blocked_wp_user->user_email; ?>
2386 <?php $blocked_user['role'] = array_shift( $blocked_wp_user->roles ); ?>
2387 <?php $blocked_user['date_added'] = $blocked_wp_user->user_registered; ?>
2388 <?php $blocked_user['is_wp_user'] = true; ?>
2389 <?php else: ?>
2390 <?php $blocked_user['is_wp_user'] = false; ?>
2391 <?php endif; ?>
2392 <li>
2393 <input type="text" id="auth_settings_<?php echo $option; ?>_<?php echo $key; ?>" name="auth_settings_<?php echo $option; ?>[<?php echo $key; ?>][email]" value="<?php echo $blocked_user['email']; ?>" readonly="true" class="auth-email" />
2394 <select name="auth_settings_<?php echo $option; ?>[<?php echo $key; ?>][role]" class="auth-role">
2395 <?php $this->wp_dropdown_permitted_roles( $blocked_user['role'] ); ?>
2396 </select>
2397 <input type="text" name="auth_settings_<?php echo $option; ?>[<?php echo $key; ?>][date_added]" value="<?php echo date( 'M Y', strtotime( $blocked_user['date_added'] ) ); ?>" readonly="true" class="auth-date-added" />
2398 <a class="button" id="ignore_user_<?php echo $key; ?>" onclick="auth_ignore_user(this, 'blocked');" title="Remove user"><span class="glyphicon glyphicon-remove"></span></a>
2399 </li>
2400 <?php endforeach; ?>
2401 </ul>
2402 <div id="new_auth_settings_<?php echo $option; ?>">
2403 <input type="text" name="new_blocked_user_email" id="new_blocked_user_email" placeholder="email address" class="auth-email new" />
2404 <select name="new_blocked_user_role" id="new_blocked_user_role" class="auth-role">
2405 <option value="<?php echo $access_default_role; ?>"><?php echo ucfirst( $access_default_role ); ?></option>
2406 </select>
2407 <input class="button-primary" type="button" id="block_user_new" onclick="auth_add_user(this, 'blocked');" value="Block" /><br />
2408 </div>
2409 <?php
2410 } // END print_combo_auth_access_users_blocked()
2411
2412
2413 function print_section_info_access_login( $args = '' ) {
2414 ?><div id="section_info_access_login" class="section_info">
2415 <?php wp_nonce_field( 'save_auth_settings', 'nonce_save_auth_settings' ); ?>
2416 <p>Choose who is able to log into this site below.</p>
2417 </div><?php
2418 } // END print_section_info_access_login()
2419
2420 function print_radio_auth_access_who_can_login( $args = '' ) {
2421 // Get plugin option.
2422 $option = 'access_who_can_login';
2423 $admin_mode = ( is_array( $args ) && array_key_exists( 'multisite_admin', $args ) && $args['multisite_admin'] === true ) ? 'multisite admin' : 'single admin';
2424 $auth_settings_option = $this->get_plugin_option( $option, $admin_mode, 'allow override', 'print overlay' );
2425
2426 // Workaround: javascript code hides/shows other settings based
2427 // on the selection in this option. If this option is overridden
2428 // by a multisite option, it should show that value in order to
2429 // correctly display the other appropriate options.
2430 // Side effect: this site option will be overwritten by the
2431 // multisite option on save. Since this is a 2-item radio, we
2432 // determined this was acceptable.
2433 if ( is_multisite() && $admin_mode === 'single admin' && $this->get_plugin_option( 'multisite_override', 'multisite admin' ) === '1' ) {
2434 $auth_settings_option = $this->get_plugin_option( $option, 'multisite admin' );
2435 }
2436
2437 // Print option elements.
2438 ?><input type="radio" id="radio_auth_settings_<?php echo $option; ?>_external_users" name="auth_settings[<?php echo $option; ?>]" value="external_users"<?php checked( 'external_users' == $auth_settings_option ); ?> /><label for="radio_auth_settings_<?php echo $option; ?>_external_users">All authenticated users (All external service users and all WordPress users)</label><br />
2439 <input type="radio" id="radio_auth_settings_<?php echo $option; ?>_approved_users" name="auth_settings[<?php echo $option; ?>]" value="approved_users"<?php checked( 'approved_users' == $auth_settings_option ); ?> /><label for="radio_auth_settings_<?php echo $option; ?>_approved_users">Only <a href="javascript:choose_tab('access_lists');" id="dashboard_link_approved_users">approved users</a> (Approved external users and all WordPress users)</label><br /><?php
2440 } // END print_radio_auth_access_who_can_login()
2441
2442 function print_select_auth_access_role_receive_pending_emails( $args = '' ) {
2443 // Get plugin option.
2444 $option = 'access_role_receive_pending_emails';
2445 $auth_settings_option = $this->get_plugin_option( $option );
2446
2447 // Print option elements.
2448 ?><select id="auth_settings_<?php echo $option; ?>" name="auth_settings[<?php echo $option; ?>]">
2449 <option value="---" <?php selected( $auth_settings_option, '---' ); ?>>None (Don't send notification emails)</option>
2450 <?php wp_dropdown_roles( $auth_settings_option ); ?>
2451 </select><?php
2452 } // END print_select_auth_access_role_receive_pending_emails()
2453
2454 function print_wysiwyg_auth_access_pending_redirect_to_message( $args = '' ) {
2455 // Get plugin option.
2456 $option = 'access_pending_redirect_to_message';
2457 $auth_settings_option = $this->get_plugin_option( $option );
2458
2459 // Print option elements.
2460 wp_editor(
2461 wpautop( $auth_settings_option ),
2462 "auth_settings_$option",
2463 array(
2464 'media_buttons' => false,
2465 'textarea_name' => "auth_settings[$option]",
2466 'textarea_rows' => 5,
2467 'tinymce' => true,
2468 'teeny' => true,
2469 'quicktags' => false,
2470 )
2471 );
2472 } // END print_wysiwyg_auth_access_pending_redirect_to_message()
2473
2474 function print_wysiwyg_auth_access_blocked_redirect_to_message( $args = '' ) {
2475 // Get plugin option.
2476 $option = 'access_blocked_redirect_to_message';
2477 $auth_settings_option = $this->get_plugin_option( $option );
2478
2479 // Print option elements.
2480 wp_editor(
2481 wpautop( $auth_settings_option ),
2482 "auth_settings_$option",
2483 array(
2484 'media_buttons' => false,
2485 'textarea_name' => "auth_settings[$option]",
2486 'textarea_rows' => 5,
2487 'tinymce' => true,
2488 'teeny' => true,
2489 'quicktags' => false,
2490 )
2491 );
2492 } // END print_wysiwyg_auth_access_blocked_redirect_to_message()
2493
2494 function print_checkbox_auth_access_should_email_approved_users( $args = '' ) {
2495 // Get plugin option.
2496 $option = 'access_should_email_approved_users';
2497 $auth_settings_option = $this->get_plugin_option( $option );
2498
2499 // Print option elements.
2500 ?><input type="checkbox" id="auth_settings_<?php echo $option; ?>" name="auth_settings[<?php echo $option; ?>]" value="1"<?php checked( 1 == $auth_settings_option ); ?> /><label for="auth_settings_<?php echo $option; ?>">Send a welcome email when approving a new user</label><?php
2501 } // END print_checkbox_auth_external_ldap()
2502
2503 function print_text_auth_access_email_approved_users_subject( $args = '' ) {
2504 // Get plugin option.
2505 $option = 'access_email_approved_users_subject';
2506 $auth_settings_option = $this->get_plugin_option( $option );
2507
2508 // Print option elements.
2509 ?><input type="text" id="auth_settings_<?php echo $option; ?>" name="auth_settings[<?php echo $option; ?>]" value="<?php echo $auth_settings_option; ?>" placeholder="Welcome to [site_name]!" style="width:320px;" /><br /><small>You can use the <b>[site_name]</b> shortcode.</small><?php
2510 } // END print_text_auth_access_email_approved_users_subject()
2511
2512 function print_wysiwyg_auth_access_email_approved_users_body( $args = '' ) {
2513 // Get plugin option.
2514 $option = 'access_email_approved_users_body';
2515 $auth_settings_option = $this->get_plugin_option( $option );
2516
2517 // Print option elements.
2518 wp_editor(
2519 wpautop( $auth_settings_option ),
2520 "auth_settings_$option",
2521 array(
2522 'media_buttons' => false,
2523 'textarea_name' => "auth_settings[$option]",
2524 'textarea_rows' => 9,
2525 'tinymce' => true,
2526 'teeny' => true,
2527 'quicktags' => false,
2528 )
2529 );
2530
2531 ?><small>You can use <b>[site_name]</b>, <b>[site_url]</b>, and <b>[user_email]</b> shortcodes.</small><?php
2532
2533 } // END print_wysiwyg_auth_access_email_approved_users_body()
2534
2535
2536 function print_section_info_access_public( $args = '' ) {
2537 ?><div id="section_info_access_public" class="section_info">
2538 <p>Choose your public access options here.</p>
2539 </div><?php
2540 } // END print_section_info_access_public()
2541
2542 function print_radio_auth_access_who_can_view( $args = '' ) {
2543 // Get plugin option.
2544 $option = 'access_who_can_view';
2545 $admin_mode = ( is_array( $args ) && array_key_exists( 'multisite_admin', $args ) && $args['multisite_admin'] === true ) ? 'multisite admin' : 'single admin';
2546 $auth_settings_option = $this->get_plugin_option( $option, $admin_mode, 'allow override', 'print overlay' );
2547
2548 // Workaround: javascript code hides/shows other settings based
2549 // on the selection in this option. If this option is overridden
2550 // by a multisite option, it should show that value in order to
2551 // correctly display the other appropriate options.
2552 // Side effect: this site option will be overwritten by the
2553 // multisite option on save. Since this is a 2-item radio, we
2554 // determined this was acceptable.
2555 if ( is_multisite() && $admin_mode === 'single admin' && $this->get_plugin_option( 'multisite_override', 'multisite admin' ) === '1' ) {
2556 $auth_settings_option = $this->get_plugin_option( $option, 'multisite admin' );
2557 }
2558
2559 // Print option elements.
2560 ?><input type="radio" id="radio_auth_settings_<?php echo $option; ?>_everyone" name="auth_settings[<?php echo $option; ?>]" value="everyone"<?php checked( 'everyone' == $auth_settings_option ); ?> /><label for="radio_auth_settings_<?php echo $option; ?>_everyone">Everyone can see the site</label><br />
2561 <input type="radio" id="radio_auth_settings_<?php echo $option; ?>_logged_in_users" name="auth_settings[<?php echo $option; ?>]" value="logged_in_users"<?php checked( 'logged_in_users' == $auth_settings_option ); ?> /><label for="radio_auth_settings_<?php echo $option; ?>_logged_in_users">Only logged in users can see the site</label><br /><?php
2562 } // END print_radio_auth_access_who_can_view()
2563
2564 function print_radio_auth_access_redirect( $args = '' ) {
2565 // Get plugin option.
2566 $option = 'access_redirect';
2567 $auth_settings_option = $this->get_plugin_option( $option );
2568
2569 // Print option elements.
2570 ?><input type="radio" id="radio_auth_settings_<?php echo $option; ?>_to_login" name="auth_settings[<?php echo $option; ?>]" value="login"<?php checked( 'login' == $auth_settings_option ); ?> /><label for="radio_auth_settings_<?php echo $option; ?>_to_login">Send them to the login screen</label><br />
2571 <input type="radio" id="radio_auth_settings_<?php echo $option; ?>_to_message" name="auth_settings[<?php echo $option; ?>]" value="message"<?php checked( 'message' == $auth_settings_option ); ?> /><label for="radio_auth_settings_<?php echo $option; ?>_to_message">Show them the anonymous access message (below)</label><?php
2572 } // END print_radio_auth_access_redirect()
2573
2574 function print_radio_auth_access_public_warning( $args = '' ) {
2575 // Get plugin option.
2576 $option = 'access_public_warning';
2577 $auth_settings_option = $this->get_plugin_option( $option );
2578
2579 // Print option elements.
2580 ?><input type="radio" id="radio_auth_settings_<?php echo $option; ?>_no" name="auth_settings[<?php echo $option; ?>]" value="no_warning"<?php checked( 'no_warning' == $auth_settings_option ); ?> /><label for="radio_auth_settings_<?php echo $option; ?>_no">Show them the page <strong>without</strong> the anonymous access message</label><br />
2581 <input type="radio" id="radio_auth_settings_<?php echo $option; ?>" name="auth_settings[<?php echo $option; ?>]" value="warning"<?php checked( 'warning' == $auth_settings_option ); ?> /><label for="radio_auth_settings_<?php echo $option; ?>">Show them the page <strong>with</strong> the anonymous access message (marked up as a <a href="http://getbootstrap.com/components/#alerts-dismissible" target="_blank">Bootstrap Dismissible Alert</a>)</label><?php
2582 } // END print_radio_auth_access_public_warning()
2583
2584 function print_wysiwyg_auth_access_redirect_to_message( $args = '' ) {
2585 // Get plugin option.
2586 $option = 'access_redirect_to_message';
2587 $auth_settings_option = $this->get_plugin_option( $option );
2588
2589 // Print option elements.
2590 wp_editor(
2591 wpautop( $auth_settings_option ),
2592 "auth_settings_$option",
2593 array(
2594 'media_buttons' => false,
2595 'textarea_name' => "auth_settings[$option]",
2596 'textarea_rows' => 5,
2597 'tinymce' => true,
2598 'teeny' => true,
2599 'quicktags' => false,
2600 )
2601 );
2602 } // END print_wysiwyg_auth_access_redirect_to_message()
2603
2604 function print_multiselect_auth_access_public_pages( $args = '' ) {
2605 // Get plugin option.
2606 $option = 'access_public_pages';
2607 $auth_settings_option = $this->get_plugin_option( $option );
2608 $auth_settings_option = is_array( $auth_settings_option ) ? $auth_settings_option : array();
2609
2610 $post_types = get_post_types( '', 'names' );
2611 $post_types = is_array( $post_types ) ? $post_types : array();
2612
2613 // Print option elements.
2614 ?><select id="auth_settings_<?php echo $option; ?>" multiple="multiple" name="auth_settings[<?php echo $option; ?>][]">
2615 <optgroup label="Special">
2616 <option value="home" <?php echo in_array( 'home', $auth_settings_option ) ? 'selected="selected"' : ''; ?>>Home Page</option>
2617 </optgroup>
2618 <?php foreach ( $post_types as $post_type ): ?>
2619 <optgroup label="<?php echo ucfirst( $post_type ); ?>">
2620 <?php $pages = get_pages( array( 'post_type' => $post_type ) ); ?>
2621 <?php $pages = is_array( $pages ) ? $pages : array(); ?>
2622 <?php foreach ( $pages as $page ): ?>
2623 <option value="<?php echo $page->ID; ?>" <?php echo in_array( $page->ID, $auth_settings_option ) ? 'selected="selected"' : ''; ?>><?php echo $page->post_title; ?></option>
2624 <?php endforeach; ?>
2625 </optgroup>
2626 <?php endforeach; ?>
2627 </select><?php
2628 } // END print_multiselect_auth_access_public_pages()
2629
2630
2631 function print_section_info_external( $args = '' ) {
2632 ?><div id="section_info_external" class="section_info">
2633 <p>Enter your external server settings below.</p>
2634 </div><?php
2635 } // END print_section_info_external()
2636
2637 function print_select_auth_access_default_role( $args = '' ) {
2638 // Get plugin option.
2639 $option = 'access_default_role';
2640 $admin_mode = ( is_array( $args ) && array_key_exists( 'multisite_admin', $args ) && $args['multisite_admin'] === true ) ? 'multisite admin' : 'single admin';
2641 $auth_settings_option = $this->get_plugin_option( $option, $admin_mode, 'allow override', 'print overlay' );
2642
2643 // Print option elements.
2644 ?><select id="auth_settings_<?php echo $option; ?>" name="auth_settings[<?php echo $option; ?>]">
2645 <?php wp_dropdown_roles( $auth_settings_option ); ?>
2646 </select><?php
2647 } // END print_select_auth_access_default_role()
2648
2649 function print_checkbox_auth_external_google( $args = '' ) {
2650 // Get plugin option.
2651 $option = 'google';
2652 $admin_mode = ( is_array( $args ) && array_key_exists( 'multisite_admin', $args ) && $args['multisite_admin'] === true ) ? 'multisite admin' : 'single admin';
2653 $auth_settings_option = $this->get_plugin_option( $option, $admin_mode, 'allow override', 'print overlay' );
2654
2655 // Make sure php5-curl extension is installed on server.
2656 $curl_installed_message = ! function_exists( 'curl_init' ) ? '<span style="color: red;">(Warning: <a href="http://www.php.net//manual/en/curl.installation.php" target="_blank" style="color: red;">PHP CURL extension</a> is <strong>not</strong> installed)</span>' : '';
2657
2658 // Print option elements.
2659 ?><input type="checkbox" id="auth_settings_<?php echo $option; ?>" name="auth_settings[<?php echo $option; ?>]" value="1"<?php checked( 1 == $auth_settings_option ); ?> /><label for="auth_settings_<?php echo $option; ?>">Enable Google Logins</label> <?php echo $curl_installed_message; ?><?php
2660 } // END print_checkbox_auth_external_google()
2661
2662 function print_text_google_clientid( $args = '' ) {
2663 // Get plugin option.
2664 $option = 'google_clientid';
2665 $admin_mode = ( is_array( $args ) && array_key_exists( 'multisite_admin', $args ) && $args['multisite_admin'] === true ) ? 'multisite admin' : 'single admin';
2666 $auth_settings_option = $this->get_plugin_option( $option, $admin_mode, 'allow override', 'print overlay' );
2667
2668 // Print option elements.
2669 $site_url_parts = parse_url( get_site_url() );
2670 $site_url_host = $site_url_parts['scheme'] . '://' . $site_url_parts['host'] . '/';
2671 ?>If you don't have a Google Client ID and Secret, generate them by following these instructions:
2672 <ol>
2673 <li>Click <strong>Create a Project</strong> on the <a href="https://cloud.google.com/console" target="_blank">Google Developers Console</a>. You can name it whatever you want.</li>
2674 <li>Within the project, navigate to <em>APIs and Auth</em> &gt; <em>Credentials</em>, then click <strong>Create New Client ID</strong> under OAuth. Use these settings:
2675 <ul>
2676 <li>Application Type: <strong>Web application</strong></li>
2677 <li>Authorized Javascript Origins: <strong><?php echo $site_url_host; ?></strong></li>
2678 <li>Authorized Redirect URI: <em>none</em></li>
2679 </ul>
2680 </li>
2681 <li>Copy/paste your new Client ID/Secret pair into the fields below.</li>
2682 <li><strong>Note</strong>: Navigate to <em>APIs and Auth</em> &gt; <em>Consent screen</em> to change the way the Google consent screen appears after a user has successfully entered their password, but before they are redirected back to WordPress.</li>
2683 </ol>
2684 <input type="text" id="auth_settings_<?php echo $option; ?>" name="auth_settings[<?php echo $option; ?>]" value="<?php echo $auth_settings_option; ?>" placeholder="1234567890123-kdjr85yt6vjr6d8g7dhr8g7d6durjf7g.apps.googleusercontent.com" style="width:560px;" /><?php
2685 } // END print_text_google_clientid()
2686
2687 function print_text_google_clientsecret( $args = '' ) {
2688 // Get plugin option.
2689 $option = 'google_clientsecret';
2690 $admin_mode = ( is_array( $args ) && array_key_exists( 'multisite_admin', $args ) && $args['multisite_admin'] === true ) ? 'multisite admin' : 'single admin';
2691 $auth_settings_option = $this->get_plugin_option( $option, $admin_mode, 'allow override', 'print overlay' );
2692
2693 // Print option elements.
2694 ?><input type="text" id="auth_settings_<?php echo $option; ?>" name="auth_settings[<?php echo $option; ?>]" value="<?php echo $auth_settings_option; ?>" placeholder="sDNgX5_pr_5bly-frKmvp8jT" style="width:220px;" /><?php
2695 } // END print_text_google_clientsecret()
2696
2697 function print_checkbox_auth_external_cas( $args = '' ) {
2698 // Get plugin option.
2699 $option = 'cas';
2700 $admin_mode = ( is_array( $args ) && array_key_exists( 'multisite_admin', $args ) && $args['multisite_admin'] === true ) ? 'multisite admin' : 'single admin';
2701 $auth_settings_option = $this->get_plugin_option( $option, $admin_mode, 'allow override', 'print overlay' );
2702
2703 // Make sure php5-curl extension is installed on server.
2704 $curl_installed_message = ! function_exists( 'curl_init' ) ? '<span style="color: red;">(Warning: <a href="http://www.php.net//manual/en/curl.installation.php" target="_blank" style="color: red;">PHP CURL extension</a> is <strong>not</strong> installed)</span>' : '';
2705
2706 // Print option elements.
2707 ?><input type="checkbox" id="auth_settings_<?php echo $option; ?>" name="auth_settings[<?php echo $option; ?>]" value="1"<?php checked( 1 == $auth_settings_option ); ?> /><label for="auth_settings_<?php echo $option; ?>">Enable CAS Logins</label> <?php echo $curl_installed_message; ?><?php
2708 } // END print_checkbox_auth_external_cas()
2709
2710 function print_text_cas_custom_label( $args = '' ) {
2711 // Get plugin option.
2712 $option = 'cas_custom_label';
2713 $admin_mode = ( is_array( $args ) && array_key_exists( 'multisite_admin', $args ) && $args['multisite_admin'] === true ) ? 'multisite admin' : 'single admin';
2714 $auth_settings_option = $this->get_plugin_option( $option, $admin_mode, 'allow override', 'print overlay' );
2715
2716 // Print option elements.
2717 ?>The button on the login page will read:<p><a class="button-primary button-large" style="padding: 3px 16px; height: 36px;"><span class="dashicons dashicons-lock" style="margin: 4px 4px 0 0;"></span> <strong>Sign in with </strong><input type="text" id="auth_settings_<?php echo $option; ?>" name="auth_settings[<?php echo $option; ?>]" value="<?php echo $auth_settings_option; ?>" placeholder="CAS" style="width: 100px;" /></a></p><?php
2718 } // END print_text_cas_custom_label()
2719
2720 function print_text_cas_host( $args = '' ) {
2721 // Get plugin option.
2722 $option = 'cas_host';
2723 $admin_mode = ( is_array( $args ) && array_key_exists( 'multisite_admin', $args ) && $args['multisite_admin'] === true ) ? 'multisite admin' : 'single admin';
2724 $auth_settings_option = $this->get_plugin_option( $option, $admin_mode, 'allow override', 'print overlay' );
2725
2726 // Print option elements.
2727 ?><input type="text" id="auth_settings_<?php echo $option; ?>" name="auth_settings[<?php echo $option; ?>]" value="<?php echo $auth_settings_option; ?>" placeholder="authn.example.edu" /><?php
2728 } // END print_text_cas_host()
2729
2730 function print_text_cas_port( $args = '' ) {
2731 // Get plugin option.
2732 $option = 'cas_port';
2733 $admin_mode = ( is_array( $args ) && array_key_exists( 'multisite_admin', $args ) && $args['multisite_admin'] === true ) ? 'multisite admin' : 'single admin';
2734 $auth_settings_option = $this->get_plugin_option( $option, $admin_mode, 'allow override', 'print overlay' );
2735
2736 // Print option elements.
2737 ?><input type="text" id="auth_settings_<?php echo $option; ?>" name="auth_settings[<?php echo $option; ?>]" value="<?php echo $auth_settings_option; ?>" placeholder="443" style="width:50px;" /><?php
2738 } // END print_text_cas_port()
2739
2740 function print_text_cas_path( $args = '' ) {
2741 // Get plugin option.
2742 $option = 'cas_path';
2743 $admin_mode = ( is_array( $args ) && array_key_exists( 'multisite_admin', $args ) && $args['multisite_admin'] === true ) ? 'multisite admin' : 'single admin';
2744 $auth_settings_option = $this->get_plugin_option( $option, $admin_mode, 'allow override', 'print overlay' );
2745
2746 // Print option elements.
2747 ?><input type="text" id="auth_settings_<?php echo $option; ?>" name="auth_settings[<?php echo $option; ?>]" value="<?php echo $auth_settings_option; ?>" placeholder="/cas" /><?php
2748 } // END print_text_cas_path()
2749
2750 function print_checkbox_auth_external_ldap( $args = '' ) {
2751 // Get plugin option.
2752 $option = 'ldap';
2753 $admin_mode = ( is_array( $args ) && array_key_exists( 'multisite_admin', $args ) && $args['multisite_admin'] === true ) ? 'multisite admin' : 'single admin';
2754 $auth_settings_option = $this->get_plugin_option( $option, $admin_mode, 'allow override', 'print overlay' );
2755
2756 // Make sure php5-ldap extension is installed on server.
2757 $ldap_installed_message = ! function_exists( 'ldap_connect' ) ? '<span style="color: red;">(Warning: <a href="http://www.php.net/manual/en/ldap.installation.php" target="_blank" style="color: red;">PHP LDAP extension</a> is <strong>not</strong> installed)</span>' : '';
2758
2759 // Print option elements.
2760 ?><input type="checkbox" id="auth_settings_<?php echo $option; ?>" name="auth_settings[<?php echo $option; ?>]" value="1"<?php checked( 1 == $auth_settings_option ); ?> /><label for="auth_settings_<?php echo $option; ?>">Enable LDAP Logins</label> <?php echo $ldap_installed_message; ?><?php
2761 } // END print_checkbox_auth_external_ldap()
2762
2763 function print_text_ldap_host( $args = '' ) {
2764 // Get plugin option.
2765 $option = 'ldap_host';
2766 $admin_mode = ( is_array( $args ) && array_key_exists( 'multisite_admin', $args ) && $args['multisite_admin'] === true ) ? 'multisite admin' : 'single admin';
2767 $auth_settings_option = $this->get_plugin_option( $option, $admin_mode, 'allow override', 'print overlay' );
2768
2769 // Print option elements.
2770 ?><input type="text" id="auth_settings_<?php echo $option; ?>" name="auth_settings[<?php echo $option; ?>]" value="<?php echo $auth_settings_option; ?>" placeholder="ldap.example.edu" /><?php
2771 } // END print_text_ldap_host()
2772
2773 function print_text_ldap_port( $args = '' ) {
2774 // Get plugin option.
2775 $option = 'ldap_port';
2776 $admin_mode = ( is_array( $args ) && array_key_exists( 'multisite_admin', $args ) && $args['multisite_admin'] === true ) ? 'multisite admin' : 'single admin';
2777 $auth_settings_option = $this->get_plugin_option( $option, $admin_mode, 'allow override', 'print overlay' );
2778
2779 // Print option elements.
2780 ?><input type="text" id="auth_settings_<?php echo $option; ?>" name="auth_settings[<?php echo $option; ?>]" value="<?php echo $auth_settings_option; ?>" placeholder="389" style="width:50px;" /><?php
2781 } // END print_text_ldap_port()
2782
2783 function print_text_ldap_search_base( $args = '' ) {
2784 // Get plugin option.
2785 $option = 'ldap_search_base';
2786 $admin_mode = ( is_array( $args ) && array_key_exists( 'multisite_admin', $args ) && $args['multisite_admin'] === true ) ? 'multisite admin' : 'single admin';
2787 $auth_settings_option = $this->get_plugin_option( $option, $admin_mode, 'allow override', 'print overlay' );
2788
2789 // Print option elements.
2790 ?><input type="text" id="auth_settings_<?php echo $option; ?>" name="auth_settings[<?php echo $option; ?>]" value="<?php echo $auth_settings_option; ?>" placeholder="ou=people,dc=example,dc=edu" style="width:225px;" /><?php
2791 } // END print_text_ldap_search_base()
2792
2793 function print_text_ldap_uid( $args = '' ) {
2794 // Get plugin option.
2795 $option = 'ldap_uid';
2796 $admin_mode = ( is_array( $args ) && array_key_exists( 'multisite_admin', $args ) && $args['multisite_admin'] === true ) ? 'multisite admin' : 'single admin';
2797 $auth_settings_option = $this->get_plugin_option( $option, $admin_mode, 'allow override', 'print overlay' );
2798
2799 // Print option elements.
2800 ?><input type="text" id="auth_settings_<?php echo $option; ?>" name="auth_settings[<?php echo $option; ?>]" value="<?php echo $auth_settings_option; ?>" placeholder="uid" style="width:80px;" /><?php
2801 } // END print_text_ldap_uid()
2802
2803 function print_text_ldap_user( $args = '' ) {
2804 // Get plugin option.
2805 $option = 'ldap_user';
2806 $admin_mode = ( is_array( $args ) && array_key_exists( 'multisite_admin', $args ) && $args['multisite_admin'] === true ) ? 'multisite admin' : 'single admin';
2807 $auth_settings_option = $this->get_plugin_option( $option, $admin_mode, 'allow override', 'print overlay' );
2808
2809 // Print option elements.
2810 ?><input type="text" id="auth_settings_<?php echo $option; ?>" name="auth_settings[<?php echo $option; ?>]" value="<?php echo $auth_settings_option; ?>" placeholder="cn=directory-user,ou=specials,dc=example,dc=edu" style="width:330px;" /><?php
2811 } // END print_text_ldap_user()
2812
2813 function print_password_ldap_password( $args = '' ) {
2814 // Get plugin option.
2815 $option = 'ldap_password';
2816 $admin_mode = ( is_array( $args ) && array_key_exists( 'multisite_admin', $args ) && $args['multisite_admin'] === true ) ? 'multisite admin' : 'single admin';
2817 $auth_settings_option = $this->get_plugin_option( $option, $admin_mode, 'allow override', 'print overlay' );
2818
2819 // Print option elements.
2820 ?><input type="password" id="garbage_to_stop_autofill" name="garbage" value="" autocomplete="off" style="display:none;" />
2821 <input type="password" id="auth_settings_<?php echo $option; ?>" name="auth_settings[<?php echo $option; ?>]" value="<?php echo $this->decrypt( base64_decode( $auth_settings_option ) ); ?>" autocomplete="off" /><?php
2822 } // END print_password_ldap_password()
2823
2824 function print_checkbox_ldap_tls( $args = '' ) {
2825 // Get plugin option.
2826 $option = 'ldap_tls';
2827 $admin_mode = ( is_array( $args ) && array_key_exists( 'multisite_admin', $args ) && $args['multisite_admin'] === true ) ? 'multisite admin' : 'single admin';
2828 $auth_settings_option = $this->get_plugin_option( $option, $admin_mode, 'allow override', 'print overlay' );
2829
2830 // Print option elements.
2831 ?><input type="checkbox" id="auth_settings_<?php echo $option; ?>" name="auth_settings[<?php echo $option; ?>]" value="1"<?php checked( 1 == $auth_settings_option ); ?> /><label for="auth_settings_<?php echo $option; ?>">Use TLS</label><?php
2832 } // END print_checkbox_ldap_tls
2833
2834 function print_text_ldap_lostpassword_url( $args = '' ) {
2835 // Get plugin option.
2836 $option = 'ldap_lostpassword_url';
2837 $admin_mode = ( is_array( $args ) && array_key_exists( 'multisite_admin', $args ) && $args['multisite_admin'] === true ) ? 'multisite admin' : 'single admin';
2838 $auth_settings_option = $this->get_plugin_option( $option, $admin_mode, 'allow override', 'print overlay' );
2839
2840 // Print option elements.
2841 ?><input type="text" id="auth_settings_<?php echo $option; ?>" name="auth_settings[<?php echo $option; ?>]" value="<?php echo $auth_settings_option; ?>" placeholder="https://myschool.example.edu:8888/am-forgot-password" style="width: 400px;" /><?php
2842 } // END print_text_ldap_lostpassword_url()
2843
2844
2845 function print_section_info_advanced( $args = '' ) {
2846 ?><div id="section_info_advanced" class="section_info">
2847 <p>You may optionally specify some advanced settings below.</p>
2848 </div><?php
2849 } // END print_section_info_advanced()
2850
2851 function print_text_auth_advanced_lockouts( $args = '' ) {
2852 // Get plugin option.
2853 $option = 'advanced_lockouts';
2854 $admin_mode = ( is_array( $args ) && array_key_exists( 'multisite_admin', $args ) && $args['multisite_admin'] === true ) ? 'multisite admin' : 'single admin';
2855 $auth_settings_option = $this->get_plugin_option( $option, $admin_mode, 'allow override', 'print overlay' );
2856
2857 // Print option elements.
2858 ?>After
2859 <input type="text" id="auth_settings_<?php echo $option; ?>_attempts_1" name="auth_settings[<?php echo $option; ?>][attempts_1]" value="<?php echo $auth_settings_option['attempts_1']; ?>" placeholder="10" style="width:30px;" />
2860 invalid password attempts, delay further attempts on that user for
2861 <input type="text" id="auth_settings_<?php echo $option; ?>_duration_1" name="auth_settings[<?php echo $option; ?>][duration_1]" value="<?php echo $auth_settings_option['duration_1']; ?>" placeholder="1" style="width:30px;" />
2862 minute(s).
2863 <br />
2864 After
2865 <input type="text" id="auth_settings_<?php echo $option; ?>_attempts_2" name="auth_settings[<?php echo $option; ?>][attempts_2]" value="<?php echo $auth_settings_option['attempts_2']; ?>" placeholder="10" style="width:30px;" />
2866 more invalid attempts, increase the delay to
2867 <input type="text" id="auth_settings_<?php echo $option; ?>_duration_2" name="auth_settings[<?php echo $option; ?>][duration_2]" value="<?php echo $auth_settings_option['duration_2']; ?>" placeholder="10" style="width:30px;" />
2868 minutes.
2869 <br />
2870 Reset the delays after
2871 <input type="text" id="auth_settings_<?php echo $option; ?>_reset_duration" name="auth_settings[<?php echo $option; ?>][reset_duration]" value="<?php echo $auth_settings_option['reset_duration']; ?>" placeholder="240" style="width:40px;" />
2872 minutes with no invalid attempts.<?php
2873 } // END print_text_auth_advanced_lockouts()
2874
2875 function print_checkbox_auth_advanced_hide_wp_login( $args = '' ) {
2876 // Get plugin option.
2877 $option = 'advanced_hide_wp_login';
2878 $admin_mode = ( is_array( $args ) && array_key_exists( 'multisite_admin', $args ) && $args['multisite_admin'] === true ) ? 'multisite admin' : 'single admin';
2879 $auth_settings_option = $this->get_plugin_option( $option, $admin_mode, 'allow override', 'print overlay' );
2880
2881 // Print option elements.
2882 ?><input type="checkbox" id="auth_settings_<?php echo $option; ?>" name="auth_settings[<?php echo $option; ?>]" value="1"<?php checked( 1 == $auth_settings_option ); ?> /><label for="auth_settings_<?php echo $option; ?>">Hide WordPress Logins</label>
2883 <p><small>Note: You can always access the WordPress logins by adding external=wordpress to the wp-login URL, like so:<br /><a href="<?php echo wp_login_url(); ?>?external=wordpress" target="_blank"><?php echo wp_login_url(); ?>?external=wordpress</a>.</p><?php
2884 } // END print_checkbox_auth_advanced_hide_wp_login()
2885
2886 function print_radio_auth_advanced_branding( $args = '' ) {
2887 // Get plugin option.
2888 $option = 'advanced_branding';
2889 $auth_settings_option = $this->get_plugin_option( $option );
2890
2891 // Print option elements.
2892 ?><input type="radio" id="radio_auth_settings_<?php echo $option; ?>_default" name="auth_settings[<?php echo $option; ?>]" value="default"<?php checked( 'default' == $auth_settings_option ); ?> /><label for="radio_auth_settings_<?php echo $option; ?>_default">Default WordPress login screen</label><br />
2893 <?php
2894
2895 /**
2896 * Developers can use the `authorizer_add_branding_option` filter
2897 * to add a radio button for "Custom WordPress login branding"
2898 * under the "Advanced" tab in Authorizer options. Example:
2899 *
2900 * function my_authorizer_add_branding_option( $branding_options ) {
2901 * $new_branding_option = array(
2902 * 'value' => 'your_brand'
2903 * 'description' => 'Custom Your Brand Login Screen',
2904 * 'css_url' => 'http://url/to/your_brand.css',
2905 * 'js_url' => 'http://url/to/your_brand.js',
2906 * );
2907 * array_push( $branding_options, $new_branding_option );
2908 * return $branding_options;
2909 * }
2910 * add_filter( 'authorizer_add_branding_option', 'my_authorizer_add_branding_option' );
2911 */
2912 $branding_options = array();
2913 $branding_options = apply_filters( 'authorizer_add_branding_option', $branding_options );
2914 foreach ( $branding_options as $branding_option ) {
2915 // Make sure the custom brands have the required values
2916 if ( ! ( is_array( $branding_option ) && array_key_exists( 'value', $branding_option ) && array_key_exists( 'description', $branding_option ) ) ) {
2917 continue;
2918 }
2919 ?><input type="radio" id="radio_auth_settings_<?php echo $option; ?>_<?php echo sanitize_title( $branding_option['value'] ); ?>" name="auth_settings[<?php echo $option; ?>]" value="<?php echo $branding_option['value']; ?>"<?php checked( $branding_option['value'] == $auth_settings_option ); ?> /><label for="radio_auth_settings_<?php echo $option; ?>_<?php echo sanitize_title( $branding_option['value'] ); ?>"><?php echo $branding_option['description']; ?></label><br /><?php
2920 }
2921
2922 // Print message about adding custom brands if there are none.
2923 if ( count( $branding_options ) === 0 ) {
2924 ?><p><em><strong>Note for theme developers</strong>: Add more options here by using the `authorizer_add_branding_option` filter in your theme. You can see an example theme that implements this filter in the plugin directory under sample-theme-add-branding.</em></p><?php
2925 }
2926 } // END print_radio_auth_advanced_branding()
2927
2928 function print_radio_auth_advanced_admin_menu( $args = '' ) {
2929 // Get plugin option.
2930 $option = 'advanced_admin_menu';
2931 $auth_settings_option = $this->get_plugin_option( $option );
2932
2933 // Print option elements.
2934 ?><input type="radio" id="radio_auth_settings_<?php echo $option; ?>_settings" name="auth_settings[<?php echo $option; ?>]" value="settings"<?php checked( 'settings' == $auth_settings_option ); ?> /><label for="radio_auth_settings_<?php echo $option; ?>_settings">Show in Settings menu</label><br />
2935 <input type="radio" id="radio_auth_settings_<?php echo $option; ?>_top" name="auth_settings[<?php echo $option; ?>]" value="top"<?php checked( 'top' == $auth_settings_option ); ?> /><label for="radio_auth_settings_<?php echo $option; ?>_top">Show in sidebar (top level)</label><br /><?php
2936
2937 } // END print_radio_auth_advanced_admin_menu()
2938
2939 function print_select_auth_advanced_usermeta( $args = '' ) {
2940 // Get plugin option.
2941 $option = 'advanced_usermeta';
2942 $auth_settings_option = $this->get_plugin_option( $option );
2943
2944 // Print option elements.
2945 ?><select id="auth_settings_<?php echo $option; ?>" name="auth_settings[<?php echo $option; ?>]">
2946 <option value="">-- None --</option>
2947 <?php foreach ( $this->get_all_usermeta_keys() as $meta_key ) : if ( substr( $meta_key, 0, 3 ) === 'wp_' ) continue; ?>
2948 <option value="<?php echo $meta_key; ?>" <?php if ( $auth_settings_option === $meta_key ) echo ' selected="selected"'; ?>><?php echo $meta_key; ?></option>
2949 <?php endforeach; ?>
2950 </select><?php
2951 } // END print_select_auth_advanced_usermeta()
2952
2953
2954
2955 /**
2956 * Add help documentation to the options page.
2957 * Run on action hook chain: load-settings_page_authorizer > admin_head
2958 */
2959 public function admin_head() {
2960 $screen = get_current_screen();
2961
2962 // Add help tab for Access Lists Settings
2963 $help_auth_settings_access_lists_content = '
2964 <p><strong>Pending Users</strong>: Pending users are users who have successfully logged in to the site, but who haven\'t yet been approved (or blocked) by you.</p>
2965 <p><strong>Approved Users</strong>: Approved users have access to the site once they successfully log in.</p>
2966 <p><strong>Blocked Users</strong>: Blocked users will receive an error message when they try to visit the site after authenticating.</p>
2967 <p>Users in the <strong>Pending</strong> list appear automatically after a new user tries to log in from the configured external authentication service. You can add users to the <strong>Approved</strong> or <strong>Blocked</strong> lists by typing them in manually, or by clicking the <em>Approve</em> or <em>Block</em> buttons next to a user in the <strong>Pending</strong> list.</p>
2968 ';
2969 $screen->add_help_tab(
2970 array(
2971 'id' => 'help_auth_settings_access_lists_content',
2972 'title' => 'Access Lists',
2973 'content' => $help_auth_settings_access_lists_content,
2974 )
2975 );
2976
2977 // Add help tab for Login Access Settings
2978 $help_auth_settings_access_login_content = '
2979 <p><strong>Who can log in to the site?</strong>: Choose the level of access restriction you\'d like to use on your site here. You can leave the site open to anyone with a WordPress account or an account on an external service like Google, CAS, or LDAP, or restrict it to WordPress users and only the external users that you specify via the <em>Access Lists</em>.</p>
2980 <p><strong>Which role should receive email notifications about pending users?</strong>: If you\'ve restricted access to <strong>approved users</strong>, you can determine which WordPress users will receive a notification email everytime a new external user successfully logs in and is added to the pending list. All users of the specified role will receive an email, and the external user will get a message (specified below) telling them their access is pending approval.</p>
2981 <p><strong>What message should pending users see after attempting to log in?</strong>: Here you can specify the exact message a new external user will see once they try to log in to the site for the first time.</p>
2982 ';
2983 $screen->add_help_tab(
2984 array(
2985 'id' => 'help_auth_settings_access_login_content',
2986 'title' => 'Login Access',
2987 'content' => $help_auth_settings_access_login_content,
2988 )
2989 );
2990
2991 // Add help tab for Public Access Settings
2992 $help_auth_settings_access_public_content = '
2993 <p><strong>Who can view the site?</strong>: You can restrict the site\'s visibility by only allowing logged in users to see pages. If you do so, you can customize the specifics about the site\'s privacy using the settings below.</p>
2994 <p><strong>What pages (if any) should be available to everyone?</strong>: If you\'d like to declare certain pages on your site as always public (such as the course syllabus, introduction, or calendar), specify those pages here. These pages will always be available no matter what access restrictions exist.</p>
2995 <p><strong>What happens to people without access when they visit a <em>private</em> page?</strong>: Choose the response anonymous users receive when visiting the site. You can choose between immediately taking them to the <strong>login screen</strong>, or simply showing them a <strong>message</strong>.</p>
2996 <p><strong>What happens to people without access when they visit a <em>public</em> page?</strong>: Choose the response anonymous users receive when visiting a page on the site marked as public. You can choose between showing them the page without any message, or showing them a the page with a message above the content.</p>
2997 <p><strong>What message should people without access see?</strong>: If you chose to show new users a <strong>message</strong> above, type that message here.</p>
2998 ';
2999 $screen->add_help_tab(
3000 array(
3001 'id' => 'help_auth_settings_access_public_content',
3002 'title' => 'Public Access',
3003 'content' => $help_auth_settings_access_public_content,
3004 )
3005 );
3006
3007 // Add help tab for External Service (CAS, LDAP) Settings
3008 $help_auth_settings_external_content = '
3009 <p><strong>Type of external service to authenticate against</strong>: Choose which authentication service type you will be using. You\'ll have to fill out different fields below depending on which service you choose.</p>
3010 <p><strong>Enable Google Logins</strong>: Choose if you want to allow users to log in with their Google Account credentials. You will need to enter your API Client ID and Secret to enable Google Logins.</p>
3011 <p><strong>Enable CAS Logins</strong>: Choose if you want to allow users to log in with via CAS (Central Authentication Service). You will need to enter details about your CAS server (host, port, and path) to enable CAS Logins.</p>
3012 <p><strong>Enable LDAP Logins</strong>: Choose if you want to allow users to log in with their LDAP (Lightweight Directory Access Protocol) credentials. You will need to enter details about your LDAP server (host, port, search base, uid attribute, directory user, directory user password, and whether to use TLS) to enable Google Logins.</p>
3013 <p><strong>Default role for new CAS users</strong>: Specify which role new external users will get by default. Be sure to choose a role with limited permissions!</p>
3014 <p><strong><em>If you enable Google logins:</em></strong></p>
3015 <ul>
3016 <li><strong>Google Client ID</strong>: You can generate this ID by creating a new Project in the <a href="https://cloud.google.com/console">Google Developers Console</a>. A Client ID typically looks something like this: 1234567890123-kdjr85yt6vjr6d8g7dhr8g7d6durjf7g.apps.googleusercontent.com</li>
3017 <li><strong>Google Client Secret</strong>: You can generate this secret by creating a new Project in the <a href="https://cloud.google.com/console">Google Developers Console</a>. A Client Secret typically looks something like this: sDNgX5_pr_5bly-frKmvp8jT</li>
3018 </ul>
3019 <p><strong><em>If you enable CAS logins:</em></strong></p>
3020 <ul>
3021 <li><strong>CAS server hostname</strong>: Enter the hostname of the CAS server you authenticate against (e.g., authn.example.edu).</li>
3022 <li><strong>CAS server port</strong>: Enter the port on the CAS server to connect to (e.g., 443).</li>
3023 <li><strong>CAS server path/context</strong>: Enter the path to the login endpoint on the CAS server (e.g., /cas).</li>
3024 </ul>
3025 <p><strong><em>If you enable LDAP logins:</em></strong></p>
3026 <ul>
3027 <li><strong>LDAP Host</strong>: Enter the URL of the LDAP server you authenticate against.</li>
3028 <li><strong>LDAP Port</strong>: Enter the port number that the LDAP server listens on.</li>
3029 <li><strong>LDAP Search Base</strong>: Enter the LDAP string that represents the search base, e.g., ou=people,dc=example,dc=edu</li>
3030 <li><strong>LDAP attribute containing username</strong>: Enter the name of the LDAP attribute that contains the usernames used by those attempting to log in. The plugin will search on this attribute to find the cn to bind against for login attempts.</li>
3031 <li><strong>LDAP Directory User</strong>: Enter the name of the LDAP user that has permissions to browse the directory.</li>
3032 <li><strong>LDAP Directory User Password</strong>: Enter the password for the LDAP user that has permission to browse the directory.</li>
3033 <li><strong>Secure Connection (TLS)</strong>: Select whether all communication with the LDAP server should be performed over a TLS-secured connection.</li>
3034 </ul>';
3035 $screen->add_help_tab(
3036 array(
3037 'id' => 'help_auth_settings_external_content',
3038 'title' => 'External Service',
3039 'content' => $help_auth_settings_external_content,
3040 )
3041 );
3042
3043 // Add help tab for Advanced Settings
3044 $help_auth_settings_advanced_content = '
3045 <p><strong>Limit invalid login attempts</strong>: Choose how soon (and for how long) to restrict access to individuals (or bots) making repeated invalid login attempts. You may set a shorter delay first, and then a longer delay after repeated invalid attempts; you may also set how much time must pass before the delays will be reset to normal.</p>
3046 <p><strong>Custom lost password URL</strong>: The WordPress login page contains a link to recover a lost password. If you have external users who shouldn\'t change the password on their WordPress account, point them to the appropriate location to change the password on their external authentication service here.</p>
3047 <p><strong>Hide WordPress Logins</strong>: If you want to hide the WordPress username and password fields and the Log In button on the wp-login screen, enable this option. Note: You can always access the WordPress logins by adding external=wordpress to the wp-login URL, like so: <a href="' . wp_login_url() . '?external=wordpress" target="_blank">' . wp_login_url() . '?external=wordpress</a>.</p>
3048 <p><strong>Custom WordPress login branding</strong>: If you\'d like to use custom branding on the WordPress login page, select that here. You will need to use the `authorizer_add_branding_option` filter in your theme to add it. You can see an example theme that implements this filter in the plugin directory under sample-theme-add-branding.</p>
3049 ';
3050 $screen->add_help_tab(
3051 array(
3052 'id' => 'help_auth_settings_advanced_content',
3053 'title' => 'Advanced',
3054 'content' => $help_auth_settings_advanced_content,
3055 )
3056 );
3057 } // END admin_head()
3058
3059
3060
3061 /**
3062 * ***************************
3063 * Multisite: Network Admin Options page
3064 * ***************************
3065 */
3066
3067
3068 /**
3069 * Network Admin menu item
3070 * Hook: network_admin_menu
3071 *
3072 * @param none
3073 * @return void
3074 */
3075 public function network_admin_menu() {
3076 // @see http://codex.wordpress.org/Function_Reference/add_menu_page
3077 add_menu_page(
3078 'Authorizer', // Page title
3079 'Authorizer', // Menu title
3080 'manage_network_options', // Capability
3081 'authorizer', // Menu slug
3082 array( $this, 'create_network_admin_page' ),
3083 'dashicons-groups', // Icon URL
3084 89 // Position
3085 );
3086 } // END network_admin_menu()
3087
3088 /**
3089 * Output the HTML for the options page
3090 */
3091 public function create_network_admin_page() {
3092 if ( ! current_user_can( 'manage_network_options' ) ) {
3093 wp_die( __( 'You do not have sufficient permissions to access this page.' ) );
3094 }
3095 $auth_settings = get_blog_option( BLOG_ID_CURRENT_SITE, 'auth_multisite_settings', array() ); ?>
3096 <div class="wrap">
3097 <form method="post" action="" autocomplete="off">
3098 <h2>Authorizer Settings</h2>
3099 <p>Most <strong>Authorizer</strong> settings are set in the individual sites, but you can specify a few options here that apply to <strong>all sites in the network</strong>. These settings will override settings in the individual sites.</p>
3100
3101 <input type="checkbox" id="auth_settings_multisite_override" name="auth_settings[multisite_override]" value="1"<?php checked( 1 == $auth_settings['multisite_override'] ); ?> /><label for="auth_settings_multisite_override">Override individual site settings with the settings below</label>
3102
3103 <div id="auth_multisite_settings_disabled_overlay" style="display: none;"></div>
3104
3105 <div class="wrap" id="auth_multisite_settings">
3106 <?php $this->print_section_info_tabs( array( 'multisite_admin' => true ) ); ?>
3107
3108 <?php wp_nonce_field( 'save_auth_settings', 'nonce_save_auth_settings' ); ?>
3109
3110 <?php // Custom access lists (for network, we only really want approved list, not pending or blocked) ?>
3111 <div id="section_info_access_lists" class="section_info">
3112 <p>Manage who has access to all sites in the network.</p>
3113 </div>
3114 <table class="form-table"><tbody>
3115 <tr>
3116 <th scope="row">Who can log in to sites in this network?</th>
3117 <td><?php $this->print_radio_auth_access_who_can_login( array( 'multisite_admin' => true ) ); ?></td>
3118 </tr>
3119 <tr>
3120 <th scope="row">Who can view sites in this network?</th>
3121 <td><?php $this->print_radio_auth_access_who_can_view( array( 'multisite_admin' => true ) ); ?></td>
3122 </tr>
3123 <tr>
3124 <th scope="row">Approved Users (All Sites)<br /><small><em>Note: these users will <strong>not</strong> receive welcome emails when approved. Only users approved from individual sites can receive these messages.</em></small></th>
3125 <td><?php $this->print_combo_auth_access_users_approved( array( 'multisite_admin' => true ) ); ?></td>
3126 </tr>
3127 </tbody></table>
3128
3129 <?php $this->print_section_info_external(); ?>
3130 <table class="form-table"><tbody>
3131 <tr>
3132 <th scope="row">Default role for new users</th>
3133 <td><?php $this->print_select_auth_access_default_role( array( 'multisite_admin' => true ) ); ?></td>
3134 </tr>
3135 <tr>
3136 <th scope="row">Google Logins</th>
3137 <td><?php $this->print_checkbox_auth_external_google( array( 'multisite_admin' => true ) ); ?></td>
3138 </tr>
3139 <tr>
3140 <th scope="row">Google Client ID</th>
3141 <td><?php $this->print_text_google_clientid( array( 'multisite_admin' => true ) ); ?></td>
3142 </tr>
3143 <tr>
3144 <th scope="row">Google Client Secret</th>
3145 <td><?php $this->print_text_google_clientsecret( array( 'multisite_admin' => true ) ); ?></td>
3146 </tr>
3147 <tr>
3148 <th scope="row">CAS Logins</th>
3149 <td><?php $this->print_checkbox_auth_external_cas( array( 'multisite_admin' => true ) ); ?></td>
3150 </tr>
3151 <tr>
3152 <th scope="row">CAS Custom Label</th>
3153 <td><?php $this->print_text_cas_custom_label( array( 'multisite_admin' => true ) ); ?></td>
3154 </tr>
3155 <tr>
3156 <th scope="row">CAS server hostname</th>
3157 <td><?php $this->print_text_cas_host( array( 'multisite_admin' => true ) ); ?></td>
3158 </tr>
3159 <tr>
3160 <th scope="row">CAS server port</th>
3161 <td><?php $this->print_text_cas_port( array( 'multisite_admin' => true ) ); ?></td>
3162 </tr>
3163 <tr>
3164 <th scope="row">CAS server path/context</th>
3165 <td><?php $this->print_text_cas_path( array( 'multisite_admin' => true ) ); ?></td>
3166 </tr>
3167 <tr>
3168 <th scope="row">LDAP Logins</th>
3169 <td><?php $this->print_checkbox_auth_external_ldap( array( 'multisite_admin' => true ) ); ?></td>
3170 </tr>
3171 <tr>
3172 <th scope="row">LDAP Host</th>
3173 <td><?php $this->print_text_ldap_host( array( 'multisite_admin' => true ) ); ?></td>
3174 </tr>
3175 <tr>
3176 <th scope="row">LDAP Port</th>
3177 <td><?php $this->print_text_ldap_port( array( 'multisite_admin' => true ) ); ?></td>
3178 </tr>
3179 <tr>
3180 <th scope="row">LDAP Search Base</th>
3181 <td><?php $this->print_text_ldap_search_base( array( 'multisite_admin' => true ) ); ?></td>
3182 </tr>
3183 <tr>
3184 <th scope="row">LDAP attribute containing username</th>
3185 <td><?php $this->print_text_ldap_uid( array( 'multisite_admin' => true ) ); ?></td>
3186 </tr>
3187 <tr>
3188 <th scope="row">LDAP Directory User</th>
3189 <td><?php $this->print_text_ldap_user( array( 'multisite_admin' => true ) ); ?></td>
3190 </tr>
3191 <tr>
3192 <th scope="row">LDAP Directory User Password</th>
3193 <td><?php $this->print_password_ldap_password( array( 'multisite_admin' => true ) ); ?></td>
3194 </tr>
3195 <tr>
3196 <th scope="row">Secure Connection (TLS)</th>
3197 <td><?php $this->print_checkbox_ldap_tls( array( 'multisite_admin' => true ) ); ?></td>
3198 </tr>
3199 <tr>
3200 <th scope="row">Custom lost password URL</th>
3201 <td><?php $this->print_text_ldap_lostpassword_url( array( 'multisite_admin' => true ) ); ?></td>
3202 </tr>
3203 </tbody></table>
3204
3205 <?php $this->print_section_info_advanced(); ?>
3206 <table class="form-table"><tbody>
3207 <tr>
3208 <th scope="row">Limit invalid login attempts</th>
3209 <td><?php $this->print_text_auth_advanced_lockouts( array( 'multisite_admin' => true ) ); ?></td>
3210 </tr>
3211 <tr>
3212 <th scope="row">Hide WordPress Logins</th>
3213 <td><?php $this->print_checkbox_auth_advanced_hide_wp_login( array( 'multisite_admin' => true ) ); ?></td>
3214 </tr>
3215 </tbody></table>
3216
3217 <br class="clear" />
3218 </div>
3219 <input type="button" name="submit" id="submit" class="button button-primary" value="Save Changes" onclick="save_auth_multisite_settings(this);" />
3220 </form>
3221 </div>
3222 <?php
3223 } // END create_network_admin_page()
3224
3225 /**
3226 * Save multisite settings (ajax call).
3227 */
3228 function ajax_save_auth_multisite_settings() {
3229 // Fail silently if current user doesn't have permissions.
3230 if ( ! current_user_can( 'manage_network_options' ) ) {
3231 die( '' );
3232 }
3233
3234 // Make sure nonce exists.
3235 if ( empty( $_POST['nonce_save_auth_settings'] ) ) {
3236 die( '' );
3237 }
3238
3239 // Nonce check.
3240 if ( ! wp_verify_nonce( $_POST['nonce_save_auth_settings'], 'save_auth_settings' ) ) {
3241 die( '' );
3242 }
3243
3244 // Assert multisite.
3245 if ( ! is_multisite() ) {
3246 die( '' );
3247 }
3248
3249 // Get multisite settings.
3250 $auth_multisite_settings = get_blog_option( BLOG_ID_CURRENT_SITE, 'auth_multisite_settings', array() );
3251
3252 // Sanitize settings
3253 $auth_multisite_settings = $this->sanitize_options( $_POST, 'multisite' );
3254
3255 // Filter options to only the allowed values (multisite options are a subset of all options)
3256 $allowed = array(
3257 'multisite_override',
3258 'access_who_can_login',
3259 'access_who_can_view',
3260 'access_default_role',
3261 'google',
3262 'google_clientid',
3263 'google_clientsecret',
3264 'cas',
3265 'cas_custom_label',
3266 'cas_host',
3267 'cas_port',
3268 'cas_path',
3269 'ldap',
3270 'ldap_host',
3271 'ldap_port',
3272 'ldap_search_base',
3273 'ldap_uid',
3274 'ldap_user',
3275 'ldap_password',
3276 'ldap_tls',
3277 'ldap_lostpassword_url',
3278 'advanced_lockouts',
3279 'advanced_hide_wp_login',
3280 );
3281 $auth_multisite_settings = array_intersect_key( $auth_multisite_settings, array_flip( $allowed ) );
3282
3283 // Update multisite settings in database.
3284 update_blog_option( BLOG_ID_CURRENT_SITE, 'auth_multisite_settings', $auth_multisite_settings );
3285
3286 // Return 'success' value to AJAX call.
3287 die( 'success' );
3288 } // END ajax_save_auth_multisite_settings()
3289
3290
3291
3292 /**
3293 * ***************************
3294 * Dashboard widget
3295 * ***************************
3296 */
3297
3298
3299
3300 function add_dashboard_widgets() {
3301 // Only users who can edit can see the authorizer dashboard widget
3302 if ( current_user_can( 'create_users' ) ) {
3303 // Add dashboard widget for adding/editing users with access
3304 wp_add_dashboard_widget( 'auth_dashboard_widget', 'Authorizer Settings', array( $this, 'add_auth_dashboard_widget' ) );
3305 }
3306 } // END add_dashboard_widgets()
3307
3308
3309 function add_auth_dashboard_widget() {
3310 ?><form method="post" id="auth_settings_access_form" action="">
3311 <?php $this->print_section_info_access_login(); ?>
3312 <div>
3313 <h2>Pending Users</h2>
3314 <?php $this->print_combo_auth_access_users_pending(); ?>
3315 </div>
3316 <div>
3317 <h2>Approved Users</h2>
3318 <?php $this->print_combo_auth_access_users_approved(); ?>
3319 </div>
3320 <div>
3321 <h2>Blocked Users</h2>
3322 <?php $this->print_combo_auth_access_users_blocked(); ?>
3323 </div>
3324 <br class="clear" />
3325 </form><?php
3326 } // END add_auth_dashboard_widget()
3327
3328
3329 function ajax_update_auth_usermeta() {
3330
3331 // Fail silently if current user doesn't have permissions.
3332 if ( ! current_user_can( 'create_users' ) ) {
3333 die( '' );
3334 }
3335
3336 // Nonce check.
3337 if ( empty( $_POST['nonce_save_auth_settings'] ) || ! wp_verify_nonce( $_POST['nonce_save_auth_settings'], 'save_auth_settings' ) ) {
3338 die( '' );
3339 }
3340
3341 // Fail if required post data doesn't exist.
3342 if ( ! array_key_exists( 'email', $_REQUEST ) || ! array_key_exists( 'usermeta', $_REQUEST ) ) {
3343 die( '' );
3344 }
3345
3346 // Fail if user doesn't exist.
3347 if ( ! ( $wp_user = get_user_by( 'email', $_REQUEST['email'] ) ) ) {
3348 die( '' );
3349 }
3350
3351 // Update user's usermeta value for usermeta key stored in authorizer options.
3352 $meta_key = $this->get_plugin_option( 'advanced_usermeta' );
3353 $meta_value = $_REQUEST['usermeta'];
3354 if ( ! update_user_meta( $wp_user->ID, $meta_key, $meta_value ) ) {
3355 die( '' );
3356 }
3357
3358 // Return 'success' value to AJAX call.
3359 die( 'success' );
3360 }
3361
3362
3363 function ajax_update_auth_user() {
3364
3365 // Fail silently if current user doesn't have permissions.
3366 if ( ! current_user_can( 'create_users' ) ) {
3367 die( '' );
3368 }
3369
3370 // Nonce check.
3371 if ( empty( $_POST['nonce_save_auth_settings'] ) || ! wp_verify_nonce( $_POST['nonce_save_auth_settings'], 'save_auth_settings' ) ) {
3372 die( '' );
3373 }
3374
3375 // Fail if requesting a change to an invalid setting.
3376 if ( ! in_array( $_POST['setting'], array( 'access_users_pending', 'access_users_approved', 'access_users_blocked' ) ) ) {
3377 die( '' );
3378 }
3379
3380 // Editing a pending list entry.
3381 if ( $_POST['setting'] === 'access_users_pending' ) {
3382 // Initialize posted data if empty.
3383 if ( ! ( array_key_exists( 'access_users_pending', $_POST ) && is_array( $_POST['access_users_pending'] ) ) ) {
3384 $_POST['access_users_pending'] = array();
3385 }
3386
3387 // Deal with each modified user (add or remove).
3388 foreach ( $_POST['access_users_pending'] as $pending_user ) {
3389
3390 if ( $pending_user['edit_action'] === 'add' ) {
3391
3392 // Add new user to pending list and save (skip if it's
3393 // already there--someone else might have just done it).
3394 if ( ! $this->is_email_in_list( $pending_user['email'], 'pending' ) ) {
3395 $auth_settings_access_users_pending = $this->sanitize_user_list(
3396 $this->get_plugin_option( 'access_users_pending', 'single admin' )
3397 );
3398 array_push( $auth_settings_access_users_pending, $pending_user );
3399 update_option( 'auth_settings_access_users_pending', $auth_settings_access_users_pending );
3400 }
3401
3402 } elseif ( $pending_user['edit_action'] === 'remove' ) {
3403
3404 // Remove user from pending list and save
3405 if ( $this->is_email_in_list( $pending_user['email'], 'pending' ) ) {
3406 $auth_settings_access_users_pending = $this->sanitize_user_list(
3407 $this->get_plugin_option( 'access_users_pending', 'single admin' )
3408 );
3409 foreach ( $auth_settings_access_users_pending as $key => $existing_user ) {
3410 if ( $pending_user['email'] == $existing_user['email'] ) {
3411 unset( $auth_settings_access_users_pending[$key] );
3412 break;
3413 }
3414 }
3415 update_option( 'auth_settings_access_users_pending', $auth_settings_access_users_pending );
3416 }
3417
3418 }
3419 }
3420 }
3421
3422 // Editing an approved list entry.
3423 if ( $_POST['setting'] === 'access_users_approved' ) {
3424 // Initialize posted data if empty.
3425 if ( ! ( array_key_exists( 'access_users_approved', $_POST ) && is_array( $_POST['access_users_approved'] ) ) ) {
3426 $_POST['access_users_approved'] = array();
3427 }
3428
3429 // Deal with each modified user (add, remove, or change_role).
3430 foreach ( $_POST['access_users_approved'] as $approved_user ) {
3431 if ( $approved_user['edit_action'] === 'add' ) {
3432
3433 // New user (create user, or add existing user to current site in multisite).
3434 $new_user = get_user_by( 'email', $approved_user['email'] );
3435 if ( $new_user !== false ) {
3436 if ( is_multisite() ) {
3437 add_user_to_blog( get_current_blog_id(), $new_user->ID, $approved_user['role'] );
3438 }
3439 } elseif ( $approved_user['local_user'] === 'true' ) {
3440 // Create a WP account for this new *local* user and email the password.
3441 $plaintext_password = wp_generate_password(); // random password
3442 // If there's already a user with this username (e.g.,
3443 // johndoe/johndoe@gmail.com exists, and we're trying to add
3444 // johndoe/johndoe@example.com), use the full email address
3445 // as the username.
3446 $username = explode( "@", $approved_user['email'] );
3447 $username = $username[0];
3448 if ( get_user_by( 'login', $username ) !== false ) {
3449 $username = $approved_user['email'];
3450 }
3451 if ( $approved_user['multisite_user'] !== 'false' ) {
3452 $result = wpmu_create_user(
3453 strtolower( $username ),
3454 $plaintext_password,
3455 strtolower( $approved_user['email'] )
3456 );
3457 } else {
3458 $result = wp_insert_user(
3459 array(
3460 'user_login' => strtolower( $username ),
3461 'user_pass' => $plaintext_password,
3462 'first_name' => '',
3463 'last_name' => '',
3464 'user_email' => strtolower( $approved_user['email'] ),
3465 'user_registered' => date( 'Y-m-d H:i:s' ),
3466 'role' => $approved_user['role'],
3467 )
3468 );
3469 }
3470 if ( ! is_wp_error( $result ) ) {
3471 // Email password to new user
3472 wp_new_user_notification( $result, $plaintext_password );
3473 }
3474
3475 }
3476
3477 // Email new user welcome message if plugin option is set.
3478 $this->maybe_email_welcome_message( $approved_user['email'] );
3479
3480 // Add new user to approved list and save (skip if it's
3481 // already there--someone else might have just done it).
3482 if ( $approved_user['multisite_user'] !== 'false' ) {
3483 if ( ! $this->is_email_in_list( $approved_user['email'], 'approved', 'multisite' ) ) {
3484 $auth_multisite_settings_access_users_approved = $this->sanitize_user_list(
3485 $this->get_plugin_option( 'access_users_approved', 'multisite admin' )
3486 );
3487 $approved_user['date_added'] = date( 'M Y' );
3488 array_push( $auth_multisite_settings_access_users_approved, $approved_user );
3489 update_blog_option( BLOG_ID_CURRENT_SITE, 'auth_multisite_settings_access_users_approved', $auth_multisite_settings_access_users_approved );
3490 }
3491 } else {
3492 if ( ! $this->is_email_in_list( $approved_user['email'], 'approved' ) ) {
3493 $auth_settings_access_users_approved = $this->sanitize_user_list(
3494 $this->get_plugin_option( 'access_users_approved', 'single admin' )
3495 );
3496 $approved_user['date_added'] = date( 'M Y' );
3497 array_push( $auth_settings_access_users_approved, $approved_user );
3498 update_option( 'auth_settings_access_users_approved', $auth_settings_access_users_approved );
3499 }
3500 }
3501
3502 // If we've added a new multisite user, go through all pending/approved/blocked lists
3503 // on individual sites and remove this user from them (to prevent duplicate entries).
3504 if ( $approved_user['multisite_user'] !== 'false' && is_multisite() ) {
3505 $list_names = array( 'access_users_pending', 'access_users_approved', 'access_users_blocked' );
3506 foreach ( wp_get_sites( array( 'limit' => 999999 ) ) as $site ) {
3507 foreach ( $list_names as $list_name ) {
3508 $user_list = get_blog_option( $site['blog_id'], 'auth_settings_' . $list_name, array() );
3509 $list_changed = false;
3510 foreach ( $user_list as $key => $user ) {
3511 if ( $user['email'] == $approved_user['email'] ) {
3512 unset( $user_list[$key] );
3513 $list_changed = true;
3514 }
3515 }
3516 if ( $list_changed ) {
3517 update_blog_option( $site['blog_id'], 'auth_settings_' . $list_name, $user_list );
3518 }
3519 }
3520 }
3521 }
3522
3523 } elseif ( $approved_user['edit_action'] === 'remove' ) {
3524
3525 // Remove user from approved list and save
3526 if ( $approved_user['multisite_user'] !== 'false' ) {
3527 if ( $this->is_email_in_list( $approved_user['email'], 'approved', 'multisite' ) ) {
3528 $auth_multisite_settings_access_users_approved = $this->sanitize_user_list(
3529 $this->get_plugin_option( 'access_users_approved', 'multisite admin' )
3530 );
3531 foreach ( $auth_multisite_settings_access_users_approved as $key => $existing_user ) {
3532 if ( $approved_user['email'] == $existing_user['email'] ) {
3533 unset( $auth_multisite_settings_access_users_approved[$key] );
3534 break;
3535 }
3536 }
3537 update_blog_option( BLOG_ID_CURRENT_SITE, 'auth_multisite_settings_access_users_approved', $auth_multisite_settings_access_users_approved );
3538 }
3539 } else {
3540 if ( $this->is_email_in_list( $approved_user['email'], 'approved' ) ) {
3541 $auth_settings_access_users_approved = $this->sanitize_user_list(
3542 $this->get_plugin_option( 'access_users_approved', 'single admin' )
3543 );
3544 foreach ( $auth_settings_access_users_approved as $key => $existing_user ) {
3545 if ( $approved_user['email'] == $existing_user['email'] ) {
3546 unset( $auth_settings_access_users_approved[$key] );
3547 break;
3548 }
3549 }
3550 update_option( 'auth_settings_access_users_approved', $auth_settings_access_users_approved );
3551 }
3552 }
3553
3554 } elseif ( $approved_user['edit_action'] === 'change_role' ) {
3555
3556 // Update user's role in WordPress
3557 $changed_user = get_user_by( 'email', $approved_user['email'] );
3558 if ( $changed_user ) {
3559 if ( is_multisite() && $approved_user['multisite_user'] !== 'false' ) {
3560 foreach ( get_blogs_of_user( $changed_user->ID ) as $blog ) {
3561 add_user_to_blog( $blog->userblog_id, $changed_user->ID, $approved_user['role'] );
3562 }
3563 } else {
3564 $changed_user->set_role( $approved_user['role'] );
3565 }
3566 }
3567
3568 if ( $approved_user['multisite_user'] !== 'false' ) {
3569 if ( $this->is_email_in_list( $approved_user['email'], 'approved', 'multisite' ) ) {
3570 $auth_multisite_settings_access_users_approved = $this->sanitize_user_list(
3571 $this->get_plugin_option( 'access_users_approved', 'multisite admin' )
3572 );
3573 foreach ( $auth_multisite_settings_access_users_approved as $key => $existing_user ) {
3574 if ( $approved_user['email'] == $existing_user['email'] ) {
3575 $auth_multisite_settings_access_users_approved[$key]['role'] = $approved_user['role'];
3576 break;
3577 }
3578 }
3579 update_blog_option( BLOG_ID_CURRENT_SITE, 'auth_multisite_settings_access_users_approved', $auth_multisite_settings_access_users_approved );
3580 }
3581 } else {
3582 // Update user's role in approved list and save.
3583 if ( $this->is_email_in_list( $approved_user['email'], 'approved' ) ) {
3584 $auth_settings_access_users_approved = $this->sanitize_user_list(
3585 $this->get_plugin_option( 'access_users_approved', 'single admin' )
3586 );
3587 foreach ( $auth_settings_access_users_approved as $key => $existing_user ) {
3588 if ( $approved_user['email'] == $existing_user['email'] ) {
3589 $auth_settings_access_users_approved[$key]['role'] = $approved_user['role'];
3590 break;
3591 }
3592 }
3593 update_option( 'auth_settings_access_users_approved', $auth_settings_access_users_approved );
3594 }
3595 }
3596
3597 }
3598 }
3599 }
3600
3601 // Editing a blocked list entry.
3602 if ( $_POST['setting'] === 'access_users_blocked' ) {
3603 // Initialize posted data if empty.
3604 if ( ! ( array_key_exists( 'access_users_blocked', $_POST ) && is_array( $_POST['access_users_blocked'] ) ) ) {
3605 $_POST['access_users_blocked'] = array();
3606 }
3607
3608 // Deal with each modified user (add or remove).
3609 foreach ( $_POST['access_users_blocked'] as $blocked_user ) {
3610
3611 if ( $blocked_user['edit_action'] === 'add' ) {
3612
3613 // Add new user to blocked list and save (skip if it's
3614 // already there--someone else might have just done it).
3615 if ( ! $this->is_email_in_list( $blocked_user['email'], 'blocked' ) ) {
3616 $auth_settings_access_users_blocked = $this->sanitize_user_list(
3617 $this->get_plugin_option( 'access_users_blocked', 'single admin' )
3618 );
3619 $blocked_user['date_added'] = date( 'M Y' );
3620 array_push( $auth_settings_access_users_blocked, $blocked_user );
3621 update_option( 'auth_settings_access_users_blocked', $auth_settings_access_users_blocked );
3622 }
3623
3624 } elseif ( $blocked_user['edit_action'] === 'remove' ) {
3625
3626 // Remove auth_blocked usermeta for the user.
3627 $unblocked_user = get_user_by( 'email', $blocked_user['email'] );
3628 if ( $unblocked_user !== false ) {
3629 delete_user_meta( $unblocked_user->ID, 'auth_blocked', 'yes' );
3630 }
3631
3632 // Remove user from blocked list and save
3633 if ( $this->is_email_in_list( $blocked_user['email'], 'blocked' ) ) {
3634 $auth_settings_access_users_blocked = $this->sanitize_user_list(
3635 $this->get_plugin_option( 'access_users_blocked', 'single admin' )
3636 );
3637 foreach ( $auth_settings_access_users_blocked as $key => $existing_user ) {
3638 if ( $blocked_user['email'] == $existing_user['email'] ) {
3639 unset( $auth_settings_access_users_blocked[$key] );
3640 break;
3641 }
3642 }
3643 update_option( 'auth_settings_access_users_blocked', $auth_settings_access_users_blocked );
3644 }
3645
3646 }
3647 }
3648 }
3649
3650 // Return 'success' value to AJAX call.
3651 die( 'success' );
3652 } // END update_auth_user()
3653
3654
3655
3656 /**
3657 * ***************************
3658 * Helper functions
3659 * ***************************
3660 */
3661
3662
3663 /**
3664 * Retrieves a specific plugin option from db. Multisite enabled.
3665 *
3666 * @param string $option Option name
3667 * @param string $admin_mode 'multisite admin' will retrieve the multisite value
3668 * @param string $override_mode 'allow override' will retrieve the multisite value if it exists
3669 * @param string $print_mode 'print overlay' will output overlay that hides this option on the settings page
3670 * @return mixed Option value, or null on failure
3671 */
3672 private function get_plugin_option( $option, $admin_mode = 'single admin', $override_mode = 'no override', $print_mode = 'no overlay' ) {
3673
3674 // Special case for user lists (they are saved seperately to prevent concurrency issues).
3675 if ( in_array( $option, array( 'access_users_pending', 'access_users_approved', 'access_users_blocked' ) ) ) {
3676 $list = $admin_mode === 'multisite admin' ? array() : get_option( 'auth_settings_' . $option );
3677 if ( is_multisite() && $admin_mode === 'multisite admin' ) {
3678 $list = get_blog_option( BLOG_ID_CURRENT_SITE, 'auth_multisite_settings_' . $option, array() );
3679 }
3680 return $list;
3681 }
3682
3683 // Get all plugin options.
3684 $auth_settings = $this->get_plugin_options( $admin_mode, $override_mode );
3685
3686 // Set option to null if it wasn't found.
3687 if ( ! array_key_exists( $option, $auth_settings ) ) {
3688 return null;
3689 }
3690
3691 // If the requested and appropriate, print the overlay hiding the
3692 // single site option that is overridden by a multisite option.
3693 if (
3694 $admin_mode !== 'multisite admin' &&
3695 $override_mode === 'allow override' &&
3696 $print_mode === 'print overlay' &&
3697 array_key_exists( 'multisite_override', $auth_settings ) &&
3698 $auth_settings['multisite_override'] === '1'
3699 ) {
3700 // Get original plugin options (not overridden value). We'll
3701 // show this old value behind the disabled overlay.
3702 $auth_settings = $this->get_plugin_options( $admin_mode, 'no override' );
3703
3704 $name = "auth_settings[$option]";
3705 $id = "auth_settings_$option"; ?>
3706 <div id="overlay-hide-auth_settings_<?php echo $option; ?>" class="auth_multisite_override_overlay">
3707 <span class="overlay-note">
3708 This setting is overridden by a <a href="<?php echo network_admin_url( 'admin.php?page=authorizer&tab=external' ); ?>">multisite option</a>.
3709 </span>
3710 </div>
3711 <?php
3712 }
3713
3714 return $auth_settings[$option];
3715 }
3716
3717 /**
3718 * Retrieves all plugin options from db. Multisite enabled.
3719 *
3720 * @param string $admin_mode 'multisite admin' will retrieve the multisite value
3721 * @param string $override_mode 'allow override' will retrieve the multisite value if it exists
3722 * @return mixed Option value, or null on failure
3723 */
3724 private function get_plugin_options( $admin_mode = 'single admin', $override_mode = 'no override' ) {
3725 // Grab plugin settings (skip if in multisite admin mode).
3726 $auth_settings = $admin_mode === 'multisite admin' ? array() : get_option( 'auth_settings' );
3727
3728 // Initialize to empty array if the plugin option doesn't exist.
3729 if ( $auth_settings === FALSE ) {
3730 $auth_settings = array();
3731 }
3732
3733 // Merge multisite options if we're in a network.
3734 if ( is_multisite() ) {
3735 // Get multisite options.
3736 $auth_multisite_settings = get_blog_option( BLOG_ID_CURRENT_SITE, 'auth_multisite_settings', array() );
3737
3738 // Return the multisite options if we're viewing the network admin options page.
3739 // Otherwise override options with their multisite equivalents.
3740 if ( $admin_mode === 'multisite admin' ) {
3741 $auth_settings = $auth_multisite_settings;
3742 } elseif (
3743 $override_mode === 'allow override' &&
3744 array_key_exists( 'multisite_override', $auth_multisite_settings ) &&
3745 $auth_multisite_settings['multisite_override'] === '1'
3746 ) {
3747 // Keep track of the multisite override selection.
3748 $auth_settings['multisite_override'] = $auth_multisite_settings['multisite_override'];
3749
3750 // Note: the options below should be the complete list of
3751 // overridden options. It is *not* the complete list of all
3752 // options (some options don't have a multisite equivalent)
3753
3754 // Note: access_users_approved, access_users_pending, and
3755 // access_users_blocked do not get overridden. However,
3756 // since access_users_approved has a multisite equivalent,
3757 // you must retrieve them both seperately. This is done
3758 // because the two lists should be treated differently.
3759 // $approved_users = $this->get_plugin_option( 'access_users_approved', 'single admin' );
3760 // $ms_approved_users = $this->get_plugin_option( 'access_users_approved', 'multisite admin' );
3761
3762 // Override external services (google, cas, or ldap) and associated options
3763 $auth_settings['google'] = $auth_multisite_settings['google'];
3764 $auth_settings['google_clientid'] = $auth_multisite_settings['google_clientid'];
3765 $auth_settings['google_clientsecret'] = $auth_multisite_settings['google_clientsecret'];
3766 $auth_settings['cas'] = $auth_multisite_settings['cas'];
3767 $auth_settings['cas_custom_label'] = $auth_multisite_settings['cas_custom_label'];
3768 $auth_settings['cas_host'] = $auth_multisite_settings['cas_host'];
3769 $auth_settings['cas_port'] = $auth_multisite_settings['cas_port'];
3770 $auth_settings['cas_path'] = $auth_multisite_settings['cas_path'];
3771 $auth_settings['ldap'] = $auth_multisite_settings['ldap'];
3772 $auth_settings['ldap_host'] = $auth_multisite_settings['ldap_host'];
3773 $auth_settings['ldap_port'] = $auth_multisite_settings['ldap_port'];
3774 $auth_settings['ldap_search_base'] = $auth_multisite_settings['ldap_search_base'];
3775 $auth_settings['ldap_uid'] = $auth_multisite_settings['ldap_uid'];
3776 $auth_settings['ldap_user'] = $auth_multisite_settings['ldap_user'];
3777 $auth_settings['ldap_password'] = $auth_multisite_settings['ldap_password'];
3778 $auth_settings['ldap_tls'] = $auth_multisite_settings['ldap_tls'];
3779 $auth_settings['ldap_lostpassword_url'] = $auth_multisite_settings['ldap_lostpassword_url'];
3780
3781 // Override access_who_can_login and access_who_can_view
3782 $auth_settings['access_who_can_login'] = $auth_multisite_settings['access_who_can_login'];
3783 $auth_settings['access_who_can_view'] = $auth_multisite_settings['access_who_can_view'];
3784
3785 // Override access_default_role
3786 $auth_settings['access_default_role'] = $auth_multisite_settings['access_default_role'];
3787
3788 // Override lockouts
3789 $auth_settings['advanced_lockouts'] = $auth_multisite_settings['advanced_lockouts'];
3790
3791 // Override Hide WordPress login
3792 $auth_settings['advanced_hide_wp_login'] = $auth_multisite_settings['advanced_hide_wp_login'];
3793 }
3794 }
3795 return $auth_settings;
3796 }
3797
3798
3799 private function maybe_email_welcome_message( $email ) {
3800 // Get option for whether to email welcome messages.
3801 $should_email_new_approved_users = $this->get_plugin_option( 'access_should_email_approved_users' );
3802
3803 // Do not send welcome email if option not enabled.
3804 if ( $should_email_new_approved_users !== '1' ) {
3805 return false;
3806 }
3807
3808 // Make sure we didn't just email this user (can happen with
3809 // multiple admins saving at the same time, or by clicking
3810 // Approve button too rapidly).
3811 $recently_sent_emails = get_option( 'auth_settings_recently_sent_emails' );
3812 if ( $recently_sent_emails === FALSE ) {
3813 $recently_sent_emails = array();
3814 }
3815 foreach ( $recently_sent_emails as $key => $recently_sent_email ) {
3816 if ( $recently_sent_email['time'] < strtotime( 'now -1 minutes' ) ) {
3817 // Remove emails sent more than 1 minute ago.
3818 unset( $recently_sent_emails[$key] );
3819 } elseif ( $recently_sent_email['email'] === $email ) {
3820 // Sent an email to this user within the last 1 minute, so
3821 // quit without sending.
3822 return false;
3823 }
3824 }
3825 // Add the email we're about to send to the list.
3826 $recently_sent_emails[] = array(
3827 'email' => $email,
3828 'time' => time(),
3829 );
3830 update_option( 'auth_settings_recently_sent_emails', $recently_sent_emails );
3831
3832 // Get welcome email subject and body text
3833 $subject = $this->get_plugin_option( 'access_email_approved_users_subject' );
3834 $body = apply_filters( 'the_content', $this->get_plugin_option( 'access_email_approved_users_body' ) );
3835
3836 // Fail if the subject/body options don't exist or are empty.
3837 if ( is_null( $subject ) || is_null( $body ) || strlen( $subject ) === 0 || strlen( $body ) === 0 ) {
3838 return false;
3839 }
3840
3841 // Replace approved shortcode patterns in subject and body.
3842 $site_name = get_bloginfo( 'name' );
3843 $site_url = get_site_url();
3844 $subject = str_replace( '[site_name]', $site_name, $subject );
3845 $body = str_replace( '[site_name]', $site_name, $body );
3846 $body = str_replace( '[site_url]', $site_url, $body );
3847 $body = str_replace( '[user_email]', $email, $body );
3848 $headers = 'Content-type: text/html' . "\r\n";
3849
3850 // Send email.
3851 wp_mail( $email, $subject, $body, $headers );
3852
3853 // Indicate mail was sent.
3854 return true;
3855 }
3856
3857 /**
3858 * Generate a unique cookie to add to nonces to prevent CSRF.
3859 */
3860 protected $cookie_value = null;
3861 function get_cookie_value() {
3862 if ( ! $this->cookie_value ) {
3863 if ( isset( $_COOKIE['login_unique'] ) ) {
3864 $this->cookie_value = $_COOKIE['login_unique'];
3865 } else {
3866 $this->cookie_value = md5( rand() );
3867 }
3868 }
3869 return $this->cookie_value;
3870 } // END get_cookie_value()
3871
3872 /**
3873 * Basic encryption using a public (not secret!) key. Used for general
3874 * database obfuscation of passwords.
3875 */
3876 private static $key = '8QxnrvjdtweisvCBKEY!+0';
3877 function encrypt( $text ) {
3878 $result = '';
3879
3880 // Use mcrypt library (better) if php5-mcrypt extension is enabled.
3881 if ( function_exists( 'mcrypt_encrypt' ) ) {
3882 $result = mcrypt_encrypt( MCRYPT_RIJNDAEL_256, self::$key, $text, MCRYPT_MODE_ECB, 'abcdefghijklmnopqrstuvwxyz012345' );
3883 } else {
3884 for ( $i = 0; $i < strlen( $text ); $i++ ) {
3885 $char = substr( $text, $i, 1 );
3886 $keychar = substr( self::$key, ( $i % strlen( self::$key ) ) - 1, 1 );
3887 $char = chr( ord( $char ) + ord( $keychar ) );
3888 $result .= $char;
3889 }
3890 $result = base64_encode( $result );
3891 }
3892
3893 return $result;
3894 } // END encrypt()
3895
3896 function decrypt( $secret ) {
3897 $result = '';
3898
3899 // Use mcrypt library (better) if php5-mcrypt extension is enabled.
3900 if ( function_exists( 'mcrypt_decrypt' ) ) {
3901 $result = rtrim( mcrypt_decrypt( MCRYPT_RIJNDAEL_256, self::$key, $secret, MCRYPT_MODE_ECB, 'abcdefghijklmnopqrstuvwxyz012345' ), "\0$result" );
3902 } else {
3903 $secret = base64_decode( $secret );
3904 for ( $i = 0; $i < strlen( $secret ); $i++ ) {
3905 $char = substr( $secret, $i, 1 );
3906 $keychar = substr( self::$key, ( $i % strlen( self::$key ) ) - 1, 1 );
3907 $char = chr( ord( $char ) - ord( $keychar ) );
3908 $result .= $char;
3909 }
3910 }
3911
3912 return $result;
3913 } // END decrypt()
3914
3915 /**
3916 * In a multisite environment, returns true if the current user is logged
3917 * in and a user of the current blog. In single site mode, simply returns
3918 * true if the current user is logged in.
3919 */
3920 function is_user_logged_in_and_blog_user() {
3921 $is_user_logged_in_and_blog_user = false;
3922 if ( is_multisite() ) {
3923 $is_user_logged_in_and_blog_user = is_user_logged_in() && is_user_member_of_blog( get_current_user_id() );
3924 } else {
3925 $is_user_logged_in_and_blog_user = is_user_logged_in();
3926 }
3927 return $is_user_logged_in_and_blog_user;
3928 } // END is_user_logged_in_and_blog_user()
3929
3930 /**
3931 * Helper function to determine whether a given email is in one of
3932 * the lists (pending, approved, blocked). Defaults to the list of
3933 * approved users.
3934 */
3935 function is_email_in_list( $email = '', $list = 'approved', $multisite_mode = 'single' ) {
3936 if ( empty( $email ) )
3937 return false;
3938
3939 switch ( $list ) {
3940 case 'pending':
3941 $auth_settings_access_users_pending = $this->get_plugin_option( 'access_users_pending', 'single admin' );
3942 return $this->in_multi_array( $email, $auth_settings_access_users_pending );
3943 break;
3944 case 'blocked':
3945 $auth_settings_access_users_blocked = $this->get_plugin_option( 'access_users_blocked', 'single admin' );
3946 return $this->in_multi_array( $email, $auth_settings_access_users_blocked );
3947 break;
3948 case 'approved':
3949 default:
3950 $auth_settings_access_users_approved = $multisite_mode !== 'single' ?
3951 $this->get_plugin_option( 'access_users_approved', 'multisite admin' )
3952 : array_merge(
3953 $this->get_plugin_option( 'access_users_approved', 'single admin' ),
3954 $this->get_plugin_option( 'access_users_approved', 'multisite admin' )
3955 );
3956 return $this->in_multi_array( $email, $auth_settings_access_users_approved );
3957 break;
3958 }
3959 } // END is_email_in_list
3960
3961 /**
3962 * Helper function to search a multidimensional array for a value.
3963 */
3964 function in_multi_array( $needle = '', $haystack = array(), $strict_mode = 'not strict', $case_sensitivity = 'case insensitive' ) {
3965 if ( ! is_array( $haystack ) ) {
3966 return false;
3967 }
3968 if ( $case_sensitivity === 'case insensitive' ) {
3969 $needle = strtolower( $needle );
3970 }
3971 foreach ( $haystack as $item ) {
3972 if ( $case_sensitivity === 'case insensitive' && ! is_array( $item ) ) {
3973 $item = strtolower( $item );
3974 }
3975 if ( ( $strict_mode === 'strict' ? $item === $needle : $item == $needle ) || ( is_array( $item ) && $this->in_multi_array( $needle, $item, $strict_mode, $case_sensitivity ) ) ) {
3976 return true;
3977 }
3978 }
3979 return false;
3980 } // END in_multi_array()
3981
3982 /**
3983 * Helper function to get a WordPress page ID from the pagename.
3984 *
3985 * @param string $pagename Page Slug
3986 * @return int Page/Post ID
3987 */
3988 function get_id_from_pagename( $pagename = '' ) {
3989 global $wpdb;
3990 $page_id = $wpdb->get_var( "SELECT ID FROM $wpdb->posts WHERE post_name = '" . sanitize_title_for_query( $pagename ) . "'" );
3991 return $page_id;
3992 } // END get_id_from_pagename()
3993
3994 /**
3995 * Helper function to determine if an URL is accessible.
3996 *
3997 * @param string $url URL that should be publicly reachable
3998 * @return boolean Whether the URL is publicly reachable
3999 */
4000 function url_is_accessible( $url ) {
4001 // Make sure php5-curl extension is installed on server.
4002 if ( ! function_exists( 'curl_init' ) ) {
4003 // Note: This will silently fail, saying url is not accessible.
4004 // Warn user elsewhere that they should install curl.
4005 return false;
4006 }
4007
4008 // Use curl to retrieve the URL.
4009 $handle = curl_init( $url );
4010 curl_setopt( $handle, CURLOPT_RETURNTRANSFER, TRUE );
4011 $response = curl_exec( $handle );
4012 $http_code = curl_getinfo( $handle, CURLINFO_HTTP_CODE );
4013 curl_close( $handle );
4014
4015 // Return true if the document has loaded successfully without any redirection or error
4016 return $http_code >= 200 && $http_code < 400;
4017 } // END url_is_accessible()
4018
4019 // Helper function that builds option tags for a select element for all
4020 // roles the current user has permission to assign.
4021 function wp_dropdown_permitted_roles( $selected_role = 'subscriber', $disable_input = 'not disabled' ) {
4022 $roles = get_editable_roles();
4023 $current_user = wp_get_current_user();
4024
4025 // Make sure we have a selected role (default to subscriber).
4026 if ( strlen( $selected_role ) < 1 ) {
4027 $selected_role = 'subscriber';
4028 }
4029
4030 // If the currently selected role is not in the list of roles, it
4031 // either doesn't exist or the current user is not permitted to
4032 // assign it.
4033 if ( ! array_key_exists( $selected_role, $roles ) ) {
4034 ?><option value="<?php echo $selected_role; ?>"><?php echo ucfirst( $selected_role ); ?></option><?php
4035
4036 // If the role exists, that means the user isn't permitted to
4037 // assign it, so assume they can't edit that user's role at
4038 // all. Return only the one role for the dropdown list.
4039 if ( ! is_null( get_role( $selected_role ) ) ) {
4040 return;
4041 }
4042 }
4043
4044 // Print an option element for each permitted role.
4045 foreach ( $roles as $name => $role ) {
4046 $selected = $selected_role === $name ? ' selected="selected"' : '';
4047
4048 // Don't let a user change their own role
4049 $disabled = $selected_role !== $name && $disable_input === 'disabled' ? ' disabled="disabled"' : '';
4050
4051 // But network admins can always change their role.
4052 if ( is_multisite() && current_user_can( 'manage_network' ) ) {
4053 $disabled = '';
4054 }
4055
4056 ?><option value="<?php echo $name; ?>"<?php echo $selected . $disabled; ?>><?php echo $role['name']; ?></option><?php
4057 }
4058 } // END wp_dropdown_permitted_roles()
4059
4060 // Helper function to get a single user info array from one of the
4061 // access control lists (pending, approved, or blocked).
4062 // Returns: false if not found; otherwise
4063 // array( 'email' => '', 'role' => '', 'date_added' => '');
4064 function get_user_info_from_list( $email, $list ) {
4065 foreach ( $list as $user_info ) {
4066 if ( $user_info['email'] === $email ) {
4067 return $user_info;
4068 }
4069 }
4070 return false;
4071 } // END get_user_info_from_list()
4072
4073 // Helper function to convert seconds to human readable text.
4074 // Source: http://csl.name/php-secs-to-human-text/
4075 function seconds_as_sentence( $secs ) {
4076 $units = array(
4077 "week" => 7 * 24 * 3600,
4078 "day" => 24 * 3600,
4079 "hour" => 3600,
4080 "minute" => 60,
4081 "second" => 1,
4082 );
4083
4084 // specifically handle zero
4085 if ( $secs == 0 ) return "0 seconds";
4086
4087 $s = "";
4088
4089 foreach ( $units as $name => $divisor ) {
4090 if ( $quot = intval( $secs / $divisor ) ) {
4091 $s .= "$quot $name";
4092 $s .= ( abs( $quot ) > 1 ? "s" : "" ) . ", ";
4093 $secs -= $quot * $divisor;
4094 }
4095 }
4096
4097 return substr( $s, 0, -2 );
4098 } // END seconds_as_sentence()
4099
4100 // Helper function to get all available usermeta keys as an array.
4101 function get_all_usermeta_keys() {
4102 global $wpdb;
4103 $usermeta_keys = $wpdb->get_col( "SELECT DISTINCT $wpdb->usermeta.meta_key FROM $wpdb->usermeta" );
4104 return $usermeta_keys;
4105 }
4106
4107
4108 /**
4109 * Plugin Update Routines.
4110 */
4111 function auth_update_check() {
4112 // Update: migrate user lists to own options (addresses concurrency
4113 // when saving plugin options, since user lists are changed often
4114 // and we don't want to overwrite changes to the lists when an
4115 // admin saves all of the plugin options.)
4116 // Note: Pending user list is changed whenever a new user tries to
4117 // log in; approved and blocked lists are changed whenever an admin
4118 // changes them from the multisite panel, the dashboard widget, or
4119 // the plugin options page.
4120 $update_if_older_than = 20140709;
4121 $auth_version = get_option( 'auth_version' );
4122 if ( $auth_version === false || intval( $auth_version ) < $update_if_older_than ) {
4123 // Copy single site user lists to new options (if they exist).
4124 $auth_settings = get_option( 'auth_settings' );
4125 if ( is_array( $auth_settings ) && array_key_exists( 'access_users_pending', $auth_settings ) ) {
4126 update_option( 'auth_settings_access_users_pending', $auth_settings['access_users_pending'] );
4127 unset( $auth_settings['access_users_pending'] );
4128 update_option( 'auth_settings', $auth_settings );
4129 }
4130 if ( is_array( $auth_settings ) && array_key_exists( 'access_users_approved', $auth_settings ) ) {
4131 update_option( 'auth_settings_access_users_approved', $auth_settings['access_users_approved'] );
4132 unset( $auth_settings['access_users_approved'] );
4133 update_option( 'auth_settings', $auth_settings );
4134 }
4135 if ( is_array( $auth_settings ) && array_key_exists( 'access_users_blocked', $auth_settings ) ) {
4136 update_option( 'auth_settings_access_users_blocked', $auth_settings['access_users_blocked'] );
4137 unset( $auth_settings['access_users_blocked'] );
4138 update_option( 'auth_settings', $auth_settings );
4139 }
4140 // Copy multisite user lists to new options (if they exist).
4141 if ( is_multisite() ) {
4142 $auth_multisite_settings = get_blog_option( BLOG_ID_CURRENT_SITE, 'auth_multisite_settings', array() );
4143 if ( is_array( $auth_multisite_settings ) && array_key_exists( 'access_users_pending', $auth_multisite_settings ) ) {
4144 update_blog_option( BLOG_ID_CURRENT_SITE, 'auth_multisite_settings_access_users_pending', $auth_multisite_settings['access_users_pending'] );
4145 unset( $auth_multisite_settings['access_users_pending'] );
4146 update_blog_option( BLOG_ID_CURRENT_SITE, 'auth_multisite_settings', $auth_multisite_settings );
4147 }
4148 if ( is_array( $auth_multisite_settings ) && array_key_exists( 'access_users_approved', $auth_multisite_settings ) ) {
4149 update_blog_option( BLOG_ID_CURRENT_SITE, 'auth_multisite_settings_access_users_approved', $auth_multisite_settings['access_users_approved'] );
4150 unset( $auth_multisite_settings['access_users_approved'] );
4151 update_blog_option( BLOG_ID_CURRENT_SITE, 'auth_multisite_settings', $auth_multisite_settings );
4152 }
4153 if ( is_array( $auth_multisite_settings ) && array_key_exists( 'access_users_blocked', $auth_multisite_settings ) ) {
4154 update_blog_option( BLOG_ID_CURRENT_SITE, 'auth_multisite_settings_access_users_blocked', $auth_multisite_settings['access_users_blocked'] );
4155 unset( $auth_multisite_settings['access_users_blocked'] );
4156 update_blog_option( BLOG_ID_CURRENT_SITE, 'auth_multisite_settings', $auth_multisite_settings );
4157 }
4158 }
4159 // Update version to reflect this change has been made.
4160 update_option( 'auth_version', $update_if_older_than );
4161 }
4162
4163 // // Update: TEMPLATE
4164 // $update_if_older_than = YYYYMMDD;
4165 // $auth_version = get_option( 'auth_version' );
4166 // if ( $auth_version === false || intval( $auth_version ) < $update_if_older_than ) {
4167 // UPDATE CODE HERE
4168 // update_option( 'auth_version', $update_if_older_than );
4169 // }
4170 }
4171
4172 } // END class WP_Plugin_Authorizer
4173 }
4174
4175 // Instantiate the plugin class.
4176 $wp_plugin_authorizer = new WP_Plugin_Authorizer();
4177