Specify the level of access to different pages at the time of user creation

I created something along these lines for a client a few months ago. I couldn’t find anything that did what I needed at the time. It will require some custom code (nothing too crazy). I will try give a quick breakdown of how I did it, to help give you an overview of what you need to do, and things you need to consider.

I also created user groups to collectively manage a group’s access rather than individual users, but you can skip that part and just focus on the users without groups.

Important: I decided to break the access level for content on the site into 3 tiers, public, logged-in, and private. So in my management interface I would specify each page being one of these three tiers. So now I can make for example the Home page and about page accessible for anyone by setting it to public, and then the contact page only accessible to anyone who is logged in, and then finally maybe a store page only accessible to a certain group of users.


//Database
I created 3 tables:

  • wp_user_groups — This is the user groups, just had id, slug and title, but the slug and title were just for management purposes.

  • wp_user_group_access — This is a pivot table (group_id, post_id) where you link group ids to post_ids (post_ids = page_ids).

  • wp_user_user_group — Another pivot talbe (group_id, user_id) to link users to groups. Again if you don’t intend to use groups you can skip straight to just doing a user access where you assign the access to post_ids directly to users.

  • Page access levels — At the time I decided to store these in wp_options arrays containing the ids of the posts instead, so I had 3 wp_options, access_posts_public, access_posts_logged_in, and access_posts_private. You can still use a table, but in my case a wp_option is a bit simpler to manage and works well.


//Management UI (wp-admin page)

You need to create a small management interface where you can create groups, add users to groups, and assign page/post access to groups.


//Authentication

Now you need to check if the user is allowed to access the requested resource. For the (wp)functions that I collectively used, I found the template_redirect action hook to work best for this.

You should do something a little cleaner than this, like set up an authentication class, but essentially in you functions.php file add:

add_action( 'template_redirect', custom_authentication );
function custom_authentication() {
  //Authentication checks
}

Then the order of the authentication checks to make it as simple as possible:

  • First check if the page/post id is in the access_posts_public wp_option, if it is, return (end) the function.
  • Check if the user is logged in, if not redirect them to a login or other page.
  • Check if the user is a admin, if they are we can just return the function as you probably don’t want to block admins from viewing pages.
  • Now the user is logged in, check if the page is in the access_posts_logged_in wp_option, if it is, return (end) the function.
  • If we reach this point then the post/page is set to private. Check then if the user is in a group that has access to this post/page.