sufia 0.0.2 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. data/README.md +3 -0
  2. data/app/assets/javascripts/sufia.js +11 -0
  3. data/app/assets/stylesheets/sufia.css +1 -0
  4. data/app/controllers/batch_edits_controller.rb +1 -1
  5. data/app/controllers/downloads_controller.rb +1 -65
  6. data/app/controllers/generic_files_controller.rb +1 -296
  7. data/app/models/datastreams/generic_file_rdf_datastream.rb +0 -4
  8. data/app/views/_ga.html.erb +2 -2
  9. data/app/views/batch/edit.html.erb +1 -13
  10. data/app/views/batch_edits/edit.html.erb +0 -8
  11. data/app/views/catalog/index.html.erb +1 -1
  12. data/app/views/dashboard/index.html.erb +0 -19
  13. data/app/views/generic_files/_media_display.html.erb +6 -6
  14. data/app/views/generic_files/_show_actions.html.erb +37 -0
  15. data/app/views/generic_files/_show_descriptions.html.erb +118 -0
  16. data/app/views/generic_files/_show_details.html.erb +67 -0
  17. data/app/views/generic_files/edit.html.erb +6 -19
  18. data/app/views/generic_files/show.html.erb +3 -236
  19. data/app/views/users/edit.html.erb +0 -6
  20. data/lib/generators/sufia/templates/catalog_controller.rb +2 -2
  21. data/lib/generators/sufia/templates/config/sufia.rb +3 -0
  22. data/lib/sufia.rb +10 -8
  23. data/lib/sufia/downloads_controller_behavior.rb +77 -0
  24. data/lib/sufia/files_controller_behavior.rb +245 -0
  25. data/lib/sufia/generic_file.rb +9 -15
  26. data/lib/sufia/version.rb +1 -1
  27. data/spec/controllers/generic_files_controller_spec.rb +9 -19
  28. data/spec/models/generic_file_spec.rb +2 -3
  29. metadata +7 -7
  30. data/app/assets/javascripts/batch.js +0 -26
  31. data/app/assets/javascripts/bootstrap-button.js +0 -96
  32. data/app/assets/javascripts/bootstrap-dropdown.js +0 -100
  33. data/app/assets/javascripts/bootstrap-modal.js +0 -218
  34. data/app/assets/javascripts/dashboard.js +0 -40
@@ -14,12 +14,6 @@ See the License for the specific language governing permissions and
14
14
  limitations under the License.
15
15
  %>
16
16
 
17
- <% content_for :js_head do %>
18
-
19
- <%= javascript_include_tag 'bootstrap-tooltip.js'%>
20
- <%= javascript_include_tag 'bootstrap-popover.js'%>
21
- <% end %>
22
-
23
17
  <% content_for :local_js do %>
24
18
  // initialize popover helpers
25
19
  $("a[rel=popover]").popover();
@@ -290,8 +290,8 @@ class CatalogController < ApplicationController
290
290
  :"spellcheck.dictionary" => "format"
291
291
  }
292
292
  field.solr_local_parameters = {
293
- :qf => "generic_file__format_t",
294
- :pf => "generic_file__format_t"
293
+ :qf => "file_format_t",
294
+ :pf => "file_format_t"
295
295
  }
296
296
  end
297
297
 
@@ -95,6 +95,9 @@ Sufia.config do |config|
95
95
 
96
96
  config.queue = Sufia::Resque::Queue
97
97
 
98
+ # Map hostnames onto Google Analytics tracking IDs
99
+ #config.google_analytics_id = 'UA-99999999-1'
100
+
98
101
  end
99
102
 
100
103
 
@@ -68,13 +68,15 @@ module Sufia
68
68
  end
69
69
 
70
70
  autoload :GenericFile
