sufia 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
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