Skip to:
Content

bbPress.org

Changeset 7484


Ignore:
Timestamp:
09/11/2026 04:22:26 AM (9 days ago)
Author:
johnjamesjacoby
Message:

Replies: Authorize the topic's forum.

Backport the reply forum authorization fix from trunk. Always derive the forum used for reply creation and capability checks from the submitted topic, and call read_forum for every forum so inherited restrictions are enforced.

Add regression coverage for normal replies and participant attempts to target hidden and inherited restricted forums.

Merges r7483 to 2.6.

In branches/2.6, for 2.6.16.

Props vvh1te3zz.

Location:
branches/2.6
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • branches/2.6/src/includes/replies/functions.php

    r7468 r7484  
    209209        /** Forum ID **************************************************************/
    210210
    211         // Try to use the forum id of the topic
    212         if ( ! isset( $_POST['bbp_forum_id'] ) && ! empty( $topic_id ) ) {
     211        // Use the forum id of the topic
     212        if ( ! empty( $topic_id ) ) {
    213213                $forum_id = bbp_get_topic_forum_id( $topic_id );
     214        }
    214215
    215216        // Error check the POST'ed forum id
    216         } elseif ( isset( $_POST['bbp_forum_id'] ) ) {
     217        if ( isset( $_POST['bbp_forum_id'] ) ) {
    217218
    218219                // Empty Forum id was passed
     
    242243                                bbp_add_error( 'bbp_topic_forum_id', __( '<strong>Error</strong>: Forum does not exist.', 'bbpress' ) );
    243244
    244                         // Use the POST'ed forum id
    245                         } else {
    246                                 $forum_id = $posted_forum_id;
    247245                        }
    248246                }
     
    264262                        }
    265263
    266                         // Forum is private and user cannot access
    267                         if ( bbp_is_forum_private( $forum_id ) && ! current_user_can( 'read_forum', $forum_id ) ) {
    268                                 bbp_add_error( 'bbp_new_reply_forum_private', __( '<strong>Error</strong>: This forum is private and you do not have the capability to read or create new replies in it.', 'bbpress' ) );
    269 
    270                         // Forum is hidden and user cannot access
    271                         } elseif ( bbp_is_forum_hidden( $forum_id ) && ! current_user_can( 'read_forum', $forum_id ) ) {
    272                                 bbp_add_error( 'bbp_new_reply_forum_hidden', __( '<strong>Error</strong>: This forum is hidden and you do not have the capability to read or create new replies in it.', 'bbpress' ) );
     264                        // Forum not readable by user
     265                        if ( ! current_user_can( 'read_forum', $forum_id ) ) {
     266                                bbp_add_error( 'bbp_new_reply_forum_read', __( '<strong>Error</strong>: You do not have the capability to read or create new replies in this forum.', 'bbpress' ) );
    273267                        }
    274268                }
  • branches/2.6/tests/phpunit/testcases/replies/functions/permissions.php

    r7480 r7484  
    3333        }
    3434
    35         /**
    36          * @covers ::bbp_new_reply_handler
    37          */
    38         public function test_participant_cannot_submit_reply_to_private_topic() {
    39                 $forum_id = $this->factory->forum->create();
    40                 $topic_id = $this->factory->topic->create(
    41                         array(
    42                                 'post_status' => bbp_get_private_status_id(),
    43                                 'post_parent' => $forum_id,
    44                                 'topic_meta'  => array(
    45                                         'forum_id' => $forum_id,
    46                                 ),
    47                         )
    48                 );
    49                 $user_id  = $this->factory->user->create(
    50                         array(
    51                                 'role' => bbp_get_participant_role(),
    52                         )
    53                 );
    54 
    55                 $this->set_current_user( $user_id );
    56                 bbpress()->errors = new WP_Error();
    57 
    58                 $this->assertFalse( current_user_can( 'read_topic', $topic_id ) );
    59 
     35        protected function submit_reply( $topic_id, $forum_id = null, $content = '', $anonymous_data = array() ) {
    6036                $home_url             = wp_parse_url( home_url( '/' ) );
    6137                $_SERVER['HTTP_HOST'] = $home_url['host'];
     
    6642
    6743                $_SERVER['REQUEST_URI']     = $home_url['path'];
     44                $_SERVER['REMOTE_ADDR']     = '127.0.0.1';
    6845                $_POST['bbp_topic_id']      = $topic_id;
    69                 $_POST['bbp_reply_content'] = 'A reply to a private topic.';
     46                $_POST['bbp_reply_content'] = $content;
    7047                $_REQUEST['_wpnonce']       = wp_create_nonce( 'bbp-new-reply' );
     48
     49                if ( null !== $forum_id ) {
     50                        $_POST['bbp_forum_id'] = $forum_id;
     51                }
     52
     53                $_POST = array_merge( $_POST, $anonymous_data );
    7154
    7255                $did_redirect     = false;
    7356                $prevent_redirect = function( $location ) use ( &$did_redirect ) {
    7457                        $did_redirect = true;
    75                         throw new RuntimeException( 'Unexpected reply redirect.' );
     58                        throw new RuntimeException( 'Reply redirect.' );
    7659                };
     60                $prevent_cookies  = function() {
     61                        return array();
     62                };
    7763
    7864                add_filter( 'wp_redirect', $prevent_redirect );
     65                add_filter( 'bbp_filter_anonymous_post_data', $prevent_cookies );
    7966
    8067                try {
    8168                        bbp_new_reply_handler( 'bbp-new-reply' );
    8269                } catch ( RuntimeException $exception ) {
    83                         if ( 'Unexpected reply redirect.' !== $exception->getMessage() ) {
     70                        if ( 'Reply redirect.' !== $exception->getMessage() ) {
    8471                                throw $exception;
    8572                        }
     
    8774
    8875                remove_filter( 'wp_redirect', $prevent_redirect );
    89 
    90                 $reply_ids = get_posts(
     76                remove_filter( 'bbp_filter_anonymous_post_data', $prevent_cookies );
     77
     78                return $did_redirect;
     79        }
     80
     81        protected function get_reply_ids( $topic_id ) {
     82                return get_posts(
    9183                        array(
    9284                                'fields'      => 'ids',
     
    9688                        )
    9789                );
     90        }
     91
     92        /**
     93         * @covers ::bbp_new_reply_handler
     94         */
     95        public function test_participant_cannot_submit_reply_to_private_topic() {
     96                $forum_id = $this->factory->forum->create();
     97                $topic_id = $this->factory->topic->create(
     98                        array(
     99                                'post_status' => bbp_get_private_status_id(),
     100                                'post_parent' => $forum_id,
     101                                'topic_meta'  => array(
     102                                        'forum_id' => $forum_id,
     103                                ),
     104                        )
     105                );
     106                $user_id  = $this->factory->user->create(
     107                        array(
     108                                'role' => bbp_get_participant_role(),
     109                        )
     110                );
     111
     112                $this->set_current_user( $user_id );
     113                bbpress()->errors = new WP_Error();
     114
     115                $this->assertFalse( current_user_can( 'read_topic', $topic_id ) );
     116
     117                $did_redirect = $this->submit_reply( $topic_id, null, 'A reply to a private topic.' );
     118                $reply_ids    = $this->get_reply_ids( $topic_id );
    98119
    99120                $this->assertSame( array(), $reply_ids );
     
    101122                $this->assertFalse( $did_redirect );
    102123        }
     124
     125        /**
     126         * @covers ::bbp_new_reply_handler
     127         */
     128        public function test_participant_can_submit_reply_when_forum_id_matches_topic() {
     129                $forum_id = $this->factory->forum->create();
     130                $topic_id = $this->factory->topic->create(
     131                        array(
     132                                'post_parent' => $forum_id,
     133                                'topic_meta'  => array(
     134                                        'forum_id' => $forum_id,
     135                                ),
     136                        )
     137                );
     138                $user_id  = $this->factory->user->create(
     139                        array(
     140                                'role' => bbp_get_participant_role(),
     141                        )
     142                );
     143
     144                $this->set_current_user( $user_id );
     145                bbpress()->errors = new WP_Error();
     146
     147                $did_redirect = $this->submit_reply( $topic_id, $forum_id, 'A reply to a public topic.' );
     148                $reply_ids    = $this->get_reply_ids( $topic_id );
     149
     150                $this->assertCount( 1, $reply_ids );
     151                $this->assertSame( $forum_id, bbp_get_reply_forum_id( $reply_ids[0] ) );
     152                $this->assertSame( array(), bbpress()->errors->get_error_codes() );
     153                $this->assertTrue( $did_redirect );
     154        }
     155
     156        /**
     157         * @covers ::bbp_new_reply_handler
     158         */
     159        public function test_participant_cannot_spoof_forum_id_to_reply_to_hidden_topic() {
     160                $public_forum_id = $this->factory->forum->create();
     161                $hidden_forum_id = $this->factory->forum->create(
     162                        array(
     163                                'post_status' => bbp_get_hidden_status_id(),
     164                        )
     165                );
     166                $topic_id       = $this->factory->topic->create(
     167                        array(
     168                                'post_parent' => $hidden_forum_id,
     169                                'topic_meta'  => array(
     170                                        'forum_id' => $hidden_forum_id,
     171                                ),
     172                        )
     173                );
     174                $user_id        = $this->factory->user->create(
     175                        array(
     176                                'role' => bbp_get_participant_role(),
     177                        )
     178                );
     179
     180                $this->set_current_user( $user_id );
     181                bbpress()->errors = new WP_Error();
     182
     183                $this->assertTrue( current_user_can( 'read_topic', $topic_id ) );
     184                $this->assertFalse( current_user_can( 'read_forum', $hidden_forum_id ) );
     185                $this->assertTrue( current_user_can( 'read_forum', $public_forum_id ) );
     186
     187                $did_redirect = $this->submit_reply( $topic_id, $public_forum_id, 'A reply to a topic in a hidden forum.' );
     188                $reply_ids    = $this->get_reply_ids( $topic_id );
     189
     190                $this->assertSame( array(), $reply_ids );
     191                $this->assertContains( 'bbp_new_reply_forum_read', bbpress()->errors->get_error_codes() );
     192                $this->assertFalse( $did_redirect );
     193        }
     194
     195        /**
     196         * @covers ::bbp_new_reply_handler
     197         */
     198        public function test_participant_cannot_spoof_forum_id_to_reply_below_hidden_forum() {
     199                $public_forum_id = $this->factory->forum->create();
     200                $hidden_forum_id = $this->factory->forum->create(
     201                        array(
     202                                'post_status' => bbp_get_hidden_status_id(),
     203                        )
     204                );
     205                $child_forum_id  = $this->factory->forum->create(
     206                        array(
     207                                'post_parent' => $hidden_forum_id,
     208                        )
     209                );
     210                $topic_id        = $this->factory->topic->create(
     211                        array(
     212                                'post_parent' => $child_forum_id,
     213                                'topic_meta'  => array(
     214                                        'forum_id' => $child_forum_id,
     215                                ),
     216                        )
     217                );
     218                $user_id         = $this->factory->user->create(
     219                        array(
     220                                'role' => bbp_get_participant_role(),
     221                        )
     222                );
     223
     224                $this->set_current_user( $user_id );
     225                bbpress()->errors = new WP_Error();
     226
     227                $this->assertTrue( current_user_can( 'read_topic', $topic_id ) );
     228                $this->assertFalse( current_user_can( 'read_forum', $child_forum_id ) );
     229                $this->assertTrue( current_user_can( 'read_forum', $public_forum_id ) );
     230
     231                $did_redirect = $this->submit_reply( $topic_id, $public_forum_id, 'A reply below a hidden forum.' );
     232                $reply_ids    = $this->get_reply_ids( $topic_id );
     233
     234                $this->assertSame( array(), $reply_ids );
     235                $this->assertContains( 'bbp_new_reply_forum_read', bbpress()->errors->get_error_codes() );
     236                $this->assertFalse( $did_redirect );
     237        }
     238
    103239}
Note: See TracChangeset for help on using the changeset viewer.