14 Commits

Author SHA1 Message Date
Jeff Dutil
7dabf1a520 Support Spree 1.3.x, add default unauthorized page, and organize locales. 2013-03-10 09:46:06 -04:00
Michael Bianco
52e7009c17 Running tests, and fixing breaking changes, for 1.2.3 2013-03-10 09:35:48 -04:00
Michael Bianco
8d44a25199 Note about improvement to create_digital_links 2013-03-10 09:35:48 -04:00
Michael Bianco
e6f8d6b4cc Merge pull request #35 from nitsujri/master
Fix for digital_controller throwing an error with unavailable.html.erb
2013-03-10 06:29:03 -07:00
Justin Louie
1d9fab3942 Fixing controller for current_order bug
unavailable.html.erb throws an error missing current_order

https://groups.google.com/forum/?fromgroups=#!topic/spree-user/mbEVVManQY8
2013-03-10 14:08:04 +08:00
Michael Bianco
f6d5812379 Merge pull request #32 from jdutil/patch-1
Fix README link.
2013-02-12 13:06:25 -08:00
Jeff Dutil
e2f33cd006 Fix README link.
Also add shell syntax highlighting.
2013-02-09 14:01:39 -05:00
Michael Bianco
9360c63503 Fixing deface name typo 2013-01-28 10:01:39 -05:00
Dave Mitchell
b381ede8e1 Convert 1.9 to 1.8 syntax. Fixes #23 2013-01-08 13:41:07 -05:00
Michael Bianco
37fe465dd9 Updating documentation. Adding nginx send_file info 2012-11-06 11:34:28 -05:00
Michael Bianco
23317eb0fb Adding button to order admin to reset digital downloads
* Resets expire time
* Resets download count
2012-11-01 17:36:47 -04:00
Michael Bianco
4dc2d9d54f Minor improvement to digital factory 2012-10-29 13:05:35 -04:00
Michael Bianco
446a23ce3a Adding Spree::Order#reset_digital_links! to ease in handling customer support
Hope to add this as a button to the admin soon.
2012-10-29 13:04:39 -04:00
Michael Bianco
fdd8536b5b Tests passing on 1.2 2012-10-29 12:55:37 -04:00
18 changed files with 231 additions and 134 deletions

View File

@@ -9,4 +9,4 @@ group :test do
end
end
gem 'spree', '~> 1.1.3'
gem 'spree', '~> 1.3.2'

View File

