PluginProbe
Authorizer / 2.6.23
Authorizer v2.6.23
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.23, at authorizer.php

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