curation_concerns 0.12.0.pre1 → 0.12.0.pre2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (212) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +24 -16
  3. data/Gemfile +0 -4
  4. data/README.md +14 -0
  5. data/RELEASING.md +2 -2
  6. data/Rakefile +2 -0
  7. data/app/actors/concerns/curation_concerns/manages_embargoes_actor.rb +28 -0
  8. data/app/actors/curation_concerns/abstract_actor.rb +28 -0
  9. data/app/actors/curation_concerns/add_to_collection_actor.rb +38 -0
  10. data/app/actors/curation_concerns/apply_order_actor.rb +24 -0
  11. data/app/actors/curation_concerns/assign_identifier_actor.rb +7 -0
  12. data/app/actors/curation_concerns/assign_representative_actor.rb +18 -0
  13. data/app/actors/curation_concerns/attach_files_actor.rb +39 -0
  14. data/app/actors/curation_concerns/base_actor.rb +71 -0
  15. data/app/actors/curation_concerns/embargo_actor.rb +19 -0
  16. data/app/actors/curation_concerns/file_actor.rb +79 -0
  17. data/app/actors/curation_concerns/file_set_actor.rb +146 -0
  18. data/app/actors/curation_concerns/interpret_visibility_actor.rb +123 -0
  19. data/app/actors/curation_concerns/lease_actor.rb +19 -0
  20. data/app/actors/curation_concerns/root_actor.rb +17 -0
  21. data/app/actors/curation_concerns/work_actor_behavior.rb +8 -0
  22. data/app/assets/javascripts/curation_concerns/batch_select.js +42 -0
  23. data/app/assets/javascripts/curation_concerns/collections.js +13 -0
  24. data/app/assets/javascripts/curation_concerns/curation_concerns.js +2 -0
  25. data/app/assets/stylesheets/curation_concerns/_curation_concerns.scss +0 -3
  26. data/app/assets/stylesheets/curation_concerns/_modules.scss +1 -1
  27. data/app/assets/stylesheets/curation_concerns/_positioning.scss +3 -6
  28. data/app/assets/stylesheets/curation_concerns/_theme.scss +0 -39
  29. data/app/assets/stylesheets/curation_concerns/_typography.scss +0 -69
  30. data/app/assets/stylesheets/curation_concerns/modules/classify_work.scss +0 -2
  31. data/app/assets/stylesheets/curation_concerns/modules/collections.scss +4 -0
  32. data/app/assets/stylesheets/curation_concerns/modules/forms.scss +0 -4
  33. data/app/assets/stylesheets/curation_concerns/modules/site_actions.scss +34 -29
  34. data/app/assets/stylesheets/curation_concerns/modules/site_search.scss +0 -46
  35. data/app/assets/stylesheets/curation_concerns.scss +4 -0
  36. data/app/controllers/concerns/curation_concerns/collections_controller_behavior.rb +166 -21
  37. data/app/controllers/concerns/curation_concerns/embargoes_controller_behavior.rb +1 -1
  38. data/app/controllers/concerns/curation_concerns/leases_controller_behavior.rb +1 -1
  39. data/app/controllers/concerns/curation_concerns/selects_collections.rb +65 -0
  40. data/app/forms/curation_concerns/forms/collection_edit_form.rb +0 -29
  41. data/app/forms/curation_concerns/forms/work_form.rb +2 -1
  42. data/app/helpers/batch_select_helper.rb +23 -0
  43. data/app/helpers/collections_helper.rb +4 -0
  44. data/app/helpers/curation_concerns/collections_helper.rb +2 -2
  45. data/app/helpers/curation_concerns/collections_helper_behavior.rb +56 -0
  46. data/app/helpers/curation_concerns/render_constraints_helper.rb +14 -35
  47. data/app/helpers/curation_concerns/title_helper.rb +4 -0
  48. data/app/indexers/curation_concerns/collection_indexer.rb +16 -0
  49. data/app/indexers/curation_concerns/file_set_indexer.rb +46 -0
  50. data/app/indexers/curation_concerns/work_indexer.rb +15 -0
  51. data/app/jobs/audit_job.rb +49 -0
  52. data/app/jobs/characterize_job.rb +11 -0
  53. data/app/jobs/create_derivatives_job.rb +21 -0
  54. data/app/jobs/import_url_job.rb +48 -0
  55. data/app/jobs/ingest_file_job.rb +30 -0
  56. data/app/jobs/ingest_local_file_job.rb +20 -0
  57. data/app/jobs/resolrize_job.rb +7 -0
  58. data/app/models/checksum_audit_log.rb +20 -0
  59. data/app/models/collection.rb +6 -0
  60. data/app/models/concerns/curation_concerns/ability.rb +49 -0
  61. data/app/models/concerns/curation_concerns/basic_metadata.rb +64 -0
  62. data/app/models/concerns/curation_concerns/collection.rb +16 -0
  63. data/app/models/concerns/curation_concerns/collection_behavior.rb +62 -0
  64. data/app/models/concerns/curation_concerns/file_set/belongs_to_works.rb +47 -0
  65. data/app/models/concerns/curation_concerns/file_set/derivatives.rb +65 -0
  66. data/app/models/concerns/curation_concerns/file_set/full_text_indexing.rb +11 -0
  67. data/app/models/concerns/curation_concerns/file_set/indexing.rb +14 -0
  68. data/app/models/concerns/curation_concerns/file_set/querying.rb +17 -0
  69. data/app/models/concerns/curation_concerns/file_set_behavior.rb +36 -0
  70. data/app/models/concerns/curation_concerns/has_representative.rb +13 -0
  71. data/app/models/concerns/curation_concerns/human_readable_type.rb +17 -0
  72. data/app/models/concerns/curation_concerns/naming.rb +17 -0
  73. data/app/models/concerns/curation_concerns/permissions/readable.rb +18 -0
  74. data/app/models/concerns/curation_concerns/permissions/writable.rb +34 -0
  75. data/app/models/concerns/curation_concerns/permissions.rb +7 -0
  76. data/app/models/concerns/curation_concerns/required_metadata.rb +30 -0
  77. data/app/models/concerns/curation_concerns/serializers.rb +13 -0
  78. data/app/models/concerns/curation_concerns/solr_document_behavior.rb +147 -0
  79. data/app/models/concerns/curation_concerns/user.rb +18 -0
  80. data/app/models/concerns/curation_concerns/with_file_sets.rb +37 -0
  81. data/app/models/concerns/curation_concerns/work_behavior.rb +45 -0
  82. data/app/models/curation_concerns/classify_concern.rb +49 -0
  83. data/app/models/curation_concerns/quick_classification_query.rb +38 -0
  84. data/app/models/single_use_link.rb +34 -0
  85. data/app/models/version_committer.rb +2 -0
  86. data/app/search_builders/curation_concerns/collection_member_search_builder.rb +1 -1
  87. data/app/search_builders/curation_concerns/collection_search_builder.rb +33 -0
  88. data/app/search_builders/curation_concerns/member_search_builder.rb +17 -0
  89. data/app/services/curation_concerns/derivative_path.rb +49 -0
  90. data/app/services/curation_concerns/file_set_audit_service.rb +105 -0
  91. data/app/services/curation_concerns/indexes_thumbnails.rb +30 -0
  92. data/app/services/curation_concerns/local_file_service.rb +10 -0
  93. data/app/services/curation_concerns/lock_manager.rb +39 -0
  94. data/app/services/curation_concerns/lockable.rb +16 -0
  95. data/app/services/curation_concerns/noid.rb +23 -0
  96. data/app/services/curation_concerns/persist_derivatives.rb +33 -0
  97. data/app/services/curation_concerns/persist_directly_contained_output_file_service.rb +26 -0
  98. data/app/services/curation_concerns/repository_audit_service.rb +7 -0
  99. data/app/services/curation_concerns/thumbnail_path_service.rb +46 -0
  100. data/app/services/curation_concerns/time_service.rb +7 -0
  101. data/app/services/curation_concerns/versioning_service.rb +26 -0
  102. data/app/validators/has_one_title_validator.rb +8 -0
  103. data/app/views/batch_select/_add_button.html.erb +3 -0
  104. data/app/views/batch_select/_check_all.html.erb +4 -0
  105. data/app/views/batch_select/_tools.html.erb +10 -0
  106. data/app/views/catalog/_action_menu_partials/_collection.html.erb +3 -3
  107. data/app/views/catalog/_action_menu_partials/_default.html.erb +1 -1
  108. data/app/views/catalog/_document_list.html.erb +1 -1
  109. data/app/views/collections/_bookmark_control.html.erb +2 -0
  110. data/app/views/collections/_button_create_collection.html.erb +2 -0
  111. data/app/views/collections/_button_for_creating_empty_collection.html.erb +1 -1
  112. data/app/views/collections/_button_for_delete_collection.html.erb +4 -0
  113. data/app/views/collections/_button_for_remove_selected_from_collection.html.erb +8 -0
  114. data/app/views/collections/_button_for_update_collection.html.erb +4 -0
  115. data/app/views/collections/_button_remove_from_collection.html.erb +4 -0
  116. data/app/views/collections/_document_header.html.erb +9 -0
  117. data/app/views/collections/_edit_actions.html.erb +1 -1
  118. data/app/views/collections/_edit_descriptions.html.erb +1 -1
  119. data/app/views/collections/_form.html.erb +2 -2
  120. data/app/views/collections/_form_for_select_destination_collection.html.erb +21 -0
  121. data/app/views/collections/_form_to_add_member.html.erb +1 -1
  122. data/app/views/collections/_index_default.html.erb +2 -0
  123. data/app/views/collections/_index_header_default.html.erb +2 -0
  124. data/app/views/collections/_media_display.html.erb +1 -1
  125. data/app/views/collections/_paginate.html.erb +1 -1
  126. data/app/views/collections/_paginate_compact.html.erb +1 -0
  127. data/app/views/collections/_results_pagination.html.erb +9 -0
  128. data/app/views/collections/_search_collection_dashboard_form.html.erb +1 -1
  129. data/app/views/collections/_search_form.html.erb +1 -1
  130. data/app/views/collections/_search_results.html.erb +23 -0
  131. data/app/views/collections/_show_actions.html.erb +1 -1
  132. data/app/views/collections/_sort_and_per_page.html.erb +1 -1
  133. data/app/views/collections/_view_type_group.html.erb +1 -1
  134. data/app/views/collections/index.html.erb +9 -0
  135. data/app/views/collections/new.html.erb +3 -0
  136. data/app/views/curation_concerns/base/_form_permission.html.erb +10 -11
  137. data/app/views/curation_concerns/base/_form_permission_embargo.html.erb +1 -1
  138. data/app/views/curation_concerns/base/_form_permission_lease.html.erb +1 -1
  139. data/app/views/curation_concerns/base/_legally_binding_text.html.erb +7 -7
  140. data/app/views/curation_concerns/base/_related_files.html.erb +1 -1
  141. data/app/views/curation_concerns/base/_visibility.html.erb +2 -2
  142. data/app/views/curation_concerns/file_sets/_actions.html.erb +1 -1
  143. data/app/views/embargoes/_list_expired_active_embargoes.html.erb +1 -1
  144. data/app/views/error/single_use_error.html.erb +1 -1
  145. data/app/views/shared/_add_content.html.erb +17 -15
  146. data/app/views/shared/_brand_bar.html.erb +19 -10
  147. data/app/views/shared/_header.html.erb +2 -6
  148. data/app/views/shared/_my_actions.html.erb +28 -27
  149. data/app/views/shared/_site_actions.html.erb +5 -1
  150. data/app/views/shared/_site_search.html.erb +3 -2
  151. data/app/views/shared/_title_bar.html.erb +7 -16
  152. data/app/views/welcome/index.html.erb +2 -2
  153. data/config/locales/curation_concerns.en.yml +25 -1
  154. data/curation_concerns.gemspec +21 -5
  155. data/lib/curation_concerns/collections/accepts_batches.rb +53 -0
  156. data/lib/curation_concerns/collections/search_service.rb +57 -0
  157. data/lib/curation_concerns/collections.rb +10 -0
  158. data/lib/curation_concerns/configuration.rb +167 -0
  159. data/lib/curation_concerns/engine.rb +22 -1
  160. data/lib/curation_concerns/messages.rb +68 -0
  161. data/lib/curation_concerns/models.rb +42 -0
  162. data/lib/curation_concerns/name.rb +20 -0
  163. data/lib/curation_concerns/null_logger.rb +10 -0
  164. data/lib/curation_concerns/rails/routes.rb +1 -3
  165. data/lib/curation_concerns/version.rb +1 -1
  166. data/lib/curation_concerns.rb +2 -0
  167. data/lib/generators/curation_concerns/abstract_migration_generator.rb +31 -0
  168. data/lib/generators/curation_concerns/clamav_generator.rb +19 -0
  169. data/lib/generators/curation_concerns/collection_generator.rb +15 -0
  170. data/lib/generators/curation_concerns/install_generator.rb +1 -2
  171. data/lib/generators/curation_concerns/models_generator.rb +62 -0
  172. data/lib/generators/curation_concerns/templates/app/models/collection.rb +6 -0
  173. data/lib/generators/curation_concerns/templates/app/models/file_set.rb +4 -0
  174. data/lib/generators/curation_concerns/templates/config/clamav.rb +1 -0
  175. data/lib/generators/curation_concerns/templates/config/curation_concerns.rb +61 -0
  176. data/lib/generators/curation_concerns/templates/config/mime_types.rb +6 -0
  177. data/lib/generators/curation_concerns/templates/config/redis.yml +9 -0
  178. data/lib/generators/curation_concerns/templates/config/redis_config.rb +29 -0
  179. data/lib/generators/curation_concerns/templates/config/resque-pool.yml +1 -0
  180. data/lib/generators/curation_concerns/templates/config/resque_config.rb +6 -0
  181. data/lib/generators/curation_concerns/templates/curation_concerns.scss +3 -2
  182. data/lib/generators/curation_concerns/templates/migrations/create_checksum_audit_logs.rb +19 -0
  183. data/lib/generators/curation_concerns/templates/migrations/create_single_use_links.rb +12 -0
  184. data/lib/generators/curation_concerns/templates/migrations/create_version_committers.rb +15 -0
  185. data/lib/tasks/migrate.rake +11 -0
  186. data/lib/tasks/resque.rake +14 -0
  187. data/lib/tasks/solr_reindex.rake +8 -0
  188. data/spec/actors/curation_concerns/file_set_actor_spec.rb +31 -0
  189. data/spec/controllers/accepts_batches_controller_spec.rb +65 -0
  190. data/spec/controllers/collections_controller_spec.rb +272 -0
  191. data/spec/controllers/curation_concerns/collections_controller_spec.rb +1 -2
  192. data/spec/controllers/selects_collections_controller_spec.rb +109 -0
  193. data/spec/features/create_work_spec.rb +1 -1
  194. data/spec/features/work_generator_spec.rb +1 -1
  195. data/spec/forms/collection_edit_form_spec.rb +2 -9
  196. data/spec/forms/work_form_spec.rb +5 -0
  197. data/spec/helpers/collections_helper_spec.rb +129 -0
  198. data/spec/helpers/curation_concerns/collections_helper_spec.rb +2 -2
  199. data/spec/helpers/render_constraints_helper_spec.rb +23 -1
  200. data/spec/lib/curation_concerns/collections/search_service_spec.rb +33 -0
  201. data/spec/models/collection_spec.rb +165 -0
  202. data/spec/tasks/rake_spec.rb +1 -1
  203. data/spec/test_app_templates/lib/generators/test_app_generator.rb +1 -1
  204. data/spec/views/curation_concerns/base/_form_permission.html.erb_spec.rb +4 -1
  205. data/spec/views/curation_concerns/file_sets/show.html.erb_spec.rb +1 -0
  206. data/spec/views/shared/_add_content.html.erb_spec.rb +3 -3
  207. metadata +341 -24
  208. data/VERSION +0 -1
  209. data/app/assets/stylesheets/curation_concerns/_global-variables.scss +0 -5
  210. data/app/assets/stylesheets/curation_concerns/modules/multi_value_fields.scss +0 -52
  211. data/app/views/collections/_form_required_information.html.erb +0 -11
  212. data/tasks/release.rake +0 -93