71
- autoload :Controller, 'sufia/controller'
72
- autoload :Utils, 'sufia/utils'
73
- autoload :User, 'sufia/user'
74
- autoload :ModelMethods, 'sufia/model_methods'
75
- autoload :Noid, 'sufia/noid'
76
- autoload :IdService, 'sufia/id_service'
77
- autoload :HttpHeaderAuth, 'sufia/http_header_auth'
78
- autoload :SolrDocumentBehavior, 'sufia/solr_document_behavior'
71
+ autoload :Controller
72
+ autoload :Utils
73
+ autoload :User
74
+ autoload :ModelMethods
75
+ autoload :Noid
76
+ autoload :IdService
77
+ autoload :HttpHeaderAuth
78
+ autoload :SolrDocumentBehavior
79
+ autoload :FilesControllerBehavior
80
+ autoload :DownloadsControllerBehavior
79
81
  end
80
82
 
@@ -0,0 +1,77 @@
1
+ # Copyright © 2012 The Pennsylvania State University
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ module Sufia
16
+ module DownloadsControllerBehavior
17
+ extend ActiveSupport::Concern
18
+
19
+ included do
20
+ # module mixes in normalize_identifier method
21
+ include Sufia::Noid
22
+
23
+ # moved check into the routine so we can handle the user with no access
24
+ prepend_before_filter :normalize_identifier
25
+ end
26
+
27
+ def show
28
+ if can? :read, params["id"]
29
+ logger.info "Can read #{params['id']}"
30
+
31
+ send_content (params["id"])
32
+ return
33
+ else
34
+ logger.info "Can not read #{params['id']}"
35
+ redirect_to "/assets/NoAccess.png"
36
+ end
37
+ end
38
+
39
+ protected
40
+
41
+ def send_content (id)
42
+ @asset = ActiveFedora::Base.find(id, :cast=>true)
43
+ opts = {}
44
+ ds = nil
45
+ opts[:filename] = params["filename"] || @asset.label
46
+ opts[:disposition] = 'inline'
47
+ if params.has_key?(:datastream_id)
48
+ opts[:filename] = params[:datastream_id]
49
+ ds = @asset.datastreams[params[:datastream_id]]
50
+ end
51
+ ds = default_content_ds(@asset) if ds.nil?
52
+ raise ActionController::RoutingError.new('Not Found') if ds.nil?
53
+ data = ds.content
54
+ opts[:type] = ds.mimeType
55
+ send_data data, opts
56
+ return
57
+ end
58
+
59
+
60
+ private
61
+
62
+ def default_content_ds(asset)
63
+ ActiveFedora::ContentModel.known_models_for(asset).each do |model_class|
64
+ return model_class.default_content_ds if model_class.respond_to?(:default_content_ds)
65
+ end
66
+ if asset.datastreams.keys.include?(DownloadsController.default_content_dsid)
67
+ return asset.datastreams[DownloadsController.default_content_dsid]
68
+ end
69
+ end
70
+
71
+ module ClassMethods
72
+ def default_content_dsid
73
+ "content"
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,245 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright © 2012 The Pennsylvania State University
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ module Sufia
17
+ module FilesControllerBehavior
18
+ extend ActiveSupport::Concern
19
+
20
+ included do
21
+ include Hydra::Controller::ControllerBehavior
22
+ include Hydra::Controller::UploadBehavior # for add_posted_blob_to_asset method
23
+ include Blacklight::Configurable # comply with BL 3.7
24
+ include Sufia::Noid # for normalize_identifier method
25
+
26
+ # This is needed as of BL 3.7
27
+ self.copy_blacklight_config_from(CatalogController)
28
+
29
+ # Catch permission errors
30
+ rescue_from Hydra::AccessDenied, CanCan::AccessDenied do |exception|
31
+ if (exception.action == :edit)
32
+ redirect_to(sufia.url_for({:action=>'show'}), :alert => "You do not have sufficient privileges to edit this document")
33
+ elsif current_user and current_user.persisted?
34
+ redirect_to root_url, :alert => exception.message
35
+ else
36
+ session["user_return_to"] = request.url
37
+ redirect_to new_user_session_url, :alert => exception.message
38
+ end
39
+ end
40
+
41
+ # actions: audit, index, create, new, edit, show, update, destroy, permissions, citation
42
+ before_filter :authenticate_user!, :except => [:show, :citation]
43
+ before_filter :has_access?, :except => [:show]
44
+ prepend_before_filter :normalize_identifier, :except => [:index, :create, :new]
45
+ load_resource :only=>[:audit]
46
+ load_and_authorize_resource :except=>[:index, :audit]
47
+ end
48
+
49
+
50
+ # routed to /files/new
51
+ def new
52
+ @generic_file = ::GenericFile.new
53
+ @batch_noid = Sufia::Noid.noidify(Sufia::IdService.mint)
54
+ end
55
+
56
+ # routed to /files/:id/edit
57
+ def edit
58
+ @terms = @generic_file.get_terms
59
+ @groups = current_user.groups
60
+ end
61
+
62
+ # routed to /files/:id
63
+ def index
64
+ @generic_files = ::GenericFile.find(:all, :rows => ::GenericFile.count)
65
+ render :json => @generic_files.map(&:to_jq_upload).to_json
66
+ end
67
+
68
+ # routed to /files/:id (DELETE)
69
+ def destroy
70
+ pid = @generic_file.noid
71
+ @generic_file.delete
72
+ Sufia.queue.push(ContentDeleteEventJob.new(pid, current_user.user_key))
73
+ redirect_to sufia.dashboard_index_path, :notice => render_to_string(:partial=>'generic_files/asset_deleted_flash', :locals => { :generic_file => @generic_file })
74
+ end
75
+
76
+ # routed to /files (POST)
77
+ def create
78
+ begin
79
+ retval = " "
80
+ # check error condition No files
81
+ if !params.has_key?(:files)
82
+ retval = render :json => [{:error => "Error! No file to save"}].to_json
83
+
84
+ # check error condition empty file
85
+ elsif ((params[:files][0].respond_to?(:tempfile)) && (params[:files][0].tempfile.size == 0))
86
+ retval = render :json => [{ :name => params[:files][0].original_filename, :error => "Error! Zero Length File!"}].to_json
87
+
88
+ elsif ((params[:files][0].respond_to?(:size)) && (params[:files][0].size == 0))
89
+ retval = render :json => [{ :name => params[:files][0].original_filename, :error => "Error! Zero Length File!"}].to_json
90
+
91
+ elsif (params[:terms_of_service] != '1')
92
+ retval = render :json => [{ :name => params[:files][0].original_filename, :error => "You must accept the terms of service!"}].to_json
93
+
94
+ # process file
95
+ else
96
+ create_and_save_generic_file
97
+ if @generic_file
98
+ Sufia.queue.push(ContentDepositEventJob.new(@generic_file.pid, current_user.user_key))
99
+ respond_to do |format|
100
+ format.html {
101
+ retval = render :json => [@generic_file.to_jq_upload].to_json,
102
+ :content_type => 'text/html',
103
+ :layout => false
104
+ }
105
+ format.json {
106
+ retval = render :json => [@generic_file.to_jq_upload].to_json
107
+ }
108
+ end
109
+ else
110
+ retval = render :json => [{:error => "Error creating generic file."}].to_json
111
+ end
112
+ end
113
+ rescue => error
114
+ logger.error "GenericFilesController::create rescued #{error.class}\n\t#{error.to_s}\n #{error.backtrace.join("\n")}\n\n"
115
+ retval = render :json => [{:error => "Error occurred while creating generic file."}].to_json
116
+ ensure
117
+ # remove the tempfile (only if it is a temp file)
118
+ params[:files][0].tempfile.delete if params[:files][0].respond_to?(:tempfile)
119
+ end
120
+
121
+ return retval
122
+ end
123
+
124
+ # routed to /files/:id/citation
125
+ def citation
126
+ end
127
+
128
+ # routed to /files/:id
129
+ def show
130
+ @can_edit = can? :edit, @generic_file
131
+ @events = @generic_file.events(100)
132
+
133
+ respond_to do |format|
134
+ format.html
135
+ format.endnote { render :text => @generic_file.export_as_endnote }
136
+ end
137
+ end
138
+
139
+ # routed to /files/:id/audit (POST)
140
+ def audit
141
+ render :json=>@generic_file.audit
142
+ end
143
+
144
+ # routed to /files/:id (PUT)
145
+ def update
146
+ version_event = false
147
+
148
+ if params.has_key?(:revision) and params[:revision] != @generic_file.content.latest_version.versionID
149
+ revision = @generic_file.content.get_version(params[:revision])
150
+ @generic_file.add_file_datastream(revision.content, :dsid => 'content')
151
+ version_event = true
152
+ Sufia.queue.push(ContentRestoredVersionEventJob.new(@generic_file.pid, current_user.user_key, params[:revision]))
153
+ end
154
+
155
+ if params.has_key?(:filedata)
156
+ return unless virus_check(params[:filedata]) == 0
157
+ add_posted_blob_to_asset(@generic_file, params[:filedata])
158
+ version_event = true
159
+ Sufia.queue.push(ContentNewVersionEventJob.new(@generic_file.pid, current_user.user_key))
160
+ end
161
+ @generic_file.attributes = params[:generic_file].reject { |k,v| %w{ Filedata Filename revision part_of date_modified date_uploaded format }.include? k}
162
+ @generic_file.set_visibility(params[:visibility])
163
+ @generic_file.date_modified = Time.now.ctime
164
+ @generic_file.save!
165
+ # do not trigger an update event if a version event has already been triggered
166
+ Sufia.queue.push(ContentUpdateEventJob.new(@generic_file.pid, current_user.user_key)) unless version_event
167
+ record_version_committer(@generic_file, current_user)
168
+ redirect_to sufia.edit_generic_file_path(:tab => params[:redirect_tab]), :notice => render_to_string(:partial=>'generic_files/asset_updated_flash', :locals => { :generic_file => @generic_file })
169
+
170
+ end
171
+
172
+ protected
173
+ def record_version_committer(generic_file, user)
174
+ version = generic_file.content.latest_version
175
+ # content datastream not (yet?) present
176
+ return if version.nil?
177
+ VersionCommitter.create(:obj_id => version.pid,
178
+ :datastream_id => version.dsid,
179
+ :version_id => version.versionID,
180
+ :committer_login => user.user_key)
181
+ end
182
+
183
+ def virus_check( file)
184
+ if defined? ClamAV
185
+ stat = ClamAV.instance.scanfile(file.path)
186
+ flash[:error] = "Virus checking did not pass for #{file.original_filename} status = #{stat}" unless stat == 0
187
+ logger.warn "Virus checking did not pass for #{file.inspect} status = #{stat}" unless stat == 0
188
+ stat
189
+ else
190
+ logger.warn "Virus checking disabled for #{file.inspect}"
191
+ 0
192
+ end
193
+ end
194
+
195
+ def create_and_save_generic_file
196
+ unless params.has_key?(:files)
197
+ logger.warn "!!!! No Files !!!!"
198
+ return
199
+ end
200
+ file = params[:files][0]
201
+ return nil unless virus_check(file) == 0
202
+
203
+ @generic_file = ::GenericFile.new
204
+ @generic_file.terms_of_service = params[:terms_of_service]
205
+ # if we want to be able to save zero length files then we can use this to make the file 1 byte instead of zero length and fedora will take it
206
+ #if (file.tempfile.size == 0)
207
+ # logger.warn "Encountered an empty file... Creating a new temp file with on space."
208
+ # f = Tempfile.new ("emptyfile")
209
+ # f.write " "
210
+ # f.rewind
211
+ # file.tempfile = f
212
+ #end
213
+ add_posted_blob_to_asset(@generic_file,file)
214
+
215
+ @generic_file.apply_depositor_metadata(user_key)
216
+ @generic_file.date_uploaded = Time.now.ctime
217
+ @generic_file.date_modified = Time.now.ctime
218
+ @generic_file.relative_path = params[:relative_path] if params.has_key?(:relative_path)
219
+ @generic_file.creator = current_user.name
220
+
221
+ if params.has_key?(:batch_id)
222
+ batch_id = Sufia::Noid.namespaceize(params[:batch_id])
223
+ @generic_file.add_relationship("isPartOf", "info:fedora/#{batch_id}")
224
+ else
225
+ logger.warn "unable to find batch to attach to"
226
+ end
227
+
228
+ save_tries = 0
229
+ begin
230
+ @generic_file.save
231
+ rescue RSolr::Error::Http => error
232
+ logger.warn "GenericFilesController::create_and_save_generic_file Caught RSOLR error #{error.inspect}"
233
+ save_tries+=1
234
+ # fail for good if the tries is greater than 3
235
+ rescue_action_without_handler(error) if save_tries >=3
236
+ sleep 0.01
237
+ retry
238
+ end
239
+
240
+ record_version_committer(@generic_file, current_user)
241
+ Sufia.queue.push(UnzipJob.new(@generic_file.pid)) if file.content_type == 'application/zip'
242
+ return @generic_file
243
+ end
244
+ end
245
+ end
@@ -32,12 +32,13 @@ module Sufia
32
32
  delegate_to :descMetadata, [:date_uploaded, :date_modified], :unique => true
