sufia 6.0.0 → 6.1.0

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 (290) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +2 -5
  3. data/CONTRIBUTING.md +4 -4
  4. data/Gemfile +2 -1
  5. data/History.md +69 -0
  6. data/README.md +84 -4
  7. data/SUFIA_VERSION +1 -1
  8. data/app/assets/images/zotero.png +0 -0
  9. data/app/assets/javascripts/sufia/featured_works.js +20 -3
  10. data/app/assets/stylesheets/generic_files.css.erb +2 -2
  11. data/app/assets/stylesheets/sufia.css.scss +2 -2
  12. data/app/assets/stylesheets/sufia/_buttons.scss +2 -2
  13. data/app/assets/stylesheets/sufia/_collections.scss +4 -4
  14. data/app/assets/stylesheets/sufia/_dashboard.scss +1 -1
  15. data/app/assets/stylesheets/sufia/_file-listing.scss +3 -0
  16. data/app/assets/stylesheets/sufia/_modal.scss +4 -0
  17. data/app/assets/stylesheets/sufia/_settings.scss +4 -3
  18. data/app/assets/stylesheets/sufia/_styles.scss +4 -0
  19. data/app/controllers/admin/stats_controller.rb +68 -0
  20. data/app/controllers/api/items_controller.rb +78 -0
  21. data/app/controllers/api/zotero_controller.rb +70 -0
  22. data/app/controllers/authorities_controller.rb +6 -5
  23. data/app/controllers/concerns/sufia/batch_edits_controller_behavior.rb +2 -1
  24. data/app/controllers/concerns/sufia/breadcrumbs.rb +1 -1
  25. data/app/controllers/concerns/sufia/depositors_controller_behavior.rb +11 -0
  26. data/app/controllers/concerns/sufia/files_controller/browse_everything.rb +1 -1
  27. data/app/controllers/concerns/sufia/files_controller/local_ingest_behavior.rb +1 -1
  28. data/app/controllers/concerns/sufia/files_controller_behavior.rb +23 -11
  29. data/app/controllers/concerns/sufia/my_controller_behavior.rb +1 -7
  30. data/app/controllers/concerns/sufia/users_controller_behavior.rb +1 -2
  31. data/app/controllers/my/collections_controller.rb +1 -0
  32. data/app/controllers/my/files_controller.rb +1 -1
  33. data/app/helpers/sufia/sufia_helper_behavior.rb +28 -16
  34. data/app/models/my_search_builder.rb +4 -0
  35. data/app/search_builders/sufia/my_search_builder_behavior.rb +20 -0
  36. data/app/search_builders/sufia/search_builder.rb +1 -1
  37. data/app/views/admin/stats/index.html.erb +68 -0
  38. data/app/views/collections/_action_menu.html.erb +22 -20
  39. data/app/views/collections/_collection.html.erb +1 -1
  40. data/app/views/collections/_form_for_select_collection.html.erb +5 -3
  41. data/app/views/generic_files/_show_actions.html.erb +4 -2
  42. data/app/views/generic_files/show.html.erb +1 -1
  43. data/app/views/layouts/sufia-dashboard.html.erb +5 -4
  44. data/app/views/layouts/sufia-one-column.html.erb +2 -0
  45. data/app/views/layouts/sufia-two-column.html.erb +6 -4
  46. data/app/views/my/_facet_layout.html.erb +2 -2
  47. data/app/views/my/_facets.html.erb +4 -6
  48. data/app/views/my/index.html.erb +4 -3
  49. data/app/views/users/_edit_primary.html.erb +18 -17
  50. data/app/views/users/_follower_modal.html.erb +5 -1
  51. data/app/views/users/_following_modal.html.erb +5 -1
  52. data/app/views/users/_user_info.html.erb +6 -1
  53. data/app/views/users/_zotero.html.erb +12 -0
  54. data/config/locales/sufia.en.yml +10 -1
  55. data/config/routes.rb +23 -1
  56. data/lib/generators/sufia/admin_stat_generator.rb +17 -0
  57. data/lib/generators/sufia/install_generator.rb +8 -3
  58. data/{sufia-models/lib/generators/sufia/models/templates/config/resque_admin.rb → lib/generators/sufia/templates/sufia/stats_admin.rb} +3 -3
  59. data/lib/generators/sufia/upgrade400_generator.rb +2 -2
  60. data/lib/sufia.rb +3 -0
  61. data/lib/sufia/arkivo.rb +11 -0
  62. data/lib/sufia/arkivo/actor.rb +95 -0
  63. data/lib/sufia/arkivo/config.rb +11 -0
  64. data/lib/sufia/arkivo/create_subscription_job.rb +67 -0
  65. data/lib/sufia/arkivo/metadata_munger.rb +51 -0
  66. data/lib/sufia/arkivo/schema_validator.rb +55 -0
  67. data/lib/sufia/form_builder.rb +1 -1
  68. data/lib/sufia/inflections.rb +3 -0
  69. data/lib/sufia/version.rb +1 -1
  70. data/lib/sufia/zotero.rb +6 -0
  71. data/lib/sufia/zotero/config.rb +15 -0
  72. data/solr_conf/conf/solrconfig.xml +11 -0
  73. data/spec/controllers/admin_stats_controller_spec.rb +73 -0
  74. data/spec/controllers/api/items_controller_spec.rb +476 -0
  75. data/spec/controllers/api/zotero_controller_spec.rb +178 -0
  76. data/spec/controllers/batch_edits_controller_spec.rb +7 -0
  77. data/spec/controllers/collections_controller_spec.rb +1 -1
  78. data/spec/controllers/dashboard_controller_spec.rb +1 -1
  79. data/spec/controllers/depositors_controller_spec.rb +9 -5
  80. data/spec/controllers/generic_files_controller_spec.rb +5 -4
  81. data/spec/controllers/mailbox_controller_spec.rb +2 -2
  82. data/spec/controllers/my/collections_controller_spec.rb +1 -2
  83. data/spec/controllers/my/files_controller_spec.rb +5 -5
  84. data/spec/controllers/my/shares_controller_spec.rb +15 -3
  85. data/spec/controllers/pages_controller_spec.rb +1 -1
  86. data/spec/controllers/users_controller_spec.rb +10 -9
  87. data/spec/factories/api_items.rb +91 -0
  88. data/spec/factories/generic_files.rb +4 -0
  89. data/spec/factories/users.rb +4 -4
  90. data/spec/features/featured_item_spec.rb +26 -0
  91. data/spec/features/ingest_upload_files_spec.rb +2 -3
  92. data/spec/features/proxy_spec.rb +0 -1
  93. data/spec/helpers/permissions_helper_spec.rb +2 -2
  94. data/spec/helpers/sufia_helper_spec.rb +11 -5
  95. data/spec/inputs/select_with_help_input_spec.rb +2 -2
  96. data/spec/javascripts/helpers/.gitkeep +0 -0
  97. data/spec/javascripts/helpers/jasmine-jquery.js +832 -0
  98. data/spec/javascripts/jasmine_spec.rb +31 -0
  99. data/spec/javascripts/notify_update_link_spec.js +8 -0
  100. data/spec/javascripts/single_use_link_spec.js.coffee +23 -0
  101. data/spec/javascripts/support/jasmine.yml +124 -0
  102. data/spec/javascripts/support/jasmine_helper.rb +15 -0
  103. data/spec/javascripts/terms_of_service_spec.js.coffee +32 -0
  104. data/spec/javascripts/toggle_icon_spec.js +11 -0
  105. data/spec/jobs/active_fedora_id_based_job_spec.rb +3 -3
  106. data/spec/jobs/import_url_job_spec.rb +0 -2
  107. data/spec/lib/sufia/arkivo/actor_spec.rb +139 -0
  108. data/spec/lib/sufia/arkivo/create_subscription_job_spec.rb +54 -0
  109. data/spec/lib/sufia/arkivo/metadata_munger_spec.rb +48 -0
  110. data/spec/lib/sufia/arkivo/schema_validator_spec.rb +65 -0
  111. data/spec/lib/sufia/upload_complete_behavior_spec.rb +1 -1
  112. data/spec/lib/sufia/user_stat_importer_spec.rb +60 -0
  113. data/spec/lib/sufia/zotero/config_spec.rb +30 -0
  114. data/spec/models/collection_spec.rb +36 -7
  115. data/spec/models/file_download_stat_spec.rb +5 -5
  116. data/spec/models/file_usage_spec.rb +23 -0
  117. data/spec/models/file_view_stat_spec.rb +6 -6
  118. data/spec/models/fits_datastream_spec.rb +0 -5
  119. data/spec/models/generic_file_spec.rb +49 -14
  120. data/spec/models/local_authority_spec.rb +1 -1
  121. data/spec/models/proxy_deposit_request_spec.rb +1 -1
  122. data/spec/models/trophy_spec.rb +8 -8
  123. data/spec/models/user_spec.rb +33 -0
  124. data/spec/presenters/sufia/collection_presenter_spec.rb +1 -1
  125. data/spec/routing/api_route_spec.rb +91 -0
  126. data/spec/routing/route_spec.rb +1 -1
  127. data/spec/services/generic_file_audit_service_spec.rb +44 -8
  128. data/spec/spec_helper.rb +18 -3
  129. data/spec/support/features.rb +0 -2
  130. data/spec/support/locations.rb +0 -21
  131. data/spec/support/rake.rb +41 -0
  132. data/spec/support/selectors.rb +0 -50
  133. data/spec/tasks/rake_spec.rb +33 -12
  134. data/spec/test_app_templates/lib/generators/test_app_generator.rb +12 -0
  135. data/spec/views/admin/stats/index.html.erb_spec.rb +45 -0
  136. data/spec/views/catalog/sort_and_per_page.html.erb_spec.rb +0 -1
  137. data/spec/views/dashboard/index_spec.rb +1 -1
  138. data/spec/views/generic_file/edit.html.erb_spec.rb +1 -1
  139. data/spec/views/generic_file/show.html.erb_spec.rb +1 -3
  140. data/spec/views/users/_follower_modal.html.erb_spec.rb +44 -7
  141. data/spec/views/users/_following_modal.html.erb_spec.rb +49 -7
  142. data/spec/views/users/edit.html.erb_spec.rb +72 -0
  143. data/spec/views/users/show.html.erb_spec.rb +1 -1
  144. data/sufia.gemspec +6 -2
  145. data/tasks/sufia-user.rake +14 -0
  146. metadata +130 -156
  147. data/spec/lib/sufia/id_service_spec.rb +0 -32
  148. data/spec/services/noid_spec.rb +0 -9
  149. data/spec/support/poltergeist.rb +0 -11
  150. data/spec/support/rake_output.rb +0 -20
  151. data/sufia-models/.gitignore +0 -17
  152. data/sufia-models/Gemfile +0 -4
  153. data/sufia-models/LICENSE.md +0 -177
  154. data/sufia-models/README.md +0 -39
  155. data/sufia-models/Rakefile +0 -1
  156. data/sufia-models/app/actors/sufia/generic_file/actor.rb +0 -137
  157. data/sufia-models/app/jobs/active_fedora_id_based_job.rb +0 -22
  158. data/sufia-models/app/jobs/active_fedora_pid_based_job.rb +0 -7
  159. data/sufia-models/app/jobs/audit_job.rb +0 -62
  160. data/sufia-models/app/jobs/batch_update_job.rb +0 -72
  161. data/sufia-models/app/jobs/characterize_job.rb +0 -10
  162. data/sufia-models/app/jobs/create_derivatives_job.rb +0 -14
  163. data/sufia-models/app/jobs/import_url_job.rb +0 -52
  164. data/sufia-models/app/jobs/ingest_local_file_job.rb +0 -46
  165. data/sufia-models/app/jobs/resolrize_job.rb +0 -9
  166. data/sufia-models/app/models/batch.rb +0 -36
  167. data/sufia-models/app/models/checksum_audit_log.rb +0 -21
  168. data/sufia-models/app/models/concerns/sufia/ability.rb +0 -61
  169. data/sufia-models/app/models/concerns/sufia/collection_behavior.rb +0 -24
  170. data/sufia-models/app/models/concerns/sufia/file_stat_utils.rb +0 -35
  171. data/sufia-models/app/models/concerns/sufia/generic_file.rb +0 -25
  172. data/sufia-models/app/models/concerns/sufia/generic_file/batches.rb +0 -28
  173. data/sufia-models/app/models/concerns/sufia/generic_file/characterization.rb +0 -89
  174. data/sufia-models/app/models/concerns/sufia/generic_file/content.rb +0 -13
  175. data/sufia-models/app/models/concerns/sufia/generic_file/derivatives.rb +0 -26
  176. data/sufia-models/app/models/concerns/sufia/generic_file/export.rb +0 -343
  177. data/sufia-models/app/models/concerns/sufia/generic_file/featured.rb +0 -11
  178. data/sufia-models/app/models/concerns/sufia/generic_file/full_text_indexing.rb +0 -43
  179. data/sufia-models/app/models/concerns/sufia/generic_file/indexing.rb +0 -14
  180. data/sufia-models/app/models/concerns/sufia/generic_file/metadata.rb +0 -98
  181. data/sufia-models/app/models/concerns/sufia/generic_file/mime_types.rb +0 -69
  182. data/sufia-models/app/models/concerns/sufia/generic_file/permissions.rb +0 -11
  183. data/sufia-models/app/models/concerns/sufia/generic_file/proxy_deposit.rb +0 -31
  184. data/sufia-models/app/models/concerns/sufia/generic_file/trophies.rb +0 -14
  185. data/sufia-models/app/models/concerns/sufia/generic_file/versions.rb +0 -16
  186. data/sufia-models/app/models/concerns/sufia/generic_file/virus_check.rb +0 -37
  187. data/sufia-models/app/models/concerns/sufia/model_methods.rb +0 -20
  188. data/sufia-models/app/models/concerns/sufia/user.rb +0 -137
  189. data/sufia-models/app/models/concerns/sufia/user_usage_stats.rb +0 -15
  190. data/sufia-models/app/models/datastreams/file_content_datastream.rb +0 -4
  191. data/sufia-models/app/models/datastreams/fits_datastream.rb +0 -152
  192. data/sufia-models/app/models/domain_term.rb +0 -5
  193. data/sufia-models/app/models/featured_work.rb +0 -22
  194. data/sufia-models/app/models/file_download_stat.rb +0 -18
  195. data/sufia-models/app/models/file_usage.rb +0 -34
  196. data/sufia-models/app/models/file_view_stat.rb +0 -18
  197. data/sufia-models/app/models/follow.rb +0 -12
  198. data/sufia-models/app/models/generic_file.rb +0 -3
  199. data/sufia-models/app/models/geo_names_resource.rb +0 -18
  200. data/sufia-models/app/models/group.rb +0 -8
  201. data/sufia-models/app/models/local_authority.rb +0 -86
  202. data/sufia-models/app/models/local_authority_entry.rb +0 -3
  203. data/sufia-models/app/models/proxy_deposit_request.rb +0 -85
  204. data/sufia-models/app/models/proxy_deposit_rights.rb +0 -4
  205. data/sufia-models/app/models/single_use_link.rb +0 -42
  206. data/sufia-models/app/models/subject_local_authority_entry.rb +0 -2
  207. data/sufia-models/app/models/sufia/avatar_uploader.rb +0 -20
  208. data/sufia-models/app/models/sufia/avatar_validator.rb +0 -8
  209. data/sufia-models/app/models/sufia/collection.rb +0 -5
  210. data/sufia-models/app/models/sufia/download.rb +0 -9
  211. data/sufia-models/app/models/sufia/orcid_validator.rb +0 -12
  212. data/sufia-models/app/models/sufia/pageview.rb +0 -9
  213. data/sufia-models/app/models/trophy.rb +0 -10
  214. data/sufia-models/app/models/user_stat.rb +0 -2
  215. data/sufia-models/app/models/version_committer.rb +0 -2
  216. data/sufia-models/app/services/sufia/analytics.rb +0 -50
  217. data/sufia-models/app/services/sufia/generic_file_audit_service.rb +0 -83
  218. data/sufia-models/app/services/sufia/generic_file_indexing_service.rb +0 -12
  219. data/sufia-models/app/services/sufia/id_service.rb +0 -45
  220. data/sufia-models/app/services/sufia/noid.rb +0 -22
  221. data/sufia-models/app/services/sufia/repository_audit_service.rb +0 -9
  222. data/sufia-models/config/locales/sufia.en.yml +0 -6
  223. data/sufia-models/lib/generators/sufia/models/abstract_migration_generator.rb +0 -30
  224. data/sufia-models/lib/generators/sufia/models/cached_stats_generator.rb +0 -24
  225. data/sufia-models/lib/generators/sufia/models/fulltext_generator.rb +0 -27
  226. data/sufia-models/lib/generators/sufia/models/install_generator.rb +0 -106
  227. data/sufia-models/lib/generators/sufia/models/orcid_field_generator.rb +0 -19
  228. data/sufia-models/lib/generators/sufia/models/proxies_generator.rb +0 -24
  229. data/sufia-models/lib/generators/sufia/models/templates/app/models/collection.rb +0 -2
  230. data/sufia-models/lib/generators/sufia/models/templates/config/analytics.yml +0 -9
  231. data/sufia-models/lib/generators/sufia/models/templates/config/clamav.rb +0 -1
  232. data/sufia-models/lib/generators/sufia/models/templates/config/mailboxer.rb +0 -17
  233. data/sufia-models/lib/generators/sufia/models/templates/config/mime_types.rb +0 -6
  234. data/sufia-models/lib/generators/sufia/models/templates/config/redis.yml +0 -9
  235. data/sufia-models/lib/generators/sufia/models/templates/config/redis_config.rb +0 -32
  236. data/sufia-models/lib/generators/sufia/models/templates/config/resque-pool.yml +0 -1
  237. data/sufia-models/lib/generators/sufia/models/templates/config/resque_config.rb +0 -5
  238. data/sufia-models/lib/generators/sufia/models/templates/config/setup_mail.rb +0 -3
  239. data/sufia-models/lib/generators/sufia/models/templates/config/solrconfig.xml +0 -223
  240. data/sufia-models/lib/generators/sufia/models/templates/config/sufia.rb +0 -144
  241. data/sufia-models/lib/generators/sufia/models/templates/migrations/acts_as_follower_migration.rb +0 -17
  242. data/sufia-models/lib/generators/sufia/models/templates/migrations/add_avatars_to_users.rb +0 -15
  243. data/sufia-models/lib/generators/sufia/models/templates/migrations/add_external_key_to_content_blocks.rb +0 -6
  244. data/sufia-models/lib/generators/sufia/models/templates/migrations/add_groups_to_users.rb +0 -11
  245. data/sufia-models/lib/generators/sufia/models/templates/migrations/add_ldap_attrs_to_user.rb +0 -27
  246. data/sufia-models/lib/generators/sufia/models/templates/migrations/add_linkedin_to_users.rb +0 -5
  247. data/sufia-models/lib/generators/sufia/models/templates/migrations/add_orcid_to_users.rb +0 -5
  248. data/sufia-models/lib/generators/sufia/models/templates/migrations/add_social_to_users.rb +0 -13
  249. data/sufia-models/lib/generators/sufia/models/templates/migrations/change_audit_log_pid_to_generic_file_id.rb +0 -5
  250. data/sufia-models/lib/generators/sufia/models/templates/migrations/change_proxy_deposit_request_pid_to_generic_file_id.rb +0 -5
  251. data/sufia-models/lib/generators/sufia/models/templates/migrations/create_checksum_audit_logs.rb +0 -19
  252. data/sufia-models/lib/generators/sufia/models/templates/migrations/create_content_blocks.rb +0 -10
  253. data/sufia-models/lib/generators/sufia/models/templates/migrations/create_featured_works.rb +0 -12
  254. data/sufia-models/lib/generators/sufia/models/templates/migrations/create_file_download_stats.rb +0 -12
  255. data/sufia-models/lib/generators/sufia/models/templates/migrations/create_file_view_stats.rb +0 -12
  256. data/sufia-models/lib/generators/sufia/models/templates/migrations/create_local_authorities.rb +0 -50
  257. data/sufia-models/lib/generators/sufia/models/templates/migrations/create_proxy_deposit_requests.rb +0 -16
  258. data/sufia-models/lib/generators/sufia/models/templates/migrations/create_proxy_deposit_rights.rb +0 -11
  259. data/sufia-models/lib/generators/sufia/models/templates/migrations/create_single_use_links.rb +0 -12
  260. data/sufia-models/lib/generators/sufia/models/templates/migrations/create_tinymce_assets.rb +0 -8
  261. data/sufia-models/lib/generators/sufia/models/templates/migrations/create_trophies.rb +0 -10
  262. data/sufia-models/lib/generators/sufia/models/templates/migrations/create_user_stats.rb +0 -19
  263. data/sufia-models/lib/generators/sufia/models/templates/migrations/create_version_committers.rb +0 -15
  264. data/sufia-models/lib/generators/sufia/models/update_content_blocks_generator.rb +0 -18
  265. data/sufia-models/lib/generators/sufia/models/upgrade400_generator.rb +0 -54
  266. data/sufia-models/lib/generators/sufia/models/upgrade600_generator.rb +0 -21
  267. data/sufia-models/lib/generators/sufia/models/usagestats_generator.rb +0 -19
  268. data/sufia-models/lib/generators/sufia/models/user_stats_generator.rb +0 -31
  269. data/sufia-models/lib/sufia/messages.rb +0 -66
  270. data/sufia-models/lib/sufia/models.rb +0 -34
  271. data/sufia-models/lib/sufia/models/active_fedora/redis.rb +0 -43
  272. data/sufia-models/lib/sufia/models/active_record/redis.rb +0 -56
  273. data/sufia-models/lib/sufia/models/engine.rb +0 -79
  274. data/sufia-models/lib/sufia/models/file_content.rb +0 -6
  275. data/sufia-models/lib/sufia/models/file_content/versions.rb +0 -21
  276. data/sufia-models/lib/sufia/models/resque.rb +0 -36
  277. data/sufia-models/lib/sufia/models/stats/user_stat_importer.rb +0 -108
  278. data/sufia-models/lib/sufia/models/user_local_directory_behavior.rb +0 -29
  279. data/sufia-models/lib/sufia/models/utils.rb +0 -22
  280. data/sufia-models/lib/sufia/models/version.rb +0 -5
  281. data/sufia-models/lib/sufia/models/virus_found_error.rb +0 -4
  282. data/sufia-models/lib/sufia/permissions.rb +0 -9
  283. data/sufia-models/lib/sufia/permissions/readable.rb +0 -20
  284. data/sufia-models/lib/sufia/permissions/writable.rb +0 -74
  285. data/sufia-models/lib/tasks/batch_cleanup.rake +0 -19
  286. data/sufia-models/lib/tasks/migrate.rake +0 -21
  287. data/sufia-models/lib/tasks/resque.rake +0 -13
  288. data/sufia-models/lib/tasks/stats_tasks.rake +0 -12
  289. data/sufia-models/lib/tasks/sufia-models_tasks.rake +0 -80
  290. data/sufia-models/sufia-models.gemspec +0 -52
