spud_media 0.8.3 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
data/Readme.markdown ADDED
@@ -0,0 +1,53 @@
1
+ # Spud Media
2
+
3
+ Spud Media is an engine for managing documents and other media miscellaneous files, designed for use with [Spud][1].
4
+
5
+ ## Installation/Usage
6
+
7
+ 1. In your Gemfile add the following
8
+
9
+ gem 'spud_media'
10
+
11
+ 2. Run bundle install
12
+ 3. Copy in database migrations to your new rails project
13
+
14
+ bundle exec rake railties:install:migrations
15
+ rake db:migrate
16
+
17
+ 4. Run a rails server instance and point your browser to /spud/admin
18
+
19
+ ## Configuration
20
+
21
+ Spud Photos accepts the following configuration options:
22
+
23
+ Spud::Media.configure do |config|
24
+
25
+ # s3 storage requires the 'aws-sdk' gem. defaults to filesystem
26
+ config.paperclip_storage = :s3
27
+ config.s3_credentials = "#{Rails.root}/config/s3.yml"
28
+
29
+ # see below for notes on 'storage_path_protected'
30
+ config.storage_path = "public/system/spud_media/:id/:style/:basename.:extension"
31
+ config.storage_path_protected = "public/system/spud_media_protected/:id/:style/:basename.:extension"
32
+ config.storage_url = "/system/spud_media/:id/:style/:basename.:extension"
33
+ end
34
+
35
+ ## File Protection
36
+
37
+ Spud Media allows for individual files to be marked as protected. How this is actually implemented depends on whether you are using the local file system or Amazon S3 for file storage.
38
+
39
+ ### Filesystem
40
+
41
+ Unprotected files are stored under `/public/system/spud_media` and are accessed directly by the web server. No further configuration is required, though you may customize the storage location if desired using `config.storage_path`.
42
+
43
+ Protected files are moved to `public/system/spud_media_protected`. Note that the public-facing download URL should __not__ reflect the `protected` storage path. Instead the user will hit the same URL as before, but this time their request will hit the `show` action of the `ProtectedMedia` controller.
44
+
45
+ It is up to the individual developer to make sure that the protected storage path is not accessible by the public. You may choose to protect this folder via server configurations, or you can move the folder out of the document root using `config.storage_path_protected`.
46
+
47
+ ### Amazon S3
48
+
49
+ Files marked as unprotected will be uploaded to Amazon using the `public_read` ACL. These files are accessed directly - ie, calling `@media.attachment_url` will link directly to Amazon.
50
+
51
+ Files marked as protected are uploaded using the `private` ACL. In this case, calling `@media.attachment_url` will return a local URL that hits the show action of our `ProtectedMedia` controller. Once we have verified the user is logged in we generate a secure URL and redirect the user to it. The generated URL is good for 10 minutes.
52
+
53
+ [1]:https://github.com/davydotcom/spud_core_admin
@@ -0,0 +1,26 @@
1
+ class ProtectedMediaController < Spud::ApplicationController
2
+
3
+ before_filter :require_user
4
+
5
+ def show
6
+ @media = SpudMedia.where(:id => params[:id]).first
7
+ if @media.blank?
8
+ flash[:error] = "The requested file could not be found"
9
+ redirect_to(root_url)
10
+ else
11
+ if Spud::Media.config.paperclip_storage == :s3
12
+ secure_url = @media.attachment.s3_object.url_for(:read, :secure => true, :expires => 10.minutes)
13
+ redirect_to(secure_url.to_s)
14
+ else
15
+ filepath = File.join(Rails.root, @media.attachment.path)
16
+ if !File.exists?(filepath)
17
+ flash[:error] = "The requested file could not be found"
18
+ redirect_to root_path
19
+ else
20
+ send_file(filepath, :disposition => 'inline')
21
+ end
22
+ end
23
+ end
24
+ end
25
+
26
+ end
@@ -2,7 +2,8 @@ class Spud::Admin::MediaController < Spud::Admin::ApplicationController
2
2
  layout 'spud/admin/media/detail'
3
3
  add_breadcrumb "Media", :spud_admin_media_path
4
4
  belongs_to_spud_app :media