33
33
  delegate_to :descMetadata, [:related_url, :based_near, :part_of, :creator,
34
34
  :contributor, :title, :tag, :description, :rights,
35
- :publisher, :date_created, :subject, :format,
35
+ :publisher, :date_created, :subject,
36
36
  :resource_type, :identifier, :language]
37
37
  around_save :characterize_if_changed, :retry_warming
38
38
 
39
39
  #make sure the terms of service is present and set to 1 before saving
40
40
  validates_acceptance_of :terms_of_service, :allow_nil => false
41
+ after_find :preset_terms
41
42
  end
42
43
 
43
44
  def pdf?
@@ -160,7 +161,7 @@ module Sufia
160
161
  terms.each do |t|
161
162
  next if t.empty?
162
163
  key = t.to_s.split("generic_file__").last
163
- next if ['part_of', 'date_modified', 'date_uploaded', 'format'].include?(key)
164
+ next if ['part_of', 'date_modified', 'date_uploaded'].include?(key)
164
165
  values[key] = self.send(key) if self.respond_to?(key)
165
166
  end
166
167
  return values
@@ -173,26 +174,19 @@ module Sufia
173
174
  return (!self.batch.status.empty?) && (self.batch.status.count == 1) && (self.batch.status[0] == "processing")
174
175
  end
