• Resolved Giulio

    (@ferocious)


    Hello, what I’m looking to do is hide CPT from user to user. Currently any user can post and edit any CPT from his edit page, but I’d like that user can only edit/delete/post its contents. I have added a new role with add_role() then I gave it these capabilities via register_post_type() and add_cap() functions:

    publish_products,
    edit_products,
    delete_products,
    delete_product,
    edit_product,
    read_product

    If user visits the edit page edit.php?post_type=my_product it lists the CPTs of all users and this is not good.

Viewing 4 replies - 1 through 4 (of 4 total)
  • Moderator bcworkz

    (@bcworkz)

    If ‘edit_others_products’ is a capability of the CPT and the role of most users is lacking this, they cannot edit other’s CPTs, only their own. But they can still see other’s posts.

    You can manage what posts show up in the CPT list table with ‘pre_get_posts’ action just like any other WP_Query. Your callback would need to discern a posts list query from all other queries in order to know when to restrict the query by post author. This will not stop someone from requesting an individual post of someone else by ID or slug, but if they cannot see the full list it makes such a request more difficult to construct.

    Thread Starter Giulio

    (@ferocious)

    Thank you very much bcworkz!
    Could you tell me if the following code is safe for production?

    add_action( 'load-edit.php', 'm_show_posts' );
    
    function m_show_posts() {
    add_action( 'pre_get_posts', function( $query ) {
    		$user_id = get_current_user_id();
    		if ( is_post_type_archive( 'm_product' ) && $query->is_main_query() ) {
    			$query->set( 'author', $user_id );
    		}
    } );

    How could I stop someone from requesting an individual post of someone else?

    Moderator bcworkz

    (@bcworkz)

    I’m not aware of a ‘load-edit.php’ action, but if it works on your system then it should be OK. I’m not too sure which hook in a default installation would be good to insure the ‘pre_get_posts’ action is only added for list table queries. Maybe ‘edit_posts_per_page’? I think it’s still early enough. I’m not too sure it wouldn’t fire under other situations, you’d need to do some testing. The filter is for another purpose, but it can still serve to only add ‘pre_get_posts’ when needed. The post type is passed to your callback, so you can at least only add ‘pre_get_posts’ for the proper post type.

    The other thing I see is minor. Using is_post_type_archive() in the conditional is probably fine, but an improvement would be to use the equivalent method of the passed query: $query->is_post_type_archive('m_product')

    Come to think of it though, $query->is_post_type_archive() is to check if the query is for the post type’s archive page. I don’t know if it returns true for a lists table query as well. If you’ve tested this and it works, then fine. It may not be necessary at all if ‘load-edit.php’ or ‘edit_posts_per_page’ is specific enough.

    That does bring up the issue of a user requesting the archive page for the post type. The solution for this is like that for an individual page. You can modify the templates responsible to only output posts belonging to the user. The query may return posts of other users, but it is the loop that does the output. Code in the loop so only the user’s posts are output will address this possible avenue of accessing other’s posts.

    Thread Starter Giulio

    (@ferocious)

    Thank you!

Viewing 4 replies - 1 through 4 (of 4 total)
  • The topic ‘Apropos capabilities’ is closed to new replies.