@@ -1,98 +0,0 @@
h1. Spree Digital
This is a spree extension to enable downloadable products. The design goal is to keep it robust. It should survive future spree versions out of the box.
The master branch is compatible with Spree 1.1.x, <= 1.0 versions are referenced in the Versionfile.
The idea is simple. You attach a file to a Product (or a Variant of this Product) and when people buy it, they will receive a link via email where they can download it once. There are a few assumptions that spree_digital (currently) makes and it's important to be aware of them.
* The table structure of spree_core is not touched. Spree_digital lives parallel to spree_core and does not do any changes to your existing database, except adding two new tables.
* The download links will be sent via email in the order confirmation (or "resend" from the admin section). The links do *not* appear in the order "overview" that the customer sees.
* There should only be "live" payments. Once the order is checked-out, the download links will immediately be sent (i.e. in the order confirmation).
* You should create a ShippingMethod based on the Digital Delivery calculator type. The default cost for digital delivery is 0, but you can define a flat rate (creating a per-item digital delivery fee would be possible as well).
* One may buy several items of the same digital product in one cart. The customer will simply receive several links by doing so. This allows customer's to legally purchase multiple copies of the same product and maybe give one away to a friend.
* The links will only work 3 times (but we tell the customer that it works only once). After 24 hours the links are deactivated. This should keep you reasonably free from complaints of people who are not capable of appropriately clicking on a link. They can try a whole day long, 3 times per link. The file should really be downloadable for weird customers. I understand that this is a little bit security by obscurity, but it's better than other solutions that I've seen. The number of clicks and days the links are valid for is customizable via preferences.
* The file @views/order_mailer/confirm_email.text.erb@ is the only thing that should need customization. But since I assume you do that anyway, it doesn't hurt to do it when you're using spree_digital. The reason is that the download links are added to the confirmation email to the customer. "http://github.com/iloveitaly/spree-html-email":http://github.com/iloveitaly/spree-html-email also supports spree_digital.
* A purchased product can be downloaded even if you disable the product immediately. You would have to remove the attached file in your admin section to prevent people from downloading purchased products.
* File are uploaded to @rails_root/private@. Make sure it's symlinked in case you're using Capistrano.
* You must add a views/spree/digitals/unauthorized.html.erb file to present an error message to the user if they exceed the download / days limit
* We use send_file to send the files on download. Yes, it goes through the entire stack right now.
h2. Installation
I assume that you already have a Rails 3 Spree application up and running. If not, the "Spree Documentation":http://spreecommerce.com/documentation will help you getting started.
To make use of @digital_spree@, you need to add this line to your @Gemfile@:
<pre>
gem 'spree_digital', :git => 'git://github.com/funkensturm/spree_digital.git', :branch => 'master'
</pre>
The following terminal commands will copy the migration files to the corresponding directory in your Rails application and apply the migrations to your database.
<pre>
rake spree_digital:install:migrations
rake db:migrate
</pre>
This should be all there is to do.
h3. Important!
You should create a ShippingMethod based on the Digital Delivery calculator type. It will be detected by spree_digital. Otherwise your customer will be forced to choose something like "UPS" even if they purchase only downloadable products.
h2. Usage
...
h1. Developer Section
h3. Table Diagram
<img src="http://github.com/funkensturm/spree_digital/raw/master/doc/tables.png">
h3. Installation (for Developers)
Get the spree framework and spree_digital extension for it:
<pre>
git clone git://github.com/spree/spree.git
git clone git://github.com/funkensturm/spree_digital
</pre>
Go into the spree directory and run the bundle command:
<pre>
cd spree
bundle install
</pre>
Go into the spree_digital directory and do the same:
NOTE: At this point you may need to uncomment the stuff in the @Gemfile@ before you can start developing and testing!
<pre>
cd spree_digital
bundle install
</pre>
Bring up the test application (you only need to do this whenever you fiddle around with the migrations) and then you can run the tests as you please.
<pre>
rake test_app
rake spec
</pre>
This link may be very helpful to you: "http://github.com/spree/spree":http://github.com/spree/spree
h3. Authors
* "iloveitaly":http://github.com/iloveitaly/
* "funkensturm":http://github.com/funkensturm
h3. License
Copyright (c) 2011 funkensturm.
Released under the MIT License
See "http://github.com/funkensturm/spree_digital/blob/master/LICENSE":LICENSE

View File

@@ -1,4 +1,5 @@
"0.7.x" => { :ref => "eddaea63959586d123007cbca3be5bf9c5edb1a7" }
"1.0.x" => { :ref => "a8c27750ef1cf9d0ad1a2a6ebe33307da900a5c1" }
"1.1.x" => { :branch => "1-1-stable" }
"1.2.x" => { :branch => "master" }
"1.2.x" => { :ref => "9360c635039aaeeee18026b830aa96cc7587cd0d" }
"1.3.x" => { :branch => "master" }

View File

@@ -1,6 +1,6 @@
module Spree
class Admin::DigitalsController < Spree::Admin::ResourceController
belongs_to "spree/product", find_by: :permalink
belongs_to "spree/product", :find_by => :permalink
protected
def location_after_save

View File

@@ -0,0 +1,7 @@
Spree::Admin::OrdersController.class_eval do
def reset_digitals
@order.reset_digital_links!
flash[:notice] = t(:downloads_reset)
redirect_to admin_order_url(@order)
end
end

View File

@@ -1,5 +1,5 @@
module Spree
class DigitalsController < Spree::BaseController
class DigitalsController < Spree::StoreController
ssl_required :show
def show

View File

@@ -9,7 +9,7 @@ Spree::LineItem.class_eval do
private
# Create the download link for this item if it is digital.
# TODO there is no reason to create the digital links until the order is complete
def create_digital_links
digital_links.delete_all

