Make WordPress Core


Ignore:
Timestamp:
10/29/2020 05:42:13 PM (6 years ago)
Author:
desrosj
Message:

XML-RPC: Improve error messages for unprivileged users.

Add specific permission checks to avoid ambiguous failure messages.

Props zieladam, peterwilsoncc, xknown, whyisjake.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/tests/phpunit/tests/xmlrpc/wp/newComment.php

    r49303 r49380  
    77
    88        /**
    9          * Post object for shared fixture.
    10          *
    11          * @var WP_Post
    12          */
    13         public static $post;
     9         * Array of posts.
     10         *
     11         * @var WP_Post[]
     12         */
     13        public static $posts;
     14
     15        /**
     16         * User IDs.
     17         *
     18         * Array of user IDs keyed by role.
     19         *
     20         * @var int[]
     21         */
     22        public static $user_ids;
    1423
    1524        public static function wpSetUpBeforeClass( $factory ) {
    16                 self::make_user_by_role( 'administrator' );
    17                 self::$post = $factory->post->create_and_get();
     25                self::$user_ids                     = array(
     26                        'administrator' => self::make_user_by_role( 'administrator' ),
     27                        'contributor'   => self::make_user_by_role( 'contributor' ),
     28                );
     29                self::$posts['publish']             = $factory->post->create_and_get();
     30                self::$posts['password']            = $factory->post->create_and_get(
     31                        array(
     32                                'post_password' => 'xmlrpc',
     33                                'post_author'   => self::$user_ids['administrator'],
     34                        )
     35                );
     36                self::$posts['private']             = $factory->post->create_and_get(
     37                        array(
     38                                'post_status' => 'private',
     39                                'post_author' => self::$user_ids['administrator'],
     40                        )
     41                );
     42                self::$posts['private_contributor'] = $factory->post->create_and_get(
     43                        array(
     44                                'post_status' => 'private',
     45                                'post_author' => self::$user_ids['contributor'],
     46                        )
     47                );
    1848        }
    1949
    … …  
    2454                                'administrator',
    2555                                'administrator',
    26                                 self::$post->ID,
     56                                self::$posts['publish']->ID,
    2757                                array(
    2858                                        'content' => rand_str( 100 ),
    … …  
    4070                                'administrator',
    4171                                'administrator',
    42                                 self::$post->ID,
     72                                self::$posts['publish']->ID,
    4373                                array(
    4474                                        'content' => '',
    … …  
    6090                                'administrator',
    6191                                'administrator',
    62                                 self::$post->ID,
     92                                self::$posts['publish']->ID,
    6393                                array(
    6494                                        'content' => '   ',
    … …  
    80110                                'administrator',
    81111                                'administrator',
    82                                 self::$post->ID,
     112                                self::$posts['publish']->ID,
    83113                                array(
    84114                                        'content' => '0',
    … …  
    100130                                'administrator',
    101131                                'administrator',
    102                                 self::$post->ID,
     132                                self::$posts['publish']->ID,
    103133                                array(
    104134                                        'content' => '   ',
    … …  
    140170                        'administrator',
    141171                        'administrator',
    142                         self::$post->ID,
     172                        self::$posts['publish']->ID,
    143173                        array(
    144174                                'content' => rand_str( 100 ),
    … …  
    169199                        '',
    170200                        '',
    171                         self::$post->ID,
     201                        self::$posts['publish']->ID,
    172202                        array(
    173203                                'author'       => 'WordPress',
    … …  
    194224                        '',
    195225                        '',
    196                         self::$post->ID,
     226                        self::$posts['publish']->ID,
    197227                        array(
    198228                                'author'       => 'WordPress',
    … …  
    219249                        'administrator',
    220250                        'administrator',
    221                         self::$post->ID,
     251                        self::$posts['publish']->ID,
    222252                        array(
    223253                                'author'       => 'WordPress',
    … …  
    233263                $this->assertSame( $user_id, (int) $comment->user_id );
    234264        }
     265
     266        /**
     267         * Ensure users can only comment on posts they're permitted to access.
     268         *
     269         * @dataProvider data_comments_observe_post_permissions
     270         *
     271         * @param string $post_key      Post identifier from the self::$posts array.
     272         * @param string $username      Username leaving comment.
     273         * @param bool   $expected      Expected result. True: successfull comment. False: Refused comment.
     274         * @param string $anon_callback Optional. Allow anonymous comment callback. Default __return_false.
     275         */
     276        function test_comments_observe_post_permissions( $post_key, $username, $expected, $anon_callback = '__return_false' ) {
     277                add_filter( 'xmlrpc_allow_anonymous_comments', $anon_callback );
     278
     279                $comment_args = array(
     280                        1,
     281                        $username,
     282                        $username,
     283                        self::$posts[ $post_key ]->ID,
     284                        array(
     285                                'author'       => 'WordPress',
     286                                'author_email' => 'noreply@wordpress.org',
     287                                'content'      => 'Test Comment',
     288                        ),
     289                );
     290
     291                $result = $this->myxmlrpcserver->wp_newComment( $comment_args );
     292                if ( $expected ) {
     293                        $this->assertInternalType( 'int', $result );
     294                        return;
     295                }
     296
     297                $this->assertIXRError( $result );
     298                $this->assertSame( 403, $result->code );
     299        }
     300
     301        /**
     302         * Data provider for test_comments_observe_post_permissions.
     303         *
     304         * @return array[] {
     305         *     @type string Post identifier from the self::$posts array.
     306         *     @type string Username leaving comment.
     307         *     @type bool   Expected result. True: successfull comment. False: Refused comment.
     308         *     @type string Optional. Allow anonymous comment callback. Default __return_false.
     309         * }
     310         */
     311        function data_comments_observe_post_permissions() {
     312                return array(
     313                        // 0: Post author, password protected public post.
     314                        array(
     315                                'password',
     316                                'administrator',
     317                                true,
     318                        ),
     319                        // 1: Low privileged non-author, password protected public post.
     320                        array(
     321                                'password',
     322                                'contributor',
     323                                false,
     324                        ),
     325                        // 2: Anonymous user, password protected public post.
     326                        array(
     327                                'password',
     328                                '', // Anonymous user.
     329                                false,
     330                        ),
     331                        // 3: Anonymous user, anon comments allowed, password protected public post.
     332                        array(
     333                                'password',
     334                                '', // Anonymous user.
     335                                false,
     336                                '__return_true',
     337                        ),
     338
     339                        // 4: Post author, private post.
     340                        array(
     341                                'private',
     342                                'administrator',
     343                                true,
     344                        ),
     345                        // 5: Low privileged non-author, private post.
     346                        array(
     347                                'private',
     348                                'contributor',
     349                                false,
     350                        ),
     351                        // 6: Anonymous user, private post.
     352                        array(
     353                                'private',
     354                                '', // Anonymous user.
     355                                false,
     356                        ),
     357                        // 7: Anonymous user, anon comments allowed, private post.
     358                        array(
     359                                'private',
     360                                '', // Anonymous user.
     361                                false,
     362                                '__return_true',
     363                        ),
     364
     365                        // 8: High privileged non-author, private post.
     366                        array(
     367                                'private_contributor',
     368                                'administrator',
     369                                true,
     370                        ),
     371                        // 9: Low privileged author, private post.
     372                        array(
     373                                'private_contributor',
     374                                'contributor',
     375                                true,
     376                        ),
     377                        // 10: Anonymous user, private post.
     378                        array(
     379                                'private_contributor',
     380                                '', // Anonymous user.
     381                                false,
     382                        ),
     383                        // 11: Anonymous user, anon comments allowed, private post.
     384                        array(
     385                                'private_contributor',
     386                                '', // Anonymous user.
     387                                false,
     388                                '__return_true',
     389                        ),
     390                );
     391        }
    235392}
Note: See TracChangeset for help on using the changeset viewer.