Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WordPress. Used remove_cap(), getting "Sorry, you are not allowed to access this page." even after removing this function

Tags:

php

wordpress

In WordPress v5.5.1, I have used below function to restrict authors to publish the posts:

function set_capabilities() {
    $author = get_role('author');
    $caps = array(
        'edit_others_posts',
        'edit_others_pages',
        'publish_posts',
        'delete_posts',
        'delete_published_posts',
    );

    foreach ($caps as $cap) {
        $author->remove_cap($cap);
    }
}
add_action('init', 'set_capabilities');

It resulted in complete removal of posts page and adding new posts at wp-admin/post-new.php.

I have removed the set_capabilities() function, still getting the error "Sorry, you are not allowed to access this page.".

I have tried resetting the wp-capabilities, still it did not worked for me.

I have tried adding a new user with author role, the new user have the same issue as well.

How can I have the authors create a post accessing wp-admin/post-new.php again?

like image 962
theKing Avatar asked Oct 16 '22 00:10

theKing


1 Answers

Problem

After calling $author->remove_cap($cap) the capability was removed from the author role, not only in memory but also in the database (see reference section below for implementation and links). As a result, removing the call to set_capabilities() or adding a new user to the role would not reset the role capabilities.

Solutions

Approach 1 - Using Wordpress

You could do the opposite of set_capabilities() eg add_capabilities() as shown below to re-assign these privileges both in memory and database using the official Wordpress API

function add_capabilities() {
    $author = get_role('author');
    $caps = array(
        'edit_others_posts',
        'edit_others_pages',
        'publish_posts',
        'delete_posts',
        'delete_published_posts',
    );

    foreach ($caps as $cap) {
        $author->add_cap($cap);
    }
}
add_action('init', 'add_capabilities');

From your users administration page you could then ensure the user is assigned the desired role of author.

Approach 2 - Manually accessing and updating your database

Assuming wp_ as your database prefix, you could ensure that the user is indeed assigned the role of author and if not manually assign this. This is in your wp_usermeta table, you should see a record with the user_id in question and the name wp_capabilities. The value stores a php serialized array of roles for example if the user was just an author the value would be a:1:{s:6:"author";b:1;}.

Now that you have ensured the user is indeed in the role, all role capabilities are stored in wp_options table within option_name wp_user_roles. Again, this is a long serialized php associative array that is structed as such (assume $roleName to be any role eg. 'author')

["$roleName"=>[
     'name'=>"$roleName",
     'capabilities'=>[
         'edit_others_posts',
        'edit_others_pages',
        'publish_posts',
        'delete_posts',
        'delete_published_posts',
     ]
 ]
]

If you had a backup or another working location you could restore it. If you desire to manually modify these values, due to the need for php serialization, I would recommend writing custom code in php to achieve such as a last resort if using Solution 1 is not helpful or the Wordpress methods are not available eg. working from a different client/server/location.

Additional Resources and References

See implementation from official Wordpress Documenation

$author = get_role('author'); --> returns a WP_Role in $author

And an implementation of the remove_cap called and the add_cap I will make reference to retrieved from https://developer.wordpress.org/reference/classes/wp_roles/ is included below:

/**
     * Add capability to role.
     *
     * @since 2.0.0
     *
     * @param string $role  Role name.
     * @param string $cap   Capability name.
     * @param bool   $grant Optional. Whether role is capable of performing capability.
     *                      Default true.
     */
    public function add_cap( $role, $cap, $grant = true ) {
        if ( ! isset( $this->roles[ $role ] ) ) {
            return;
        }
 
        $this->roles[ $role ]['capabilities'][ $cap ] = $grant;
        if ( $this->use_db ) {
            update_option( $this->role_key, $this->roles );
        }
    }
 
    /**
     * Remove capability from role.
     *
     * @since 2.0.0
     *
     * @param string $role Role name.
     * @param string $cap  Capability name.
     */
    public function remove_cap( $role, $cap ) {
        if ( ! isset( $this->roles[ $role ] ) ) {
            return;
        }
 
        unset( $this->roles[ $role ]['capabilities'][ $cap ] );
        if ( $this->use_db ) {
            update_option( $this->role_key, $this->roles );
        }
    }
like image 171
ggordon Avatar answered Oct 21 '22 05:10

ggordon