Join GitHub today
GitHub is home to over 40 million developers working together to host and review code, manage projects, and build software together.Sign up
Save private item attachments on protected folder #241
So here are the results of what I found so far as possible approaches:
Changing directory structure
First of all we thought it would be a good idea to change the uploads directory structure to better organize Tainacan items attachments and documents, so they dont get all mixed up with other uploads under the uploads and year and month folders...
However, it turns out this is not very easy to achieve.
The most used approach is to hook into the
But the problem is that, inside these hooks, and in any hook in
You could do this by getting the post_id from the http request (
So one way to achieve this would be not to use the default WordPress way of handling uploads... of course this comes with a huge downsize. For example, plugins that integrates with external storage services, like amazon s3, would not work out of the box.
There are basically 2 ways we could protect the files:
Create a folder for private files
We could create a separate folder to store private files, but:
Check permission on every upload before serve it
This would be an approach similar to this plugin: https://wordpress.org/plugins/private-files/
A .htacces file directs all traffic to php, that checks file permission.
But this is a performance killer...
An intermediate solution, if we managed to separate a folder for all uploads related to tainacan items, woud be to add this only to this folder, leaving regular WordPress uploads out of it. But still...
However, this is the easiest way to implement it right now.
Conclusion (so far)
We still have to think better on how to deal with this.
The only way to assure total control and security over the files seems to be not using WordPress native upload workflows.
This would give more security and control, but would make it more difficult for integrations. It's easy to think that Tainacan would go well together with plugins that save the files somewhere else, like amazon S3 or similar services, and this approach would break this.
The easiest way to do this right now is to direct all traffic to php and check permissions before serving static files, at a high performance cost... Maybe we could give it a try and look how fast we could make it...
Gave it a second try and a second thought.
Serving all files from the upload folder via php is just unacceptable. It could easily kill the web server.
I've created a feature branch (named feature/241) and made a proof of concept on changing the upload dir based on the post id. It works, but we will have to start attaching the document file to the Item. Here are few things we must do:
Then, the first approach is to upload files on a collection_id/item_id folder structure inside the uploads folder.
Finally we will protect the folder of private items or collections. In apache, we will do this by adding a
Let's see how it goes
ps - I was thinking on putting all the private files in a separated folder. Then we would only have to protect one folder. But Im dropping this idea for now, as this would require some background processes if we, for example, made a collection with thousands of items private and we had to move thousands of files around at once. I want to avoid that
Ok, at the end I think the implementation is fairly good, a bit different from the last comment.
How it works
Everytime an attachment or a document is uploaded to an item, the file is saved under a special directory inside the uploads folder. There is a base directory for all items files,
The URL for the files will always remain the plain strucutre, for example,
So if the item with ID
Since the URL and the folder in the filesystem don't match, this would cause a 404 error. But then tainacan will detect this is an attempt to access an item file and will look into the prefixed folders for it.
If it finds, it will check whether current user can read the item and then serve it for authorized users, or leave a 404 response for non authorized users.
Everytime you edit an item or a collection, or even bulk edit items, the folders will be renamed accordingly.
The base folder for items attachments can be changed setting the
The prefix for private folders can be changed setting the
Note: This constants must be setted in a fresh install. If they are changed after there are uploads, all the links will break...
Now you can add a rule to your
Even if a person manages to find out the real file path, with the prefixed folder name, he/she will not be able to access it, only via the clean URL that will pass permission check.
This is the basic difference from my last comment. One rule to rule them all. And it should work fine for nginx as well. :)
What is left to do