How to build a "private" website in Drupal
Drupal lets you build certain kinds of website very quickly. That's why it's in my toolset. Recently I was asked to do a site that was clearly a candidate for Organic Groups so I duly fired up drush and started building.
The website in question was a members-only website. Non-members would only be able to see a single page. The non-member-accessible page would have login and register forms and some other things. I'd built another site with similar requirements before. The previous site had no need to look pretty (it was functionally an intranet) so I just left it showing "Access denied" and the login form to all anonymous visitors.
This time, that would not be acceptable. The site needed to look professional to potential users and that meant a proper home page for anonymous users. I was surprised at how unintuitive this setup was.
My first attempt at a solution was to look at access control modules. Drupal ninjas please correct me if I've got this wrong, but this generally required giving anon users the core permission to see published content and then removing access to specific content types (or sets of content defined in other ways) through a contributed module. If any module in Drupal grants you a permission then no other can take it away but, under the hood, these contributed modules are defining new permissions (or permission-like things) and denying access if either the core system or their own system would dictate that.
This situation surprised me and mildly complicated the administration of the site. Unless you can make a new content types private by default then this situation needs careful attention because new content-types will be public and nodes of those types will be accessible to anonymous users until settings are changed. How often will this happen? Well, probably not often, but it still made me uncomfortable.
I posted in the Drupal forums about this issue, asking for solutions. I was somewhat reassured to realise that there was no "standard" solution to this and that my google-fu was not completely broken. WordFallz drew my attention to the Private module which would have been a pretty good solution. It adds some very simple UI to the "Publishing options" section of nodes and content-types, allowing the default privacy to be set. (Access to private content is an extra permission.) I'd already implemented a solution by the time I saw this, otherwise I would have defined an "Anon home page" content type to be public while everything else was private. I like the Private module a lot and have already used it on another site.
The solution I actually used was simple and complicated:
- I defined a custom page in code (using hook_menu() ) to be the logged-out home page.
- The logged-in home page was a regular node.
- I set the site default front page to be my custom logged-out home page.
- I used the Front page module to select the logged-in home page for authenticated users. Note: The Front page project's identifier is front (while the module name is front_page, *sigh*), not to be confused with the Frontpage module!
This is pretty simple because there are, after all, only four steps to do this. It's more complicated than it needs to be however because the logged-out home page is defined in code and you need to jump through a hoop or two if (like me) you need to have some user-editable content on that page.
Edit: Using a module that unconditionally redirects a user after login has a problem: The reset password workflow is broken. There is an unresolved issue about this for the Front page module. It surprised me a bit that (1) it took this long for me to get a report from a user about this problem and (2) that a module that does not allow for this could get installed on 19,000 sites.