PluginProbe
Authorizer / 2.6.19
Authorizer v2.6.19
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.6.19, at authorizer.php

6,285 lines 299.4 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/uhm-coe/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.6.19
7 Author: Paul Ryan
8 Author URI: http://www.linkedin.com/in/paulrryan/
9 Text Domain: authorizer
10 Domain Path: /languages
11 License: GPL2
12 */
13
14
15 /*
16 Copyright 2014 Paul Ryan (email: prar@hawaii.edu)
17
18 This program is free software; you can redistribute it and/or modify
19 it under the terms of the GNU General Public License, version 2, as
20 published by the Free Software Foundation.
21
22 This program is distributed in the hope that it will be useful,
23 but WITHOUT ANY WARRANTY; without even the implied warranty of
24 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 GNU General Public License for more details.
26
27 You should have received a copy of the GNU General Public License
28 along with this program; if not, write to the Free Software
29 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
30 */
31
32
33 /*
34 Portions forked from Restricted Site Access plugin: http://wordpress.org/plugins/restricted-site-access/
35 Portions forked from wpCAS plugin: http://wordpress.org/extend/plugins/cas-authentication/
36 Portions forked from Limit Login Attempts: http://wordpress.org/plugins/limit-login-attempts/
37 */
38
39
40 define( 'MULTISITE_ADMIN', 'multisite_admin' );
41 define( 'SINGLE_ADMIN', 'single_admin' );
42
43
44 // Add phpCAS library if it's not included.
45 // @see https://wiki.jasig.org/display/CASC/phpCAS+installation+guide
46 if ( ! defined( 'PHPCAS_VERSION' ) ) {
47 require_once dirname( __FILE__ ) . '/vendor/CAS-1.3.5/CAS.php';
48 }
49
50
51 if ( ! class_exists( 'WP_Plugin_Authorizer' ) ) {
52 /**
53 * Define class for plugin: Authorizer.
54 *
55 * @category Authentication
56 * @package Authorizer
57 * @author Paul Ryan <prar@hawaii.edu>
58 * @license http://www.gnu.org/licenses/gpl-2.0.html GPL2
59 * @link http://hawaii.edu/coe/dcdc/wordpress/authorizer/doc/
60 */
61 class WP_Plugin_Authorizer {
62
63
64 /**
65 * Constructor.
66 */
67 public function __construct() {
68 // Installation and uninstallation hooks.
69 register_activation_hook( __FILE__, array( $this, 'activate' ) );
70 register_deactivation_hook( __FILE__, array( $this, 'deactivate' ) );
71
72 // Register filters.
73
74 // Custom wp authentication routine using external service.
75 add_filter( 'authenticate', array( $this, 'custom_authenticate' ), 1, 3 );
76
77 // Custom logout action using external service.
78 add_action( 'wp_logout', array( $this, 'custom_logout' ) );
79
80 // Removing this bypasses Wordpress authentication (so if external auth fails,
81 // no one can log in); with it enabled, it will run if external auth fails.
82 //remove_filter('authenticate', 'wp_authenticate_username_password', 20, 3);
83
84 // Create settings link on Plugins page
85 add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), array( $this, 'plugin_settings_link' ) );
86 add_filter( 'network_admin_plugin_action_links_' . plugin_basename( __FILE__ ), array( $this, 'network_admin_plugin_settings_link' ) );
87
88 // Modify login page with a custom password url (if option is set).
89 add_filter( 'lostpassword_url', array( $this, 'custom_lostpassword_url' ) );
90
91 // If we have a custom login error, add the filter to show it.
92 $error = get_option( 'auth_settings_advanced_login_error' );
93 if ( $error && strlen( $error ) > 0 ) {
94 add_filter( 'login_errors', array( $this, 'show_advanced_login_error' ) );
95 }
96
97 // Register actions.
98
99 // Enable localization. Translation files stored in /languages.
100 add_action( 'plugins_loaded', array( $this, 'load_textdomain' ) );
101
102 // Perform plugin updates if newer version installed.
103 add_action( 'plugins_loaded', array( $this, 'auth_update_check' ) );
104
105 // Update the user meta with this user's failed login attempt.
106 add_action( 'wp_login_failed', array( $this, 'update_login_failed_count' ) );
107
108 // Add users who successfully login to the approved list.
109 add_action( 'wp_login', array( $this, 'ensure_wordpress_user_in_approved_list_on_login' ), 10, 2 );
110
111 // Create menu item in Settings
112 add_action( 'admin_menu', array( $this, 'add_plugin_page' ) );
113
114 // Create options page
115 add_action( 'admin_init', array( $this, 'page_init' ) );
116
117 // Update user role in approved list if it's changed in the WordPress edit user page.
118 add_action( 'edit_user_profile_update', array( $this, 'edit_user_profile_update_role' ) );
119 add_action( 'personal_options_update', array( $this, 'edit_user_profile_update_role' ) );
120
121 // Enqueue javascript and css on the plugin's options page, the
122 // dashboard (for the widget), and the network admin.
123 add_action( 'load-settings_page_authorizer', array( $this, 'load_options_page' ) );
124 add_action( 'admin_head-index.php', array( $this, 'load_options_page' ) );
125 add_action( 'load-toplevel_page_authorizer', array( $this, 'load_options_page' ) );
126
127 // Add custom css and js to wp-login.php
128 add_action( 'login_enqueue_scripts', array( $this, 'login_enqueue_scripts_and_styles' ) );
129 add_action( 'login_footer', array( $this, 'load_login_footer_js' ) );
130
131 // Modify login page with external auth links (if enabled; e.g., google or cas)
132 add_action( 'login_form', array( $this, 'login_form_add_external_service_links' ) );
133
134 // Redirect to CAS login when visiting login page (only if option is
135 // enabled, CAS is the only service, and WordPress logins are hidden).
136 // Note: hook into wp_login_errors filter so this fires after the
137 // authenticate hook (where the redirect to CAS happens), but before html
138 // output is started (so the redirect header doesn't complain about data
139 // already being sent).
140 add_filter( 'wp_login_errors', array( $this, 'wp_login_errors__maybe_redirect_to_cas' ), 10, 2 );
141
142 // Verify current user has access to page they are visiting
143 add_action( 'parse_request', array( $this, 'restrict_access' ), 9 );
144 add_action( 'init', array( $this, 'init__maybe_add_network_approved_user' ) );
145
146 // ajax save options from dashboard widget
147 add_action( 'wp_ajax_update_auth_user', array( $this, 'ajax_update_auth_user' ) );
148
149 // ajax save options from multisite options page
150 add_action( 'wp_ajax_save_auth_multisite_settings', array( $this, 'ajax_save_auth_multisite_settings' ) );
151
152 // ajax save usermeta from options page
153 add_action( 'wp_ajax_update_auth_usermeta', array( $this, 'ajax_update_auth_usermeta' ) );
154
155 // ajax verify google login
156 add_action( 'wp_ajax_process_google_login', array( $this, 'ajax_process_google_login' ) );
157 add_action( 'wp_ajax_nopriv_process_google_login', array( $this, 'ajax_process_google_login' ) );
158
159 // Add dashboard widget so instructors can add/edit users with access.
160 // Hint: For Multisite Network Admin Dashboard use wp_network_dashboard_setup instead of wp_dashboard_setup.
161 add_action( 'wp_dashboard_setup', array( $this, 'add_dashboard_widgets' ) );
162
163 // If we have a custom admin message, add the action to show it.
164 $notice = get_option( 'auth_settings_advanced_admin_notice' );
165 if ( $notice && strlen( $notice ) > 0 ) {
166 add_action( 'admin_notices', array( $this, 'show_advanced_admin_notice' ) );
167 add_action( 'network_admin_notices', array( $this, 'show_advanced_admin_notice' ) );
168 }
169
170 // Load custom javascript for the main site (e.g., for displaying alerts).
171 add_action( 'wp_enqueue_scripts', array( $this, 'auth_public_scripts' ), 20 );
172
173 // Multisite-specific actions.
174 if ( is_multisite() ) {
175 // Add network admin options page (global settings for all sites)
176 add_action( 'network_admin_menu', array( $this, 'network_admin_menu' ) );
177 }
178
179 // Remove user from authorizer lists when that user is deleted in WordPress.
180 add_action( 'delete_user', array( $this, 'remove_user_from_authorizer_when_deleted' ) );
181 if ( is_multisite() ) {
182 // Remove multisite user from authorizer lists when that user is deleted from Network Users.
183 add_action( 'remove_user_from_blog', array( $this, 'remove_network_user_from_site_when_removed' ), 10, 2 );
184 add_action( 'wpmu_delete_user', array( $this, 'remove_network_user_from_authorizer_when_deleted' ) );
185 }
186
187 // Add user to authorizer approved list when that user is added to a blog from the Users screen.
188 // Multisite: invite_user action fired when adding (inviting) an existing network user to the current site (with email confirmation).
189 add_action( 'invite_user', array( $this, 'add_existing_user_to_authorizer_when_created' ), 10, 3 );
190 // Multisite: added_existing_user action fired when adding an existing network user to the current site (without email confirmation).
191 add_action( 'added_existing_user', array( $this, 'add_existing_user_to_authorizer_when_created_noconfirmation' ), 10, 2 );
192 // Multisite: after_signup_user action fired when adding a new user to the site (with or without email confirmation).
193 add_action( 'after_signup_user', array( $this, 'add_new_user_to_authorizer_when_created' ), 10, 4 );
194 // Single site: edit_user_created_user action fired when adding a new user to the site (with or without email notification).
195 add_action( 'edit_user_created_user', array( $this, 'add_new_user_to_authorizer_when_created_single_site' ), 10, 2 );
196
197 // Add user to network approved users (and remove from individual sites)
198 // when user is elevated to super admin status.
199 add_action( 'grant_super_admin', array( $this, 'grant_super_admin__add_to_network_approved' ) );
200 // Remove user from network approved users (and add them to the approved
201 // list on sites they are already on) when super admin status is removed.
202 add_action( 'revoke_super_admin', array( $this, 'revoke_super_admin__remove_from_network_approved' ) );
203
204 }
205
206
207 /**
208 * Plugin activation hook.
209 * Will also activate the plugin for all sites/blogs if this is a "Network enable."
210 *
211 * @return void
212 */
213 public function activate() {
214 global $wpdb;
215
216 // If we're in a multisite environment, run the plugin activation for each site when network enabling
217 if ( is_multisite() && isset( $_GET['networkwide'] ) && $_GET['networkwide'] == 1 ) {
218
219 // Add super admins to the multisite approved list.
220 $auth_multisite_settings_access_users_approved = get_blog_option( BLOG_ID_CURRENT_SITE, 'auth_multisite_settings_access_users_approved', array() );
221 $should_update_auth_multisite_settings_access_users_approved = false;
222 foreach ( get_super_admins() as $super_admin ) {
223 $user = get_user_by( 'login', $super_admin );
224 // Add to approved list if not there.
225 if ( ! $this->in_multi_array( $user->user_email, $auth_multisite_settings_access_users_approved ) ) {
226 $approved_user = array(
227 'email' => mb_strtolower( $user->user_email ),
228 'role' => count( $user->roles ) > 0 ? $user->roles[0] : 'administrator',
229 'date_added' => date( 'M Y', strtotime( $user->user_registered ) ),
230 'local_user' => true,
231 );
232 array_push( $auth_multisite_settings_access_users_approved, $approved_user );
233 $should_update_auth_multisite_settings_access_users_approved = true;
234 }
235 }
236 if ( $should_update_auth_multisite_settings_access_users_approved ) {
237 update_blog_option( BLOG_ID_CURRENT_SITE, 'auth_multisite_settings_access_users_approved', $auth_multisite_settings_access_users_approved );
238 }
239
240 // Run plugin activation on each site in the network.
241 $current_blog_id = $wpdb->blogid;
242 $sites = function_exists( 'get_sites' ) ? get_sites() : wp_get_sites( array( 'limit' => PHP_INT_MAX ) );
243 foreach ( $sites as $site ) {
244 $blog_id = function_exists( 'get_sites' ) ? $site->blog_id : $site['blog_id'];
245 switch_to_blog( $blog_id );
246 // Set default plugin options and add current users to approved list.
247 $this->set_default_options();
248 $this->add_wp_users_to_approved_list();
249 }
250 switch_to_blog( $current_blog_id );
251
252 } else {
253 // Set default plugin options and add current users to approved list.
254 $this->set_default_options();
255 $this->add_wp_users_to_approved_list();
256 }
257
258 }
259
260
261 /**
262 * Adds all WordPress users in the current site to the approved list,
263 * unless they are already in the blocked list. Also removes them
264 * from the pending list if they are there.
265 *
266 * Runs in plugin activation hook.
267 *
268 * @return void
269 */
270 private function add_wp_users_to_approved_list() {
271 // Add current WordPress users to the approved list.
272 $auth_multisite_settings_access_users_approved = is_multisite() ? get_blog_option( BLOG_ID_CURRENT_SITE, 'auth_multisite_settings_access_users_approved', array() ) : array();
273 $auth_settings_access_users_pending = $this->get_plugin_option( 'access_users_pending', SINGLE_ADMIN );
274 $auth_settings_access_users_approved = $this->get_plugin_option( 'access_users_approved', SINGLE_ADMIN );
275 $auth_settings_access_users_blocked = $this->get_plugin_option( 'access_users_blocked', SINGLE_ADMIN );
276 $updated = false;
277 foreach ( get_users() as $user ) {
278 // Skip if user is in blocked list.
279 if ( $this->in_multi_array( $user->user_email, $auth_settings_access_users_blocked ) ) {
280 continue;
281 }
282 // Remove from pending list if there.
283 foreach ( $auth_settings_access_users_pending as $key => $pending_user ) {
284 if ( 0 === strcasecmp( $pending_user['email'], $user->user_email ) ) {
285 unset( $auth_settings_access_users_pending[$key] );
286 $updated = true;
287 }
288 }
289 // Skip if user is in multisite approved list.
290 if ( $this->in_multi_array( $user->user_email, $auth_multisite_settings_access_users_approved ) ) {
291 continue;
292 }
293 // Add to approved list if not there.
294 if ( ! $this->in_multi_array( $user->user_email, $auth_settings_access_users_approved ) ) {
295 $approved_user = array(
296 'email' => mb_strtolower( $user->user_email ),
297 'role' => count( $user->roles ) > 0 ? $user->roles[0] : '',
298 'date_added' => date( 'M Y', strtotime( $user->user_registered ) ),
299 'local_user' => true,
300 );
301 array_push( $auth_settings_access_users_approved, $approved_user );
302 $updated = true;
303 }
304 }
305 if ( $updated ) {
306 update_option( 'auth_settings_access_users_pending', $auth_settings_access_users_pending );
307 update_option( 'auth_settings_access_users_approved', $auth_settings_access_users_approved );
308 }
309 }
310
311
312 /**
313 * Plugin deactivation.
314 *
315 * @return void
316 */
317 public function deactivate() {
318 // Do nothing.
319 }
320
321
322
323 /**
324 * ***************************
325 * External Authentication
326 * ***************************
327 */
328
329
330
331 /**
332 * Authenticate against an external service.
333 *
334 * @param WP_User $user user to authenticate
335 * @param string $username optional username to authenticate.
336 * @param string $password optional password to authenticate.
337 *
338 * @return WP_User or WP_Error
339 */
340 public function custom_authenticate( $user, $username, $password ) {
341 // Pass through if already authenticated.
342 if ( is_a( $user, 'WP_User' ) ) {
343 return $user;
344 } else {
345 $user = null;
346 }
347
348 // If username and password are blank, this isn't a log in attempt
349 $is_login_attempt = strlen( $username ) > 0 && strlen( $password ) > 0;
350
351 // Check to make sure that $username is not locked out due to too
352 // many invalid login attempts. If it is, tell the user how much
353 // time remains until they can try again.
354 $unauthenticated_user = $is_login_attempt ? get_user_by( 'login', $username ) : false;
355 $unauthenticated_user_is_blocked = false;
356 if ( $is_login_attempt && $unauthenticated_user !== false ) {
357 $last_attempt = get_user_meta( $unauthenticated_user->ID, 'auth_settings_advanced_lockouts_time_last_failed', true );
358 $num_attempts = get_user_meta( $unauthenticated_user->ID, 'auth_settings_advanced_lockouts_failed_attempts', true );
359 // Also check the auth_blocked user_meta flag (users in blocked list will get this flag)
360 $unauthenticated_user_is_blocked = get_user_meta( $unauthenticated_user->ID, 'auth_blocked', true ) === 'yes';
361 } else {
362 $last_attempt = get_option( 'auth_settings_advanced_lockouts_time_last_failed' );
363 $num_attempts = get_option( 'auth_settings_advanced_lockouts_failed_attempts' );
364 }
365
366 // Inactive users should be treated like deleted users (we just
367 // do this to preserve any content they created, but here we should
368 // pretend they don't exist).
369 if ( $unauthenticated_user_is_blocked ) {
370 remove_filter( 'authenticate', 'wp_authenticate_username_password', 20, 3 );
371 return new WP_Error( 'empty_password', __( '<strong>ERROR</strong>: Incorrect username or password.', 'authorizer' ) );
372 }
373
374 // Grab plugin settings.
375 $auth_settings = $this->get_plugin_options( SINGLE_ADMIN, 'allow override' );
376
377 // Make sure $last_attempt (time) and $num_attempts are positive integers.
378 // Note: this addresses resetting them if either is unset from above.
379 $last_attempt = abs( intval( $last_attempt ) );
380 $num_attempts = abs( intval( $num_attempts ) );
381
382 // Create semantic lockout variables.
383 $lockouts = $auth_settings['advanced_lockouts'];
384 $time_since_last_fail = time() - $last_attempt;
385 $reset_duration = $lockouts['reset_duration'] * 60; // minutes to seconds
386 $num_attempts_long_lockout = $lockouts['attempts_1'] + $lockouts['attempts_2'];
387 $num_attempts_short_lockout = $lockouts['attempts_1'];
388 $seconds_remaining_long_lockout = $lockouts['duration_2'] * 60 - $time_since_last_fail;
389 $seconds_remaining_short_lockout = $lockouts['duration_1'] * 60 - $time_since_last_fail;
390
391 // Check if we need to institute a lockout delay
392 if ( $is_login_attempt && $time_since_last_fail > $reset_duration ) {
393 // Enough time has passed since the last invalid attempt and
394 // now that we can reset the failed attempt count, and let this
395 // login attempt go through.
396 $num_attempts = 0; // This does nothing, but include it for semantic meaning.
397 } elseif ( $is_login_attempt && $num_attempts > $num_attempts_long_lockout && $seconds_remaining_long_lockout > 0 ) {
398 // Stronger lockout (1st/2nd round of invalid attempts reached)
399 // Note: set the error code to 'empty_password' so it doesn't
400 // trigger the wp_login_failed hook, which would continue to
401 // increment the failed attempt count.
402 remove_filter( 'authenticate', 'wp_authenticate_username_password', 20, 3 );
403 return new WP_Error(
404 'empty_password',
405 sprintf(
406 __( '<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>?', 'authorizer' ),
407 $username,
408 $seconds_remaining_long_lockout,
409 $this->seconds_as_sentence( $seconds_remaining_long_lockout ),
410 wp_lostpassword_url()
411 )
412 );
413 } elseif ( $is_login_attempt && $num_attempts > $num_attempts_short_lockout && $seconds_remaining_short_lockout > 0 ) {
414 // Normal lockout (1st round of invalid attempts reached)
415 // Note: set the error code to 'empty_password' so it doesn't
416 // trigger the wp_login_failed hook, which would continue to
417 // increment the failed attempt count.
418 remove_filter( 'authenticate', 'wp_authenticate_username_password', 20, 3 );
419 return new WP_Error(
420 'empty_password',
421 sprintf(
422 __( '<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>?', 'authorizer' ),
423 $username,
424 $seconds_remaining_short_lockout,
425 $this->seconds_as_sentence( $seconds_remaining_short_lockout ),
426 wp_lostpassword_url()
427 )
428 );
429 }
430
431 // Start external authentication.
432 $externally_authenticated_emails = array();
433 $authenticated_by = '';
434 $result = null;
435
436 // Try Google authentication if it's enabled and we don't have a
437 // successful login yet.
438 if (
439 $auth_settings['google'] === '1' &&
440 count( $externally_authenticated_emails ) === 0 &&
441 ! is_wp_error( $result )
442 ) {
443 $result = $this->custom_authenticate_google( $auth_settings );
444 if ( ! is_null( $result ) && ! is_wp_error( $result ) ) {
445 if ( is_array( $result['email'] ) ) {
446 $externally_authenticated_emails = $result['email'];
447 } else {
448 $externally_authenticated_emails[] = $result['email'];
449 }
450 $authenticated_by = $result['authenticated_by'];
451 }
452 }
453
454 // Try CAS authentication if it's enabled and we don't have a
455 // successful login yet.
456 if (
457 $auth_settings['cas'] === '1' &&
458 count( $externally_authenticated_emails ) === 0 &&
459 ! is_wp_error( $result )
460 ) {
461 $result = $this->custom_authenticate_cas( $auth_settings );
462 if ( ! is_null( $result ) && ! is_wp_error( $result ) ) {
463 if ( is_array( $result['email'] ) ) {
464 $externally_authenticated_emails = $result['email'];
465 } else {
466 $externally_authenticated_emails[] = $result['email'];
467 }
468 $authenticated_by = $result['authenticated_by'];
469 }
470 }
471
472 // Try LDAP authentication if it's enabled and we don't have an
473 // authenticated user yet.
474 if (
475 $auth_settings['ldap'] === '1' &&
476 count( $externally_authenticated_emails ) === 0 &&
477 ! is_wp_error( $result )
478 ) {
479 $result = $this->custom_authenticate_ldap( $auth_settings, $username, $password );
480 if ( ! is_null( $result ) && ! is_wp_error( $result ) ) {
481 if ( is_array( $result['email'] ) ) {
482 $externally_authenticated_emails = $result['email'];
483 } else {
484 $externally_authenticated_emails[] = $result['email'];
485 }
486 $authenticated_by = $result['authenticated_by'];
487 }
488 }
489
490 // Skip to WordPress authentication if we don't have an externally
491 // authenticated user.
492 if ( count( array_filter( $externally_authenticated_emails ) ) < 1 ) {
493 return $result;
494 }
495
496 // Remove duplicate and blank emails, if any.
497 $externally_authenticated_emails = array_filter( array_unique( $externally_authenticated_emails ) );
498
499 // If we've made it this far, we should have an externally
500 // authenticated user. The following should be set:
501 // $externally_authenticated_emails
502 // $authenticated_by
503
504 // Get the external user's WordPress account by email address.
505 foreach ( $externally_authenticated_emails as $externally_authenticated_email ) {
506 $user = get_user_by( 'email', mb_strtolower( $externally_authenticated_email ) );
507
508 // If we've already found a WordPress user associated with one
509 // of the supplied email addresses, don't keep examining other
510 // email addresses associated with the externally authenticated user.
511 if ( $user !== FALSE ) {
512 break;
513 }
514 }
515
516 // Check this external user's access against the access lists
517 // (pending, approved, blocked)
518 $result = $this->check_user_access( $user, $externally_authenticated_emails, $result );
519
520 // Fail with message if there was an error creating/adding the user.
521 if ( is_wp_error( $result ) || $result === 0 ) {
522 return $result;
523 }
524
525 // If we created a new user in check_user_access(), log that user in.
526 if ( get_class( $result ) === 'WP_User' ) {
527 $user = $result;
528 }
529
530 // We'll track how this user was authenticated in user meta.
531 if ( $user ) {
532 update_user_meta( $user->ID, 'authenticated_by', $authenticated_by );
533 }
534
535 // If we haven't exited yet, we have a valid/approved user, so authenticate them.
536 return $user;
537 }
538
539
540 /**
541 * This function will fail with a wp_die() message to the user if they
542 * don't have access.
543 *
544 * @param WP_User $user User to check
545 * @param [type] $user_emails Array of user's plaintext emails (in case current user doesn't have a WP account)
546 * @param [type] $user_data Array of keys for email, username, first_name, last_name,
547 * authenticated_by, google_attributes, cas_attributes, ldap_attributes.
548 * @return WP_Error if there was an error on user creation / adding user to blog
549 * wp_die() if user does not have access
550 * null if user has access (success)
551 * WP_User if user has access and a new account was created for them
552 */
553 private function check_user_access( $user, $user_emails, $user_data = array() ) {
554 // Grab plugin settings.
555 $auth_settings = $this->get_plugin_options( SINGLE_ADMIN, 'allow override' );
556 $auth_settings_access_users_pending = $this->sanitize_user_list(
557 $this->get_plugin_option( 'access_users_pending', SINGLE_ADMIN )
558 );
559 $auth_settings_access_users_approved_single = $this->get_plugin_option( 'access_users_approved', SINGLE_ADMIN );
560 $auth_settings_access_users_approved_multi = $this->get_plugin_option( 'access_users_approved', MULTISITE_ADMIN );
561 $auth_settings_access_users_approved = $this->sanitize_user_list(
562 array_merge(
563 $auth_settings_access_users_approved_single,
564 $auth_settings_access_users_approved_multi
565 )
566 );
567
568 /**
569 * Filter whether to block the currently logging in user based on any of
570 * their user attributes.
571 *
572 * @param bool $allow_login Whether to block the currently logging in user.
573 * @param array $user_data User data returned from external service.
574 */
575 $allow_login = apply_filters( 'authorizer_allow_login', true, $user_data );
576 $blocked_by_filter = ! $allow_login; // Use this for better readability.
577
578 // Check our externally authenticated user against the block list.
579 // If any of their email addresses are blocked, set the relevant user
580 // meta field, and show them an error screen.
581 foreach ( $user_emails as $user_email ) {
582 if ( $blocked_by_filter || $this->is_email_in_list( $user_email, 'blocked' ) ) {
583
584 // Add user to blocked list if it was blocked via the filter.
585 if ( $blocked_by_filter && ! $this->is_email_in_list( $user_email, 'blocked' ) ) {
586 $auth_settings_access_users_blocked = $this->sanitize_user_list(
587 $this->get_plugin_option( 'access_users_blocked', SINGLE_ADMIN )
588 );
589 array_push( $auth_settings_access_users_blocked, array(
590 'email' => mb_strtolower( $user_email ),
591 'date_added' => date( 'M Y' ),
592 ));
593 update_option( 'auth_settings_access_users_blocked', $auth_settings_access_users_blocked );
594 }
595
596 // If the blocked external user has a WordPress account, mark it as
597 // blocked (enforce block in this->authenticate()).
598 if ( $user ) {
599 update_user_meta( $user->ID, 'auth_blocked', 'yes' );
600 }
601
602 // Notify user about blocked status and return without authenticating them.
603 $redirect_to = ! empty( $_REQUEST['redirect_to'] ) ? $_REQUEST['redirect_to'] : home_url();
604 $page_title = sprintf(
605 /* TRANSLATORS: %s: Name of blog */
606 __( '%s - Access Restricted', 'authorizer' ),
607 get_bloginfo( 'name' )
608 );
609 $error_message =
610 apply_filters( 'the_content', $auth_settings['access_blocked_redirect_to_message'] ) .
611 '<hr />' .
612 '<p style="text-align: center;">' .
613 '<a class="button" href="' . wp_logout_url( $redirect_to ) . '">' .
614 __( 'Back', 'authorizer' ) .
615 '</a></p>';
616 update_option( 'auth_settings_advanced_login_error', $error_message );
617 wp_die( $error_message, $page_title );
618 }
619 }
620
621 // Get the default role for this user (or their current role, if they
622 // already have an account).
623 $default_role = $user && is_array( $user->roles ) && count( $user->roles ) > 0 ? $user->roles[0] : $auth_settings['access_default_role'];
624 /**
625 * Filter the role of the user currently logging in. The role will be
626 * set to the default (specified in Authorizer options) for new users,
627 * or the user's current role for existing users. This filter allows
628 * changing user roles based on custom CAS/LDAP attributes.
629 * @param bool $role Role of the user currently logging in.
630 * @param array $user_data User data returned from external service.
631 */
632 $approved_role = apply_filters( 'authorizer_custom_role', $default_role, $user_data );
633
634 /**
635 * Filter whether to automatically approve the currently logging in user
636 * based on any of their user attributes.
637 *
638 * @param bool $automatically_approve_login
639 * Whether to automatically approve the currently logging in user.
640 * @param array $user_data User data returned from external service.
641 */
642 $automatically_approve_login = apply_filters( 'authorizer_automatically_approve_login', false, $user_data );
643
644 // Iterate through each of the email addresses provided by the external
645 // service and determine if any of them have access.
646 $last_email = end( $user_emails );
647 reset( $user_emails );
648 foreach ( $user_emails as $user_email ) {
649 $is_newly_approved_user = false;
650
651 // If this externally authenticated user is an existing administrator
652 // (administrator in single site mode, or super admin in network mode),
653 // and is not in the blocked list, let them in.
654 if ( $user && is_super_admin( $user->ID ) ) {
655 return;
656 }
657
658 // If this externally authenticated user isn't in the approved list
659 // and login access is set to "All authenticated users," or if they were
660 // automatically approved in the "authorizer_approve_login" filter
661 // above, then add them to the approved list (they'll get an account
662 // created below if they don't have one yet).
663 if (
664 ! $this->is_email_in_list( $user_email, 'approved' ) &&
665 ( $auth_settings['access_who_can_login'] === 'external_users' || $automatically_approve_login )
666 ) {
667 $is_newly_approved_user = true;
668
669 // If this user happens to be in the pending list (rare),
670 // remove them from pending before adding them to approved.
671 if ( $this->is_email_in_list( $user_email, 'pending' ) ) {
672 foreach ( $auth_settings_access_users_pending as $key => $pending_user ) {
673 if ( 0 === strcasecmp( $pending_user['email'], $user_email ) ) {
674 unset( $auth_settings_access_users_pending[ $key ] );
675 update_option( 'auth_settings_access_users_pending', $auth_settings_access_users_pending );
676 break;
677 }
678 }
679 }
680
681 // Add this user to the approved list.
682 $approved_user = array(
683 'email' => mb_strtolower( $user_email ),
684 'role' => $approved_role,
685 'date_added' => date( "Y-m-d H:i:s" ),
686 );
687 array_push( $auth_settings_access_users_approved, $approved_user );
688 array_push( $auth_settings_access_users_approved_single, $approved_user );
689 update_option( 'auth_settings_access_users_approved', $auth_settings_access_users_approved_single );
690 }
691
692 // Check our externally authenticated user against the approved
693 // list. If they are approved, log them in (and create their account
694 // if necessary).
695 if ( $is_newly_approved_user || $this->is_email_in_list( $user_email, 'approved' ) ) {
696 $user_info = $is_newly_approved_user ? $approved_user : $this->get_user_info_from_list( $user_email, $auth_settings_access_users_approved );
697
698 // If this user's role was modified above (in the
699 // authorizer_custom_role filter), use that value instead of
700 // whatever is specified in the approved list.
701 if ( $default_role !== $approved_role ) {
702 $user_info['role'] = $approved_role;
703 }
704
705 // If the approved external user does not have a WordPress account, create it
706 if ( ! $user ) {
707 // If there's already a user with this username (e.g.,
708 // johndoe/johndoe@gmail.com exists, and we're trying to add
709 // johndoe/johndoe@example.com), use the full email address
710 // as the username.
711 if ( array_key_exists( 'username', $user_data ) ) {
712 $username = $user_data['username'];
713 } else {
714 $username = explode( '@', $user_info['email'] );
715 $username = $username[0];
716 }
717 if ( get_user_by( 'login', $username ) !== false ) {
718 $username = $user_info['email'];
719 }
720 $result = wp_insert_user(
721 array(
722 'user_login' => strtolower( $username ),
723 'user_pass' => wp_generate_password(), // random password
724 'first_name' => array_key_exists( 'first_name', $user_data ) ? $user_data['first_name'] : '',
725 'last_name' => array_key_exists( 'last_name', $user_data ) ? $user_data['last_name'] : '',
726 'user_email' => mb_strtolower( $user_info['email'] ),
727 'user_registered' => date( 'Y-m-d H:i:s' ),
728 'role' => $user_info['role'],
729 )
730 );
731
732 // Fail with message if error.
733 if ( is_wp_error( $result ) || $result === 0 ) {
734 return $result;
735 }
736
737 // Authenticate as new user
738 $user = new WP_User( $result );
739
740 // If multisite, iterate through all sites in the network and add the user
741 // currently logging in to any of them that have the user on the approved list.
742 // Note: this is useful for first-time logins--some users will have access
743 // to multiple sites, and this prevents them from having to log into each
744 // site individually to get access.
745 if ( is_multisite() ) {
746 $site_ids_of_user = array_map(
747 function ( $site_of_user ) { return $site_of_user->userblog_id; },
748 get_blogs_of_user( $user->ID )
749 );
750
751 $sites = function_exists( 'get_sites' ) ? get_sites() : wp_get_sites( array( 'limit' => PHP_INT_MAX ) );
752 foreach ( $sites as $site ) {
753 $blog_id = function_exists( 'get_sites' ) ? $site->blog_id : $site['blog_id'];
754
755 // Skip if user is already added to this site.
756 if ( in_array( $blog_id, $site_ids_of_user ) ) {
757 continue;
758 }
759
760 // Check if user is on the approved list of this site they are not added to.
761 $other_auth_settings_access_users_approved = get_blog_option( $blog_id, 'auth_settings_access_users_approved', array() );
762 if ( $this->in_multi_array( $user->user_email, $other_auth_settings_access_users_approved ) ) {
763 $other_user_info = $this->get_user_info_from_list( $user->user_email, $other_auth_settings_access_users_approved );
764 // Add user to other site.
765 add_user_to_blog( $blog_id, $user->ID, $other_user_info['role'] );
766 }
767 }
768 }
769
770 // Check if this new user has any preassigned usermeta
771 // values in their approved list entry, and apply them to
772 // their new WordPress account.
773 if ( array_key_exists( 'usermeta', $user_info ) && is_array( $user_info['usermeta'] ) ) {
774 $meta_key = $this->get_plugin_option( 'advanced_usermeta' );
775
776 if ( array_key_exists( 'meta_key', $user_info['usermeta'] ) && array_key_exists( 'meta_value', $user_info['usermeta'] ) ) {
777 // Only update the usermeta if the stored value matches
778 // the option set in authorizer settings (if they don't
779 // match it's probably old data).
780 if ( $meta_key === $user_info['usermeta']['meta_key'] ) {
781 // Update user's usermeta value for usermeta key stored in authorizer options.
782 if ( strpos( $meta_key, 'acf___' ) === 0 && class_exists( 'acf' ) ) {
783 // We have an ACF field value, so use the ACF function to update it.
784 update_field( str_replace('acf___', '', $meta_key ), $user_info['usermeta']['meta_value'], 'user_' . $user->ID );
785 } else {
786 // We have a normal usermeta value, so just update it via the WordPress function.
787 update_user_meta( $user->ID, $meta_key, $user_info['usermeta']['meta_value'] );
788 }
789 }
790 } elseif ( is_multisite() && count( $user_info['usermeta'] ) > 0 ) {
791 // Update usermeta for each multisite blog defined for this user.
792 foreach ( $user_info['usermeta'] as $blog_id => $usermeta ) {
793 if ( array_key_exists( 'meta_key', $usermeta ) && array_key_exists( 'meta_value', $usermeta ) ) {
794 // Add this new user to the blog before we create their user meta (this step typically happens below, but we need it to happen early so we can create user meta here).
795 if ( ! is_user_member_of_blog( $user->ID, $blog_id ) ) {
796 add_user_to_blog( $blog_id, $user->ID, $user_info['role'] );
797 }
798 switch_to_blog( $blog_id );
799 // Update user's usermeta value for usermeta key stored in authorizer options.
800 if ( strpos( $meta_key, 'acf___' ) === 0 && class_exists( 'acf' ) ) {
801 // We have an ACF field value, so use the ACF function to update it.
802 update_field( str_replace('acf___', '', $meta_key ), $usermeta['meta_value'], 'user_' . $user->ID );
803 } else {
804 // We have a normal usermeta value, so just update it via the WordPress function.
805 update_user_meta( $user->ID, $meta_key, $usermeta['meta_value'] );
806 }
807 restore_current_blog();
808 }
809 }
810 }
811 }
812 } else {
813 // Update first/last names of WordPress user from external
814 // service if that option is set.
815 if ( ( array_key_exists( 'authenticated_by', $user_data ) && $user_data['authenticated_by'] === 'cas' && array_key_exists( 'cas_attr_update_on_login', $auth_settings ) && $auth_settings['cas_attr_update_on_login'] == 1 ) || ( array_key_exists( 'authenticated_by', $user_data ) && $user_data['authenticated_by'] === 'ldap' && array_key_exists( 'ldap_attr_update_on_login', $auth_settings ) && $auth_settings['ldap_attr_update_on_login'] == 1 ) ) {
816 if ( array_key_exists( 'first_name', $user_data ) && strlen( $user_data['first_name'] ) > 0 ) {
817 wp_update_user( array(
818 'ID' => $user->ID,
819 'first_name' => $user_data['first_name'],
820 ));
821 }
822 if ( array_key_exists( 'last_name', $user_data ) && strlen( $user_data['last_name'] ) > 0 ) {
823 wp_update_user( array(
824 'ID' => $user->ID,
825 'last_name' => $user_data['last_name'],
826 ));
827 }
828 }
829
830 // Update this user's role if it was modified in the
831 // authorizer_custom_role filter.
832 if ( $default_role !== $approved_role ) {
833 // Update user's role in WordPress.
834 $user->set_role( $approved_role );
835
836 // Update user's role in this site's approved list and save.
837 foreach ( $auth_settings_access_users_approved_single as $key => $existing_user ) {
838 if ( 0 === strcasecmp( $user->user_email, $existing_user['email'] ) ) {
839 $auth_settings_access_users_approved_single[$key]['role'] = $approved_role;
840 break;
841 }
842 }
843 update_option( 'auth_settings_access_users_approved', $auth_settings_access_users_approved_single );
844 }
845 }
846
847 // If this is multisite, add new user to current blog.
848 if ( is_multisite() && ! is_user_member_of_blog( $user->ID ) ) {
849 $result = add_user_to_blog( get_current_blog_id(), $user->ID, $user_info['role'] );
850
851 // Fail with message if error.
852 if ( is_wp_error( $result ) ) {
853 return $result;
854 }
855 }
856
857 // Ensure user has the same role as their entry in the approved list.
858 // (This is just a precaution, the role should already be set when
859 // saving admin options in the sanitizing function.)
860 if ( $user_info && ! array_key_exists( $user_info['role'], $user->roles ) ) {
861 $user->set_role( $user_info['role'] );
862 }
863
864 return $user;
865
866 // Note: only do this for the last email address we are checking (we need
867 // to iterate through them all to make sure one of them isn't approved).
868 } elseif ( 0 === strcasecmp( $user_email, $last_email ) ) {
869 // User isn't an admin, is not blocked, and is not approved.
870 // Add them to the pending list and notify them and their instructor.
871 if ( strlen( $user_email ) > 0 && ! $this->is_email_in_list( $user_email, 'pending' ) ) {
872 $pending_user = array();
873 $pending_user['email'] = mb_strtolower( $user_email );
874 $pending_user['role'] = $approved_role;
875 $pending_user['date_added'] = '';
876 array_push( $auth_settings_access_users_pending, $pending_user );
877 update_option( 'auth_settings_access_users_pending', $auth_settings_access_users_pending );
878
879 // Create strings used in the email notification.
880 $site_name = get_bloginfo( 'name' );
881 $site_url = get_bloginfo( 'url' );
882 $authorizer_options_url = $auth_settings['advanced_admin_menu'] === 'settings' ? admin_url( 'options-general.php?page=authorizer' ) : admin_url( '?page=authorizer' );
883
884 // Notify users with the role specified in "Which role should
885 // receive email notifications about pending users?".
886 if ( strlen( $auth_settings['access_role_receive_pending_emails'] ) > 0 ) {
887 foreach ( get_users( array( 'role' => $auth_settings['access_role_receive_pending_emails'] ) ) as $user_recipient ) {
888 wp_mail(
889 $user_recipient->user_email,
890 sprintf(
891 /* TRANSLATORS: 1: User email 2: Name of site */
892 __( 'Action required: Pending user %1$s at %2$s', 'authorizer' ),
893 $pending_user['email'],
894 $site_name
895 ),
896 sprintf(
897 /* TRANSLATORS: 1: Name of site 2: URL of site 3: URL of authorizer */
898 __( "A new user has tried to access the %1\$s site you manage at:\n%2\$s\n\nPlease log in to approve or deny their request:\n%3\$s\n", 'authorizer' ),
899 $site_name,
900 $site_url,
901 $authorizer_options_url
902 )
903 );
904 }
905 }
906 }
907
908 // Notify user about pending status and return without authenticating them.
909 $redirect_to = ! empty( $_REQUEST['redirect_to'] ) ? $_REQUEST['redirect_to'] : home_url();
910 $page_title = get_bloginfo( 'name' ) . ' - Access Pending';
911 $error_message =
912 apply_filters( 'the_content', $auth_settings['access_pending_redirect_to_message'] ) .
913 '<hr />' .
914 '<p style="text-align: center;">' .
915 '<a class="button" href="' . wp_logout_url( $redirect_to ) . '">' .
916 __( 'Back', 'authorizer' ) .
917 '</a></p>';
918 update_option( 'auth_settings_advanced_login_error', $error_message );
919 wp_die( $error_message, $page_title );
920 }
921 }
922
923 // Sanity check: if we made it here without returning, something has gone wrong.
924 return new WP_Error( 'invalid_login', __( 'Invalid login attempted.', 'authorizer' ) );
925
926 }
927
928
929 /**
930 * Verify the Google login and set a session token.
931 *
932 * Flow: "Sign in with Google" button clicked; JS Google library
933 * called; JS function signInCallback() fired with results from Google;
934 * signInCallback() posts code and nonce (via AJAX) to this function;
935 * This function checks the token using the Google PHP library, and
936 * saves it to a session variable if it's authentic; control passes
937 * back to signInCallback(), which will reload the current page
938 * (wp-login.php) on success; wp-login.php reloads; custom_authenticate
939 * hooked into authenticate action fires again, and
940 * custom_authenticate_google() runs to verify the token; once verified
941 * custom_authenticate proceeds as normal with the google email address
942 * as a successfully authenticated external user.
943 *
944 * @return void, but die with the value to return to the success() function in AJAX call signInCallback()
945 */
946 function ajax_process_google_login() {
947 $nonce = array_key_exists( 'nonce', $_POST ) ? $_POST['nonce'] : '';
948 $code = array_key_exists( 'code', $_POST ) ? $_POST['code'] : null;
949
950 // Nonce check.
951 if ( ! wp_verify_nonce( $nonce, 'google_csrf_nonce' ) ) {
952 return '';
953 }
954
955 // Grab plugin settings.
956 $auth_settings = $this->get_plugin_options( SINGLE_ADMIN, 'allow override' );
957
958 // Add Google API PHP Client.
959 // @see https://github.com/google/google-api-php-client branch:v1-master
960 require_once dirname( __FILE__ ) . '/vendor/google-api-php-client/src/Google/autoload.php';
961
962 // Build the Google Client.
963 $client = new Google_Client();
964 $client->setApplicationName( 'WordPress' );
965 $client->setClientId( $auth_settings['google_clientid'] );
966 $client->setClientSecret( $auth_settings['google_clientsecret'] );
967 $client->setRedirectUri( 'postmessage' );
968
969 // If the hosted domain parameter is set, restrict logins to that domain.
970 // Note: Will have to upgrade to google-api-php-client v2 or higher for
971 // this to function server-side; it's not complete in v1, so this check
972 // is performed manually below.
973 // if ( array_key_exists( 'google_hosteddomain', $auth_settings ) && strlen( $auth_settings['google_hosteddomain'] ) > 0 ) {
974 // $google_hosteddomains = explode( "\n", str_replace( "\r", '', $auth_settings['google_hosteddomain'] ) );
975 // $google_hosteddomain = trim( $google_hosteddomains[0] );
976 // $client->setHostedDomain( $google_hosteddomain );
977 // }
978
979 // Get one time use token (if it doesn't exist, we'll create one below)
980 session_start();
981 $token = array_key_exists( 'token', $_SESSION ) ? json_decode( $_SESSION['token'] ) : null;
982
983 if ( empty( $token ) ) {
984 // Exchange the OAuth 2.0 authorization code for user credentials.
985 $client->authenticate( $code );
986 $token = json_decode( $client->getAccessToken() );
987
988 // Store the token in the session for later use.
989 $_SESSION['token'] = json_encode( $token );
990
991 $response = "Successfully authenticated.";
992 } else {
993 $client->setAccessToken( json_encode( $token ) );
994
995 $response = 'Already authenticated.';
996 }
997
998 die( $response );
999 }
1000
1001
1002 /**
1003 * Validate this user's credentials against Google.
1004 *
1005 * @param array $auth_settings Plugin settings
1006 * @return [mixed] Array containing email, authenticated_by,
1007 * first_name, last_name, and username
1008 * strings for the successfully authenticated
1009 * user, or WP_Error() object on failure,
1010 * or null if not attempting a google login.
1011 */
1012 private function custom_authenticate_google( $auth_settings ) {
1013 // Move on if Google auth hasn't been requested here.
1014 if ( empty( $_GET['external'] ) || $_GET['external'] !== 'google' ) {
1015 return null;
1016 }
1017
1018 // Get one time use token
1019 session_start();
1020 $token = array_key_exists( 'token', $_SESSION ) ? json_decode( $_SESSION['token'] ) : null;
1021
1022 // No token, so this is not a succesful Google login.
1023 if ( is_null( $token ) ) {
1024 return null;
1025 }
1026
1027 // Add Google API PHP Client.
1028 // @see https://github.com/google/google-api-php-client branch:v1-master
1029 require_once dirname( __FILE__ ) . '/vendor/google-api-php-client/src/Google/autoload.php';
1030
1031 // Build the Google Client.
1032 $client = new Google_Client();
1033 $client->setApplicationName( 'WordPress' );
1034 $client->setClientId( $auth_settings['google_clientid'] );
1035 $client->setClientSecret( $auth_settings['google_clientsecret'] );
1036 $client->setRedirectUri( 'postmessage' );
1037
1038 // If the hosted domain parameter is set, restrict logins to that domain.
1039 // Note: Will have to upgrade to google-api-php-client v2 or higher for
1040 // this to function server-side; it's not complete in v1, so this check
1041 // is performed manually below.
1042 // if ( array_key_exists( 'google_hosteddomain', $auth_settings ) && strlen( $auth_settings['google_hosteddomain'] ) > 0 ) {
1043 // $google_hosteddomains = explode( "\n", str_replace( "\r", '', $auth_settings['google_hosteddomain'] ) );
1044 // $google_hosteddomain = trim( $google_hosteddomains[0] );
1045 // $client->setHostedDomain( $google_hosteddomain );
1046 // }
1047
1048 // Verify this is a successful Google authentication
1049 try {
1050 $ticket = $client->verifyIdToken( $token->id_token, $auth_settings['google_clientid'] );
1051 } catch ( Google_Auth_Exception $e ) {
1052 // Invalid ticket, so this in not a successful Google login.
1053 return new WP_Error( 'invalid_google_login', __( 'Invalid Google credentials provided.', 'authorizer' ) );
1054 }
1055
1056 // Invalid ticket, so this in not a successful Google login.
1057 if ( ! $ticket ) {
1058 return new WP_Error( 'invalid_google_login', __( 'Invalid Google credentials provided.', 'authorizer' ) );
1059 }
1060
1061 // Get email address
1062 $attributes = $ticket->getAttributes();
1063 $email = mb_strtolower( $attributes['payload']['email'] );
1064 $email_domain = substr( strrchr( $email, '@' ), 1 );
1065 $username = current( explode( '@', $email ) );
1066
1067 // Fail if hd param is set and the logging in user's email address doesn't
1068 // match the allowed hosted domain.
1069 // See: https://developers.google.com/identity/protocols/OpenIDConnect#hd-param
1070 // See: https://github.com/google/google-api-php-client/blob/v1-master/src/Google/Client.php#L407-L416
1071 // Note: Will have to upgrade to google-api-php-client v2 or higher for
1072 // this to function server-side; it's not complete in v1, so this check
1073 // is only performed here.
1074 if ( array_key_exists( 'google_hosteddomain', $auth_settings ) && strlen( $auth_settings['google_hosteddomain'] ) > 0 ) {
1075 // Allow multiple whitelisted domains.
1076 $google_hosteddomains = explode( "\n", str_replace( "\r", '', $auth_settings['google_hosteddomain'] ) );
1077 if ( ! in_array( $email_domain, $google_hosteddomains ) ) {
1078 $this->custom_logout();
1079 return new WP_Error( 'invalid_google_login', __( 'Google credentials do not match the allowed hosted domain', 'authorizer' ) );
1080 }
1081 }
1082
1083 return array(
1084 'email' => $email,
1085 'username' => $username,
1086 'first_name' => '',
1087 'last_name' => '',
1088 'authenticated_by' => 'google',
1089 'google_attributes' => $attributes,
1090 );
1091 }
1092
1093
1094 /**
1095 * Validate this user's credentials against CAS.
1096 *
1097 * @param array $auth_settings Plugin settings
1098 * @return [mixed] Array containing 'email' and 'authenticated_by'
1099 * strings for the successfully authenticated
1100 * user, or WP_Error() object on failure,
1101 * or null if not attempting a CAS login.
1102 */
1103 private function custom_authenticate_cas( $auth_settings ) {
1104 // Move on if CAS hasn't been requested here.
1105 if ( empty( $_GET['external'] ) || $_GET['external'] !== 'cas' ) {
1106 return null;
1107 }
1108
1109 // Get the CAS server version (default to SAML_VERSION_1_1).
1110 // See: https://developer.jasig.org/cas-clients/php/1.3.4/docs/api/group__public.html
1111 $cas_version = SAML_VERSION_1_1;
1112 if ( $auth_settings['cas_version'] === 'CAS_VERSION_3_0' ) {
1113 $cas_version = CAS_VERSION_3_0;
1114 } elseif ( $auth_settings['cas_version'] === 'CAS_VERSION_2_0' ) {
1115 $cas_version = CAS_VERSION_2_0;
1116 } elseif ( $auth_settings['cas_version'] === 'CAS_VERSION_1_0' ) {
1117 $cas_version = CAS_VERSION_1_0;
1118 }
1119
1120 // Set the CAS client configuration
1121 phpCAS::client( $cas_version, $auth_settings['cas_host'], intval( $auth_settings['cas_port'] ), $auth_settings['cas_path'] );
1122
1123 // Update server certificate bundle if it doesn't exist or is older
1124 // than 6 months, then use it to ensure CAS server is legitimate.
1125 // Note: only try to update if the system has the php_openssl extension.
1126 $cacert_url = 'https://curl.haxx.se/ca/cacert.pem';
1127 $cacert_path = plugin_dir_path( __FILE__ ) . 'vendor/cacert.pem';
1128 $time_180_days = 180 * 24 * 60 * 60; // days * hours * minutes * seconds
1129 $time_180_days_ago = time() - $time_180_days;
1130 if (
1131 extension_loaded( 'openssl' ) &&
1132 ( ! file_exists( $cacert_path ) || filemtime( $cacert_path ) < $time_180_days_ago )
1133 ) {
1134 // Get new cacert.pem file from https://curl.haxx.se/ca/cacert.pem.
1135 $response = wp_safe_remote_get( $cacert_url );
1136 if (
1137 is_wp_error( $response ) ||
1138 200 !== wp_remote_retrieve_response_code( $response ) ||
1139 ! array_key_exists( 'body', $response )
1140 ) {
1141 new WP_Error( 'cannot_update_cacert', __( 'Unable to update outdated server certificates from https://curl.haxx.se/ca/cacert.pem.', 'authorizer' ) );
1142 }
1143 $cacert_contents = $response['body'];
1144
1145 // Write out the updated certs to the plugin directory.
1146 file_put_contents( $cacert_path, $cacert_contents );
1147 }
1148 phpCAS::setCasServerCACert( $cacert_path );
1149
1150 // Set the CAS service URL (including the redirect URL for WordPress when it comes back from CAS).
1151 $cas_service_url = site_url( '/wp-login.php?external=cas' );
1152 $login_querystring = array(); parse_str( $_SERVER['QUERY_STRING'], $login_querystring );
1153 if ( isset( $login_querystring['redirect_to'] ) ) {
1154 $cas_service_url .= '&redirect_to=' . urlencode( $login_querystring['redirect_to'] );
1155 }
1156 phpCAS::setFixedServiceURL( $cas_service_url );
1157
1158 // Authenticate against CAS
1159 try {
1160 phpCAS::forceAuthentication();
1161 } catch ( CAS_AuthenticationException $e ) {
1162 // CAS server threw an error in isAuthenticated(), potentially because
1163 // the cached ticket is outdated. Try renewing the authentication.
1164 error_log( __( 'CAS server returned an Authentication Exception. Details:', 'authorizer' ) );
1165 error_log( print_r( $e, true ) );
1166
1167 // CAS server is throwing errors on this login, so try logging the
1168 // user out of CAS and redirecting them to the login page.
1169 phpCAS::logoutWithRedirectService( wp_login_url() );
1170 die();
1171 }
1172
1173 // Get username (as specified by the CAS server).
1174 $username = phpCAS::getUser();
1175
1176 // Get email that successfully authenticated against the external service (CAS).
1177 $externally_authenticated_email = strtolower( $username );
1178 if ( ! filter_var( $externally_authenticated_email, FILTER_VALIDATE_EMAIL ) ) {
1179 // If we can't get the user's email address from a CAS attribute,
1180 // try to guess the domain from the CAS server hostname. This will only
1181 // be used if we can't discover the email address from CAS attributes.
1182 $domain_guess = preg_match( '/[^.]*\.[^.]*$/', $auth_settings['cas_host'], $matches ) === 1 ? $matches[0] : '';
1183 $externally_authenticated_email = mb_strtolower( $username ) . '@' . $domain_guess;
1184 }
1185
1186 // Retrieve the user attributes (e.g., email address, first name, last name) from the CAS server.
1187 $cas_attributes = phpCAS::getAttributes();
1188
1189 // Get user email if it is specified in another field.
1190 if ( array_key_exists( 'cas_attr_email', $auth_settings ) && strlen( $auth_settings['cas_attr_email'] ) > 0 ) {
1191 // If the email attribute starts with an at symbol (@), assume that the
1192 // email domain is manually entered there (instead of a reference to a
1193 // CAS attribute), and combine that with the username to create the email.
1194 // Otherwise, look up the CAS attribute for email.
1195 if ( substr( $auth_settings['cas_attr_email'], 0, 1 ) === '@' ) {
1196 $externally_authenticated_email = mb_strtolower( $username . $auth_settings['cas_attr_email'] );
1197 } elseif (
1198 // If a CAS attribute has been specified as containing the email address, use that instead.
1199 // Email attribute can be a string or an array of strings.
1200 array_key_exists( $auth_settings['cas_attr_email'], $cas_attributes ) && (
1201 (
1202 is_array( $cas_attributes[$auth_settings['cas_attr_email']] ) &&
1203 count( $cas_attributes[$auth_settings['cas_attr_email']] ) > 0
1204 ) || (
1205 is_string( $cas_attributes[$auth_settings['cas_attr_email']] ) &&
1206 strlen( $cas_attributes[$auth_settings['cas_attr_email']] ) > 0
1207 )
1208 )
1209 ) {
1210 $externally_authenticated_email = mb_strtolower( $cas_attributes[$auth_settings['cas_attr_email']] );
1211 }
1212 }
1213
1214 // Get user first name and last name.
1215 $first_name = array_key_exists( 'cas_attr_first_name', $auth_settings ) && strlen( $auth_settings['cas_attr_first_name'] ) > 0 && array_key_exists( $auth_settings['cas_attr_first_name'], $cas_attributes ) && strlen( $cas_attributes[$auth_settings['cas_attr_first_name']] ) > 0 ? $cas_attributes[$auth_settings['cas_attr_first_name']] : '';
1216 $last_name = array_key_exists( 'cas_attr_last_name', $auth_settings ) && strlen( $auth_settings['cas_attr_last_name'] ) > 0 && array_key_exists( $auth_settings['cas_attr_last_name'], $cas_attributes ) && strlen( $cas_attributes[$auth_settings['cas_attr_last_name']] ) > 0 ? $cas_attributes[$auth_settings['cas_attr_last_name']] : '';
1217
1218 return array(
1219 'email' => $externally_authenticated_email,
1220 'username' => $username,
1221 'first_name' => $first_name,
1222 'last_name' => $last_name,
1223 'authenticated_by' => 'cas',
1224 'cas_attributes' => $cas_attributes,
1225 );
1226 }
1227
1228
1229 /**
1230 * Validate this user's credentials against LDAP.
1231 *
1232 * @param array $auth_settings Plugin settings
1233 * @param string $username Attempted username from authenticate action
1234 * @param string $password Attempted password from authenticate action
1235 * @return [mixed] Array containing 'email' and 'authenticated_by'
1236 * strings for the successfully authenticated
1237 * user, or WP_Error() object on failure,
1238 * or null if skipping LDAP auth and falling back to WP auth.
1239 */
1240 private function custom_authenticate_ldap( $auth_settings, $username, $password ) {
1241 // Get the FQDN from the LDAP search base domain components (dc). For
1242 // example, ou=people,dc=example,dc=edu,dc=uk would yield user@example.edu.uk
1243 $search_base_components = explode( ',', trim( $auth_settings['ldap_search_base'] ) );
1244 $domain = array();
1245 foreach ( $search_base_components as $search_base_component ) {
1246 $component = explode( '=', $search_base_component );
1247 if ( count( $component ) === 2 && $component[0] === 'dc' ) {
1248 $domain[] = $component[1];
1249 }
1250 }
1251 $domain = implode( '.', $domain );
1252
1253 // If we can't get the logging in user's email address from an LDAP attribute,
1254 // just use the domain from the LDAP host. This will only be used if we
1255 // can't discover the email address from an LDAP attribute.
1256 if ( empty( $domain ) ) {
1257 $domain = preg_match( '/[^.]*\.[^.]*$/', $auth_settings['ldap_host'], $matches ) === 1 ? $matches[0] : '';
1258 }
1259
1260 // remove @domain if it exists in the username (i.e., if user entered their email)
1261 $username = str_replace( '@' . $domain, '', $username );
1262
1263 // Fail silently (fall back to WordPress authentication) if both username
1264 // and password are empty (this will be the case when visiting wp-login.php
1265 // for the first time, or when clicking the Log In button without filling
1266 // out either field.
1267 if ( empty( $username ) && empty( $password ) ) {
1268 return null;
1269 }
1270
1271 // Fail with error message if username or password is blank.
1272 if ( empty( $username ) ) {
1273 return new WP_Error( 'empty_username', __( 'You must provide a username or email.', 'authorizer' ) );
1274 }
1275 if ( empty( $password ) ) {
1276 return new WP_Error( 'empty_password', __( 'You must provide a password.', 'authorizer' ) );
1277 }
1278
1279 // If php5-ldap extension isn't installed on server, fall back to WP auth.
1280 if ( ! function_exists( 'ldap_connect' ) ) {
1281 return null;
1282 }
1283
1284 // Authenticate against LDAP using options provided in plugin settings.
1285 $result = false;
1286 $ldap_user_dn = '';
1287 $first_name = '';
1288 $last_name = '';
1289 $email = '';
1290
1291 // Construct LDAP connection parameters. ldap_connect() takes either a
1292 // hostname or a full LDAP URI as its first parameter (works with OpenLDAP
1293 // 2.x.x or later). If it's an LDAP URI, the second parameter, $port, is
1294 // ignored, and port must be specified in the full URI. An LDAP URI is of
1295 // the form ldap://hostname:port or ldaps://hostname:port.
1296 $ldap_host = $auth_settings['ldap_host'];
1297 $ldap_port = intval( $auth_settings['ldap_port'] );
1298 $parsed_host = parse_url( $ldap_host );
1299 // Fail (fall back to WordPress auth) if invalid host is specified.
1300 if ( $parsed_host === false ) {
1301 return null;
1302 }
1303 // If a scheme is in the LDAP host, use full LDAP URI instead of just hostname.
1304 if ( array_key_exists( 'scheme', $parsed_host ) ) {
1305 // If the port isn't in the LDAP URI, use the one in the LDAP port field.
1306 if ( ! array_key_exists( 'port', $parsed_host ) ) {
1307 $parsed_host['port'] = $ldap_port;
1308 }
1309 $ldap_host = $this->build_url( $parsed_host );
1310 }
1311
1312 // Establish LDAP connection.
1313 $ldap = ldap_connect( $ldap_host, $ldap_port );
1314 ldap_set_option( $ldap, LDAP_OPT_PROTOCOL_VERSION, 3 );
1315 if ( $auth_settings['ldap_tls'] == 1 ) {
1316 if( ! ldap_start_tls( $ldap ) ) {
1317 return null;
1318 }
1319 }
1320
1321 // Set bind credentials; attempt an anonymous bind if not provided.
1322 $bind_rdn = NULL;
1323 $bind_password = NULL;
1324 if ( strlen( $auth_settings['ldap_user'] ) > 0 ) {
1325 $bind_rdn = $auth_settings['ldap_user'];
1326 $bind_password = $this->decrypt( $auth_settings['ldap_password'] );
1327 }
1328
1329 // Attempt LDAP bind.
1330 $result = @ldap_bind( $ldap, $bind_rdn, stripslashes( $bind_password ) );
1331 if ( ! $result ) {
1332 // Can't connect to LDAP, so fall back to WordPress authentication.
1333 return null;
1334 }
1335 // Look up the bind DN (and first/last name) of the user trying to
1336 // log in by performing an LDAP search for the login username in
1337 // the field specified in the LDAP settings. This setup is common.
1338 $ldap_attributes_to_retrieve = array( 'dn' );
1339 if ( array_key_exists( 'ldap_attr_first_name', $auth_settings ) && strlen( $auth_settings['ldap_attr_first_name'] ) > 0 ) {
1340 array_push( $ldap_attributes_to_retrieve, $auth_settings['ldap_attr_first_name'] );
1341 }
1342 if ( array_key_exists( 'ldap_attr_last_name', $auth_settings ) && strlen( $auth_settings['ldap_attr_last_name'] ) > 0 ) {
1343 array_push( $ldap_attributes_to_retrieve, $auth_settings['ldap_attr_last_name'] );
1344 }
1345 if ( array_key_exists( 'ldap_attr_email', $auth_settings ) && strlen( $auth_settings['ldap_attr_email'] ) > 0 && substr( $auth_settings['ldap_attr_email'], 0, 1 ) !== '@' ) {
1346 array_push( $ldap_attributes_to_retrieve, mb_strtolower( $auth_settings['ldap_attr_email'] ) );
1347 }
1348 $ldap_search = ldap_search(
1349 $ldap,
1350 $auth_settings['ldap_search_base'],
1351 "(" . $auth_settings['ldap_uid'] . "=" . $username . ")",
1352 $ldap_attributes_to_retrieve
1353 );
1354 $ldap_entries = ldap_get_entries( $ldap, $ldap_search );
1355
1356 // If we didn't find any users in ldap, fall back to WordPress authentication.
1357 if ( $ldap_entries['count'] < 1 ) {
1358 return null;
1359 }
1360
1361 // Get the bind dn and first/last names; if there are multiple results returned, just get the last one.
1362 for ( $i = 0; $i < $ldap_entries['count']; $i++ ) {
1363 $ldap_user_dn = $ldap_entries[$i]['dn'];
1364
1365 // Get user first name and last name.
1366 $ldap_attr_first_name = array_key_exists( 'ldap_attr_first_name', $auth_settings ) ? mb_strtolower( $auth_settings['ldap_attr_first_name'] ) : '';
1367 if ( strlen( $ldap_attr_first_name ) > 0 && array_key_exists( $ldap_attr_first_name, $ldap_entries[$i] ) && $ldap_entries[$i][$ldap_attr_first_name]['count'] > 0 && strlen( $ldap_entries[$i][$ldap_attr_first_name][0] ) > 0 ) {
1368 $first_name = $ldap_entries[$i][$ldap_attr_first_name][0];
1369 }
1370 $ldap_attr_last_name = array_key_exists( 'ldap_attr_last_name', $auth_settings ) ? mb_strtolower( $auth_settings['ldap_attr_last_name'] ) : '';
1371 if ( strlen( $ldap_attr_last_name ) > 0 && array_key_exists( $ldap_attr_last_name, $ldap_entries[$i] ) && $ldap_entries[$i][$ldap_attr_last_name]['count'] > 0 && strlen( $ldap_entries[$i][$ldap_attr_last_name][0] ) > 0 ) {
1372 $last_name = $ldap_entries[$i][$ldap_attr_last_name][0];
1373 }
1374 // Get user email if it is specified in another field.
1375 $ldap_attr_email = array_key_exists( 'ldap_attr_email', $auth_settings ) ? mb_strtolower( $auth_settings['ldap_attr_email'] ) : '';
1376 if ( strlen( $ldap_attr_email ) > 0 ) {
1377 // If the email attribute starts with an at symbol (@), assume that the
1378 // email domain is manually entered there (instead of a reference to an
1379 // LDAP attribute), and combine that with the username to create the email.
1380 // Otherwise, look up the LDAP attribute for email.
1381 if ( substr( $ldap_attr_email, 0, 1 ) === '@' ) {
1382 $email = mb_strtolower( $username . $ldap_attr_email );
1383 } elseif ( array_key_exists( $ldap_attr_email, $ldap_entries[$i] ) && $ldap_entries[$i][$ldap_attr_email]['count'] > 0 && strlen( $ldap_entries[$i][$ldap_attr_email][0] ) > 0 ) {
1384 $email = mb_strtolower( $ldap_entries[$i][$ldap_attr_email][0] );
1385 }
1386 }
1387 }
1388
1389 $result = @ldap_bind( $ldap, $ldap_user_dn, stripslashes( $password ) );
1390 if ( ! $result ) {
1391 // We have a real ldap user, but an invalid password. Pass
1392 // through to wp authentication after failing LDAP (since
1393 // this could be a local account that happens to be the
1394 // same name as an LDAP user).
1395 return null;
1396 }
1397
1398 // User successfully authenticated against LDAP, so set the relevant variables.
1399 $externally_authenticated_email = mb_strtolower( $username . '@' . $domain );
1400
1401 // If an LDAP attribute has been specified as containing the email address, use that instead.
1402 if ( strlen( $email ) > 0 ) {
1403 $externally_authenticated_email = mb_strtolower( $email );
1404 }
1405
1406 return array(
1407 'email' => $externally_authenticated_email,
1408 'username' => $username,
1409 'first_name' => $first_name,
1410 'last_name' => $last_name,
1411 'authenticated_by' => 'ldap',
1412 'ldap_attributes' => $ldap_entries,
1413 );
1414 }
1415
1416
1417 /**
1418 * Log out of the attached external service.
1419 *
1420 * @return void
1421 */
1422 public function custom_logout() {
1423 // Grab plugin settings.
1424 $auth_settings = $this->get_plugin_options( SINGLE_ADMIN, 'allow override' );
1425
1426 // Reset option containing old error messages.
1427 delete_option( 'auth_settings_advanced_login_error' );
1428
1429 if ( session_id() == '' ) {
1430 session_start();
1431 }
1432
1433 $current_user_authenticated_by = get_user_meta( get_current_user_id(), 'authenticated_by', true );
1434
1435 // If logged in to CAS, Log out of CAS.
1436 if ( $current_user_authenticated_by === 'cas' && $auth_settings['cas'] === '1' ) {
1437 if ( ! array_key_exists( 'PHPCAS_CLIENT', $GLOBALS ) || ! array_key_exists( 'phpCAS', $_SESSION ) ) {
1438
1439 // Get the CAS server version (default to SAML_VERSION_1_1).
1440 // See: https://developer.jasig.org/cas-clients/php/1.3.4/docs/api/group__public.html
1441 $cas_version = SAML_VERSION_1_1;
1442 if ( $auth_settings['cas_version'] === 'CAS_VERSION_3_0' ) {
1443 $cas_version = CAS_VERSION_3_0;
1444 } elseif ( $auth_settings['cas_version'] === 'CAS_VERSION_2_0' ) {
1445 $cas_version = CAS_VERSION_2_0;
1446 } elseif ( $auth_settings['cas_version'] === 'CAS_VERSION_1_0' ) {
1447 $cas_version = CAS_VERSION_1_0;
1448 }
1449
1450 // Set the CAS client configuration if it hasn't been set already.
1451 phpCAS::client( $cas_version, $auth_settings['cas_host'], intval( $auth_settings['cas_port'] ), $auth_settings['cas_path'] );
1452 // Restrict logout request origin to the CAS server only (prevent DDOS).
1453 phpCAS::handleLogoutRequests( true, array( $auth_settings['cas_host'] ) );
1454 }
1455 if ( phpCAS::isAuthenticated() ) {
1456 // Redirect to home page, or specified page if it's been provided.
1457 $redirect_to = site_url( '/' );
1458 if ( array_key_exists( 'redirect_to', $_REQUEST ) && filter_var( $_REQUEST['redirect_to'], FILTER_VALIDATE_URL ) !== false ) {
1459 $redirect_to = $_REQUEST['redirect_to'];
1460 }
1461
1462 phpCAS::logoutWithRedirectService( $redirect_to );
1463 }
1464 }
1465
1466 // If session token set, log out of Google.
1467 if ( $current_user_authenticated_by === 'google' || array_key_exists( 'token', $_SESSION ) ) {
1468 $token = json_decode( $_SESSION['token'] )->access_token;
1469
1470 // Add Google API PHP Client.
1471 // @see https://github.com/google/google-api-php-client branch:v1-master
1472 require_once dirname( __FILE__ ) . '/vendor/google-api-php-client/src/Google/autoload.php';
1473
1474 // Build the Google Client.
1475 $client = new Google_Client();
1476 $client->setApplicationName( 'WordPress' );
1477 $client->setClientId( $auth_settings['google_clientid'] );
1478 $client->setClientSecret( $auth_settings['google_clientsecret'] );
1479 $client->setRedirectUri( 'postmessage' );
1480
1481 // Revoke the token
1482 $client->revokeToken( $token );
1483
1484 // Remove the credentials from the user's session.
1485 unset( $_SESSION['token'] );
1486 }
1487
1488 }
1489
1490
1491
1492 /**
1493 * ***************************
1494 * Access Restriction
1495 * ***************************
1496 */
1497
1498
1499
1500 /**
1501 * Restrict access to WordPress site based on settings (everyone, logged_in_users).
1502 * Hook: parse_request http://codex.wordpress.org/Plugin_API/Action_Reference/parse_request
1503 *
1504 * @param array $wp WordPress object.
1505 *
1506 * @return void
1507 */
1508 public function restrict_access( $wp ) {
1509 // Grab plugin settings.
1510 $auth_settings = $this->get_plugin_options( SINGLE_ADMIN, 'allow override' );
1511
1512 // Grab current user.
1513 $current_user = wp_get_current_user();
1514
1515 $has_access = (
1516 // Always allow access if WordPress is installing
1517 ( defined( 'WP_INSTALLING' ) && isset( $_GET['key'] ) ) ||
1518 // Always allow access to admins
1519 ( current_user_can( 'create_users' ) ) ||
1520 // Allow access if option is set to 'everyone'
1521 ( $auth_settings['access_who_can_view'] == 'everyone' ) ||
1522 // Allow access to approved external users and logged in users if option is set to 'logged_in_users'
1523 ( $auth_settings['access_who_can_view'] == 'logged_in_users' && $this->is_user_logged_in_and_blog_user() && $this->is_email_in_list( $current_user->user_email, 'approved' ) ) ||
1524 // Allow access for requests to /wp-json/oauth1 so oauth clients can authenticate to use the REST API
1525 ( property_exists( $wp, 'matched_query' ) && stripos( $wp->matched_query, "rest_oauth1=" ) === 0 ) ||
1526 // Allow access for non-GET requests to /wp-json/*, since REST API authentication already covers them
1527 ( property_exists( $wp, 'matched_query' ) && stripos( $wp->matched_query, "rest_route=" ) === 0 && $_SERVER['REQUEST_METHOD'] !== 'GET' ) ||
1528 // Allow access for GET requests to /wp-json/ (root), since REST API discovery calls rely on this
1529 ( property_exists( $wp, 'matched_query' ) && $wp->matched_query === 'rest_route=/' )
1530 // Note that GET requests to a rest endpoint will be restricted by authorizer. In that case, error messages will be returned as JSON.
1531 );
1532
1533 /**
1534 * Developers can use the `authorizer_has_access` filter
1535 * to override restricted access on certain pages. Note that the
1536 * restriction checks happens before WordPress executes any queries, so
1537 * use the global `$wp` variable to investigate what the visitor is
1538 * trying to load.
1539 *
1540 * For example, to unblock an RSS feed, place the following PHP code in
1541 * the theme's functions.php file or in a simple plug-in:
1542 *
1543 * function my_rsa_feed_access_override( $has_access ) {
1544 * global $wp;
1545 * // check query variables to see if this is the feed
1546 * if ( ! empty( $wp->query_vars['feed'] ) )
1547 * $has_access = true;
1548 * return $has_access;
1549 * }
1550 * add_filter( 'authorizer_has_access', 'my_rsa_feed_access_override' );
1551 */
1552 if ( apply_filters( 'authorizer_has_access', $has_access, $wp ) === true ) {
1553 // Turn off the public notice about browsing anonymously
1554 update_option( 'auth_settings_advanced_public_notice', false );
1555
1556 // We've determined that the current user has access, so simply return to grant access.
1557 return $wp;
1558 }
1559
1560 // Allow HEAD requests to the root (usually discovery from a REST client).
1561 if ( $_SERVER['REQUEST_METHOD'] === 'HEAD' && empty( $wp->request ) && empty( $wp->matched_query ) ) {
1562 return $wp;
1563 }
1564
1565 // We've determined that the current user doesn't have access, so we deal with them now.
1566
1567 // Fringe case: In a multisite, a user of a different blog can successfully
1568 // log in, but they aren't on the 'approved' whitelist for this blog.
1569 // If that's the case, add them to the pending list for this blog.
1570 if ( is_multisite() && is_user_logged_in() && ! $has_access ) {
1571 $current_user = wp_get_current_user();
1572
1573 // Check user access; block if not, add them to pending list if open, let them through otherwise.
1574 $result = $this->check_user_access( $current_user, array( $current_user->user_email ) );
1575 }
1576
1577 // Check to see if the requested page is public. If so, show it.
1578 $current_page_name = property_exists( $wp, 'query_vars' ) && array_key_exists( 'name', $wp->query_vars ) && strlen( $wp->query_vars['name'] ) > 0 ? $wp->query_vars['name'] : '';
1579 if ( ! $current_page_name ) {
1580 // Different WordPress versions store the page slug in different places; look for it elsewhere.
1581 if ( property_exists( $wp, 'query_vars' ) && array_key_exists( 'pagename', $wp->query_vars ) && strlen( $wp->query_vars['pagename'] ) > 0 ) {
1582 $current_page_name = $wp->query_vars['pagename'];
1583 }
1584 }
1585 $current_page_id = '';
1586 if ( empty( $wp->request ) ) {
1587 $current_page_id = 'home';
1588 } else {
1589 $current_page = get_page_by_path( $current_page_name );
1590 if ( is_object( $current_page ) && isset( $current_page->ID ) ) {
1591 $current_page_id = $current_page->ID;
1592 }
1593 }
1594 if ( ! array_key_exists( 'access_public_pages', $auth_settings ) || ! is_array( $auth_settings['access_public_pages'] ) ) {
1595 $auth_settings['access_public_pages'] = array();
1596 }
1597 if ( in_array( $current_page_id, $auth_settings['access_public_pages'] ) ) {
1598 if ( $auth_settings['access_public_warning'] === 'no_warning' ) {
1599 update_option( 'auth_settings_advanced_public_notice', false );
1600 } else {
1601 update_option( 'auth_settings_advanced_public_notice', true );
1602 }
1603 return $wp;
1604 }
1605
1606 // Check to see if any category assigned to the requested page is public. If so, show it.
1607 $current_page_categories = wp_get_post_categories( $current_page_id, array( 'fields' => 'slugs' ) );
1608 foreach( $current_page_categories as $current_page_category ) {
1609 if ( in_array( 'cat_' . $current_page_category, $auth_settings['access_public_pages'] ) ) {
1610 if ( $auth_settings['access_public_warning'] === 'no_warning' ) {
1611 update_option( 'auth_settings_advanced_public_notice', false );
1612 } else {
1613 update_option( 'auth_settings_advanced_public_notice', true );
1614 }
1615 return $wp;
1616 }
1617 }
1618
1619 // Check to see if this page can't be found. If so, allow showing the 404 page.
1620 if ( strlen( $current_page_name ) > 0 && strlen( $current_page_id ) < 1 ) {
1621 if ( in_array( 'auth_public_404', $auth_settings['access_public_pages'] ) ) {
1622 if ( $auth_settings['access_public_warning'] === 'no_warning' ) {
1623 update_option( 'auth_settings_advanced_public_notice', false );
1624 } else {
1625 update_option( 'auth_settings_advanced_public_notice', true );
1626 }
1627 return $wp;
1628 }
1629
1630 }
1631
1632 // Check to see if the requested category is public. If so, show it.
1633 $current_category_name = property_exists( $wp, 'query_vars' ) && array_key_exists( 'category_name', $wp->query_vars ) && strlen( $wp->query_vars['category_name'] ) > 0 ? $wp->query_vars['category_name'] : '';
1634 if ( $current_category_name ) {
1635 $current_category_name = end( explode( '/', $current_category_name ) );
1636 if ( in_array( 'cat_' . $current_category_name, $auth_settings['access_public_pages'] ) ) {
1637 if ( $auth_settings['access_public_warning'] === 'no_warning' ) {
1638 update_option( 'auth_settings_advanced_public_notice', false );
1639 } else {
1640 update_option( 'auth_settings_advanced_public_notice', true );
1641 }
1642 return $wp;
1643 }
1644 }
1645
1646 // User is denied access, so show them the error message. Render as JSON
1647 // if this is a REST API call; otherwise, show the error message via
1648 // wp_die() (rendered html), or redirect to the login URL.
1649 $current_path = empty( $_SERVER['REQUEST_URI'] ) ? home_url() : $_SERVER['REQUEST_URI'];
1650 if ( property_exists( $wp, 'matched_query' ) && stripos( $wp->matched_query, "rest_route=" ) === 0 && $_SERVER['REQUEST_METHOD'] === 'GET' ) {
1651 wp_send_json( array(
1652 'code' => 'rest_cannot_view',
1653 'message' => strip_tags( $auth_settings['access_redirect_to_message'] ),
1654 'data' => array(
1655 'status' => 401,
1656 ),
1657 ));
1658 } elseif ( $auth_settings['access_redirect'] === 'message' ) {
1659 $page_title = sprintf(
1660 /* TRANSLATORS: %s: Name of blog */
1661 __( '%s - Access Restricted', 'authorizer' ),
1662 get_bloginfo( 'name' )
1663 );
1664 $error_message =
1665 apply_filters( 'the_content', $auth_settings['access_redirect_to_message'] ) .
1666 '<hr />' .
1667 '<p style="text-align: center;margin-bottom: -15px;">' .
1668 '<a class="button" href="' . wp_login_url( $current_path ) . '">' .
1669 __( 'Log In', 'authorizer' ) .
1670 '</a></p>';
1671 wp_die( $error_message, $page_title );
1672 } else { // if ( $auth_settings['access_redirect'] === 'login' ) {
1673 wp_redirect( wp_login_url( $current_path ), 302 );
1674 exit;
1675 }
1676
1677 // Sanity check: we should never get here
1678 wp_die( '<p>Access denied.</p>', 'Site Access Restricted' );
1679 }
1680
1681
1682 /**
1683 * On an admin page load, check for edge case (network-approved user who has
1684 * not yet been added to this particular blog in a multisite). Note: we do
1685 * this because check_user_access() runs on the parse_request hook, which
1686 * does not fire on wp-admin pages.
1687 *
1688 * Hook: admin_menu
1689 */
1690 public function init__maybe_add_network_approved_user() {
1691 global $current_user;
1692
1693 // If this is a multisite install and we have a logged in user that's not
1694 // a member of this blog, but is (network) approved, add them to this blog.
1695 if (
1696 is_admin() &&
1697 is_multisite() &&
1698 is_user_logged_in() &&
1699 ! is_user_member_of_blog() &&
1700 $this->is_email_in_list( $current_user->user_email, 'approved' )
1701 ) {
1702 // Get all approved users.
1703 $auth_settings_access_users_approved = $this->sanitize_user_list(
1704 array_merge(
1705 $this->get_plugin_option( 'access_users_approved', SINGLE_ADMIN ),
1706 $this->get_plugin_option( 'access_users_approved', MULTISITE_ADMIN )
1707 )
1708 );
1709
1710 // Get user info (we need user role).
1711 $user_info = $this->get_user_info_from_list(
1712 $current_user->user_email,
1713 $auth_settings_access_users_approved
1714 );
1715
1716 // Add user to blog.
1717 add_user_to_blog( get_current_blog_id(), $current_user->ID, $user_info['role'] );
1718
1719 // Refresh user permissions.
1720 $current_user = new WP_User( $current_user->ID );
1721 }
1722 }
1723
1724
1725
1726 /**
1727 * ***************************
1728 * Login page (wp-login.php)
1729 * ***************************
1730 */
1731
1732
1733
1734 /**
1735 * Add custom error message to login screen.
1736 * Filter: login_errors
1737 */
1738 function show_advanced_login_error( $errors ) {
1739 $error = get_option( 'auth_settings_advanced_login_error' );
1740 delete_option( 'auth_settings_advanced_login_error' );
1741 $errors = ' ' . $error . "<br />\n";
1742 return $errors;
1743 }
1744
1745
1746 /**
1747 * Load external resources for the public-facing site.
1748 */
1749 function auth_public_scripts() {
1750 // Load (and localize) public scripts
1751 $current_path = empty( $_SERVER['REQUEST_URI'] ) ? home_url() : $_SERVER['REQUEST_URI'];
1752 wp_enqueue_script( 'auth_public_scripts', plugins_url( '/js/authorizer-public.js', __FILE__ ), array( 'jquery' ), '2.3.2' );
1753 $auth_localized = array(
1754 'wp_login_url' => wp_login_url( $current_path ),
1755 'public_warning' => get_option( 'auth_settings_advanced_public_notice' ),
1756 'anonymous_notice' => $this->get_plugin_option( 'access_redirect_to_message' ),
1757 'log_in' => esc_html__( 'Log In', 'authorizer' ),
1758 );
1759 wp_localize_script( 'auth_public_scripts', 'auth', $auth_localized );
1760 //update_option( 'auth_settings_advanced_public_notice', false);
1761
1762 // Load public css
1763 wp_register_style( 'authorizer-public-css', plugins_url( 'css/authorizer-public.css', __FILE__ ), array(), '2.3.2' );
1764 wp_enqueue_style( 'authorizer-public-css' );
1765 }
1766
1767
1768 /**
1769 * Enqueue JS scripts and CSS styles appearing on wp-login.php.
1770 *
1771 * @return void
1772 */
1773 function login_enqueue_scripts_and_styles() {
1774 // Grab plugin settings.
1775 $auth_settings = $this->get_plugin_options( SINGLE_ADMIN, 'allow override' );
1776
1777 // Enqueue scripts appearing on wp-login.php.
1778 wp_enqueue_script( 'auth_login_scripts', plugins_url( '/js/authorizer-login.js', __FILE__ ), array( 'jquery' ), '2.3.2' );
1779
1780 // Enqueue styles appearing on wp-login.php.
1781 wp_register_style( 'authorizer-login-css', plugins_url( '/css/authorizer-login.css', __FILE__ ), array(), '2.3.2' );
1782 wp_enqueue_style( 'authorizer-login-css' );
1783
1784 /**
1785 * Developers can use the `authorizer_add_branding_option` filter
1786 * to add a radio button for "Custom WordPress login branding"
1787 * under the "Advanced" tab in Authorizer options. Example:
1788 *
1789 * function my_authorizer_add_branding_option( $branding_options ) {
1790 * $new_branding_option = array(
1791 * 'value' => 'your_brand'
1792 * 'description' => 'Custom Your Brand Login Screen',
1793 * 'css_url' => 'http://url/to/your_brand.css',
1794 * 'js_url' => 'http://url/to/your_brand.js',
1795 * );
1796 * array_push( $branding_options, $new_branding_option );
1797 * return $branding_options;
1798 * }
1799 * add_filter( 'authorizer_add_branding_option', 'my_authorizer_add_branding_option' );
1800 */
1801 $branding_options = array();
1802 $branding_options = apply_filters( 'authorizer_add_branding_option', $branding_options );
1803 foreach ( $branding_options as $branding_option ) {
1804 // Make sure the custom brands have the required values
1805 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 ) ) ) {
1806 continue;
1807 }
1808 if ( $auth_settings['advanced_branding'] === $branding_option['value'] ) {
1809 wp_enqueue_script( 'auth_login_custom_scripts-' . sanitize_title( $branding_option['value'] ), $branding_option['js_url'], array( 'jquery' ), '2.3.2' );
1810 wp_register_style( 'authorizer-login-custom-css-' . sanitize_title( $branding_option['value'] ), $branding_option['css_url'], array(), '2.3.2' );
1811 wp_enqueue_style( 'authorizer-login-custom-css-' . sanitize_title( $branding_option['value'] ) );
1812 }
1813 }
1814
1815 // If we're using Google logins, load those resources.
1816 if ( $auth_settings['google'] === '1' ) {
1817 wp_enqueue_script( 'authorizer-login-custom-google', plugins_url( '/js/authorizer-login-custom_google.js', __FILE__ ), array( 'jquery' ), '2.3.2' ); ?>
1818 <meta name="google-signin-clientid" content="<?php echo $auth_settings['google_clientid']; ?>" />
1819 <meta name="google-signin-scope" content="email" />
1820 <meta name="google-signin-cookiepolicy" content="single_host_origin" />
1821 <?php
1822 }
1823 }
1824
1825
1826 /**
1827 * Load external resources in the footer of the wp-login.php page.
1828 * Run on action hook: login_footer
1829 */
1830 function load_login_footer_js() {
1831 // Grab plugin settings.
1832 $auth_settings = $this->get_plugin_options( SINGLE_ADMIN, 'allow override' ); ?>
1833 <?php if ( $auth_settings['google'] === '1' ): ?>
1834 <script type="text/javascript">
1835 // Reload login page if reauth querystring param exists,
1836 // since reauth interrupts external logins (e.g., google).
1837 if ( location.search.indexOf( 'reauth=1' ) >= 0 ) {
1838 location.href = location.href.replace( 'reauth=1', '' );
1839 }
1840
1841 function auth_update_querystring_param( uri, key, value ) {
1842 var re = new RegExp( '([?&])' + key + '=.*?(&|$)', 'i' );
1843 var separator = uri.indexOf( '?' ) !== -1 ? '&' : '?';
1844 if ( uri.match( re ) ) {
1845 return uri.replace( re, '$1' + key + '=' + value + '$2' );
1846 } else {
1847 return uri + separator + key + '=' + value;
1848 }
1849 }
1850
1851 function signInCallback( authResult ) {
1852 var $ = jQuery;
1853 if ( authResult['status'] && authResult['status']['signed_in'] ) {
1854 // Hide the sign-in button now that the user is authorized, for example:
1855 $( '#googleplus_button' ).attr( 'style', 'display: none' );
1856
1857 // Send the code to the server
1858 var ajaxurl = '<?php echo admin_url( "admin-ajax.php" ); ?>';
1859 $.post(ajaxurl, {
1860 action: 'process_google_login',
1861 'code': authResult['code'],
1862 'nonce': $('#nonce_google_auth-<?php echo $this->get_cookie_value(); ?>' ).val(),
1863 }, function( response ) {
1864 // Handle or verify the server response if necessary.
1865 //console.log( response );
1866
1867 // Reload wp-login.php to continue the authentication process.
1868 var new_href = auth_update_querystring_param( location.href, 'external', 'google' );
1869 if ( location.href === new_href ) {
1870 location.reload();
1871 } else {
1872 location.href = new_href;
1873 }
1874 });
1875 } else {
1876 // Update the app to reflect a signed out user
1877 // Possible error values:
1878 // "user_signed_out" - User is signed-out
1879 // "access_denied" - User denied access to your app
1880 // "immediate_failed" - Could not automatically log in the user
1881 //console.log('Sign-in state: ' + authResult['error']);
1882
1883 // If user denies access, reload the login page.
1884 if ( authResult['error'] === 'access_denied' || authResult['error'] === 'user_signed_out' ) {
1885 window.location.reload();
1886 }
1887 }
1888 }
1889 </script>
1890 <?php endif;
1891 }
1892
1893
1894 /**
1895 * Create links for any external authentication services that are enabled.
1896 */
1897 function login_form_add_external_service_links() {
1898 // Grab plugin settings.
1899 $auth_settings = $this->get_plugin_options( SINGLE_ADMIN, 'allow override' ); ?>
1900 <div id="auth-external-service-login">
1901 <?php if ( $auth_settings['google'] === '1' ): ?>
1902 <p><a id="googleplus_button" class="button button-primary button-external button-google"><span class="dashicons dashicons-googleplus"></span><span class="label"><?php _e( 'Sign in with Google', 'authorizer' ); ?></span></a></p>
1903 <?php wp_nonce_field( 'google_csrf_nonce', 'nonce_google_auth-' . $this->get_cookie_value() ); ?>
1904 <?php endif; ?>
1905
1906 <?php if ( $auth_settings['cas'] === '1' ): ?>
1907 <p><a class="button button-primary button-external button-cas" href="<?php echo $this->modify_current_url_for_cas_login(); ?>">
1908 <span class="dashicons dashicons-lock"></span>
1909 <span class="label"><?php
1910 printf(
1911 /* TRANSLATORS: %s: Custom CAS label from authorizer options */
1912 __( 'Sign in with %s', 'authorizer' ),
1913 $auth_settings['cas_custom_label']
1914 );
1915 ?></span>
1916 </a></p>
1917 <?php endif; ?>
1918
1919 <?php if ( $auth_settings['advanced_hide_wp_login'] === '1' && strpos( $_SERVER['QUERY_STRING'], 'external=wordpress' ) === false ): ?>
1920 <style type="text/css">
1921 #loginform {
1922 padding-bottom: 8px !important;
1923 }
1924 #loginform p>label, #loginform p.forgetmenot, #loginform p.submit, p#nav {
1925 display: none !important;
1926 }
1927 </style>
1928 <?php elseif ( $auth_settings['cas'] === '1' || $auth_settings['google'] === '1' ): ?>
1929 <h3> &mdash; <?php _e( 'or', 'authorizer' ); ?> &mdash; </h3>
1930 <?php endif; ?>
1931 </div>
1932 <?php
1933
1934 }
1935
1936
1937 /**
1938 * Redirect to CAS login when visiting login page (only if option is
1939 * enabled, CAS is the only service, and WordPress logins are hidden).
1940 * Note: hook into wp_login_errors filter so this fires after the
1941 * authenticate hook (where the redirect to CAS happens), but before html
1942 * output is started (so the redirect header doesn't complain about data
1943 * already being sent).
1944 */
1945 function wp_login_errors__maybe_redirect_to_cas( $errors, $redirect_to ) {
1946 // Grab plugin settings.
1947 $auth_settings = $this->get_plugin_options( SINGLE_ADMIN, 'allow override' );
1948
1949 // Check whether we should redirect to CAS.
1950 if (
1951 strpos( $_SERVER['QUERY_STRING'], 'external=wordpress' ) === false &&
1952 array_key_exists( 'cas_auto_login', $auth_settings ) && $auth_settings['cas_auto_login'] === '1' &&
1953 array_key_exists( 'cas', $auth_settings ) && $auth_settings['cas'] === '1' &&
1954 ( ! array_key_exists( 'ldap', $auth_settings ) || $auth_settings['ldap'] !== '1' ) &&
1955 ( ! array_key_exists( 'google', $auth_settings ) || $auth_settings['google'] !== '1' ) &&
1956 array_key_exists( 'advanced_hide_wp_login', $auth_settings ) && $auth_settings['advanced_hide_wp_login'] === '1'
1957 ) {
1958 wp_redirect( $this->modify_current_url_for_cas_login() );
1959 exit;
1960 }
1961
1962 return $errors;
1963 }
1964
1965
1966 /**
1967 * Implements hook: do_action( 'wp_login_failed', $username );
1968 * Update the user meta for the user that just failed logging in.
1969 * Keep track of time of last failed attempt and number of failed attempts.
1970 */
1971 function update_login_failed_count( $username ) {
1972 // Grab plugin settings.
1973 $auth_settings = $this->get_plugin_options( SINGLE_ADMIN, 'allow override' );
1974
1975 // Get user trying to log in.
1976 // If this isn't a real user, update the global failed attempt
1977 // variables. We'll use these global variables to institute the
1978 // lockouts on nonexistent accounts. We do this so an attacker
1979 // won't be able to determine which accounts are real by which
1980 // accounts get locked out on multiple invalid attempts.
1981 $user = get_user_by( 'login', $username );
1982
1983 if ( $user !== FALSE ) {
1984 $last_attempt = get_user_meta( $user->ID, 'auth_settings_advanced_lockouts_time_last_failed', true );
1985 $num_attempts = get_user_meta( $user->ID, 'auth_settings_advanced_lockouts_failed_attempts', true );
1986 } else {
1987 $last_attempt = get_option( 'auth_settings_advanced_lockouts_time_last_failed' );
1988 $num_attempts = get_option( 'auth_settings_advanced_lockouts_failed_attempts' );
1989 }
1990
1991 // Make sure $last_attempt (time) and $num_attempts are positive integers.
1992 // Note: this addresses resetting them if either is unset from above.
1993 $last_attempt = abs( intval( $last_attempt ) );
1994 $num_attempts = abs( intval( $num_attempts ) );
1995
1996 // Reset the failed attempt count if the time since the last
1997 // failed attempt is greater than the reset duration.
1998 $time_since_last_fail = time() - $last_attempt;
1999 $reset_duration = $auth_settings['advanced_lockouts']['reset_duration'] * 60; // minutes to seconds
2000 if ( $time_since_last_fail > $reset_duration ) {
2001 $num_attempts = 0;
2002 }
2003
2004 // Set last failed time to now and increment last failed count.
2005 if ( $user !== FALSE ) {
2006 update_user_meta( $user->ID, 'auth_settings_advanced_lockouts_time_last_failed', time() );
2007 update_user_meta( $user->ID, 'auth_settings_advanced_lockouts_failed_attempts', $num_attempts + 1 );
2008 } else {
2009 update_option( 'auth_settings_advanced_lockouts_time_last_failed', time() );
2010 update_option( 'auth_settings_advanced_lockouts_failed_attempts', $num_attempts + 1 );
2011 }
2012 }
2013
2014
2015 /**
2016 * When they successfully log in, make sure WordPress users are in the approved list.
2017 *
2018 * @action wp_login
2019 *
2020 * @param string $user_login Username of the user logging in.
2021 * @param WP_User $user WP_User object of the user logging in.
2022 * @return null
2023 */
2024 function ensure_wordpress_user_in_approved_list_on_login( $user_login, $user ) {
2025 $this->add_user_to_authorizer_when_created( $user->user_email, $user->user_registered, $user->user_roles );
2026 }
2027
2028
2029 /**
2030 * Overwrite the URL for the lost password link on the login form.
2031 * If we're authenticating against an external service, standard
2032 * WordPress password resets won't work.
2033 */
2034 function custom_lostpassword_url( $lostpassword_url ) {
2035 // Grab plugin settings.
2036 $auth_settings = $this->get_plugin_options( SINGLE_ADMIN, 'allow override' );
2037
2038 if (
2039 array_key_exists( 'ldap_lostpassword_url', $auth_settings ) &&
2040 filter_var( $auth_settings['ldap_lostpassword_url'], FILTER_VALIDATE_URL )
2041 ) {
2042 $lostpassword_url = $auth_settings['ldap_lostpassword_url'];
2043 }
2044 return $lostpassword_url;
2045 }
2046
2047
2048
2049 /**
2050 * ***************************
2051 * Options page
2052 * ***************************
2053 */
2054
2055
2056
2057 /**
2058 * Add a link to this plugin's settings page from the WordPress Plugins page.
2059 * Called from "plugin_action_links" filter in __construct() above.
2060 *
2061 * @param array $links array of links in the admin sidebar
2062 *
2063 * @return array of links to show in the admin sidebar.
2064 */
2065 public function plugin_settings_link( $links ) {
2066 $admin_menu = $this->get_plugin_option( 'advanced_admin_menu' );
2067 $settings_url = $admin_menu === 'settings' ? admin_url( 'options-general.php?page=authorizer' ) : admin_url( 'admin.php?page=authorizer' );
2068 array_unshift( $links, '<a href="' . $settings_url . '">' . __( 'Settings', 'authorizer' ) . '</a>' );
2069 return $links;
2070 }
2071
2072
2073 /**
2074 * Add a link to this plugin's network settings page from the WordPress Plugins page.
2075 * Called from "network_admin_plugin_action_links" filter in __construct() above.
2076 *
2077 * @param array $links array of links in the network admin sidebar
2078 *
2079 * @return array of links to show in the network admin sidebar.
2080 */
2081 public function network_admin_plugin_settings_link( $links ) {
2082 $settings_link = '<a href="admin.php?page=authorizer">' . __( 'Network Settings', 'authorizer' ) . '</a>';
2083 array_unshift( $links, $settings_link );
2084 return $links;
2085 }
2086
2087
2088 /**
2089 * Create the options page under Dashboard > Settings
2090 * Run on action hook: admin_menu
2091 */
2092 public function add_plugin_page() {
2093 $admin_menu = $this->get_plugin_option( 'advanced_admin_menu' );
2094 if ( $admin_menu === 'settings' ) {
2095 // @see http://codex.wordpress.org/Function_Reference/add_options_page
2096 add_options_page(
2097 'Authorizer', // Page title
2098 'Authorizer', // Menu title
2099 'create_users', // Capability
2100 'authorizer', // Menu slug
2101 array( $this, 'create_admin_page' ) // function
2102 );
2103 } else {
2104 // @see http://codex.wordpress.org/Function_Reference/add_menu_page
2105 add_menu_page(
2106 'Authorizer', // Page title
2107 'Authorizer', // Menu title
2108 'create_users', // Capability
2109 'authorizer', // Menu slug
2110 array( $this, 'create_admin_page' ), // callback
2111 'dashicons-groups', // icon
2112 '99.0018465' // position (decimal is to make overlap with other plugins less likely)
2113 );
2114 }
2115 }
2116
2117
2118 /**
2119 * Output the HTML for the options page
2120 */
2121 public function create_admin_page() { ?>
2122 <div class="wrap">
2123 <h2><?php _e( 'Authorizer Settings', 'authorizer' ); ?></h2>
2124 <form method="post" action="options.php" autocomplete="off"><?php
2125 // This prints out all hidden settings fields
2126 // @see http://codex.wordpress.org/Function_Reference/settings_fields
2127 settings_fields( 'auth_settings_group' );
2128 // This prints out all the sections
2129 // @see http://codex.wordpress.org/Function_Reference/do_settings_sections
2130 do_settings_sections( 'authorizer' );
2131 submit_button(); ?>
2132 </form>
2133 </div><?php
2134 }
2135
2136
2137 /**
2138 * Load external resources on this plugin's options page.
2139 * Run on action hooks: load-settings_page_authorizer, load-toplevel_page_authorizer, admin_head-index.php
2140 */
2141 public function load_options_page() {
2142 wp_enqueue_script(
2143 'authorizer',
2144 plugins_url( 'js/authorizer.js', __FILE__ ),
2145 array( 'jquery-effects-shake' ), '2.3.2', true
2146 );
2147 wp_localize_script( 'authorizer', 'auth_L10n', array(
2148 'baseurl' => get_bloginfo( 'url' ),
2149 'saved' => esc_html__( 'Saved', 'authorizer' ),
2150 'failed' => esc_html__( 'Failed', 'authorizer' ),
2151 'local_wordpress_user' => esc_html__( 'Local WordPress user', 'authorizer' ),
2152 'block_ban_user' => esc_html__( 'Block/Ban user', 'authorizer' ),
2153 'remove_user' => esc_html__( 'Remove user', 'authorizer' ),
2154 'no_users_in' => esc_html__( 'No users in', 'authorizer' ),
2155 'save_changes' => esc_html__( 'Save Changes', 'authorizer' ),
2156 'private_pages' => esc_html__( 'Private Pages', 'authorizer' ),
2157 'public_pages' => esc_html__( 'Public Pages', 'authorizer' ),
2158 ));
2159
2160 wp_enqueue_script(
2161 'jquery.multi-select',
2162 plugins_url( 'vendor/jquery.multi-select/js/jquery.multi-select.js', __FILE__ ),
2163 array( 'jquery' ), '1.8', true
2164 );
2165
2166 wp_register_style( 'authorizer-css', plugins_url( 'css/authorizer.css', __FILE__ ), array(), '2.3.2' );
2167 wp_enqueue_style( 'authorizer-css' );
2168
2169 wp_register_style( 'jquery-multi-select-css', plugins_url( 'vendor/jquery.multi-select/css/multi-select.css', __FILE__ ), array(), '1.8' );
2170 wp_enqueue_style( 'jquery-multi-select-css' );
2171
2172 add_action( 'admin_notices', array( $this, 'admin_notices' ) ); // Add any notices to the top of the options page.
2173 add_action( 'admin_head', array( $this, 'admin_head' ) ); // Add help documentation to the options page.
2174 }
2175
2176
2177 /**
2178 * Show custom admin notice.
2179 * Filter: admin_notice
2180 */
2181 function show_advanced_admin_notice() {
2182 $notice = get_option( 'auth_settings_advanced_admin_notice' );
2183 delete_option( 'auth_settings_advanced_admin_notice' );
2184
2185 if ( $notice && strlen( $notice ) > 0 ) { ?>
2186 <div class="error">
2187 <p><?php echo $notice; ?></p>
2188 </div><?php
2189 }
2190 }
2191
2192
2193 /**
2194 * Add notices to the top of the options page.
2195 * Run on action hook chain: load-settings_page_authorizer > admin_notices
2196 * Description: Check for invalid settings combinations and show a warning message, e.g.:
2197 * if ( cas url inaccessible ) : ?>
2198 * <div class='updated settings-error'><p>Can't reach CAS server.</p></div>
2199 * <?php endif;
2200 */
2201 public function admin_notices() {
2202 // Grab plugin settings.
2203 $auth_settings = $this->get_plugin_options( SINGLE_ADMIN, 'allow override' );
2204
2205 if ( $auth_settings['cas'] === '1' ) :
2206 // Check if provided CAS URL is accessible.
2207 $protocol = in_array( $auth_settings['cas_port'], array( '80', '8080' ) ) ? 'http' : 'https';
2208 $cas_url = $protocol . '://' . $auth_settings['cas_host'] . ':' . $auth_settings['cas_port'] . $auth_settings['cas_path'];
2209 $cas_url = trailingslashit( $cas_url ) . 'login'; // Check the specific CAS login endpoint
2210 if ( ! $this->url_is_accessible( $cas_url ) ) :
2211 $authorizer_options_url = $auth_settings['advanced_admin_menu'] === 'settings' ? admin_url( 'options-general.php?page=authorizer' ) : admin_url( '?page=authorizer' );
2212 ?><div class='notice notice-warning is-dismissible'>
2213 <p><?php _e( "Can't reach CAS server. Please provide", 'authorizer' ); ?> <a href='<?php echo $authorizer_options_url; ?>&tab=external'><?php _e( 'accurate CAS settings', 'authorizer' ); ?></a> <?php _e( 'if you intend to use it.', 'authorizer' ); ?></p>
2214 </div><?php
2215 endif;
2216 endif;
2217 }
2218
2219
2220 /**
2221 * Create sections and options
2222 * Run on action hook: admin_init
2223 */
2224 public function page_init() {
2225 // Create one setting that holds all the options (array)
2226 // @see http://codex.wordpress.org/Function_Reference/register_setting
2227 // @see http://codex.wordpress.org/Function_Reference/add_settings_section
2228 // @see http://codex.wordpress.org/Function_Reference/add_settings_field
2229 register_setting(
2230 'auth_settings_group', // Option group
2231 'auth_settings', // Option name
2232 array( $this, 'sanitize_options' ) // Sanitize callback
2233 );
2234
2235 add_settings_section(
2236 'auth_settings_tabs', // HTML element ID
2237 '', // HTML element Title
2238 array( $this, 'print_section_info_tabs' ), // Callback (echos section content)
2239 'authorizer' // Page this section is shown on (slug)
2240 );
2241
2242 // Create Access Lists section
2243 add_settings_section(
2244 'auth_settings_lists', // HTML element ID
2245 '', // HTML element Title
2246 array( $this, 'print_section_info_access_lists' ), // Callback (echos section content)
2247 'authorizer' // Page this section is shown on (slug)
2248 );
2249
2250 // Create Login Access section
2251 add_settings_section(
2252 'auth_settings_access_login', // HTML element ID
2253 '', // HTML element Title
2254 array( $this, 'print_section_info_access_login' ), // Callback (echos section content)
2255 'authorizer' // Page this section is shown on (slug)
2256 );
2257 add_settings_field(
2258 'auth_settings_access_who_can_login', // HTML element ID
2259 __( 'Who can log into the site?', 'authorizer' ), // HTML element Title
2260 array( $this, 'print_radio_auth_access_who_can_login' ), // Callback (echos form element)
2261 'authorizer', // Page this setting is shown on (slug)
2262 'auth_settings_access_login' // Section this setting is shown on
2263 );
2264 add_settings_field(
2265 'auth_settings_access_role_receive_pending_emails', // HTML element ID
2266 __( 'Which role should receive email notifications about pending users?', 'authorizer' ), // HTML element Title
2267 array( $this, 'print_select_auth_access_role_receive_pending_emails' ), // Callback (echos form element)
2268 'authorizer', // Page this setting is shown on (slug)
2269 'auth_settings_access_login' // Section this setting is shown on
2270 );
2271 add_settings_field(
2272 'auth_settings_access_pending_redirect_to_message', // HTML element ID
2273 __( 'What message should pending users see after attempting to log in?', 'authorizer' ), // HTML element Title
2274 array( $this, 'print_wysiwyg_auth_access_pending_redirect_to_message' ), // Callback (echos form element)
2275 'authorizer', // Page this setting is shown on (slug)
2276 'auth_settings_access_login' // Section this setting is shown on
2277 );
2278 add_settings_field(
2279 'auth_settings_access_blocked_redirect_to_message', // HTML element ID
2280 __( 'What message should blocked users see after attempting to log in?', 'authorizer' ), // HTML element Title
2281 array( $this, 'print_wysiwyg_auth_access_blocked_redirect_to_message' ), // Callback (echos form element)
2282 'authorizer', // Page this setting is shown on (slug)
2283 'auth_settings_access_login' // Section this setting is shown on
2284 );
2285 add_settings_field(
2286 'auth_settings_access_should_email_approved_users', // HTML element ID
2287 __( 'Send welcome email to new approved users?', 'authorizer' ), // HTML element Title
2288 array( $this, 'print_checkbox_auth_access_should_email_approved_users' ), // Callback (echos form element)
2289 'authorizer', // Page this setting is shown on (slug)
2290 'auth_settings_access_login' // Section this setting is shown on
2291 );
2292 add_settings_field(
2293 'auth_settings_access_email_approved_users_subject', // HTML element ID
2294 __( 'Welcome email subject', 'authorizer' ), // HTML element Title
2295 array( $this, 'print_text_auth_access_email_approved_users_subject' ), // Callback (echos form element)
2296 'authorizer', // Page this setting is shown on (slug)
2297 'auth_settings_access_login' // Section this setting is shown on
2298 );
2299 add_settings_field(
2300 'auth_settings_access_email_approved_users_body', // HTML element ID
2301 __( 'Welcome email body', 'authorizer' ), // HTML element Title
2302 array( $this, 'print_wysiwyg_auth_access_email_approved_users_body' ), // Callback (echos form element)
2303 'authorizer', // Page this setting is shown on (slug)
2304 'auth_settings_access_login' // Section this setting is shown on
2305 );
2306
2307
2308 // Create Public Access section
2309 add_settings_section(
2310 'auth_settings_access_public', // HTML element ID
2311 '', // HTML element Title
2312 array( $this, 'print_section_info_access_public' ), // Callback (echos section content)
2313 'authorizer' // Page this section is shown on (slug)
2314 );
2315 add_settings_field(
2316 'auth_settings_access_who_can_view', // HTML element ID
2317 __( 'Who can view the site?', 'authorizer' ), // HTML element Title
2318 array( $this, 'print_radio_auth_access_who_can_view' ), // Callback (echos form element)
2319 'authorizer', // Page this setting is shown on (slug)
2320 'auth_settings_access_public' // Section this setting is shown on
2321 );
2322 add_settings_field(
2323 'auth_settings_access_public_pages', // HTML element ID
2324 __( 'What pages (if any) should be available to everyone?', 'authorizer' ), // HTML element Title
2325 array( $this, 'print_multiselect_auth_access_public_pages' ), // Callback (echos form element)
2326 'authorizer', // Page this setting is shown on (slug)
2327 'auth_settings_access_public' // Section this setting is shown on
2328 );
2329 add_settings_field(
2330 'auth_settings_access_redirect', // HTML element ID
2331 __( 'What happens to people without access when they visit a private page?', 'authorizer' ), // HTML element Title
2332 array( $this, 'print_radio_auth_access_redirect' ), // Callback (echos form element)
2333 'authorizer', // Page this setting is shown on (slug)
2334 'auth_settings_access_public' // Section this setting is shown on
2335 );
2336 add_settings_field(
2337 'auth_settings_access_public_warning', // HTML element ID
2338 __( 'What happens to people without access when they visit a public page?', 'authorizer' ), // HTML element Title
2339 array( $this, 'print_radio_auth_access_public_warning' ), // Callback (echos form element)
2340 'authorizer', // Page this setting is shown on (slug)
2341 'auth_settings_access_public' // Section this setting is shown on
2342 );
2343 add_settings_field(
2344 'auth_settings_access_redirect_to_message', // HTML element ID
2345 __( 'What message should people without access see?', 'authorizer' ), // HTML element Title
2346 array( $this, 'print_wysiwyg_auth_access_redirect_to_message' ), // Callback (echos form element)
2347 'authorizer', // Page this setting is shown on (slug)
2348 'auth_settings_access_public' // Section this setting is shown on
2349 );
2350
2351 // Create External Service Settings section
2352 add_settings_section(
2353 'auth_settings_external', // HTML element ID
2354 '', // HTML element Title
2355 array( $this, 'print_section_info_external' ), // Callback (echos section content)
2356 'authorizer' // Page this section is shown on (slug)
2357 );
2358 add_settings_field(
2359 'auth_settings_access_default_role', // HTML element ID
2360 __( 'Default role for new users', 'authorizer' ), // HTML element Title
2361 array( $this, 'print_select_auth_access_default_role' ), // Callback (echos form element)
2362 'authorizer', // Page this setting is shown on (slug)
2363 'auth_settings_external' // Section this setting is shown on
2364 );
2365 add_settings_field(
2366 'auth_settings_external_google', // HTML element ID
2367 __( 'Google Logins', 'authorizer' ), // HTML element Title
2368 array( $this, 'print_checkbox_auth_external_google' ), // Callback (echos form element)
2369 'authorizer', // Page this setting is shown on (slug)
2370 'auth_settings_external' // Section this setting is shown on
2371 );
2372 add_settings_field(
2373 'auth_settings_google_clientid', // HTML element ID
2374 __( 'Google Client ID', 'authorizer' ), // HTML element Title
2375 array( $this, 'print_text_google_clientid' ), // Callback (echos form element)
2376 'authorizer', // Page this setting is shown on (slug)
2377 'auth_settings_external' // Section this setting is shown on
2378 );
2379 add_settings_field(
2380 'auth_settings_google_clientsecret', // HTML element ID
2381 __( 'Google Client Secret', 'authorizer' ), // HTML element Title
2382 array( $this, 'print_text_google_clientsecret' ), // Callback (echos form element)
2383 'authorizer', // Page this setting is shown on (slug)
2384 'auth_settings_external' // Section this setting is shown on
2385 );
2386 add_settings_field(
2387 'auth_settings_google_hosteddomain', // HTML element ID
2388 __( 'Google Hosted Domain', 'authorizer' ), // HTML element Title
2389 array( $this, 'print_text_google_hosteddomain' ), // Callback (echos form element)
2390 'authorizer', // Page this setting is shown on (slug)
2391 'auth_settings_external' // Section this setting is shown on
2392 );
2393 add_settings_field(
2394 'auth_settings_external_cas', // HTML element ID
2395 __( 'CAS Logins', 'authorizer' ), // HTML element Title
2396 array( $this, 'print_checkbox_auth_external_cas' ), // Callback (echos form element)
2397 'authorizer', // Page this setting is shown on (slug)
2398 'auth_settings_external' // Section this setting is shown on
2399 );
2400 add_settings_field(
2401 'auth_settings_cas_custom_label', // HTML element ID
2402 __( 'CAS custom label', 'authorizer' ), // HTML element Title
2403 array( $this, 'print_text_cas_custom_label' ), // Callback (echos form element)
2404 'authorizer', // Page this setting is shown on (slug)
2405 'auth_settings_external' // Section this setting is shown on
2406 );
2407 add_settings_field(
2408 'auth_settings_cas_host', // HTML element ID
2409 __( 'CAS server hostname', 'authorizer' ), // HTML element Title
2410 array( $this, 'print_text_cas_host' ), // Callback (echos form element)
2411 'authorizer', // Page this setting is shown on (slug)
2412 'auth_settings_external' // Section this setting is shown on
2413 );
2414 add_settings_field(
2415 'auth_settings_cas_port', // HTML element ID
2416 __( 'CAS server port', 'authorizer' ), // HTML element Title
2417 array( $this, 'print_text_cas_port' ), // Callback (echos form element)
2418 'authorizer', // Page this setting is shown on (slug)
2419 'auth_settings_external' // Section this setting is shown on
2420 );
2421 add_settings_field(
2422 'auth_settings_cas_path', // HTML element ID
2423 __( 'CAS server path/context', 'authorizer' ), // HTML element Title
2424 array( $this, 'print_text_cas_path' ), // Callback (echos form element)
2425 'authorizer', // Page this setting is shown on (slug)
2426 'auth_settings_external' // Section this setting is shown on
2427 );
2428 add_settings_field(
2429 'auth_settings_cas_version', // HTML element ID
2430 'CAS server version', // HTML element Title
2431 array( $this, 'print_select_cas_version' ), // Callback (echos form element)
2432 'authorizer', // Page this setting is shown on (slug)
2433 'auth_settings_external' // Section this setting is shown on
2434 );
2435 add_settings_field(
2436 'auth_settings_cas_attr_email', // HTML element ID
2437 __( 'CAS attribute containing email address', 'authorizer' ), // HTML element Title
2438 array( $this, 'print_text_cas_attr_email' ), // Callback (echos form element)
2439 'authorizer', // Page this setting is shown on (slug)
2440 'auth_settings_external' // Section this setting is shown on
2441 );
2442 add_settings_field(
2443 'auth_settings_cas_attr_first_name', // HTML element ID
2444 __( 'CAS attribute containing first name', 'authorizer' ), // HTML element Title
2445 array( $this, 'print_text_cas_attr_first_name' ), // Callback (echos form element)
2446 'authorizer', // Page this setting is shown on (slug)
2447 'auth_settings_external' // Section this setting is shown on
2448 );
2449 add_settings_field(
2450 'auth_settings_cas_attr_last_name', // HTML element ID
2451 __( 'CAS attribute containing last name', 'authorizer' ), // HTML element Title
2452 array( $this, 'print_text_cas_attr_last_name' ), // Callback (echos form element)
2453 'authorizer', // Page this setting is shown on (slug)
2454 'auth_settings_external' // Section this setting is shown on
2455 );
2456 add_settings_field(
2457 'auth_settings_cas_attr_update_on_login', // HTML element ID
2458 __( 'CAS attribute update', 'authorizer' ), // HTML element Title
2459 array( $this, 'print_checkbox_cas_attr_update_on_login' ), // Callback (echos form element)
2460 'authorizer', // Page this setting is shown on (slug)
2461 'auth_settings_external' // Section this setting is shown on
2462 );
2463 add_settings_field(
2464 'auth_settings_cas_auto_login', // HTML element ID
2465 __( 'CAS automatic login', 'authorizer' ), // HTML element Title
2466 array( $this, 'print_checkbox_cas_auto_login' ), // Callback (echos form element)
2467 'authorizer', // Page this setting is shown on (slug)
2468 'auth_settings_external' // Section this setting is shown on
2469 );
2470 add_settings_field(
2471 'auth_settings_external_ldap', // HTML element ID
2472 __( 'LDAP Logins', 'authorizer' ), // HTML element Title
2473 array( $this, 'print_checkbox_auth_external_ldap' ), // Callback (echos form element)
2474 'authorizer', // Page this setting is shown on (slug)
2475 'auth_settings_external' // Section this setting is shown on
2476 );
2477 add_settings_field(
2478 'auth_settings_ldap_host', // HTML element ID
2479 __( 'LDAP Host', 'authorizer' ), // HTML element Title
2480 array( $this, 'print_text_ldap_host' ), // Callback (echos form element)
2481 'authorizer', // Page this setting is shown on (slug)
2482 'auth_settings_external' // Section this setting is shown on
2483 );
2484 add_settings_field(
2485 'auth_settings_ldap_port', // HTML element ID
2486 __( 'LDAP Port', 'authorizer' ), // HTML element Title
2487 array( $this, 'print_text_ldap_port' ), // Callback (echos form element)
2488 'authorizer', // Page this setting is shown on (slug)
2489 'auth_settings_external' // Section this setting is shown on
2490 );
2491 add_settings_field(
2492 'auth_settings_ldap_tls', // HTML element ID
2493 __( 'Secure Connection (TLS)', 'authorizer' ), // HTML element Title
2494 array( $this, 'print_checkbox_ldap_tls' ), // Callback (echos form element)
2495 'authorizer', // Page this setting is shown on (slug)
2496 'auth_settings_external' // Section this setting is shown on
2497 );
2498 add_settings_field(
2499 'auth_settings_ldap_search_base', // HTML element ID
2500 __( 'LDAP Search Base', 'authorizer' ), // HTML element Title
2501 array( $this, 'print_text_ldap_search_base' ), // Callback (echos form element)
2502 'authorizer', // Page this setting is shown on (slug)
2503 'auth_settings_external' // Section this setting is shown on
2504 );
2505 add_settings_field(
2506 'auth_settings_ldap_uid', // HTML element ID
2507 __( 'LDAP attribute containing username', 'authorizer' ), // HTML element Title
2508 array( $this, 'print_text_ldap_uid' ), // Callback (echos form element)
2509 'authorizer', // Page this setting is shown on (slug)
2510 'auth_settings_external' // Section this setting is shown on
2511 );
2512 add_settings_field(
2513 'auth_settings_ldap_attr_email', // HTML element ID
2514 __( 'LDAP attribute containing email address', 'authorizer' ), // HTML element Title
2515 array( $this, 'print_text_ldap_attr_email' ), // Callback (echos form element)
2516 'authorizer', // Page this setting is shown on (slug)
2517 'auth_settings_external' // Section this setting is shown on
2518 );
2519 add_settings_field(
2520 'auth_settings_ldap_user', // HTML element ID
2521 __( 'LDAP Directory User', 'authorizer' ), // HTML element Title
2522 array( $this, 'print_text_ldap_user' ), // Callback (echos form element)
2523 'authorizer', // Page this setting is shown on (slug)
2524 'auth_settings_external' // Section this setting is shown on
2525 );
2526 add_settings_field(
2527 'auth_settings_ldap_password', // HTML element ID
2528 __( 'LDAP Directory User Password', 'authorizer' ), // HTML element Title
2529 array( $this, 'print_password_ldap_password' ), // Callback (echos form element)
2530 'authorizer', // Page this setting is shown on (slug)
2531 'auth_settings_external' // Section this setting is shown on
2532 );
2533 add_settings_field(
2534 'auth_settings_ldap_lostpassword_url', // HTML element ID
2535 __( 'Custom lost password URL', 'authorizer' ), // HTML element Title
2536 array( $this, 'print_text_ldap_lostpassword_url' ), // Callback (echos form element)
2537 'authorizer', // Page this setting is shown on (slug)
2538 'auth_settings_external' // Section this setting is shown on
2539 );
2540 add_settings_field(
2541 'auth_settings_ldap_attr_first_name', // HTML element ID
2542 __( 'LDAP attribute containing first name', 'authorizer' ), // HTML element Title
2543 array( $this, 'print_text_ldap_attr_first_name' ), // Callback (echos form element)
2544 'authorizer', // Page this setting is shown on (slug)
2545 'auth_settings_external' // Section this setting is shown on
2546 );
2547 add_settings_field(
2548 'auth_settings_ldap_attr_last_name', // HTML element ID
2549 __( 'LDAP attribute containing last name', 'authorizer' ), // HTML element Title
2550 array( $this, 'print_text_ldap_attr_last_name' ), // Callback (echos form element)
2551 'authorizer', // Page this setting is shown on (slug)
2552 'auth_settings_external' // Section this setting is shown on
2553 );
2554 add_settings_field(
2555 'auth_settings_ldap_attr_update_on_login', // HTML element ID
2556 __( 'LDAP attribute update', 'authorizer' ), // HTML element Title
2557 array( $this, 'print_checkbox_ldap_attr_update_on_login' ), // Callback (echos form element)
2558 'authorizer', // Page this setting is shown on (slug)
2559 'auth_settings_external' // Section this setting is shown on
2560 );
2561
2562 // Create Advanced Settings section
2563 add_settings_section(
2564 'auth_settings_advanced', // HTML element ID
2565 '', // HTML element Title
2566 array( $this, 'print_section_info_advanced' ), // Callback (echos section content)
2567 'authorizer' // Page this section is shown on (slug)
2568 );
2569 add_settings_field(
2570 'auth_settings_advanced_lockouts', // HTML element ID
2571 __( 'Limit invalid login attempts', 'authorizer' ), // HTML element Title
2572 array( $this, 'print_text_auth_advanced_lockouts' ), // Callback (echos form element)
2573 'authorizer', // Page this setting is shown on (slug)
2574 'auth_settings_advanced' // Section this setting is shown on
2575 );
2576 add_settings_field(
2577 'auth_settings_advanced_hide_wp_login', // HTML element ID
2578 __( 'Hide WordPress Login', 'authorizer' ), // HTML element Title
2579 array( $this, 'print_checkbox_auth_advanced_hide_wp_login' ), // Callback (echos form element)
2580 'authorizer', // Page this setting is shown on (slug)
2581 'auth_settings_advanced' // Section this setting is shown on
2582 );
2583 add_settings_field(
2584 'auth_settings_advanced_branding', // HTML element ID
2585 __( 'Custom WordPress login branding', 'authorizer' ), // HTML element Title
2586 array( $this, 'print_radio_auth_advanced_branding' ), // Callback (echos form element)
2587 'authorizer', // Page this setting is shown on (slug)
2588 'auth_settings_advanced' // Section this setting is shown on
2589 );
2590 add_settings_field(
2591 'auth_settings_advanced_admin_menu', // HTML element ID
2592 __( 'Authorizer admin menu item location', 'authorizer' ), // HTML element Title
2593 array( $this, 'print_radio_auth_advanced_admin_menu' ), // Callback (echos form element)
2594 'authorizer', // Page this setting is shown on (slug)
2595 'auth_settings_advanced' // Section this setting is shown on
2596 );
2597 add_settings_field(
2598 'auth_settings_advanced_usermeta', // HTML element ID
2599 __( 'Show custom usermeta in user list', 'authorizer' ), // HTML element Title
2600 array( $this, 'print_select_auth_advanced_usermeta' ), // Callback (echos form element)
2601 'authorizer', // Page this setting is shown on (slug)
2602 'auth_settings_advanced' // Section this setting is shown on
2603 );
2604 // On multisite installs, add an option to override all multisite settings on individual sites.
2605 if ( is_multisite() ) {
2606 add_settings_field(
2607 'auth_settings_advanced_override_multisite', // HTML element ID
2608 __( 'Override multisite options', 'authorizer' ), // HTML element Title
2609 array( $this, 'print_checkbox_auth_advanced_override_multisite' ), // Callback (echos form element)
2610 'authorizer', // Page this setting is shown on (slug)
2611 'auth_settings_advanced' // Section this setting is shown on
2612 );
2613 }
2614 }
2615
2616
2617 /**
2618 * Set meaningful defaults for the plugin options.
2619 * Note: This function is called on plugin activation.
2620 */
2621 function set_default_options() {
2622 global $wp_roles;
2623
2624 $auth_settings = get_option( 'auth_settings' );
2625 if ( $auth_settings === FALSE ) {
2626 $auth_settings = array();
2627 }
2628
2629 // Access Lists Defaults.
2630 $auth_settings_access_users_pending = get_option( 'auth_settings_access_users_pending' );
2631 if ( $auth_settings_access_users_pending === FALSE ) {
2632 $auth_settings_access_users_pending = array();
2633 }
2634 $auth_settings_access_users_approved = get_option( 'auth_settings_access_users_approved' );
2635 if ( $auth_settings_access_users_approved === FALSE ) {
2636 $auth_settings_access_users_approved = array();
2637 }
2638 $auth_settings_access_users_blocked = get_option( 'auth_settings_access_users_blocked' );
2639 if ( $auth_settings_access_users_blocked === FALSE ) {
2640 $auth_settings_access_users_blocked = array();
2641 }
2642
2643 // Login Access Defaults.
2644 if ( ! array_key_exists( 'access_who_can_login', $auth_settings ) ) {
2645 $auth_settings['access_who_can_login'] = 'approved_users';
2646 }
2647 if ( ! array_key_exists( 'access_role_receive_pending_emails', $auth_settings ) ) {
2648 $auth_settings['access_role_receive_pending_emails'] = '---';
2649 }
2650 if ( ! array_key_exists( 'access_pending_redirect_to_message', $auth_settings ) ) {
2651 $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.", 'authorizer' ) . '</p>';
2652 }
2653 if ( ! array_key_exists( 'access_blocked_redirect_to_message', $auth_settings ) ) {
2654 $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.", 'authorizer' ) . '</p>';
2655 }
2656 if ( ! array_key_exists( 'access_should_email_approved_users', $auth_settings ) ) {
2657 $auth_settings['access_should_email_approved_users'] = '';
2658 }
2659 if ( ! array_key_exists( 'access_email_approved_users_subject', $auth_settings ) ) {
2660 $auth_settings['access_email_approved_users_subject'] = sprintf(
2661 /* TRANSLATORS: %s: Shortcode for name of site */
2662 __( 'Welcome to %s!', 'authorizer' ),
2663 '[site_name]'
2664 );
2665 }
2666 if ( ! array_key_exists( 'access_email_approved_users_body', $auth_settings ) ) {
2667 $auth_settings['access_email_approved_users_body'] = sprintf(
2668 /* TRANSLATORS: 1: Shortcode for user email 2: Shortcode for site name 3: Shortcode for site URL */
2669 __( "Hello %1\$s,\nWelcome to %2\$s! You now have access to all content on the site. Please visit us here:\n%3\$s\n", 'authorizer' ),
2670 '[user_email]',
2671 '[site_name]',
2672 '[site_url]'
2673 );
2674 }
2675
2676 // Public Access to Private Page Defaults.
2677 if ( ! array_key_exists( 'access_who_can_view', $auth_settings ) ) {
2678 $auth_settings['access_who_can_view'] = 'everyone';
2679 }
2680 if ( ! array_key_exists( 'access_public_pages', $auth_settings ) ) {
2681 $auth_settings['access_public_pages'] = array();
2682 }
2683 if ( ! array_key_exists( 'access_redirect', $auth_settings ) ) {
2684 $auth_settings['access_redirect'] = 'login';
2685 }
2686 if ( ! array_key_exists( 'access_public_warning', $auth_settings ) ) {
2687 $auth_settings['access_public_warning'] = 'no_warning';
2688 }
2689 if ( ! array_key_exists( 'access_redirect_to_message', $auth_settings ) ) {
2690 $auth_settings['access_redirect_to_message'] = '<p>' . __( 'Notice: You are browsing this site anonymously, and only have access to a portion of its content.', 'authorizer' ) . '</p>';
2691 }
2692
2693
2694 // External Service Defaults.
2695 if ( ! array_key_exists( 'access_default_role', $auth_settings ) ) {
2696 // Set default role to 'student' if that role exists, 'subscriber' otherwise.
2697 $all_roles = $wp_roles->roles;
2698 $editable_roles = apply_filters( 'editable_roles', $all_roles );
2699 if ( array_key_exists( 'student', $editable_roles ) ) {
2700 $auth_settings['access_default_role'] = 'student';
2701 } else {
2702 $auth_settings['access_default_role'] = 'subscriber';
2703 }
2704 }
2705
2706 if ( ! array_key_exists( 'google', $auth_settings ) ) {
2707 $auth_settings['google'] = '';
2708 }
2709 if ( ! array_key_exists( 'cas', $auth_settings ) ) {
2710 $auth_settings['cas'] = '';
2711 }
2712 if ( ! array_key_exists( 'ldap', $auth_settings ) ) {
2713 $auth_settings['ldap'] = '';
2714 }
2715
2716 if ( ! array_key_exists( 'google_clientid', $auth_settings ) ) {
2717 $auth_settings['google_clientid'] = '';
2718 }
2719 if ( ! array_key_exists( 'google_clientsecret', $auth_settings ) ) {
2720 $auth_settings['google_clientsecret'] = '';
2721 }
2722 if ( ! array_key_exists( 'google_hosteddomain', $auth_settings ) ) {
2723 $auth_settings['google_hosteddomain'] = '';
2724 }
2725
2726 if ( ! array_key_exists( 'cas_custom_label', $auth_settings ) ) {
2727 $auth_settings['cas_custom_label'] = 'CAS';
2728 }
2729 if ( ! array_key_exists( 'cas_host', $auth_settings ) ) {
2730 $auth_settings['cas_host'] = '';
2731 }
2732 if ( ! array_key_exists( 'cas_port', $auth_settings ) ) {
2733 $auth_settings['cas_port'] = '';
2734 }
2735 if ( ! array_key_exists( 'cas_path', $auth_settings ) ) {
2736 $auth_settings['cas_path'] = '';
2737 }
2738 if ( ! array_key_exists( 'cas_version', $auth_settings ) ) {
2739 $auth_settings['cas_version'] = 'SAML_VERSION_1_1';
2740 }
2741 if ( ! array_key_exists( 'cas_attr_email', $auth_settings ) ) {
2742 $auth_settings['cas_attr_email'] = '';
2743 }
2744 if ( ! array_key_exists( 'cas_attr_first_name', $auth_settings ) ) {
2745 $auth_settings['cas_attr_first_name'] = '';
2746 }
2747 if ( ! array_key_exists( 'cas_attr_last_name', $auth_settings ) ) {
2748 $auth_settings['cas_attr_last_name'] = '';
2749 }
2750 if ( ! array_key_exists( 'cas_attr_update_on_login', $auth_settings ) ) {
2751 $auth_settings['cas_attr_update_on_login'] = '';
2752 }
2753 if ( ! array_key_exists( 'cas_auto_login', $auth_settings ) ) {
2754 $auth_settings['cas_auto_login'] = '';
2755 }
2756
2757 if ( ! array_key_exists( 'ldap_host', $auth_settings ) ) {
2758 $auth_settings['ldap_host'] = '';
2759 }
2760 if ( ! array_key_exists( 'ldap_port', $auth_settings ) ) {
2761 $auth_settings['ldap_port'] = '389';
2762 }
2763 if ( ! array_key_exists( 'ldap_tls', $auth_settings ) ) {
2764 $auth_settings['ldap_tls'] = '1';
2765 }
2766 if ( ! array_key_exists( 'ldap_search_base', $auth_settings ) ) {
2767 $auth_settings['ldap_search_base'] = '';
2768 }
2769 if ( ! array_key_exists( 'ldap_uid', $auth_settings ) ) {
2770 $auth_settings['ldap_uid'] = 'uid';
2771 }
2772 if ( ! array_key_exists( 'ldap_attr_email', $auth_settings ) ) {
2773 $auth_settings['ldap_attr_email'] = '';
2774 }
2775 if ( ! array_key_exists( 'ldap_user', $auth_settings ) ) {
2776 $auth_settings['ldap_user'] = '';
2777 }
2778 if ( ! array_key_exists( 'ldap_password', $auth_settings ) ) {
2779 $auth_settings['ldap_password'] = '';
2780 }
2781 if ( ! array_key_exists( 'ldap_lostpassword_url', $auth_settings ) ) {
2782 $auth_settings['ldap_lostpassword_url'] = '';
2783 }
2784 if ( ! array_key_exists( 'ldap_attr_first_name', $auth_settings ) ) {
2785 $auth_settings['ldap_attr_first_name'] = '';
2786 }
2787 if ( ! array_key_exists( 'ldap_attr_last_name', $auth_settings ) ) {
2788 $auth_settings['ldap_attr_last_name'] = '';
2789 }
2790 if ( ! array_key_exists( 'ldap_attr_update_on_login', $auth_settings ) ) {
2791 $auth_settings['ldap_attr_update_on_login'] = '';
2792 }
2793
2794 // Advanced defaults.
2795 if ( ! array_key_exists( 'advanced_lockouts', $auth_settings ) ) {
2796 $auth_settings['advanced_lockouts'] = array(
2797 'attempts_1' => 10,
2798 'duration_1' => 1,
2799 'attempts_2' => 10,
2800 'duration_2' => 10,
2801 'reset_duration' => 120,
2802 );
2803 }
2804 if ( ! array_key_exists( 'advanced_hide_wp_login', $auth_settings ) ) {
2805 $auth_settings['advanced_hide_wp_login'] = '';
2806 }
2807 if ( ! array_key_exists( 'advanced_branding', $auth_settings ) ) {
2808 $auth_settings['advanced_branding'] = 'default';
2809 }
2810 if ( ! array_key_exists( 'advanced_admin_menu', $auth_settings ) ) {
2811 $auth_settings['advanced_admin_menu'] = 'top';
2812 }
2813 if ( ! array_key_exists( 'advanced_usermeta', $auth_settings ) ) {
2814 $auth_settings['advanced_usermeta'] = '';
2815 }
2816 if ( ! array_key_exists( 'advanced_override_multisite', $auth_settings ) ) {
2817 $auth_settings['advanced_override_multisite'] = '';
2818 }
2819
2820 // Save default options to database.
2821 update_option( 'auth_settings', $auth_settings );
2822 update_option( 'auth_settings_access_users_pending', $auth_settings_access_users_pending );
2823 update_option( 'auth_settings_access_users_approved', $auth_settings_access_users_approved );
2824 update_option( 'auth_settings_access_users_blocked', $auth_settings_access_users_blocked );
2825
2826 // Multisite defaults.
2827 if ( is_multisite() ) {
2828 $auth_multisite_settings = get_blog_option( BLOG_ID_CURRENT_SITE, 'auth_multisite_settings', array() );
2829
2830 if ( $auth_multisite_settings === FALSE ) {
2831 $auth_multisite_settings = array();
2832 }
2833 // Global switch for enabling multisite options.
2834 if ( ! array_key_exists( 'multisite_override', $auth_multisite_settings ) ) {
2835 $auth_multisite_settings['multisite_override'] = '';
2836 }
2837 // Access Lists Defaults.
2838 $auth_multisite_settings_access_users_approved = get_blog_option( BLOG_ID_CURRENT_SITE, 'auth_multisite_settings_access_users_approved' );
2839 if ( $auth_multisite_settings_access_users_approved === FALSE ) {
2840 $auth_multisite_settings_access_users_approved = array();
2841 }
2842 // Login Access Defaults.
2843 if ( ! array_key_exists( 'access_who_can_login', $auth_multisite_settings ) ) {
2844 $auth_multisite_settings['access_who_can_login'] = 'approved_users';
2845 }
2846 // View Access Defaults.
2847 if ( ! array_key_exists( 'access_who_can_view', $auth_multisite_settings ) ) {
2848 $auth_multisite_settings['access_who_can_view'] = 'everyone';
2849 }
2850 // External Service Defaults.
2851 if ( ! array_key_exists( 'access_default_role', $auth_multisite_settings ) ) {
2852 // Set default role to 'student' if that role exists, 'subscriber' otherwise.
2853 $all_roles = $wp_roles->roles;
2854 $editable_roles = apply_filters( 'editable_roles', $all_roles );
2855 if ( array_key_exists( 'student', $editable_roles ) ) {
2856 $auth_multisite_settings['access_default_role'] = 'student';
2857 } else {
2858 $auth_multisite_settings['access_default_role'] = 'subscriber';
2859 }
2860 }
2861 if ( ! array_key_exists( 'google', $auth_multisite_settings ) ) {
2862 $auth_multisite_settings['google'] = '';
2863 }
2864 if ( ! array_key_exists( 'cas', $auth_multisite_settings ) ) {
2865 $auth_multisite_settings['cas'] = '';
2866 }
2867 if ( ! array_key_exists( 'ldap', $auth_multisite_settings ) ) {
2868 $auth_multisite_settings['ldap'] = '';
2869 }
2870 if ( ! array_key_exists( 'google_clientid', $auth_multisite_settings ) ) {
2871 $auth_multisite_settings['google_clientid'] = '';
2872 }
2873 if ( ! array_key_exists( 'google_clientsecret', $auth_multisite_settings ) ) {
2874 $auth_multisite_settings['google_clientsecret'] = '';
2875 }
2876 if ( ! array_key_exists( 'google_hosteddomain', $auth_multisite_settings ) ) {
2877 $auth_multisite_settings['google_hosteddomain'] = '';
2878 }
2879 if ( ! array_key_exists( 'cas_custom_label', $auth_multisite_settings ) ) {
2880 $auth_multisite_settings['cas_custom_label'] = 'CAS';
2881 }
2882 if ( ! array_key_exists( 'cas_host', $auth_multisite_settings ) ) {
2883 $auth_multisite_settings['cas_host'] = '';
2884 }
2885 if ( ! array_key_exists( 'cas_port', $auth_multisite_settings ) ) {
2886 $auth_multisite_settings['cas_port'] = '';
2887 }
2888 if ( ! array_key_exists( 'cas_path', $auth_multisite_settings ) ) {
2889 $auth_multisite_settings['cas_path'] = '';
2890 }
2891 if ( ! array_key_exists( 'cas_version', $auth_multisite_settings ) ) {
2892 $auth_multisite_settings['cas_version'] = 'SAML_VERSION_1_1';
2893 }
2894 if ( ! array_key_exists( 'cas_attr_email', $auth_multisite_settings ) ) {
2895 $auth_multisite_settings['cas_attr_email'] = '';
2896 }
2897 if ( ! array_key_exists( 'cas_attr_first_name', $auth_multisite_settings ) ) {
2898 $auth_multisite_settings['cas_attr_first_name'] = '';
2899 }
2900 if ( ! array_key_exists( 'cas_attr_last_name', $auth_multisite_settings ) ) {
2901 $auth_multisite_settings['cas_attr_last_name'] = '';
2902 }
2903 if ( ! array_key_exists( 'cas_attr_update_on_login', $auth_multisite_settings ) ) {
2904 $auth_multisite_settings['cas_attr_update_on_login'] = '';
2905 }
2906 if ( ! array_key_exists( 'cas_auto_login', $auth_multisite_settings ) ) {
2907 $auth_multisite_settings['cas_auto_login'] = '';
2908 }
2909 if ( ! array_key_exists( 'ldap_host', $auth_multisite_settings ) ) {
2910 $auth_multisite_settings['ldap_host'] = '';
2911 }
2912 if ( ! array_key_exists( 'ldap_port', $auth_multisite_settings ) ) {
2913 $auth_multisite_settings['ldap_port'] = '389';
2914 }
2915 if ( ! array_key_exists( 'ldap_tls', $auth_multisite_settings ) ) {
2916 $auth_multisite_settings['ldap_tls'] = '1';
2917 }
2918 if ( ! array_key_exists( 'ldap_search_base', $auth_multisite_settings ) ) {
2919 $auth_multisite_settings['ldap_search_base'] = '';
2920 }
2921 if ( ! array_key_exists( 'ldap_uid', $auth_multisite_settings ) ) {
2922 $auth_multisite_settings['ldap_uid'] = 'uid';
2923 }
2924 if ( ! array_key_exists( 'ldap_attr_email', $auth_multisite_settings ) ) {
2925 $auth_multisite_settings['ldap_attr_email'] = '';
2926 }
2927 if ( ! array_key_exists( 'ldap_user', $auth_multisite_settings ) ) {
2928 $auth_multisite_settings['ldap_user'] = '';
2929 }
2930 if ( ! array_key_exists( 'ldap_password', $auth_multisite_settings ) ) {
2931 $auth_multisite_settings['ldap_password'] = '';
2932 }
2933 if ( ! array_key_exists( 'ldap_lostpassword_url', $auth_multisite_settings ) ) {
2934 $auth_multisite_settings['ldap_lostpassword_url'] = '';
2935 }
2936 if ( ! array_key_exists( 'ldap_attr_first_name', $auth_multisite_settings ) ) {
2937 $auth_multisite_settings['ldap_attr_first_name'] = '';
2938 }
2939 if ( ! array_key_exists( 'ldap_attr_last_name', $auth_multisite_settings ) ) {
2940 $auth_multisite_settings['ldap_attr_last_name'] = '';
2941 }
2942 if ( ! array_key_exists( 'ldap_attr_update_on_login', $auth_multisite_settings ) ) {
2943 $auth_multisite_settings['ldap_attr_update_on_login'] = '';
2944 }
2945 // Advanced defaults.
2946 if ( ! array_key_exists( 'advanced_lockouts', $auth_multisite_settings ) ) {
2947 $auth_multisite_settings['advanced_lockouts'] = array(
2948 'attempts_1' => 10,
2949 'duration_1' => 1,
2950 'attempts_2' => 10,
2951 'duration_2' => 10,
2952 'reset_duration' => 120,
2953 );
2954 }
2955 if ( ! array_key_exists( 'advanced_hide_wp_login', $auth_multisite_settings ) ) {
2956 $auth_multisite_settings['advanced_hide_wp_login'] = '';
2957 }
2958 // Save default network options to database.
2959 update_blog_option( BLOG_ID_CURRENT_SITE, 'auth_multisite_settings', $auth_multisite_settings );
2960 update_blog_option( BLOG_ID_CURRENT_SITE, 'auth_multisite_settings_access_users_approved', $auth_multisite_settings_access_users_approved );
2961 }
2962
2963 return $auth_settings;
2964 }
2965
2966
2967 /**
2968 * List sanitizer.
2969 * $side_effect = 'none' or 'update roles' to make sure WP user roles match
2970 * $multisite_mode = 'single' or 'multisite' to indicate which user roles to change (this site or all sites)
2971 */
2972 function sanitize_user_list( $list, $side_effect = 'none', $multisite_mode = 'single' ) {
2973 // If it's not a list, make it so.
2974 if ( ! is_array( $list ) ) {
2975 $list = array();
2976 }
2977 foreach ( $list as $key => $user_info ) {
2978 if ( strlen( $user_info['email'] ) < 1 ) {
2979 // Make sure there are no empty entries in the list
2980 unset( $list[$key] );
2981 } elseif ( $side_effect === 'update roles' ) {
2982 // Make sure the WordPress user accounts have the same role
2983 // as that indicated in the list.
2984 $wp_user = get_user_by( 'email', $user_info['email'] );
2985 if ( $wp_user ) {
2986 if ( is_multisite() && $multisite_mode === 'multisite' ) {
2987 foreach ( get_blogs_of_user( $wp_user->ID ) as $blog ) {
2988 add_user_to_blog( $blog->userblog_id, $wp_user->ID, $user_info['role'] );
2989 }
2990 } else {
2991 $wp_user->set_role( $user_info['role'] );
2992 }
2993 }
2994 }
2995 }
2996 return $list;
2997 }
2998
2999
3000 /**
3001 * Settings sanitizer callback
3002 */
3003 function sanitize_options( $auth_settings ) {
3004 // Default to "Approved Users" login access restriction.
3005 if ( ! in_array( $auth_settings['access_who_can_login'], array( 'external_users', 'approved_users' ) ) ) {
3006 $auth_settings['access_who_can_login'] = 'approved_users';
3007 }
3008
3009 // Default to "Everyone" view access restriction.
3010 if ( ! in_array( $auth_settings['access_who_can_view'], array( 'everyone', 'logged_in_users' ) ) ) {
3011 $auth_settings['access_who_can_view'] = 'everyone';
3012 }
3013
3014 // Default to WordPress login access redirect.
3015 // Note: this option doesn't exist in multisite options, so we first
3016 // check to see if it exists.
3017 if ( array_key_exists( 'access_redirect', $auth_settings ) && ! in_array( $auth_settings['access_redirect'], array( 'login', 'page', 'message' ) ) ) {
3018 $auth_settings['access_redirect'] = 'login';
3019 }
3020
3021 // Default to warning message for anonymous users on public pages.
3022 // Note: this option doesn't exist in multisite options, so we first
3023 // check to see if it exists.
3024 if ( array_key_exists( 'access_public_warning', $auth_settings ) && ! in_array( $auth_settings['access_public_warning'], array( 'no_warning', 'warning' ) ) ) {
3025 $auth_settings['access_public_warning'] = 'no_warning';
3026 }
3027
3028 // Sanitize Send welcome email (checkbox: value can only be '1' or empty string)
3029 $auth_settings['access_should_email_approved_users'] = array_key_exists( 'access_should_email_approved_users', $auth_settings ) && strlen( $auth_settings['access_should_email_approved_users'] ) > 0 ? '1' : '';
3030
3031 // Sanitize Enable Google Logins (checkbox: value can only be '1' or empty string)
3032 $auth_settings['google'] = array_key_exists( 'google', $auth_settings ) && strlen( $auth_settings['google'] ) > 0 ? '1' : '';
3033
3034 // Sanitize Enable CAS Logins (checkbox: value can only be '1' or empty string)
3035 $auth_settings['cas'] = array_key_exists( 'cas', $auth_settings ) && strlen( $auth_settings['cas'] ) > 0 ? '1' : '';
3036
3037 // Sanitize CAS Host setting
3038 $auth_settings['cas_host'] = filter_var( $auth_settings['cas_host'], FILTER_SANITIZE_URL );
3039
3040 // Sanitize CAS Port (int)
3041 $auth_settings['cas_port'] = filter_var( $auth_settings['cas_port'], FILTER_SANITIZE_NUMBER_INT );
3042
3043 // Sanitize CAS attribute update (checkbox: value can only be '1' or empty string)
3044 $auth_settings['cas_attr_update_on_login'] = array_key_exists( 'cas_attr_update_on_login', $auth_settings ) && strlen( $auth_settings['cas_attr_update_on_login'] ) > 0 ? '1' : '';
3045
3046 // Sanitize CAS auto-login (checkbox: value can only be '1' or empty string)
3047 $auth_settings['cas_auto_login'] = array_key_exists( 'cas_auto_login', $auth_settings ) && strlen( $auth_settings['cas_auto_login'] ) > 0 ? '1' : '';
3048
3049 // Sanitize Enable LDAP Logins (checkbox: value can only be '1' or empty string)
3050 $auth_settings['ldap'] = array_key_exists( 'ldap', $auth_settings ) && strlen( $auth_settings['ldap'] ) > 0 ? '1' : '';
3051
3052 // Sanitize LDAP Host setting
3053 $auth_settings['ldap_host'] = filter_var( $auth_settings['ldap_host'], FILTER_SANITIZE_URL );
3054
3055 // Sanitize LDAP Port (int)
3056 $auth_settings['ldap_port'] = filter_var( $auth_settings['ldap_port'], FILTER_SANITIZE_NUMBER_INT );
3057
3058 // Sanitize LDAP TLS (checkbox: value can only be '1' or empty string)
3059 $auth_settings['ldap_tls'] = array_key_exists( 'ldap_tls', $auth_settings ) && strlen( $auth_settings['ldap_tls'] ) > 0 ? '1' : '';
3060
3061 // Sanitize LDAP attributes (basically make sure they don't have any parentheses)
3062 $auth_settings['ldap_uid'] = filter_var( $auth_settings['ldap_uid'], FILTER_SANITIZE_EMAIL );
3063
3064 // Sanitize LDAP Lost Password URL
3065 $auth_settings['ldap_lostpassword_url'] = filter_var( $auth_settings['ldap_lostpassword_url'], FILTER_SANITIZE_URL );
3066
3067 // Obfuscate LDAP directory user password
3068 if ( strlen( $auth_settings['ldap_password'] ) > 0 ) {
3069 // encrypt the directory user password for some minor obfuscation in the database.
3070 $auth_settings['ldap_password'] = $this->encrypt( $auth_settings['ldap_password'] );
3071 }
3072
3073 // Sanitize LDAP attribute update (checkbox: value can only be '1' or empty string)
3074 $auth_settings['ldap_attr_update_on_login'] = array_key_exists( 'ldap_attr_update_on_login', $auth_settings ) && strlen( $auth_settings['ldap_attr_update_on_login'] ) > 0 ? '1' : '';
3075
3076 // Make sure public pages is an empty array if it's empty
3077 // Note: this option doesn't exist in multisite options, so we first
3078 // check to see if it exists.
3079 if ( array_key_exists( 'access_public_pages', $auth_settings ) && ! is_array( $auth_settings['access_public_pages'] ) ) {
3080 $auth_settings['access_public_pages'] = array();
3081 }
3082
3083 // Make sure all lockout options are integers (attempts_1,
3084 // duration_1, attempts_2, duration_2, reset_duration).
3085 foreach ( $auth_settings['advanced_lockouts'] as $key => $value ) {
3086 $auth_settings['advanced_lockouts'][$key] = filter_var( $value, FILTER_SANITIZE_NUMBER_INT );
3087 }
3088
3089 // Sanitize Hide WordPress logins (checkbox: value can only be '1' or empty string)
3090 $auth_settings['advanced_hide_wp_login'] = array_key_exists( 'advanced_hide_wp_login', $auth_settings ) && strlen( $auth_settings['advanced_hide_wp_login'] ) > 0 ? '1' : '';
3091
3092 // Sanitize Override multisite options (checkbox: value can only be '1' or empty string)
3093 $auth_settings['advanced_override_multisite'] = array_key_exists( 'advanced_override_multisite', $auth_settings ) && strlen( $auth_settings['advanced_override_multisite'] ) > 0 ? '1' : '';
3094
3095 return $auth_settings;
3096 }
3097
3098
3099 /**
3100 * Keep authorizer approved users' roles in sync with WordPress roles
3101 * if someone changes the role via the WordPress Edit User options page.
3102 *
3103 * @action edit_user_profile_update
3104 * @ref https://codex.wordpress.org/Plugin_API/Action_Reference/edit_user_profile_update
3105 * @param int $user_id The user ID of the user being edited
3106
3107 * @action personal_options_update
3108 * @ref https://codex.wordpress.org/Plugin_API/Action_Reference/personal_options_update
3109 * @param int $user_id The user ID of the user being edited
3110 */
3111 function edit_user_profile_update_role( $user_id ) {
3112 if ( ! current_user_can( 'edit_user', $user_id ) ) {
3113 return;
3114 }
3115
3116 // If user is in approved list, update his/her associated role.
3117 $wp_user = get_user_by( 'id', $user_id );
3118 if ( $this->is_email_in_list( $wp_user->get( 'user_email' ), 'approved' ) ) {
3119 $auth_settings_access_users_approved = $this->sanitize_user_list( $this->get_plugin_option( 'access_users_approved', SINGLE_ADMIN ) );
3120 // Find approved user and sync with the corresponding WP_User.
3121 foreach ( $auth_settings_access_users_approved as $key => $user ) {
3122 if ( 0 === strcasecmp( $user['email'], $wp_user->user_email ) ) {
3123 // Sync user role.
3124 if ( array_key_exists( 'role', $_REQUEST ) ) {
3125 $auth_settings_access_users_approved[$key]['role'] = $_REQUEST['role'];
3126 }
3127 // Sync email address.
3128 if ( array_key_exists( 'email', $_REQUEST ) ) {
3129 $auth_settings_access_users_approved[$key]['email'] = mb_strtolower( $_REQUEST['email'] );
3130 }
3131 }
3132 }
3133
3134 update_option( 'auth_settings_access_users_approved', $auth_settings_access_users_approved );
3135 }
3136 }
3137
3138
3139 /**
3140 * Settings print callbacks
3141 */
3142 function print_section_info_tabs( $args = '' ) {
3143 if ( MULTISITE_ADMIN === $this->get_admin_mode( $args )): ?>
3144 <h2 class="nav-tab-wrapper">
3145 <a class="nav-tab nav-tab-access_lists nav-tab-active" href="javascript:choose_tab('access_lists' );"><?php _e( 'Access Lists', 'authorizer' ); ?></a>
3146 <a class="nav-tab nav-tab-external" href="javascript:choose_tab('external' );"><?php _e( 'External Service', 'authorizer' ); ?></a>
3147 <a class="nav-tab nav-tab-advanced" href="javascript:choose_tab('advanced' );"><?php _e( 'Advanced', 'authorizer' ); ?></a>
3148 </h2>
3149 <?php else: ?>
3150 <h2 class="nav-tab-wrapper">
3151 <a class="nav-tab nav-tab-access_lists nav-tab-active" href="javascript:choose_tab('access_lists' );"><?php _e( 'Access Lists', 'authorizer' ); ?></a>
3152 <a class="nav-tab nav-tab-access_login" href="javascript:choose_tab('access_login' );"><?php _e( 'Login Access', 'authorizer' ); ?></a>
3153 <a class="nav-tab nav-tab-access_public" href="javascript:choose_tab('access_public' );"><?php _e( 'Public Access', 'authorizer' ); ?></a>
3154 <a class="nav-tab nav-tab-external" href="javascript:choose_tab('external' );"><?php _e( 'External Service', 'authorizer' ); ?></a>
3155 <a class="nav-tab nav-tab-advanced" href="javascript:choose_tab('advanced' );"><?php _e( 'Advanced', 'authorizer' ); ?></a>
3156 </h2>
3157 <?php endif;
3158 }
3159
3160
3161 function print_section_info_access_lists( $args = '' ) {
3162 $admin_mode = $this->get_admin_mode( $args );
3163 ?><div id="section_info_access_lists" class="section_info">
3164 <p><?php _e( 'Manage who has access to this site using these lists.', 'authorizer' ); ?></p>
3165 <ol>
3166 <li><?php _e( "<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.", 'authorizer' ); ?></li>
3167 <li><?php _e( '<strong>Approved</strong> users have access to the site once they successfully log in.', 'authorizer' ); ?></li>
3168 <li><?php _e( '<strong>Blocked</strong> users will receive an error message when they try to visit the site after authenticating.', 'authorizer' ); ?></li>
3169 </ol>
3170 </div>
3171 <table class="form-table">
3172 <tbody>
3173 <tr>
3174 <th scope="row"><?php _e( 'Pending Users', 'authorizer' ); ?> <em>(<?php echo $this->get_user_count_from_list( 'pending', $admin_mode ); ?>)</em></th>
3175 <td><?php $this->print_combo_auth_access_users_pending(); ?></td>
3176 </tr>
3177 <tr>
3178 <th scope="row"><?php _e( 'Approved Users', 'authorizer' ); ?> <em>(<?php echo $this->get_user_count_from_list( 'approved', $admin_mode ); ?>)</em></th>
3179 <td><?php $this->print_combo_auth_access_users_approved(); ?></td>
3180 </tr>
3181 <tr>
3182 <th scope="row"><?php _e( 'Blocked Users', 'authorizer' ); ?> <em>(<?php echo $this->get_user_count_from_list( 'blocked', $admin_mode ); ?>)</em></th>
3183 <td><?php $this->print_combo_auth_access_users_blocked(); ?></td>
3184 </tr>
3185 </tbody>
3186 </table>
3187 <?php
3188 }
3189
3190
3191 function print_combo_auth_access_users_pending( $args = '' ) {
3192 // Get plugin option.
3193 $option = 'access_users_pending';
3194 $auth_settings_option = $this->get_plugin_option( $option );
3195 $auth_settings_option = is_array( $auth_settings_option ) ? $auth_settings_option : array();
3196
3197 // Print option elements.
3198 ?><ul id="list_auth_settings_access_users_pending" style="margin:0;">
3199 <?php if ( count( $auth_settings_option ) > 0 ) : ?>
3200 <?php foreach ( $auth_settings_option as $key => $pending_user ): ?>
3201 <?php if ( empty( $pending_user ) || count( $pending_user ) < 1 ) continue; ?>
3202 <?php $pending_user['is_wp_user'] = false; ?>
3203 <li>
3204 <input type="text" id="auth_settings_<?php echo $option; ?>_<?php echo $key; ?>" value="<?php echo $pending_user['email']; ?>" readonly="true" class="auth-email" />
3205 <select id="auth_settings_<?php echo $option; ?>_<?php echo $key; ?>_role" class="auth-role">
3206 <?php $this->wp_dropdown_permitted_roles( $pending_user['role'] ); ?>
3207 </select>
3208 <a href="javascript:void(0);" class="button-primary" id="approve_user_<?php echo $key; ?>" onclick="auth_add_user( this, 'approved', false ); auth_ignore_user( this, 'pending' );"><span class="glyphicon glyphicon-ok"></span> <?php _e( 'Approve', 'authorizer' ); ?></a>
3209 <a href="javascript:void(0);" class="button-primary" id="block_user_<?php echo $key; ?>" onclick="auth_add_user( this, 'blocked', false ); auth_ignore_user( this, 'pending' );"><span class="glyphicon glyphicon-ban-circle"></span> <?php _e( 'Block', 'authorizer' ); ?></a>
3210 <a href="javascript:void(0);" class="button button-secondary" id="ignore_user_<?php echo $key; ?>" onclick="auth_ignore_user( this, 'pending' );" title="<?php _e( 'Remove user', 'authorizer' ); ?>"><span class="glyphicon glyphicon-remove"></span> <?php _e( 'Ignore', 'authorizer' ); ?></a>
3211 </li>
3212 <?php endforeach; ?>
3213 <?php else: ?>
3214 <li class="auth-empty"><em><?php _e( 'No pending users', 'authorizer' ); ?></em></li>
3215 <?php endif; ?>
3216 </ul>
3217 <?php
3218 }
3219
3220
3221 function print_combo_auth_access_users_approved( $args = '' ) {
3222 // Get plugin option.
3223 $option = 'access_users_approved';
3224 $admin_mode = $this->get_admin_mode( $args );
3225 $auth_settings_option = $this->get_plugin_option( $option, $admin_mode, 'no override' );
3226 $auth_settings_option = is_array( $auth_settings_option ) ? $auth_settings_option : array();
3227
3228 // Get multisite approved users (add them to top of list, greyed out).
3229 $auth_override_multisite = $this->get_plugin_option( 'advanced_override_multisite' );
3230 $auth_multisite_settings = $this->get_plugin_options( MULTISITE_ADMIN );
3231 $auth_settings_option_multisite = array();
3232 if (
3233 is_multisite() &&
3234 $auth_override_multisite != '1' &&
3235 array_key_exists( 'multisite_override', $auth_multisite_settings ) &&
3236 $auth_multisite_settings['multisite_override'] === '1'
3237 ) {
3238 $auth_settings_option_multisite = $this->get_plugin_option( $option, MULTISITE_ADMIN, 'allow override' );
3239 $auth_settings_option_multisite = is_array( $auth_settings_option_multisite ) ? $auth_settings_option_multisite : array();
3240 }
3241
3242 // Get default role for new user dropdown.
3243 $access_default_role = $this->get_plugin_option( 'access_default_role', SINGLE_ADMIN, 'allow override' );
3244
3245 // Get custom usermeta field to show.
3246 $advanced_usermeta = $this->get_plugin_option( 'advanced_usermeta' );
3247
3248 // Adjust javascript function prefixes if multisite.
3249 $js_function_prefix = $admin_mode === MULTISITE_ADMIN ? 'auth_multisite_' : 'auth_';
3250 $multisite_admin_page = $admin_mode === MULTISITE_ADMIN;
3251
3252 ?><ul id="list_auth_settings_access_users_approved" style="margin:0;">
3253 <?php if ( ! $multisite_admin_page ) :
3254 foreach ( $auth_settings_option_multisite as $key => $approved_user ) :
3255 if ( empty( $approved_user ) || count( $approved_user ) < 1 ) :
3256 continue;
3257 endif;
3258 $approved_wp_user = get_user_by( 'email', $approved_user['email'] );
3259 if ( $approved_wp_user ) :
3260 $approved_user['email'] = $approved_wp_user->user_email;
3261 $approved_user['role'] = $multisite_admin_page || count( $approved_wp_user->roles ) === 0 ? $approved_user['role'] : array_shift( $approved_wp_user->roles );
3262 $approved_user['date_added'] = $approved_wp_user->user_registered;
3263 // Get usermeta field from the WordPress user's real usermeta.
3264 if ( strlen( $advanced_usermeta ) > 0 ) :
3265 if ( strpos( $advanced_usermeta, 'acf___' ) === 0 && class_exists( 'acf' ) ) :
3266 // Get ACF Field value for the user
3267 $approved_user['usermeta'] = get_field( str_replace('acf___', '', $advanced_usermeta ), 'user_' . $approved_wp_user->ID );
3268 else :
3269 // Get regular usermeta value for the user.
3270 $approved_user['usermeta'] = get_user_meta( $approved_wp_user->ID, $advanced_usermeta, true );
3271 endif;
3272
3273 if ( is_array( $approved_user['usermeta'] ) || is_object( $approved_user['usermeta'] ) ) :
3274 $approved_user['usermeta'] = serialize( $approved_user['usermeta'] );
3275 endif;
3276 endif;
3277 endif;
3278 if ( ! array_key_exists( 'usermeta', $approved_user ) ) :
3279 $approved_user['usermeta'] = '';
3280 endif; ?>
3281 <li>
3282 <input type="text" id="auth_multisite_settings_<?php echo $option; ?>_<?php echo $key; ?>" value="<?php echo $approved_user['email']; ?>" readonly="true" class="auth-email auth-multisite-email" />
3283 <select id="auth_multisite_settings_<?php echo $option; ?>_<?php echo $key; ?>_role" class="auth-role auth-multisite-role" disabled="disabled">
3284 <?php $this->wp_dropdown_permitted_roles( $approved_user['role'] ); ?>
3285 </select>
3286 <input type="text" id="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" />
3287 <?php if ( strlen( $advanced_usermeta ) > 0 ) :
3288 $should_show_usermeta_in_text_field = true; // Fallback renderer for usermeta; try to use a select first.
3289 if ( strpos( $advanced_usermeta, 'acf___' ) === 0 && class_exists( 'acf' ) ) :
3290 $field_object = get_field_object( str_replace('acf___', '', $advanced_usermeta ) );
3291 if ( is_array( $field_object ) && array_key_exists( 'type', $field_object ) && $field_object['type'] === 'select' ) :
3292 $should_show_usermeta_in_text_field = false; ?>
3293 <select id="auth_settings_<?php echo $option; ?>_<?php echo $key; ?>_usermeta" class="auth-usermeta auth-multisite-usermeta" onchange="<?php echo $js_function_prefix; ?>update_usermeta( this );">
3294 <option value=""<?php if ( empty( $approved_user['usermeta'] ) ) echo ' selected="selected"'; ?>><?php _e( '-- None --', 'authorizer' ); ?></option>
3295 <?php foreach ( $field_object['choices'] as $key => $label ) : ?>
3296 <option value="<?php echo $key; ?>"<?php if ( $key === $approved_user['usermeta'] || ( is_array( $approved_user['usermeta'] ) && array_key_exists( get_current_blog_id(), $approved_user['usermeta'] ) && $key === $approved_user['usermeta'][get_current_blog_id()]['meta_value'] ) ) echo ' selected="selected"'; ?>><?php echo $label; ?></option>
3297 <?php endforeach; ?>
3298 </select>
3299 <?php endif; ?>
3300 <?php endif; ?>
3301 <?php if ( $should_show_usermeta_in_text_field ) : ?>
3302 <input type="text" id="auth_multisite_settings_<?php echo $option; ?>_<?php echo $key; ?>_usermeta" value="<?php echo htmlspecialchars( $approved_user['usermeta'], ENT_COMPAT ); ?>" class="auth-usermeta auth-multisite-usermeta" />
3303 <a class="button button-small button-primary update-usermeta" 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>
3304 <?php endif; ?>
3305 <?php endif; ?>
3306 &nbsp;&nbsp;<a title="WordPress Multisite user" class="auth-multisite-user"><span class="glyphicon glyphicon-globe"></span></a>
3307 </li>
3308 <?php endforeach;
3309 endif;
3310 foreach ( $auth_settings_option as $key => $approved_user ):
3311 $is_current_user = false;
3312 $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>' : '';
3313 if ( empty( $approved_user ) || count( $approved_user ) < 1 ) :
3314 continue;
3315 endif;
3316 $approved_wp_user = get_user_by( 'email', $approved_user['email'] );
3317 if ( $approved_wp_user ) :
3318 $approved_user['email'] = $approved_wp_user->user_email;
3319 $approved_user['role'] = $multisite_admin_page || count( $approved_wp_user->roles ) === 0 ? $approved_user['role'] : array_shift( $approved_wp_user->roles );
3320 $approved_user['date_added'] = $approved_wp_user->user_registered;
3321 $approved_user['is_wp_user'] = true;
3322 $is_current_user = $approved_wp_user->ID === get_current_user_id();
3323 // Get usermeta field from the WordPress user's real usermeta.
3324 if ( strlen( $advanced_usermeta ) > 0 ) :
3325 if ( strpos( $advanced_usermeta, 'acf___' ) === 0 && class_exists( 'acf' ) ) :
3326 // Get ACF Field value for the user
3327 $approved_user['usermeta'] = get_field( str_replace('acf___', '', $advanced_usermeta ), 'user_' . $approved_wp_user->ID );
3328 else :
3329 // Get regular usermeta value for the user.
3330 $approved_user['usermeta'] = get_user_meta( $approved_wp_user->ID, $advanced_usermeta, true );
3331 endif;
3332
3333 if ( is_array( $approved_user['usermeta'] ) || is_object( $approved_user['usermeta'] ) ) :
3334 $approved_user['usermeta'] = serialize( $approved_user['usermeta'] );
3335 endif;
3336 endif;
3337 else :
3338 $approved_user['is_wp_user'] = false;
3339 endif;
3340 if ( ! array_key_exists( 'usermeta', $approved_user ) ) :
3341 $approved_user['usermeta'] = '';
3342 endif; ?>
3343 <li>
3344 <input type="text" id="auth_settings_<?php echo $option; ?>_<?php echo $key; ?>" value="<?php echo $approved_user['email']; ?>" readonly="true" class="auth-email" />
3345 <select id="auth_settings_<?php echo $option; ?>_<?php echo $key; ?>_role" class="auth-role" onchange="<?php echo $js_function_prefix; ?>change_role( this );">
3346 <?php $disable_input = $is_current_user ? 'disabled' : null; ?>
3347 <?php $this->wp_dropdown_permitted_roles( $approved_user['role'], $disable_input, $admin_mode ); ?>
3348 </select>
3349 <input type="text" id="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" />
3350 <?php if ( strlen( $advanced_usermeta ) > 0 ) :
3351 $should_show_usermeta_in_text_field = true; // Fallback renderer for usermeta; try to use a select first.
3352 if ( strpos( $advanced_usermeta, 'acf___' ) === 0 && class_exists( 'acf' ) ) :
3353 $field_object = get_field_object( str_replace('acf___', '', $advanced_usermeta ) );
3354 if ( is_array( $field_object ) && array_key_exists( 'type', $field_object ) && $field_object['type'] === 'select' ) :
3355 $should_show_usermeta_in_text_field = false; ?>
3356 <select id="auth_settings_<?php echo $option; ?>_<?php echo $key; ?>_usermeta" class="auth-usermeta" onchange="<?php echo $js_function_prefix; ?>update_usermeta( this );" >
3357 <option value=""<?php if ( empty( $approved_user['usermeta'] ) ) echo ' selected="selected"'; ?>><?php _e( '-- None --', 'authorizer' ); ?></option>
3358 <?php foreach ( $field_object['choices'] as $key => $label ) : ?>
3359 <option value="<?php echo $key; ?>"<?php if ( $key === $approved_user['usermeta'] || ( is_array( $approved_user['usermeta'] ) && $key === $approved_user['usermeta']['meta_value'] ) ) echo ' selected="selected"'; ?>><?php echo $label; ?></option>
3360 <?php endforeach; ?>
3361 </select>
3362 <?php endif; ?>
3363 <?php endif; ?>
3364 <?php if ( $should_show_usermeta_in_text_field ) : ?>
3365 <input type="text" id="auth_settings_<?php echo $option; ?>_<?php echo $key; ?>_usermeta" value="<?php echo htmlspecialchars( $approved_user['usermeta'], ENT_COMPAT ); ?>" class="auth-usermeta" />
3366 <a class="button button-small button-primary update-usermeta" 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>
3367 <?php endif; ?>
3368 <?php endif; ?>
3369 <?php if ( ! $is_current_user ): ?>
3370 <?php if ( ! $multisite_admin_page ) : ?>
3371 <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="<?php _e( 'Block/Ban user', 'authorizer' ); ?>"><span class="glyphicon glyphicon-ban-circle"></span></a>
3372 <?php endif; ?>
3373 <a class="button" id="ignore_user_<?php echo $key; ?>" onclick="<?php echo $js_function_prefix; ?>ignore_user(this, 'approved' );" title="<?php _e( 'Remove user', 'authorizer' ); ?>"><span class="glyphicon glyphicon-remove"></span></a>
3374 <?php endif; ?>
3375 <?php echo $local_user_icon; ?>
3376 </li>
3377 <?php endforeach; ?>
3378 </ul>
3379 <div id="new_auth_settings_<?php echo $option; ?>">
3380 <input type="text" id="new_approved_user_email" placeholder="<?php _e( 'email address', 'authorizer' ); ?>" class="auth-email new" />
3381 <select id="new_approved_user_role" class="auth-role">
3382 <?php $this->wp_dropdown_permitted_roles( $access_default_role, 'not disabled', $admin_mode ); ?>
3383 </select>
3384 <div class="btn-group">
3385 <a href="javascript:void(0);" class="btn button-primary dropdown-toggle" id="approve_user_new" onclick="<?php echo $js_function_prefix; ?>add_user(this, 'approved' );"><span class="glyphicon glyphicon-ok"></span> <?php _e( 'Approve', 'authorizer' ); ?></a>
3386 <button type="button" class="btn button-primary dropdown-toggle" data-toggle="dropdown">
3387 <span class="caret"></span>
3388 <span class="sr-only"><?php _e( 'Toggle Dropdown', 'authorizer' ); ?></span>
3389 </button>
3390 <ul class="dropdown-menu" role="menu">
3391 <li><a href="javascript:void(0);" onclick="<?php echo $js_function_prefix; ?>add_user( document.getElementById('approve_user_new' ), 'approved', true);"><?php _e( 'Create a local WordPress <br />account instead, and email <br />the user their password.', 'authorizer' ); ?></a></li>
3392 </ul>
3393 </div>
3394 </div>
3395 <?php
3396 }
3397
3398
3399 function print_combo_auth_access_users_blocked( $args = '' ) {
3400 // Get plugin option.
3401 $option = 'access_users_blocked';
3402 $auth_settings_option = $this->get_plugin_option( $option );
3403 $auth_settings_option = is_array( $auth_settings_option ) ? $auth_settings_option : array();
3404
3405 // Get default role for new blocked user dropdown.
3406 $access_default_role = $this->get_plugin_option( 'access_default_role', SINGLE_ADMIN, 'allow override' );
3407
3408 // Print option elements.
3409 ?><ul id="list_auth_settings_<?php echo $option; ?>" style="margin:0;">
3410 <?php foreach ( $auth_settings_option as $key => $blocked_user ): ?>
3411 <?php if ( empty( $blocked_user ) || count( $blocked_user ) < 1 ) continue; ?>
3412 <?php if ( $blocked_wp_user = get_user_by( 'email', $blocked_user['email'] ) ): ?>
3413 <?php $blocked_user['email'] = $blocked_wp_user->user_email; ?>
3414 <?php $blocked_user['role'] = array_shift( $blocked_wp_user->roles ); ?>
3415 <?php $blocked_user['date_added'] = $blocked_wp_user->user_registered; ?>
3416 <?php $blocked_user['is_wp_user'] = true; ?>
3417 <?php else: ?>
3418 <?php $blocked_user['is_wp_user'] = false; ?>
3419 <?php endif; ?>
3420 <li>
3421 <input type="text" id="auth_settings_<?php echo $option; ?>_<?php echo $key; ?>" value="<?php echo $blocked_user['email']; ?>" readonly="true" class="auth-email" />
3422 <select id="auth_settings_<?php echo $option; ?>_<?php echo $key; ?>_role" class="auth-role">
3423 <?php $this->wp_dropdown_permitted_roles( $blocked_user['role'] ); ?>
3424 </select>
3425 <input type="text" id="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" />
3426 <a class="button" id="ignore_user_<?php echo $key; ?>" onclick="auth_ignore_user(this, 'blocked' );" title="<?php _e( 'Remove user', 'authorizer' ); ?>"><span class="glyphicon glyphicon-remove"></span></a>
3427 </li>
3428 <?php endforeach; ?>
3429 </ul>
3430 <div id="new_auth_settings_<?php echo $option; ?>">
3431 <input type="text" id="new_blocked_user_email" placeholder="<?php _e( 'email address', 'authorizer' ); ?>" class="auth-email new" />
3432 <select id="new_blocked_user_role" class="auth-role">
3433 <option value="<?php echo $access_default_role; ?>"><?php echo ucfirst( $access_default_role ); ?></option>
3434 </select>
3435 <a href="javascript:void(0);" class="button-primary" id="block_user_new" onclick="auth_add_user(this, 'blocked' );"><span class="glyphicon glyphicon-ban-circle"></span> <?php _e( 'Block', 'authorizer' ); ?></a>
3436 </div>
3437 <?php
3438 }
3439
3440
3441 function print_section_info_access_login( $args = '' ) {
3442 ?><div id="section_info_access_login" class="section_info">
3443 <?php wp_nonce_field( 'save_auth_settings', 'nonce_save_auth_settings' ); ?>
3444 <p><?php _e( 'Choose who is able to log into this site below.', 'authorizer' ); ?></p>
3445 </div><?php
3446 }
3447
3448
3449 function print_radio_auth_access_who_can_login( $args = '' ) {
3450 // Get plugin option.
3451 $option = 'access_who_can_login';
3452 $admin_mode = $this->get_admin_mode( $args );
3453 $auth_settings_option = $this->get_plugin_option( $option, $admin_mode, 'allow override', 'print overlay' );
3454
3455 // If this site is configured independently of any multisite overrides, make sure we are not grabbing the multisite value; otherwise, grab the multisite value to show behind the disabled overlay.
3456 if ( is_multisite() && $this->get_plugin_option( 'advanced_override_multisite' ) == '1' ) {
3457 $auth_settings_option = $this->get_plugin_option( $option );
3458 } elseif ( is_multisite() && $admin_mode === SINGLE_ADMIN && $this->get_plugin_option( 'multisite_override', MULTISITE_ADMIN ) === '1' ) {
3459 // Workaround: javascript code hides/shows other settings based
3460 // on the selection in this option. If this option is overridden
3461 // by a multisite option, it should show that value in order to
3462 // correctly display the other appropriate options.
3463 // Side effect: this site option will be overwritten by the
3464 // multisite option on save. Since this is a 2-item radio, we
3465 // determined this was acceptable.
3466 $auth_settings_option = $this->get_plugin_option( $option, MULTISITE_ADMIN );
3467 }
3468
3469 // Print option elements.
3470 ?><input type="radio" id="radio_auth_settings_<?php echo $option; ?>_external_users" name="auth_settings[<?php echo $option; ?>]" value="external_users"<?php checked( 'external_users' == $auth_settings_option ); ?> /><label for="radio_auth_settings_<?php echo $option; ?>_external_users"><?php _e( 'All authenticated users (All external service users and all WordPress users)', 'authorizer' ); ?></label><br />
3471 <input type="radio" id="radio_auth_settings_<?php echo $option; ?>_approved_users" name="auth_settings[<?php echo $option; ?>]" value="approved_users"<?php checked( 'approved_users' == $auth_settings_option ); ?> /><label for="radio_auth_settings_<?php echo $option; ?>_approved_users"><?php _e( 'Only', 'authorizer' ); ?> <a href="javascript:choose_tab('access_lists' );" id="dashboard_link_approved_users"><?php _e( 'approved users', 'authorizer' ); ?></a> <?php _e( '(Approved external users and all WordPress users)', 'authorizer' ); ?></label><br /><?php
3472 }
3473
3474
3475 function print_select_auth_access_role_receive_pending_emails( $args = '' ) {
3476 // Get plugin option.
3477 $option = 'access_role_receive_pending_emails';
3478 $auth_settings_option = $this->get_plugin_option( $option );
3479
3480 // Print option elements.
3481 ?><select id="auth_settings_<?php echo $option; ?>" name="auth_settings[<?php echo $option; ?>]">
3482 <option value="---" <?php selected( $auth_settings_option, '---' ); ?>><?php _e( "None (Don't send notification emails)", 'authorizer' ); ?></option>
3483 <?php wp_dropdown_roles( $auth_settings_option ); ?>
3484 </select><?php
3485 }
3486
3487
3488 function print_wysiwyg_auth_access_pending_redirect_to_message( $args = '' ) {
3489 // Get plugin option.
3490 $option = 'access_pending_redirect_to_message';
3491 $auth_settings_option = $this->get_plugin_option( $option );
3492
3493 // Print option elements.
3494 wp_editor(
3495 wpautop( $auth_settings_option ),
3496 "auth_settings_$option",
3497 array(
3498 'media_buttons' => false,
3499 'textarea_name' => "auth_settings[$option]",
3500 'textarea_rows' => 5,
3501 'tinymce' => true,
3502 'teeny' => true,
3503 'quicktags' => false,
3504 )
3505 );
3506 }
3507
3508
3509 function print_wysiwyg_auth_access_blocked_redirect_to_message( $args = '' ) {
3510 // Get plugin option.
3511 $option = 'access_blocked_redirect_to_message';
3512 $auth_settings_option = $this->get_plugin_option( $option );
3513
3514 // Print option elements.
3515 wp_editor(
3516 wpautop( $auth_settings_option ),
3517 "auth_settings_$option",
3518 array(
3519 'media_buttons' => false,
3520 'textarea_name' => "auth_settings[$option]",
3521 'textarea_rows' => 5,
3522 'tinymce' => true,
3523 'teeny' => true,
3524 'quicktags' => false,
3525 )
3526 );
3527 }
3528
3529
3530 function print_checkbox_auth_access_should_email_approved_users( $args = '' ) {
3531 // Get plugin option.
3532 $option = 'access_should_email_approved_users';
3533 $auth_settings_option = $this->get_plugin_option( $option );
3534
3535 // Print option elements.
3536 ?><input type="checkbox" id="auth_settings_<?php echo $option; ?>" name="auth_settings[<?php echo $option; ?>]" value="1"<?php checked( 1 == $auth_settings_option ); ?> /><label for="auth_settings_<?php echo $option; ?>"><?php _e( 'Send a welcome email when approving a new user', 'authorizer' ); ?></label><?php
3537 }
3538
3539
3540 function print_text_auth_access_email_approved_users_subject( $args = '' ) {
3541 // Get plugin option.
3542 $option = 'access_email_approved_users_subject';
3543 $auth_settings_option = $this->get_plugin_option( $option );
3544
3545 // Print option elements.
3546 ?><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><?php _e( 'You can use the <b>[site_name]</b> shortcode.', 'authorizer' ); ?></small><?php
3547 }
3548
3549
3550 function print_wysiwyg_auth_access_email_approved_users_body( $args = '' ) {
3551 // Get plugin option.
3552 $option = 'access_email_approved_users_body';
3553 $auth_settings_option = $this->get_plugin_option( $option );
3554
3555 // Print option elements.
3556 wp_editor(
3557 wpautop( $auth_settings_option ),
3558 "auth_settings_$option",
3559 array(
3560 'media_buttons' => false,
3561 'textarea_name' => "auth_settings[$option]",
3562 'textarea_rows' => 9,
3563 'tinymce' => true,
3564 'teeny' => true,
3565 'quicktags' => false,
3566 )
3567 );
3568
3569 ?><small><?php printf(
3570 /* TRANSLATORS: 1: Shortcode for site name 2: Shortcode for site URL 3: Shortcode for user email */
3571 __( 'You can use %1$s, %2$s, and %3$s shortcodes.', 'authorizer' ),
3572 '<b>[site_name]</b>',
3573 '<b>[site_url]</b>',
3574 '<b>[user_email]</b>'
3575 ); ?></small><?php
3576
3577 }
3578
3579
3580 function print_section_info_access_public( $args = '' ) {
3581 ?><div id="section_info_access_public" class="section_info">
3582 <p><?php _e( 'Choose your public access options here.', 'authorizer' ); ?></p>
3583 </div><?php
3584 }
3585
3586
3587 function print_radio_auth_access_who_can_view( $args = '' ) {
3588 // Get plugin option.
3589 $option = 'access_who_can_view';
3590 $admin_mode = $this->get_admin_mode( $args );
3591 $auth_settings_option = $this->get_plugin_option( $option, $admin_mode, 'allow override', 'print overlay' );
3592
3593 // If this site is configured independently of any multisite overrides, make sure we are not grabbing the multisite value; otherwise, grab the multisite value to show behind the disabled overlay.
3594 if ( is_multisite() && $this->get_plugin_option( 'advanced_override_multisite' ) == '1' ) {
3595 $auth_settings_option = $this->get_plugin_option( $option );
3596 } elseif ( is_multisite() && $admin_mode === SINGLE_ADMIN && $this->get_plugin_option( 'multisite_override', MULTISITE_ADMIN ) === '1' ) {
3597 // Workaround: javascript code hides/shows other settings based
3598 // on the selection in this option. If this option is overridden
3599 // by a multisite option, it should show that value in order to
3600 // correctly display the other appropriate options.
3601 // Side effect: this site option will be overwritten by the
3602 // multisite option on save. Since this is a 2-item radio, we
3603 // determined this was acceptable.
3604 $auth_settings_option = $this->get_plugin_option( $option, MULTISITE_ADMIN );
3605 }
3606
3607 // Print option elements.
3608 ?><input type="radio" id="radio_auth_settings_<?php echo $option; ?>_everyone" name="auth_settings[<?php echo $option; ?>]" value="everyone"<?php checked( 'everyone' == $auth_settings_option ); ?> /><label for="radio_auth_settings_<?php echo $option; ?>_everyone"><?php _e( 'Everyone can see the site', 'authorizer' ); ?></label><br />
3609 <input type="radio" id="radio_auth_settings_<?php echo $option; ?>_logged_in_users" name="auth_settings[<?php echo $option; ?>]" value="logged_in_users"<?php checked( 'logged_in_users' == $auth_settings_option ); ?> /><label for="radio_auth_settings_<?php echo $option; ?>_logged_in_users"><?php _e( 'Only logged in users can see the site', 'authorizer' ); ?></label><br /><?php
3610 }
3611
3612
3613 function print_radio_auth_access_redirect( $args = '' ) {
3614 // Get plugin option.
3615 $option = 'access_redirect';
3616 $auth_settings_option = $this->get_plugin_option( $option );
3617
3618 // Print option elements.
3619 ?><input type="radio" id="radio_auth_settings_<?php echo $option; ?>_to_login" name="auth_settings[<?php echo $option; ?>]" value="login"<?php checked( 'login' == $auth_settings_option ); ?> /><label for="radio_auth_settings_<?php echo $option; ?>_to_login"><?php _e( 'Send them to the login screen', 'authorizer' ); ?></label><br />
3620 <input type="radio" id="radio_auth_settings_<?php echo $option; ?>_to_message" name="auth_settings[<?php echo $option; ?>]" value="message"<?php checked( 'message' == $auth_settings_option ); ?> /><label for="radio_auth_settings_<?php echo $option; ?>_to_message"><?php _e( 'Show them the anonymous access message (below)', 'authorizer' ); ?></label><?php
3621 }
3622
3623
3624 function print_radio_auth_access_public_warning( $args = '' ) {
3625 // Get plugin option.
3626 $option = 'access_public_warning';
3627 $auth_settings_option = $this->get_plugin_option( $option );
3628
3629 // Print option elements.
3630 ?><input type="radio" id="radio_auth_settings_<?php echo $option; ?>_no" name="auth_settings[<?php echo $option; ?>]" value="no_warning"<?php checked( 'no_warning' == $auth_settings_option ); ?> /><label for="radio_auth_settings_<?php echo $option; ?>_no"><?php _e( 'Show them the page <strong>without</strong> the anonymous access message', 'authorizer' ); ?></label><br />
3631 <input type="radio" id="radio_auth_settings_<?php echo $option; ?>" name="auth_settings[<?php echo $option; ?>]" value="warning"<?php checked( 'warning' == $auth_settings_option ); ?> /><label for="radio_auth_settings_<?php echo $option; ?>"><?php _e( 'Show them the page <strong>with</strong> the anonymous access message (marked up as a <a href="http://getbootstrap.com/components/#alerts-dismissible" target="_blank">Bootstrap Dismissible Alert</a>)', 'authorizer' ); ?></label><?php
3632 }
3633
3634
3635 function print_wysiwyg_auth_access_redirect_to_message( $args = '' ) {
3636 // Get plugin option.
3637 $option = 'access_redirect_to_message';
3638 $auth_settings_option = $this->get_plugin_option( $option );
3639
3640 // Print option elements.
3641 wp_editor(
3642 wpautop( $auth_settings_option ),
3643 "auth_settings_$option",
3644 array(
3645 'media_buttons' => false,
3646 'textarea_name' => "auth_settings[$option]",
3647 'textarea_rows' => 5,
3648 'tinymce' => true,
3649 'teeny' => true,
3650 'quicktags' => false,
3651 )
3652 );
3653 }
3654
3655
3656 function print_multiselect_auth_access_public_pages( $args = '' ) {
3657 // Get plugin option.
3658 $option = 'access_public_pages';
3659 $auth_settings_option = $this->get_plugin_option( $option );
3660 $auth_settings_option = is_array( $auth_settings_option ) ? $auth_settings_option : array();
3661
3662 $post_types = array_merge( array( 'page', 'post' ), get_post_types( array( '_builtin' => false ), 'names' ) );
3663 $post_types = is_array( $post_types ) ? $post_types : array();
3664
3665 // Print option elements.
3666 ?><select id="auth_settings_<?php echo $option; ?>" multiple="multiple" name="auth_settings[<?php echo $option; ?>][]">
3667 <optgroup label="<?php _e( 'Home', 'authorizer' ); ?>">
3668 <option value="home" <?php echo in_array( 'home', $auth_settings_option ) ? 'selected="selected"' : ''; ?>><?php _e( 'Home Page', 'authorizer' ); ?></option>
3669 <option value="auth_public_404" <?php echo in_array( 'auth_public_404', $auth_settings_option ) ? 'selected="selected"' : ''; ?>><?php _e( 'Nonexistent (404) Pages', 'authorizer' ); ?></option>
3670 </optgroup>
3671 <?php foreach ( $post_types as $post_type ): ?>
3672 <optgroup label="<?php echo ucfirst( $post_type ); ?>">
3673 <?php $pages = get_posts( array( 'post_type' => $post_type, 'posts_per_page' => -1 ) ); ?>
3674 <?php $pages = is_array( $pages ) ? $pages : array(); ?>
3675 <?php foreach ( $pages as $page ): ?>
3676 <option value="<?php echo $page->ID; ?>" <?php echo in_array( $page->ID, $auth_settings_option ) ? 'selected="selected"' : ''; ?>><?php echo $page->post_title; ?></option>
3677 <?php endforeach; ?>
3678 </optgroup>
3679 <?php endforeach; ?>
3680 <optgroup label="<?php _e( 'Categories', 'authorizer' ); ?>">
3681 <?php
3682 // If sitepress-multilingual-cms plugin is enabled, temporarily disable
3683 // its terms_clauses filter since it conflicts with the category handling.
3684 if ( array_key_exists( 'sitepress', $GLOBALS ) && is_object( $GLOBALS['sitepress'] ) ) {
3685 remove_filter( 'terms_clauses', array( $GLOBALS['sitepress'], 'terms_clauses' ) );
3686 $categories = get_categories( array( 'hide_empty' => false ) );
3687 add_filter( 'terms_clauses', array( $GLOBALS['sitepress'], 'terms_clauses' ) );
3688 } else {
3689 $categories = get_categories( array( 'hide_empty' => false ) );
3690 }
3691 foreach ( $categories as $category ) : ?>
3692 <option value="<?php echo 'cat_' . $category->slug; ?>" <?php echo in_array( 'cat_' . $category->slug, $auth_settings_option ) ? 'selected="selected"' : ''; ?>><?php echo $category->name; ?></option>
3693 <?php endforeach; ?>
3694 </optgroup>
3695 </select><?php
3696 }
3697
3698
3699 function print_section_info_external( $args = '' ) {
3700 ?><div id="section_info_external" class="section_info">
3701 <p><?php _e( 'Enter your external server settings below.', 'authorizer' ); ?></p>
3702 </div><?php
3703 }
3704
3705
3706 function get_admin_mode( $args ) {
3707 if ( is_array( $args ) && array_key_exists( MULTISITE_ADMIN, $args ) && $args[MULTISITE_ADMIN] === true ) {
3708 return MULTISITE_ADMIN;
3709 } else {
3710 return SINGLE_ADMIN;
3711 }
3712 }
3713
3714
3715 function print_select_auth_access_default_role( $args = '' ) {
3716 // Get plugin option.
3717 $option = 'access_default_role';
3718 $auth_settings_option = $this->get_plugin_option( $option, $this->get_admin_mode( $args ), 'allow override', 'print overlay' );
3719
3720 // Print option elements.
3721 ?><select id="auth_settings_<?php echo $option; ?>" name="auth_settings[<?php echo $option; ?>]">
3722 <?php wp_dropdown_roles( $auth_settings_option ); ?>
3723 </select><?php
3724 }
3725
3726
3727 function print_checkbox_auth_external_google( $args = '' ) {
3728 // Get plugin option.
3729 $option = 'google';
3730 $auth_settings_option = $this->get_plugin_option( $option, $this->get_admin_mode( $args ), 'allow override', 'print overlay' );
3731
3732 // Print option elements.
3733 ?><input type="checkbox" id="auth_settings_<?php echo $option; ?>" name="auth_settings[<?php echo $option; ?>]" value="1"<?php checked( 1 == $auth_settings_option ); ?> /><label for="auth_settings_<?php echo $option; ?>"><?php _e( 'Enable Google Logins', 'authorizer' ); ?></label><?php
3734 }
3735
3736
3737 function print_text_google_clientid( $args = '' ) {
3738 // Get plugin option.
3739 $option = 'google_clientid';
3740 $auth_settings_option = $this->get_plugin_option( $option, $this->get_admin_mode( $args ), 'allow override', 'print overlay' );
3741
3742 // Print option elements.
3743 $site_url_parts = parse_url( get_site_url() );
3744 $site_url_host = $site_url_parts['scheme'] . '://' . $site_url_parts['host'] . '/';
3745 ?><?php _e( "If you don't have a Google Client ID and Secret, generate them by following these instructions:", 'authorizer' ); ?>
3746 <ol>
3747 <li><?php _e( '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.', 'authorizer' ); ?></li>
3748 <li><?php _e( '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:', 'authorizer' ); ?>
3749 <ul>
3750 <li><?php _e( 'Application Type: <strong>Web application</strong>', 'authorizer' ); ?></li>
3751 <li><?php _e( 'Authorized Javascript Origins:', 'authorizer' ); ?> <strong><?php echo rtrim( $site_url_host, '/' ); ?></strong></li>
3752 <li><?php _e( 'Authorized Redirect URI: <em>none</em>', 'authorizer' ); ?></li>
3753 </ul>
3754 </li>
3755 <li><?php _e( 'Copy/paste your new Client ID/Secret pair into the fields below.', 'authorizer' ); ?></li>
3756 <li><?php _e( '<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.', 'authorizer' ); ?></li>
3757 <li><?php _e( 'Note: Google may have a more recent version of these instructions in their <a href="https://developers.google.com/identity/sign-in/web/devconsole-project" target="_blank">developer documentation</a>.', 'authorizer' ); ?></li>
3758 </ol>
3759 <input type="text" id="auth_settings_<?php echo $option; ?>" name="auth_settings[<?php echo $option; ?>]" value="<?php echo $auth_settings_option; ?>" placeholder="" style="width:560px;" />
3760 <br /><label for="auth_settings_<?php echo $option; ?>" class="helper"><?php _e( 'Example: 1234567890123-kdjr85yt6vjr6d8g7dhr8g7d6durjf7g.apps.googleusercontent.com', 'authorizer'); ?></label><?php
3761 }
3762
3763
3764 function print_text_google_clientsecret( $args = '' ) {
3765 // Get plugin option.
3766 $option = 'google_clientsecret';
3767 $auth_settings_option = $this->get_plugin_option( $option, $this->get_admin_mode( $args ), 'allow override', 'print overlay' );
3768
3769 // Print option elements.
3770 ?><input type="text" id="auth_settings_<?php echo $option; ?>" name="auth_settings[<?php echo $option; ?>]" value="<?php echo $auth_settings_option; ?>" placeholder="" style="width:220px;" />
3771 <br /><label for="auth_settings_<?php echo $option; ?>" class="helper"><?php _e( 'Example: sDNgX5_pr_5bly-frKmvp8jT', 'authorizer'); ?></label><?php
3772 }
3773
3774
3775 function print_text_google_hosteddomain( $args = '' ) {
3776 // Get plugin option.
3777 $option = 'google_hosteddomain';
3778 $auth_settings_option = $this->get_plugin_option( $option, $this->get_admin_mode( $args ), 'allow override', 'print overlay' );
3779
3780 // Print option elements.
3781 ?><textarea id="auth_settings_<?php echo $option; ?>" name="auth_settings[<?php echo $option; ?>]" placeholder="" style="width:220px;"><?php echo $auth_settings_option; ?></textarea>
3782 <br /><small><?php _e( 'Restrict Google logins to a specific Google Apps hosted domain (for example, mycollege.edu). Leave blank to allow all Google sign-ins.', 'authorizer' ); ?><br /><?php _e( 'If restricting to multiple domains, add one domain per line.', 'authorizer' ); ?></small>
3783 <?php
3784 }
3785
3786
3787 function print_checkbox_auth_external_cas( $args = '' ) {
3788 // Get plugin option.
3789 $option = 'cas';
3790 $auth_settings_option = $this->get_plugin_option( $option, $this->get_admin_mode( $args ), 'allow override', 'print overlay' );
3791
3792 // Make sure php5-curl extension is installed on server.
3793 $curl_installed_message = ! function_exists( 'curl_init' ) ? __( '<a href="http://www.php.net//manual/en/curl.installation.php" target="_blank" style="color: red;">PHP CURL extension</a> is not installed', 'authorizer' ) : '';
3794
3795 // Make sure php_openssl extension is installed on server.
3796 $openssl_installed_message = ! extension_loaded( 'openssl' ) ? __( '<a href="http://stackoverflow.com/questions/23424459/enable-php-openssl-not-working" target="_blank" style="color: red;">PHP openssl extension</a> is not installed', 'authorizer' ) : '';
3797
3798 // Build error message string.
3799 $error_message = '';
3800 if ( strlen( $curl_installed_message ) > 0 || strlen( $openssl_installed_message ) > 0 ) {
3801 $error_message = '<span style="color: red;">(' .
3802 __( 'Warning', 'authorizer' ) . ': ' .
3803 $curl_installed_message .
3804 ( strlen( $curl_installed_message ) > 0 && strlen( $openssl_installed_message ) > 0 ? '; ' : '' ) .
3805 $openssl_installed_message .
3806 ')</span>';
3807 }
3808
3809 // Print option elements.
3810 ?><input type="checkbox" id="auth_settings_<?php echo $option; ?>" name="auth_settings[<?php echo $option; ?>]" value="1"<?php checked( 1 == $auth_settings_option ); ?> /><label for="auth_settings_<?php echo $option; ?>"><?php _e( 'Enable CAS Logins', 'authorizer' ); ?></label> <?php echo $error_message; ?><?php
3811 }
3812
3813
3814 function print_text_cas_custom_label( $args = '' ) {
3815 // Get plugin option.
3816 $option = 'cas_custom_label';
3817 $auth_settings_option = $this->get_plugin_option( $option, $this->get_admin_mode( $args ), 'allow override', 'print overlay' );
3818
3819 // Print option elements.
3820 ?><?php _e( 'The button on the login page will read:', 'authorizer' ); ?><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><?php _e( 'Sign in with', 'authorizer' ); ?> </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
3821 }
3822
3823
3824 function print_text_cas_host( $args = '' ) {
3825 // Get plugin option.
3826 $option = 'cas_host';
3827 $auth_settings_option = $this->get_plugin_option( $option, $this->get_admin_mode( $args ), 'allow override', 'print overlay' );
3828
3829 // Print option elements.
3830 ?><input type="text" id="auth_settings_<?php echo $option; ?>" name="auth_settings[<?php echo $option; ?>]" value="<?php echo $auth_settings_option; ?>" placeholder="" />
3831 <br /><label for="auth_settings_<?php echo $option; ?>" class="helper"><?php _e( 'Example: authn.example.edu', 'authorizer'); ?></label><?php
3832 }
3833
3834
3835 function print_text_cas_port( $args = '' ) {
3836 // Get plugin option.
3837 $option = 'cas_port';
3838 $auth_settings_option = $this->get_plugin_option( $option, $this->get_admin_mode( $args ), 'allow override', 'print overlay' );
3839
3840 // Print option elements.
3841 ?><input type="text" id="auth_settings_<?php echo $option; ?>" name="auth_settings[<?php echo $option; ?>]" value="<?php echo $auth_settings_option; ?>" placeholder="" style="width:50px;" />
3842 <br /><label for="auth_settings_<?php echo $option; ?>" class="helper"><?php _e( 'Example: 443', 'authorizer'); ?></label><?php
3843 }
3844
3845
3846 function print_text_cas_path( $args = '' ) {
3847 // Get plugin option.
3848 $option = 'cas_path';
3849 $auth_settings_option = $this->get_plugin_option( $option, $this->get_admin_mode( $args ), 'allow override', 'print overlay' );
3850
3851 // Print option elements.
3852 ?><input type="text" id="auth_settings_<?php echo $option; ?>" name="auth_settings[<?php echo $option; ?>]" value="<?php echo $auth_settings_option; ?>" placeholder="" />
3853 <br /><label for="auth_settings_<?php echo $option; ?>" class="helper"><?php _e( 'Example: /cas', 'authorizer'); ?></label><?php
3854 }
3855
3856
3857 function print_select_cas_version( $args = '' ) {
3858 // Get plugin option.
3859 $option = 'cas_version';
3860 $auth_settings_option = $this->get_plugin_option( $option, $this->get_admin_mode( $args ), 'allow override', 'print overlay' );
3861
3862 // Print option elements.
3863 ?><select id="auth_settings_<?php echo $option; ?>" name="auth_settings[<?php echo $option; ?>]">
3864 <option value="SAML_VERSION_1_1" <?php selected( $auth_settings_option, 'SAML_VERSION_1_1' ); ?>>SAML_VERSION_1_1</option>
3865 <option value="CAS_VERSION_3_0" <?php selected( $auth_settings_option, 'CAS_VERSION_3_0' ); ?>>CAS_VERSION_3_0</option>
3866 <option value="CAS_VERSION_2_0" <?php selected( $auth_settings_option, 'CAS_VERSION_2_0' ); ?>>CAS_VERSION_2_0</option>
3867 <option value="CAS_VERSION_1_0" <?php selected( $auth_settings_option, 'CAS_VERSION_1_0' ); ?>>CAS_VERSION_1_0</option>
3868 </select><?php
3869 }
3870
3871
3872 function print_text_cas_attr_email( $args = '' ) {
3873 // Get plugin option.
3874 $option = 'cas_attr_email';
3875 $auth_settings_option = $this->get_plugin_option( $option, $this->get_admin_mode( $args ), 'allow override', 'print overlay' );
3876
3877 // Print option elements.
3878 ?><input type="text" id="auth_settings_<?php echo $option; ?>" name="auth_settings[<?php echo $option; ?>]" value="<?php echo $auth_settings_option; ?>" placeholder="" />
3879 <br /><label for="auth_settings_<?php echo $option; ?>" class="helper"><?php _e( 'Example: mail', 'authorizer'); ?></label>
3880 <br /><small><?php _e( "Note: If your CAS server doesn't return an attribute containing an email, you can specify the @domain portion of the email address here, and the email address will be constructed from it and the username. For example, if user 'bob' logs in and his email address should be bob@example.edu, then enter <strong>@example.edu</strong> in this field.", 'authorizer' ); ?></small><?php
3881 }
3882
3883
3884 function print_text_cas_attr_first_name( $args = '' ) {
3885 // Get plugin option.
3886 $option = 'cas_attr_first_name';
3887 $auth_settings_option = $this->get_plugin_option( $option, $this->get_admin_mode( $args ), 'allow override', 'print overlay' );
3888
3889 // Print option elements.
3890 ?><input type="text" id="auth_settings_<?php echo $option; ?>" name="auth_settings[<?php echo $option; ?>]" value="<?php echo $auth_settings_option; ?>" placeholder="" />
3891 <br /><label for="auth_settings_<?php echo $option; ?>" class="helper"><?php _e( 'Example: givenName', 'authorizer'); ?></label><?php
3892 }
3893
3894
3895 function print_text_cas_attr_last_name( $args = '' ) {
3896 // Get plugin option.
3897 $option = 'cas_attr_last_name';
3898 $auth_settings_option = $this->get_plugin_option( $option, $this->get_admin_mode( $args ), 'allow override', 'print overlay' );
3899
3900 // Print option elements.
3901 ?><input type="text" id="auth_settings_<?php echo $option; ?>" name="auth_settings[<?php echo $option; ?>]" value="<?php echo $auth_settings_option; ?>" placeholder="" />
3902 <br /><label for="auth_settings_<?php echo $option; ?>" class="helper"><?php _e( 'Example: sn', 'authorizer'); ?></label><?php
3903 }
3904
3905
3906 function print_checkbox_cas_attr_update_on_login( $args = '' ) {
3907 // Get plugin option.
3908 $option = 'cas_attr_update_on_login';
3909 $auth_settings_option = $this->get_plugin_option( $option, $this->get_admin_mode( $args ), 'allow override', 'print overlay' );
3910
3911 // Print option elements.
3912 ?><input type="checkbox" id="auth_settings_<?php echo $option; ?>" name="auth_settings[<?php echo $option; ?>]" value="1"<?php checked( 1 == $auth_settings_option ); ?> /><label for="auth_settings_<?php echo $option; ?>"><?php _e( 'Update first and last name fields on login (will overwrite any name the user has supplied in their profile)', 'authorizer' ); ?></label><?php
3913 }
3914
3915
3916 function print_checkbox_cas_auto_login( $args = '' ) {
3917 // Get plugin option.
3918 $option = 'cas_auto_login';
3919 $auth_settings_option = $this->get_plugin_option( $option, $this->get_admin_mode( $args ), 'allow override', 'print overlay' );
3920
3921 // Print option elements.
3922 ?><input type="checkbox" id="auth_settings_<?php echo $option; ?>" name="auth_settings[<?php echo $option; ?>]" value="1"<?php checked( 1 == $auth_settings_option ); ?> /><label for="auth_settings_<?php echo $option; ?>"><?php _e( "Immediately redirect to CAS login form if it's the only enabled external service and WordPress logins are hidden", 'authorizer' ); ?></label>
3923 <p><small><?php _e( 'Note: This feature will only work if you have checked "Hide WordPress Logins" in Advanced settings, and if CAS is the only enabled service (i.e., no Google or LDAP). If you have enabled CAS Single Sign-On (SSO), and a user has already logged into CAS elsewhere, enabling this feature will allow automatic logins without any user interaction.', 'authorizer' ); ?></small></p><?php
3924 }
3925
3926
3927 function print_checkbox_auth_external_ldap( $args = '' ) {
3928 // Get plugin option.
3929 $option = 'ldap';
3930 $auth_settings_option = $this->get_plugin_option( $option, $this->get_admin_mode( $args ), 'allow override', 'print overlay' );
3931
3932 // Make sure php5-ldap extension is installed on server.
3933 $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', 'authorizer' ) . ')</span>' : '';
3934
3935 // Print option elements.
3936 ?><input type="checkbox" id="auth_settings_<?php echo $option; ?>" name="auth_settings[<?php echo $option; ?>]" value="1"<?php checked( 1 == $auth_settings_option ); ?> /><label for="auth_settings_<?php echo $option; ?>"><?php _e( 'Enable LDAP Logins', 'authorizer' ); ?></label> <?php echo $ldap_installed_message; ?><?php
3937 }
3938
3939
3940 function print_text_ldap_host( $args = '' ) {
3941 // Get plugin option.
3942 $option = 'ldap_host';
3943 $auth_settings_option = $this->get_plugin_option( $option, $this->get_admin_mode( $args ), 'allow override', 'print overlay' );
3944
3945 // Print option elements.
3946 ?><input type="text" id="auth_settings_<?php echo $option; ?>" name="auth_settings[<?php echo $option; ?>]" value="<?php echo $auth_settings_option; ?>" placeholder="" style="width:330px;" />
3947 <br /><small><?php _e( "Specify either a hostname (for example, ldap.example.edu) or a full LDAP URI (for example, ldaps://ldap.example.edu:636).", 'authorizer' ); ?></small><?php
3948 }
3949
3950
3951 function print_text_ldap_port( $args = '' ) {
3952 // Get plugin option.
3953 $option = 'ldap_port';
3954 $auth_settings_option = $this->get_plugin_option( $option, $this->get_admin_mode( $args ), 'allow override', 'print overlay' );
3955
3956 // Print option elements.
3957 ?><input type="text" id="auth_settings_<?php echo $option; ?>" name="auth_settings[<?php echo $option; ?>]" value="<?php echo $auth_settings_option; ?>" placeholder="" style="width:50px;" />
3958 <br /><label for="auth_settings_<?php echo $option; ?>" class="helper"><?php _e( 'Example: 389', 'authorizer' ); ?></label>
3959 <br /><small><?php _e( "If a full LDAP URI (ldaps://hostname:port) is specified above, this field is ignored.", 'authorizer' ); ?></small><?php
3960 }
3961
3962
3963 function print_checkbox_ldap_tls( $args = '' ) {
3964 // Get plugin option.
3965 $option = 'ldap_tls';
3966 $auth_settings_option = $this->get_plugin_option( $option, $this->get_admin_mode( $args ), 'allow override', 'print overlay' );
3967
3968 // Print option elements.
3969 ?><input type="checkbox" id="auth_settings_<?php echo $option; ?>" name="auth_settings[<?php echo $option; ?>]" value="1"<?php checked( 1 == $auth_settings_option ); ?> /><label for="auth_settings_<?php echo $option; ?>"><?php _e( 'Use TLS', 'authorizer' ); ?></label><?php
3970 }
3971
3972
3973 function print_text_ldap_search_base( $args = '' ) {
3974 // Get plugin option.
3975 $option = 'ldap_search_base';
3976 $auth_settings_option = $this->get_plugin_option( $option, $this->get_admin_mode( $args ), 'allow override', 'print overlay' );
3977
3978 // Print option elements.
3979 ?><input type="text" id="auth_settings_<?php echo $option; ?>" name="auth_settings[<?php echo $option; ?>]" value="<?php echo $auth_settings_option; ?>" placeholder="" style="width:330px;" />
3980 <br /><label for="auth_settings_<?php echo $option; ?>" class="helper"><?php _e( 'Example: ou=people,dc=example,dc=edu', 'authorizer'); ?></label><?php
3981 }
3982
3983
3984 function print_text_ldap_uid( $args = '' ) {
3985 // Get plugin option.
3986 $option = 'ldap_uid';
3987 $auth_settings_option = $this->get_plugin_option( $option, $this->get_admin_mode( $args ), 'allow override', 'print overlay' );
3988
3989 // Print option elements.
3990 ?><input type="text" id="auth_settings_<?php echo $option; ?>" name="auth_settings[<?php echo $option; ?>]" value="<?php echo $auth_settings_option; ?>" placeholder="" style="width:80px;" />
3991 <br /><label for="auth_settings_<?php echo $option; ?>" class="helper"><?php _e( 'Example: uid', 'authorizer' ); ?></label><?php
3992 }
3993
3994
3995 function print_text_ldap_attr_email( $args = '' ) {
3996 // Get plugin option.
3997 $option = 'ldap_attr_email';
3998 $auth_settings_option = $this->get_plugin_option( $option, $this->get_admin_mode( $args ), 'allow override', 'print overlay' );
3999
4000 // Print option elements.
4001 ?><input type="text" id="auth_settings_<?php echo $option; ?>" name="auth_settings[<?php echo $option; ?>]" value="<?php echo $auth_settings_option; ?>" placeholder="" />
4002 <br /><label for="auth_settings_<?php echo $option; ?>" class="helper"><?php _e( 'Example: mail', 'authorizer' ); ?></label>
4003 <br /><small><?php _e( "Note: If your LDAP server doesn't return an attribute containing an email, you can specify the @domain portion of the email address here, and the email address will be constructed from it and the username. For example, if user 'bob' logs in and his email address should be bob@example.edu, then enter <strong>@example.edu</strong> in this field.", 'authorizer' ); ?></small><?php
4004 }
4005
4006
4007 function print_text_ldap_user( $args = '' ) {
4008 // Get plugin option.
4009 $option = 'ldap_user';
4010 $auth_settings_option = $this->get_plugin_option( $option, $this->get_admin_mode( $args ), 'allow override', 'print overlay' );
4011
4012 // Print option elements.
4013 ?><input type="text" id="auth_settings_<?php echo $option; ?>" name="auth_settings[<?php echo $option; ?>]" value="<?php echo $auth_settings_option; ?>" placeholder="" style="width:330px;" />
4014 <br /><label for="auth_settings_<?php echo $option; ?>" class="helper"><?php _e( 'Example: cn=directory-user,ou=specials,dc=example,dc=edu', 'authorizer' ); ?></label><?php
4015 }
4016
4017
4018 function print_password_ldap_password( $args = '' ) {
4019 // Get plugin option.
4020 $option = 'ldap_password';
4021 $auth_settings_option = $this->get_plugin_option( $option, $this->get_admin_mode( $args ), 'allow override', 'print overlay' );
4022
4023 // Print option elements.
4024 ?><input type="password" id="garbage_to_stop_autofill" name="garbage" value="" autocomplete="off" style="display:none;" />
4025 <input type="password" id="auth_settings_<?php echo $option; ?>" name="auth_settings[<?php echo $option; ?>]" value="<?php echo $this->decrypt( $auth_settings_option ); ?>" autocomplete="off" /><?php
4026 }
4027
4028
4029 function print_text_ldap_lostpassword_url( $args = '' ) {
4030 // Get plugin option.
4031 $option = 'ldap_lostpassword_url';
4032 $auth_settings_option = $this->get_plugin_option( $option, $this->get_admin_mode( $args ), 'allow override', 'print overlay' );
4033
4034 // Print option elements.
4035 ?><input type="text" id="auth_settings_<?php echo $option; ?>" name="auth_settings[<?php echo $option; ?>]" value="<?php echo $auth_settings_option; ?>" placeholder="" style="width: 400px;" />
4036 <br /><label for="auth_settings_<?php echo $option; ?>" class="helper"><?php _e( 'Example: https://myschool.example.edu:8888/am-forgot-password', 'authorizer' ); ?></label><?php
4037 }
4038
4039
4040 function print_text_ldap_attr_first_name( $args = '' ) {
4041 // Get plugin option.
4042 $option = 'ldap_attr_first_name';
4043 $auth_settings_option = $this->get_plugin_option( $option, $this->get_admin_mode( $args ), 'allow override', 'print overlay' );
4044
4045 // Print option elements.
4046 ?><input type="text" id="auth_settings_<?php echo $option; ?>" name="auth_settings[<?php echo $option; ?>]" value="<?php echo $auth_settings_option; ?>" placeholder="" />
4047 <br /><label for="auth_settings_<?php echo $option; ?>" class="helper"><?php _e( 'Example: givenname', 'authorizer' ); ?></label><?php
4048 }
4049
4050
4051 function print_text_ldap_attr_last_name( $args = '' ) {
4052 // Get plugin option.
4053 $option = 'ldap_attr_last_name';
4054 $auth_settings_option = $this->get_plugin_option( $option, $this->get_admin_mode( $args ), 'allow override', 'print overlay' );
4055
4056 // Print option elements.
4057 ?><input type="text" id="auth_settings_<?php echo $option; ?>" name="auth_settings[<?php echo $option; ?>]" value="<?php echo $auth_settings_option; ?>" placeholder="" />
4058 <br /><label for="auth_settings_<?php echo $option; ?>" class="helper"><?php _e( 'Example: sn', 'authorizer' ); ?></label><?php
4059 }
4060
4061
4062 function print_checkbox_ldap_attr_update_on_login( $args = '' ) {
4063 // Get plugin option.
4064 $option = 'ldap_attr_update_on_login';
4065 $auth_settings_option = $this->get_plugin_option( $option, $this->get_admin_mode( $args ), 'allow override', 'print overlay' );
4066
4067 // Print option elements.
4068 ?><input type="checkbox" id="auth_settings_<?php echo $option; ?>" name="auth_settings[<?php echo $option; ?>]" value="1"<?php checked( 1 == $auth_settings_option ); ?> /><label for="auth_settings_<?php echo $option; ?>"><?php _e( 'Update first and last name fields on login (will overwrite any name the user has supplied in their profile)', 'authorizer' ); ?></label><?php
4069 }
4070
4071
4072 function print_section_info_advanced( $args = '' ) {
4073 ?><div id="section_info_advanced" class="section_info">
4074 <p><?php _e( 'You may optionally specify some advanced settings below.', 'authorizer' ); ?></p>
4075 </div><?php
4076 }
4077
4078
4079 function print_text_auth_advanced_lockouts( $args = '' ) {
4080 // Get plugin option.
4081 $option = 'advanced_lockouts';
4082 $auth_settings_option = $this->get_plugin_option( $option, $this->get_admin_mode( $args ), 'allow override', 'print overlay' );
4083
4084 // Print option elements.
4085 ?><?php _e( 'After', 'authorizer' ); ?>
4086 <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;" />
4087 <?php _e( 'invalid password attempts, delay further attempts on that user for', 'authorizer' ); ?>
4088 <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;" />
4089 <?php _e( 'minute(s).', 'authorizer' ); ?>
4090 <br />
4091 <?php _e( 'After', 'authorizer' ); ?>
4092 <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;" />
4093 <?php _e( 'more invalid attempts, increase the delay to', 'authorizer' ); ?>
4094 <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;" />
4095 <?php _e( 'minutes.', 'authorizer' ); ?>
4096 <br />
4097 <?php _e( 'Reset the delays after', 'authorizer' ); ?>
4098 <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;" />
4099 <?php _e( 'minutes with no invalid attempts.', 'authorizer' ); ?><?php
4100 }
4101
4102
4103 function print_checkbox_auth_advanced_hide_wp_login( $args = '' ) {
4104 // Get plugin option.
4105 $option = 'advanced_hide_wp_login';
4106 $auth_settings_option = $this->get_plugin_option( $option, $this->get_admin_mode( $args ), 'allow override', 'print overlay' );
4107
4108 // Print option elements.
4109 ?><input type="checkbox" id="auth_settings_<?php echo $option; ?>" name="auth_settings[<?php echo $option; ?>]" value="1"<?php checked( 1 == $auth_settings_option ); ?> /><label for="auth_settings_<?php echo $option; ?>"><?php _e( 'Hide WordPress Logins', 'authorizer' ); ?></label>
4110 <p><small><?php _e( 'Note: You can always access the WordPress logins by adding external=wordpress to the wp-login URL, like so:', 'authorizer' ); ?><br /><a href="<?php echo wp_login_url(); ?>?external=wordpress" target="_blank"><?php echo wp_login_url(); ?>?external=wordpress</a>.</p><?php
4111 }
4112
4113
4114 function print_radio_auth_advanced_branding( $args = '' ) {
4115 // Get plugin option.
4116 $option = 'advanced_branding';
4117 $auth_settings_option = $this->get_plugin_option( $option );
4118
4119 // Print option elements.
4120 ?><input type="radio" id="radio_auth_settings_<?php echo $option; ?>_default" name="auth_settings[<?php echo $option; ?>]" value="default"<?php checked( 'default' == $auth_settings_option ); ?> /><label for="radio_auth_settings_<?php echo $option; ?>_default"><?php _e( 'Default WordPress login screen', 'authorizer' ); ?></label><br />
4121 <?php
4122
4123 /**
4124 * Developers can use the `authorizer_add_branding_option` filter
4125 * to add a radio button for "Custom WordPress login branding"
4126 * under the "Advanced" tab in Authorizer options. Example:
4127 *
4128 * function my_authorizer_add_branding_option( $branding_options ) {
4129 * $new_branding_option = array(
4130 * 'value' => 'your_brand'
4131 * 'description' => 'Custom Your Brand Login Screen',
4132 * 'css_url' => 'http://url/to/your_brand.css',
4133 * 'js_url' => 'http://url/to/your_brand.js',
4134 * );
4135 * array_push( $branding_options, $new_branding_option );
4136 * return $branding_options;
4137 * }
4138 * add_filter( 'authorizer_add_branding_option', 'my_authorizer_add_branding_option' );
4139 */
4140 $branding_options = array();
4141 $branding_options = apply_filters( 'authorizer_add_branding_option', $branding_options );
4142 foreach ( $branding_options as $branding_option ) {
4143 // Make sure the custom brands have the required values
4144 if ( ! ( is_array( $branding_option ) && array_key_exists( 'value', $branding_option ) && array_key_exists( 'description', $branding_option ) ) ) {
4145 continue;
4146 }
4147 ?><input type="radio" id="radio_auth_settings_<?php echo $option; ?>_<?php echo sanitize_title( $branding_option['value'] ); ?>" name="auth_settings[<?php echo $option; ?>]" value="<?php echo $branding_option['value']; ?>"<?php checked( $branding_option['value'] == $auth_settings_option ); ?> /><label for="radio_auth_settings_<?php echo $option; ?>_<?php echo sanitize_title( $branding_option['value'] ); ?>"><?php echo $branding_option['description']; ?></label><br /><?php
4148 }
4149
4150 // Print message about adding custom brands if there are none.
4151 if ( count( $branding_options ) === 0 ) {
4152 ?><p><em><?php _e( '<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.', 'authorizer' ); ?></em></p><?php
4153 }
4154 }
4155
4156
4157 function print_radio_auth_advanced_admin_menu( $args = '' ) {
4158 // Get plugin option.
4159 $option = 'advanced_admin_menu';
4160 $auth_settings_option = $this->get_plugin_option( $option );
4161
4162 // Print option elements.
4163 ?><input type="radio" id="radio_auth_settings_<?php echo $option; ?>_settings" name="auth_settings[<?php echo $option; ?>]" value="settings"<?php checked( 'settings' == $auth_settings_option ); ?> /><label for="radio_auth_settings_<?php echo $option; ?>_settings"><?php _e( 'Show in Settings menu', 'authorizer' ); ?></label><br />
4164 <input type="radio" id="radio_auth_settings_<?php echo $option; ?>_top" name="auth_settings[<?php echo $option; ?>]" value="top"<?php checked( 'top' == $auth_settings_option ); ?> /><label for="radio_auth_settings_<?php echo $option; ?>_top"><?php _e( 'Show in sidebar (top level)', 'authorizer' ); ?></label><br /><?php
4165
4166 }
4167
4168
4169 function print_select_auth_advanced_usermeta( $args = '' ) {
4170 // Get plugin option.
4171 $option = 'advanced_usermeta';
4172 $auth_settings_option = $this->get_plugin_option( $option );
4173
4174 // Print option elements.
4175 ?><select id="auth_settings_<?php echo $option; ?>" name="auth_settings[<?php echo $option; ?>]">
4176 <option value=""><?php _e( '-- None --', 'authorizer' ); ?></option>
4177 <?php if ( class_exists( 'acf' ) ) :
4178 // Get ACF 5 fields. Note: it would be much easier to use `get_field_objects()`
4179 // or `get_field_objects( 'user_' . get_current_user_id() )`, but neither will
4180 // list fields that have never been given values for users (i.e., new ACF
4181 // fields). Therefore we fall back on finding any ACF fields applied to users
4182 // (user_role or user_form location rules in the field group definition).
4183 $fields = array();
4184 $acf_field_group_ids = array();
4185 $acf_field_groups = new WP_Query( array(
4186 'post_type' => 'acf-field-group',
4187 ));
4188 while ( $acf_field_groups->have_posts() ) : $acf_field_groups->the_post();
4189 if ( strpos( get_the_content(), 's:5:"param";s:9:"user_role"' ) !== false || strpos( get_the_content(), 's:5:"param";s:9:"user_form"' ) !== false ) :
4190 array_push( $acf_field_group_ids, get_the_ID() );
4191 endif;
4192 endwhile; wp_reset_postdata();
4193 foreach ( $acf_field_group_ids as $acf_field_group_id ) :
4194 $acf_fields = new WP_Query( array(
4195 'post_type' => 'acf-field',
4196 'post_parent' => $acf_field_group_id,
4197 ));
4198 while ( $acf_fields->have_posts() ) : $acf_fields->the_post();
4199 global $post;
4200 $fields[$post->post_name] = get_field_object( $post->post_name );
4201 endwhile; wp_reset_postdata();
4202 endforeach;
4203 // Get ACF 4 fields.
4204 $acf4_field_groups = new WP_Query( array(
4205 'post_type' => 'acf',
4206 ));
4207 while ( $acf4_field_groups->have_posts() ) : $acf4_field_groups->the_post();
4208 $field_group_rules = get_post_meta( get_the_ID(), 'rule', true );
4209 if ( is_array( $field_group_rules ) && array_key_exists( 'param', $field_group_rules ) && $field_group_rules['param'] === 'ef_user' ) :
4210 $acf4_fields = get_post_custom( get_the_ID() );
4211 foreach ( $acf4_fields as $meta_key => $meta_value ) :
4212 if ( strpos( $meta_key, 'field_' ) === 0 ) :
4213 $meta_value = unserialize( $meta_value[0] );
4214 $fields[$meta_key] = $meta_value;
4215 endif;
4216 endforeach;
4217 endif;
4218 endwhile; wp_reset_postdata(); ?>
4219 <optgroup label="ACF User Fields:">
4220 <?php foreach ( (array)$fields as $field => $field_object ) : ?>
4221 <option value="acf___<?php echo $field_object['key']; ?>"<?php if ( $auth_settings_option === "acf___{$field_object['key']}" ) echo ' selected="selected"'; ?>><?php echo $field_object['label']; ?></option>
4222 <?php endforeach; ?>
4223 </optgroup>
4224 <?php endif; ?>
4225 <optgroup label="<?php _e( 'All Usermeta:', 'authorizer' ); ?>">
4226 <?php foreach ( $this->get_all_usermeta_keys() as $meta_key ) : if ( substr( $meta_key, 0, 3 ) === 'wp_' ) continue; ?>
4227 <option value="<?php echo $meta_key; ?>"<?php if ( $auth_settings_option === $meta_key ) echo ' selected="selected"'; ?>><?php echo $meta_key; ?></option>
4228 <?php endforeach; ?>
4229 </optgroup>
4230 </select><?php
4231 }
4232
4233
4234 function print_checkbox_auth_advanced_override_multisite( $args = '' ) {
4235 // Get plugin option.
4236 $option = 'advanced_override_multisite';
4237 $auth_settings_option = $this->get_plugin_option( $option );
4238
4239 // Print option elements.
4240 ?><input type="checkbox" id="auth_settings_<?php echo $option; ?>" name="auth_settings[<?php echo $option; ?>]" value="1"<?php checked( 1 == $auth_settings_option ); ?> /><label for="auth_settings_<?php echo $option; ?>"><?php _e( "Configure this site independently (don't inherit any multisite settings)", 'authorizer' ); ?></label><?php
4241 }
4242
4243
4244
4245 /**
4246 * Add help documentation to the options page.
4247 * Run on action hook chain: load-settings_page_authorizer > admin_head
4248 */
4249 public function admin_head() {
4250 $screen = get_current_screen();
4251
4252 // Add help tab for Access Lists Settings
4253 $help_auth_settings_access_lists_content = '
4254 <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.", 'authorizer' ) .'</p>
4255 <p>' . __( "<strong>Approved Users</strong>: Approved users have access to the site once they successfully log in.", 'authorizer' ) . '</p>
4256 <p>' . __( "<strong>Blocked Users</strong>: Blocked users will receive an error message when they try to visit the site after authenticating.", 'authorizer' ) . '</p>
4257 <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.", 'authorizer' ) . '</p>
4258 ';
4259 $screen->add_help_tab(
4260 array(
4261 'id' => 'help_auth_settings_access_lists_content',
4262 'title' => __( 'Access Lists', 'authorizer' ),
4263 'content' => $help_auth_settings_access_lists_content,
4264 )
4265 );
4266
4267 // Add help tab for Login Access Settings
4268 $help_auth_settings_access_login_content = '
4269 <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>.", 'authorizer' ) . '</p>
4270 <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.", 'authorizer' ) . '</p>
4271 <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.', 'authorizer' ) . '</p>
4272 ';
4273 $screen->add_help_tab(
4274 array(
4275 'id' => 'help_auth_settings_access_login_content',
4276 'title' => __( 'Login Access', 'authorizer' ),
4277 'content' => $help_auth_settings_access_login_content,
4278 )
4279 );
4280
4281 // Add help tab for Public Access Settings
4282 $help_auth_settings_access_public_content = '
4283 <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.", 'authorizer' ) . '</p>
4284 <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.", 'authorizer' ) . '</p>
4285 <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>.", 'authorizer' ) . '</p>
4286 <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.", 'authorizer' ) . '</p>
4287 <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.", 'authorizer' ) . '</p>
4288 ';
4289 $screen->add_help_tab(
4290 array(
4291 'id' => 'help_auth_settings_access_public_content',
4292 'title' => __( 'Public Access', 'authorizer' ),
4293 'content' => $help_auth_settings_access_public_content,
4294 )
4295 );
4296
4297 // Add help tab for External Service (CAS, LDAP) Settings
4298 $help_auth_settings_external_content = '
4299 <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.", 'authorizer' ) . '</p>
4300 <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.", 'authorizer' ) . '</p>
4301 <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.", 'authorizer' ) . '</p>
4302 <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.", 'authorizer' ) . '</p>
4303 <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!", 'authorizer' ) . '</p>
4304 <p><strong><em>' . __( "If you enable Google logins:", 'authorizer' ) . '</em></strong></p>
4305 <ul>
4306 <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", 'authorizer' ) . '</li>
4307 <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", 'authorizer' ) . '</li>
4308 </ul>
4309 <p><strong><em>' . __( "If you enable CAS logins:", 'authorizer' ) . '</em></strong></p>
4310 <ul>
4311 <li>' . __( "<strong>CAS server hostname</strong>: Enter the hostname of the CAS server you authenticate against (e.g., authn.example.edu).", 'authorizer' ) . '</li>
4312 <li>' . __( "<strong>CAS server port</strong>: Enter the port on the CAS server to connect to (e.g., 443).", 'authorizer' ) . '</li>
4313 <li>' . __( "<strong>CAS server path/context</strong>: Enter the path to the login endpoint on the CAS server (e.g., /cas).", 'authorizer' ) . '</li>
4314 <li>' . __( "<strong>CAS attribute containing first name</strong>: Enter the CAS attribute that has the user's first name. When this user first logs in, their WordPress account will have their first name retrieved from CAS and added to their WordPress profile.", 'authorizer' ) . '</li>
4315 <li>' . __( "<strong>CAS attribute containing last name</strong>: Enter the CAS attribute that has the user's last name. When this user first logs in, their WordPress account will have their last name retrieved from CAS and added to their WordPress profile.", 'authorizer' ) . '</li>
4316 <li>' . __( "<strong>CAS attribute update</strong>: Select whether the first and last names retrieved from CAS should overwrite any value the user has entered in the first and last name fields in their WordPress profile. If this is not set, this only happens the first time they log in.", 'authorizer' ) . '</li>
4317 </ul>
4318 <p><strong><em>' . __( "If you enable LDAP logins:", 'authorizer' ) . '</em></strong></p>
4319 <ul>
4320 <li>' . __( "<strong>LDAP Host</strong>: Enter the URL of the LDAP server you authenticate against.", 'authorizer' ) . '</li>
4321 <li>' . __( "<strong>LDAP Port</strong>: Enter the port number that the LDAP server listens on.", 'authorizer' ) . '</li>
4322 <li>' . __( "<strong>LDAP Search Base</strong>: Enter the LDAP string that represents the search base, e.g., ou=people,dc=example,dc=edu", 'authorizer' ) . '</li>
4323 <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.", 'authorizer' ) . '</li>
4324 <li>' . __( "<strong>LDAP Directory User</strong>: Enter the name of the LDAP user that has permissions to browse the directory.", 'authorizer' ) . '</li>
4325 <li>' . __( "<strong>LDAP Directory User Password</strong>: Enter the password for the LDAP user that has permission to browse the directory.", 'authorizer' ) . '</li>
4326 <li>' . __( "<strong>Secure Connection (TLS)</strong>: Select whether all communication with the LDAP server should be performed over a TLS-secured connection.", 'authorizer' ) . '</li>
4327 <li>' . __( "<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.", 'authorizer' ) . '</li>
4328 <li>' . __( "<strong>LDAP attribute containing first name</strong>: Enter the LDAP attribute that has the user's first name. When this user first logs in, their WordPress account will have their first name retrieved from LDAP and added to their WordPress profile.", 'authorizer' ) . '</li>
4329 <li>' . __( "<strong>LDAP attribute containing last name</strong>: Enter the LDAP attribute that has the user's last name. When this user first logs in, their WordPress account will have their last name retrieved from LDAP and added to their WordPress profile.", 'authorizer' ) . '</li>
4330 <li>' . __( "<strong>LDAP attribute update</strong>: Select whether the first and last names retrieved from LDAP should overwrite any value the user has entered in the first and last name fields in their WordPress profile. If this is not set, this only happens the first time they log in.", 'authorizer' ) . '</li>
4331 </ul>
4332 ';
4333 $screen->add_help_tab(
4334 array(
4335 'id' => 'help_auth_settings_external_content',
4336 'title' => __( 'External Service', 'authorizer' ),
4337 'content' => $help_auth_settings_external_content,
4338 )
4339 );
4340
4341 // Add help tab for Advanced Settings
4342 $help_auth_settings_advanced_content = '
4343 <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.", 'authorizer' ) . '</p>
4344 <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:", 'authorizer' ) . ' <a href="' . wp_login_url() . '?external=wordpress" target="_blank">' . wp_login_url() . '?external=wordpress</a>.</p>
4345 <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.", 'authorizer' ) . '</p>
4346 ';
4347 $screen->add_help_tab(
4348 array(
4349 'id' => 'help_auth_settings_advanced_content',
4350 'title' => __( 'Advanced', 'authorizer' ),
4351 'content' => $help_auth_settings_advanced_content,
4352 )
4353 );
4354 }
4355
4356
4357
4358 /**
4359 * ***************************
4360 * Multisite: Network Admin Options page
4361 * ***************************
4362 */
4363
4364
4365 /**
4366 * Network Admin menu item
4367 * Hook: network_admin_menu
4368 *
4369 * @param none
4370 * @return void
4371 */
4372 public function network_admin_menu() {
4373 // @see http://codex.wordpress.org/Function_Reference/add_menu_page
4374 add_menu_page(
4375 'Authorizer', // Page title
4376 'Authorizer', // Menu title
4377 'manage_network_options', // Capability
4378 'authorizer', // Menu slug
4379 array( $this, 'create_network_admin_page' ),
4380 'dashicons-groups', // Icon URL
4381 89 // Position
4382 );
4383 }
4384
4385
4386 /**
4387 * Output the HTML for the options page
4388 */
4389 public function create_network_admin_page() {
4390 if ( ! current_user_can( 'manage_network_options' ) ) {
4391 wp_die( __( 'You do not have sufficient permissions to access this page.', 'authorizer' ) );
4392 }
4393 $auth_settings = get_blog_option( BLOG_ID_CURRENT_SITE, 'auth_multisite_settings', array() ); ?>
4394 <div class="wrap">
4395 <form method="post" action="" autocomplete="off">
4396 <h2><?php _e( 'Authorizer Settings', 'authorizer' ); ?></h2>
4397 <p><?php _e( '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.', 'authorizer' ); ?></p>
4398
4399 <input type="checkbox" id="auth_settings_multisite_override" name="auth_settings[multisite_override]" value="1"<?php checked( 1 == $auth_settings['multisite_override'] ); ?> /><label for="auth_settings_multisite_override"><?php _e( 'Override individual site settings with the settings below', 'authorizer' ); ?></label>
4400
4401 <div id="auth_multisite_settings_disabled_overlay" style="display: none;"></div>
4402
4403 <div class="wrap" id="auth_multisite_settings">
4404 <?php $this->print_section_info_tabs( array( MULTISITE_ADMIN => true ) ); ?>
4405
4406 <?php wp_nonce_field( 'save_auth_settings', 'nonce_save_auth_settings' ); ?>
4407
4408 <?php // Custom access lists (for network, we only really want approved list, not pending or blocked) ?>
4409 <div id="section_info_access_lists" class="section_info">
4410 <p><?php _e( 'Manage who has access to all sites in the network.', 'authorizer' ); ?></p>
4411 </div>
4412 <table class="form-table"><tbody>
4413 <tr>
4414 <th scope="row"><?php _e( 'Who can log in to sites in this network?', 'authorizer' ); ?></th>
4415 <td><?php $this->print_radio_auth_access_who_can_login( array( MULTISITE_ADMIN => true ) ); ?></td>
4416 </tr>
4417 <tr>
4418 <th scope="row"><?php _e( 'Who can view sites in this network?', 'authorizer' ); ?></th>
4419 <td><?php $this->print_radio_auth_access_who_can_view( array( MULTISITE_ADMIN => true ) ); ?></td>
4420 </tr>
4421 <tr>
4422 <th scope="row"><?php _e( 'Approved Users (All Sites)', 'authorizer' ); ?><br /><small><em><?php _e( 'Note: these users will <strong>not</strong> receive welcome emails when approved. Only users approved from individual sites can receive these messages.', 'authorizer' ); ?></em></small></th>
4423 <td><?php $this->print_combo_auth_access_users_approved( array( MULTISITE_ADMIN => true ) ); ?></td>
4424 </tr>
4425 </tbody></table>
4426
4427 <?php $this->print_section_info_external(); ?>
4428 <table class="form-table"><tbody>
4429 <tr>
4430 <th scope="row"><?php _e( 'Default role for new users', 'authorizer' ); ?></th>
4431 <td><?php $this->print_select_auth_access_default_role( array( MULTISITE_ADMIN => true ) ); ?></td>
4432 </tr>
4433 <tr>
4434 <th scope="row"><?php _e( 'Google Logins', 'authorizer' ); ?></th>
4435 <td><?php $this->print_checkbox_auth_external_google( array( MULTISITE_ADMIN => true ) ); ?></td>
4436 </tr>
4437 <tr>
4438 <th scope="row"><?php _e( 'Google Client ID', 'authorizer' ); ?></th>
4439 <td><?php $this->print_text_google_clientid( array( MULTISITE_ADMIN => true ) ); ?></td>
4440 </tr>
4441 <tr>
4442 <th scope="row"><?php _e( 'Google Client Secret', 'authorizer' ); ?></th>
4443 <td><?php $this->print_text_google_clientsecret( array( MULTISITE_ADMIN => true ) ); ?></td>
4444 </tr>
4445 <tr>
4446 <th scope="row"><?php _e( 'Google Hosted Domain', 'authorizer' ); ?></th>
4447 <td><?php $this->print_text_google_hosteddomain( array( MULTISITE_ADMIN => true ) ); ?></td>
4448 </tr>
4449 <tr>
4450 <th scope="row"><?php _e( 'CAS Logins', 'authorizer' ); ?></th>
4451 <td><?php $this->print_checkbox_auth_external_cas( array( MULTISITE_ADMIN => true ) ); ?></td>
4452 </tr>
4453 <tr>
4454 <th scope="row"><?php _e( 'CAS Custom Label', 'authorizer' ); ?></th>
4455 <td><?php $this->print_text_cas_custom_label( array( MULTISITE_ADMIN => true ) ); ?></td>
4456 </tr>
4457 <tr>
4458 <th scope="row"><?php _e( 'CAS server hostname', 'authorizer' ); ?></th>
4459 <td><?php $this->print_text_cas_host( array( MULTISITE_ADMIN => true ) ); ?></td>
4460 </tr>
4461 <tr>
4462 <th scope="row"><?php _e( 'CAS server port', 'authorizer' ); ?></th>
4463 <td><?php $this->print_text_cas_port( array( MULTISITE_ADMIN => true ) ); ?></td>
4464 </tr>
4465 <tr>
4466 <th scope="row"><?php _e( 'CAS server path/context', 'authorizer' ); ?></th>
4467 <td><?php $this->print_text_cas_path( array( MULTISITE_ADMIN => true ) ); ?></td>
4468 </tr>
4469 <tr>
4470 <th scope="row"><?php _e( 'CAS server version', 'authorizer' ); ?></th>
4471 <td><?php $this->print_select_cas_version( array( MULTISITE_ADMIN => true ) ); ?></td>
4472 </tr>
4473 <tr>
4474 <th scope="row"><?php _e( 'CAS attribute containing email', 'authorizer' ); ?></th>
4475 <td><?php $this->print_text_cas_attr_email( array( MULTISITE_ADMIN => true ) ); ?></td>
4476 </tr>
4477 <tr>
4478 <th scope="row"><?php _e( 'CAS attribute containing first name', 'authorizer' ); ?></th>
4479 <td><?php $this->print_text_cas_attr_first_name( array( MULTISITE_ADMIN => true ) ); ?></td>
4480 </tr>
4481 <tr>
4482 <th scope="row"><?php _e( 'CAS attribute containing last name', 'authorizer' ); ?></th>
4483 <td><?php $this->print_text_cas_attr_last_name( array( MULTISITE_ADMIN => true ) ); ?></td>
4484 </tr>
4485 <tr>
4486 <th scope="row"><?php _e( 'CAS attribute update', 'authorizer' ); ?></th>
4487 <td><?php $this->print_checkbox_cas_attr_update_on_login( array( MULTISITE_ADMIN => true ) ); ?></td>
4488 </tr>
4489 <tr>
4490 <th scope="row"><?php _e( 'CAS automatic login', 'authorizer' ); ?></th>
4491 <td><?php $this->print_checkbox_cas_auto_login( array( MULTISITE_ADMIN => true ) ); ?></td>
4492 </tr>
4493 <tr>
4494 <th scope="row"><?php _e( 'LDAP Logins', 'authorizer' ); ?></th>
4495 <td><?php $this->print_checkbox_auth_external_ldap( array( MULTISITE_ADMIN => true ) ); ?></td>
4496 </tr>
4497 <tr>
4498 <th scope="row"><?php _e( 'LDAP Host', 'authorizer' ); ?></th>
4499 <td><?php $this->print_text_ldap_host( array( MULTISITE_ADMIN => true ) ); ?></td>
4500 </tr>
4501 <tr>
4502 <th scope="row"><?php _e( 'LDAP Port', 'authorizer' ); ?></th>
4503 <td><?php $this->print_text_ldap_port( array( MULTISITE_ADMIN => true ) ); ?></td>
4504 </tr>
4505 <tr>
4506 <th scope="row"><?php _e( 'Secure Connection (TLS)', 'authorizer' ); ?></th>
4507 <td><?php $this->print_checkbox_ldap_tls( array( MULTISITE_ADMIN => true ) ); ?></td>
4508 </tr>
4509 <tr>
4510 <th scope="row"><?php _e( 'LDAP Search Base', 'authorizer' ); ?></th>
4511 <td><?php $this->print_text_ldap_search_base( array( MULTISITE_ADMIN => true ) ); ?></td>
4512 </tr>
4513 <tr>
4514 <th scope="row"><?php _e( 'LDAP attribute containing username', 'authorizer' ); ?></th>
4515 <td><?php $this->print_text_ldap_uid( array( MULTISITE_ADMIN => true ) ); ?></td>
4516 </tr>
4517 <tr>
4518 <th scope="row"><?php _e( 'LDAP attribute containing email', 'authorizer' ); ?></th>
4519 <td><?php $this->print_text_ldap_attr_email( array( MULTISITE_ADMIN => true ) ); ?></td>
4520 </tr>
4521 <tr>
4522 <th scope="row"><?php _e( 'LDAP Directory User', 'authorizer' ); ?></th>
4523 <td><?php $this->print_text_ldap_user( array( MULTISITE_ADMIN => true ) ); ?></td>
4524 </tr>
4525 <tr>
4526 <th scope="row"><?php _e( 'LDAP Directory User Password', 'authorizer' ); ?></th>
4527 <td><?php $this->print_password_ldap_password( array( MULTISITE_ADMIN => true ) ); ?></td>
4528 </tr>
4529 <tr>
4530 <th scope="row"><?php _e( 'Custom lost password URL', 'authorizer' ); ?></th>
4531 <td><?php $this->print_text_ldap_lostpassword_url( array( MULTISITE_ADMIN => true ) ); ?></td>
4532 </tr>
4533 <tr>
4534 <th scope="row"><?php _e( 'LDAP attribute containing first name', 'authorizer' ); ?></th>
4535 <td><?php $this->print_text_ldap_attr_first_name( array( MULTISITE_ADMIN => true ) ); ?></td>
4536 </tr>
4537 <tr>
4538 <th scope="row"><?php _e( 'LDAP attribute containing last name', 'authorizer' ); ?></th>
4539 <td><?php $this->print_text_ldap_attr_last_name( array( MULTISITE_ADMIN => true ) ); ?></td>
4540 </tr>
4541 <tr>
4542 <th scope="row"><?php _e( 'LDAP attribute update', 'authorizer' ); ?></th>
4543 <td><?php $this->print_checkbox_ldap_attr_update_on_login( array( MULTISITE_ADMIN => true ) ); ?></td>
4544 </tr>
4545 </tbody></table>
4546
4547 <?php $this->print_section_info_advanced(); ?>
4548 <table class="form-table"><tbody>
4549 <tr>
4550 <th scope="row"><?php _e( 'Limit invalid login attempts', 'authorizer' ); ?></th>
4551 <td><?php $this->print_text_auth_advanced_lockouts( array( MULTISITE_ADMIN => true ) ); ?></td>
4552 </tr>
4553 <tr>
4554 <th scope="row"><?php _e( 'Hide WordPress Logins', 'authorizer' ); ?></th>
4555 <td><?php $this->print_checkbox_auth_advanced_hide_wp_login( array( MULTISITE_ADMIN => true ) ); ?></td>
4556 </tr>
4557 </tbody></table>
4558
4559 <br class="clear" />
4560 </div>
4561 <input type="button" name="submit" id="submit" class="button button-primary" value="<?php _e( 'Save Changes', 'authorizer' ); ?>" onclick="save_auth_multisite_settings(this);" />
4562 </form>
4563 </div>
4564 <?php
4565 }
4566
4567
4568 /**
4569 * Save multisite settings (ajax call).
4570 */
4571 function ajax_save_auth_multisite_settings() {
4572 // Fail silently if current user doesn't have permissions.
4573 if ( ! current_user_can( 'manage_network_options' ) ) {
4574 die( '' );
4575 }
4576
4577 // Make sure nonce exists.
4578 if ( empty( $_POST['nonce_save_auth_settings'] ) ) {
4579 die( '' );
4580 }
4581
4582 // Nonce check.
4583 if ( ! wp_verify_nonce( $_POST['nonce_save_auth_settings'], 'save_auth_settings' ) ) {
4584 die( '' );
4585 }
4586
4587 // Assert multisite.
4588 if ( ! is_multisite() ) {
4589 die( '' );
4590 }
4591
4592 // Get multisite settings.
4593 $auth_multisite_settings = get_blog_option( BLOG_ID_CURRENT_SITE, 'auth_multisite_settings', array() );
4594
4595 // Sanitize settings
4596 $auth_multisite_settings = $this->sanitize_options( $_POST );
4597
4598 // Filter options to only the allowed values (multisite options are a subset of all options)
4599 $allowed = array(
4600 'multisite_override',
4601 'access_who_can_login',
4602 'access_who_can_view',
4603 'access_default_role',
4604 'google',
4605 'google_clientid',
4606 'google_clientsecret',
4607 'google_hosteddomain',
4608 'cas',
4609 'cas_custom_label',
4610 'cas_host',
4611 'cas_port',
4612 'cas_path',
4613 'cas_version',
4614 'cas_attr_email',
4615 'cas_attr_first_name',
4616 'cas_attr_last_name',
4617 'cas_attr_update_on_login',
4618 'cas_auto_login',
4619 'ldap',
4620 'ldap_host',
4621 'ldap_port',
4622 'ldap_tls',
4623 'ldap_search_base',
4624 'ldap_uid',
4625 'ldap_attr_email',
4626 'ldap_user',
4627 'ldap_password',
4628 'ldap_lostpassword_url',
4629 'ldap_attr_first_name',
4630 'ldap_attr_last_name',
4631 'ldap_attr_update_on_login',
4632 'advanced_lockouts',
4633 'advanced_hide_wp_login',
4634 );
4635 $auth_multisite_settings = array_intersect_key( $auth_multisite_settings, array_flip( $allowed ) );
4636
4637 // Update multisite settings in database.
4638 update_blog_option( BLOG_ID_CURRENT_SITE, 'auth_multisite_settings', $auth_multisite_settings );
4639
4640 // Return 'success' value to AJAX call.
4641 die( 'success' );
4642 }
4643
4644
4645
4646 /**
4647 * ***************************
4648 * Dashboard widget
4649 * ***************************
4650 */
4651
4652
4653
4654 function add_dashboard_widgets() {
4655 // Only users who can edit can see the authorizer dashboard widget
4656 if ( current_user_can( 'create_users' ) ) {
4657 // Add dashboard widget for adding/editing users with access
4658 wp_add_dashboard_widget( 'auth_dashboard_widget', __( 'Authorizer Settings', 'authorizer' ), array( $this, 'add_auth_dashboard_widget' ) );
4659 }
4660 }
4661
4662
4663 function add_auth_dashboard_widget() {
4664 ?><form method="post" id="auth_settings_access_form" action="">
4665 <?php $this->print_section_info_access_login(); ?>
4666 <div>
4667 <h2><?php _e( 'Pending Users', 'authorizer' ); ?></h2>
4668 <?php $this->print_combo_auth_access_users_pending(); ?>
4669 </div>
4670 <div>
4671 <h2><?php _e( 'Approved Users', 'authorizer' ); ?></h2>
4672 <?php $this->print_combo_auth_access_users_approved(); ?>
4673 </div>
4674 <div>
4675 <h2><?php _e( 'Blocked Users', 'authorizer' ); ?></h2>
4676 <?php $this->print_combo_auth_access_users_blocked(); ?>
4677 </div>
4678 <br class="clear" />
4679 </form><?php
4680 }
4681
4682
4683 // Fired on a change event from the optional usermeta field in the
4684 // approved user list. Updates the selected usermeta value, or saves it
4685 // in the user's approved list entry if the user hasn't logged in yet
4686 // and created a WordPress account.
4687 function ajax_update_auth_usermeta() {
4688 // Fail silently if current user doesn't have permissions.
4689 if ( ! current_user_can( 'create_users' ) ) {
4690 die( '' );
4691 }
4692
4693 // Nonce check.
4694 if ( empty( $_POST['nonce_save_auth_settings'] ) || ! wp_verify_nonce( $_POST['nonce_save_auth_settings'], 'save_auth_settings' ) ) {
4695 die( '' );
4696 }
4697
4698 // Fail if required post data doesn't exist.
4699 if ( ! array_key_exists( 'email', $_REQUEST ) || ! array_key_exists( 'usermeta', $_REQUEST ) ) {
4700 die( '' );
4701 }
4702
4703 // Get values to update from post data.
4704 $email = $_REQUEST['email'];
4705 $meta_value = $_REQUEST['usermeta'];
4706 $meta_key = $this->get_plugin_option( 'advanced_usermeta' );
4707
4708 // If user doesn't exist, save usermeta selection to authorizer
4709 // list. This value will get saved to usermeta when the user first
4710 // logs in (i.e., when their WordPress account is created).
4711 if ( ! ( $wp_user = get_user_by( 'email', $email ) ) ) {
4712 // Look through multisite approved users and add a usermeta
4713 // reference for the current blog if the user is found.
4714 $auth_multisite_settings_access_users_approved = is_multisite() ? get_blog_option( BLOG_ID_CURRENT_SITE, 'auth_multisite_settings_access_users_approved', array() ) : array();
4715 $should_update_auth_multisite_settings_access_users_approved = false;
4716 foreach ( $auth_multisite_settings_access_users_approved as $index => $approved_user ) {
4717 if ( 0 === strcasecmp( $email, $approved_user['email'] ) ) {
4718 if ( ! is_array( $auth_multisite_settings_access_users_approved[$index]['usermeta'] ) ) {
4719 // Initialize the array of usermeta for each blog this user belongs to.
4720 $auth_multisite_settings_access_users_approved[$index]['usermeta'] = array();
4721 } else {
4722 // There is already usermeta associated with this
4723 // preapproved user; iterate through it and make
4724 // sure it's not for old meta_keys (delete it if
4725 // so). This can happen if someone changes the
4726 // usermeta key in authorizer options, and we don't
4727 // want to hang on to old data.
4728 foreach ( $auth_multisite_settings_access_users_approved[$index]['usermeta'] as $blog_id => $usermeta ) {
4729 if ( array_key_exists( 'meta_key', $usermeta ) && $usermeta['meta_key'] === $meta_key ) {
4730 continue;
4731 } else {
4732 unset( $auth_multisite_settings_access_users_approved[$index]['usermeta'][$blog_id] );
4733 }
4734 }
4735 }
4736 $auth_multisite_settings_access_users_approved[$index]['usermeta'][get_current_blog_id()] = array(
4737 'meta_key' => $meta_key,
4738 'meta_value' => $meta_value,
4739 );
4740 $should_update_auth_multisite_settings_access_users_approved = true;
4741 }
4742 }
4743 if ( $should_update_auth_multisite_settings_access_users_approved ) {
4744 update_blog_option( BLOG_ID_CURRENT_SITE, 'auth_multisite_settings_access_users_approved', $auth_multisite_settings_access_users_approved );
4745 }
4746
4747 // Look through the approved users (of the current blog in a
4748 // multisite install, or just of the single site) and add a
4749 // usermeta reference if the user is found.
4750 $auth_settings_access_users_approved = $this->get_plugin_option( 'access_users_approved', SINGLE_ADMIN );
4751 $should_update_auth_settings_access_users_approved = false;
4752 foreach ( $auth_settings_access_users_approved as $index => $approved_user ) {
4753 if ( 0 === strcasecmp( $email, $approved_user['email'] ) ) {
4754 $auth_settings_access_users_approved[$index]['usermeta'] = array(
4755 'meta_key' => $meta_key,
4756 'meta_value' => $meta_value,
4757 );
4758 $should_update_auth_settings_access_users_approved = true;
4759 }
4760 }
4761 if ( $should_update_auth_settings_access_users_approved ) {
4762 update_option( 'auth_settings_access_users_approved', $auth_settings_access_users_approved );
4763 }
4764
4765 } else {
4766 // Update user's usermeta value for usermeta key stored in authorizer options.
4767 if ( strpos( $meta_key, 'acf___' ) === 0 && class_exists( 'acf' ) ) {
4768 // We have an ACF field value, so use the ACF function to update it.
4769 update_field( str_replace('acf___', '', $meta_key ), $meta_value, 'user_' . $wp_user->ID );
4770 } else {
4771 // We have a normal usermeta value, so just update it via the WordPress function.
4772 update_user_meta( $wp_user->ID, $meta_key, $meta_value );
4773 }
4774
4775 }
4776
4777 // Return 'success' value to AJAX call.
4778 die( 'success' );
4779 }
4780
4781
4782 function ajax_update_auth_user() {
4783 // Fail silently if current user doesn't have permissions.
4784 if ( ! current_user_can( 'create_users' ) ) {
4785 die( '' );
4786 }
4787
4788 // Nonce check.
4789 if ( empty( $_POST['nonce_save_auth_settings'] ) || ! wp_verify_nonce( $_POST['nonce_save_auth_settings'], 'save_auth_settings' ) ) {
4790 die( '' );
4791 }
4792
4793 // Fail if requesting a change to an invalid setting.
4794 if ( ! in_array( $_POST['setting'], array( 'access_users_pending', 'access_users_approved', 'access_users_blocked' ) ) ) {
4795 die( '' );
4796 }
4797
4798 // Editing a pending list entry.
4799 if ( $_POST['setting'] === 'access_users_pending' ) {
4800 // Initialize posted data if empty.
4801 if ( ! ( array_key_exists( 'access_users_pending', $_POST ) && is_array( $_POST['access_users_pending'] ) ) ) {
4802 $_POST['access_users_pending'] = array();
4803 }
4804
4805 // Deal with each modified user (add or remove).
4806 foreach ( $_POST['access_users_pending'] as $pending_user ) {
4807
4808 if ( $pending_user['edit_action'] === 'add' ) {
4809
4810 // Add new user to pending list and save (skip if it's
4811 // already there--someone else might have just done it).
4812 if ( ! $this->is_email_in_list( $pending_user['email'], 'pending' ) ) {
4813 $auth_settings_access_users_pending = $this->sanitize_user_list(
4814 $this->get_plugin_option( 'access_users_pending', SINGLE_ADMIN )
4815 );
4816 array_push( $auth_settings_access_users_pending, $pending_user );
4817 update_option( 'auth_settings_access_users_pending', $auth_settings_access_users_pending );
4818 }
4819
4820 } elseif ( $pending_user['edit_action'] === 'remove' ) {
4821
4822 // Remove user from pending list and save
4823 if ( $this->is_email_in_list( $pending_user['email'], 'pending' ) ) {
4824 $auth_settings_access_users_pending = $this->sanitize_user_list(
4825 $this->get_plugin_option( 'access_users_pending', SINGLE_ADMIN )
4826 );
4827 foreach ( $auth_settings_access_users_pending as $key => $existing_user ) {
4828 if ( 0 === strcasecmp( $pending_user['email'], $existing_user['email'] ) ) {
4829 unset( $auth_settings_access_users_pending[$key] );
4830 break;
4831 }
4832 }
4833 update_option( 'auth_settings_access_users_pending', $auth_settings_access_users_pending );
4834 }
4835
4836 }
4837 }
4838 }
4839
4840 // Editing an approved list entry.
4841 if ( $_POST['setting'] === 'access_users_approved' ) {
4842 // Initialize posted data if empty.
4843 if ( ! ( array_key_exists( 'access_users_approved', $_POST ) && is_array( $_POST['access_users_approved'] ) ) ) {
4844 $_POST['access_users_approved'] = array();
4845 }
4846
4847 // Deal with each modified user (add, remove, or change_role).
4848 foreach ( $_POST['access_users_approved'] as $approved_user ) {
4849
4850 // New user (create user, or add existing user to current site in multisite).
4851 if ( $approved_user['edit_action'] === 'add' ) {
4852 $new_user = get_user_by( 'email', $approved_user['email'] );
4853 if ( $new_user !== false ) {
4854 // If we're adding an existing multisite user, make sure their
4855 // newly-assigned role is updated on all sites they are already in.
4856 if ( is_multisite() && $approved_user['multisite_user'] !== 'false' ) {
4857 foreach ( get_blogs_of_user( $new_user->ID ) as $blog ) {
4858 add_user_to_blog( $blog->userblog_id, $new_user->ID, $approved_user['role'] );
4859 }
4860 }
4861 // If this user already has an account on another site in the network, add them to this site.
4862 if ( is_multisite() ) {
4863 add_user_to_blog( get_current_blog_id(), $new_user->ID, $approved_user['role'] );
4864 }
4865 } elseif ( $approved_user['local_user'] === 'true' ) {
4866 // Create a WP account for this new *local* user and email the password.
4867 $plaintext_password = wp_generate_password(); // random password
4868 // If there's already a user with this username (e.g.,
4869 // johndoe/johndoe@gmail.com exists, and we're trying to add
4870 // johndoe/johndoe@example.com), use the full email address
4871 // as the username.
4872 $username = explode( '@', $approved_user['email'] );
4873 $username = $username[0];
4874 if ( get_user_by( 'login', $username ) !== false ) {
4875 $username = mb_strtolower( $approved_user['email'] );
4876 }
4877 if ( $approved_user['multisite_user'] !== 'false' ) {
4878 $result = wpmu_create_user(
4879 strtolower( $username ),
4880 $plaintext_password,
4881 mb_strtolower( $approved_user['email'] )
4882 );
4883 } else {
4884 $result = wp_insert_user(
4885 array(
4886 'user_login' => strtolower( $username ),
4887 'user_pass' => $plaintext_password,
4888 'first_name' => '',
4889 'last_name' => '',
4890 'user_email' => mb_strtolower( $approved_user['email'] ),
4891 'user_registered' => date( 'Y-m-d H:i:s' ),
4892 'role' => $approved_user['role'],
4893 )
4894 );
4895 }
4896 if ( ! is_wp_error( $result ) ) {
4897 // Email login credentials to new user.
4898 wp_new_user_notification( $result, null, 'both' );
4899 }
4900
4901 }
4902
4903 // Email new user welcome message if plugin option is set.
4904 $this->maybe_email_welcome_message( $approved_user['email'] );
4905
4906 // Add new user to approved list and save (skip if it's
4907 // already there--someone else might have just done it).
4908 if ( $approved_user['multisite_user'] !== 'false' ) {
4909 if ( ! $this->is_email_in_list( $approved_user['email'], 'approved', 'multisite' ) ) {
4910 $auth_multisite_settings_access_users_approved = $this->sanitize_user_list(
4911 $this->get_plugin_option( 'access_users_approved', MULTISITE_ADMIN )
4912 );
4913 $approved_user['date_added'] = date( 'M Y' );
4914 array_push( $auth_multisite_settings_access_users_approved, $approved_user );
4915 update_blog_option( BLOG_ID_CURRENT_SITE, 'auth_multisite_settings_access_users_approved', $auth_multisite_settings_access_users_approved );
4916 }
4917 } else {
4918 if ( ! $this->is_email_in_list( $approved_user['email'], 'approved' ) ) {
4919 $auth_settings_access_users_approved = $this->sanitize_user_list(
4920 $this->get_plugin_option( 'access_users_approved', SINGLE_ADMIN )
4921 );
4922 $approved_user['date_added'] = date( 'M Y' );
4923 array_push( $auth_settings_access_users_approved, $approved_user );
4924 update_option( 'auth_settings_access_users_approved', $auth_settings_access_users_approved );
4925 }
4926 }
4927
4928 // If we've added a new multisite user, go through all pending/approved/blocked lists
4929 // on individual sites and remove this user from them (to prevent duplicate entries).
4930 if ( $approved_user['multisite_user'] !== 'false' && is_multisite() ) {
4931 $list_names = array( 'access_users_pending', 'access_users_approved', 'access_users_blocked' );
4932 $sites = function_exists( 'get_sites' ) ? get_sites() : wp_get_sites( array( 'limit' => PHP_INT_MAX ) );
4933 foreach ( $sites as $site ) {
4934 $blog_id = function_exists( 'get_sites' ) ? $site->blog_id : $site['blog_id'];
4935 foreach ( $list_names as $list_name ) {
4936 $user_list = get_blog_option( $blog_id, 'auth_settings_' . $list_name, array() );
4937 $list_changed = false;
4938 foreach ( $user_list as $key => $user ) {
4939 if ( 0 === strcasecmp( $user['email'], $approved_user['email'] ) ) {
4940 unset( $user_list[$key] );
4941 $list_changed = true;
4942 }
4943 }
4944 if ( $list_changed ) {
4945 update_blog_option( $blog_id, 'auth_settings_' . $list_name, $user_list );
4946 }
4947 }
4948 }
4949 }
4950
4951 // Remove user from approved list and save (also remove their role if they have a WordPress account)
4952 } elseif ( $approved_user['edit_action'] === 'remove' ) {
4953 if ( $approved_user['multisite_user'] !== 'false' ) {
4954 if ( $this->is_email_in_list( $approved_user['email'], 'approved', 'multisite' ) ) {
4955 $auth_multisite_settings_access_users_approved = $this->sanitize_user_list(
4956 $this->get_plugin_option( 'access_users_approved', MULTISITE_ADMIN )
4957 );
4958 foreach ( $auth_multisite_settings_access_users_approved as $key => $existing_user ) {
4959 if ( 0 === strcasecmp( $approved_user['email'], $existing_user['email'] ) ) {
4960 // Remove role of the associated WordPress user from all blogs (but don't delete the user).
4961 $user = get_user_by( 'email', $approved_user['email'] );
4962 if ( $user !== false ) {
4963 // Loop through all of the blogs this user is a member of and remove their capabilities.
4964 foreach ( get_blogs_of_user( $user->ID ) as $blog ) {
4965 remove_user_from_blog( $user->ID, $blog->userblog_id, '' );
4966 }
4967 }
4968 // Remove entry from Approved Users list.
4969 unset( $auth_multisite_settings_access_users_approved[$key] );
4970 break;
4971 }
4972 }
4973 update_blog_option( BLOG_ID_CURRENT_SITE, 'auth_multisite_settings_access_users_approved', $auth_multisite_settings_access_users_approved );
4974 }
4975 } else {
4976 if ( $this->is_email_in_list( $approved_user['email'], 'approved' ) ) {
4977 $auth_settings_access_users_approved = $this->sanitize_user_list(
4978 $this->get_plugin_option( 'access_users_approved', SINGLE_ADMIN )
4979 );
4980 foreach ( $auth_settings_access_users_approved as $key => $existing_user ) {
4981 if ( 0 === strcasecmp( $approved_user['email'], $existing_user['email'] ) ) {
4982 // Remove role of the associated WordPress user (but don't delete the user).
4983 $user = get_user_by( 'email', $approved_user['email'] );
4984 if ( $user !== false ) {
4985 $user->set_role( '' );
4986 }
4987 // Remove entry from Approved Users list.
4988 unset( $auth_settings_access_users_approved[$key] );
4989 break;
4990 }
4991 }
4992 update_option( 'auth_settings_access_users_approved', $auth_settings_access_users_approved );
4993 }
4994 }
4995
4996 // Update user's role in WordPress
4997 } elseif ( $approved_user['edit_action'] === 'change_role' ) {
4998 $changed_user = get_user_by( 'email', $approved_user['email'] );
4999 if ( $changed_user ) {
5000 if ( is_multisite() && $approved_user['multisite_user'] !== 'false' ) {
5001 foreach ( get_blogs_of_user( $changed_user->ID ) as $blog ) {
5002 add_user_to_blog( $blog->userblog_id, $changed_user->ID, $approved_user['role'] );
5003 }
5004 } else {
5005 $changed_user->set_role( $approved_user['role'] );
5006 }
5007 }
5008
5009 if ( $approved_user['multisite_user'] !== 'false' ) {
5010 if ( $this->is_email_in_list( $approved_user['email'], 'approved', 'multisite' ) ) {
5011 $auth_multisite_settings_access_users_approved = $this->sanitize_user_list(
5012 $this->get_plugin_option( 'access_users_approved', MULTISITE_ADMIN )
5013 );
5014 foreach ( $auth_multisite_settings_access_users_approved as $key => $existing_user ) {
5015 if ( 0 === strcasecmp( $approved_user['email'], $existing_user['email'] ) ) {
5016 $auth_multisite_settings_access_users_approved[$key]['role'] = $approved_user['role'];
5017 break;
5018 }
5019 }
5020 update_blog_option( BLOG_ID_CURRENT_SITE, 'auth_multisite_settings_access_users_approved', $auth_multisite_settings_access_users_approved );
5021 }
5022 } else {
5023 // Update user's role in approved list and save.
5024 if ( $this->is_email_in_list( $approved_user['email'], 'approved' ) ) {
5025 $auth_settings_access_users_approved = $this->sanitize_user_list(
5026 $this->get_plugin_option( 'access_users_approved', SINGLE_ADMIN )
5027 );
5028 foreach ( $auth_settings_access_users_approved as $key => $existing_user ) {
5029 if ( 0 === strcasecmp( $approved_user['email'], $existing_user['email'] ) ) {
5030 $auth_settings_access_users_approved[$key]['role'] = $approved_user['role'];
5031 break;
5032 }
5033 }
5034 update_option( 'auth_settings_access_users_approved', $auth_settings_access_users_approved );
5035 }
5036 }
5037
5038 }
5039 }
5040 }
5041
5042 // Editing a blocked list entry.
5043 if ( $_POST['setting'] === 'access_users_blocked' ) {
5044 // Initialize posted data if empty.
5045 if ( ! ( array_key_exists( 'access_users_blocked', $_POST ) && is_array( $_POST['access_users_blocked'] ) ) ) {
5046 $_POST['access_users_blocked'] = array();
5047 }
5048
5049 // Deal with each modified user (add or remove).
5050 foreach ( $_POST['access_users_blocked'] as $blocked_user ) {
5051
5052 if ( $blocked_user['edit_action'] === 'add' ) {
5053
5054 // Add auth_blocked usermeta for the user.
5055 $blocked_wp_user = get_user_by( 'email', $blocked_user['email'] );
5056 if ( $blocked_wp_user !== false ) {
5057 update_user_meta( $blocked_wp_user->ID, 'auth_blocked', 'yes' );
5058 }
5059
5060 // Add new user to blocked list and save (skip if it's
5061 // already there--someone else might have just done it).
5062 if ( ! $this->is_email_in_list( $blocked_user['email'], 'blocked' ) ) {
5063 $auth_settings_access_users_blocked = $this->sanitize_user_list(
5064 $this->get_plugin_option( 'access_users_blocked', SINGLE_ADMIN )
5065 );
5066 $blocked_user['date_added'] = date( 'M Y' );
5067 array_push( $auth_settings_access_users_blocked, $blocked_user );
5068 update_option( 'auth_settings_access_users_blocked', $auth_settings_access_users_blocked );
5069 }
5070
5071 } elseif ( $blocked_user['edit_action'] === 'remove' ) {
5072
5073 // Remove auth_blocked usermeta for the user.
5074 $unblocked_user = get_user_by( 'email', $blocked_user['email'] );
5075 if ( $unblocked_user !== false ) {
5076 delete_user_meta( $unblocked_user->ID, 'auth_blocked', 'yes' );
5077 }
5078
5079 // Remove user from blocked list and save
5080 if ( $this->is_email_in_list( $blocked_user['email'], 'blocked' ) ) {
5081 $auth_settings_access_users_blocked = $this->sanitize_user_list(
5082 $this->get_plugin_option( 'access_users_blocked', SINGLE_ADMIN )
5083 );
5084 foreach ( $auth_settings_access_users_blocked as $key => $existing_user ) {
5085 if ( 0 === strcasecmp( $blocked_user['email'], $existing_user['email'] ) ) {
5086 unset( $auth_settings_access_users_blocked[$key] );
5087 break;
5088 }
5089 }
5090 update_option( 'auth_settings_access_users_blocked', $auth_settings_access_users_blocked );
5091 }
5092
5093 }
5094 }
5095 }
5096
5097 // Return 'success' value to AJAX call.
5098 die( 'success' );
5099 }
5100
5101
5102
5103 /**
5104 * ***************************
5105 * Helper functions
5106 * ***************************
5107 */
5108
5109
5110 /**
5111 * Retrieves a specific plugin option from db. Multisite enabled.
5112 *
5113 * @param string $option Option name
5114 * @param string $admin_mode MULTISITE_ADMIN will retrieve the multisite value
5115 * @param string $override_mode 'allow override' will retrieve the multisite value if it exists
5116 * @param string $print_mode 'print overlay' will output overlay that hides this option on the settings page
5117 * @return mixed Option value, or null on failure
5118 */
5119 private function get_plugin_option( $option, $admin_mode = SINGLE_ADMIN, $override_mode = 'no override', $print_mode = 'no overlay' ) {
5120 // Special case for user lists (they are saved seperately to prevent concurrency issues).
5121 if ( in_array( $option, array( 'access_users_pending', 'access_users_approved', 'access_users_blocked' ) ) ) {
5122 $list = $admin_mode === MULTISITE_ADMIN ? array() : get_option( 'auth_settings_' . $option );
5123 if ( is_multisite() && $admin_mode === MULTISITE_ADMIN ) {
5124 $list = get_blog_option( BLOG_ID_CURRENT_SITE, 'auth_multisite_settings_' . $option, array() );
5125 }
5126 return $list;
5127 }
5128
5129 // Get all plugin options.
5130 $auth_settings = $this->get_plugin_options( $admin_mode, $override_mode );
5131
5132 // Set option to null if it wasn't found.
5133 if ( ! array_key_exists( $option, $auth_settings ) ) {
5134 return null;
5135 }
5136
5137 // If requested and appropriate, print the overlay hiding the
5138 // single site option that is overridden by a multisite option.
5139 if (
5140 $admin_mode !== MULTISITE_ADMIN &&
5141 $override_mode === 'allow override' &&
5142 $print_mode === 'print overlay' &&
5143 array_key_exists( 'multisite_override', $auth_settings ) &&
5144 $auth_settings['multisite_override'] === '1' &&
5145 ( ! array_key_exists( 'advanced_override_multisite', $auth_settings ) || $auth_settings['advanced_override_multisite'] != '1' )
5146 ) {
5147 // Get original plugin options (not overridden value). We'll
5148 // show this old value behind the disabled overlay.
5149 $auth_settings = $this->get_plugin_options( $admin_mode, 'no override' );
5150
5151 $name = "auth_settings[$option]";
5152 $id = "auth_settings_$option"; ?>
5153 <div id="overlay-hide-auth_settings_<?php echo $option; ?>" class="auth_multisite_override_overlay">
5154 <span class="overlay-note">
5155 <?php _e( 'This setting is overridden by a', 'authorizer' ); ?> <a href="<?php echo network_admin_url( 'admin.php?page=authorizer&tab=external' ); ?>"><?php _e( 'multisite option', 'authorizer' ); ?></a>.
5156 </span>
5157 </div>
5158 <?php
5159 }
5160
5161 // If we're getting an option in a site that has overridden the multisite override, make
5162 // sure we are returning the option value from that site (not the multisite value).
5163 if ( array_key_exists( 'advanced_override_multisite', $auth_settings ) && $auth_settings['advanced_override_multisite'] == '1' ) {
5164 $auth_settings = $this->get_plugin_options( $admin_mode, 'no override' );
5165 }
5166
5167 // Set option to null if it wasn't found.
5168 if ( ! array_key_exists( $option, $auth_settings ) ) {
5169 return null;
5170 }
5171
5172 return $auth_settings[$option];
5173 }
5174
5175 /**
5176 * Retrieves all plugin options from db. Multisite enabled.
5177 *
5178 * @param string $admin_mode MULTISITE_ADMIN will retrieve the multisite value
5179 * @param string $override_mode 'allow override' will retrieve the multisite value if it exists
5180 * @return mixed Option value, or null on failure
5181 */
5182 private function get_plugin_options( $admin_mode = SINGLE_ADMIN, $override_mode = 'no override' ) {
5183 // Grab plugin settings (skip if in MULTISITE_ADMIN mode).
5184 $auth_settings = $admin_mode === MULTISITE_ADMIN ? array() : get_option( 'auth_settings' );
5185
5186 // Initialize to default values if the plugin option doesn't exist.
5187 if ( $auth_settings === FALSE ) {
5188 $auth_settings = $this->set_default_options();
5189 }
5190
5191 // Merge multisite options if we're in a network and the current site hasn't overridden multisite settings.
5192 if ( is_multisite() && ( ! array_key_exists( 'advanced_override_multisite', $auth_settings ) || $auth_settings['advanced_override_multisite'] != '1' ) ) {
5193 // Get multisite options.
5194 $auth_multisite_settings = get_blog_option( BLOG_ID_CURRENT_SITE, 'auth_multisite_settings', array() );
5195
5196 // Return the multisite options if we're viewing the network admin options page.
5197 // Otherwise override options with their multisite equivalents.
5198 if ( $admin_mode === MULTISITE_ADMIN ) {
5199 $auth_settings = $auth_multisite_settings;
5200 } elseif (
5201 $override_mode === 'allow override' &&
5202 array_key_exists( 'multisite_override', $auth_multisite_settings ) &&
5203 $auth_multisite_settings['multisite_override'] === '1'
5204 ) {
5205 // Keep track of the multisite override selection.
5206 $auth_settings['multisite_override'] = $auth_multisite_settings['multisite_override'];
5207
5208 // Note: the options below should be the complete list of
5209 // overridden options. It is *not* the complete list of all
5210 // options (some options don't have a multisite equivalent)
5211
5212 // Note: access_users_approved, access_users_pending, and
5213 // access_users_blocked do not get overridden. However,
5214 // since access_users_approved has a multisite equivalent,
5215 // you must retrieve them both seperately. This is done
5216 // because the two lists should be treated differently.
5217 // $approved_users = $this->get_plugin_option( 'access_users_approved', SINGLE_ADMIN );
5218 // $ms_approved_users = $this->get_plugin_option( 'access_users_approved', MULTISITE_ADMIN );
5219
5220 // Override external services (google, cas, or ldap) and associated options
5221 $auth_settings['google'] = $auth_multisite_settings['google'];
5222 $auth_settings['google_clientid'] = $auth_multisite_settings['google_clientid'];
5223 $auth_settings['google_clientsecret'] = $auth_multisite_settings['google_clientsecret'];
5224 $auth_settings['google_hosteddomain'] = $auth_multisite_settings['google_hosteddomain'];
5225 $auth_settings['cas'] = $auth_multisite_settings['cas'];
5226 $auth_settings['cas_custom_label'] = $auth_multisite_settings['cas_custom_label'];
5227 $auth_settings['cas_host'] = $auth_multisite_settings['cas_host'];
5228 $auth_settings['cas_port'] = $auth_multisite_settings['cas_port'];
5229 $auth_settings['cas_path'] = $auth_multisite_settings['cas_path'];
5230 $auth_settings['cas_version'] = $auth_multisite_settings['cas_version'];
5231 $auth_settings['cas_attr_email'] = $auth_multisite_settings['cas_attr_email'];
5232 $auth_settings['cas_attr_first_name'] = $auth_multisite_settings['cas_attr_first_name'];
5233 $auth_settings['cas_attr_last_name'] = $auth_multisite_settings['cas_attr_last_name'];
5234 $auth_settings['cas_attr_update_on_login'] = $auth_multisite_settings['cas_attr_update_on_login'];
5235 $auth_settings['cas_auto_login'] = $auth_multisite_settings['cas_auto_login'];
5236 $auth_settings['ldap'] = $auth_multisite_settings['ldap'];
5237 $auth_settings['ldap_host'] = $auth_multisite_settings['ldap_host'];
5238 $auth_settings['ldap_port'] = $auth_multisite_settings['ldap_port'];
5239 $auth_settings['ldap_tls'] = $auth_multisite_settings['ldap_tls'];
5240 $auth_settings['ldap_search_base'] = $auth_multisite_settings['ldap_search_base'];
5241 $auth_settings['ldap_uid'] = $auth_multisite_settings['ldap_uid'];
5242 $auth_settings['ldap_attr_email'] = $auth_multisite_settings['ldap_attr_email'];
5243 $auth_settings['ldap_user'] = $auth_multisite_settings['ldap_user'];
5244 $auth_settings['ldap_password'] = $auth_multisite_settings['ldap_password'];
5245 $auth_settings['ldap_lostpassword_url'] = $auth_multisite_settings['ldap_lostpassword_url'];
5246 $auth_settings['ldap_attr_first_name'] = $auth_multisite_settings['ldap_attr_first_name'];
5247 $auth_settings['ldap_attr_last_name'] = $auth_multisite_settings['ldap_attr_last_name'];
5248 $auth_settings['ldap_attr_update_on_login'] = $auth_multisite_settings['ldap_attr_update_on_login'];
5249
5250 // Override access_who_can_login and access_who_can_view
5251 $auth_settings['access_who_can_login'] = $auth_multisite_settings['access_who_can_login'];
5252 $auth_settings['access_who_can_view'] = $auth_multisite_settings['access_who_can_view'];
5253
5254 // Override access_default_role
5255 $auth_settings['access_default_role'] = $auth_multisite_settings['access_default_role'];
5256
5257 // Override lockouts
5258 $auth_settings['advanced_lockouts'] = $auth_multisite_settings['advanced_lockouts'];
5259
5260 // Override Hide WordPress login
5261 $auth_settings['advanced_hide_wp_login'] = $auth_multisite_settings['advanced_hide_wp_login'];
5262 }
5263 }
5264 return $auth_settings;
5265 }
5266
5267
5268 /**
5269 * Remove user from authorizer lists when that user is deleted in WordPress.
5270 * Run on action hook: delete_user
5271 */
5272 function remove_user_from_authorizer_when_deleted( $user_id ) {
5273 $user = get_user_by( 'id', $user_id );
5274 $deleted_email = $user->user_email;
5275
5276 // Remove user from pending/approved lists and save.
5277 $list_names = array( 'access_users_pending', 'access_users_approved' );
5278 foreach ( $list_names as $list_name ) {
5279 $user_list = $this->sanitize_user_list( $this->get_plugin_option( $list_name, SINGLE_ADMIN ) );
5280 $list_changed = false;
5281 foreach ( $user_list as $key => $existing_user ) {
5282 if ( 0 === strcasecmp( $deleted_email, $existing_user['email'] ) ) {
5283 $list_changed = true;
5284 unset( $user_list[$key] );
5285 }
5286 }
5287 if ( $list_changed ) {
5288 update_option( 'auth_settings_' . $list_name, $user_list );
5289 }
5290 }
5291 }
5292
5293
5294 /**
5295 * Remove multisite user from authorizer lists when that user is deleted from Network Users.
5296 * Run on action hook: wpmu_delete_user
5297 */
5298 function remove_network_user_from_authorizer_when_deleted( $user_id ) {
5299 $user = get_user_by( 'id', $user_id );
5300 $deleted_email = $user->user_email;
5301
5302 // Go through multisite approved user list and remove this user.
5303 $auth_multisite_settings_access_users_approved = $this->sanitize_user_list(
5304 $this->get_plugin_option( 'access_users_approved', MULTISITE_ADMIN )
5305 );
5306 $list_changed = false;
5307 foreach ( $auth_multisite_settings_access_users_approved as $key => $existing_user ) {
5308 if ( 0 === strcasecmp( $deleted_email, $existing_user['email'] ) ) {
5309 $list_changed = true;
5310 unset( $auth_multisite_settings_access_users_approved[$key] );
5311 }
5312 }
5313 if ( $list_changed ) {
5314 update_blog_option( BLOG_ID_CURRENT_SITE, 'auth_multisite_settings_access_users_approved', $auth_multisite_settings_access_users_approved );
5315 }
5316
5317 // Go through all pending/approved lists on individual sites and remove this user from them.
5318 $sites = function_exists( 'get_sites' ) ? get_sites() : wp_get_sites( array( 'limit' => PHP_INT_MAX ) );
5319 foreach ( $sites as $site ) {
5320 $blog_id = function_exists( 'get_sites' ) ? $site->blog_id : $site['blog_id'];
5321 $this->remove_network_user_from_site_when_removed( $user_id, $blog_id );
5322 }
5323
5324 }
5325
5326
5327 /**
5328 * Remove multisite user from a specific site's lists when that user is removed from the site.
5329 * Run on action hook: remove_user_from_blog
5330 */
5331 function remove_network_user_from_site_when_removed( $user_id, $blog_id ) {
5332 $user = get_user_by( 'id', $user_id );
5333 $deleted_email = $user->user_email;
5334
5335 $list_names = array( 'access_users_pending', 'access_users_approved' );
5336 foreach ( $list_names as $list_name ) {
5337 $user_list = get_blog_option( $blog_id, 'auth_settings_' . $list_name, array() );
5338 $list_changed = false;
5339 foreach ( $user_list as $key => $existing_user ) {
5340 if ( 0 === strcasecmp( $deleted_email, $existing_user['email'] ) ) {
5341 $list_changed = true;
5342 unset( $user_list[$key] );
5343 }
5344 }
5345 if ( $list_changed ) {
5346 update_blog_option( $blog_id, 'auth_settings_' . $list_name, $user_list );
5347 }
5348 }
5349 }
5350
5351
5352 /**
5353 * Helper: Add multisite user to a specific site's approved list.
5354 */
5355 function add_network_user_to_site( $user_id, $blog_id ) {
5356 // Switch to blog.
5357 switch_to_blog( $blog_id );
5358
5359 // Get user details and role.
5360 $access_default_role = $this->get_plugin_option( 'access_default_role', SINGLE_ADMIN, 'allow override' );
5361 $user = get_user_by( 'id', $user_id );
5362 $user_email = $user->user_email;
5363 $user_role = $user && is_array( $user->roles ) && count( $user->roles ) > 0 ? $user->roles[0] : $access_default_role;
5364
5365 // Add user to approved list if not already there and not in blocked list.
5366 $auth_settings_access_users_approved = $this->get_plugin_option( 'access_users_approved', SINGLE_ADMIN );
5367 $auth_settings_access_users_blocked = $this->get_plugin_option( 'access_users_blocked', SINGLE_ADMIN );
5368 if ( ! $this->in_multi_array( $user_email, $auth_settings_access_users_approved ) && ! $this->in_multi_array( $user_email, $auth_settings_access_users_blocked ) ) {
5369 $approved_user = array(
5370 'email' => mb_strtolower( $user_email ),
5371 'role' => $user_role,
5372 'date_added' => date( 'M Y', strtotime( $user->user_registered ) ),
5373 'local_user' => true,
5374 );
5375 array_push( $auth_settings_access_users_approved, $approved_user );
5376 update_option( 'auth_settings_access_users_approved', $auth_settings_access_users_approved );
5377 }
5378
5379 // Restore original blog.
5380 restore_current_blog();
5381 }
5382
5383
5384 /**
5385 * Multisite:
5386 * When an existing user is invited to the current site (or a new user is created),
5387 * add them to the authorizer approved list. This action fires when the admin
5388 * doesn't select the "Skip Confirmation Email" option.
5389 *
5390 * @action invite_user
5391 *
5392 * @param int $user_id The invited user's ID.
5393 * @param array $role The role of the invited user (or none if a new user creation).
5394 * @param string $newuser_key The key of the invitation.
5395 */
5396 function add_existing_user_to_authorizer_when_created( $user_id, $role = array(), $newuser_key = '' ) {
5397 $user = get_user_by( 'id', $user_id );
5398 $this->add_user_to_authorizer_when_created( $user->user_email, $user->user_registered, $user->user_roles, $role );
5399 }
5400
5401
5402 /**
5403 * Multisite:
5404 * When an existing user is invited to the current site (or a new user is created),
5405 * add them to the authorizer approved list. This action fires when the admin
5406 * selects the "Skip Confirmation Email" option.
5407 *
5408 * @action added_existing_user
5409 *
5410 * @param int $user_id The invited user's ID.
5411 * @param mixed $result True on success or a WP_Error object if the user doesn't exist.
5412 */
5413 function add_existing_user_to_authorizer_when_created_noconfirmation( $user_id, $result ) {
5414 $user = get_user_by( 'id', $user_id );
5415 $this->add_user_to_authorizer_when_created( $user->user_email, $user->user_registered, $user->user_roles );
5416 }
5417
5418
5419 /**
5420 * Multisite:
5421 * When a new user is invited to the current site (or a new user is created),
5422 * add them to the authorizer approved list.
5423 *
5424 * @action after_signup_user
5425 *
5426 * @param string $user User's requested login name.
5427 * @param string $user_email User's email address.
5428 * @param string $key User's activation key.
5429 * @param array $meta Additional signup meta.
5430 */
5431 function add_new_user_to_authorizer_when_created( $user, $user_email, $key, $meta ) {
5432 $this->add_user_to_authorizer_when_created( $user_email, time() );
5433 }
5434
5435
5436 /**
5437 * Single site:
5438 * When a new user is added in single site mode, add them to the authorizer
5439 * approved list.
5440 *
5441 * @action edit_user_created_user
5442 *
5443 * @param int $user_id ID of the newly created user.
5444 * @param string $notify Type of notification that should happen. See wp_send_new_user_notifications()
5445 * for more information on possible values.
5446 */
5447 function add_new_user_to_authorizer_when_created_single_site( $user_id, $notify ) {
5448 $user = get_user_by( 'id', $user_id );
5449 $this->add_user_to_authorizer_when_created( $user->user_email, $user->user_registered, $user->user_roles );
5450 }
5451
5452
5453 /**
5454 * Helper: When a new user is added/invited to the current site (or a new
5455 * user is created), add them to the authorizer approved list.
5456 */
5457 private function add_user_to_authorizer_when_created( $user_email, $date_registered, $user_roles = array(), $default_role = array() ) {
5458 $auth_multisite_settings_access_users_approved = is_multisite() ? get_blog_option( BLOG_ID_CURRENT_SITE, 'auth_multisite_settings_access_users_approved', array() ) : array();
5459 $auth_settings_access_users_pending = $this->get_plugin_option( 'access_users_pending', SINGLE_ADMIN );
5460 $auth_settings_access_users_approved = $this->get_plugin_option( 'access_users_approved', SINGLE_ADMIN );
5461 $auth_settings_access_users_blocked = $this->get_plugin_option( 'access_users_blocked', SINGLE_ADMIN );
5462
5463 // Get default role if one isn't specified.
5464 if ( count( $default_role ) < 1 ) {
5465 $default_role = '';
5466 } else {
5467 $default_role = strtolower( $default_role['name'] );
5468 }
5469
5470 $updated = false;
5471
5472 // Skip if user is in blocked list.
5473 if ( $this->in_multi_array( $user_email, $auth_settings_access_users_blocked ) ) {
5474 return;
5475 }
5476 // Remove from pending list if there.
5477 foreach ( $auth_settings_access_users_pending as $key => $pending_user ) {
5478 if ( 0 === strcasecmp( $pending_user['email'], $user_email ) ) {
5479 unset( $auth_settings_access_users_pending[$key] );
5480 $updated = true;
5481 }
5482 }
5483 // Skip if user is in multisite approved list.
5484 if ( $this->in_multi_array( $user_email, $auth_multisite_settings_access_users_approved ) ) {
5485 return;
5486 }
5487 // Add to approved list if not there.
5488 if ( ! $this->in_multi_array( $user_email, $auth_settings_access_users_approved ) ) {
5489 $approved_user = array(
5490 'email' => mb_strtolower( $user_email ),
5491 'role' => is_array( $user_roles ) && count( $user_roles ) > 0 ? $user_roles[0] : $default_role,
5492 'date_added' => date( 'M Y', strtotime( $date_registered ) ),
5493 'local_user' => true,
5494 );
5495 array_push( $auth_settings_access_users_approved, $approved_user );
5496 $updated = true;
5497 }
5498
5499 if ( $updated ) {
5500 update_option( 'auth_settings_access_users_pending', $auth_settings_access_users_pending );
5501 update_option( 'auth_settings_access_users_approved', $auth_settings_access_users_approved );
5502 }
5503 }
5504
5505
5506 /**
5507 * Multisite:
5508 * When a user is granted super admin status (checkbox on network user edit
5509 * screen), add them to the authorizer network approved list. Also remove
5510 * them from pending/approved list on any individual sites.
5511 *
5512 * @action grant_super_admin
5513 *
5514 * @param int $user_id The user's ID.
5515 */
5516 function grant_super_admin__add_to_network_approved( $user_id ) {
5517 $user = get_user_by( 'id', $user_id );
5518 $user_email = $user->user_email;
5519
5520 // Add user to multisite approved user list (if not already there).
5521 $auth_multisite_settings_access_users_approved = $this->sanitize_user_list(
5522 $this->get_plugin_option( 'access_users_approved', MULTISITE_ADMIN )
5523 );
5524 if ( ! $this->in_multi_array( $user_email, $auth_multisite_settings_access_users_approved ) ) {
5525 $multisite_approved_user = array(
5526 'email' => mb_strtolower( $user_email ),
5527 'role' => count( $user->roles ) > 0 ? $user->roles[0] : 'administrator',
5528 'date_added' => date( 'M Y', strtotime( $user->user_registered ) ),
5529 'local_user' => true,
5530 );
5531 array_push( $auth_multisite_settings_access_users_approved, $multisite_approved_user );
5532 update_blog_option( BLOG_ID_CURRENT_SITE, 'auth_multisite_settings_access_users_approved', $auth_multisite_settings_access_users_approved );
5533 }
5534
5535 // Go through all pending/approved lists on individual sites and remove this user from them.
5536 $sites = function_exists( 'get_sites' ) ? get_sites() : wp_get_sites( array( 'limit' => PHP_INT_MAX ) );
5537 foreach ( $sites as $site ) {
5538 $blog_id = function_exists( 'get_sites' ) ? $site->blog_id : $site['blog_id'];
5539 $this->remove_network_user_from_site_when_removed( $user_id, $blog_id );
5540 }
5541
5542 }
5543
5544 /**
5545 * Multisite:
5546 * When a user's super admin status is revoked (checkbox on network user edit
5547 * screen), remove them from the authorizer network approved list. Also add
5548 * them to approved list on any individual sites they are already a part of.
5549 *
5550 * @action revoke_super_admin
5551 *
5552 * @param int $user_id The user's ID.
5553 */
5554 function revoke_super_admin__remove_from_network_approved( $user_id ) {
5555 $user = get_user_by( 'id', $user_id );
5556 $revoked_email = $user->user_email;
5557
5558 // Go through multisite approved user list and remove this user.
5559 $auth_multisite_settings_access_users_approved = $this->sanitize_user_list(
5560 $this->get_plugin_option( 'access_users_approved', MULTISITE_ADMIN )
5561 );
5562 $list_changed = false;
5563 foreach ( $auth_multisite_settings_access_users_approved as $key => $existing_user ) {
5564 if ( 0 === strcasecmp( $revoked_email, $existing_user['email'] ) ) {
5565 $list_changed = true;
5566 unset( $auth_multisite_settings_access_users_approved[$key] );
5567 }
5568 }
5569 if ( $list_changed ) {
5570 update_blog_option( BLOG_ID_CURRENT_SITE, 'auth_multisite_settings_access_users_approved', $auth_multisite_settings_access_users_approved );
5571 }
5572
5573 // Go through this user's current sites and add them to the approved list
5574 // (since they are no longer on the network approved list).
5575 $sites_of_user = get_blogs_of_user( $user_id );
5576 foreach ( $sites_of_user as $site ) {
5577 $blog_id = $site->userblog_id;
5578 $this->add_network_user_to_site( $user_id, $blog_id );
5579 }
5580
5581 }
5582
5583 private function maybe_email_welcome_message( $email ) {
5584 // Get option for whether to email welcome messages.
5585 $should_email_new_approved_users = $this->get_plugin_option( 'access_should_email_approved_users' );
5586
5587 // Do not send welcome email if option not enabled.
5588 if ( $should_email_new_approved_users !== '1' ) {
5589 return false;
5590 }
5591
5592 // Make sure we didn't just email this user (can happen with
5593 // multiple admins saving at the same time, or by clicking
5594 // Approve button too rapidly).
5595 $recently_sent_emails = get_option( 'auth_settings_recently_sent_emails' );
5596 if ( $recently_sent_emails === FALSE ) {
5597 $recently_sent_emails = array();
5598 }
5599 foreach ( $recently_sent_emails as $key => $recently_sent_email ) {
5600 if ( $recently_sent_email['time'] < strtotime( 'now -1 minutes' ) ) {
5601 // Remove emails sent more than 1 minute ago.
5602 unset( $recently_sent_emails[$key] );
5603 } elseif ( $recently_sent_email['email'] === $email ) {
5604 // Sent an email to this user within the last 1 minute, so
5605 // quit without sending.
5606 return false;
5607 }
5608 }
5609 // Add the email we're about to send to the list.
5610 $recently_sent_emails[] = array(
5611 'email' => $email,
5612 'time' => time(),
5613 );
5614 update_option( 'auth_settings_recently_sent_emails', $recently_sent_emails );
5615
5616 // Get welcome email subject and body text
5617 $subject = $this->get_plugin_option( 'access_email_approved_users_subject' );
5618 $body = apply_filters( 'the_content', $this->get_plugin_option( 'access_email_approved_users_body' ) );
5619
5620 // Fail if the subject/body options don't exist or are empty.
5621 if ( is_null( $subject ) || is_null( $body ) || strlen( $subject ) === 0 || strlen( $body ) === 0 ) {
5622 return false;
5623 }
5624
5625 // Replace approved shortcode patterns in subject and body.
5626 $site_name = get_bloginfo( 'name' );
5627 $site_url = get_site_url();
5628 $subject = str_replace( '[site_name]', $site_name, $subject );
5629 $body = str_replace( '[site_name]', $site_name, $body );
5630 $body = str_replace( '[site_url]', $site_url, $body );
5631 $body = str_replace( '[user_email]', $email, $body );
5632 $headers = 'Content-type: text/html' . "\r\n";
5633
5634 // Send email.
5635 wp_mail( $email, $subject, $body, $headers );
5636
5637 // Indicate mail was sent.
5638 return true;
5639 }
5640
5641
5642 /**
5643 * Generate a unique cookie to add to nonces to prevent CSRF.
5644 */
5645 protected $cookie_value = null;
5646 function get_cookie_value() {
5647 if ( ! $this->cookie_value ) {
5648 if ( isset( $_COOKIE['login_unique'] ) ) {
5649 $this->cookie_value = $_COOKIE['login_unique'];
5650 } else {
5651 $this->cookie_value = md5( rand() );
5652 setcookie( 'login_unique', $this->cookie_value, time()+1800, '/', defined( 'COOKIE_DOMAIN' ) ? COOKIE_DOMAIN : '' );
5653 }
5654 }
5655 return $this->cookie_value;
5656 }
5657
5658
5659 /**
5660 * Basic encryption using a public (not secret!) key. Used for general
5661 * database obfuscation of passwords.
5662 * @param $text String to encrypt.
5663 * @param $library Encryption lib to use (openssl).
5664 * @return Encrypted string
5665 */
5666 private static $key = "8QxnrvjdtweisvCBKEY!+0\0\0";
5667 private static $iv = "R_O2D]jPn]1[fhJl!-P1.oe";
5668 function encrypt( $text, $library = 'openssl' ) {
5669 $result = '';
5670
5671 // Use openssl library (better) if it is enabled.
5672 if ( function_exists( 'openssl_encrypt' ) && $library === 'openssl' ) {
5673 $result = base64_encode( openssl_encrypt(
5674 $text,
5675 'AES-256-CBC',
5676 hash( 'sha256', self::$key ),
5677 0,
5678 substr( hash( 'sha256', self::$iv ), 0, 16 )
5679 ) );
5680 // Use mcrypt library (deprecated in PHP 7.1) if php5-mcrypt extension is enabled.
5681 } else if ( function_exists( 'mcrypt_encrypt' ) ) {
5682 $result = base64_encode( mcrypt_encrypt( MCRYPT_RIJNDAEL_256, self::$key, $text, MCRYPT_MODE_ECB, 'abcdefghijklmnopqrstuvwxyz012345' ) );
5683 // Fall back to basic obfuscation.
5684 } else {
5685 for ( $i = 0; $i < strlen( $text ); $i++ ) {
5686 $char = substr( $text, $i, 1 );
5687 $keychar = substr( self::$key, ( $i % strlen( self::$key ) ) - 1, 1 );
5688 $char = chr( ord( $char ) + ord( $keychar ) );
5689 $result .= $char;
5690 }
5691 $result = base64_encode( $result );
5692 }
5693
5694 return $result;
5695 }
5696
5697
5698 /**
5699 * Basic decryption using a public (not secret!) key. Used for general
5700 * database obfuscation of passwords.
5701 * @param $text String to encrypt.
5702 * @param $library Encryption lib to use (openssl).
5703 * @return Decrypted string
5704 */
5705 function decrypt( $secret, $library = 'openssl' ) {
5706 $result = '';
5707
5708 // Use openssl library (better) if it is enabled.
5709 if ( function_exists( 'openssl_decrypt' ) && $library === 'openssl' ) {
5710 $result = openssl_decrypt(
5711 base64_decode( $secret ),
5712 'AES-256-CBC',
5713 hash( 'sha256', self::$key ),
5714 0,
5715 substr( hash( 'sha256', self::$iv ), 0, 16 )
5716 );
5717 // Use mcrypt library (deprecated in PHP 7.1) if php5-mcrypt extension is enabled.
5718 } else if ( function_exists( 'mcrypt_decrypt' ) ) {
5719 $secret = base64_decode( $secret );
5720 $result = rtrim( mcrypt_decrypt( MCRYPT_RIJNDAEL_256, self::$key, $secret, MCRYPT_MODE_ECB, 'abcdefghijklmnopqrstuvwxyz012345' ), "\0$result" );
5721 // Fall back to basic obfuscation.
5722 } else {
5723 $secret = base64_decode( $secret );
5724 for ( $i = 0; $i < strlen( $secret ); $i++ ) {
5725 $char = substr( $secret, $i, 1 );
5726 $keychar = substr( self::$key, ( $i % strlen( self::$key ) ) - 1, 1 );
5727 $char = chr( ord( $char ) - ord( $keychar ) );
5728 $result .= $char;
5729 }
5730 }
5731
5732 return $result;
5733 }
5734
5735
5736 /**
5737 * In a multisite environment, returns true if the current user is logged
5738 * in and a user of the current blog. In single site mode, simply returns
5739 * true if the current user is logged in.
5740 */
5741 function is_user_logged_in_and_blog_user() {
5742 $is_user_logged_in_and_blog_user = false;
5743 if ( is_multisite() ) {
5744 $is_user_logged_in_and_blog_user = is_user_logged_in() && is_user_member_of_blog( get_current_user_id() );
5745 } else {
5746 $is_user_logged_in_and_blog_user = is_user_logged_in();
5747 }
5748 return $is_user_logged_in_and_blog_user;
5749 }
5750
5751
5752 /**
5753 * Helper function to determine whether a given email is in one of
5754 * the lists (pending, approved, blocked). Defaults to the list of
5755 * approved users.
5756 */
5757 function is_email_in_list( $email = '', $list = 'approved', $multisite_mode = 'single' ) {
5758 if ( empty( $email ) )
5759 return false;
5760
5761 switch ( $list ) {
5762 case 'pending':
5763 $auth_settings_access_users_pending = $this->get_plugin_option( 'access_users_pending', SINGLE_ADMIN );
5764 return $this->in_multi_array( $email, $auth_settings_access_users_pending );
5765 break;
5766 case 'blocked':
5767 $auth_settings_access_users_blocked = $this->get_plugin_option( 'access_users_blocked', SINGLE_ADMIN );
5768 return $this->in_multi_array( $email, $auth_settings_access_users_blocked );
5769 break;
5770 case 'approved':
5771 default:
5772 if ( $multisite_mode !== 'single' ) {
5773 // Get multisite users only.
5774 $auth_settings_access_users_approved = $this->get_plugin_option( 'access_users_approved', MULTISITE_ADMIN );
5775 } elseif ( is_multisite() && $this->get_plugin_option( 'advanced_override_multisite' ) == '1' ) {
5776 // This site has overridden any multisite settings, so only get its users.
5777 $auth_settings_access_users_approved = $this->get_plugin_option( 'access_users_approved', SINGLE_ADMIN );
5778 } else {
5779 // Get all site users and all multisite users.
5780 $auth_settings_access_users_approved = array_merge(
5781 $this->get_plugin_option( 'access_users_approved', SINGLE_ADMIN ),
5782 $this->get_plugin_option( 'access_users_approved', MULTISITE_ADMIN )
5783 );
5784 }
5785 return $this->in_multi_array( $email, $auth_settings_access_users_approved );
5786 break;
5787 }
5788 }
5789
5790
5791 /**
5792 * Helper function to get number of users (including multisite users)
5793 * in a given list (pending, approved, or blocked).
5794 * @param string $list
5795 * @param string $admin_mode SINGLE_ADMIN or MULTISITE_ADMIN determines whether to include multisite users
5796 * @return int number of users in list
5797 */
5798 function get_user_count_from_list( $list, $admin_mode = SINGLE_ADMIN ) {
5799 $auth_settings_access_users = array();
5800
5801 switch ( $list ) {
5802 case 'pending':
5803 $auth_settings_access_users = $this->get_plugin_option( 'access_users_pending', SINGLE_ADMIN );
5804 break;
5805 case 'blocked':
5806 $auth_settings_access_users = $this->get_plugin_option( 'access_users_blocked', SINGLE_ADMIN );
5807 break;
5808 case 'approved':
5809 if ( $admin_mode !== SINGLE_ADMIN ) {
5810 // Get multisite users only.
5811 $auth_settings_access_users = $this->get_plugin_option( 'access_users_approved', MULTISITE_ADMIN );
5812 } elseif ( is_multisite() && $this->get_plugin_option( 'advanced_override_multisite' ) == '1' ) {
5813 // This site has overridden any multisite settings, so only get its users.
5814 $auth_settings_access_users = $this->get_plugin_option( 'access_users_approved', SINGLE_ADMIN );
5815 } else {
5816 // Get all site users and all multisite users.
5817 $auth_settings_access_users = array_merge(
5818 $this->get_plugin_option( 'access_users_approved', SINGLE_ADMIN ),
5819 $this->get_plugin_option( 'access_users_approved', MULTISITE_ADMIN )
5820 );
5821 }
5822 }
5823
5824 return count( $auth_settings_access_users );
5825 }
5826
5827
5828 /**
5829 * Helper function to search a multidimensional array for a value.
5830 */
5831 function in_multi_array( $needle = '', $haystack = array(), $strict_mode = 'not strict', $case_sensitivity = 'case insensitive' ) {
5832 if ( ! is_array( $haystack ) ) {
5833 return false;
5834 }
5835 if ( $case_sensitivity === 'case insensitive' ) {
5836 $needle = strtolower( $needle );
5837 }
5838 foreach ( $haystack as $item ) {
5839 if ( $case_sensitivity === 'case insensitive' && ! is_array( $item ) ) {
5840 $item = strtolower( $item );
5841 }
5842 if ( ( $strict_mode === 'strict' ? $item === $needle : $item == $needle ) || ( is_array( $item ) && $this->in_multi_array( $needle, $item, $strict_mode, $case_sensitivity ) ) ) {
5843 return true;
5844 }
5845 }
5846 return false;
5847 }
5848
5849
5850 /**
5851 * Helper function to determine if an URL is accessible.
5852 *
5853 * @param string $url URL that should be publicly reachable
5854 * @return boolean Whether the URL is publicly reachable
5855 */
5856 function url_is_accessible( $url ) {
5857 // Use wp_remote_retrieve_response_code() to retrieve the URL.
5858 $response = wp_remote_get( $url );
5859 $response_code = wp_remote_retrieve_response_code( $response );
5860
5861 // Return true if the document has loaded successfully without any redirection or error
5862 return $response_code >= 200 && $response_code < 400;
5863 }
5864
5865
5866 /**
5867 * Helper function to reconstruct a URL split using parse_url().
5868 * @param array $parts Array returned from parse_url().
5869 * @return string URL.
5870 */
5871 function build_url( $parts = array() ) {
5872 return
5873 ( isset( $parts['scheme'] ) ? "{$parts['scheme']}:" : '' ) .
5874 ( ( isset( $parts['user'] ) || isset( $parts['host'] ) ) ? '//' : '' ) .
5875 ( isset( $parts['user'] ) ? "{$parts['user']}" : '' ) .
5876 ( isset( $parts['pass'] ) ? ":{$parts['pass']}" : '' ) .
5877 ( isset( $parts['user'] ) ? '@' : '' ) .
5878 ( isset( $parts['host'] ) ? "{$parts['host']}" : '' ) .
5879 ( isset( $parts['port'] ) ? ":{$parts['port']}" : '' ) .
5880 ( isset( $parts['path'] ) ? "{$parts['path']}" : '' ) .
5881 ( isset( $parts['query'] ) ? "?{$parts['query']}" : '' ) .
5882 ( isset( $parts['fragment'] ) ? "#{$parts['fragment']}" : '' );
5883 }
5884
5885
5886 // Helper function that builds option tags for a select element for all
5887 // roles the current user has permission to assign.
5888 function wp_dropdown_permitted_roles( $selected_role = 'subscriber', $disable_input = 'not disabled', $admin_mode = SINGLE_ADMIN ) {
5889 $roles = get_editable_roles();
5890 $current_user = wp_get_current_user();
5891
5892 // If we're in network admin, also show any roles that might exist only on
5893 // specific sites in the network (themes can add their own roles).
5894 if ( $admin_mode === MULTISITE_ADMIN ) {
5895 $sites = function_exists( 'get_sites' ) ? get_sites() : wp_get_sites( array( 'limit' => PHP_INT_MAX ) );
5896 foreach ( $sites as $site ) {
5897 $blog_id = function_exists( 'get_sites' ) ? $site->blog_id : $site['blog_id'];
5898 switch_to_blog( $blog_id );
5899 $roles = array_merge( $roles, get_editable_roles() );
5900 restore_current_blog();
5901 }
5902 $unique_role_names = array();
5903 foreach ( $roles as $role_name => $role_info ) {
5904 if ( array_key_exists( $role_name, $unique_role_names ) ) {
5905 unset( $roles[$role_name] );
5906 } else {
5907 $unique_role_names[$role_name] = true;
5908 }
5909 }
5910 }
5911
5912 // If the currently selected role exists, but is not in the list of roles,
5913 // the current user is not permitted to assign it. Assume they can't edit
5914 // that user's role at all. Return only the one role for the dropdown list.
5915 if ( strlen( $selected_role ) > 0 && ! array_key_exists( $selected_role, $roles ) && ! is_null( get_role( $selected_role ) ) ) {
5916 return;
5917 }
5918
5919 // Print an option element for each permitted role.
5920 foreach ( $roles as $name => $role ) {
5921 $selected = $selected_role === $name ? ' selected="selected"' : '';
5922
5923 // Don't let a user change their own role
5924 $disabled = $selected_role !== $name && $disable_input === 'disabled' ? ' disabled="disabled"' : '';
5925
5926 // But network admins can always change their role.
5927 if ( is_multisite() && current_user_can( 'manage_network' ) ) {
5928 $disabled = '';
5929 }
5930
5931 ?><option value="<?php echo $name; ?>"<?php echo $selected . $disabled; ?>><?php echo $role['name']; ?></option><?php
5932 }
5933
5934 // Print default role (no role).
5935 $selected = strlen( $selected_role ) == 0 || ! array_key_exists( $selected_role, $roles ) ? ' selected="selected"' : '';
5936 $disabled = strlen( $selected_role ) > 0 && $disable_input === 'disabled' ? ' disabled="disabled"' : '';
5937 if ( is_multisite() && current_user_can( 'manage_network' ) ) {
5938 $disabled = '';
5939 }
5940 ?><option value=""<?php echo $selected . $disabled; ?>><?php _e( '&mdash; No role for this site &mdash;', 'authorizer' ); ?></option><?php
5941
5942 }
5943
5944
5945 // Helper function to get a single user info array from one of the
5946 // access control lists (pending, approved, or blocked).
5947 // Returns: false if not found; otherwise
5948 // array( 'email' => '', 'role' => '', 'date_added' => '', ['usermeta' => [''|array()]] );
5949 function get_user_info_from_list( $email, $list ) {
5950 foreach ( $list as $user_info ) {
5951 if ( 0 === strcasecmp( $user_info['email'], $email ) ) {
5952 return $user_info;
5953 }
5954 }
5955 return false;
5956 }
5957
5958
5959 // Helper function to convert seconds to human readable text.
5960 // Source: http://csl.name/php-secs-to-human-text/
5961 function seconds_as_sentence( $secs ) {
5962 $units = array(
5963 "week" => 7 * 24 * 3600,
5964 "day" => 24 * 3600,
5965 "hour" => 3600,
5966 "minute" => 60,
5967 "second" => 1,
5968 );
5969
5970 // specifically handle zero
5971 if ( $secs == 0 ) return "0 seconds";
5972
5973 $s = "";
5974
5975 foreach ( $units as $name => $divisor ) {
5976 if ( $quot = intval( $secs / $divisor ) ) {
5977 $s .= "$quot $name";
5978 $s .= ( abs( $quot ) > 1 ? "s" : "" ) . ", ";
5979 $secs -= $quot * $divisor;
5980 }
5981 }
5982
5983 return substr( $s, 0, -2 );
5984 }
5985
5986 // Helper function to get all available usermeta keys as an array.
5987 function get_all_usermeta_keys() {
5988 global $wpdb;
5989 $usermeta_keys = $wpdb->get_col( "SELECT DISTINCT $wpdb->usermeta.meta_key FROM $wpdb->usermeta" );
5990 return $usermeta_keys;
5991 }
5992
5993
5994 /**
5995 * Load translated strings from *.mo files in /languages.
5996 */
5997 function load_textdomain() {
5998 load_plugin_textdomain(
5999 'authorizer',
6000 false,
6001 plugin_basename( dirname( __FILE__ ) ) . '/languages'
6002 );
6003 }
6004
6005
6006 /**
6007 * Generate CAS authentication URL (wp-login.php URL with reauth=1 removed
6008 * and external=cas added).
6009 */
6010 function modify_current_url_for_cas_login() {
6011 // Construct the URL of the current page (wp-login.php).
6012 $url = 'http' . ( isset( $_SERVER['HTTPS'] ) ? 's' : '' ) . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
6013
6014 // Parse the URL into its components.
6015 $parsed_url = parse_url( $url );
6016
6017 // Fix up the querystring values (remove reauth, make sure external=cas).
6018 $querystring = array();
6019 if ( array_key_exists( 'query', $parsed_url ) ) {
6020 parse_str( $parsed_url['query'], $querystring );
6021 }
6022 unset( $querystring['reauth'] );
6023 $querystring['external'] = 'cas';
6024 $parsed_url['query'] = http_build_query( $querystring );
6025
6026 // Return the URL as a string.
6027 return $this->unparse_url( $parsed_url );
6028 }
6029
6030
6031 /**
6032 * Reconstruct a URL after it has been deconstructed with parse_url().
6033 * @param $parsed_url array() with keys from parse_url().
6034 * @return string URL constructed from the components in $parsed_url.
6035 */
6036 function unparse_url( $parsed_url = array() ) {
6037 $scheme = isset( $parsed_url['scheme'] ) ? $parsed_url['scheme'] . '://' : '';
6038 $host = isset( $parsed_url['host'] ) ? $parsed_url['host'] : '';
6039 $port = isset( $parsed_url['port'] ) ? ':' . $parsed_url['port'] : '';
6040 $user = isset( $parsed_url['user'] ) ? $parsed_url['user'] : '';
6041 $pass = isset( $parsed_url['pass'] ) ? ':' . $parsed_url['pass'] : '';
6042 $pass = $user || $pass ? "$pass@" : '';
6043 $path = isset( $parsed_url['path'] ) ? $parsed_url['path'] : '';
6044 $query = isset( $parsed_url['query'] ) ? '?' . $parsed_url['query'] : '';
6045 $fragment = isset( $parsed_url['fragment'] ) ? '#' . $parsed_url['fragment'] : '';
6046 return "$scheme$user$pass$host$port$path$query$fragment";
6047 }
6048
6049
6050 /**
6051 * Plugin Update Routines.
6052 */
6053 function auth_update_check() {
6054 // Get current version.
6055 $needs_updating = false;
6056 if ( is_multisite() ) {
6057 $auth_version = get_blog_option( BLOG_ID_CURRENT_SITE, 'auth_version' );
6058 } else {
6059 $auth_version = get_option( 'auth_version' );
6060 }
6061
6062 // Update: migrate user lists to own options (addresses concurrency
6063 // when saving plugin options, since user lists are changed often
6064 // and we don't want to overwrite changes to the lists when an
6065 // admin saves all of the plugin options.)
6066 // Note: Pending user list is changed whenever a new user tries to
6067 // log in; approved and blocked lists are changed whenever an admin
6068 // changes them from the multisite panel, the dashboard widget, or
6069 // the plugin options page.
6070 $update_if_older_than = 20140709;
6071 if ( $auth_version === false || intval( $auth_version ) < $update_if_older_than ) {
6072 // Copy single site user lists to new options (if they exist).
6073 $auth_settings = get_option( 'auth_settings' );
6074 if ( is_array( $auth_settings ) && array_key_exists( 'access_users_pending', $auth_settings ) ) {
6075 update_option( 'auth_settings_access_users_pending', $auth_settings['access_users_pending'] );
6076 unset( $auth_settings['access_users_pending'] );
6077 update_option( 'auth_settings', $auth_settings );
6078 }
6079 if ( is_array( $auth_settings ) && array_key_exists( 'access_users_approved', $auth_settings ) ) {
6080 update_option( 'auth_settings_access_users_approved', $auth_settings['access_users_approved'] );
6081 unset( $auth_settings['access_users_approved'] );
6082 update_option( 'auth_settings', $auth_settings );
6083 }
6084 if ( is_array( $auth_settings ) && array_key_exists( 'access_users_blocked', $auth_settings ) ) {
6085 update_option( 'auth_settings_access_users_blocked', $auth_settings['access_users_blocked'] );
6086 unset( $auth_settings['access_users_blocked'] );
6087 update_option( 'auth_settings', $auth_settings );
6088 }
6089 // Copy multisite user lists to new options (if they exist).
6090 if ( is_multisite() ) {
6091 $auth_multisite_settings = get_blog_option( BLOG_ID_CURRENT_SITE, 'auth_multisite_settings', array() );
6092 if ( is_array( $auth_multisite_settings ) && array_key_exists( 'access_users_pending', $auth_multisite_settings ) ) {
6093 update_blog_option( BLOG_ID_CURRENT_SITE, 'auth_multisite_settings_access_users_pending', $auth_multisite_settings['access_users_pending'] );
6094 unset( $auth_multisite_settings['access_users_pending'] );
6095 update_blog_option( BLOG_ID_CURRENT_SITE, 'auth_multisite_settings', $auth_multisite_settings );
6096 }
6097 if ( is_array( $auth_multisite_settings ) && array_key_exists( 'access_users_approved', $auth_multisite_settings ) ) {
6098 update_blog_option( BLOG_ID_CURRENT_SITE, 'auth_multisite_settings_access_users_approved', $auth_multisite_settings['access_users_approved'] );
6099 unset( $auth_multisite_settings['access_users_approved'] );
6100 update_blog_option( BLOG_ID_CURRENT_SITE, 'auth_multisite_settings', $auth_multisite_settings );
6101 }
6102 if ( is_array( $auth_multisite_settings ) && array_key_exists( 'access_users_blocked', $auth_multisite_settings ) ) {
6103 update_blog_option( BLOG_ID_CURRENT_SITE, 'auth_multisite_settings_access_users_blocked', $auth_multisite_settings['access_users_blocked'] );
6104 unset( $auth_multisite_settings['access_users_blocked'] );
6105 update_blog_option( BLOG_ID_CURRENT_SITE, 'auth_multisite_settings', $auth_multisite_settings );
6106 }
6107 }
6108 // Update version to reflect this change has been made.
6109 $auth_version = $update_if_older_than;
6110 $needs_updating = true;
6111 }
6112
6113 // Update: Set default values for newly added options (forgot to do
6114 // this, so some users are getting debug log notices about undefined
6115 // indexes in $auth_settings).
6116 $update_if_older_than = 20160831;
6117 if ( $auth_version === false || intval( $auth_version ) < $update_if_older_than ) {
6118 // Provide default values for any $auth_settings options that don't exist.
6119 if ( is_multisite() ) {
6120 // Get all blog ids
6121 $sites = function_exists( 'get_sites' ) ? get_sites() : wp_get_sites( array( 'limit' => PHP_INT_MAX ) );
6122 foreach ( $sites as $site ) {
6123 $blog_id = function_exists( 'get_sites' ) ? $site->blog_id : $site['blog_id'];
6124 switch_to_blog( $blog_id );
6125 // Set meaningful defaults for other sites in the network.
6126 $this->set_default_options();
6127 // Switch back to original blog. See: https://codex.wordpress.org/Function_Reference/restore_current_blog
6128 restore_current_blog();
6129 }
6130 } else {
6131 // Set meaningful defaults for this site.
6132 $this->set_default_options();
6133 }
6134 // Update version to reflect this change has been made.
6135 $auth_version = $update_if_older_than;
6136 $needs_updating = true;
6137 }
6138
6139 // Update: Migrate LDAP passwords encrypted with mcrypt since mcrypt is
6140 // deprecated as of PHP 7.1. Use openssl library instead.
6141 $update_if_older_than = 20170510;
6142 if ( $auth_version === false || intval( $auth_version ) < $update_if_older_than ) {
6143 if ( is_multisite() ) {
6144 // Reencrypt LDAP passwords in each site in the network.
6145 $sites = function_exists( 'get_sites' ) ? get_sites() : wp_get_sites( array( 'limit' => PHP_INT_MAX ) );
6146 foreach ( $sites as $site ) {
6147 $blog_id = function_exists( 'get_sites' ) ? $site->blog_id : $site['blog_id'];
6148 $auth_settings = get_blog_option( $blog_id, 'auth_settings', array() );
6149 if ( array_key_exists( 'ldap_password', $auth_settings ) && strlen( $auth_settings['ldap_password'] ) > 0 ) {
6150 $plaintext_ldap_password = $this->decrypt( $auth_settings['ldap_password'], 'mcrypt' );
6151 $auth_settings['ldap_password'] = $this->encrypt( $plaintext_ldap_password );
6152 update_blog_option( $blog_id, 'auth_settings', $auth_settings );
6153 }
6154 }
6155 } else {
6156 // Reencrypt LDAP password on this single-site install.
6157 $auth_settings = get_option( 'auth_settings', array() );
6158 if ( array_key_exists( 'ldap_password', $auth_settings ) && strlen( $auth_settings['ldap_password'] ) > 0 ) {
6159 $plaintext_ldap_password = $this->decrypt( $auth_settings['ldap_password'], 'mcrypt' );
6160 $auth_settings['ldap_password'] = $this->encrypt( $plaintext_ldap_password );
6161 update_option( 'auth_settings', $auth_settings );
6162 }
6163 }
6164 // Update version to reflect this change has been made.
6165 $auth_version = $update_if_older_than;
6166 $needs_updating = true;
6167 }
6168
6169 // Update: Migrate LDAP passwords encrypted with mcrypt since mcrypt is
6170 // deprecated as of PHP 7.1. Use openssl library instead.
6171 // Note: Forgot to update the auth_multisite_settings ldap password! Do it here.
6172 $update_if_older_than = 20170511;
6173 if ( $auth_version === false || intval( $auth_version ) < $update_if_older_than ) {
6174 if ( is_multisite() ) {
6175 // Reencrypt LDAP password in network (multisite) options.
6176 $auth_multisite_settings = get_blog_option( BLOG_ID_CURRENT_SITE, 'auth_multisite_settings', array() );
6177 if ( array_key_exists( 'ldap_password', $auth_multisite_settings ) && strlen( $auth_multisite_settings['ldap_password'] ) > 0 ) {
6178 $plaintext_ldap_password = $this->decrypt( $auth_multisite_settings['ldap_password'], 'mcrypt' );
6179 $auth_multisite_settings['ldap_password'] = $this->encrypt( $plaintext_ldap_password );
6180 update_blog_option( BLOG_ID_CURRENT_SITE, 'auth_multisite_settings', $auth_multisite_settings );
6181 }
6182 }
6183 // Update version to reflect this change has been made.
6184 $auth_version = $update_if_older_than;
6185 $needs_updating = true;
6186 }
6187
6188 // Update: Remove duplicates from approved list caused by authorizer_automatically_approve_login
6189 // filter not respecting users who are already in the approved list
6190 // (causing them to get re-added each time they logged in).
6191 $update_if_older_than = 20170711;
6192 if ( $auth_version === false || intval( $auth_version ) < $update_if_older_than ) {
6193 // Remove duplicates from approved user lists.
6194 if ( is_multisite() ) {
6195 // Remove duplicates from each site in the multisite
6196 $sites = function_exists( 'get_sites' ) ? get_sites() : wp_get_sites( array( 'limit' => PHP_INT_MAX ) );
6197 foreach ( $sites as $site ) {
6198 $blog_id = function_exists( 'get_sites' ) ? $site->blog_id : $site['blog_id'];
6199 $auth_settings_access_users_approved = get_blog_option( $blog_id, 'auth_settings_access_users_approved', array() );
6200 if ( is_array( $auth_settings_access_users_approved ) ) {
6201 $should_update = false;
6202 $distinct_emails = array();
6203 foreach ( $auth_settings_access_users_approved as $key => $user ) {
6204 if ( in_array( $user['email'], $distinct_emails ) ) {
6205 $should_update = true;
6206 unset( $auth_settings_access_users_approved[$key] );
6207 } else {
6208 $distinct_emails[] = $user['email'];
6209 }
6210 }
6211 if ( $should_update ) {
6212 update_blog_option( $blog_id, 'auth_settings_access_users_approved', $auth_settings_access_users_approved );
6213 }
6214 }
6215 }
6216 // Remove duplicates from multisite approved user list.
6217 $auth_multisite_settings_access_users_approved = get_blog_option( BLOG_ID_CURRENT_SITE, 'auth_multisite_settings_access_users_approved', array() );
6218 if ( is_array( $auth_multisite_settings_access_users_approved ) ) {
6219 $should_update = false;
6220 $distinct_emails = array();
6221 foreach ( $auth_multisite_settings_access_users_approved as $key => $user ) {
6222 if ( in_array( $user['email'], $distinct_emails ) ) {
6223 $should_update = true;
6224 unset( $auth_multisite_settings_access_users_approved[$key] );
6225 } else {
6226 $distinct_emails[] = $user['email'];
6227 }
6228 }
6229 if ( $should_update ) {
6230 update_blog_option( BLOG_ID_CURRENT_SITE, 'auth_multisite_settings_access_users_approved', $auth_multisite_settings_access_users_approved );
6231 }
6232 }
6233 } else {
6234 // Remove duplicates from single site approved user list.
6235 $auth_settings_access_users_approved = get_option( 'auth_settings_access_users_approved' );
6236 if ( is_array( $auth_settings_access_users_approved ) ) {
6237 $should_update = false;
6238 $distinct_emails = array();
6239 foreach ( $auth_settings_access_users_approved as $key => $user ) {
6240 if ( in_array( $user['email'], $distinct_emails ) ) {
6241 $should_update = true;
6242 unset( $auth_settings_access_users_approved[$key] );
6243 } else {
6244 $distinct_emails[] = $user['email'];
6245 }
6246 }
6247 if ( $should_update ) {
6248 update_option( 'auth_settings_access_users_approved', $auth_settings_access_users_approved );
6249 }
6250 }
6251 }
6252 // Update version to reflect this change has been made.
6253 $auth_version = $update_if_older_than;
6254 $needs_updating = true;
6255 }
6256
6257 // // Update: TEMPLATE
6258 // $update_if_older_than = YYYYMMDD;
6259 // if ( $auth_version === false || intval( $auth_version ) < $update_if_older_than ) {
6260 // UPDATE CODE HERE
6261 // // Update version to reflect this change has been made.
6262 // $auth_version = $update_if_older_than;
6263 // $needs_updating = true;
6264 // }
6265
6266 // Save new version number if we performed any updates.
6267 if ( $needs_updating ) {
6268 if ( is_multisite() ) {
6269 $sites = function_exists( 'get_sites' ) ? get_sites() : wp_get_sites( array( 'limit' => PHP_INT_MAX ) );
6270 foreach ( $sites as $site ) {
6271 $blog_id = function_exists( 'get_sites' ) ? $site->blog_id : $site['blog_id'];
6272 update_blog_option( $blog_id, 'auth_version', $auth_version );
6273 }
6274 } else {
6275 update_option( 'auth_version', $auth_version );
6276 }
6277 }
6278 }
6279
6280 }
6281 }
6282
6283 // Instantiate the plugin class.
6284 $wp_plugin_authorizer = new WP_Plugin_Authorizer();
6285