5
- before_filter :load_media,:only => [:edit,:update,:show,:destroy]
5
+ before_filter :load_media,:only => [:edit,:update,:show,:destroy,:set_private,:set_access]
6
+
6
7
  def index
7
8
  @media = SpudMedia.order("created_at DESC").paginate :page => params[:page]
8
9
  respond_with @media
@@ -31,12 +32,20 @@ class Spud::Admin::MediaController < Spud::Admin::ApplicationController
31
32
  end
32
33
 
33
34
  def update
35
+
34
36
  end
35
37
 
36
38
  def destroy
37
39
  flash[:notice] = "File successfully destroyed" if @media.destroy
38
40
  respond_with @media, :location => spud_admin_media_url
39
41
  end
42
+
43
+ def set_access
44
+ is_protected = params[:protected] || false
45
+ @media.update_attribute(:is_protected, is_protected)
46
+ respond_with @media, :location => spud_admin_media_url
47
+ end
48
+
40
49
  private
41
50
  def load_media
42
51
  @media = SpudMedia.where(:id => params[:id]).first
@@ -0,0 +1,3 @@
1
+ module ProtectedMediaHelper
2
+
3
+ end
@@ -1,10 +1,19 @@
1
1
  class SpudMedia < ActiveRecord::Base
2
+
2
3
  has_attached_file :attachment,
3
4
  :storage => Spud::Media.paperclip_storage,
4
5
  :s3_credentials => Spud::Media.s3_credentials,
5
- :path => Spud::Media.storage_path,
6
+ :s3_permissions => lambda { |attachment, style|
7
+ attachment.instance.is_protected ? 'private' : 'public-read'
8
+ },
9
+ :path => Spud::Media.paperclip_storage == :s3 ? Spud::Media.storage_path : lambda { |attachment|
10
+ attachment.instance.is_protected ? Spud::Media.storage_path_protected : Spud::Media.storage_path
11
+ },
6
12
  :url => Spud::Media.storage_url
7
- attr_accessible :attachment_content_type,:attachment_file_name,:attachment_file_size,:attachment
13
+
14
+ before_update :validate_permissions
15
+
16
+ attr_accessible :attachment_content_type,:attachment_file_name,:attachment_file_size,:attachment, :is_protected
8
17
  def image_from_type
9
18
  if self.attachment_content_type.blank?
10
19
  return "spud/admin/files_thumbs/dat_thumb.png"
@@ -14,8 +23,6 @@ class SpudMedia < ActiveRecord::Base
14
23
  return "spud/admin/files_thumbs/jpg_thumb.png"
15
24
  end
16
25
 
17
-
18
-
19
26
  if self.attachment_content_type.match(/png/)
20
27
  return "spud/admin/files_thumbs/png_thumb.png"
21
28
  end
@@ -45,4 +52,50 @@ class SpudMedia < ActiveRecord::Base
45
52
 
46
53
  return "spud/admin/files_thumbs/dat_thumb.png"
47
54
  end
55
+
56
+ # if you are using S3, attachment.url will automatically point to the S3 url
57
+ # protected files need to hit the rails middle-man first
58
+ # this method will provide the correct url for either case
59
+ def attachment_url
60
+ if Spud::Media.paperclip_storage == :s3 && is_protected
61
+ return Paperclip::Interpolations.interpolate(Spud::Media.config.storage_url, attachment, 'original')
62
+ else
63
+ return attachment.url
64
+ end
65
+ end
66
+
67
+ # If is_protected has changed, we need to make sure we are setting the appropriate permissions
68
+ # This means either moving the file in the filesystem or setting the appropriate ACL in S3
69
+ def validate_permissions
70
+ if Spud::Media.config.paperclip_storage == :filesystem
71
+ validate_permissions_filesystem
72
+ elsif Spud::Media.config.paperclip_storage == :s3
73
+ validate_permissions_s3
74
+ end
75
+ end
76
+
77
+ private
78
+
79
+ def validate_permissions_filesystem
80
+ if is_protected
81
+ old_path = Paperclip::Interpolations.interpolate(Spud::Media.config.storage_path, attachment, 'original')
82
+ new_path = Paperclip::Interpolations.interpolate(Spud::Media.config.storage_path_protected, attachment, 'original')
83
+ else
84
+ old_path = Paperclip::Interpolations.interpolate(Spud::Media.config.storage_path_protected, attachment, 'original')
85
+ new_path = Paperclip::Interpolations.interpolate(Spud::Media.config.storage_path, attachment, 'original')
86
+ end
87
+ new_base_dir = File.dirname(new_path)
88
+ old_base_dir= File.dirname(old_path)
89
+ if File.directory?(old_base_dir)
90
+ FileUtils.mv(old_base_dir, new_base_dir)
91
+ end
92
+ end
93
+
94
+ def validate_permissions_s3
95
+ if is_protected
96
+ attachment.s3_object.acl = :private
97
+ else
98
+ attachment.s3_object.acl = :public_read
99
+ end
100
+ end
48
101
  end
