PluginProbe
Authorizer / 2.6.21
Authorizer v2.6.21
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.21, at authorizer.php

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