diff --git a/classes/Visualizer/Module/Chart.php b/classes/Visualizer/Module/Chart.php index fc3190f4..340bca54 100644 --- a/classes/Visualizer/Module/Chart.php +++ b/classes/Visualizer/Module/Chart.php @@ -1222,12 +1222,13 @@ public function uploadData() { // if this is being called internally from pro and VISUALIZER_DO_NOT_DIE is set. // otherwise, assume this is a normal web request. $can_die = ! ( defined( 'VISUALIZER_DO_NOT_DIE' ) && VISUALIZER_DO_NOT_DIE ); + // $can_die also gates the capability checks below, so VISUALIZER_DO_NOT_DIE must stay internal-only (never set from request input or globally). - // validate nonce + // validate nonce; capability check applies to web requests only, not trusted internal calls. if ( ! isset( $_GET['nonce'] ) || ! wp_verify_nonce( $_GET['nonce'], 'visualizer-upload-data' ) || - ! current_user_can( 'edit_posts' ) + ( $can_die && ! current_user_can( 'edit_posts' ) ) ) { if ( ! $can_die ) { return; @@ -1244,7 +1245,7 @@ public function uploadData() { ! $chart_id || ! $chart || $chart->post_type !== Visualizer_Plugin::CPT_VISUALIZER || - ! current_user_can( 'edit_post', $chart_id ) + ( $can_die && ! current_user_can( 'edit_post', $chart_id ) ) ) { if ( ! $can_die ) { return; diff --git a/tests/test-schedule.php b/tests/test-schedule.php new file mode 100644 index 00000000..20d57004 --- /dev/null +++ b/tests/test-schedule.php @@ -0,0 +1,45 @@ +assertFalse( current_user_can( 'edit_posts' ), 'precondition: background context has no editing user' ); + + $chart_id = self::factory()->post->create( + array( + 'post_type' => Visualizer_Plugin::CPT_VISUALIZER, + 'post_status' => 'publish', + 'post_content' => 'OLD-CONTENT', + ) + ); + + // mimic Pro's internal invocation; clean superglobals so prior tests don't reroute uploadData(). + $_GET = $_POST = $_FILES = array(); + define( 'VISUALIZER_DO_NOT_DIE', true ); + $_GET['nonce'] = wp_create_nonce( 'visualizer-upload-data' ); + $_GET['chart'] = $chart_id; + $_POST['editor-type'] = 'text'; + $_POST['chart_data'] = "Name,Value\nstring,number\nAlpha,111\nBeta,222"; + + do_action( 'wp_ajax_' . Visualizer_Plugin::ACTION_UPLOAD_DATA ); + + $content = get_post_field( 'post_content', $chart_id ); + $this->assertStringContainsString( 'Alpha', $content, 'scheduled/background import must update chart data without a logged-in user' ); + } +}