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

authorizer.php in Authorizer 2.2, at authorizer.php

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