Improve access gate to unpublished content

This commit is contained in:
Tetrakern 2023-08-31 17:30:24 +02:00
parent 5219412710
commit db8f002fa1
4 changed files with 46 additions and 15 deletions

View File

@ -1893,22 +1893,56 @@ if ( ! function_exists( 'fictioneer_redirect_to_404' ) ) {
// PREVIEW ACCESS VERIFICATION
// =============================================================================
if ( ! function_exists( 'fictioneer_verify_preview_access' ) ) {
if ( ! function_exists( 'fictioneer_verify_unpublish_access' ) ) {
/**
* Verifies preview query vars
* Verifies access to unpublished posts (not drafts)
*
* @since Fictioneer 5.6.0
*
* @return boolean True if access granted, false otherwise.
*/
function fictioneer_verify_preview_access() {
if ( isset( $_GET['preview'], $_GET['preview_nonce'] ) && $_GET['preview'] === 'true' ) {
if ( wp_verify_nonce( $_GET['preview_nonce'], 'post_preview_' . $_GET['preview_id'] ) ) {
return true;
function fictioneer_verify_unpublish_access( $post_id ) {
// Setup
$post = get_post( $post_id );
// Always let owner to pass
if ( get_current_user_id() === absint( $post->post_author ) ) {
return true;
}
// Always let administrators pass
if ( current_user_can( 'manage_options' ) ) {
return true;
}
// Check capability for post type
if ( $post->post_status === 'private' ) {
switch ( $post->post_type ) {
case 'post':
return current_user_can( 'edit_private_posts' );
break;
case 'page':
return current_user_can( 'edit_private_pages' );
break;
case 'fcn_chapter':
return current_user_can( 'read_private_fcn_chapters' );
break;
case 'fcn_story':
return current_user_can( 'read_private_fcn_stories' );
break;
case 'fcn_recommendation':
return current_user_can( 'read_private_fcn_recommendations' );
break;
case 'fcn_collection':
return current_user_can( 'read_private_fcn_collections' );
break;
default:
return current_user_can( 'edit_others_posts' );
}
}
// Drafts are handled by WordPress
return false;
}
}

View File

@ -1105,10 +1105,6 @@ if ( get_option( 'fictioneer_see_some_evil' ) ) {
/**
* Gates access to unpublished posts
*
* This is meant for sites with public caching, which could otherwise
* accidentally expose private posts or drafts. It ignored the user in
* favor of preview query vars via `fictioneer_verify_preview_access()`.
*
* @since Fictioneer 5.6.0
* @global WP_Post $post The current WordPress post object.
*/
@ -1119,7 +1115,8 @@ function fictioneer_gate_unpublished_content() {
// Do nothing if...
if (
! is_singular() ||
( $post->post_status === 'publish' && $post->post_type !== 'fcn_chapter' )
( $post->post_status === 'publish' && $post->post_type !== 'fcn_chapter' ) ||
get_current_user_id() === absint( $post->post_author )
) {
return;
}
@ -1128,7 +1125,7 @@ function fictioneer_gate_unpublished_content() {
if (
fictioneer_caching_active() &&
$post->post_status !== 'publish' &&
! fictioneer_verify_preview_access()
! fictioneer_verify_unpublish_access( $post->ID )
) {
fictioneer_redirect_to_404();
}
@ -1140,7 +1137,7 @@ function fictioneer_gate_unpublished_content() {
if (
! empty( $story_id ) &&
get_post_status( $story_id ) !== 'publish' &&
! fictioneer_verify_preview_access()
! fictioneer_verify_unpublish_access( $story_id )
) {
// 404
fictioneer_redirect_to_404();

View File

@ -25,7 +25,7 @@ defined( 'ABSPATH' ) OR exit;
$story_visible = $args['story_post'] &&
! empty( $args['story_data']['title'] ) &&
get_post_status( $args['story_post']->ID ) === 'publish';
in_array( get_post_status( $args['story_post']->ID ), ['publish', 'private'] );
?>

View File

@ -51,7 +51,7 @@ get_header( null, $header_args );
$story_data = null;
$story_post = null;
if ( get_post_status( $story_id ) === 'publish' ) {
if ( $story_id && in_array( get_post_status( $story_id ), ['publish', 'private'] ) ) {
$story_post = empty( $story_id ) ? null : get_post( $story_id );
}