@@ -0,0 +1,61 @@
1
+ CurationConcerns.configure do |config|
2
+ # Should schema.org microdata be displayed?
3
+ # config.display_microdata = true
4
+
5
+ # What default microdata type should be used if a more appropriate
6
+ # type can not be found in the locale file?
7
+ # config.microdata_default_type = 'http://schema.org/CreativeWork'
8
+
9
+ # How frequently should a file be audited.
10
+ # Note: In CurationConcerns you must trigger the FileSetAuditService manually.
11
+ # config.max_days_between_audits = 7
12
+
13
+ # Enable displaying usage statistics in the UI
14
+ # Requires a Google Analytics id and OAuth2 keyfile. See README for more info
15
+ # config.analytics = false
16
+
17
+ # Specify a Google Analytics tracking ID to gather usage statistics
18
+ # config.google_analytics_id = 'UA-99999999-1'
19
+
20
+ # Specify a date you wish to start collecting Google Analytic statistics for.
21
+ # config.analytic_start_date = DateTime.new(2014,9,10)
22
+
23
+ # Where to store tempfiles, leave blank for the system temp directory (e.g. /tmp)
24
+ # config.temp_file_base = '/home/developer1'
25
+
26
+ # Location on local file system where derivatives will be stored.
27
+ # If you use a multi-server architecture, this MUST be a shared volume.
28
+ # config.derivatives_path = File.join(Rails.root, 'tmp', 'derivatives')
29
+
30
+ # Location on local file system where uploaded files will be staged
31
+ # prior to being ingested into the repository or having derivatives generated.
32
+ # If you use a multi-server architecture, this MUST be a shared volume.
33
+ # config.working_path = File.join(Rails.root, 'tmp', 'uploads')
34
+
35
+ # If you have ffmpeg installed and want to transcode audio and video uncomment this line
36
+ # config.enable_ffmpeg = true
37
+
38
+ # CurationConcerns uses NOIDs for files and collections instead of Fedora UUIDs
39
+ # where NOID = 10-character string and UUID = 32-character string w/ hyphens
40
+ # config.enable_noids = true
41
+
42
+ # Specify a different template for your repository's NOID IDs
43
+ # config.noid_template = ".reeddeeddk"
44
+
45
+ # Store identifier minter's state in a file for later replayability
46
+ # If you use a multi-server architecture, this MUST be on a shared volume.
47
+ # config.minter_statefile = '/tmp/minter-state'
48
+
49
+ # Specify the prefix for Redis keys:
50
+ # config.redis_namespace = "curation_concerns"
51
+
52
+ # Specify the path to the file characterization tool:
53
+ # config.fits_path = "fits.sh"
54
+
55
+ # Specify a date you wish to start collecting Google Analytic statistics for.
56
+ # Leaving it blank will set the start date to when ever the file was uploaded by
57
+ # NOTE: if you have always sent analytics to GA for downloads and page views leave this commented out
58
+ # config.analytic_start_date = DateTime.new(2014,9,10)
59
+ end
60
+
61
+ Date::DATE_FORMATS[:standard] = '%m/%d/%Y'
@@ -0,0 +1,6 @@
1
+ # Be sure to restart your server when you modify this file.
2
+
3
+ # Add new mime types for use in respond_to blocks:
4
+ # Mime::Type.register "text/richtext", :rtf
5
+ # Mime::Type.register_alias "text/html", :iphone
6
+ Mime::Type.register 'application/x-endnote-refer', :endnote
@@ -0,0 +1,9 @@
1
+ development:
2
+ host: localhost
3
+ port: 6379
4
+ test:
5
+ host: localhost
6
+ port: 6379
7
+ production:
8
+ host: localhost
9
+ port: 6379
@@ -0,0 +1,29 @@
1
+ if defined?(PhusionPassenger)
2
+ PhusionPassenger.on_event(:starting_worker_process) do |forked|
3
+ # We're in smart spawning mode.
4
+ if forked
5
+ # Re-establish redis connection
6
+ require 'redis'
7
+ config = YAML.load(ERB.new(IO.read(File.join(Rails.root, 'config', 'redis.yml'))).result)[Rails.env].with_indifferent_access
8
+
9
+ # The important two lines
10
+ Redis.current.disconnect!
11
+ Redis.current = begin
12
+ Redis.new(config.merge(thread_safe: true))
13
+ rescue
14
+ nil
15
+ end
16
+ Resque.redis = Redis.current
17
+ Resque.redis.namespace = "#{CurationConcerns.config.redis_namespace}:#{Rails.env}"
18
+ Resque.redis.client.reconnect if Resque.redis
19
+ end
20
+ end
21
+ else
22
+ config = YAML.load(ERB.new(IO.read(File.join(Rails.root, 'config', 'redis.yml'))).result)[Rails.env].with_indifferent_access
23
+ require 'redis'
24
+ Redis.current = begin
25
+ Redis.new(config.merge(thread_safe: true))
26
+ rescue
27
+ nil
28
+ end
29
+ end
@@ -0,0 +1,6 @@
1
+ require 'resque'
2
+ config = YAML.load(ERB.new(IO.read(File.join(Rails.root, 'config', 'redis.yml'))).result)[Rails.env].with_indifferent_access
3
+ Resque.redis = Redis.new(host: config[:host], port: config[:port], thread_safe: true)
4
+
5
+ Resque.inline = Rails.env.test?
6
+ Resque.redis.namespace = "#{CurationConcerns.config.redis_namespace}:#{Rails.env}"
@@ -1,3 +1,4 @@
1
- //@import 'blacklight/blacklight';
2
- @import 'curation_concerns/curation_concerns';
1
+ @import 'bootstrap-sprockets';
2
+ @import 'bootstrap';
3
3
 
