4

I created a custom post type for WP, that should just be visitable for user that have a custom capability read_cpt. Within templates and pre_get_posts I can run checks to include or exclude the CPT by using current_user_can().

I don't want the CPT, not even the endpoint, to show up within the REST API, to keep it top secret, as long as a user doesn't have the custom capability.

The only way I could figure out to hide the endpoints in the API to run this code.

Register post type for "classic" WP:

function add_post_type() {
    $args = array(
        [...]
        'public'                => false,
        'has_archive'           => false,
        'exclude_from_search'   => true,
        'publicly_queryable'    => false,
        'show_in_rest'          => false,
    );
    register_post_type( 'cpt', $args );
}
add_action( 'init', 'add_post_type', 0 );

and separately add it to the REST API:

add_action( 'init', 'cpt_rest_support', 25 );
function cpt_rest_support() {
    global $wp_post_types;

    if ( current_user_can( 'read_addresses' ) ) {
        //be sure to set this to the name of your post type!
        $post_type_name = 'address';
        if( isset( $wp_post_types[ 'cpt' ] ) ) {
            $wp_post_types[ 'cpt' ]->show_in_rest = true;
        }
    }
}

By creating a custom WP_REST_Posts_Controller class I couldn't find a way to hide the endpoint by modifying any of the *_permissions_check

Is there something like a "show_in_rest_permition_check" argument for register_post_type() or is the described way the only method?

4 Answers 4

2

The REST API has no parameters, options to solve this - in my opinion. But you should register only if the users have the capability in his role, like the follow example.

add_action( 'rest_api_init', function() {

    // Exit, if the logged in user have not enough rights.
    if ( ! current_user_can( 'edit_posts' ) ) {
        return;
    }

    // Register Meta Data.
    register_meta( 'post', 'foo', array(
        'show_in_rest' => true,
    ));
});

That's fire the custom data in the REST API only, if the user have enough rights, capabilities in his role. My register_meta() is only an example, that should also work with your additional parameter for register_post_type, like $wp_post_types[ 'cpt' ]->show_in_rest = true;.

1

Old question but this worked for me following @Drivingralle requirements. You could use current_user_can() as a boolean switch to modify show_in_rest parameter behaviour:

function add_post_type() {

    $show_in_rest = current_user_can( 'read_cpt' ); //this will return true or false

    $args = array(
        [...]
        'public'                => false,
        'has_archive'           => false,
        'exclude_from_search'   => true,
        'publicly_queryable'    => false,
        'show_in_rest'          => $show_in_rest, //bool switch from current_user_can()
    );
    register_post_type( 'cpt', $args );
}
add_action( 'init', 'add_post_type' );

This way the custom post type is only shown in rest for users with the required capability.

0

Don't rely solely on hiding it.

Instead, return an error in the handler:

if (!current_user_can('read_addresses')) {
    return new WP_REST_Response('restricted', 403);
}

To hide it as well, filter the content of the hooks rest_index and rest_namespace_index.

0

Use the register_rest_route() function.

if( current_user_can( 'read_addresses' ) ) {
    register_rest_route( 'namespace/v1', 'cpt', array(
        'methods' => array( 'GET' ),
        'callback' => 'callback_function',
        'permission_callback' => 'permission_callback_function'
    ) );
}

Your callback_function would handle the request and return the response. The permissions_callback_function would check the user permissions and return an error if the user does not have the specified capabilities. In this case the permissions callback is probably not necessary, but it wouldn't hurt to have it in place just in case.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.