Make WordPress Core


Ignore:
Timestamp:
03/04/2021 12:12:55 AM (5 years ago)
Author:
peterwilsoncc
Message:

Roles/Caps: Return same result from current_user_can and user_can().

Ensure current_user_can() and user_can() return the same results for logged out users. For core capabilities this changes user_can( 0, 'exist' ) to return true rather than false in line with current_user_can( 'exist' ) for logged out users.

Convert current_user_can() and current_user_can_for_blog() to wrapper functions ultimately calling user_can().

Add anonymous user to primitive capability checks as appropriate. Convert Tests_User_Capabilities::test_other_caps_for_all_roles() to use a data provider and add tests to check whether user exists in the database (WP_User::exists()) as that intentionally differs from the exist capability.

Props jjj, johnbillion, peterwilsoncc, SergeyBiryukov, TimothyBlynJacobs.
Fixes #52076.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/tests/phpunit/tests/user/capabilities.php

    r50131 r50490  
    1313         */
    1414        protected static $users = array(
     15                'anonymous'     => null,
    1516                'administrator' => null,
    1617                'editor'        => null,
     
    3233        public static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ) {
    3334                self::$users       = array(
     35                        'anonymous'     => new WP_User( 0 ),
    3436                        'administrator' => $factory->user->create_and_get( array( 'role' => 'administrator' ) ),
    3537                        'editor'        => $factory->user->create_and_get( array( 'role' => 'editor' ) ),
     
    343345        }
    344346
     347        /**
     348         * Data provider for testing a single site install's roles.
     349         *
     350         * @return array[] {
     351         *     Arguments for test.
     352         *
     353         *     @type string $role The role to test for.
     354         * }
     355         */
     356        function data_single_site_roles_to_check() {
     357                return array(
     358                        array( 'anonymous' ),
     359                        array( 'administrator' ),
     360                        array( 'editor' ),
     361                        array( 'author' ),
     362                        array( 'contributor' ),
     363                        array( 'subscriber' ),
     364                );
     365        }
     366
    345367        protected function getAllCapsAndRoles() {
    346368                return $this->getPrimitiveCapsAndRoles() + $this->getMetaCapsAndRoles();
     
    392414
    393415                foreach ( self::$users as $role => $user ) {
    394 
    395                         // Make sure the user is valid.
    396                         $this->assertTrue( $user->exists(), "User with {$role} role does not exist" );
     416                        if ( 'anonymous' === $role ) {
     417                                // The anonymous role does not exist.
     418                                $this->assertFalse( $user->exists(), "User with {$role} role should not exist" );
     419                        } else {
     420                                // Make sure the user is valid.
     421                                $this->assertTrue( $user->exists(), "User with {$role} role does not exist" );
     422                        }
    397423
    398424                        $user_caps = $user->allcaps;
     
    564590        /**
    565591         * Test miscellaneous capabilities of all user roles.
    566          */
    567         function test_other_caps_for_all_roles() {
    568                 foreach ( self::$users as $role => $user ) {
    569                         // Make sure the user is valid.
    570                         $this->assertTrue( $user->exists(), "User with {$role} role does not exist" );
    571 
    572                         // Make sure the role name is correct.
    573                         $this->assertSame( array( $role ), $user->roles, "User should only have the {$role} role" );
    574 
    575                         $this->assertFalse( $user->has_cap( 'start_a_fire' ), "User with the {$role} role should not have a custom capability" );
    576                         $this->assertFalse( user_can( $user, 'start_a_fire' ), "User with the {$role} role should not have a custom capability" );
    577 
    578                         $this->assertFalse( $user->has_cap( 'do_not_allow' ), "User with the {$role} role should not have the do_not_allow capability" );
    579                         $this->assertFalse( user_can( $user, 'do_not_allow' ), "User with the {$role} role should not have the do_not_allow capability" );
    580 
    581                         $this->assertTrue( $user->has_cap( 'exist' ), "User with the {$role} role should have the exist capability" );
    582                         $this->assertTrue( user_can( $user, 'exist' ), "User with the {$role} role should have the exist capability" );
    583                 }
     592         *
     593         * @dataProvider data_single_site_roles_to_check
     594         */
     595        function test_other_caps_for_all_roles( $role ) {
     596                $user   = self::$users[ $role ];
     597                $old_id = wp_get_current_user()->ID;
     598                wp_set_current_user( $user->ID );
     599
     600                // Make sure the role name is correct.
     601                $expected_roles = array( $role );
     602                if ( 'anonymous' === $role ) {
     603                        //  Anonymous role does not exist, user roles should be empty.
     604                        $expected_roles = array();
     605                }
     606                $this->assertSame( $expected_roles, $user->roles, "User should only have the {$role} role" );
     607
     608                $this->assertFalse( $user->has_cap( 'start_a_fire' ), "User with the {$role} role should not have a custom capability (test via WP_User->has_cap() method)." );
     609                $this->assertFalse( user_can( $user, 'start_a_fire' ), "User with the {$role} role should not have a custom capability (test by user object)." );
     610                $this->assertFalse( user_can( $user->ID, 'start_a_fire' ), "User with the {$role} role should not have a custom capability (test by user ID)." );
     611                $this->assertFalse( current_user_can( 'start_a_fire' ), "User with the {$role} role should not have a custom capability (test by current user)." );
     612
     613                $this->assertFalse( $user->has_cap( 'do_not_allow' ), "User with the {$role} role should not have the do_not_allow capability (test via WP_User->has_cap() method)." );
     614                $this->assertFalse( user_can( $user, 'do_not_allow' ), "User with the {$role} role should not have the do_not_allow capability (test by user object)." );
     615                $this->assertFalse( user_can( $user->ID, 'do_not_allow' ), "User with the {$role} role should not have the do_not_allow capability (test by user ID)." );
     616                $this->assertFalse( current_user_can( 'do_not_allow' ), "User with the {$role} role should not have the do_not_allow capability (test by current user)." );
     617
     618                $this->assertTrue( $user->has_cap( 'exist' ), "User with the {$role} role should have the exist capability (test via WP_User->has_cap() method)." );
     619                $this->assertTrue( user_can( $user, 'exist' ), "User with the {$role} role should have the exist capability (test by user object)." );
     620                $this->assertTrue( user_can( $user->ID, 'exist' ), "User with the {$role} role should have the exist capability (test by user ID)." );
     621                $this->assertTrue( current_user_can( 'exist' ), "User with the {$role} role should have the exist capability (test by current user)." );
     622
     623                wp_set_current_user( $old_id );
     624        }
     625
     626        /**
     627         * Test user exists/does not exist as expected.
     628         *
     629         * @dataProvider data_single_site_roles_to_check
     630         */
     631        function test_user_exists_in_database( $role ) {
     632                $user     = self::$users[ $role ];
     633                $expected = true;
     634
     635                if ( 'anonymous' === $role ) {
     636                        $expected = false;
     637                }
     638
     639                $this->assertSame( $expected, $user->exists() );
    584640        }
    585641
     
    595651                        $user->remove_cap( 'do_not_allow' );
    596652                        $this->assertFalse( $has_cap, "User with the {$role} role should not have the do_not_allow capability" );
     653
     654                        # Test adding the cap via a filter
     655                        add_filter( 'user_has_cap', array( $this, 'grant_do_not_allow' ), 10, 4 );
     656                        $has_cap = $user->has_cap( 'do_not_allow' );
     657                        remove_filter( 'user_has_cap', array( $this, 'grant_do_not_allow' ), 10, 4 );
     658                        $this->assertFalse( $has_cap, "User with the {$role} role should not have the do_not_allow capability" );
     659
     660                        if ( 'anonymous' === $role ) {
     661                                // The anonymous role does not exist.
     662                                continue;
     663                        }
    597664
    598665                        # Test adding the cap to the user's role
     
    602669                        $role_obj->remove_cap( 'do_not_allow' );
    603670                        $this->assertFalse( $has_cap, "User with the {$role} role should not have the do_not_allow capability" );
    604 
    605                         # Test adding the cap via a filter
    606                         add_filter( 'user_has_cap', array( $this, 'grant_do_not_allow' ), 10, 4 );
    607                         $has_cap = $user->has_cap( 'do_not_allow' );
    608                         remove_filter( 'user_has_cap', array( $this, 'grant_do_not_allow' ), 10, 4 );
    609                         $this->assertFalse( $has_cap, "User with the {$role} role should not have the do_not_allow capability" );
    610 
    611671                }
    612672        }
Note: See TracChangeset for help on using the changeset viewer.