4
+ @import 'curation_concerns/curation_concerns';
@@ -0,0 +1,19 @@
1
+ class CreateChecksumAuditLogs < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :checksum_audit_logs do |t|
4
+ t.string :file_set_id
5
+ t.string :file_id
6
+ t.string :version
7
+ t.integer :pass
8
+ t.string :expected_result
9
+ t.string :actual_result
10
+ t.timestamps
11
+ end
12
+ add_index :checksum_audit_logs, [:file_set_id, :file_id], name: 'by_file_set_id_and_file_id', order: { created_at: 'DESC' }
13
+ end
14
+
15
+ def self.down
16
+ remove_index(:checksum_audit_logs, name: 'by_file_set_id_and_file_id')
17
+ drop_table :checksum_audit_logs
18
+ end
19
+ end
@@ -0,0 +1,12 @@
1
+ class CreateSingleUseLinks < ActiveRecord::Migration
2
+ def change
3
+ create_table :single_use_links do |t|
4
+ t.string :downloadKey
5
+ t.string :path
6
+ t.string :itemId
7
+ t.datetime :expires
8
+
9
+ t.timestamps
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,15 @@
1
+ class CreateVersionCommitters < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :version_committers do |t|
4
+ t.string :obj_id
5
+ t.string :datastream_id
6
+ t.string :version_id
7
+ t.string :committer_login
8
+ t.timestamps
9
+ end
10
+ end
11
+
12
+ def self.down
13
+ drop_table :version_committers
14
+ end
15
+ end
@@ -0,0 +1,11 @@
1
+ namespace :curation_concerns do
2
+ namespace :migrate do
3
+ desc "Migrate audit logs"
4
+ task audit_logs: :environment do
5
+ ChecksumAuditLog.all.each do |cs|
6
+ cs.file_set_id = cs.file_set_id.delete "#{CurationConcerns.config.redis_namespace}:"
7
+ cs.save
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,14 @@
1
+ require 'resque/pool/tasks'
2
+
3
+ # This provides access to the Rails env within all Resque workers
4
+ task 'resque:setup' => :environment
5
+
6
+ # Set up resque-pool
7
+ task 'resque:pool:setup' do
8
+ ActiveRecord::Base.connection.disconnect!
9
+ require 'resque/pool'
10
+ Resque::Pool.after_prefork do |job|
11
+ ActiveRecord::Base.establish_connection
12
+ Resque.redis.client.reconnect
13
+ end
14
+ end
@@ -0,0 +1,8 @@
1
+ namespace :curation_concerns do
2
+ namespace :solr do
3
+ desc "Enqueue a job to resolrize the repository objects"
4
+ task reindex: :environment do
5
+ ResolrizeJob.perform_later
6
+ end
7
+ end
8
+ end
@@ -253,4 +253,35 @@ describe CurationConcerns::FileSetActor do
253
253
  end