@@ -6,9 +6,20 @@
6
6
  <%@media.each do |media|%>
7
7
  <div class="page_row">
8
8
 
9
- <span class="row_meta"><%=image_tag(media.image_from_type,:class => "size-50-thumb")%><%=link_to media.attachment.url.split("/").last,media.attachment.url%></span>
9
+ <span class="row_meta">
10
+ <%=image_tag(media.image_from_type,:class => "size-50-thumb")%>
11
+ <%=link_to media.attachment.url.split("/").last, media.attachment_url %>
12
+ </span>
10
13
 
11
- <span class="edit_controls"><%=link_to "Remove",spud_admin_medium_path(:id => media.id),:method => :delete,:class => 'btn btn-danger',:confirm => "Are you sure you want to remove this file?"%></span>
14
+ <span class="edit_controls">
15
+ <% if media.is_protected %>
16
+ <%= link_to raw('<i class="icon-lock"></i> Protected'), set_access_spud_admin_medium_path(media.id, :protected => false), :method => :put, :class => 'btn' %>
17
+ <% else %>
18
+ <%= link_to 'Public', set_access_spud_admin_medium_path(media.id, :protected => true), :method => :put, :class => 'btn' %>
19
+ <% end %>
20
+ <%=link_to "Remove",spud_admin_medium_path(:id => media.id),:method => :delete,:class => 'btn btn-danger',:confirm => "Are you sure you want to remove this file?"%>
21
+ </span>
22
+
12
23
  <br style="clear:both;"/>
13
24
  </div>
14
25
  <%end%>
@@ -12,6 +12,13 @@
12
12
  </div>
13
13
  </div>
14
14
 
15
+ <div class="control-group">
16
+ <%= f.label :is_protected, 'Protected File', :class => 'control-label' %>
17
+ <div class="controls">
18
+ <%= f.check_box :is_protected %>
19
+ </div>
20
+ </div>
21
+
15
22
  <div class="form-actions">
16
23
  <%=f.submit "Upload", :class=>"btn btn-primary","data-loading-text"=>"Uploading..."%> or <%=link_to "cancel",spud_admin_media_path,:class => "btn"%>
17
24
  </div>
data/config/routes.rb CHANGED
@@ -1,9 +1,11 @@
1
1
  Rails.application.routes.draw do
2
2
  namespace :spud do
3
3
  namespace :admin do
4
- resources :media
4
+ resources :media do
5
+ put 'set_access', :on => :member
6
+ end
5
7
  end
6
8
  end
7
-
8
- end
9
9
 
10
+ get Spud::Media.config.storage_url => 'ProtectedMedia#show', :as => 'protected_media'
11
+ end
@@ -8,4 +8,4 @@ class CreateSpudMedia < ActiveRecord::Migration
8
8
  t.timestamps
9
9
  end
10
10
  end
11
- end
11
+ end
@@ -0,0 +1,6 @@
1
+ class AddProtectedToSpudMedia < ActiveRecord::Migration
2
+ def change
3
+ add_column :spud_media, :is_protected, :boolean, :default => false
4
+ add_column :spud_media, :attachment_updated_at, :datetime
5
+ end
6
+ end
@@ -1,10 +1,11 @@
1
1
  module Spud
2
2
  module Media
3
3
  include ActiveSupport::Configurable