View File

@@ -10,8 +10,14 @@ Spree::Order.class_eval do
false
end
# UPGRADE_CHECK this works as of spree 1.1.1; make sure to check the original function on upgrade
def reset_digital_links!
line_items.select(&:digital?).map(&:digital_links).flatten.each do |digital_link|
digital_link.update_column :access_counter, 0
digital_link.update_column :created_at, Time.now
end
end
# UPGRADE_CHECK this works as of spree 1.2.0. check function for changes on upgrade
def available_shipping_methods(display_on = nil)
return [] unless ship_address
all_methods = Spree::ShippingMethod.all_available(self, display_on)

View File

@@ -0,0 +1,7 @@
Deface::Override.new(:virtual_path => "spree/admin/shared/_order_tabs",
:name => "add_reset_digitals_to_admin_orders",
:insert_after => ".sidebar",
:text => %q{
<%= content_tag(:p, button_link_to(t(:reset_downloads), reset_digitals_admin_order_url(@order)), class: 'clear') if @order.digital? or true %>
},
:disabled => false)

View File

@@ -0,0 +1,9 @@
<% if defined?(SpreeFancy) %>
<% content_for :subheader do %>
<h1><%= t('.unauthorized') %></h1>
<% end %>
<% else %>
<h1><%= t('.unauthorized') %></h1>
<% end %>
<%= t('.explained') %>

View File

@@ -1,9 +1,7 @@
en:
digital_versions: Digital Versions
current_file: Current File
new_file: New File
delete_file: Delete this file
broken_file: Warning! this file is broken
current_file: Current File
delete_file: Delete this file
delete_file_cofirmation: Are you sure you want to delete the file %{filename}?
digital_delivery: Digital Delivery
digital_download: Download %{type} ↓
@@ -13,5 +11,14 @@ en:
mobi: Kindle eBook
epub: ePub eBook
pdf: pdf eBook
digital_versions: Digital Versions
downloads_reset: Digital Downloads Reset
new_file: New File
reset_downloads: Reset Digital Downloads
spree:
digitals:
unauthorized:
explained: This download link has expired.
unauthorized: Unauthorized
spree_digital:
upload: Upload

View File

@@ -1,9 +1,7 @@
it:
digital_versions: Versioni Digitali
current_file: File Corrente
new_file: Nuovo File
delete_file: Elimina questo file
broken_file: Attenzione! questo file sembra essere rotto
current_file: File Corrente
delete_file: Elimina questo file
delete_file_cofirmation: Sei sicuro di voler eliminare il file %{filename}?
digital_delivery: Consegna Digitale
digital_download: Download %{type} ↓
@@ -13,6 +11,12 @@ it:
mobi: Kindle eBook
epub: ePub eBook
pdf: pdf eBook
digital_versions: Versioni Digitali
new_file: Nuovo File
spree:
digitals:
unauthorized:
explained: This download link has expired.
unauthorized: Unauthorized
spree_digital:
upload: Upload

View File

@@ -1,12 +1,14 @@
ja:
digital_versions: デジタル版
current_file: 現在のバージョン
new_file: 新しいファイル
upload: アップロード
delete_file: このファイルを削除
broken_file: 注意! このファイルが壊れている!
current_file: 現在のバージョン
delete_file: このファイルを削除
delete_file_cofirmation: 本当に「%{filename}」を削除しても宜しいですか?
digital_shipping: ダウンロードリンクを<strong>%{email}</strong>に送ります
digital_versions: デジタル版
new_file: 新しいファイル
spree:
digitals:
unauthorized:
explained: This download link has expired.
unauthorized: Unauthorized
upload: アップロード

View File

@@ -3,8 +3,13 @@ Spree::Core::Engine.routes.draw do
resources :products do
resources :digitals
end
resources :orders do
member do
get :reset_digitals
end
end
end
get '/digital/:secret', :to => 'digitals#show', :via => :get, :as => 'digital', :constraints => { :secret => /[a-zA-Z0-9]{30}/ }
end

146
readme.md Normal file
View File

