1

I'm trying to limit the content that is returned via REST API routes to only contain content published by the current logged in user. I'm trying to do this using pre_get_posts which works fine when in the admin view but the REST API output is still including all posts.

In this case I am trying to do it via the REST route for a custom post type, so the route is /wp-json/wp/v2/todos/. Accessing this route works fine by default and returns all posts, but with my pre_get_posts code in place it still always returns all posts. Here is my pre_get_posts code:

function only_users_todos( $query ) {
    global $user_ID;
    $query->set( 'author', $user_ID );
    return $query;
}
add_filter( 'pre_get_posts', 'only_users_todos' );

Am I missing something obvious here, or does pre_get_posts just not get called for REST API requests?

  • Are you sure that $user_ID is not empty? Have you tried get_current_user_id() instead? – czerspalace Mar 15 at 18:33
  • Thanks, the issue is related to not getting the current user id, see Jacob's response and comments below. – Rick Curran Mar 18 at 10:58
2

Yes, pre_get_posts runs for REST API requests. Your issue is likely that your request is not properly authenticated, so $user_ID is not set. To allow the REST API to recognise the logged-in user you need to send the wp_rest nonce with the request. You can create this with wp_create_nonce( 'wp_rest' ) and send it with the request as the X-WP-Nonce header. This is documented in more detail in the developer handbook.

It's not relevant to your original question, but the code in your question will apply to all queries. This includes posts, pages, menus etc. So if you won't want that behaviour you need to add some sort of check so that your code only applies to certain queries. For example:

function only_users_todos( $query ) {
    if ( $query->get( 'post_type' ) === 'todo' ) {
        $query->set( 'author', get_current_user_id() );
    }
}
add_action( 'pre_get_posts', 'only_users_todos' );

Also, pre_get_posts is an action, not a filter, so you don't need to return $query.

  • Thanks for confirming that pre_get_posts runs for REST API requests, I figured that must be the case but just wanted to confirm. However, the problem I'm trying to solve though is not that I don't get a response (I am properly authenticated using a nonce in the way that you've indicated), but the problem is that I only ever get all posts via the REST API so my pre_get_posts code doesn't seem to have any effect. As you say, the code I've put in place should affect all queries, so it's another reason why it's strange that it doesn't seem to be affecting my REST API request. – Rick Curran Mar 18 at 9:35
  • I explained that. You’re filter is being applied, but the logic isn’t doing anything because it depends on the current user. The current user is not available if you don’t authenticate the request with a nonce, as I described. – Jacob Peattie Mar 18 at 10:05
  • Thanks, digging into it further I can see you are correct. I've actually got other code in place to not serve up any REST API responses unless you are logged in so this was misleading me to think I should be authenticated, but doing a quick test using the is_user_logged_in() condition indeed confirms that the response I'm getting is because it's not getting the current user ID. To be honest, I'm still a little confused as obviously it knows I'm logged in to be able to respond with the REST response at all, but just doesn't know I'm logged in to be able to apply it to pre_get_posts. – Rick Curran Mar 18 at 10:57
  • Getting posts doesn't require the user to be logged in. – Jacob Peattie Mar 18 at 14:03
  • Thanks, I've managed to request the posts as the authenticated user now and correctly get only their posts. I've actually blocked access to the main un-authenticated end-point so the only way you can view these 'todos' posts is if you're logged in. – Rick Curran Mar 19 at 8:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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