@@ -8,7 +8,7 @@ module Sufia
8
8
  input = find_input(attribute_name, options)
9
9
  wrapper = find_wrapper(input.input_type, options)
10
10
  components = (wrapper.components.map(&:namespace) & ATTRIBUTE_COMPONENTS) + [:input]
11
- components = components.map { |component| SimpleForm::Wrappers::Leaf.new(component) }
11
+ components.map { |component| SimpleForm::Wrappers::Leaf.new(component) }
12
12
 
13
13
  input.label.html_safe
14
14
  end
@@ -0,0 +1,3 @@
1
+ ActiveSupport::Inflector.inflections(:en) do |inflect|
2
+ inflect.acronym 'API'
3
+ end
@@ -1,3 +1,3 @@
1
1
  module Sufia
2
- VERSION = "6.0.0"
2
+ VERSION = "6.1.0"
3
3
  end
@@ -0,0 +1,6 @@
1
+ require 'sufia/zotero/config'
2
+
3
+ module Sufia
4
+ module Zotero
5
+ end
6
+ end
@@ -0,0 +1,15 @@
1
+ module Sufia
2
+ module Zotero
3
+ def self.config
4
+ @config ||= reload_config!
5
+ end
6
+
7
+ def self.reload_config!
8
+ @config = YAML.load(ERB.new(IO.read(File.join(Rails.root, 'config', 'zotero.yml'))).result)['zotero']
9
+ end
10
+
11
+ def self.publications_url(zotero_userid)
12
+ "/users/#{zotero_userid}/publications/items"
13
+ end
14
+ end
15
+ end
@@ -150,6 +150,17 @@
150
150
  </lst>