@@ -0,0 +1,146 @@
# Spree Digital
This is a spree extension to enable downloadable products (ebooks, MP3s, videos, etc).
The master branch is compatible with Spree 1.2.x. 1.0.x - 1.1.x versions are available, check the `Versionfile`.
This documentation is not complete and possibly out of date in some cases. There are features that have been implemented that are not documented here, please look at the source for complete documentation.
The idea is simple. You attach a file to a Product (or a Variant of this Product) and when people buy it, they will receive a link via email where they can download it once. There are a few assumptions that spree_digital (currently) makes and it's important to be aware of them.
* The table structure of spree_core is not touched. Spree digital lives parallel to spree_core and does change the existing database, except adding two new tables.
* The download links will be sent via email in the order confirmation (or "resend" from the admin section). The links do *not* appear in the order "overview" that the customer sees. Adding download buttons to `OrdersController#show` is easy, [check out this gist](https://gist.github.com/3187793#file_add_spree_digital_buttons_to_invoice.rb).
* Once the order is checked-out, the download links will immediately be sent (i.e. in the order confirmation). You'll have to modify the system to support 'delayed' payments (like a billable account).
* You should create a ShippingMethod based on the Digital Delivery calculator type. The default cost for digital delivery is 0, but you can define a flat rate (creating a per-item digital delivery fee would be possible as well). Checkout the [source code](https://github.com/halo/spree_digital/blob/master/app/models/spree/calculator/digital_delivery.rb) for the Digital Delivery calculator for more information.
* One may buy several items of the same digital product in one cart. The customer will simply receive several links by doing so. This allows customer's to legally purchase multiple copies of the same product and maybe give one away to a friend.
* You can set how many times (clicks) the users downloads will work. You can also set how long the users links will work (expiration). For more information, [check out the preferences object](https://github.com/halo/spree_digital/blob/master/lib/spree/spree_digital_configuration.rb)
* The file `views/order_mailer/confirm_email.text.erb` is the only thing that should need customization. If you are looking for HTML emails, [this branch of spree-html-email](http://github.com/iloveitaly/spree-html-email) supports spree_digital
* A purchased product can be downloaded even if you disable the product immediately. You would have to remove the attached file in your admin section to prevent people from downloading purchased products.
* File are uploaded to `rails_root/private`. Make sure it's symlinked in case you're using Capistrano. If you want to change the upload path, [check out this gist](https://gist.github.com/3187793#file_spree_digital_path_change_decorator.rb)
* You must add a `views/spree/digitals/unauthorized.html.erb` file to customize an error message to the user if they exceed the download / days limit
* We use send_file to send the files on download. See below for instructions on how to push file downloading off to nginx.
## Installation
Add this line to your gemfile:
```shell
gem 'spree_digital', :git => 'git://github.com/halo/spree_digital.git', :branch => 'master'
```
The following terminal commands will copy the migration files to the corresponding directory in your Rails application and apply the migrations to your database.
```shell
bundle exec rails g spree_digital:install
bundle exec rake db:migrate
```
Then set any preferences.
### Shipping Configuration
You should create a ShippingMethod based on the Digital Delivery calculator type. It will be detected by `spree_digital`. Otherwise your customer will be forced to choose something like "UPS" even if they purchase only downloadable products.
### Improving File Downloading: `send_file` + nginx
Without customization, all file downloading will route through the rails stack. This means that if you have two workers, and two customers are downloading files, your server is maxed out and will be unresponsive until the downloads have finished.
Luckily there is an easy way around this: pass off file downloading to nginx (or apache, etc). Take a look at [this article](http://blog.kiskolabs.com/post/637725747/nginx-rails-send-file) for a good explanation.
```
# in your app's source
# config/environments/production.rb
# Specifies the header that your server uses for sending files
# config.action_dispatch.x_sendfile_header = "X-Sendfile" # for apache
config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx
# on your server
# /etc/nginx/sites-available/spree-secure
upstream unicorn_spree_secure {
server unix:/data/spree/shared/sockets/unicorn.sock fail_timeout=0;
}
server {
listen 443;
...
location / {
proxy_set_header X_FORWARDED_PROTO https;
...
proxy_set_header X-Sendfile-Type X-Accel-Redirect;
proxy_set_header X-Accel-Mapping /data/spree/shared/uploaded-files/digitals/=/digitals/;
...
}
location /digitals/ {
internal;
root /data/spree/shared/uploaded-files/;
}
...
}
```
References:
* [Gist of example config](https://gist.github.com/416004)
* [Change paperclip's upload / download path](https://gist.github.com/3187793#file_spree_digital_path_change_decorator.rb)
* ["X-Accel-Mapping header missing" in nginx error log](http://stackoverflow.com/questions/6237016/message-x-accel-mapping-header-missing-in-nginx-error-log)
* [Another good, but older, explanation](http://kovyrin.net/2006/11/01/nginx-x-accel-redirect-php-rails/)
## Usage
### Table Diagram
<img src="http://github.com/halo/spree_digital/raw/master/doc/tables.png">
### Installation
Get the spree framework and spree_digital extension for it:
```shell
git clone git://github.com/spree/spree.git
git clone git://github.com/halo/spree_digital.git
```
Go into the spree directory and run the bundle command:
```shell
cd spree
bundle install
```
Go into the spree_digital directory and do the same:
NOTE: At this point you may need to uncomment the stuff in the `Gemfile` before you can start developing and testing!
```shell
cd spree_digital
bundle install
```
Bring up the test application (you only need to do this whenever you fiddle around with the migrations) and then you can run the tests as you please.
```shell
rake test_app
rake spec
```
This link may be very helpful to you: [http://github.com/spree/spree](http://github.com/spree/spree)
### Authors
* [iloveitaly](http://github.com/iloveitaly/)
* [halo](http://github.com/halo)
### License
Copyright (c) 2011 funkensturm.
Released under the MIT License
See [LICENSE](http://github.com/funkensturm/spree_digital/blob/master/LICENSE)

View File

@@ -2,5 +2,8 @@ FactoryGirl.define do
factory :digital, :class => Spree::Digital do |f|
# TODO good to assign variant association if no association is manually defined
# f.variant { |p| p.association(:variant) }
attachment_content_type 'application/octet-stream'
attachment_file_name 'a_great_book.epub'
end
end

View File

@@ -1,16 +1,14 @@
ENV["RAILS_ENV"] = "test"
require File.expand_path("../dummy/config/environment.rb", __FILE__)
require 'rspec/rails'
require 'database_cleaner'
require 'ffaker'
require 'shoulda-matchers'
# Requires supporting ruby files with custom matchers and macros, etc,
# in spec/support/ and its subdirectories.
Dir[File.join(File.dirname(__FILE__), "support/**/*.rb")].each {|f| require f }
require 'spree/core/testing_support/factories'
require 'spree/core/testing_support/env'
require 'spree/core/testing_support/controller_requests'
require 'spree/core/url_helpers'
@@ -21,7 +19,6 @@ RSpec.configure do |config|
config.include FactoryGirl::Syntax::Methods
config.include Spree::Core::UrlHelpers
config.include Spree::Core::TestingSupport::ControllerRequests
config.include Devise::TestHelpers, :type => :controller
config.use_transactional_fixtures = false
config.before(:each) do

View File

@@ -3,7 +3,7 @@ Gem::Specification.new do |s|
s.name = 'spree_digital'
s.version = '1.1.1'
s.summary = ''
s.description = 'Add digital download functionality to spree'
s.description = 'Digital download functionality for spree'
s.authors = ['funkensturm', 'Michael Bianco']
s.email = ['info@cliffsidedev.com']
s.homepage = 'http://www.funkensturm.com'
@@ -12,7 +12,8 @@ Gem::Specification.new do |s|
s.require_path = 'lib'
s.requirements << 'none'
s.required_ruby_version = '>= 1.8.7'
s.add_dependency 'spree_core', '>= 1.1.0'
s.add_dependency 'spree_core', '~> 1.3.0'
# test suite
s.add_development_dependency 'shoulda-matchers'