Blogs
Shortcut: If you "just" want to know how to make different distinct sites (read: communities or organizations) appear as just one site, continue below the reasoning.
Problem space
Permissions are a sensitive area in any application. Quite often requirement documents can give the impression that it's more important what an application must not allow than the actual value proposition. Try to balance "increased communication" with "very strictly controlled access" and you see what I mean.

The content on the marked pages should be editable only by dedicated (different) users This is not to say that those requirements are bogus - after all there are valid reasons to limit write access to various areas of the portal. However, such requirements should not lead to overly complex solutions. I'd like to go into more detail for one specific sample solution request(*): "Provide write access only for WebContent on a given set of pages of a site".
In Liferay we have sites (communities or organizations), pages and content - the content happens to be scoped to a site, as are all the permissions: Within a site users typically have the same permissions to all content.
Content can be shown on any number of pages on a site (or none at all). And the navigation shows the pages for only one site. For this reason, the solution given is not trivial (and not natural) to implement. But you'll see that the underlying hidden Feature Request can be easy to implement.
Solutions
1. Organizational: Assume the best, blame the rest
My first, simplest and favourite answer to this kind of request is: "Try to go with organizational (nontechnical) permissions - assume your authors are responsible people and know what they should and shouldn't change". This is underwritten by the possibility to audit: You can see who edited a given article - and if a change is not appropriate, you can hold them responsible for their changes. If this is not enough, you might want to consider workflow. You might be using workflow already, so you already have someone double checking each article. My assumption is that this level of control is adequate for a lot of applications out there.
But...
But then, there still are some conditions in which this does absolutely not apply. I'm seeing two different solutions proposed for these remaining applications: One requires lots of work, is almost impossible to get completely correct and will make upgrades a pain. The other is simple and imposes a bit of thinking or structuring, but has no notable effect on upgrading. Guess which one I prefer.
2. Custom Permission checking (You don't want this)
Naturally, many think about customizing Liferay's permission checking code to take the new criteria into account.
For many reasons this is hard:
- The permission checker itself is a very abstract component when you want to extend it with code knowing about WebContent and the currently displayed page.
- You need to take into account that this might break access to content through the API
- How do you handle editing of articles that are not (yet) positioned on any page?
- As you'll be working somewhere in the guts of Liferay, it's easy to break something completely unrelated.
- Think about upgrading to the next service pack or major version - prepare to do everything again.
- Oh - and think about the nightmare of a UI that you'd have to create to configure who has access to what content.
Conclusion: You most likely do not want to change the internal permission checking code.
3. Customize the presentation of the content (try this)
This is the easy route: For your application you know what kind of different content you have. Divide it up in communities or organizations (referred to as sites). This maps neatly to how Liferay allows you to provide permissions to users.
Done.
Well - almost.
You still want to display all the pages as if they were still in the same site. You can do that easily: Your theme is already tailored to your needs, you can use it to handle this aspect as well. Just add the following templates. Out of habit I'm using velocity here, the two different sites that are combined here are "public", "researchdevelopment" and "production".
(Edit: As Erik commented, I've made a debugging/copying mistake writing this post. I also fixed navigation.vm to show only the toplevel pages on the top level. The code is now corrected, version 2)
navigation.vm
#set ($layoutLS = $serviceLocator.findService("com.liferay.portal.service.LayoutLocalService"))
#set ($groupService = $serviceLocator.findService("com.liferay.portal.service.GroupService"))
<nav class="$nav_css_class" id="navigation">
<h1>
<span>#language("navigation")</span>
</h1>
<ul>
#set ($current_group = $groupService.getGroup($company_id,"public"))
#set ($current_nav_items = $layoutLS.getLayouts($current_group.getGroupId(), false, 0))
#parse ("$full_templates_path/navigation_list.vm")
#set ($current_group = $groupService.getGroup($company_id,"researchdevelopment"))
#set ($current_nav_items = $layoutLS.getLayouts($current_group.getGroupId(), false, 0))
#parse ("$full_templates_path/navigation_list.vm")
#set ($current_group = $groupService.getGroup($company_id,"production"))
#set ($current_nav_items = $layoutLS.getLayouts($current_group.getGroupId(), false, 0))
#parse ("$full_templates_path/navigation_list.vm")
</ul>
</nav>
navigation_list.vm
#foreach ($nav_item in $current_nav_items)
#if($current_group.getGroupId() == $scopeGroupId && $nav_item.getLayoutId() == $layout.getLayoutId())
<li class="selected">
#else
<li>
#end
<a href="/web$current_group.getFriendlyURL()$nav_item.getFriendlyURL()">
<span>$nav_item.getName()</span>
</a>
#if ($nav_item.hasChildren())
<ul class="child-menu">
#foreach ($nav_child in $nav_item.getChildren())
#if($current_group.getGroupId() == $scopeGroupId && $nav_child.getLayoutId() == $layout.getLayoutId())
<li class="selected">
#else
<li>
#end
<a href="/web$current_group.getFriendlyURL()$nav_child.getFriendlyURL()">
$nav_child.getName()
</a>
</li>
#end
</ul>
#end
</li>
#end
What's the drawback?
Well - it's kind of hardcoded content. But on the other hand: You typically modify your theme - if you have one plugin deployed, it's most likely a theme. The theme contains everything that makes your site look like yours. I find that this is the perfect place to hardcode something that makes the site appear as yours.
Is there more?
Sure. Another solution to the same problem - without changing the theme - will be part of my symposium presentations at the upcoming US-Westcoast and European Symposiums. I hope you don't mind the teaser and shameless plug ;-)
(*) Some vocabulary definition might help, namely "Feature Request" vs. "Solution Request": A Feature Request typically describes a usecase that a system can cover once it's implemented. It typically states the problem space so that it's easy to check if the proposed business case is covered. In contrast to this, I refer to a Solution Request as what should be implemented (and how) without stating the original problem. The problem with this is that it's not easy to see if the proposed solution is an appropriate answer to the underlying problem. In fact, typically it's impossible.

