Secure File Field For Orchard CMS

Today I published a complete version of the CloudConstruct.SecureFileField module to the Orchard gallery. After having some issues with my Version 1.0, 1.1, and 1.2...1.3 is the working version. I also broke the Orchard Gallery somehow as well. Sorry guys!

I developed this module because natively there was no way to support securing a file from a user by content item permissions. A project I was working on required users with the "Researcher" role to have access to marketing documents that "Anonymous" users could not. Secondly, this Orchard CMS project was to be hosted in Azure so durable file storage was not an option. The goal was to have a user attach a file to a content type via an Orchard field and then upload it to a location outside of the Media directory so permissions could be enforced.

Installation & Setup

First of you need to install the module from the Orchard gallery via the link above. The module requires Orchard.ContentPermissions but doe not require you to set any permissions if you do not want to.

After installing the module you can create a new content type or attach your new field type to an existing one.

After you attach the field you need to make sure you configure the settings for your new SecureFileField. The main option you want to look at it where you want to store the file. You can store it locally to a directory like "C:\temp" or you may choose to utilize remote Windows Azure BLOB storage. Azure BLOB storage is good for when you are running in Azure because your file storage is not durable and can be wiped out at anytime. Lastly, if you choose Azure you need to decide how you want to serve the file to the user. Thanks to Bill Wilder for suggesting using Shared Access Signatures (SAS) as an option to serve the files to users. Streaming the file down from BLOB storage and then to the user will take some extra time as opposed to opening up a Shared Access Signature (SAS) on the file for a certain amount of time. If you want to use SAS then just specify an expiration limit greater than zero and the module will generate a SAS url for your client.

NOTE : Be sure to follow the directions on each field so your file can be properly saved and retrieved.

Storage & Retrieval 

Now that you have your content type configured with your Secure File field you can choose to add Content Permissions on your type as well. If not the file will just be available along with the content item to any user. If you choose to add permissions to the content item then the ability to view the file will also be determined by the permissions assigned for its content item. Most of the logic for serving the file based on permissions came from the Orchard.ContentPermissions module. I just duplicated it there.

When you bring up your content item it should now have a field for you to upload a file. Go ahead and try and upload a file and verify that it is saved to the location you specified.

The last step is to verify your file is now available on the front end by browsing to your content item. Depending on your retrieval method you will get a SAS url or just a link to a controller that will verify permissions for you. NOTE : Keep in mind the SAS Url will not run the permissions on the request of the file but it assumes anyone with the URL has gotten it via the proper sources. If you chose to stream the file, it checks permissions on the request as well because it goes through our controller. This is done because if someone tried to circumvent the page and just access the item via url it would be verified as well.

Important Notes

1. Right now the file types it works for are "text/plain" and ""application/pdf". If you want to serve more file types you can add those to the /Providers/StorageFile.cs document. I will work to make this better in the next release.

2. Make sure you create your secure directory first and do not add a trailing space to your secure directory name in the configuration screen. I have not tested it in doing that, so use a location like "C:\temp" and not "C:\temp\".

3. For your Azure BLOB endpoint be sure to make it a private containter and set it up before using the module. In the next version I will add code to create the container on the fly. Lastly, for the endpoint keep the trailing "/" on the location.

4. I did not have time to make this super clean, but any question feel free to comment here and I will do my best to help!

About the Author:

Arra Derderian serves as the President and as a Lead Technical Architect for Cloud Construct. As a founder at Cloud Construct, Arra is involved in all levels of the business from new project engagements, project planning, and development.

He also serves as the founder of the Boston Orchard CMS User Group and is a member of the Windows Azure Insiders group.

Arra graduated from Northeastern University School with a Bachelor of Science degree in Computer Science.