PluginProbe
Authorizer / 2.9.11
Authorizer v2.9.11
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 / src / authorizer / class-authorization.php

class-authorization.php in Authorizer 2.9.11, at src/authorizer/class-authorization.php

691 lines 30.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Authorizer
4 *
5 * @license GPL-2.0+
6 * @link https://github.com/uhm-coe/authorizer
7 * @package authorizer
8 */
9
10 namespace Authorizer;
11
12 use Authorizer\Helper;
13 use Authorizer\Options;
14
15 /**
16 * Implements the authorization (roles and permissions) features of the plugin.
17 */
18 class Authorization extends Static_Instance {
19
20 /**
21 * This function will fail with a wp_die() message to the user if they
22 * don't have access.
23 *
24 * @param WP_User $user User to check.
25 * @param array $user_emails Array of user's plaintext emails (in case current user doesn't have a WP account).
26 * @param array $user_data Array of keys for email, username, first_name, last_name,
27 * authenticated_by, google_attributes, cas_attributes, ldap_attributes.
28 * @return WP_Error|WP_User
29 * WP_Error if there was an error on user creation / adding user to blog.
30 * WP_Error / wp_die() if user does not have access.
31 * WP_User if user has access.
32 */
33 public function check_user_access( $user, $user_emails, $user_data = array() ) {
34 // Grab plugin settings.
35 $options = Options::get_instance();
36 $auth_settings = $options->get_all( Helper::SINGLE_CONTEXT, 'allow override' );
37 $auth_settings_access_users_pending = $options->sanitize_user_list(
38 $options->get( 'access_users_pending', Helper::SINGLE_CONTEXT )
39 );
40 $auth_settings_access_users_approved_single = $options->get( 'access_users_approved', Helper::SINGLE_CONTEXT );
41 $auth_settings_access_users_approved_multi = $options->get( 'access_users_approved', Helper::NETWORK_CONTEXT );
42 $auth_settings_access_users_approved = $options->sanitize_user_list(
43 array_merge(
44 $auth_settings_access_users_approved_single,
45 $auth_settings_access_users_approved_multi
46 )
47 );
48
49 /**
50 * Filter whether to block the currently logging in user based on any of
51 * their user attributes.
52 *
53 * @param bool $allow_login Whether to block the currently logging in user.
54 * @param array $user_data User data returned from external service.
55 */
56 $allow_login = apply_filters( 'authorizer_allow_login', true, $user_data );
57 $blocked_by_filter = ! $allow_login; // Use this for better readability.
58
59 // Check our externally authenticated user against the block list.
60 // If any of their email addresses are blocked, set the relevant user
61 // meta field, and show them an error screen.
62 foreach ( $user_emails as $user_email ) {
63 if ( $blocked_by_filter || $this->is_email_in_list( $user_email, 'blocked' ) ) {
64
65 // Add user to blocked list if it was blocked via the filter.
66 if ( $blocked_by_filter && ! $this->is_email_in_list( $user_email, 'blocked' ) ) {
67 $auth_settings_access_users_blocked = $options->sanitize_user_list(
68 $options->get( 'access_users_blocked', Helper::SINGLE_CONTEXT )
69 );
70 array_push(
71 $auth_settings_access_users_blocked,
72 array(
73 'email' => Helper::lowercase( $user_email ),
74 'date_added' => date( 'M Y' ),
75 )
76 );
77 update_option( 'auth_settings_access_users_blocked', $auth_settings_access_users_blocked );
78 }
79
80 // If the blocked external user has a WordPress account, mark it as
81 // blocked (enforce block in this->authenticate()).
82 if ( $user ) {
83 update_user_meta( $user->ID, 'auth_blocked', 'yes' );
84 }
85
86 // Notify user about blocked status and return without authenticating them.
87 // phpcs:ignore WordPress.Security.NonceVerification
88 $redirect_to = ! empty( $_REQUEST['redirect_to'] ) ? esc_url_raw( wp_unslash( $_REQUEST['redirect_to'] ) ) : home_url();
89 $page_title = sprintf(
90 /* TRANSLATORS: %s: Name of blog */
91 __( '%s - Access Restricted', 'authorizer' ),
92 get_bloginfo( 'name' )
93 );
94 $error_message =
95 apply_filters( 'the_content', $auth_settings['access_blocked_redirect_to_message'] ) .
96 '<hr />' .
97 '<p style="text-align: center;">' .
98 '<a class="button" href="' . wp_logout_url( $redirect_to ) . '">' .
99 __( 'Back', 'authorizer' ) .
100 '</a></p>';
101 update_option( 'auth_settings_advanced_login_error', $error_message );
102 wp_die( wp_kses( $error_message, Helper::$allowed_html ), esc_html( $page_title ) );
103 return new \WP_Error( 'invalid_login', __( 'Invalid login attempted.', 'authorizer' ) );
104 }
105 }
106
107 // Get the default role for this user (or their current role, if they
108 // already have an account).
109 $default_role = $user && is_array( $user->roles ) && count( $user->roles ) > 0 ? $user->roles[0] : $auth_settings['access_default_role'];
110 /**
111 * Filter the role of the user currently logging in. The role will be
112 * set to the default (specified in Authorizer options) for new users,
113 * or the user's current role for existing users. This filter allows
114 * changing user roles based on custom CAS/LDAP attributes.
115 *
116 * @param bool $role Role of the user currently logging in.
117 * @param array $user_data User data returned from external service.
118 */
119 $approved_role = apply_filters( 'authorizer_custom_role', $default_role, $user_data );
120
121 /**
122 * Filter whether to automatically approve the currently logging in user
123 * based on any of their user attributes.
124 *
125 * @param bool $automatically_approve_login
126 * Whether to automatically approve the currently logging in user.
127 * @param array $user_data User data returned from external service.
128 */
129 $automatically_approve_login = apply_filters( 'authorizer_automatically_approve_login', false, $user_data );
130
131 // Iterate through each of the email addresses provided by the external
132 // service and determine if any of them have access.
133 $last_email = end( $user_emails );
134 reset( $user_emails );
135 foreach ( $user_emails as $user_email ) {
136 $is_newly_approved_user = false;
137
138 // If this externally authenticated user is an existing administrator
139 // (administrator in single site mode, or super admin in network mode),
140 // and is not in the blocked list, let them in.
141 if ( $user && is_super_admin( $user->ID ) ) {
142 return $user;
143 }
144
145 // If this externally authenticated user isn't in the approved list
146 // and login access is set to "All authenticated users," or if they were
147 // automatically approved in the "authorizer_approve_login" filter
148 // above, then add them to the approved list (they'll get an account
149 // created below if they don't have one yet).
150 if (
151 ! $this->is_email_in_list( $user_email, 'approved' ) &&
152 ( 'external_users' === $auth_settings['access_who_can_login'] || $automatically_approve_login )
153 ) {
154 $is_newly_approved_user = true;
155
156 // If this user happens to be in the pending list (rare),
157 // remove them from pending before adding them to approved.
158 if ( $this->is_email_in_list( $user_email, 'pending' ) ) {
159 foreach ( $auth_settings_access_users_pending as $key => $pending_user ) {
160 if ( 0 === strcasecmp( $pending_user['email'], $user_email ) ) {
161 unset( $auth_settings_access_users_pending[ $key ] );
162 update_option( 'auth_settings_access_users_pending', $auth_settings_access_users_pending );
163 break;
164 }
165 }
166 }
167
168 // Add this user to the approved list.
169 $approved_user = array(
170 'email' => Helper::lowercase( $user_email ),
171 'role' => $approved_role,
172 'date_added' => date( 'Y-m-d H:i:s' ),
173 );
174 array_push( $auth_settings_access_users_approved, $approved_user );
175 array_push( $auth_settings_access_users_approved_single, $approved_user );
176 update_option( 'auth_settings_access_users_approved', $auth_settings_access_users_approved_single );
177 }
178
179 // Check our externally authenticated user against the approved
180 // list. If they are approved, log them in (and create their account
181 // if necessary).
182 if ( $is_newly_approved_user || $this->is_email_in_list( $user_email, 'approved' ) ) {
183 $user_info = $is_newly_approved_user ? $approved_user : Helper::get_user_info_from_list( $user_email, $auth_settings_access_users_approved );
184
185 // If this user's role was modified above (in the
186 // authorizer_custom_role filter), use that value instead of
187 // whatever is specified in the approved list.
188 if ( $default_role !== $approved_role ) {
189 $user_info['role'] = $approved_role;
190 }
191
192 // If the approved external user does not have a WordPress account, create it.
193 if ( ! $user ) {
194 if ( array_key_exists( 'username', $user_data ) ) {
195 $username = $user_data['username'];
196 } else {
197 $username = explode( '@', $user_info['email'] );
198 $username = $username[0];
199 }
200 // If there's already a user with this username (e.g.,
201 // johndoe/johndoe@gmail.com exists, and we're trying to add
202 // johndoe/johndoe@example.com), use the full email address
203 // as the username.
204 if ( get_user_by( 'login', $username ) !== false ) {
205 $username = $user_info['email'];
206 }
207 $result = wp_insert_user(
208 array(
209 'user_login' => strtolower( $username ),
210 'user_pass' => wp_generate_password(), // random password.
211 'first_name' => array_key_exists( 'first_name', $user_data ) ? $user_data['first_name'] : '',
212 'last_name' => array_key_exists( 'last_name', $user_data ) ? $user_data['last_name'] : '',
213 'user_email' => Helper::lowercase( $user_info['email'] ),
214 'user_registered' => date( 'Y-m-d H:i:s' ),
215 'role' => $user_info['role'],
216 )
217 );
218
219 // Fail with message if error.
220 if ( is_wp_error( $result ) || 0 === $result ) {
221 return $result;
222 }
223
224 // Authenticate as new user.
225 $user = new \WP_User( $result );
226
227 /**
228 * Fires after an external user is authenticated for the first time
229 * and a new WordPress account is created for them.
230 *
231 * @since 2.8.0
232 *
233 * @param WP_User $user User object.
234 * @param array $user_data User data from external service.
235 *
236 * Example $user_data:
237 * array(
238 * 'email' => 'user@example.edu',
239 * 'username' => 'user',
240 * 'first_name' => 'First',
241 * 'last_name' => 'Last',
242 * 'authenticated_by' => 'cas',
243 * 'cas_attributes' => array( ... ),
244 * );
245 */
246 do_action( 'authorizer_user_register', $user, $user_data );
247
248 // If multisite, iterate through all sites in the network and add the user
249 // currently logging in to any of them that have the user on the approved list.
250 // Note: this is useful for first-time logins--some users will have access
251 // to multiple sites, and this prevents them from having to log into each
252 // site individually to get access.
253 if ( is_multisite() ) {
254 $site_ids_of_user = array_map(
255 function ( $site_of_user ) {
256 return intval( $site_of_user->userblog_id );
257 },
258 get_blogs_of_user( $user->ID )
259 );
260
261 // phpcs:ignore WordPress.WP.DeprecatedFunctions.wp_get_sitesFound
262 $sites = function_exists( 'get_sites' ) ? get_sites() : wp_get_sites( array( 'limit' => PHP_INT_MAX ) );
263 foreach ( $sites as $site ) {
264 $blog_id = function_exists( 'get_sites' ) ? $site->blog_id : $site['blog_id'];
265
266 // Skip if user is already added to this site.
267 if ( in_array( intval( $blog_id ), $site_ids_of_user, true ) ) {
268 continue;
269 }
270
271 // Check if user is on the approved list of this site they are not added to.
272 $other_auth_settings_access_users_approved = get_blog_option( $blog_id, 'auth_settings_access_users_approved', array() );
273 if ( Helper::in_multi_array( $user->user_email, $other_auth_settings_access_users_approved ) ) {
274 $other_user_info = Helper::get_user_info_from_list( $user->user_email, $other_auth_settings_access_users_approved );
275 // Add user to other site.
276 add_user_to_blog( $blog_id, $user->ID, $other_user_info['role'] );
277 }
278 }
279 }
280
281 // Check if this new user has any preassigned usermeta
282 // values in their approved list entry, and apply them to
283 // their new WordPress account.
284 if ( array_key_exists( 'usermeta', $user_info ) && is_array( $user_info['usermeta'] ) ) {
285 $meta_key = $options->get( 'advanced_usermeta' );
286
287 if ( array_key_exists( 'meta_key', $user_info['usermeta'] ) && array_key_exists( 'meta_value', $user_info['usermeta'] ) ) {
288 // Only update the usermeta if the stored value matches
289 // the option set in authorizer settings (if they don't
290 // match it's probably old data).
291 if ( $meta_key === $user_info['usermeta']['meta_key'] ) {
292 // Update user's usermeta value for usermeta key stored in authorizer options.
293 if ( strpos( $meta_key, 'acf___' ) === 0 && class_exists( 'acf' ) ) {
294 // We have an ACF field value, so use the ACF function to update it.
295 update_field( str_replace( 'acf___', '', $meta_key ), $user_info['usermeta']['meta_value'], 'user_' . $user->ID );
296 } else {
297 // We have a normal usermeta value, so just update it via the WordPress function.
298 update_user_meta( $user->ID, $meta_key, $user_info['usermeta']['meta_value'] );
299 }
300 }
301 } elseif ( is_multisite() && count( $user_info['usermeta'] ) > 0 ) {
302 // Update usermeta for each multisite blog defined for this user.
303 foreach ( $user_info['usermeta'] as $blog_id => $usermeta ) {
304 if ( array_key_exists( 'meta_key', $usermeta ) && array_key_exists( 'meta_value', $usermeta ) ) {
305 // 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).
306 if ( ! is_user_member_of_blog( $user->ID, $blog_id ) ) {
307 add_user_to_blog( $blog_id, $user->ID, $user_info['role'] );
308 }
309 switch_to_blog( $blog_id );
310 // Update user's usermeta value for usermeta key stored in authorizer options.
311 if ( strpos( $meta_key, 'acf___' ) === 0 && class_exists( 'acf' ) ) {
312 // We have an ACF field value, so use the ACF function to update it.
313 update_field( str_replace( 'acf___', '', $meta_key ), $usermeta['meta_value'], 'user_' . $user->ID );
314 } else {
315 // We have a normal usermeta value, so just update it via the WordPress function.
316 update_user_meta( $user->ID, $meta_key, $usermeta['meta_value'] );
317 }
318 restore_current_blog();
319 }
320 }
321 }
322 }
323 } else {
324 // Update first/last names of WordPress user from external
325 // service if that option is set.
326 if ( ( array_key_exists( 'authenticated_by', $user_data ) && 'cas' === $user_data['authenticated_by'] && array_key_exists( 'cas_attr_update_on_login', $auth_settings ) && 1 === intval( $auth_settings['cas_attr_update_on_login'] ) ) || ( array_key_exists( 'authenticated_by', $user_data ) && 'ldap' === $user_data['authenticated_by'] && array_key_exists( 'ldap_attr_update_on_login', $auth_settings ) && 1 === intval( $auth_settings['ldap_attr_update_on_login'] ) ) ) {
327 if ( array_key_exists( 'first_name', $user_data ) && 0 < strlen( $user_data['first_name'] ) ) {
328 wp_update_user(
329 array(
330 'ID' => $user->ID,
331 'first_name' => $user_data['first_name'],
332 )
333 );
334 }
335 if ( array_key_exists( 'last_name', $user_data ) && strlen( $user_data['last_name'] ) > 0 ) {
336 wp_update_user(
337 array(
338 'ID' => $user->ID,
339 'last_name' => $user_data['last_name'],
340 )
341 );
342 }
343 }
344
345 // Update this user's role if it was modified in the
346 // authorizer_custom_role filter.
347 if ( $default_role !== $approved_role ) {
348 // Update user's role in WordPress.
349 $user->set_role( $approved_role );
350
351 // Update user's role in this site's approved list and save.
352 foreach ( $auth_settings_access_users_approved_single as $key => $existing_user ) {
353 if ( 0 === strcasecmp( $user->user_email, $existing_user['email'] ) ) {
354 $auth_settings_access_users_approved_single[ $key ]['role'] = $approved_role;
355 break;
356 }
357 }
358 update_option( 'auth_settings_access_users_approved', $auth_settings_access_users_approved_single );
359 }
360 }
361
362 // If this is multisite, add new user to current blog.
363 if ( is_multisite() && ! is_user_member_of_blog( $user->ID ) ) {
364 $result = add_user_to_blog( get_current_blog_id(), $user->ID, $user_info['role'] );
365
366 // Fail with message if error.
367 if ( is_wp_error( $result ) ) {
368 return $result;
369 }
370 }
371
372 // Ensure user has the same role as their entry in the approved list.
373 if ( $user_info && ! in_array( $user_info['role'], $user->roles, true ) ) {
374 $user->set_role( $user_info['role'] );
375 }
376
377 return $user;
378
379 } elseif ( 0 === strcasecmp( $user_email, $last_email ) ) {
380 /**
381 * Note: only do this for the last email address we are checking (we need
382 * to iterate through them all to make sure one of them isn't approved).
383 */
384
385 // User isn't an admin, is not blocked, and is not approved.
386 // Add them to the pending list and notify them and their instructor.
387 if ( strlen( $user_email ) > 0 && ! $this->is_email_in_list( $user_email, 'pending' ) ) {
388 $pending_user = array();
389 $pending_user['email'] = Helper::lowercase( $user_email );
390 $pending_user['role'] = $approved_role;
391 $pending_user['date_added'] = '';
392 array_push( $auth_settings_access_users_pending, $pending_user );
393 update_option( 'auth_settings_access_users_pending', $auth_settings_access_users_pending );
394
395 // Create strings used in the email notification.
396 $site_name = get_bloginfo( 'name' );
397 $site_url = get_bloginfo( 'url' );
398 $authorizer_options_url = 'settings' === $auth_settings['advanced_admin_menu'] ? admin_url( 'options-general.php?page=authorizer' ) : admin_url( '?page=authorizer' );
399
400 // Notify users with the role specified in "Which role should
401 // receive email notifications about pending users?".
402 if ( strlen( $auth_settings['access_role_receive_pending_emails'] ) > 0 ) {
403 foreach ( get_users( array( 'role' => $auth_settings['access_role_receive_pending_emails'] ) ) as $user_recipient ) {
404 wp_mail(
405 $user_recipient->user_email,
406 sprintf(
407 /* TRANSLATORS: 1: User email 2: Name of site */
408 __( 'Action required: Pending user %1$s at %2$s', 'authorizer' ),
409 $pending_user['email'],
410 $site_name
411 ),
412 sprintf(
413 /* TRANSLATORS: 1: Name of site 2: URL of site 3: URL of authorizer */
414 __( "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' ),
415 $site_name,
416 $site_url,
417 $authorizer_options_url
418 )
419 );
420 }
421 }
422 }
423
424 // Fetch the external service this user authenticated with, and append
425 // it to the logout URL below (so we can fire custom logout routines in
426 // custom_logout() based on their external service. This is necessary
427 // because a pending user does not have a WP_User, and thus no
428 // "authenticated_by" usermeta that is normally used to do this.
429 $external_param = isset($user_data['authenticated_by']) ? '&external=' . $user_data['authenticated_by'] : '';
430
431 // Notify user about pending status and return without authenticating them.
432 // phpcs:ignore WordPress.Security.NonceVerification
433 $redirect_to = ! empty( $_REQUEST['redirect_to'] ) ? esc_url_raw( wp_unslash( $_REQUEST['redirect_to'] ) ) : home_url();
434 $page_title = get_bloginfo( 'name' ) . ' - Access Pending';
435 $error_message =
436 apply_filters( 'the_content', $auth_settings['access_pending_redirect_to_message'] ) .
437 '<hr />' .
438 '<p style="text-align: center;">' .
439 '<a class="button" href="' . wp_logout_url( $redirect_to ) . $external_param . '">' .
440 __( 'Back', 'authorizer' ) .
441 '</a></p>';
442 update_option( 'auth_settings_advanced_login_error', $error_message );
443 wp_die( wp_kses( $error_message, Helper::$allowed_html ), esc_html( $page_title ) );
444 }
445 }
446
447 // Sanity check: if we made it here without returning, something has gone wrong.
448 return new \WP_Error( 'invalid_login', __( 'Invalid login attempted.', 'authorizer' ) );
449
450 }
451
452
453 /**
454 * Restrict access to WordPress site based on settings (everyone, logged_in_users).
455 *
456 * Action: parse_request
457 *
458 * @param array $wp WordPress object.
459 * @return WP|void WP object when passing through to WordPress authentication, or void.
460 */
461 public function restrict_access( $wp ) {
462 // Grab plugin settings.
463 $options = Options::get_instance();
464 $auth_settings = $options->get_all( Helper::SINGLE_CONTEXT, 'allow override' );
465
466 // Grab current user.
467 $current_user = wp_get_current_user();
468
469 $has_access = (
470 // Always allow access if WordPress is installing.
471 // phpcs:ignore WordPress.Security.NonceVerification
472 ( defined( 'WP_INSTALLING' ) && isset( $_GET['key'] ) ) ||
473 // Always allow access to admins.
474 ( current_user_can( 'create_users' ) ) ||
475 // Allow access if option is set to 'everyone'.
476 ( 'everyone' === $auth_settings['access_who_can_view'] ) ||
477 // Allow access to approved external users and logged in users if option is set to 'logged_in_users'.
478 ( 'logged_in_users' === $auth_settings['access_who_can_view'] && Helper::is_user_logged_in_and_blog_user() && $this->is_email_in_list( $current_user->user_email, 'approved' ) ) ||
479 // Allow access for requests to /wp-json/oauth1 so oauth clients can authenticate to use the REST API.
480 ( property_exists( $wp, 'matched_query' ) && stripos( $wp->matched_query, 'rest_oauth1=' ) === 0 ) ||
481 // Allow access for non-GET requests to /wp-json/*, since REST API authentication already covers them.
482 ( property_exists( $wp, 'matched_query' ) && 0 === stripos( $wp->matched_query, 'rest_route=' ) && isset( $_SERVER['REQUEST_METHOD'] ) && 'GET' !== $_SERVER['REQUEST_METHOD'] ) ||
483 // Allow access for GET requests to /wp-json/ (root), since REST API discovery calls rely on this.
484 ( property_exists( $wp, 'matched_query' ) && 'rest_route=/' === $wp->matched_query )
485 // Note that GET requests to a rest endpoint will be restricted by authorizer. In that case, error messages will be returned as JSON.
486 );
487
488 /**
489 * Developers can use the `authorizer_has_access` filter to override
490 * restricted access on certain pages. Note that the restriction checks
491 * happens before WordPress executes any queries, so use the $wp variable
492 * to investigate what the visitor is trying to load.
493 *
494 * For example, to unblock an RSS feed, place the following PHP code in
495 * the theme's functions.php file or in a simple plug-in:
496 *
497 * function my_feed_access_override( $has_access, $wp ) {
498 * // Check query variables to see if this is the feed.
499 * if ( ! empty( $wp->query_vars['feed'] ) ) {
500 * $has_access = true;
501 * }
502 *
503 * return $has_access;
504 * }
505 * add_filter( 'authorizer_has_access', 'my_feed_access_override', 10, 2 );
506 */
507 if ( apply_filters( 'authorizer_has_access', $has_access, $wp ) === true ) {
508 // Turn off the public notice about browsing anonymously.
509 update_option( 'auth_settings_advanced_public_notice', false );
510
511 // We've determined that the current user has access, so simply return to grant access.
512 return $wp;
513 }
514
515 // Allow HEAD requests to the root (usually discovery from a REST client).
516 if ( 'HEAD' === $_SERVER['REQUEST_METHOD'] && empty( $wp->request ) && empty( $wp->matched_query ) ) {
517 return $wp;
518 }
519
520 /* We've determined that the current user doesn't have access, so we deal with them now. */
521
522 // Fringe case: In a multisite, a user of a different blog can successfully
523 // log in, but they aren't on the 'approved' whitelist for this blog.
524 // If that's the case, add them to the pending list for this blog.
525 if ( is_multisite() && is_user_logged_in() && ! $has_access ) {
526 $current_user = wp_get_current_user();
527
528 // Check user access; block if not, add them to pending list if open, let them through otherwise.
529 $result = $this->check_user_access( $current_user, array( $current_user->user_email ) );
530 }
531
532 // Check to see if the requested page is public. If so, show it.
533 if ( empty( $wp->request ) ) {
534 $current_page_id = 'home';
535 } else {
536 $request_query = isset( $wp->query_vars ) ? new \WP_Query( $wp->query_vars ) : null;
537 $current_page_id = isset( $request_query->post_count ) && $request_query->post_count > 0 ? $request_query->post->ID : '';
538 }
539 if ( ! array_key_exists( 'access_public_pages', $auth_settings ) || ! is_array( $auth_settings['access_public_pages'] ) ) {
540 $auth_settings['access_public_pages'] = array();
541 }
542 if ( in_array( strval( $current_page_id ), $auth_settings['access_public_pages'], true ) ) {
543 if ( 'no_warning' === $auth_settings['access_public_warning'] ) {
544 update_option( 'auth_settings_advanced_public_notice', false );
545 } else {
546 update_option( 'auth_settings_advanced_public_notice', true );
547 }
548 return $wp;
549 }
550
551 // Check to see if any category assigned to the requested page is public. If so, show it.
552 $current_page_categories = wp_get_post_categories( $current_page_id, array( 'fields' => 'slugs' ) );
553 foreach ( $current_page_categories as $current_page_category ) {
554 if ( in_array( 'cat_' . $current_page_category, $auth_settings['access_public_pages'], true ) ) {
555 if ( 'no_warning' === $auth_settings['access_public_warning'] ) {
556 update_option( 'auth_settings_advanced_public_notice', false );
557 } else {
558 update_option( 'auth_settings_advanced_public_notice', true );
559 }
560 return $wp;
561 }
562 }
563
564 // Check to see if this page can't be found. If so, allow showing the 404 page.
565 if ( strlen( $current_page_id ) < 1 ) {
566 if ( in_array( 'auth_public_404', $auth_settings['access_public_pages'], true ) ) {
567 if ( 'no_warning' === $auth_settings['access_public_warning'] ) {
568 update_option( 'auth_settings_advanced_public_notice', false );
569 } else {
570 update_option( 'auth_settings_advanced_public_notice', true );
571 }
572 return $wp;
573 }
574 }
575
576 // Check to see if the requested category is public. If so, show it.
577 $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'] : '';
578 if ( $current_category_name ) {
579 $current_category_name = end( explode( '/', $current_category_name ) );
580 if ( in_array( 'cat_' . $current_category_name, $auth_settings['access_public_pages'], true ) ) {
581 if ( 'no_warning' === $auth_settings['access_public_warning'] ) {
582 update_option( 'auth_settings_advanced_public_notice', false );
583 } else {
584 update_option( 'auth_settings_advanced_public_notice', true );
585 }
586 return $wp;
587 }
588 }
589
590 // User is denied access, so show them the error message. Render as JSON
591 // if this is a REST API call; otherwise, show the error message via
592 // wp_die() (rendered html), or redirect to the login URL.
593 $current_path = ! empty( $_SERVER['REQUEST_URI'] ) ? esc_url_raw( wp_unslash( $_SERVER['REQUEST_URI'] ) ) : home_url();
594 if ( property_exists( $wp, 'matched_query' ) && stripos( $wp->matched_query, 'rest_route=' ) === 0 && 'GET' === $_SERVER['REQUEST_METHOD'] ) {
595 wp_send_json(
596 array(
597 'code' => 'rest_cannot_view',
598 'message' => wp_strip_all_tags( $auth_settings['access_redirect_to_message'] ),
599 'data' => array(
600 'status' => 401,
601 ),
602 )
603 );
604 } elseif ( 'message' === $auth_settings['access_redirect'] ) {
605 $page_title = sprintf(
606 /* TRANSLATORS: %s: Name of blog */
607 __( '%s - Access Restricted', 'authorizer' ),
608 get_bloginfo( 'name' )
609 );
610 $error_message =
611 apply_filters( 'the_content', $auth_settings['access_redirect_to_message'] ) .
612 '<hr />' .
613 '<p style="text-align: center;margin-bottom: -15px;">' .
614 '<a class="button" href="' . wp_login_url( $current_path ) . '">' .
615 __( 'Log In', 'authorizer' ) .
616 '</a></p>';
617 wp_die( wp_kses( $error_message, Helper::$allowed_html ), esc_html( $page_title ) );
618 } else {
619 wp_safe_redirect( wp_login_url( $current_path ), 302 );
620 exit;
621 }
622
623 // Sanity check: we should never get here.
624 wp_die( '<p>Access denied.</p>', 'Site Access Restricted' );
625 }
626
627
628 /**
629 * Helper function to determine whether a given email is in one of
630 * the lists (pending, approved, blocked). Defaults to the list of
631 * approved users.
632 *
633 * @param string $email Email to check existent of.
634 * @param string $list List to look for email in.
635 * @param string $multisite_mode Admin context.
636 * @return boolean Whether email was found.
637 */
638 public function is_email_in_list( $email = '', $list = 'approved', $multisite_mode = 'single' ) {
639 if ( empty( $email ) ) {
640 return false;
641 }
642
643 $options = Options::get_instance();
644
645 switch ( $list ) {
646 case 'pending':
647 $auth_settings_access_users_pending = $options->get( 'access_users_pending', Helper::SINGLE_CONTEXT );
648 return Helper::in_multi_array( $email, $auth_settings_access_users_pending );
649 case 'blocked':
650 $auth_settings_access_users_blocked = $options->get( 'access_users_blocked', Helper::SINGLE_CONTEXT );
651 // Blocked list can have wildcard matches, e.g., @baddomain.com, which
652 // should match any email address at that domain. Check if any wildcards
653 // exist, and if the email address has that domain.
654 $email_in_blocked_domain = false;
655 $blocked_domains = preg_grep(
656 '/^@.*/',
657 array_map(
658 function ( $blocked_item ) {
659 return $blocked_item['email']; },
660 $auth_settings_access_users_blocked
661 )
662 );
663 foreach ( $blocked_domains as $blocked_domain ) {
664 $email_domain = substr( $email, strrpos( $email, '@' ) );
665 if ( $email_domain === $blocked_domain ) {
666 $email_in_blocked_domain = true;
667 break;
668 }
669 }
670 return $email_in_blocked_domain || Helper::in_multi_array( $email, $auth_settings_access_users_blocked );
671 case 'approved':
672 default:
673 if ( 'single' !== $multisite_mode ) {
674 // Get multisite users only.
675 $auth_settings_access_users_approved = $options->get( 'access_users_approved', Helper::NETWORK_CONTEXT );
676 } elseif ( is_multisite() && 1 === intval( $options->get( 'advanced_override_multisite' ) ) ) {
677 // This site has overridden any multisite settings, so only get its users.
678 $auth_settings_access_users_approved = $options->get( 'access_users_approved', Helper::SINGLE_CONTEXT );
679 } else {
680 // Get all site users and all multisite users.
681 $auth_settings_access_users_approved = array_merge(
682 $options->get( 'access_users_approved', Helper::SINGLE_CONTEXT ),
683 $options->get( 'access_users_approved', Helper::NETWORK_CONTEXT )
684 );
685 }
686 return Helper::in_multi_array( $email, $auth_settings_access_users_approved );
687 }
688 }
689
690 }
691