151
151
  </searchComponent>
152
152
 
153
+ <searchComponent name="termsComponent" class="solr.TermsComponent" />
154
+
155
+ <requestHandler name="/terms" class="solr.SearchHandler">
156
+ <lst name="defaults">
157
+ <bool name="terms">true</bool>
158
+ </lst>
159
+ <arr name="components">
160
+ <str>termsComponent</str>
161
+ </arr>
162
+ </requestHandler>
163
+
153
164
  <requestHandler name="/replication" class="solr.ReplicationHandler" startup="lazy" />
154
165
 
155
166
  <requestDispatcher handleSelect="true" >
@@ -0,0 +1,73 @@
1
+ require 'spec_helper'
2
+
3
+ describe Admin::StatsController, type: :controller do
4
+ let(:user1) { FactoryGirl.find_or_create(:user) }
5
+ let(:user2) { FactoryGirl.find_or_create(:archivist) }
6
+
7
+ before do
8
+ allow(user1).to receive(:groups).and_return(['admin'])
9
+ allow(user2).to receive(:groups).and_return(['not-admin'])
10
+ end
11
+
12
+ describe "statistics page" do
13
+ render_views
14
+ before do
15
+ sign_in user1
16
+ end
17
+
18
+ it 'allows an authorized user to view the page' do
19
+ get :index
20
+ expect(response).to be_success
21
+ expect(response.body).to include('Statistics for Blacklight')
22
+ expect(response.body).to include('Total Blacklight Users')
23
+ end
24
+
25
+ describe "querying user_stats" do
26
+ it "defaults to latest 5 users" do
27
+ get :index
28
+ expect(assigns[:recent_users]).to eq(User.order('created_at DESC').limit(5))
29
+ end
30
+ it "allows queries against user_stats" do
31
+ expect(User).to receive(:where).with('id' => user1.id).once.and_return([user1])
32
+ expect(User).to receive(:where).with('created_at >= ?', 1.days.ago.strftime("%Y-%m-%d")).and_return([user2])
33
+ get :index, users_stats: {start_date:1.days.ago.strftime("%Y-%m-%d")}
34
+ expect(assigns[:recent_users]).to eq([user2])
35
+ end
36
+ end
37
+
38
+ describe "files_count" do
39
+ let(:original_files_count) do
40
+ poltergeist = GenericFile.new
41
+ poltergeist.apply_depositor_metadata(user1)
42
+ poltergeist.save
43
+ original_files_count = GenericFile.count
44
+ ActiveFedora::SolrService.instance.conn.delete_by_id(poltergeist.id)
45
+ original_files_count
46
+ end
47
+ it "should provide accurate files_count, ensuring that solr deletes have been expunged first" do
48
+ get :index
49
+ expect(assigns[:files_count][:total]).to eq(original_files_count - 1)
50
+ end
51
+ end
52
+
53
+ describe "counts" do
54
+ before do
55
+ FactoryGirl.create(:generic_file, depositor: user1)
56
+ FactoryGirl.create(:public_file, depositor: user1)
57
+ FactoryGirl.create(:registered_file, depositor: user1)
58
+ Collection.create(title: "test").tap do |c|
59
+ c.apply_depositor_metadata(user1.user_key)
60
+ end
61
+ end
62
+
63
+ it "includes files but not collections" do
64
+ get :index
65
+ expect(assigns[:files_count][:total]).to eq(3)
66
+ expect(assigns[:files_count][:public]).to eq(1)
67
+ expect(assigns[:files_count][:registered]).to eq(1)
68
+ expect(assigns[:files_count][:private]).to eq(1)
69
+ end
70
+ end
71
+
72
+ end
73
+ end
@@ -0,0 +1,476 @@
1
+ require 'spec_helper'
2
+
3
+ describe API::ItemsController, type: :controller do
4
+ before do
5
+ # Don't test characterization on these items; it breaks TravisCI
6
+ allow_any_instance_of(GenericFile).to receive(:characterize)
7
+ end
8
+
9
+ let(:user) { FactoryGirl.find_or_create(:jill) }
10
+
11
+ context 'with an HTTP GET or HEAD' do
12
+ before do
13
+ post :create, format: :json, item: item
14
+ end
15
+
16
+ let(:deposited_file) { GenericFile.where(label: item['file']['filename']).take }
17
+ let(:token) { user.arkivo_token }
18
+ let(:item) { FactoryGirl.json(:post_item, token: token) }
19
+
20
+ context 'with a missing token' do
21
+ before do
22
+ get :show, format: :json, id: deposited_file.id
23
+ end
24
+
25
+ subject { response }
26
+
27
+ it { is_expected.to have_http_status(401) }
28
+
29
+ it 'describes the error' do
30
+ expect(subject.body).to include('invalid user token:')
31
+ end
32
+ end
33
+
34
+ context 'with an unfamiliar token' do
35
+ before do
36
+ get :show, format: :json, id: deposited_file.id, token: get_token
37
+ end
38
+
39
+ let(:get_token) { 'foobar' }
40
+
41
+ subject { response }
42
+
43
+ it { is_expected.to have_http_status(401) }
44
+
45
+ it 'describes the error' do
46
+ expect(subject.body).to include("invalid user token: #{get_token}")
47
+ end
48
+ end
49
+
50
+ context 'with an unauthorized resource' do
51
+ before do
52
+ allow_any_instance_of(User).to receive(:can?).with(:edit, deposited_file) { false }
53
+ get :show, format: :json, id: deposited_file.id, token: token
54
+ end
55
+
56
+ subject { response }
57
+
58
+ it { is_expected.to have_http_status(401) }
59
+
60
+ it 'loads the file' do
61
+ expect(assigns[:file]).to eq deposited_file
62
+ end
63
+
64
+ it 'provides a reason for refusing to act' do
65
+ expect(subject.body).to include("#{user} lacks access to #{deposited_file}")
66
+ end
67
+ end
68
+
69
+ context 'with a resource not deposited via Arkivo' do
70
+ before do
71
+ allow_any_instance_of(GenericFile).to receive(:arkivo_checksum) { nil }
72
+ get :show, format: :json, id: deposited_file.id, token: token
73
+ end
74
+
75
+ subject { response }
76
+
77
+ it { is_expected.to have_http_status(403) }
78
+
79
+ it 'provides a reason for refusing to act' do
80
+ expect(subject.body).to include("Forbidden: #{deposited_file} not deposited via Arkivo")
81
+ end
82
+ end
83
+
84
+ context 'with a resource not found in the repository' do
85
+ before do
86
+ allow(GenericFile).to receive(:find).with(deposited_file.id).and_raise(ActiveFedora::ObjectNotFoundError)
87
+ get :show, format: :json, id: deposited_file.id, token: token
88
+ end
89
+
90
+ subject { response }
91
+
92
+ it { is_expected.to have_http_status(404) }
93
+
94
+ it 'provides a reason for refusing to act' do
95
+ expect(subject.body).to include("id '#{deposited_file.id}' not found")
96
+ end
97
+ end
98
+
99
+ context 'with an authorized Arkivo-deposited resource' do
100
+ before do
101
+ get :show, format: :json, id: deposited_file.id, token: token
102
+ end
103
+
104
+ subject { response }
105
+
106
+ it { is_expected.to have_http_status(204) }
107
+
108
+ it 'responds with no body' do
109
+ expect(subject.body).to be_blank
110
+ end
111
+ end
112
+ end
113
+
114
+ context 'with an HTTP POST' do
115
+ context 'without an item' do
116
+ before do
117
+ post :create, format: :json
118
+ end
119
+
120
+ subject { response }
121
+
122
+ it { is_expected.to have_http_status(400) }
123
+
124
+ it 'describes the error' do
125
+ expect(subject.body).to include('no item parameter')
126
+ end
127
+ end
128
+
129
+ context 'with an invalid item' do
130
+ before do
131
+ post :create, format: :json, item: item
132
+ end
133
+
134
+ let(:item) { { foo: 'bar' }.to_json }
135
+
136
+ subject { response }
137
+
138
+ it { is_expected.to have_http_status(400) }
139
+
140
+ it 'describes the error' do
141
+ expect(subject.body).to include('The property \'#/\' did not contain a required property of \'token\'')
142
+ end
143
+ end
144
+
145
+ context 'with a valid item and matching token' do
146
+ before do
147
+ expect { post :create, format: :json, item: item }.to change { GenericFile.count }.by(1)
148
+ end
149
+
150
+ let(:deposited_file) { GenericFile.where(label: item['file']['filename']).take }
151
+ let(:token) { user.arkivo_token }
152
+ let(:item) { FactoryGirl.json(:post_item, token: token) }
153
+ let(:item_hash) { JSON.parse(item) }
154
+
155
+ subject { response }
156
+
157
+ it { is_expected.to be_success }
158
+
159
+ it 'responds with HTTP 201' do
160
+ expect(response.status).to eq 201
161
+ end
162
+
163
+ it 'provides a URI in the Location header' do
164
+ expect(response.headers['Location']).to match %r{/api/items/.{9}}
165
+ end
166
+
167
+ it 'creates a new item via POST' do
168
+ expect(deposited_file).not_to be_nil
169
+ end
170
+
171
+ it 'writes metadata to allow flagging Arkivo-deposited items' do
172
+ expect(deposited_file.arkivo_checksum).to eq item_hash['file']['md5']
173
+ end
174
+
175
+ it 'writes content' do
176
+ expect(deposited_file.content.content).to eq "arkivo\n"
177
+ end
178
+
179
+ it 'batch applies specified metadata' do
180
+ expect(deposited_file.resource_type).to eq [item_hash['metadata']['resourceType']]
181
+ expect(deposited_file.title).to eq [item_hash['metadata']['title']]
182
+ expect(deposited_file.description).to eq [item_hash['metadata']['description']]
183
+ expect(deposited_file.publisher).to eq [item_hash['metadata']['publisher']]
184
+ expect(deposited_file.date_created).to eq [item_hash['metadata']['dateCreated']]
185
+ expect(deposited_file.based_near).to eq [item_hash['metadata']['basedNear']]
186
+ expect(deposited_file.identifier).to eq [item_hash['metadata']['identifier']]
187
+ expect(deposited_file.related_url).to eq [item_hash['metadata']['url']]
188
+ expect(deposited_file.language).to eq [item_hash['metadata']['language']]
189
+ expect(deposited_file.rights).to eq [item_hash['metadata']['rights']]
190
+ expect(deposited_file.tag).to eq item_hash['metadata']['tags']
191
+ expect(deposited_file.creator).to eq ['Doe, John', 'Babs McGee']
192
+ expect(deposited_file.contributor).to eq ['Nadal, Rafael', 'Jane Doeski']
193
+ end
194
+ end
195
+
196
+ context 'with a valid item and unfamiliar token' do
197
+ before do
198
+ post :create, format: :json, item: item
199
+ end
200
+
201
+ let(:token) { 'unfamiliar_token' }
202
+ let(:item) { FactoryGirl.json(:post_item, token: token) }
203
+
204
+ subject { response }
205
+
206
+ it { is_expected.not_to be_success }
207
+
208
+ it 'responds with HTTP 401' do
209
+ expect(subject.status).to eq 401
210
+ end
211
+
212
+ it 'provides a reason for refusing to act' do
213
+ expect(subject.body).to include("invalid user token: #{token}")
214
+ end
215
+ end
216
+ end
217
+
218
+ context 'with an HTTP PUT' do
219
+ let(:post_deposited_file) { GenericFile.where(label: post_item['file']['filename']).take }
220
+ let(:post_token) { user.arkivo_token }
221
+ let(:post_item) { FactoryGirl.json(:post_item, token: post_token) }
222
+ let(:post_item_hash) { JSON.parse(post_item) }
223
+
224
+ before do
225
+ expect { post :create, format: :json, item: post_item }.to change { GenericFile.count }.by(1)
226
+ end
227
+
228
+ context 'with a valid item, matching token, and authorized resource' do
229
+ before do
230
+ put :update, id: post_deposited_file.id, format: :json, item: put_item
231
+ end
232
+
233
+ let(:put_deposited_file) { GenericFile.where(label: put_item['file']['filename']).take }
234
+ let(:put_token) { user.arkivo_token }
235
+ let(:put_item) { FactoryGirl.json(:put_item, token: put_token) }
236
+ let(:put_item_hash) { JSON.parse(put_item) }
237
+
238
+ subject { response }
239
+
240
+ it { is_expected.to be_success }
241
+
242
+ it 'responds with HTTP 204 and no body' do
243
+ expect(subject.status).to eq 204
244
+ expect(subject.body).to be_blank
245
+ end
246
+
247
+ it 'updates metadata to allow flagging Arkivo-deposited items' do
248
+ expect(put_deposited_file.arkivo_checksum).to eq put_item_hash['file']['md5']
249
+ end
250
+
251
+ it 'changes the file content' do
252
+ expect(put_deposited_file.content.content).to eq "# HEADER\n\nThis is a paragraph!\n"
253
+ end
254
+
255
+ it 'changes the metadata' do
256
+ expect(put_deposited_file.resource_type).to eq [put_item_hash['metadata']['resourceType']]
257
+ expect(put_deposited_file.title).to eq [put_item_hash['metadata']['title']]
258
+ expect(put_deposited_file.rights).to eq [put_item_hash['metadata']['rights']]
259
+ expect(put_deposited_file.tag).to eq put_item_hash['metadata']['tags']
260
+ expect(put_deposited_file.creator).to eq ['Doe, John', 'Babs McGee']
261
+ expect(put_deposited_file.description).to eq []
262
+ expect(put_deposited_file.publisher).to eq []
263
+ expect(put_deposited_file.date_created).to eq []
264
+ expect(put_deposited_file.based_near).to eq []
265
+ expect(put_deposited_file.identifier).to eq []
266
+ expect(put_deposited_file.related_url).to eq []
267
+ expect(put_deposited_file.language).to eq []
268
+ expect(put_deposited_file.contributor).to eq []
269
+ end
270
+ end
271
+
272
+ context 'with a valid item, matching token, authorized resource, but not Arkivo-deposited' do
273
+ before do
274
+ allow_any_instance_of(GenericFile).to receive(:arkivo_checksum) { nil }
275
+ put :update, id: post_deposited_file.id, format: :json, item: item
276
+ end
277
+
278
+ let(:item) { FactoryGirl.json(:put_item, token: post_token) }
279
+
280
+ subject { response }
281
+
282
+ it { is_expected.not_to be_success }
283
+
284
+ it 'responds with HTTP 403' do
285
+ expect(subject.status).to eq 403
286
+ end
287
+
288
+ it 'provides a reason for refusing to act' do
289
+ expect(subject.body).to include("Forbidden: #{post_deposited_file} not deposited via Arkivo")
290
+ end
291
+ end
292
+
293
+ context 'with a valid item, matching token, missing resource' do
294
+ before do
295
+ allow(GenericFile).to receive(:find).with(post_deposited_file.id) do
296
+ raise(ActiveFedora::ObjectNotFoundError)
297
+ end
298
+ put :update, id: post_deposited_file.id, format: :json, item: item
299
+ end
300
+
301
+ subject { response }
302
+ let(:item) { FactoryGirl.json(:put_item, token: post_token) }
303
+
304
+ it { is_expected.to have_http_status(404) }
305
+
306
+ it 'provides a reason for refusing to act' do
307
+ expect(subject.body).to include("id '#{post_deposited_file.id}' not found")
308
+ end
309
+ end
310
+
311
+ context 'with a valid item, matching token, and unauthorized resource' do
312
+ before do
313
+ allow_any_instance_of(User).to receive(:can?).with(:edit, post_deposited_file) { false }
314
+ put :update, id: post_deposited_file.id, format: :json, item: item
315
+ end
316
+
317
+ let(:item) { FactoryGirl.json(:put_item, token: post_token) }
318
+
319
+ subject { response }
320
+
321
+ it { is_expected.not_to be_success }
322
+
323
+ it 'loads the file' do
324
+ expect(assigns[:file]).to eq post_deposited_file
325
+ end
326
+
327
+ it 'responds with HTTP 401' do
328
+ expect(subject.status).to eq 401
329
+ end
330
+
331
+ it 'provides a reason for refusing to act' do
332
+ expect(subject.body).to include("#{user} lacks access to #{post_deposited_file}")
333
+ end
334
+ end
335
+
336
+ context 'with a valid item and unfamiliar token' do
337
+ before do
338
+ put :update, id: post_deposited_file.id, format: :json, item: item
339
+ end
340
+
341
+ let(:token) { 'unfamiliar_token' }
342
+ let(:item) { FactoryGirl.json(:put_item, token: token) }
343
+
344
+ subject { response }
345
+
346
+ it { is_expected.not_to be_success }
347
+
348
+ it 'responds with HTTP 401' do
349
+ expect(subject.status).to eq 401
350
+ end
351
+
352
+ it 'provides a reason for refusing to act' do
353
+ expect(subject.body).to include("invalid user token: #{token}")
354
+ end
355
+ end
356
+
357
+ context 'with an invalid item' do
358
+ before do
359
+ put :update, id: post_deposited_file.id, format: :json, item: item
360
+ end
361
+
362
+ let(:item) { { foo: 'bar' }.to_json }
363
+
364
+ subject { response }
365
+
366
+ it { is_expected.to have_http_status(400) }
367
+
368
+ it 'describes the error' do
369
+ expect(subject.body).to include('The property \'#/\' did not contain a required property of \'token\'')
370
+ end
371
+ end
372
+ end
373
+
374
+ context 'with an HTTP DELETE' do
375
+ before do
376
+ post :create, format: :json, item: item
377
+ end
378
+
379
+ let(:deposited_file) { GenericFile.where(label: item['file']['filename']).take }
380
+ let(:token) { user.arkivo_token }
381
+ let(:item) { FactoryGirl.json(:post_item, token: token) }
382
+
383
+ context 'with a missing token' do
384
+ before do
385
+ delete :destroy, format: :json, id: deposited_file.id
386
+ end
387
+
388
+ subject { response }
389
+
390
+ it { is_expected.to have_http_status(401) }
391
+
392
+ it 'describes the error' do
393
+ expect(subject.body).to include('invalid user token:')
394
+ end
395
+ end
396
+
397
+ context 'with an unfamiliar token' do
398
+ before do
399
+ delete :destroy, format: :json, id: deposited_file.id, token: delete_token
400
+ end
401
+
402
+ let(:delete_token) { 'foobar' }
403
+
404
+ subject { response }
405
+
406
+ it { is_expected.to have_http_status(401) }
407
+
408
+ it 'describes the error' do
409
+ expect(subject.body).to include("invalid user token: #{delete_token}")
410
+ end
411
+ end
412
+
413
+ context 'with an unauthorized resource' do
414
+ before do
415
+ allow_any_instance_of(User).to receive(:can?).with(:edit, deposited_file) { false }
416
+ delete :destroy, format: :json, id: deposited_file.id, token: token
417
+ end
418
+
419
+ subject { response }
420
+
421
+ it { is_expected.to have_http_status(401) }
422
+
423
+ it 'loads the file' do
424
+ expect(assigns[:file]).to eq deposited_file
425
+ end
426
+
427
+ it 'provides a reason for refusing to act' do
428
+ expect(subject.body).to include("#{user} lacks access to #{deposited_file}")
429
+ end
430
+ end
431
+
432
+ context 'with a resource not deposited via Arkivo' do
433
+ before do
434
+ allow_any_instance_of(GenericFile).to receive(:arkivo_checksum) { nil }
435
+ delete :destroy, format: :json, id: deposited_file.id, token: token
436
+ end
437
+
438
+ subject { response }
439
+
440
+ it { is_expected.to have_http_status(403) }
441
+
442
+ it 'provides a reason for refusing to act' do
443
+ expect(subject.body).to include("Forbidden: #{deposited_file} not deposited via Arkivo")
444
+ end
445
+ end
446
+
447
+ context 'with a resource not found in the repository' do
448
+ before do
449
+ allow(GenericFile).to receive(:find).with(deposited_file.id).and_raise(ActiveFedora::ObjectNotFoundError)
450
+ delete :destroy, format: :json, id: deposited_file.id, token: token
451
+ end
452
+
453
+ subject { response }
454
+
455
+ it { is_expected.to have_http_status(404) }
456
+
457
+ it 'provides a reason for refusing to act' do
458
+ expect(subject.body).to include("id '#{deposited_file.id}' not found")
459
+ end
460
+ end
461
+
462
+ context 'with an authorized Arkivo-deposited resource' do
463
+ before do
464
+ expect { delete :destroy, format: :json, id: deposited_file.id, token: token }.to change { GenericFile.count }.by(-1)
465
+ end
466
+
467
+ subject { response }
468
+
469
+ it { is_expected.to have_http_status(204) }
470
+
471
+ it 'responds with no body' do
472
+ expect(subject.body).to be_blank
473
+ end
474
+ end
475
+ end
476
+ end