175
176
 
177
+ def preset_terms
178
+ self.terms_of_service = '1'
179
+ end
180
+
176
181
  module ClassMethods
177
- @@FIELD_LABEL_MAP = {"based_near"=>"Location", 'description'=>"Abstract or Summary", 'tag'=>"Keyword", 'date_created'=>"Date Created", 'related_url'=>"Related URL"}
182
+ # TODO this could probably be better handled by i18n
183
+ @@FIELD_LABEL_MAP = {"based_near"=>"Location", 'description'=>"Abstract or Summary", 'tag'=>"Keyword", 'date_created'=>"Date Created", 'related_url'=>"Related URL"}
178
184
 
179
185
  def get_label(key)
180
186
  label = @@FIELD_LABEL_MAP[key]
181
187
  label = key.gsub('_',' ').titleize if label.blank?
182
188
  return label
183
189
  end
184
-
185
- # redefine find so that it sets the terms of service
186
- def find(args, opts={})
187
- gf = super
188
- # use the field type to see if the return will be one item or multiple
189
- if args.is_a? String
190
- gf.terms_of_service = '1'
191
- elsif gf.respond_to? :each
192
- gf.each {|f| f.terms_of_service = '1'}
193
- end
194
- return gf
195
- end
196
190
  end
197
191
 
