From 2bcb43ef7296b679943eead2e0ab35d6204bb2e0 Mon Sep 17 00:00:00 2001 From: lucadobrescu <252785083+lucadobrescu@users.noreply.github.com> Date: Mon, 27 Jul 2026 12:21:49 +0300 Subject: [PATCH 1/2] fix: check per-post edit_post capability in chart_data REST field The chart_data REST field callback only checked the generic edit_posts capability, so any contributor could read the full backend configuration of any chart (data source query, settings, JSON endpoint auth headers) via GET /wp-json/wp/v2/visualizer/{id}. Check edit_post on the requested chart instead, so access follows the standard post capability map (author or edit_others_posts). Fixes Codeinwp/visualizer-pro#605 Co-Authored-By: Claude Fable 5 --- classes/Visualizer/Gutenberg/Block.php | 2 +- tests/test-chart-data-permissions.php | 60 ++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 tests/test-chart-data-permissions.php diff --git a/classes/Visualizer/Gutenberg/Block.php b/classes/Visualizer/Gutenberg/Block.php index 1111c86b..93a0cb58 100644 --- a/classes/Visualizer/Gutenberg/Block.php +++ b/classes/Visualizer/Gutenberg/Block.php @@ -276,7 +276,7 @@ public function register_rest_endpoints() { * Get Post Meta Fields */ public function get_visualizer_data( $post ) { - if ( ! current_user_can( 'edit_posts' ) ) { + if ( ! current_user_can( 'edit_post', $post['id'] ) ) { return false; } diff --git a/tests/test-chart-data-permissions.php b/tests/test-chart-data-permissions.php new file mode 100644 index 00000000..aa2391bb --- /dev/null +++ b/tests/test-chart-data-permissions.php @@ -0,0 +1,60 @@ +post->create( + array( + 'post_type' => Visualizer_Plugin::CPT_VISUALIZER, + 'post_author' => $author_id, + 'post_content' => wp_slash( serialize( array( array( 'Label' ), array( 'Value' ) ) ) ), + ) + ); + update_post_meta( $chart_id, Visualizer_Plugin::CF_CHART_TYPE, 'line' ); + update_post_meta( $chart_id, Visualizer_Plugin::CF_SETTINGS, array() ); + update_post_meta( $chart_id, Visualizer_Plugin::CF_SERIES, array( array( 'label' => 'Label', 'type' => 'string' ) ) ); + return $chart_id; + } + + /** + * A contributor must not read another user's chart configuration. + */ + public function test_contributor_cannot_read_others_chart_data() { + $author_id = self::factory()->user->create( array( 'role' => 'editor' ) ); + $chart_id = $this->create_chart( $author_id ); + + wp_set_current_user( self::factory()->user->create( array( 'role' => 'contributor' ) ) ); + + $result = Visualizer_Gutenberg_Block::get_instance()->get_visualizer_data( array( 'id' => $chart_id ) ); + $this->assertFalse( $result ); + } + + /** + * The chart author can still read their own chart configuration. + */ + public function test_author_can_read_own_chart_data() { + $author_id = self::factory()->user->create( array( 'role' => 'editor' ) ); + $chart_id = $this->create_chart( $author_id ); + + wp_set_current_user( $author_id ); + + $result = Visualizer_Gutenberg_Block::get_instance()->get_visualizer_data( array( 'id' => $chart_id ) ); + $this->assertIsArray( $result ); + } +} From 6b05e982b1937459673220c7fc540f2326ed884b Mon Sep 17 00:00:00 2001 From: lucadobrescu <252785083+lucadobrescu@users.noreply.github.com> Date: Wed, 29 Jul 2026 11:39:26 +0300 Subject: [PATCH 2/2] fix: use can_edit_chart so contributor authors keep access to own charts Charts are force-published on save, and Contributors lack edit_published_posts, so a bare edit_post check locks chart authors out of their own charts in the Gutenberg block. Use the existing Visualizer_Module::can_edit_chart() helper, which allows the chart owner with edit_posts while still rejecting other users' charts. Covers Copilot review feedback on #1348. Co-Authored-By: Claude Fable 5 --- classes/Visualizer/Gutenberg/Block.php | 2 +- tests/test-chart-data-permissions.php | 20 ++++++++++++++++++-- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/classes/Visualizer/Gutenberg/Block.php b/classes/Visualizer/Gutenberg/Block.php index 93a0cb58..be55c623 100644 --- a/classes/Visualizer/Gutenberg/Block.php +++ b/classes/Visualizer/Gutenberg/Block.php @@ -276,7 +276,7 @@ public function register_rest_endpoints() { * Get Post Meta Fields */ public function get_visualizer_data( $post ) { - if ( ! current_user_can( 'edit_post', $post['id'] ) ) { + if ( ! Visualizer_Module::can_edit_chart( $post['id'] ) ) { return false; } diff --git a/tests/test-chart-data-permissions.php b/tests/test-chart-data-permissions.php index aa2391bb..7867f496 100644 --- a/tests/test-chart-data-permissions.php +++ b/tests/test-chart-data-permissions.php @@ -22,6 +22,7 @@ private function create_chart( $author_id ) { $chart_id = self::factory()->post->create( array( 'post_type' => Visualizer_Plugin::CPT_VISUALIZER, + 'post_status' => 'publish', 'post_author' => $author_id, 'post_content' => wp_slash( serialize( array( array( 'Label' ), array( 'Value' ) ) ) ), ) @@ -47,9 +48,12 @@ public function test_contributor_cannot_read_others_chart_data() { /** * The chart author can still read their own chart configuration. + * + * Charts are always published on save, so a Contributor author must pass + * the check even without the edit_published_posts capability. */ - public function test_author_can_read_own_chart_data() { - $author_id = self::factory()->user->create( array( 'role' => 'editor' ) ); + public function test_contributor_author_can_read_own_chart_data() { + $author_id = self::factory()->user->create( array( 'role' => 'contributor' ) ); $chart_id = $this->create_chart( $author_id ); wp_set_current_user( $author_id ); @@ -57,4 +61,16 @@ public function test_author_can_read_own_chart_data() { $result = Visualizer_Gutenberg_Block::get_instance()->get_visualizer_data( array( 'id' => $chart_id ) ); $this->assertIsArray( $result ); } + + /** + * An editor can read any chart configuration. + */ + public function test_editor_can_read_others_chart_data() { + $chart_id = $this->create_chart( self::factory()->user->create( array( 'role' => 'contributor' ) ) ); + + wp_set_current_user( self::factory()->user->create( array( 'role' => 'editor' ) ) ); + + $result = Visualizer_Gutenberg_Block::get_instance()->get_visualizer_data( array( 'id' => $chart_id ) ); + $this->assertIsArray( $result ); + } }