From d25c34b06d04f4f248e0c48afab2a27f3620c487 Mon Sep 17 00:00:00 2001 From: George Mamadashvili Date: Wed, 11 Jan 2023 16:22:05 +0400 Subject: [PATCH 1/7] Global Styles: Don't remove Custom CSS for users with the correct caps --- lib/class-wp-theme-json-gutenberg.php | 7 +- phpunit/class-wp-theme-json-test.php | 97 +++++++++++++++++++++++++++ 2 files changed, 103 insertions(+), 1 deletion(-) diff --git a/lib/class-wp-theme-json-gutenberg.php b/lib/class-wp-theme-json-gutenberg.php index 9acef6006d4e68..cd1f683c1a5d6b 100644 --- a/lib/class-wp-theme-json-gutenberg.php +++ b/lib/class-wp-theme-json-gutenberg.php @@ -2818,7 +2818,12 @@ public static function remove_insecure_properties( $theme_json ) { continue; } - $output = static::remove_insecure_styles( $input ); + // The global styles custom CSS is not sanitized, but can only be edited by users with 'edit_css' capability. + if ( isset( $input['css'] ) && current_user_can( 'edit_css' ) ) { + $output = $input; + } else { + $output = static::remove_insecure_styles( $input ); + } /* * Get a reference to element name from path. diff --git a/phpunit/class-wp-theme-json-test.php b/phpunit/class-wp-theme-json-test.php index 0d21f46ee9c291..20b192df428897 100644 --- a/phpunit/class-wp-theme-json-test.php +++ b/phpunit/class-wp-theme-json-test.php @@ -7,6 +7,23 @@ */ class WP_Theme_JSON_Gutenberg_Test extends WP_UnitTestCase { + /** + * Administrator ID. + * + * @var int + */ + protected static $administrator_id; + + public static function set_up_before_class() { + parent::set_up_before_class(); + + self::$administrator_id = self::factory()->user->create( + array( + 'role' => 'administrator', + ) + ); + } + /** * @dataProvider data_get_layout_definitions * @@ -1598,4 +1615,84 @@ public function test_get_stylesheet_handles_custom_css() { $custom_css = 'body { color:purple; }'; $this->assertEquals( $custom_css, $theme_json->get_stylesheet( array( 'custom-css' ) ) ); } + + public function test_allows_custom_css_for_users_with_caps() { + wp_set_current_user( self::$administrator_id ); + + $actual = WP_Theme_JSON_Gutenberg::remove_insecure_properties( + array( + 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, + 'styles' => array( + 'css' => 'body { color:purple; }', + 'blocks' => array( + 'core/separator' => array( + 'color' => array( + 'background' => 'blue', + ), + ), + ), + ), + ) + ); + + $expected = array( + 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, + 'styles' => array( + 'css' => 'body { color:purple; }', + 'blocks' => array( + 'core/separator' => array( + 'color' => array( + 'background' => 'blue', + ), + ), + ), + ), + ); + + $this->assertEqualSetsWithIndex( $expected, $actual ); + } + + public function test_removes_custom_css_for_users_without_caps() { + wp_set_current_user( self::$administrator_id ); + + $remove_edit_css_cap = function( $caps, $cap ) { + if ( 'edit_css' === $cap ) { + $caps = array( 'do_not_allow' ); + } + return $caps; + }; + add_filter( 'map_meta_cap', $remove_edit_css_cap, 10, 2 ); + + $actual = WP_Theme_JSON_Gutenberg::remove_insecure_properties( + array( + 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, + 'styles' => array( + 'css' => 'body { color:purple; }', + 'blocks' => array( + 'core/separator' => array( + 'color' => array( + 'background' => 'blue', + ), + ), + ), + ), + ) + ); + + $expected = array( + 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, + 'styles' => array( + 'blocks' => array( + 'core/separator' => array( + 'color' => array( + 'background' => 'blue', + ), + ), + ), + ), + ); + + $this->assertEqualSetsWithIndex( $expected, $actual ); + remove_filter( 'map_meta_cap', $remove_edit_css_cap ); + } } From 7801eca0e52aae37f02ebf708497e8d9b8b38f6d Mon Sep 17 00:00:00 2001 From: George Mamadashvili Date: Wed, 11 Jan 2023 16:55:52 +0400 Subject: [PATCH 2/7] Try fixing core kses_init_filters override --- lib/experimental/kses.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/experimental/kses.php b/lib/experimental/kses.php index fd7531617939fc..13894199bfb676 100644 --- a/lib/experimental/kses.php +++ b/lib/experimental/kses.php @@ -62,5 +62,5 @@ function gutenberg_override_core_kses_init_filters() { } } -add_action( 'init', 'gutenberg_override_core_kses_init_filters' ); +add_action( 'init', 'gutenberg_override_core_kses_init_filters', 20 ); add_action( 'set_current_user', 'gutenberg_override_core_kses_init_filters' ); From 9a95df26e13dfb7d3a94a1dcbe08cc6068a1321d Mon Sep 17 00:00:00 2001 From: George Mamadashvili Date: Thu, 12 Jan 2023 11:22:30 +0400 Subject: [PATCH 3/7] Add comment about priority change --- lib/experimental/kses.php | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/experimental/kses.php b/lib/experimental/kses.php index 13894199bfb676..830ac01c2ab0b6 100644 --- a/lib/experimental/kses.php +++ b/lib/experimental/kses.php @@ -62,5 +62,6 @@ function gutenberg_override_core_kses_init_filters() { } } +// The 'kses_init_filters' is usually initialized with default priority. Use higher priority to override. add_action( 'init', 'gutenberg_override_core_kses_init_filters', 20 ); add_action( 'set_current_user', 'gutenberg_override_core_kses_init_filters' ); From 11b9a75d5666408809eb63b00c0a34dc737e39ca Mon Sep 17 00:00:00 2001 From: George Mamadashvili Date: Thu, 12 Jan 2023 11:35:21 +0400 Subject: [PATCH 4/7] Explicitly grant 'edit_css' capabilities --- phpunit/class-wp-theme-json-test.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/phpunit/class-wp-theme-json-test.php b/phpunit/class-wp-theme-json-test.php index 20b192df428897..9ed99460ecb0e4 100644 --- a/phpunit/class-wp-theme-json-test.php +++ b/phpunit/class-wp-theme-json-test.php @@ -1619,6 +1619,15 @@ public function test_get_stylesheet_handles_custom_css() { public function test_allows_custom_css_for_users_with_caps() { wp_set_current_user( self::$administrator_id ); + // Explicitly grant 'edit_css' capabilities. + $grant_edit_css_cap = function( $caps, $cap ) { + if ( 'edit_css' === $cap ) { + $caps = array( 'edit_theme_options' ); + } + return $caps; + }; + add_filter( 'map_meta_cap', $grant_edit_css_cap, 10, 2 ); + $actual = WP_Theme_JSON_Gutenberg::remove_insecure_properties( array( 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, @@ -1650,6 +1659,7 @@ public function test_allows_custom_css_for_users_with_caps() { ); $this->assertEqualSetsWithIndex( $expected, $actual ); + remove_filter( 'map_meta_cap', $grant_edit_css_cap ); } public function test_removes_custom_css_for_users_without_caps() { From f05482f38c223f03ed9663953acf7ee38f99f9d9 Mon Sep 17 00:00:00 2001 From: hellofromtonya Date: Thu, 12 Jan 2023 11:34:12 -0600 Subject: [PATCH 5/7] Use grant_super_admin() for multisite --- phpunit/class-wp-theme-json-test.php | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/phpunit/class-wp-theme-json-test.php b/phpunit/class-wp-theme-json-test.php index 9ed99460ecb0e4..fd04e4e041059c 100644 --- a/phpunit/class-wp-theme-json-test.php +++ b/phpunit/class-wp-theme-json-test.php @@ -22,6 +22,10 @@ public static function set_up_before_class() { 'role' => 'administrator', ) ); + + if ( is_multisite() ) { + grant_super_admin( self::$administrator_id ); + } } /** @@ -1619,15 +1623,6 @@ public function test_get_stylesheet_handles_custom_css() { public function test_allows_custom_css_for_users_with_caps() { wp_set_current_user( self::$administrator_id ); - // Explicitly grant 'edit_css' capabilities. - $grant_edit_css_cap = function( $caps, $cap ) { - if ( 'edit_css' === $cap ) { - $caps = array( 'edit_theme_options' ); - } - return $caps; - }; - add_filter( 'map_meta_cap', $grant_edit_css_cap, 10, 2 ); - $actual = WP_Theme_JSON_Gutenberg::remove_insecure_properties( array( 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, From e549f8a46c49933e5aeae891a8958004c7e6dfc4 Mon Sep 17 00:00:00 2001 From: hellofromtonya Date: Thu, 12 Jan 2023 14:05:42 -0600 Subject: [PATCH 6/7] Use dataProvider --- phpunit/class-wp-theme-json-test.php | 101 +++++++++++++-------------- 1 file changed, 49 insertions(+), 52 deletions(-) diff --git a/phpunit/class-wp-theme-json-test.php b/phpunit/class-wp-theme-json-test.php index fd04e4e041059c..8b53e4d2289079 100644 --- a/phpunit/class-wp-theme-json-test.php +++ b/phpunit/class-wp-theme-json-test.php @@ -12,12 +12,19 @@ class WP_Theme_JSON_Gutenberg_Test extends WP_UnitTestCase { * * @var int */ - protected static $administrator_id; + private static $administrator_id; + + /** + * User ID. + * + * @var int + */ + private static $user_id; public static function set_up_before_class() { parent::set_up_before_class(); - self::$administrator_id = self::factory()->user->create( + static::$administrator_id = self::factory()->user->create( array( 'role' => 'administrator', ) @@ -26,6 +33,8 @@ public static function set_up_before_class() { if ( is_multisite() ) { grant_super_admin( self::$administrator_id ); } + + static::$user_id = self::factory()->user->create(); } /** @@ -1620,8 +1629,14 @@ public function test_get_stylesheet_handles_custom_css() { $this->assertEquals( $custom_css, $theme_json->get_stylesheet( array( 'custom-css' ) ) ); } - public function test_allows_custom_css_for_users_with_caps() { - wp_set_current_user( self::$administrator_id ); + /** + * @dataProvider data_custom_css_for_user_caps + * + * @param string $user_property The property name for current user. + * @param array $expected Expected results. + */ + public function test_custom_css_for_user_caps( $user_property, array $expected ) { + wp_set_current_user( static::${$user_property} ); $actual = WP_Theme_JSON_Gutenberg::remove_insecure_properties( array( @@ -1639,65 +1654,47 @@ public function test_allows_custom_css_for_users_with_caps() { ) ); - $expected = array( - 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, - 'styles' => array( - 'css' => 'body { color:purple; }', - 'blocks' => array( - 'core/separator' => array( - 'color' => array( - 'background' => 'blue', - ), - ), - ), - ), - ); - $this->assertEqualSetsWithIndex( $expected, $actual ); - remove_filter( 'map_meta_cap', $grant_edit_css_cap ); } - public function test_removes_custom_css_for_users_without_caps() { - wp_set_current_user( self::$administrator_id ); - - $remove_edit_css_cap = function( $caps, $cap ) { - if ( 'edit_css' === $cap ) { - $caps = array( 'do_not_allow' ); - } - return $caps; - }; - add_filter( 'map_meta_cap', $remove_edit_css_cap, 10, 2 ); - - $actual = WP_Theme_JSON_Gutenberg::remove_insecure_properties( - array( - 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, - 'styles' => array( - 'css' => 'body { color:purple; }', - 'blocks' => array( - 'core/separator' => array( - 'color' => array( - 'background' => 'blue', + /** + * Data provider. + * + * @return array[] + */ + public function data_custom_css_for_user_caps() { + return array( + 'allows custom css for users with caps' => array( + 'user_property' => 'administrator_id', + 'expected' => array( + 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, + 'styles' => array( + 'css' => 'body { color:purple; }', + 'blocks' => array( + 'core/separator' => array( + 'color' => array( + 'background' => 'blue', + ), ), ), ), ), - ) - ); - - $expected = array( - 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, - 'styles' => array( - 'blocks' => array( - 'core/separator' => array( - 'color' => array( - 'background' => 'blue', + ), + 'removes custom css for users without caps' => array( + 'user_property' => 'user_id', + 'expected' => array( + 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, + 'styles' => array( + 'blocks' => array( + 'core/separator' => array( + 'color' => array( + 'background' => 'blue', + ), + ), ), ), ), ), ); - - $this->assertEqualSetsWithIndex( $expected, $actual ); - remove_filter( 'map_meta_cap', $remove_edit_css_cap ); } } From a2a9aca9b9aded4e9085013119f3f8ab574bce1b Mon Sep 17 00:00:00 2001 From: hellofromtonya Date: Thu, 12 Jan 2023 14:13:32 -0600 Subject: [PATCH 7/7] Use assertSame* --- phpunit/class-wp-theme-json-test.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpunit/class-wp-theme-json-test.php b/phpunit/class-wp-theme-json-test.php index 8b53e4d2289079..795ad0ab4c8117 100644 --- a/phpunit/class-wp-theme-json-test.php +++ b/phpunit/class-wp-theme-json-test.php @@ -1654,7 +1654,7 @@ public function test_custom_css_for_user_caps( $user_property, array $expected ) ) ); - $this->assertEqualSetsWithIndex( $expected, $actual ); + $this->assertSameSetsWithIndex( $expected, $actual ); } /**