This posting is a followup to http://drupal.org/node/106565
The current situation is that:
through admin/settings/file the admin may:
- set the "files" folder to be not accessible over the web and
- force all downloads to go through system/files which is served by system.module's file_download() . The combination of these gives the possibility of controlling access to downloads by role.
This feature is presented to admin as a site-wide feature - however there is no site-wide mechanism for enforcing
privacy.
- upload.module enforces "view uploaded files" permission by role for files that it knows about
- imce.module completely breaks this mechanism by granting access to uploaded files without checking permissions
Now - you could say that imce.module has a bug in it. It "should" check permissions. But if the meaning of "private" is determined on a contrib module by contrib module basis - there will be a profusion of permissions which may contradict each other.
My conclusion is that the access permissions for a site-wide a private filesystem should not have been left up to imce.module in the first place.
System.module serves up the private files. It provides the a simple place to enforce access control by role for private files.
It may be a good idea as part of this change to remove "view uploaded files" permission from upload.module since there should be a single point of control.
I propose the following small patch to system.module
/**
* Implementation of hook_perm().
*/
function system_perm() {
return array('administer site configuration', 'access administration pages', 'select different theme','download private files');
}
/**
* Implementation of hook_file_download().
*
* Ensure that only authenticated users can access file downloads.
*/
function system_file_download($file) {
if (!user_access('download private files')) {
return array(-1);
}
}
Comments
So, you want an easy way to
So, you want an easy way to allow user roles to download all files or nothing, and not specific files?
Figuring out what "private" means
The core does not define any meaning to "Private filesystem", but system.module is the gatekeeper module for the "Private Filesystem" and is the one effective choke-point for implementing privacy for file download.
I am asking that as a minimum the system.module offers a way of making all files private by user role.
If that is available, the core then offers a concrete meaning for "privacy" of the filesystem.
This is not a limitation. An admin can tell system.module (via the proposed 'download private files' permission) to make all files available to all roles then use upload.module or imce.module (or any module that implements hook.file_download() to make finer grained permissions.
At the present time, core uses the term "private filesystem" while offering no definition and no admin-level mechanism for enforcing privacy.
Thanks for your help.
David
...
it can. You have to make the path for the files directory outside of your web root. so instead of putting it in files you would make the path /tmp/files and makje sure that the web server had access to that directory. Then people would not be able to sitename.com/files/guessfilename.zip or similar.
-Steven Peck
---------
Test site, always start with a test site.
Drupal Best Practices Guide -|- Black Mountain
-Steven Peck
---------
Test site, always start with a test site.
Drupal Best Practices Guide
...
Thanks for the feedback, here is why core does not define this effectively.
At the present time, the definition of "private" is left up to contrib modules. For example - changing files to /tmp/files, turning on the private filesystem and then installing imce.module means that all files will be downloaded for everyone.
All that has happened is that the url has changed from /files to /system/files From my perspective, a change to the URL does not make a private file system.
So - is the problem with imce.module for not having its own download permissions?
The problem is that core offers no way of defining what private means - it is entirely up to other modules.
My proposed change is simple and addresses the problem at the one point of control for all requests to the private files system (ie requests to "system/files".
One permission implemented by system.module in a half dozen lines of code gives clear definition of "private".
Thanks for your consideration.
David
A module can always grab
A module can always grab private files from the file system by not using a _file_download at all. The same way it can grab any restricted content straight from the database.
There is currently a granular access control system by file and user role, which can be used by access control code in modules.
The feature you are asking is one more permission to shut up all file downloads for certain roles, to accommodate modules which don't do any access control. But with the current way file management works (either "public method" or "private method" exclusively) this feature's usefulness is limited, because most people want to display at least some files or images to most user roles.
By the way, have you tested your code to see what it actually does?
Is this by design?
Thanks for your feedback.
Are you saying that the present behavior is "by design"?
I understand that a module may subvert any drupal security. However my concern is about urls served by system.module for "private" files.
At the moment, the only privacy difference between the public file system and the private file system when imce.module is running is that the url changes from files to system/files .
The system.module which serves private files does not offer any definition of "private".
I have implemented the code in a module of mine - it works well to prevent any system/files access for anonymous users. Your further feedback on the quality of the code is welcome.
David
What is design and what is
What is design and what is coincidence... this is a big question.
Your suggestion is similar to the "access content" permission with which anonymous users can be denied access to all nodes. In my opinion that one too should break up to particular content types for better control options. You do have a point that there is no easy option to completely shut out some user roles from all file access in the same way that you can shut them out from viewing any content at all. Some may need it.
Now I am going to digress.
File management is not one of Drupal's strong points yet, and there are many discussions and some work on how the file system should be: Taking advantage of the node system facilities or making it easy to slap files on disk? Or both?
About the meaning of "private downloads". Perhaps a better name would have been "controlled downloads". On the surface, it just changes the url to /system/files. But it also makes it possible for modules to implement file access control. You already mentioned how:
1. The upload module provides a generic access permissions for uploaded files by role. Personally I have never found this useful, but it is there. Other modules could easily do the same.
2. Individual files are associated with the node where they were uploaded. With a node access module you can easily deny access to individual files or to groups of files by denying access to the nodes themselves or to their categories. The /system/files url will just stop working for some user roles.
I find (2) very useful, and it is an important reason why I stick with modules which use the node system facilities for the files. There are also a few nice modules which use a "slap the files on disk" model. Apparently they can't take advantage of (2) until they implement their own or, even better, until a wider file API becomes available.
I don't disagree with your suggestion. I just don't find it practically important.
Using mod_rewrite with a PHP Handler might resolve this issue
I think I may have another way of confronting this issue, which should fix the imce issue without any hacks to core. It may also offer a way to deal with the course-grained access control granted by the public or private file setting. It involves using mod_rewrite and a php filehandler. I'll start with the use case:
One my clients required a method for protecting uploaded files using the access rights from Organic Groups. There were two requirements: 1) only users who were members of a group should be able to download a file that was attached to a protected node, and 2) users should be able to make any node and their attached files public along with all the documents attached to that node, even to anonymous users. These requirements made it impossible to use the private file setting (anonymous users can't see the /system/files/ directory), and forced me to find a way to protect files in the public files/ directory.
The solution was to use add a RewriteRule to the Drupal .htaccess file that forwarded any request for a URL beneath files/ to a PHP handler, which determines if the user has permission to download the file. Since mod_rewrite happens underneath IMCE, my untested guess is that it would prevent an unauthorized user from loading the file, even through IMCE. It also preserves the existing node access functions, without any core hacks (well, except the .htaccess files at root and in the files/ directory.).
The post explaining this tentative solution is here: http://drupal.org/node/116843. Your thoughts?