4
- config_accessor :paperclip_storage,:s3_credentials,:storage_path,:storage_url
4
+ config_accessor :paperclip_storage,:s3_credentials,:storage_path,:storage_path_protected,:storage_url
5
5
  self.paperclip_storage = :filesystem
6
6
  self.s3_credentials = "#{Rails.root}/config/s3.yml"
7
- self.storage_path = "public/system/:class/:id/attachment/:basename.:extension"
8
- self.storage_url = "/system/:class/:id/attachment/:basename.:extension"
7
+ self.storage_path = "public/system/spud_media/:id/:style/:basename.:extension"
8
+ self.storage_path_protected = "public/system/spud_media_protected/:id/:style/:basename.:extension"
9
+ self.storage_url = "/system/spud_media/:id/:style/:basename.:extension"
9
10
  end
10
11
  end
@@ -1,5 +1,5 @@
1
1
  module Spud
2
2
  module Media
3
- VERSION = "0.8.3"
3
+ VERSION = "0.9.0"
4
4
  end
5
5
  end
@@ -2,3 +2,14 @@
2
2
  # task :spud_media do
3
3
  # # Task goes here
4
4
  # end
5
+
6
+ namespace :spud_media do
7
+
8
+ desc "Validate that all media files have the proper permission settings"
9
+ task :validate_permissions => :environment do
10
+ SpudMedia.find_each do |m|
11
+ m.validate_permissions
12
+ end
13
+ end
14
+
15
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spud_media
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.3
4
+ version: 0.9.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-04-01 00:00:00.000000000 Z
12
+ date: 2012-05-03 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails
16
- requirement: &70147799490300 !ruby/object:Gem::Requirement
16
+ requirement: &70279704590120 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: 3.2.2
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70147799490300
24
+ version_requirements: *70279704590120
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: spud_core
27
- requirement: &70147799489780 !ruby/object:Gem::Requirement
27
+ requirement: &70279704589000 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -35,10 +35,10 @@ dependencies:
35
35
  version: 0.9.0
36
36
  type: :runtime
37
37
  prerelease: false
38
- version_requirements: *70147799489780
38
+ version_requirements: *70279704589000
39
39
  - !ruby/object:Gem::Dependency
40
40
  name: paperclip
41
- requirement: &70147799489060 !ruby/object:Gem::Requirement
41
+ requirement: &70279704603420 !ruby/object:Gem::Requirement
42
42
  none: false
43
43
  requirements:
44
44
  - - ! '>='
@@ -46,10 +46,10 @@ dependencies:
46
46
  version: '0'
47
47
  type: :runtime
48
48
  prerelease: false
49
- version_requirements: *70147799489060
49
+ version_requirements: *70279704603420
50
50
  - !ruby/object:Gem::Dependency
51
51
  name: mysql2
52
- requirement: &70147799488680 !ruby/object:Gem::Requirement
52
+ requirement: &70279704602440 !ruby/object:Gem::Requirement
53
53
  none: false
54
54
  requirements:
55
55
  - - ! '>='
@@ -57,10 +57,10 @@ dependencies:
57
57
  version: '0'
58
58
  type: :development
59
59
  prerelease: false
60
- version_requirements: *70147799488680
60
+ version_requirements: *70279704602440
61
61
  - !ruby/object:Gem::Dependency
62
62
  name: rspec
63
- requirement: &70147799488220 !ruby/object:Gem::Requirement
63
+ requirement: &70279704601520 !ruby/object:Gem::Requirement
64
64
  none: false
65
65
  requirements:
66
66
  - - ! '>='
@@ -68,10 +68,10 @@ dependencies:
68
68
  version: '0'
69
69
  type: :development
70
70
  prerelease: false
71
- version_requirements: *70147799488220
71
+ version_requirements: *70279704601520
72
72
  - !ruby/object:Gem::Dependency
73
73
  name: rspec-rails
74
- requirement: &70147799487800 !ruby/object:Gem::Requirement
74
+ requirement: &70279704600080 !ruby/object:Gem::Requirement
75
75
  none: false
76
76
  requirements:
77
77
  - - ! '>='
@@ -79,10 +79,10 @@ dependencies:
79
79
  version: '0'
80
80
  type: :development
81
81
  prerelease: false
