Let's start this with a use case. Suppose you have a client, owning an insurance company, consisting of several more or less independent departments. Let's say car insurance, life insurance, health insurance and so on. Now, that client needs a website for his intranet, so employees can efficiently communicate with each other. One important aspect of office communication is collaboration in teams. For example, the life insurance team should be able to work out a plan for a new life insurance policy without the health insurance people snooping around in their work.
So far, no problem. The organic groups module fits this situation like a glove. However, sooner or later some team members will want to share files (e.g. excel statistics on car accidents or Scribus drafts for the new life insurance brochures). In theory, adding this feature is easy. Just add a new, CCK File Field enhanced content type and you are good to go. Whenever someone wants to upload something, s/he just creates a new node in the desired group with the file attached to it. The node is then protected by OG access permissions and only visible by group members. There is one catch though. OG access control (or any other access control mechanism) does not extend past nodes.
Suppose, a co-worker wants to share "cheap car insurance II.doc" and make sure, only members of the car insurance group have access to that file. After uploading, the node may be found as hxxp://intraweb.example.com/node/42 and be perfectly protected. the file itself however is stored as hxxp://intraweb.example.com/sites/default/files/shared/cheap_car_insurance_ii.doc and as such not protected at all. Everyone knowing the URL can request it and the webserver will happily serve the resource. Access control does not apply, since no program code is ever executed for direct file requests.
Ok, how can the problem be solved? CCK File Field actually supports access control, but of course, this requires the code to be booted in the first place and that only happens, when the download method is set to private under admin/settings/file-system and the file system path points to anywhere outside of the document root.
Setting the download method to private has a number of shortcomings, however:
- It's a huge performance killer. CSS and JS files can no longer be aggregated and each file request forces a full boot of the CMS.
- Not all modules work properly with private downloads. One example for this would be the color chooser of the theming dialog.
All in all, private downloads do not really offer a satisfying solution to the problem. There should be a way to have our cake and eat it too. In fact, there is now. Since I face that scenario (though my "client" in this matter is not actually an insurance company), I wrote a little add-on module to the CCK File Field, that will, with a bit of rewrite magic add a way to mix public and private file downloads. That is, the download method can stay public, but individual CCK File Fields can be made private. The module can be downloaded here. See included README.txt for details and instructions.