sufia 3.2.1 → 3.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +2 -0
- data/CONTRIBUTING.md +2 -0
- data/Gemfile +5 -0
- data/History.md +17 -0
- data/README.md +6 -6
- data/SUFIA_VERSION +1 -1
- data/app/controllers/mailbox_controller.rb +1 -2
- data/app/controllers/single_use_links_controller.rb +40 -0
- data/app/controllers/single_use_links_viewer_controller.rb +73 -0
- data/app/views/single_use_links/new_download.html.erb +5 -0
- data/app/views/{single_use_link/generate_show.html.erb → single_use_links/new_show.html.erb} +3 -1
- data/app/views/{single_use_link → single_use_links_viewer}/show.html.erb +2 -2
- data/config/routes.rb +4 -4
- data/lib/sufia/version.rb +1 -1
- data/spec/controllers/single_use_links_controller_spec.rb +69 -0
- data/spec/controllers/{single_use_link_controller_spec.rb → single_use_links_viewer_controller_spec.rb} +28 -59
- data/spec/features/single_use_links_spec.rb +38 -0
- data/spec/models/single_use_link_spec.rb +19 -18
- data/spec/support/lib/generators/test_app_generator.rb +0 -12
- data/sufia-models/app/models/domain_term.rb +5 -1
- data/sufia-models/app/models/local_authority.rb +10 -4
- data/sufia-models/app/models/single_use_link.rb +35 -16
- data/sufia-models/lib/sufia/models/version.rb +1 -1
- data/sufia-models/sufia-models.gemspec +1 -1
- data/sufia.gemspec +1 -1
- data/tasks/release.rake +1 -2
- metadata +23 -11
- data/app/controllers/single_use_link_controller.rb +0 -95
- data/app/views/single_use_link/generate_download.html.erb +0 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 192f05ee63c1448500374b381283f9796bb6a864
|
4
|
+
data.tar.gz: 5017ed019cf96dd363991d15718c48599ae10fcb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 00027897e9f28c13ece3f1413db477941479cb2f0bebb10b90e6ebb1c73d6834866a0aecb219fbdf9d31ceea73decaacb2028805de3d5846661256a7ac3c7966
|
7
|
+
data.tar.gz: c40470550b3593473d5bfb75caea483477d1640d8a76eeecb0f0060d4341768f251184663f02c81d8f22ad9b320b218cbfad5e241a5a7b0fa670c7db07f1e9a5
|
data/.travis.yml
CHANGED
data/CONTRIBUTING.md
CHANGED
@@ -78,6 +78,8 @@ You should also add yourself to the `CONTRIBUTORS.md` file in the root of the pr
|
|
78
78
|
|
79
79
|
### Submitting Changes
|
80
80
|
|
81
|
+
[Detailed Walkthrough of One Pull Request per Commit](http://ndlib.github.io/practices/one-commit-per-pull-request/)
|
82
|
+
|
81
83
|
* Read the article ["Using Pull Requests"](https://help.github.com/articles/using-pull-requests) on GitHub.
|
82
84
|
* Make sure your branch is up to date with its parent branch (i.e. master)
|
83
85
|
* `git checkout master`
|
data/Gemfile
CHANGED
@@ -19,5 +19,10 @@ group :development, :test do
|
|
19
19
|
gem 'bcrypt-ruby'
|
20
20
|
gem "jettywrapper"
|
21
21
|
gem "factory_girl_rails", "~> 4.2.1"
|
22
|
+
gem "devise"
|
23
|
+
gem 'jquery-rails'
|
24
|
+
gem 'sass-rails'
|
25
|
+
gem 'turbolinks'
|
26
|
+
gem "bootstrap-sass"
|
22
27
|
gem "simplecov", :require => false
|
23
28
|
end # (leave this comment here to catch a stray line inserted by blacklight!)
|
data/History.md
CHANGED
@@ -1,5 +1,22 @@
|
|
1
1
|
# History of Sufia releases
|
2
2
|
|
3
|
+
## 3.3.0
|
4
|
+
* Fix authorities deprecations [Justin Coyne]
|
5
|
+
* Fix deprecation on MailboxController [Justin Coyne]
|
6
|
+
* blacklight 4.4.1/0 doesn't work with kaminari > 0.14.1 See projectblacklight/blacklight#614 [Justin Coyne]
|
7
|
+
* Allow acts_as_follower to be 0.2.0 for Rails 4 support [Justin Coyne]
|
8
|
+
* Don't run blacklight and hydra generator twice [Justin Coyne]
|
9
|
+
* Remove deprecation warning on Rails 4 [Justin Coyne]
|
10
|
+
* Updating CONTRIBUTING.md as per Hydra v6.0.0 [Jeremy Friesen]
|
11
|
+
* use cancan to authorize and validate single-use tokens. [Chris Beer]
|
12
|
+
* Add ImageMagick as a software requirement in the README. [Jessie Keck]
|
13
|
+
* split SingleUseLinkController into the authenticated controller that creates links, and a viewer that handles retrieving content for token-bearing users [Chris Beer]
|
14
|
+
* remove explicit GenericFile references, and replace them with Rails magic [Chris Beer]
|
15
|
+
* Refactor single-use links for style and clarity [Chris Beer]
|
16
|
+
* add more gems to the gemfile for running tests from the gem root [Chris Beer]
|
17
|
+
* add redis-server to the .travis.yml list of services [Chris Beer]
|
18
|
+
* Fix typos in README.md [Jessie Keck]
|
19
|
+
|
3
20
|
## 3.2.1
|
4
21
|
* Updating gemspec to not limit on sufia-models [Jeremy Friesen]
|
5
22
|
|
data/README.md
CHANGED
@@ -27,19 +27,19 @@ Sufia has the following features:
|
|
27
27
|
|
28
28
|
## Sufia needs the following software to work:
|
29
29
|
1. Solr
|
30
|
-
1. Fedora Commons
|
30
|
+
1. [Fedora Commons](http://www.fedora-commons.org/) digital repository
|
31
31
|
1. A SQL RDBMS (MySQL, SQLite)
|
32
32
|
1. [Redis](http://redis.io/) key-value store
|
33
|
+
1. [ImageMagick](http://www.imagemagick.org/)
|
33
34
|
1. Ruby
|
34
|
-
|
35
|
+
|
36
|
+
#### !! Ensure that you have all of the above components installed before you continue. !!
|
35
37
|
|
36
38
|
## Creating an application
|
37
39
|
### Generate base Rails install
|
38
40
|
```rails new my_app```
|
39
41
|
### Add gems to Gemfile
|
40
42
|
```
|
41
|
-
gem 'blacklight'
|
42
|
-
gem 'hydra-head'
|
43
43
|
gem 'sufia'
|
44
44
|
gem 'kaminari', github: 'harai/kaminari', branch: 'route_prefix_prototype' # required to handle pagination properly in dashboard. See https://github.com/amatsuda/kaminari/pull/322
|
45
45
|
gem 'jettywrapper'
|
@@ -53,7 +53,7 @@ Note the line with kaminari listed as a dependency. This is a temporary fix to
|
|
53
53
|
```
|
54
54
|
rails g blacklight --devise
|
55
55
|
rails g hydra:head -f
|
56
|
-
bundle install
|
56
|
+
bundle install
|
57
57
|
rails g sufia -f
|
58
58
|
rm public/index.html
|
59
59
|
```
|
@@ -116,7 +116,7 @@ resque-pool --daemon --environment development start
|
|
116
116
|
|
117
117
|
See https://github.com/defunkt/resque for more options
|
118
118
|
|
119
|
-
### If you want to enable transcoding of video,
|
119
|
+
### If you want to enable transcoding of video, install ffmpeg version 1.0+
|
120
120
|
#### On a mac
|
121
121
|
Use homebrew:
|
122
122
|
```
|
data/SUFIA_VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
3.
|
1
|
+
3.3.0
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'sufia/single_use_error'
|
2
|
+
|
3
|
+
class SingleUseLinksController < ApplicationController
|
4
|
+
include Sufia::Noid
|
5
|
+
|
6
|
+
prepend_before_filter :normalize_identifier
|
7
|
+
before_filter :load_asset
|
8
|
+
before_filter :authenticate_user!
|
9
|
+
before_filter :authorize_user!
|
10
|
+
|
11
|
+
def new_download
|
12
|
+
@su = SingleUseLink.create :itemId => params[:id], :path => sufia.download_path(:id => @asset)
|
13
|
+
@link = sufia.download_single_use_link_path(@su.downloadKey)
|
14
|
+
|
15
|
+
respond_to do |format|
|
16
|
+
format.html
|
17
|
+
format.js { render :js => @link }
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def new_show
|
22
|
+
@su = SingleUseLink.create :itemId => params[:id], :path => sufia.polymorphic_path(@asset)
|
23
|
+
@link = sufia.show_single_use_link_path(@su.downloadKey)
|
24
|
+
|
25
|
+
respond_to do |format|
|
26
|
+
format.html
|
27
|
+
format.js { render :js => @link }
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
protected
|
32
|
+
def authorize_user!
|
33
|
+
authorize! :read, @asset
|
34
|
+
end
|
35
|
+
|
36
|
+
def load_asset
|
37
|
+
@asset = ActiveFedora::Base.load_instance_from_solr(params[:id])
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'sufia/single_use_error'
|
2
|
+
|
3
|
+
class SingleUseLinksViewerController < ApplicationController
|
4
|
+
|
5
|
+
include Sufia::DownloadsControllerBehavior
|
6
|
+
|
7
|
+
skip_filter :normalize_identifier
|
8
|
+
skip_before_filter :load_datastream, :except => :download
|
9
|
+
|
10
|
+
before_filter :authorize_single_use_link!
|
11
|
+
|
12
|
+
class Ability
|
13
|
+
include CanCan::Ability
|
14
|
+
|
15
|
+
attr_reader :single_use_link
|
16
|
+
|
17
|
+
def initialize(user, single_use_link)
|
18
|
+
@user = user || User.new
|
19
|
+
|
20
|
+
@single_use_link = single_use_link
|
21
|
+
|
22
|
+
can :read, ActiveFedora::Base do |obj|
|
23
|
+
single_use_link.valid? and
|
24
|
+
single_use_link.itemId == obj.pid and single_use_link.destroy!
|
25
|
+
end if single_use_link
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
rescue_from Sufia::SingleUseError, :with => :render_single_use_error
|
31
|
+
rescue_from CanCan::AccessDenied, :with => :render_single_use_error
|
32
|
+
rescue_from ActiveRecord::RecordNotFound, :with => :render_single_use_error
|
33
|
+
|
34
|
+
|
35
|
+
def download
|
36
|
+
# send the data content
|
37
|
+
raise not_found_exception unless single_use_link.path == sufia.download_path(:id => @asset)
|
38
|
+
send_content(asset)
|
39
|
+
end
|
40
|
+
|
41
|
+
def show
|
42
|
+
raise not_found_exception unless single_use_link.path == sufia.polymorphic_path(@asset)
|
43
|
+
|
44
|
+
#show the file
|
45
|
+
@terms = @asset.terms_for_display
|
46
|
+
|
47
|
+
# create a dowload link that is single use for the user since we do not just want to show metadata we want to access it too
|
48
|
+
@su = single_use_link.create_for_path sufia.download_path(:id => @asset)
|
49
|
+
@download_link = sufia.download_single_use_link_path(@su.downloadKey)
|
50
|
+
end
|
51
|
+
|
52
|
+
protected
|
53
|
+
|
54
|
+
def authorize_single_use_link!
|
55
|
+
authorize! :read, @asset
|
56
|
+
end
|
57
|
+
|
58
|
+
def single_use_link
|
59
|
+
@single_use_link ||= SingleUseLink.find_by_downloadKey! params[:id]
|
60
|
+
end
|
61
|
+
|
62
|
+
def not_found_exception
|
63
|
+
Sufia::SingleUseError.new('Single-Use Link Not Found')
|
64
|
+
end
|
65
|
+
|
66
|
+
def load_asset
|
67
|
+
@asset = ActiveFedora::Base.load_instance_from_solr(single_use_link.itemId)
|
68
|
+
end
|
69
|
+
|
70
|
+
def current_ability
|
71
|
+
@current_ability ||= SingleUseLinksViewerController::Ability.new current_user, single_use_link
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,5 @@
|
|
1
|
+
<div class="single-use-link">
|
2
|
+
<h1>Single Use Link</h1>
|
3
|
+
<p>Anyone can use the following link once to download the file</p>
|
4
|
+
<%= link_to @asset, @link, :class => 'download-link' %> <%= link_to raw('<i class="icon-link icon-large"></i>'), '#', :class => 'copypaste itemicon itemcode', :title => 'Copy File URL', :id => "copy_link_#{@asset.pid}" %>
|
5
|
+
</div>
|
@@ -1,5 +1,5 @@
|
|
1
1
|
<div >
|
2
|
-
<h1 class="lower"><%= @
|
2
|
+
<h1 class="lower"><%= @asset %></h1>
|
3
3
|
<h2 class="non lower">Actions</h2>
|
4
4
|
<p>
|
5
5
|
<%= link_to "Download (can only be used once)", @download_link %>
|
@@ -10,7 +10,7 @@
|
|
10
10
|
<table class="table table-striped"><!-- class="verticalheadings"> -->
|
11
11
|
<tbody>
|
12
12
|
<% @terms.each do |term| %>
|
13
|
-
<% vals = Array( @
|
13
|
+
<% vals = Array( @asset.send(term)) %>
|
14
14
|
<tr id='row_<%=term.to_s%>' class="expandable">
|
15
15
|
<th width="20%">
|
16
16
|
<%=get_label(term)%>
|
data/config/routes.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
Sufia::Engine.routes.draw do
|
2
|
-
get 'single_use_link/generate_download/:id' => '
|
3
|
-
get 'single_use_link/generate_show/:id' => '
|
4
|
-
get 'single_use_link/show/:id' => '
|
5
|
-
get 'single_use_link/download/:id' => '
|
2
|
+
get 'single_use_link/generate_download/:id' => 'single_use_links#new_download', :as => :generate_download_single_use_link
|
3
|
+
get 'single_use_link/generate_show/:id' => 'single_use_links#new_show', :as => :generate_show_single_use_link
|
4
|
+
get 'single_use_link/show/:id' => 'single_use_links_viewer#show', :as => :show_single_use_link
|
5
|
+
get 'single_use_link/download/:id' => 'single_use_links_viewer#download', :as => :download_single_use_link
|
6
6
|
|
7
7
|
match 'batch_edits/clear' => 'batch_edits#clear', :as => :batch_edits_clear, via: [:get, :post]
|
8
8
|
|
data/lib/sufia/version.rb
CHANGED
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe SingleUseLinksController do
|
4
|
+
before(:all) do
|
5
|
+
@user = FactoryGirl.find_or_create(:user)
|
6
|
+
@file = GenericFile.new
|
7
|
+
@file.add_file(File.open(fixture_path + '/world.png'), 'content', 'world.png')
|
8
|
+
@file.apply_depositor_metadata(@user)
|
9
|
+
@file.save
|
10
|
+
@file2 = GenericFile.new
|
11
|
+
@file2.add_file(File.open(fixture_path + '/world.png'), 'content', 'world.png')
|
12
|
+
@file2.apply_depositor_metadata('mjg36')
|
13
|
+
@file2.save
|
14
|
+
end
|
15
|
+
after(:all) do
|
16
|
+
@file.delete
|
17
|
+
@file2.delete
|
18
|
+
SingleUseLink.delete_all
|
19
|
+
end
|
20
|
+
before do
|
21
|
+
controller.stub(:has_access?).and_return(true)
|
22
|
+
controller.stub(:clear_session_user) ## Don't clear out the authenticated session
|
23
|
+
end
|
24
|
+
describe "logged in user" do
|
25
|
+
before do
|
26
|
+
@user = FactoryGirl.find_or_create(:user)
|
27
|
+
sign_in @user
|
28
|
+
@now = DateTime.now
|
29
|
+
DateTime.stub(:now).and_return(@now)
|
30
|
+
@hash = "some-dummy-sha2-hash"
|
31
|
+
Digest::SHA2.should_receive(:new).and_return(@hash)
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "GET 'download'" do
|
35
|
+
it "and_return http success" do
|
36
|
+
get 'new_download', id:@file.pid
|
37
|
+
response.should be_success
|
38
|
+
assigns[:link].should == @routes.url_helpers.download_single_use_link_path(@hash)
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
describe "GET 'show'" do
|
44
|
+
it "and_return http success" do
|
45
|
+
get 'new_show', id:@file.pid
|
46
|
+
response.should be_success
|
47
|
+
assigns[:link].should == @routes.url_helpers.show_single_use_link_path(@hash)
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe "unkown user" do
|
54
|
+
describe "GET 'download'" do
|
55
|
+
it "and_return http failure" do
|
56
|
+
get 'new_download', id:@file.pid
|
57
|
+
response.should_not be_success
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe "GET 'show'" do
|
62
|
+
it "and_return http failure" do
|
63
|
+
get 'new_show', id:@file.pid
|
64
|
+
response.should_not be_success
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe
|
3
|
+
describe SingleUseLinksViewerController do
|
4
4
|
before(:all) do
|
5
5
|
@user = FactoryGirl.find_or_create(:user)
|
6
6
|
@file = GenericFile.new
|
@@ -13,65 +13,32 @@ describe SingleUseLinkController do
|
|
13
13
|
@file2.save
|
14
14
|
end
|
15
15
|
after(:all) do
|
16
|
-
SingleUseLink.delete_all
|
17
|
-
@user.delete
|
18
16
|
@file.delete
|
19
17
|
@file2.delete
|
18
|
+
SingleUseLink.delete_all
|
20
19
|
end
|
21
20
|
before do
|
22
21
|
controller.stub(:has_access?).and_return(true)
|
23
22
|
controller.stub(:clear_session_user) ## Don't clear out the authenticated session
|
24
23
|
end
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
@now = DateTime.now
|
30
|
-
DateTime.stub(:now).and_return(@now)
|
31
|
-
@hash = "sha2hash"+@now.to_f.to_s
|
32
|
-
Digest::SHA2.should_receive(:new).and_return(@hash)
|
24
|
+
|
25
|
+
describe "retrieval links" do
|
26
|
+
let :show_link do
|
27
|
+
SingleUseLink.create itemId: @file.pid, path: Sufia::Engine.routes.url_helpers.generic_file_path(:id => @file)
|
33
28
|
end
|
34
|
-
|
35
|
-
|
36
|
-
SingleUseLink.
|
37
|
-
@user.delete
|
29
|
+
|
30
|
+
let :download_link do
|
31
|
+
SingleUseLink.create itemId: @file.pid, path: Sufia::Engine.routes.url_helpers.download_path(:id => @file)
|
38
32
|
end
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
response.should be_success
|
43
|
-
assigns[:link].should == @routes.url_helpers.download_single_use_link_path(@hash)
|
44
|
-
end
|
33
|
+
|
34
|
+
let :show_link_hash do
|
35
|
+
show_link.downloadKey
|
45
36
|
end
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
get 'generate_show', id:@file.pid
|
50
|
-
response.should be_success
|
51
|
-
assigns[:link].should == @routes.url_helpers.show_single_use_link_path(@hash)
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
55
|
-
describe "unkown user" do
|
56
|
-
describe "GET 'generate_download'" do
|
57
|
-
it "and_return http failure" do
|
58
|
-
get 'generate_download', id:@file.pid
|
59
|
-
response.should_not be_success
|
60
|
-
end
|
37
|
+
|
38
|
+
let :download_link_hash do
|
39
|
+
download_link.downloadKey
|
61
40
|
end
|
62
|
-
|
63
|
-
describe "GET 'generate_show'" do
|
64
|
-
it "and_return http failure" do
|
65
|
-
get 'generate_show', id:@file.pid
|
66
|
-
response.should_not be_success
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
70
|
-
describe "retrieval links" do
|
71
|
-
before (:each) do
|
72
|
-
@dhash = SingleUseLink.create_download(@file.pid).downloadKey
|
73
|
-
@shash = SingleUseLink.create_show(@file.pid).downloadKey
|
74
|
-
end
|
41
|
+
|
75
42
|
before (:each) do
|
76
43
|
@user.delete
|
77
44
|
end
|
@@ -80,40 +47,42 @@ describe SingleUseLinkController do
|
|
80
47
|
controller.stub(:render)
|
81
48
|
expected_content = ActiveFedora::Base.find(@file.pid).content.content
|
82
49
|
controller.should_receive(:send_file_headers!).with({:filename => 'world.png', :disposition => 'inline', :type => 'image/png' })
|
83
|
-
get :download, id
|
50
|
+
get :download, id:download_link_hash
|
84
51
|
response.body.should == expected_content
|
85
52
|
response.should be_success
|
86
53
|
end
|
87
54
|
it "and_return 404 on second attempt" do
|
88
|
-
get :download, id
|
55
|
+
get :download, id:download_link_hash
|
89
56
|
response.should be_success
|
90
|
-
get :download, id
|
57
|
+
get :download, id:download_link_hash
|
91
58
|
response.should render_template('error/single_use_error')
|
92
59
|
end
|
93
60
|
it "and_return 404 on attempt to get download with show" do
|
94
|
-
get :download, id
|
61
|
+
get :download, id:download_link_hash
|
95
62
|
response.should be_success
|
96
|
-
get :
|
63
|
+
get :show, id:download_link_hash
|
97
64
|
response.should render_template('error/single_use_error')
|
98
65
|
end
|
99
66
|
end
|
100
67
|
|
101
68
|
describe "GET 'show'" do
|
102
69
|
it "and_return http success" do
|
103
|
-
|
70
|
+
|
71
|
+
get 'show', id:show_link_hash
|
104
72
|
response.should be_success
|
105
|
-
assigns[:
|
73
|
+
assigns[:asset].pid.should == @file.pid
|
106
74
|
end
|
107
75
|
it "and_return 404 on second attempt" do
|
108
|
-
get :show, id
|
76
|
+
get :show, id:show_link_hash
|
109
77
|
response.should be_success
|
110
|
-
get :show, id
|
78
|
+
get :show, id:show_link_hash
|
111
79
|
response.should render_template('error/single_use_error')
|
112
80
|
end
|
113
81
|
it "and_return 404 on attempt to get show path with download hash" do
|
114
|
-
get :show, id
|
82
|
+
get :show, id:download_link_hash
|
115
83
|
response.should render_template('error/single_use_error')
|
116
84
|
end
|
117
85
|
end
|
118
86
|
end
|
87
|
+
|
119
88
|
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "Create and use single-use links" do
|
4
|
+
include Warden::Test::Helpers
|
5
|
+
Warden.test_mode!
|
6
|
+
include Sufia::Engine.routes.url_helpers
|
7
|
+
|
8
|
+
before do
|
9
|
+
user = User.find_by_email('jilluser@example.com') || FactoryGirl.create(:user)
|
10
|
+
|
11
|
+
login_as(user, :scope => :user)
|
12
|
+
|
13
|
+
|
14
|
+
@file = GenericFile.new
|
15
|
+
@file.add_file(File.open(fixture_path + '/world.png'), 'content', 'world.png')
|
16
|
+
@file.apply_depositor_metadata(user)
|
17
|
+
@file.save
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should generate a single-use link to show the record" do
|
21
|
+
visit generate_show_single_use_link_path(:id => @file)
|
22
|
+
|
23
|
+
expect(page).to have_css '.single-use-link a'
|
24
|
+
find('.single-use-link a').click
|
25
|
+
expect(page).to have_content 'world.png'
|
26
|
+
expect(page).to have_content "Download (can only be used once)"
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should download the file contents" do
|
30
|
+
|
31
|
+
visit generate_download_single_use_link_path(:id => @file)
|
32
|
+
|
33
|
+
expect(page).to have_css '.download-link'
|
34
|
+
find('.download-link').click
|
35
|
+
expected_content = ActiveFedora::Base.find(@file.pid).content.content
|
36
|
+
expect(page.body).to eq expected_content
|
37
|
+
end
|
38
|
+
end
|
@@ -1,15 +1,19 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe SingleUseLink do
|
4
|
-
before
|
4
|
+
before(:all) do
|
5
5
|
@file = GenericFile.new
|
6
6
|
@file.apply_depositor_metadata('mjg36')
|
7
7
|
@file.save
|
8
8
|
end
|
9
|
+
|
9
10
|
after (:all) do
|
10
|
-
SingleUseLink.find(:all).each{ |l| l.delete}
|
11
11
|
@file.delete
|
12
12
|
end
|
13
|
+
|
14
|
+
let(:file) do
|
15
|
+
@file
|
16
|
+
end
|
13
17
|
|
14
18
|
describe "create" do
|
15
19
|
before do
|
@@ -20,35 +24,32 @@ describe SingleUseLink do
|
|
20
24
|
|
21
25
|
end
|
22
26
|
it "should create show link" do
|
23
|
-
su = SingleUseLink.
|
27
|
+
su = SingleUseLink.create itemId: file.pid, path: Sufia::Engine.routes.url_helpers.generic_file_path(file.pid)
|
24
28
|
su.downloadKey.should == @hash
|
25
|
-
su.itemId.should ==
|
26
|
-
su.path.should == Sufia::Engine.routes.url_helpers.generic_file_path(
|
29
|
+
su.itemId.should == file.pid
|
30
|
+
su.path.should == Sufia::Engine.routes.url_helpers.generic_file_path(file.pid)
|
27
31
|
su.delete
|
28
32
|
end
|
29
33
|
it "should create show download link" do
|
30
|
-
su = SingleUseLink.
|
34
|
+
su = SingleUseLink.create itemId: file.pid, path: Sufia::Engine.routes.url_helpers.download_path(file.pid)
|
31
35
|
su.downloadKey.should == @hash
|
32
|
-
su.itemId.should ==
|
33
|
-
su.path.should == Sufia::Engine.routes.url_helpers.download_path(
|
36
|
+
su.itemId.should == file.pid
|
37
|
+
su.path.should == Sufia::Engine.routes.url_helpers.download_path(file.pid)
|
34
38
|
su.delete
|
35
39
|
end
|
36
40
|
end
|
37
41
|
describe "find" do
|
38
42
|
describe "not expired" do
|
39
43
|
before do
|
40
|
-
@su = SingleUseLink.create(downloadKey:'sha2hashb', itemId
|
41
|
-
end
|
42
|
-
after do
|
43
|
-
@su.delete
|
44
|
+
@su = SingleUseLink.create(downloadKey:'sha2hashb', itemId:file.pid, path:Sufia::Engine.routes.url_helpers.download_path(file.noid), expires:DateTime.now.advance(:hours => 1))
|
44
45
|
end
|
45
46
|
it "should retrieve link" do
|
46
47
|
link = SingleUseLink.where(downloadKey:'sha2hashb').first
|
47
|
-
link.itemId.should ==
|
48
|
+
link.itemId.should == file.pid
|
48
49
|
end
|
49
50
|
it "should retrieve link with find_by" do
|
50
51
|
link = SingleUseLink.find_by_downloadKey('sha2hashb')
|
51
|
-
link.itemId.should ==
|
52
|
+
link.itemId.should == file.pid
|
52
53
|
end
|
53
54
|
it "should expire link" do
|
54
55
|
link = SingleUseLink.where(downloadKey:'sha2hashb').first
|
@@ -57,11 +58,11 @@ describe SingleUseLink do
|
|
57
58
|
end
|
58
59
|
describe "expired" do
|
59
60
|
before do
|
60
|
-
@su = SingleUseLink.create(downloadKey:'sha2hashb', itemId
|
61
|
-
|
62
|
-
|
63
|
-
@su.delete
|
61
|
+
@su = SingleUseLink.create!(downloadKey:'sha2hashb', itemId:file.pid, path:Sufia::Engine.routes.url_helpers.download_path(file.noid))
|
62
|
+
|
63
|
+
@su.update_attribute :expires, DateTime.now.advance(:hours => -1)
|
64
64
|
end
|
65
|
+
|
65
66
|
it "should expire link" do
|
66
67
|
link = SingleUseLink.where(downloadKey:'sha2hashb').first
|
67
68
|
link.expired?.should == true
|
@@ -3,18 +3,6 @@ require 'rails/generators'
|
|
3
3
|
class TestAppGenerator < Rails::Generators::Base
|
4
4
|
source_root File.expand_path("../../../../support", __FILE__)
|
5
5
|
|
6
|
-
def run_blacklight_generator
|
7
|
-
say_status("warning", "GENERATING BL", :yellow)
|
8
|
-
|
9
|
-
generate 'blacklight', '--devise'
|
10
|
-
end
|
11
|
-
|
12
|
-
def run_hydra_head_generator
|
13
|
-
say_status("warning", "GENERATING HH", :yellow)
|
14
|
-
|
15
|
-
generate 'hydra:head', '-f'
|
16
|
-
end
|
17
|
-
|
18
6
|
def run_sufia_generator
|
19
7
|
say_status("warning", "GENERATING SUFIA", :yellow)
|
20
8
|
|
@@ -2,5 +2,9 @@ class DomainTerm < ActiveRecord::Base
|
|
2
2
|
deprecated_attr_accessible :model, :term
|
3
3
|
|
4
4
|
# TODO we should add an index on this join table and remove the uniq query
|
5
|
-
|
5
|
+
if Rails::VERSION::MAJOR > 3
|
6
|
+
has_and_belongs_to_many :local_authorities, -> {uniq}
|
7
|
+
else
|
8
|
+
has_and_belongs_to_many :local_authorities, :uniq=> true
|
9
|
+
end
|
6
10
|
end
|
@@ -2,9 +2,15 @@ require 'rdf'
|
|
2
2
|
require 'rdf/rdfxml'
|
3
3
|
|
4
4
|
class LocalAuthority < ActiveRecord::Base
|
5
|
-
deprecated_attr_accessible
|
6
|
-
|
7
|
-
|
5
|
+
deprecated_attr_accessible :name
|
6
|
+
|
7
|
+
if Rails::VERSION::MAJOR >= 4
|
8
|
+
# TODO we should add an index on this join table and remove the uniq query
|
9
|
+
has_and_belongs_to_many :domain_terms, -> { uniq }
|
10
|
+
else
|
11
|
+
has_and_belongs_to_many :domain_terms, :uniq=> true
|
12
|
+
end
|
13
|
+
|
8
14
|
has_many :local_authority_entries
|
9
15
|
|
10
16
|
def self.harvest_rdf(name, sources, opts = {})
|
@@ -57,7 +63,7 @@ class LocalAuthority < ActiveRecord::Base
|
|
57
63
|
authority = self.find_by_name(name)
|
58
64
|
return if authority.blank?
|
59
65
|
model = model.to_s.sub(/RdfDatastream$/, '').underscore.pluralize
|
60
|
-
domain_term = DomainTerm.
|
66
|
+
domain_term = DomainTerm.find_or_create_by(model: model, term: term)
|
61
67
|
return if domain_term.local_authorities.include? authority
|
62
68
|
domain_term.local_authorities << authority
|
63
69
|
end
|
@@ -1,25 +1,44 @@
|
|
1
1
|
class SingleUseLink < ActiveRecord::Base
|
2
2
|
|
3
|
-
deprecated_attr_accessible
|
3
|
+
deprecated_attr_accessible :downloadKey, :path, :expires, :itemId
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
5
|
+
validate :expiration_date_cannot_be_in_the_past
|
6
|
+
validate :cannot_be_destroyed
|
7
|
+
|
8
|
+
after_initialize :set_defaults
|
9
9
|
|
10
|
-
def
|
11
|
-
|
10
|
+
def create_for_path path
|
11
|
+
self.class.create :itemId => itemId, :path => path
|
12
12
|
end
|
13
|
-
|
13
|
+
|
14
14
|
def expired?
|
15
|
-
|
16
|
-
return (now > expires)
|
15
|
+
DateTime.now > expires
|
17
16
|
end
|
18
|
-
|
17
|
+
|
18
|
+
|
19
|
+
def to_param
|
20
|
+
downloadKey
|
21
|
+
end
|
22
|
+
|
19
23
|
protected
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
+
|
25
|
+
def expiration_date_cannot_be_in_the_past
|
26
|
+
if expired?
|
27
|
+
errors.add(:expires, "can't be in the past")
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def cannot_be_destroyed
|
32
|
+
if destroyed?
|
33
|
+
errors[:base] << "Single Use Link has already been used"
|
34
|
+
end
|
24
35
|
end
|
25
|
-
|
36
|
+
|
37
|
+
def set_defaults
|
38
|
+
if new_record?
|
39
|
+
self.expires ||= DateTime.now.advance(hours:24)
|
40
|
+
self.downloadKey ||= (Digest::SHA2.new << rand(1000000000).to_s).to_s
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
@@ -37,7 +37,7 @@ Gem::Specification.new do |spec|
|
|
37
37
|
spec.add_dependency 'resque-pool', '0.3.0'
|
38
38
|
spec.add_dependency 'noid', '~> 0.6.6'
|
39
39
|
spec.add_dependency 'mailboxer', '~> 0.11.0'
|
40
|
-
spec.add_dependency 'acts_as_follower', '0.1.1'
|
40
|
+
spec.add_dependency 'acts_as_follower', '>= 0.1.1', '< 0.3'
|
41
41
|
spec.add_dependency 'paperclip', '~> 3.4.0'
|
42
42
|
spec.add_dependency 'zipruby', '0.3.6'
|
43
43
|
spec.add_dependency 'hydra-derivatives', '~> 0.0.5'
|
data/sufia.gemspec
CHANGED
@@ -18,7 +18,7 @@ Gem::Specification.new do |gem|
|
|
18
18
|
gem.license = 'APACHE2'
|
19
19
|
|
20
20
|
gem.add_dependency 'sufia-models', version
|
21
|
-
gem.add_dependency 'blacklight', '~> 4.0'
|
21
|
+
gem.add_dependency 'blacklight', '~> 4.0', '< 4.4' # blacklight 4.4.1/0 doesn't work with kaminari > 0.14.1
|
22
22
|
gem.add_dependency 'blacklight_advanced_search', '~> 2.1.0'
|
23
23
|
|
24
24
|
gem.add_dependency 'hydra-batch-edit', '~> 1.0'
|
data/tasks/release.rake
CHANGED
@@ -32,7 +32,6 @@ tag = "v#{version}"
|
|
32
32
|
File.open(file, 'w') { |f| f.write ruby }
|
33
33
|
end
|
34
34
|
end
|
35
|
-
task :pkg
|
36
35
|
task gem => %w(update_version_rb pkg) do
|
37
36
|
cmd = ""
|
38
37
|
cmd << "cd #{framework} && " unless framework == "sufia"
|
@@ -48,7 +47,7 @@ tag = "v#{version}"
|
|
48
47
|
task :prep_release => [:ensure_clean_state, :build]
|
49
48
|
|
50
49
|
task :push => :build do
|
51
|
-
|
50
|
+
sh "gem push #{gem}"
|
52
51
|
end
|
53
52
|
end
|
54
53
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sufia
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Justin Coyne
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-09-
|
11
|
+
date: 2013-09-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sufia-models
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - '='
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 3.
|
19
|
+
version: 3.3.0
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - '='
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 3.
|
26
|
+
version: 3.3.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: blacklight
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -31,6 +31,9 @@ dependencies:
|
|
31
31
|
- - ~>
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '4.0'
|
34
|
+
- - <
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: '4.4'
|
34
37
|
type: :runtime
|
35
38
|
prerelease: false
|
36
39
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -38,6 +41,9 @@ dependencies:
|
|
38
41
|
- - ~>
|
39
42
|
- !ruby/object:Gem::Version
|
40
43
|
version: '4.0'
|
44
|
+
- - <
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '4.4'
|
41
47
|
- !ruby/object:Gem::Dependency
|
42
48
|
name: blacklight_advanced_search
|
43
49
|
requirement: !ruby/object:Gem::Requirement
|
@@ -268,7 +274,8 @@ files:
|
|
268
274
|
- app/controllers/errors_controller.rb
|
269
275
|
- app/controllers/generic_files_controller.rb
|
270
276
|
- app/controllers/mailbox_controller.rb
|
271
|
-
- app/controllers/
|
277
|
+
- app/controllers/single_use_links_controller.rb
|
278
|
+
- app/controllers/single_use_links_viewer_controller.rb
|
272
279
|
- app/controllers/static_controller.rb
|
273
280
|
- app/controllers/users_controller.rb
|
274
281
|
- app/helpers/batch_edits_helper.rb
|
@@ -445,9 +452,9 @@ files:
|
|
445
452
|
- app/views/layouts/sufia-one-column.html.erb
|
446
453
|
- app/views/layouts/sufia-two-column.html.erb
|
447
454
|
- app/views/mailbox/index.html.erb
|
448
|
-
- app/views/
|
449
|
-
- app/views/
|
450
|
-
- app/views/
|
455
|
+
- app/views/single_use_links/new_download.html.erb
|
456
|
+
- app/views/single_use_links/new_show.html.erb
|
457
|
+
- app/views/single_use_links_viewer/show.html.erb
|
451
458
|
- app/views/static/about.html.erb
|
452
459
|
- app/views/static/agreement.html.erb
|
453
460
|
- app/views/static/help.html.erb
|
@@ -516,7 +523,8 @@ files:
|
|
516
523
|
- spec/controllers/downloads_controller_spec.rb
|
517
524
|
- spec/controllers/generic_files_controller_spec.rb
|
518
525
|
- spec/controllers/mailbox_controller_spec.rb
|
519
|
-
- spec/controllers/
|
526
|
+
- spec/controllers/single_use_links_controller_spec.rb
|
527
|
+
- spec/controllers/single_use_links_viewer_controller_spec.rb
|
520
528
|
- spec/controllers/users_controller_spec.rb
|
521
529
|
- spec/factories/checksum_audit_logs.rb
|
522
530
|
- spec/factories/single_use_links.rb
|
@@ -526,6 +534,7 @@ files:
|
|
526
534
|
- spec/features/contact_form.rb
|
527
535
|
- spec/features/display_dashboard.rb
|
528
536
|
- spec/features/ingest_upload_files.rb
|
537
|
+
- spec/features/single_use_links_spec.rb
|
529
538
|
- spec/features/users_spec.rb
|
530
539
|
- spec/fixtures/4-20.png
|
531
540
|
- spec/fixtures/Example.ogg
|
@@ -754,7 +763,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
754
763
|
version: '0'
|
755
764
|
requirements: []
|
756
765
|
rubyforge_project:
|
757
|
-
rubygems_version: 2.0.
|
766
|
+
rubygems_version: 2.0.5
|
758
767
|
signing_key:
|
759
768
|
specification_version: 4
|
760
769
|
summary: Sufia was extracted from ScholarSphere developed by Penn State University
|
@@ -770,7 +779,8 @@ test_files:
|
|
770
779
|
- spec/controllers/downloads_controller_spec.rb
|
771
780
|
- spec/controllers/generic_files_controller_spec.rb
|
772
781
|
- spec/controllers/mailbox_controller_spec.rb
|
773
|
-
- spec/controllers/
|
782
|
+
- spec/controllers/single_use_links_controller_spec.rb
|
783
|
+
- spec/controllers/single_use_links_viewer_controller_spec.rb
|
774
784
|
- spec/controllers/users_controller_spec.rb
|
775
785
|
- spec/factories/checksum_audit_logs.rb
|
776
786
|
- spec/factories/single_use_links.rb
|
@@ -780,6 +790,7 @@ test_files:
|
|
780
790
|
- spec/features/contact_form.rb
|
781
791
|
- spec/features/display_dashboard.rb
|
782
792
|
- spec/features/ingest_upload_files.rb
|
793
|
+
- spec/features/single_use_links_spec.rb
|
783
794
|
- spec/features/users_spec.rb
|
784
795
|
- spec/fixtures/4-20.png
|
785
796
|
- spec/fixtures/Example.ogg
|
@@ -866,3 +877,4 @@ test_files:
|
|
866
877
|
- spec/support/lib/generators/test_app_generator.rb
|
867
878
|
- spec/support/uploaded_file_monkeypatch.rb
|
868
879
|
- spec/views/batch_edits/check_all_spec.rb
|
880
|
+
has_rdoc:
|
@@ -1,95 +0,0 @@
|
|
1
|
-
require 'sufia/single_use_error'
|
2
|
-
|
3
|
-
class SingleUseLinkController < DownloadsController
|
4
|
-
before_filter :authenticate_user!, :except => [:download, :show]
|
5
|
-
before_filter :find_file, :only => [:generate_download, :generate_show]
|
6
|
-
before_filter :authorize_user!, :only => [:generate_download, :generate_show]
|
7
|
-
skip_filter :normalize_identifier, :load_asset, :load_datastream
|
8
|
-
prepend_before_filter :normalize_identifier, :except => [:download, :show]
|
9
|
-
rescue_from Sufia::SingleUseError, :with => :render_single_use_error
|
10
|
-
|
11
|
-
def generate_download
|
12
|
-
@su = SingleUseLink.create_download(params[:id])
|
13
|
-
@link = sufia.download_single_use_link_path(@su.downloadKey)
|
14
|
-
respond_to do |format|
|
15
|
-
format.html
|
16
|
-
format.js {render :js => @link}
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
def generate_show
|
21
|
-
@su = SingleUseLink.create_show(params[:id])
|
22
|
-
@link = sufia.show_single_use_link_path(@su.downloadKey)
|
23
|
-
respond_to do |format|
|
24
|
-
format.html
|
25
|
-
format.js {render :js => @link}
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
def download
|
30
|
-
#look up the item
|
31
|
-
link = lookup_hash
|
32
|
-
|
33
|
-
#grab the item id
|
34
|
-
id = link.itemId
|
35
|
-
|
36
|
-
#check to make sure the path matches
|
37
|
-
not_found if link.path != sufia.download_path(id)
|
38
|
-
|
39
|
-
# send the data content
|
40
|
-
@asset = GenericFile.load_instance_from_solr(id)
|
41
|
-
load_datastream
|
42
|
-
send_content(asset)
|
43
|
-
end
|
44
|
-
|
45
|
-
def show
|
46
|
-
link = lookup_hash
|
47
|
-
|
48
|
-
#grab the item id
|
49
|
-
id = link.itemId
|
50
|
-
|
51
|
-
#check to make sure the path matches
|
52
|
-
not_found if link.path != sufia.generic_file_path(id)
|
53
|
-
|
54
|
-
#show the file
|
55
|
-
@generic_file = GenericFile.load_instance_from_solr(id)
|
56
|
-
@terms = @generic_file.terms_for_display
|
57
|
-
|
58
|
-
# create a dowload link that is single use for the user since we do not just want to show metadata we want to access it too
|
59
|
-
@su = SingleUseLink.create_download(id)
|
60
|
-
@download_link = sufia.download_single_use_link_path(@su.downloadKey)
|
61
|
-
end
|
62
|
-
|
63
|
-
protected
|
64
|
-
|
65
|
-
def authorize_user!
|
66
|
-
authorize! :read, @generic_file
|
67
|
-
end
|
68
|
-
|
69
|
-
def find_file
|
70
|
-
@generic_file = GenericFile.load_instance_from_solr(params[:id])
|
71
|
-
end
|
72
|
-
|
73
|
-
def lookup_hash
|
74
|
-
id = params[:id]
|
75
|
-
# invalid hash send not found
|
76
|
-
link = SingleUseLink.where(downloadKey:id).first || not_found
|
77
|
-
|
78
|
-
# expired hash send not found
|
79
|
-
now = DateTime.now
|
80
|
-
not_found if link.expires <= now
|
81
|
-
|
82
|
-
# delete the link since it has been used
|
83
|
-
link.destroy
|
84
|
-
|
85
|
-
return link
|
86
|
-
end
|
87
|
-
|
88
|
-
def not_found
|
89
|
-
raise Sufia::SingleUseError.new('Single-Use Link Not Found')
|
90
|
-
end
|
91
|
-
|
92
|
-
def expired
|
93
|
-
raise Sufia::SingleUseError.new('Single-Use Link Expired')
|
94
|
-
end
|
95
|
-
end
|
@@ -1,3 +0,0 @@
|
|
1
|
-
<h1>Single Use Link</h1>
|
2
|
-
<p>Anyone can use the following link once to download the file</p>
|
3
|
-
<%= link_to @generic_file, @link %> <%= link_to raw('<i class="icon-link icon-large"></i>'), '#', :class => 'copypaste itemicon itemcode', :title => 'Copy File URL', :id => "copy_link_#{@generic_file.pid}" %>
|