198
192
  end
@@ -1,3 +1,3 @@
1
1
  module Sufia
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
3
3
  end
@@ -188,8 +188,7 @@ describe GenericFilesController do
188
188
 
189
189
  describe "destroy" do
190
190
  before(:each) do
191
- GenericFile.any_instance.stub(:terms_of_service).and_return('1')
192
- @generic_file = GenericFile.new
191
+ @generic_file = GenericFile.new(:terms_of_service => '1')
193
192
  @generic_file.apply_depositor_metadata(@user.user_key)
194
193
  @generic_file.save
195
194
  @user = FactoryGirl.find_or_create(:user)
@@ -213,9 +212,8 @@ describe GenericFilesController do
213
212
 
214
213
  describe "update" do
215
214
  before do
216
- GenericFile.any_instance.stub(:terms_of_service).and_return('1')
217
215
  #controller.should_receive(:virus_check).and_return(0)
218
- @generic_file = GenericFile.new
216
+ @generic_file = GenericFile.new(:terms_of_service=>'1')
219
217
  @generic_file.apply_depositor_metadata(@user.user_key)
220
218
  @generic_file.save
221
219
  end
@@ -335,9 +333,8 @@ describe GenericFilesController do
335
333
  end
336
334
 
337
335
  describe "someone elses files" do
