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 +53 -0
- data/app/controllers/protected_media_controller.rb +26 -0
- data/app/controllers/spud/admin/media_controller.rb +10 -1
- data/app/helpers/protected_media_helper.rb +3 -0
- data/app/models/spud_media.rb +57 -4
- data/app/views/spud/admin/media/index.html.erb +13 -2
- data/app/views/spud/admin/media/new.html.erb +7 -0
- data/config/routes.rb +5 -3
- data/db/migrate/20120101194256_create_spud_media.rb +1 -1
- data/db/migrate/20120501203325_add_protected_to_spud_media.rb +6 -0
- data/lib/spud_media/configuration.rb +4 -3
- data/lib/spud_media/version.rb +1 -1
- data/lib/tasks/spud_media_tasks.rake +11 -0
- metadata +27 -24
- data/README.rdoc +0 -3
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
|
data/app/models/spud_media.rb
CHANGED
@@ -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
|
-
:
|
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
|
-
|
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"
|
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"
|
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
|
@@ -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/:
|
8
|
-
self.
|
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
|
data/lib/spud_media/version.rb
CHANGED
@@ -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.
|
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-
|
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: &
|
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: *
|
24
|
+
version_requirements: *70279704590120
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: spud_core
|
27
|
-
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: *
|
38
|
+
version_requirements: *70279704589000
|
39
39
|
- !ruby/object:Gem::Dependency
|
40
40
|
name: paperclip
|
41
|
-
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: *
|
49
|
+
version_requirements: *70279704603420
|
50
50
|
- !ruby/object:Gem::Dependency
|
51
51
|
name: mysql2
|
52
|
-
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: *
|
60
|
+
version_requirements: *70279704602440
|
61
61
|
- !ruby/object:Gem::Dependency
|
62
62
|
name: rspec
|
63
|
-
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: *
|
71
|
+
version_requirements: *70279704601520
|
72
72
|
- !ruby/object:Gem::Dependency
|
73
73
|
name: rspec-rails
|
74
|
-
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: *
|
82
|
+
version_requirements: *70279704600080
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: factory_girl
|
85
|
-
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: *
|
93
|
+
version_requirements: *70279704597640
|
94
94
|
- !ruby/object:Gem::Dependency
|
95
95
|
name: mocha
|
96
|
-
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: *
|
104
|
+
version_requirements: *70279704611520
|
105
105
|
- !ruby/object:Gem::Dependency
|
106
106
|
name: database_cleaner
|
107
|
-
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: *
|
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
|
-
-
|
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:
|
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:
|
216
|
+
hash: -3389397261865265902
|
214
217
|
requirements: []
|
215
218
|
rubyforge_project:
|
216
|
-
rubygems_version: 1.8.
|
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