82
- version_requirements: *70147799487800
82
+ version_requirements: *70279704600080
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: factory_girl
85
- requirement: &70147799487300 !ruby/object:Gem::Requirement
85
+ requirement: &70279704597640 !ruby/object:Gem::Requirement
86
86
  none: false
87
87
  requirements:
88
88
  - - =
@@ -90,10 +90,10 @@ dependencies:
90
90
  version: 2.5.0
91
91
  type: :development
92
92
  prerelease: false
93
- version_requirements: *70147799487300
93
+ version_requirements: *70279704597640
94
94
  - !ruby/object:Gem::Dependency
95
95
  name: mocha
96
- requirement: &70147799486800 !ruby/object:Gem::Requirement
96
+ requirement: &70279704611520 !ruby/object:Gem::Requirement
97
97
  none: false
98
98
  requirements:
99
99
  - - =
@@ -101,10 +101,10 @@ dependencies:
101
101
  version: 0.10.3
102
102
  type: :development
103
103
  prerelease: false
104
- version_requirements: *70147799486800
104
+ version_requirements: *70279704611520
105
105
  - !ruby/object:Gem::Dependency
106
106
  name: database_cleaner
107
- requirement: &70147799656040 !ruby/object:Gem::Requirement
107
+ requirement: &70279704610980 !ruby/object:Gem::Requirement
108
108
  none: false
109
109
  requirements:
110
110
  - - =
@@ -112,7 +112,7 @@ dependencies:
112
112
  version: 0.7.1
113
113
  type: :development
114
114
  prerelease: false
115
- version_requirements: *70147799656040
115
+ version_requirements: *70279704610980
116
116
  description: Spud Media allows you to upload files to your site and manage them in
117
117
  the spud administrative panel. It also uses paperclip and supports s3 storage
118
118
  email:
@@ -142,7 +142,9 @@ files:
142
142
  - app/assets/libs/tiny_mce/plugins/spud_media/langs/en_dlg.js
143
143
  - app/assets/libs/tiny_mce/plugins/spud_media/template.htm
144
144
  - app/assets/stylesheets/spud/admin/media/application.css
145
+ - app/controllers/protected_media_controller.rb
145
146
  - app/controllers/spud/admin/media_controller.rb
147
+ - app/helpers/protected_media_helper.rb
146
148
  - app/helpers/spud/admin/users_helper.rb
147
149
  - app/helpers/spud/user_sessions_helper.rb
148
150
  - app/models/spud_media.rb
@@ -151,6 +153,7 @@ files:
151
153
  - app/views/spud/admin/media/new.html.erb
152
154
  - config/routes.rb
153
155
  - db/migrate/20120101194256_create_spud_media.rb
156
+ - db/migrate/20120501203325_add_protected_to_spud_media.rb
154
157
  - lib/spud_media/configuration.rb
155
158
  - lib/spud_media/engine.rb
156
159
  - lib/spud_media/version.rb
@@ -158,7 +161,7 @@ files:
158
161
  - lib/tasks/spud_media_tasks.rake
159
162
  - MIT-LICENSE
160
163
  - Rakefile
161
- - README.rdoc
164
+ - Readme.markdown
162
165
  - test/dummy/app/assets/javascripts/application.js
163
166
  - test/dummy/app/assets/stylesheets/application.css
164
167
  - test/dummy/app/controllers/application_controller.rb
@@ -201,7 +204,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
201
204
  version: '0'
202
205
  segments:
203
206
  - 0
204
- hash: 3757302158423942530
207
+ hash: -3389397261865265902
205
208
  required_rubygems_version: !ruby/object:Gem::Requirement
206
209
  none: false
207
210
  requirements:
@@ -210,10 +213,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
210
213
  version: '0'
211
214
  segments:
212
215
  - 0
213
- hash: 3757302158423942530
216
+ hash: -3389397261865265902
214
217
  requirements: []
215
218
  rubyforge_project:
216
- rubygems_version: 1.8.15
219
+ rubygems_version: 1.8.10
217
220
  signing_key:
218
221
  specification_version: 3
219
222
  summary: Spud File upload/management module
data/README.rdoc DELETED
@@ -1,3 +0,0 @@
1
- = SpudMedia
2
-
3
- This project rocks and uses MIT-LICENSE.