Allowing WPGraphQL to show unpublished authors in User Queries

Objective

The goal of this article is to make a non-authenticated GraphQL query for a User with no published content and to get the User returned in the response.

Like the following:

{
  users(where:{login:"UnpublishedAuthor"}) {
    nodes {
      id
      name
    }
  }
}
Screenshot of a Query for an unpublished author and the results showing the Unpublished Author data.

NOTE: To test these queries you will want to use a GraphQL client that is not Authenticated, such as GraphQL Playground or Altair. WPGraphiQL, the GraphiQL IDE built-in to WPGraphQL in the WordPress dashboard currently executes GraphQL queries as your authenticated user.

The Problem

WPGraphQL respects WordPress core access control rights. Meaning that data which is exposed publicly by WordPress core is exposed publicly in WPGraphQL, but data that is exposed only in the WordPress Dashboard is restricted by WPGraphQL to GraphQL requests made by authenticated users with proper capabilities to see the data.

In WordPress, users that have not published content are not public entities and WPGraphQL respects this.

This means by default, the same query as above would return empty results, because the “UnpublishedAuthor” user is not allowed to be seen by a public, non-authenticated GraphQL request.

Screenshot of a GraphQL Query or a user filtered by user login, showing no results.

In some cases, you might decide you want to show Users that don’t have published content in the results of your WPGraphQL Queries.

The Solution

The below snippets should help accomplish this.

Adjust the underlying WP_User_Query

When using WPGraphQL to query a connection (a list) of users, WPGraphQL sets an argument of 'has_published_posts' => true for the underlying WP_User_Query, meaning that the SQL query for a list of users will reduce the results to users that have published posts.

To adjust this, we can use the `graphql_connection_query_args` like so:

add_filter( 'graphql_connection_query_args', function( $query_args, $connection_resolver ) {

  if ( $connection_resolver instanceof \WPGraphQL\Data\Connection\UserConnectionResolver ) {
    unset( $query_args['has_published_posts'] );
  }

  return $query_args;

}, 10, 2 );

Filter the User Model to make all Users public

WPGraphQL has a Model Layer that centralizes the logic to determine if any given object, or fields of the object, should be allowed to be seen by the user requesting data.

The User Model prevents unpublished users from being seen by non-authenticated WPGraphQL requests.

To lift this restriction, we can use the following filter:

add_filter( 'graphql_object_visibility', function( $visibility, $model_name, $data, $owner, $current_user ) {

  // only apply our adjustments to the UserObject Model
  if ( 'UserObject' === $model_name ) {
    $visibility = 'public';
  }

  return $visibility;

}, 10, 5 );

Testing our Changes

Now that we’ve adjusted WPGraphQL to show all users to public GraphQL requests, we can use GraphiQL to test.

For the sake of testing, I created a new User with the name of “Unpublished Author” and will make a GraphQL Query for users, like so:

{
  users {
    nodes {
      id
      name
    }
  }
}

And with the above snippets in place, I’m now able to see the UnpublishedAuthor in my GraphQL query results.

Screenshot of a Query for an unpublished author and the results showing the Unpublished Author data.

Published by Jason Bahl

Jason is a Principal Software Engineer at WP Engine based in Denver, CO where he maintains WPGraphQL. When he's not writing code or evangelizing about GraphQL to the world, he enjoys escaping from escape rooms, playing soccer, board games and Fortnite.

Leave a comment

Your email address will not be published. Required fields are marked *