338
- before(:all) do
339
- GenericFile.any_instance.stub(:terms_of_service).and_return('1')
340
- f = GenericFile.new(:pid => 'sufia:test5')
336
+ before do
337
+ f = GenericFile.new(:pid => 'sufia:test5', :terms_of_service=> '1')
341
338
  f.apply_depositor_metadata('archivist1@example.com')
342
339
  f.set_title_and_label('world.png')
343
340
  f.add_file_datastream(File.new(fixture_path + '/world.png'))
@@ -347,8 +344,8 @@ describe GenericFilesController do
347
344
  f.save
348
345
  @file = f
349
346
  end
350
- after(:all) do
351
- GenericFile.find('sufia:test5').delete
347
+ after do
348
+ GenericFile.find('sufia:test5').destroy
352
349
  end
353
350
  describe "edit" do
354
351
  it "should give me a flash error" do
@@ -367,7 +364,6 @@ describe GenericFilesController do
367
364
  end
368
365
  end
369
366
  describe "flash" do
370
- render_views
371
367
  it "should not let the user submit if they logout" do
372
368
  sign_out @user
373
369
  get :new
@@ -376,23 +372,17 @@ describe GenericFilesController do
376
372
  flash[:alert].should include("You need to sign in or sign up before continuing")
377
373
  end
378
374
  it "should filter flash if they signin" do
379
- request.env['warden'].stub(:user).and_return(@user)
380
- sign_out @user
381
- get :new
382
375
  sign_in @user
383
376
  get :show, id:"test5"
384
- response.body.should_not include("You need to sign in or sign up before continuing")
377
+ flash[:alert].should be_nil
385
378
  end
386
379
  describe "failing audit" do
387
- before(:all) do
380
+ render_views
381
+ before do
388
382
  ActiveFedora::RelsExtDatastream.any_instance.stub(:dsChecksumValid).and_return(false)
389
383
  @archivist = FactoryGirl.find_or_create(:archivist)
390
384
  end
391
- after(:all) do
392
- @archivist.delete
393
- end
394
385
  it "should display failing audits" do
395
- sign_out @user
396
386
  sign_in @archivist
397
387
  @ds = @file.datastreams.first
398
388
  AuditJob.new(@file.pid, @ds[0], @ds[1].versionID).run