254
254
  end
255
255
  end
256
+
257
+ describe "#file_actor_class" do
258
+ context "default" do
259
+ it "is a FileActor" do
260
+ expect(actor.file_actor_class).to eq(CurationConcerns::FileActor)
261
+ end
262
+ end
263
+
264
+ context "overridden" do
265
+ let(:actor) { CustomFileSetActor.new(file_set, user) }
266
+
267
+ before do
268
+ class CustomFileActor < CurationConcerns::FileActor
269
+ end
270
+ class CustomFileSetActor < CurationConcerns::FileSetActor
271
+ def file_actor_class
272
+ CustomFileActor
273
+ end
274
+ end
275
+ end
276
+
277
+ after do
278
+ Object.send(:remove_const, :CustomFileActor)
279
+ Object.send(:remove_const, :CustomFileSetActor)
280
+ end
281
+
282
+ it "is a custom class" do
283
+ expect(actor.file_actor_class).to eq(CustomFileActor)
284
+ end
285
+ end
286
+ end
256
287
  end
@@ -0,0 +1,65 @@
1
+ require 'spec_helper'
2
+
3
+ class AcceptsBatchesController < ApplicationController
4
+ include CurationConcerns::Collections::AcceptsBatches
5
+ end
6
+
7
+ describe AcceptsBatchesController, type: :controller do
8
+ describe 'batch' do
9
+ it 'accepts batch from parameters' do
10
+ controller.params['batch_document_ids'] = %w(abc xyz)
11
+ expect(controller.batch).to eq(%w(abc xyz))
12
+ end
13
+ describe ':all' do
14
+ let(:current_user) { double(user_key: 'vanessa') }
15
+ before do
16
+ doc1 = double(id: 123)
17
+ doc2 = double(id: 456)
18
+ expect_any_instance_of(CurationConcerns::Collections::SearchService).to receive(:last_search_documents).and_return([doc1, doc2])
19
+ allow(controller).to receive(:current_user).and_return(current_user)
20
+ end
21
+ it 'adds every document in the current resultset to the batch' do
22
+ controller.params['batch_document_ids'] = 'all'
23
+ expect(controller.batch).to eq([123, 456])
24
+ end
25
+ end
26
+ end
27
+
28
+ describe 'should allow filtering for access' do
29
+ before do
30
+ @allowed = [1, 2, 3]
31
+ @disallowed = [5, 6, 7]
32
+ subject.batch = @allowed + @disallowed
33
+ end
34
+ it 'using filter_docs_with_access!' do
35
+ @allowed.each { |doc_id| expect(subject).to receive(:can?).with(:foo, doc_id).and_return(true) }
36
+ @disallowed.each { |doc_id| expect(subject).to receive(:can?).with(:foo, doc_id).and_return(false) }
37
+ subject.send(:filter_docs_with_access!, :foo)
38
+ expect(flash[:notice]).to eq("You do not have permission to edit the documents: #{@disallowed.join(', ')}")
39
+ end
40
+ it 'using filter_docs_with_edit_access!' do
41
+ @allowed.each { |doc_id| expect(subject).to receive(:can?).with(:edit, doc_id).and_return(true) }
42
+ @disallowed.each { |doc_id| expect(subject).to receive(:can?).with(:edit, doc_id).and_return(false) }
43
+ subject.send(:filter_docs_with_edit_access!)
44
+ expect(flash[:notice]).to eq("You do not have permission to edit the documents: #{@disallowed.join(', ')}")
45
+ end
46
+ it 'using filter_docs_with_read_access!' do
47
+ @allowed.each { |doc_id| expect(subject).to receive(:can?).with(:read, doc_id).and_return(true) }
48
+ @disallowed.each { |doc_id| expect(subject).to receive(:can?).with(:read, doc_id).and_return(false) }
49
+ subject.send(:filter_docs_with_read_access!)
50
+ expect(flash[:notice]).to eq("You do not have permission to edit the documents: #{@disallowed.join(', ')}")
51
+ end
52
+ it "and be sassy if you didn't select anything" do
53
+ subject.batch = []
54
+ subject.send(:filter_docs_with_read_access!)
55
+ expect(flash[:notice]).to eq('Select something first')
56
+ end
57
+ end
58
+
59
+ it 'checks for empty' do
60
+ controller.batch = %w(77826928 94120425)
61
+ expect(controller.check_for_empty_batch?).to eq(false)
62
+ controller.batch = []
63
+ expect(controller.check_for_empty_batch?).to eq(true)
64
+ end
65
+ end
@@ -0,0 +1,272 @@
1
+ require 'spec_helper'
2
+
3
+ describe CollectionsController, type: :controller do
4
+ let(:user) { FactoryGirl.create(:user) }
5
+
6
+ before do
7
+ allow(controller).to receive(:has_access?).and_return(true)
8
+
9
+ sign_in user
10
+ allow_any_instance_of(User).to receive(:groups).and_return([])
11
+ allow(controller).to receive(:clear_session_user) ## Don't clear out the authenticated session
12
+ end
13
+
14
+ describe '#index' do
15
+ let!(:collection1) { FactoryGirl.create(:collection, title: ['Beta'], user: user) }
16
+ let!(:collection2) { FactoryGirl.create(:collection, title: ['Alpha'], user: user) }
17
+ let!(:generic_file) { create(:generic_work, user: user) }
18
+
19
+ it 'shows a list of collections sorted alphabetically' do
20
+ get :index
21
+ expect(response).to be_successful
22
+ expect(assigns[:document_list].map(&:id)).not_to include generic_file.id
23
+ expect(assigns[:document_list].map(&:id)).to match_array [collection2.id, collection1.id]
24
+ end
25
+ end
26
+
27
+ describe '#new' do
28
+ it 'assigns @collection' do
29
+ get :new
30
+ expect(assigns(:collection)).to be_kind_of(Collection)
31
+ end
32
+ end
33
+
34
+ describe '#create' do
35
+ it 'creates a Collection' do
36
+ expect do
37
+ post :create, collection: { title: ['My First Collection'],
38
+ description: ["The Description\r\n\r\nand more"] }
39
+ end.to change { Collection.count }.by(1)
40
+ expect(assigns[:collection].title).to eq ['My First Collection']
41
+ expect(assigns[:collection].description).to eq ["The Description\r\n\r\nand more"]
42
+ expect(assigns[:collection].depositor).to eq(user.user_key)
43
+ expect(response).to redirect_to collection_path(assigns[:collection])
44
+ end
45
+
46
+ it 'adds docs to collection if batch ids provided' do
47
+ @asset1 = create(:generic_work, user: user)
48
+ @asset2 = create(:generic_work, user: user)
49
+ post :create, batch_document_ids: [@asset1, @asset2],
50
+ collection: { title: ['My Secong Collection'],
51
+ description: ["The Description\r\n\r\nand more"] }
52
+ expect(assigns[:collection].members).to eq [@asset1, @asset2]
53
+ end
54
+
55
+ it 'calls after_create' do
56
+ expect(controller).to receive(:after_create).and_call_original
57
+ post :create, collection: { title: ['My First Collection'],
58
+ description: ["The Description\r\n\r\nand more"] }
59
+ end
60
+
61
+ it 'adds one doc to collection if batch ids provided and add the collection id to the document in the colledction' do
62
+ @asset1 = create(:generic_work, user: user)
63
+ post :create, batch_document_ids: [@asset1],
64
+ collection: { title: ['My Second Collection'],
65
+ description: ["The Description\r\n\r\nand more"] }
66
+ expect(assigns[:collection].members).to eq [@asset1]
67
+ asset_results = ActiveFedora::SolrService.instance.conn.get 'select', params: { fq: ["id:\"#{@asset1.id}\""], fl: ['id', Solrizer.solr_name(:collection)] }
68
+ expect(asset_results['response']['numFound']).to eq(1)
69
+ doc = asset_results['response']['docs'].first
70
+ expect(doc['id']).to eq @asset1.id
71
+ afterupdate = GenericWork.find(@asset1.id)
72
+ expect(doc[Solrizer.solr_name(:collection)]).to eq(afterupdate.to_solr[Solrizer.solr_name(:collection)])
73
+ end
74
+
75
+ it 'adds docs to collection if batch ids provided and add the collection id to the documents int he colledction' do
76
+ @asset1 = create(:generic_work, user: user)
77
+ @asset2 = create(:generic_work, user: user)
78
+ post :create, batch_document_ids: [@asset1, @asset2],
79
+ collection: { title: ['My Secong Collection'],
80
+ description: ["The Description\r\n\r\nand more"] }
81
+ expect(assigns[:collection].members).to eq [@asset1, @asset2]
82
+ asset_results = ActiveFedora::SolrService.instance.conn.get 'select', params: { fq: ["id:\"#{@asset1.id}\""], fl: ['id', Solrizer.solr_name(:collection)] }
83
+ expect(asset_results['response']['numFound']).to eq(1)
84
+ doc = asset_results['response']['docs'].first
85
+ expect(doc['id']).to eq(@asset1.id)
86
+ afterupdate = GenericWork.find(@asset1.id)
87
+ expect(doc[Solrizer.solr_name(:collection)]).to eq(afterupdate.to_solr[Solrizer.solr_name(:collection)])
88
+ end
89
+ end
90
+
91
+ describe '#update' do
92
+ let(:collection) { FactoryGirl.create(:collection, user: user) }
93
+ before do
94
+ @asset1 = create(:generic_work, user: user)
95
+ @asset2 = create(:generic_work, user: user)
96
+ @asset3 = create(:generic_work, user: user)
97
+ end
98
+
99
+ it 'updates collection metadata' do
100
+ put :update, id: collection.id, collection: { title: ['New Title'], description: ['New Description'] }
101
+ expect(response).to redirect_to collection_path(collection)
102
+ expect(assigns[:collection].title).to eq(['New Title'])
103
+ expect(assigns[:collection].description).to eq(['New Description'])
104
+ end
105
+
106
+ it 'calls after_update' do
107
+ expect(controller).to receive(:after_update).and_call_original
108
+ put :update, id: collection.id, collection: { title: ['New Title'], description: ['New Description'] }
109
+ end
110
+
111
+ context 'when updating fails' do
112
+ before do
113
+ allow_any_instance_of(Collection).to receive(:save).and_return(false)
114
+ end
115
+ it 'renders edit succesfully' do
116
+ put :update, id: collection.id, collection: { title: ['New Title'] }
117
+ expect(response).to render_template 'edit'
118
+ end
119
+ end
120
+
121
+ context 'when there are existing members in the collection' do
122
+ it 'supports adding batches of members' do
123
+ collection.members << @asset1
124
+ collection.save!
125
+ put :update, id: collection, collection: { members: 'add' }, batch_document_ids: [@asset2, @asset3]
126
+ expect(response).to redirect_to collection_path(collection)
127
+ expect(assigns[:collection].members).to match_array [@asset2, @asset3, @asset1]
128
+ end
129
+
130
+ it 'supports removing batches of members' do
131
+ collection.members = [@asset1, @asset2, @asset3]
132
+ collection.save!
133
+ put :update, id: collection, collection: { members: 'remove' }, batch_document_ids: [@asset1, @asset3]
134
+ expect(response).to redirect_to collection_path(collection)
135
+ expect(assigns[:collection].members).to eq([@asset2])
136
+ end
137
+ end
138
+
139
+ it 'supports setting members array' do
140
+ put :update, id: collection, collection: { members: 'add' }, batch_document_ids: [@asset2, @asset3, @asset1]
141
+ expect(response).to redirect_to collection_path(collection)
142
+ expect(assigns[:collection].members).to match_array [@asset2, @asset3, @asset1]
143
+ end
144
+
145
+ it 'set/un-sets collection on members' do
146
+ # Add to collection (sets collection on members)
147
+ put :update, id: collection, collection: { members: 'add' }, batch_document_ids: [@asset2, @asset3]
148
+ expect(assigns[:collection].members).to match_array [@asset2, @asset3]
149
+
150
+ # Remove from collection (un-sets collection on members)
151
+ put :update, id: collection, collection: { members: 'remove' }, batch_document_ids: [@asset2]
152
+ expect(assigns[:collection].members).not_to include(@asset2)
153
+ end
154
+
155
+ context 'when moving members between collections' do
156
+ before do
157
+ collection.members = [@asset1, @asset2, @asset3]
158
+ collection.save!
159
+ end
160
+ let(:collection2) do
161
+ Collection.create(title: ['Some Collection']) do |col|
162
+ col.apply_depositor_metadata(user.user_key)
163
+ end
164
+ end
165
+
166
+ it 'moves the members' do
167
+ put :update, id: collection, collection: { members: 'move' },
168
+ destination_collection_id: collection2, batch_document_ids: [@asset2, @asset3]
169
+ expect(collection.reload.members).to eq [@asset1]
170
+ expect(collection2.reload.members).to match_array [@asset2, @asset3]
171
+ end
172
+ end
173
+ end
174
+
175
+ describe '#destroy' do
176
+ describe 'valid collection' do
177
+ let!(:collection) { FactoryGirl.create(:collection, user: user) }
178
+ before do
179
+ expect(controller).to receive(:authorize!).and_return(true)
180
+ end
181
+
182
+ it 'deletes the collection' do
183
+ delete :destroy, id: collection
184
+ expect(response).to redirect_to Rails.application.routes.url_helpers.search_catalog_path
185
+ expect(flash[:notice]).to eq('Collection was successfully deleted.')
186
+ end
187
+
188
+ it 'calls after_destroy' do
189
+ expect(controller).to receive(:after_destroy).and_call_original
190
+ delete :destroy, id: collection
191
+ end
192
+
193
+ it 'updates members' do
194
+ asset1 = create(:generic_work, user: user)
195
+ collection.members << asset1
196
+ collection.save!
197
+ expect(asset1.in_collections).to eq [collection]
198
+
199
+ delete :destroy, id: collection
200
+ expect(asset1.in_collections).to eq []
201
+ end
202
+ end
203
+
204
+ it 'does not delete an invalid collection' do
205
+ expect { delete :destroy, id: 'zz:-1' }.to raise_error
206
+ end
207
+ end
208
+
209
+ describe '#show' do
210
+ context 'when there are no assets in the collection' do
211
+ let(:collection) { FactoryGirl.create(:collection, user: user) }
212
+ it 'shows no assets' do
213
+ get :show, id: collection
214
+ expect(response).to be_successful
215
+ expect(assigns[:presenter].id).to eq collection.id
216
+ expect(assigns[:member_docs]).to be_empty
217
+ end
218
+ end
219
+
220
+ context 'with a number of assets' do
221
+ let(:asset1) { create(:generic_work, title: ['First of the Assets'], read_users: [user.user_key]) }
222
+ let(:asset2) { create(:generic_work, title: ['Second of the Assets'], read_users: [user.user_key]) }
223
+ let(:asset3) { create(:generic_work, title: ['Third of the Assets'], read_users: [user.user_key]) }
224
+ let!(:collection) do
225
+ FactoryGirl.create(:collection, members: [asset1, asset2, asset3], user: user)
226
+ end
227
+
228
+ it 'queries the collections' do
229
+ get :show, id: collection, cq: 'First'
230
+ expect(assigns[:presenter].id).to eq collection.id
231
+ expect(assigns[:member_docs].map(&:id)).to match_array [asset1.id]
232
+ end
233
+
234
+ it 'returns the specified number of rows' do
235
+ get :show, id: collection, rows: '2'
236
+ expect(assigns[:presenter].id).to eq collection.id
237
+ expect(assigns[:member_docs].size).to eq 2
238
+ end
239
+
240
+ describe 'additional collections' do
241
+ let(:asset4) { create(:generic_work, user: user, title: [asset1.id.to_s], read_users: [user.user_key]) }
242
+ let!(:collection2) do
243
+ FactoryGirl.create(:collection, members: [asset4], user: user)
244
+ end
245
+ it 'shows only the collections assets' do
246
+ get :show, id: collection
247
+ expect(assigns[:presenter].id).to eq collection.id
248
+ expect(assigns[:member_docs].map(&:id)).to match_array [asset1.id, asset2.id, asset3.id]
249
+ end
250
+
251
+ it 'shows only the other collections assets' do
252
+ get :show, id: collection2
253
+ expect(assigns[:presenter].id).to eq collection2.id
254
+ expect(assigns[:member_docs].map(&:id)).to match_array [asset4.id]
255
+ end
256
+ end
257
+
258
+ context 'When there are search matches that are not in the collection' do
259
+ let!(:bad_asset1) { create(:generic_work, user: user, title: ["#{asset1.id} #{asset1.title.first}"]) }
260
+ let!(:bad_asset2) { create(:generic_work, user: user, title: ["#{asset1.id} #{asset1.title.first}"]) }
261
+
262
+ # NOTE: This test depends on title_tesim being in the qf in solrconfig.xml
263
+ it 'only shows the collection assets' do
264
+ get :show, id: collection, cq: "\"#{asset1.title.first}\""
265
+ expect(assigns[:presenter].id).to eq collection.id
266
+ expect(assigns[:member_docs].map(&:id)).not_to include bad_asset1.id, bad_asset2.id
267
+ expect(assigns[:member_docs].map(&:id)).to match_array [asset1.id]
268
+ end
269
+ end
270
+ end
271
+ end
272
+ end
@@ -1,7 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe CollectionsController do
4
- routes { Hydra::Collections::Engine.routes }
5
4
  before do
6
5
  allow_any_instance_of(User).to receive(:groups).and_return([])
7
6
  end
@@ -20,7 +19,7 @@ describe CollectionsController do
20
19
  title: ['Bogus Asset'],
21
20
  depositor: 'abc') }
22
21
  let(:collection_attrs) do
23
- { title: 'My First Collection', description: "The Description\r\n\r\nand more" }
22
+ { title: ['My First Collection'], description: ["The Description\r\n\r\nand more"] }
24
23
  end
25
24
 
26
25
  let(:collection) { create(:collection, title: ['Collection Title'], user: user) }