Case study: Setting video file access based on Ubercart orders

One thing that's really nice about working on your own Drupal projects is that you get to share what you're working on (no NDAs, woot!). This particular project (Build a Module.com) is a video tutorial site for newer Drupal developers. For a while, I had a single product offering, but feedback made me realize that people like options. So, I decided to to offer single video purchases as well as 'collections,' or groups of videos bundled up into a single product. I also needed to make sure that customers had the right permissions set on files depending on their purchases.

Here's a video outlining the solution I came up with. Scroll down below the video for further details.

About the flow

I have 3 node types:

  1. Videos - Contains description and video file in a file field
  2. Single Video Product - Is an Ubercart product with a node reference CCK field pointing to a single video
  3. Collection Product - Another Ubercart product, but this one has a node reference CCK field that points to a number of videos

I didn't realize that a node reference field could point to multiple nodes before a fellow Drupalista pointed it out to me. Eesh! I really could have used that info a year ago.

So here's the flow:

  1. A user adds a Single Video Product or a collection to their cart
  2. They check out and complete the purchase
  3. They visit a video page
  4. A custom function checks against their orders to see if they have access to the video. If they do, they're in.

The function used in step 4 uses several queries to determine access. The queries check for the following:

  1. Is the product free? If so, show the video.
  2. Has the user purchased a product that includes the video file that this Single Video Product type points to?
  3. Same check for a Collection Product type
  4. If there is no product for the video, then give access (some videos, like the intro video, don't have an associated product)

In the hook_file_download, the same function is called, but I first have to figure out what node the file belongs to. In Drupal 6, hook_file_download only supplies you with the name of the file. No node associations or anything, so you have to connect the dots with your own query. I think the reasoning is that a file can belong to multiple nodes, but since my workflow doesn't allow that, it's not an issue.

There are some good things about this approach, such as when files change in the nodes (i.e. you upload a video with corrections), even though there is a new file name, the node association will remain the same and access will be granted.

For a while I was using a module called File Access, which allows you to set granular permissions for each file based on user or role, but because I would have to build a connector action between a purchase and the access, and then respond when new files are uploaded, I figured I would keep it simpler and just cross-reference the orders instead. The downside is that if my products change, so will access. Also, using File Access would enable access based on field, rather than on node. So, if I have two different versions of a file on the node (iPod version and full-size) and wanted to sell them separately, I would need something more complex.

Part of the reason I'm putting this info out there is to get feedback and see if a module that handles this type of access and setup would be a welcome addition to Drupal contrib, so feel free to drop me some feedback below.



Comments

You can use the flag module:

1) when a user purchases a product in Ubercart use Conditional actions (CA module) to flag the product node.
2) Use Flag API to check if the node was flagged by the user

  // Check if user has access to the full movie
  $flag = flag_get_flag('video_access');

  return $flag->is_flagged($node->nid);

flag API -- http://drupal.org/node/305086

p.s. Dude, your CAPTCH is almost impossible! ;)

Interesting idea. The Flag module could take care of one aspect of tracking, but seems like it would work similarly to the File Access module and be a middle-man between the order and file access. That kind of dissociation would be good in some cases, but another module would still be needed to implement hook_file_download.

Thanks for bringing up Flag, I need to explore the different methods for using the module. Seems like it could replace many custom database tables that exist just to associate one piece of data with another.

Also, sorry about the CAPTCHA. I got really aggressive yesterday after getting a bunch of spam on one of my posts. After looking at the output again, I have to give you some major props because man, that *was* impossible. I've toned it down and it should be a little easier next time, if it didn't completely break your spirit. :)

Glad I found this on Planet Drupal. I am in the middle of setting up paid video access for http://realitysandwich.com and this may prove to be very helpful.

We are planning to offer premium subscriptions which gives users access to all premium videos, but would also like to offer one-off purchasing of single videos or collections for those who don't want to purchase a subscription. Do you have any thoughts on a hybrid system that handles subscriptions (which I think should be role-based) and single-purchase as well?

Also would be interested to know what you're using to upload, store, and distribute the videos. I'm working with Media Mover, S3, and the Longtail Player.

Thanks again!

Hi Andy,

I'm actually using a hybrid system like that right now because I started out with role-based purchases and moved to this new system. So, if you pause at just the right place in the video, you can can see me doing a role check.

My implementation is a little more complex than yours would need to be, though. You should be able to just create a role-assigning subscription product and check for it in hook_file_download. I went one more step and created a 'collection' product which contains references to all the videos I want the subscriber to have access to, since it won't be every video on the site.

My infrastructure is pretty simple. I use the Flowplayer module as the inline player, pull the videos straight from my hosting account and use a CCK filefiled to upload the videos. This won't scale very well, so eventually I'll need to explore using Amazon's services. Thanks for mentioning Media Mover, that looks like an awesome module that could be very helpful with integrating other players and S3.

Cheers!

Also in the process of setting up something similair.
I don't want node access restrictions, but file level permissions, since i also want to add the option for a free preview video within the same node.

I'm a php programmer, but really really new to drupal and figuring out all these function implementations and how they are weight...it willbe a steep learning curve.

I might actually consider to outsource it, maybe if we'd all chip in we could have a complete video file access module with ubercart and S3 coded by some team in india :P