Make WordPress Core


Ignore:
Timestamp:
03/04/2021 12:12:55 AM (4 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.