supplejack_api 1

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 (291) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +80 -0
  3. data/Rakefile +42 -0
  4. data/app/assets/javascripts/supplejack_api/application.js +26 -0
  5. data/app/assets/stylesheets/supplejack_api/application.css +30 -0
  6. data/app/controllers/supplejack_api/admin/base_controller.rb +24 -0
  7. data/app/controllers/supplejack_api/admin/sessions_controller.rb +25 -0
  8. data/app/controllers/supplejack_api/admin/site_activities_controller.rb +21 -0
  9. data/app/controllers/supplejack_api/admin/users_controller.rb +55 -0
  10. data/app/controllers/supplejack_api/application_controller.rb +70 -0
  11. data/app/controllers/supplejack_api/concepts_controller.rb +52 -0
  12. data/app/controllers/supplejack_api/concerns/ignore_metrics.rb +14 -0
  13. data/app/controllers/supplejack_api/concerns/records_controller_metrics.rb +26 -0
  14. data/app/controllers/supplejack_api/concerns/set_items_controller_metrics.rb +20 -0
  15. data/app/controllers/supplejack_api/concerns/user_sets_controller_metrics.rb +26 -0
  16. data/app/controllers/supplejack_api/harvester/concepts_controller.rb +41 -0
  17. data/app/controllers/supplejack_api/harvester/fragments_controller.rb +30 -0
  18. data/app/controllers/supplejack_api/harvester/records_controller.rb +68 -0
  19. data/app/controllers/supplejack_api/metrics_api_controller.rb +44 -0
  20. data/app/controllers/supplejack_api/partners_controller.rb +39 -0
  21. data/app/controllers/supplejack_api/records_controller.rb +71 -0
  22. data/app/controllers/supplejack_api/schema_controller.rb +19 -0
  23. data/app/controllers/supplejack_api/set_items_controller.rb +38 -0
  24. data/app/controllers/supplejack_api/sources_controller.rb +67 -0
  25. data/app/controllers/supplejack_api/status_controller.rb +67 -0
  26. data/app/controllers/supplejack_api/user_sets_controller.rb +97 -0
  27. data/app/controllers/supplejack_api/users_controller.rb +49 -0
  28. data/app/helpers/supplejack_api/application_helper.rb +39 -0
  29. data/app/helpers/supplejack_api/facets_helper.rb +30 -0
  30. data/app/mailers/supplejack_api/request_limit_mailer.rb +43 -0
  31. data/app/models/supplejack_api/api_concept/concept_fragment.rb +31 -0
  32. data/app/models/supplejack_api/api_record/record_fragment.rb +15 -0
  33. data/app/models/supplejack_api/concept.rb +46 -0
  34. data/app/models/supplejack_api/concept_search.rb +86 -0
  35. data/app/models/supplejack_api/concerns/queryable_by_date.rb +31 -0
  36. data/app/models/supplejack_api/concerns/record.rb +108 -0
  37. data/app/models/supplejack_api/concerns/record_fragmentable.rb +24 -0
  38. data/app/models/supplejack_api/concerns/searchable.rb +430 -0
  39. data/app/models/supplejack_api/concerns/user_set.rb +219 -0
  40. data/app/models/supplejack_api/daily_metrics.rb +20 -0
  41. data/app/models/supplejack_api/faceted_metrics.rb +55 -0
  42. data/app/models/supplejack_api/fragment.rb +82 -0
  43. data/app/models/supplejack_api/interaction_models/record.rb +60 -0
  44. data/app/models/supplejack_api/interaction_models/set.rb +13 -0
  45. data/app/models/supplejack_api/interaction_updaters/all_usage_metric.rb +41 -0
  46. data/app/models/supplejack_api/interaction_updaters/set_metrics.rb +32 -0
  47. data/app/models/supplejack_api/interaction_updaters/usage_metrics.rb +73 -0
  48. data/app/models/supplejack_api/partner.rb +24 -0
  49. data/app/models/supplejack_api/preview_record.rb +30 -0
  50. data/app/models/supplejack_api/record.rb +18 -0
  51. data/app/models/supplejack_api/record_search.rb +12 -0
  52. data/app/models/supplejack_api/schema_definition.rb +147 -0
  53. data/app/models/supplejack_api/search.rb +14 -0
  54. data/app/models/supplejack_api/set_item.rb +57 -0
  55. data/app/models/supplejack_api/site_activity.rb +59 -0
  56. data/app/models/supplejack_api/source.rb +28 -0
  57. data/app/models/supplejack_api/source_activity.rb +36 -0
  58. data/app/models/supplejack_api/source_authority.rb +42 -0
  59. data/app/models/supplejack_api/supplejack_schema.rb +37 -0
  60. data/app/models/supplejack_api/support/concept/searchable.rb +79 -0
  61. data/app/models/supplejack_api/support/concept/storable.rb +59 -0
  62. data/app/models/supplejack_api/support/fragment_helpers.rb +96 -0
  63. data/app/models/supplejack_api/support/harvestable.rb +105 -0
  64. data/app/models/supplejack_api/support/searchable.rb +115 -0
  65. data/app/models/supplejack_api/support/status_logger.rb +23 -0
  66. data/app/models/supplejack_api/support/storable.rb +49 -0
  67. data/app/models/supplejack_api/support/validation_logger.rb +23 -0
  68. data/app/models/supplejack_api/usage_metrics.rb +25 -0
  69. data/app/models/supplejack_api/user.rb +211 -0
  70. data/app/models/supplejack_api/user_activity.rb +65 -0
  71. data/app/models/supplejack_api/user_set.rb +17 -0
  72. data/app/serializers/supplejack_api/application_serializer.rb +12 -0
  73. data/app/serializers/supplejack_api/concept_record_serializer.rb +23 -0
  74. data/app/serializers/supplejack_api/concept_search_serializer.rb +12 -0
  75. data/app/serializers/supplejack_api/concept_serializer.rb +100 -0
  76. data/app/serializers/supplejack_api/concerns/record_serializable.rb +119 -0
  77. data/app/serializers/supplejack_api/concerns/search_serializable.rb +24 -0
  78. data/app/serializers/supplejack_api/record_search_serializer.rb +64 -0
  79. data/app/serializers/supplejack_api/record_serializer.rb +13 -0
  80. data/app/serializers/supplejack_api/search_serializer.rb +13 -0
  81. data/app/serializers/supplejack_api/source_authority_serializer.rb +23 -0
  82. data/app/serializers/supplejack_api/user_serializer.rb +13 -0
  83. data/app/serializers/supplejack_api/user_set_record_serializer.rb +14 -0
  84. data/app/serializers/supplejack_api/user_set_serializer.rb +77 -0
  85. data/app/services/metrics_api/v3/api.rb +30 -0
  86. data/app/services/metrics_api/v3/endpoints/facets.rb +23 -0
  87. data/app/services/metrics_api/v3/endpoints/global.rb +26 -0
  88. data/app/services/metrics_api/v3/endpoints/helpers.rb +14 -0
  89. data/app/services/metrics_api/v3/endpoints/root.rb +97 -0
  90. data/app/services/metrics_api/v3/presenters/daily_metric.rb +23 -0
  91. data/app/services/metrics_api/v3/presenters/extended_metadata.rb +41 -0
  92. data/app/services/metrics_api/v3/presenters/record.rb +26 -0
  93. data/app/services/metrics_api/v3/presenters/view.rb +28 -0
  94. data/app/views/layouts/supplejack_api/_head.html.erb +17 -0
  95. data/app/views/layouts/supplejack_api/_top_nav.html.erb +33 -0
  96. data/app/views/layouts/supplejack_api/application.html.erb +33 -0
  97. data/app/views/supplejack_api/admin/sessions/new.html.erb +25 -0
  98. data/app/views/supplejack_api/admin/shared/_links.erb +34 -0
  99. data/app/views/supplejack_api/admin/site_activities/index.csv.erb +22 -0
  100. data/app/views/supplejack_api/admin/site_activities/index.html.erb +54 -0
  101. data/app/views/supplejack_api/admin/users/edit.html.erb +16 -0
  102. data/app/views/supplejack_api/admin/users/index.csv.erb +22 -0
  103. data/app/views/supplejack_api/admin/users/index.html.erb +57 -0
  104. data/app/views/supplejack_api/admin/users/show.html.erb +33 -0
  105. data/app/views/supplejack_api/request_limit_mailer/at100percent.text.erb +13 -0
  106. data/app/views/supplejack_api/request_limit_mailer/at100percent_admin.text.erb +1 -0
  107. data/app/views/supplejack_api/request_limit_mailer/at90percent.text.erb +13 -0
  108. data/app/views/supplejack_api/request_limit_mailer/at90percent_admin.text.erb +1 -0
  109. data/app/workers/supplejack_api/daily_metrics_worker.rb +112 -0
  110. data/app/workers/supplejack_api/interaction_metrics_worker.rb +45 -0
  111. data/config/cucumber.yml +16 -0
  112. data/config/initializers/force_eagerload.rb +11 -0
  113. data/config/initializers/interaction_updaters.rb +7 -0
  114. data/config/routes.rb +81 -0
  115. data/db/binding_records.development.json +7 -0
  116. data/db/binding_records.staging.json +7 -0
  117. data/db/concepts.json +33 -0
  118. data/db/concepts_data.json +569745 -0
  119. data/db/source_authorities.json +119 -0
  120. data/lib/generators/supplejack_api/install_generator.rb +124 -0
  121. data/lib/mongoid/paperclip.rb +53 -0
  122. data/lib/mongoid/string.rb +20 -0
  123. data/lib/sunspot/mongoid.rb +51 -0
  124. data/lib/sunspot/resque_session_proxy.rb +72 -0
  125. data/lib/sunspot/sunspot_spellcheck.rb +98 -0
  126. data/lib/supplejack_api.rb +13 -0
  127. data/lib/supplejack_api/admin/sortable.rb +40 -0
  128. data/lib/supplejack_api/engine.rb +46 -0
  129. data/lib/supplejack_api/harvester_constraint.rb +28 -0
  130. data/lib/supplejack_api/stylesheets.rb +36 -0
  131. data/lib/supplejack_api/utils.rb +75 -0
  132. data/lib/supplejack_api/version.rb +11 -0
  133. data/lib/tasks/resque.rake +22 -0
  134. data/lib/url_validator.rb +38 -0
  135. data/spec/controllers/supplejack_api/admin/base_controller_spec.rb +55 -0
  136. data/spec/controllers/supplejack_api/admin/site_activities_controller_spec.rb +43 -0
  137. data/spec/controllers/supplejack_api/admin/users_controller_spec.rb +79 -0
  138. data/spec/controllers/supplejack_api/application_controller_spec.rb +133 -0
  139. data/spec/controllers/supplejack_api/concepts_controller_spec.rb +83 -0
  140. data/spec/controllers/supplejack_api/concerns/records_controller_metrics_spec.rb +60 -0
  141. data/spec/controllers/supplejack_api/harvester/concepts_controller_spec.rb +57 -0
  142. data/spec/controllers/supplejack_api/harvester/records_controller_spec.rb +138 -0
  143. data/spec/controllers/supplejack_api/metrics_api_controller_spec.rb +71 -0
  144. data/spec/controllers/supplejack_api/partners_controller_spec.rb +77 -0
  145. data/spec/controllers/supplejack_api/records_controller_spec.rb +143 -0
  146. data/spec/controllers/supplejack_api/set_items_controller_spec.rb +78 -0
  147. data/spec/controllers/supplejack_api/sources_controller_spec.rb +161 -0
  148. data/spec/controllers/supplejack_api/status_controller_spec.rb +120 -0
  149. data/spec/controllers/supplejack_api/user_sets_controller_spec.rb +233 -0
  150. data/spec/controllers/supplejack_api/users_controller_spec.rb +61 -0
  151. data/spec/dummy/README.rdoc +268 -0
  152. data/spec/dummy/Rakefile +7 -0
  153. data/spec/dummy/app/assets/javascripts/application.js +23 -0
  154. data/spec/dummy/app/assets/stylesheets/application.css +22 -0
  155. data/spec/dummy/app/controllers/application_controller.rb +10 -0
  156. data/spec/dummy/app/helpers/application_helper.rb +9 -0
  157. data/spec/dummy/app/supplejack_api/concept_schema.rb +83 -0
  158. data/spec/dummy/app/supplejack_api/record_schema.rb +64 -0
  159. data/spec/dummy/app/supplejack_api/record_schema.txt +66 -0
  160. data/spec/dummy/app/views/layouts/application.html.erb +23 -0
  161. data/spec/dummy/app/workers/supplejack_api/clear_index_buffer.rb +32 -0
  162. data/spec/dummy/app/workers/supplejack_api/flush_old_records_worker.rb +17 -0
  163. data/spec/dummy/app/workers/supplejack_api/index_buffer.rb +49 -0
  164. data/spec/dummy/app/workers/supplejack_api/index_source_worker.rb +39 -0
  165. data/spec/dummy/app/workers/supplejack_api/index_worker.rb +82 -0
  166. data/spec/dummy/app/workers/supplejack_api/store_user_activity_worker.rb +24 -0
  167. data/spec/dummy/config.ru +11 -0
  168. data/spec/dummy/config/application.rb +76 -0
  169. data/spec/dummy/config/application.yml +31 -0
  170. data/spec/dummy/config/application.yml.example +36 -0
  171. data/spec/dummy/config/boot.rb +17 -0
  172. data/spec/dummy/config/environment.rb +12 -0
  173. data/spec/dummy/config/environments/development.rb +42 -0
  174. data/spec/dummy/config/environments/production.rb +76 -0
  175. data/spec/dummy/config/environments/test.rb +46 -0
  176. data/spec/dummy/config/initializers/backtrace_silencers.rb +14 -0
  177. data/spec/dummy/config/initializers/devise.rb +214 -0
  178. data/spec/dummy/config/initializers/inflections.rb +22 -0
  179. data/spec/dummy/config/initializers/kaminari_config.rb +17 -0
  180. data/spec/dummy/config/initializers/mime_types.rb +12 -0
  181. data/spec/dummy/config/initializers/mongoid.rb +9 -0
  182. data/spec/dummy/config/initializers/quiet_logger.rb +23 -0
  183. data/spec/dummy/config/initializers/resque.rb +18 -0
  184. data/spec/dummy/config/initializers/secret_token.rb +14 -0
  185. data/spec/dummy/config/initializers/session_store.rb +15 -0
  186. data/spec/dummy/config/initializers/simple_form.rb +149 -0
  187. data/spec/dummy/config/initializers/simple_form_foundation.rb +33 -0
  188. data/spec/dummy/config/initializers/state_machine.rb +8 -0
  189. data/spec/dummy/config/initializers/sunspot.rb +32 -0
  190. data/spec/dummy/config/initializers/wrap_parameters.rb +17 -0
  191. data/spec/dummy/config/locales/devise.en.yml +63 -0
  192. data/spec/dummy/config/locales/en.yml +66 -0
  193. data/spec/dummy/config/locales/simple_form.en.yml +33 -0
  194. data/spec/dummy/config/mongoid.travis.yml +34 -0
  195. data/spec/dummy/config/mongoid.yml +36 -0
  196. data/spec/dummy/config/resque-pool.yml +18 -0
  197. data/spec/dummy/config/resque_schedule.yml +12 -0
  198. data/spec/dummy/config/routes.rb +11 -0
  199. data/spec/dummy/config/secrets.yml +8 -0
  200. data/spec/dummy/config/sunspot.yml +38 -0
  201. data/spec/dummy/db/concepts.json +37 -0
  202. data/spec/dummy/db/source_authorities.json +116 -0
  203. data/spec/dummy/public/404.html +35 -0
  204. data/spec/dummy/public/422.html +35 -0
  205. data/spec/dummy/public/500.html +34 -0
  206. data/spec/dummy/public/favicon.ico +8 -0
  207. data/spec/dummy/script/rails +6 -0
  208. data/spec/dummy/solr/collection1/conf/elevate.xml +36 -0
  209. data/spec/dummy/solr/collection1/conf/mapping-FoldToASCII.txt +3813 -0
  210. data/spec/dummy/solr/collection1/conf/schema.xml +292 -0
  211. data/spec/dummy/solr/collection1/conf/solrconfig.xml +1780 -0
  212. data/spec/dummy/solr/collection1/conf/spellings.txt +2 -0
  213. data/spec/dummy/solr/collection1/conf/stopwords.txt +58 -0
  214. data/spec/dummy/solr/collection1/conf/synonyms.txt +31 -0
  215. data/spec/factories/concepts.rb +16 -0
  216. data/spec/factories/daily_metrics.rb +10 -0
  217. data/spec/factories/faceted_metrics.rb +25 -0
  218. data/spec/factories/fragment.rb +14 -0
  219. data/spec/factories/partners.rb +14 -0
  220. data/spec/factories/record_interaction.rb +17 -0
  221. data/spec/factories/records.rb +47 -0
  222. data/spec/factories/set_interaction.rb +15 -0
  223. data/spec/factories/source_authorities.rb +19 -0
  224. data/spec/factories/sources.rb +16 -0
  225. data/spec/factories/usage_metrics.rb +20 -0
  226. data/spec/factories/user_activities.rb +14 -0
  227. data/spec/factories/user_sets.rb +27 -0
  228. data/spec/factories/users.rb +23 -0
  229. data/spec/helpers/application_helper_spec.rb +35 -0
  230. data/spec/models/concept_spec.rb +163 -0
  231. data/spec/models/fragment_spec.rb +15 -0
  232. data/spec/models/site_activity_spec.rb +103 -0
  233. data/spec/models/source_activity_spec.rb +56 -0
  234. data/spec/models/source_authority_spec.rb +42 -0
  235. data/spec/models/supplejack_api/api_concept/concept_fragment_spec.rb +189 -0
  236. data/spec/models/supplejack_api/api_record/record_fragment_spec.rb +189 -0
  237. data/spec/models/supplejack_api/concept_spec.rb +0 -0
  238. data/spec/models/supplejack_api/interaction_updaters/all_usage_metric_spec.rb +41 -0
  239. data/spec/models/supplejack_api/interaction_updaters/set_metrics_spec.rb +32 -0
  240. data/spec/models/supplejack_api/interaction_updaters/usage_metrics_spec.rb +44 -0
  241. data/spec/models/supplejack_api/partner_spec.rb +20 -0
  242. data/spec/models/supplejack_api/record_search_spec.rb +429 -0
  243. data/spec/models/supplejack_api/record_spec.rb +280 -0
  244. data/spec/models/supplejack_api/schema_definition_spec.rb +272 -0
  245. data/spec/models/supplejack_api/search_spec.rb +243 -0
  246. data/spec/models/supplejack_api/set_item_spec.rb +123 -0
  247. data/spec/models/supplejack_api/source_spec.rb +22 -0
  248. data/spec/models/supplejack_api/support/fragment_helpers_spec.rb +216 -0
  249. data/spec/models/supplejack_api/support/harvestable_spec.rb +177 -0
  250. data/spec/models/supplejack_api/support/searchable_spec.rb +85 -0
  251. data/spec/models/supplejack_api/support/storable_spec.rb +18 -0
  252. data/spec/models/supplejack_api/user_activity_spec.rb +88 -0
  253. data/spec/models/supplejack_api/user_set_spec.rb +559 -0
  254. data/spec/models/supplejack_api/user_spec.rb +348 -0
  255. data/spec/routing/concepts_routing_spec.rb +22 -0
  256. data/spec/routing/harvester_constraint_spec.rb +66 -0
  257. data/spec/routing/harvester_routing_spec.rb +51 -0
  258. data/spec/routing/partner_routing_spec.rb +34 -0
  259. data/spec/routing/records_routing_spec.rb +26 -0
  260. data/spec/routing/sets_routing_spec.rb +44 -0
  261. data/spec/routing/source_routing_spec.rb +38 -0
  262. data/spec/routing/users_routing_spec.rb +18 -0
  263. data/spec/serializers/concept_record_serializer_spec.rb +30 -0
  264. data/spec/serializers/supplejack_api/application_serializer_spec.rb +14 -0
  265. data/spec/serializers/supplejack_api/concept_search_serializer_spec.rb +34 -0
  266. data/spec/serializers/supplejack_api/concept_serializer_spec.rb +92 -0
  267. data/spec/serializers/supplejack_api/record_search_serializer_spec.rb +34 -0
  268. data/spec/serializers/supplejack_api/record_serializer_spec.rb +271 -0
  269. data/spec/serializers/supplejack_api/search_serializer_spec.rb +90 -0
  270. data/spec/serializers/supplejack_api/user_serializer_spec.rb +22 -0
  271. data/spec/serializers/supplejack_api/user_set_serializer_spec.rb +96 -0
  272. data/spec/services/metrics_api/v3/api_spec.rb +23 -0
  273. data/spec/services/metrics_api/v3/endpoints/facets_spec.rb +25 -0
  274. data/spec/services/metrics_api/v3/endpoints/global_spec.rb +22 -0
  275. data/spec/services/metrics_api/v3/endpoints/root_spec.rb +49 -0
  276. data/spec/services/metrics_api/v3/presenters/extended_metadata_spec.rb +49 -0
  277. data/spec/spec_helper.rb +70 -0
  278. data/spec/support/api/schemas/metrics/daily_metrics_metadata.json +24 -0
  279. data/spec/support/api/schemas/metrics/extended_metrics.json +26 -0
  280. data/spec/support/api/schemas/metrics/extended_response.json +6 -0
  281. data/spec/support/api/schemas/metrics/facets_response.json +6 -0
  282. data/spec/support/api/schemas/metrics/record_metadata.json +33 -0
  283. data/spec/support/api/schemas/metrics/top_level_response.json +6 -0
  284. data/spec/support/api/schemas/metrics/view_metadata.json +33 -0
  285. data/spec/support/api_schema_matcher.rb +14 -0
  286. data/spec/support/devise.rb +10 -0
  287. data/spec/workers/supplejack_api/daily_metrics_worker_spec.rb +140 -0
  288. data/spec/workers/supplejack_api/flush_old_records_worker_spec.rb +20 -0
  289. data/spec/workers/supplejack_api/index_worker_spec.rb +52 -0
  290. data/spec/workers/supplejack_api/source_index_worker_spec.rb +61 -0
  291. metadata +1231 -0
@@ -0,0 +1,105 @@
1
+ # frozen_string_literal: true
2
+ # The majority of the Supplejack API code is Crown copyright (C) 2014, New Zealand Government,
3
+ # and is licensed under the GNU General Public License, version 3.
4
+ # One component is a third party component. See https://github.com/DigitalNZ/supplejack_api for details.
5
+ #
6
+ # Supplejack was created by DigitalNZ at the National Library of NZ and
7
+ # the Department of Internal Affairs. http://digitalnz.org/supplejack
8
+
9
+ module SupplejackApi
10
+ module Support
11
+ module Harvestable
12
+ extend ActiveSupport::Concern
13
+
14
+ def create_or_update_fragment(attributes)
15
+ if fragment = find_fragment(attributes['source_id'])
16
+ fragment.clear_attributes
17
+ elsif fragments.count.zero?
18
+ fragment = primary_fragment
19
+ else
20
+ fragment = fragments.build
21
+ end
22
+
23
+ fragment.update_from_harvest(attributes)
24
+ end
25
+
26
+ def update_from_harvest(attributes = {})
27
+ attributes = attributes.try(:symbolize_keys) || {}
28
+
29
+ attributes[:status] ||= 'active'
30
+
31
+ self.class.fields.each do |name, _field|
32
+ if attributes.key?(name.to_sym)
33
+ value = Array(attributes[name.to_sym]).first
34
+ send("#{name}=", value)
35
+ end
36
+ end
37
+
38
+ primary_fragment.update_from_harvest(attributes)
39
+ self.updated_at = Time.now
40
+ end
41
+
42
+ def update_from_harvest!(attributes = {})
43
+ update_from_harvest(attributes)
44
+ save
45
+ end
46
+
47
+ def set_status(required_fragments)
48
+ missing_fragments = Array(required_fragments) - fragments.map(&:source_id)
49
+ self.status = missing_fragments.empty? ? 'active' : 'partial'
50
+ end
51
+
52
+ # Sets all the Record attributes to nil except the internal ones
53
+ # that shouldn't be removed (_id, _type, etc..)
54
+ #
55
+ def clear_attributes
56
+ self[:source_url] = nil
57
+ primary_fragment.clear_attributes
58
+ end
59
+
60
+ def unset_null_fields
61
+ raw_json = raw_attributes || {}
62
+ unset_hash = {}
63
+ raw_json.each do |key, value|
64
+ unset_hash.merge!(key => true) if value.nil?
65
+ end
66
+ if raw_json['fragments'].present?
67
+ raw_json['fragments'].each_with_index do |fragment, index|
68
+ next if fragment.nil?
69
+ fragment.each do |key, value|
70
+ unset_hash.merge!("fragments.#{index}.#{key}" => true) if value.nil?
71
+ end
72
+ end
73
+ end
74
+ collection.find(atomic_selector).update('$unset' => unset_hash) if unset_hash.any?
75
+ end
76
+
77
+ module ClassMethods
78
+ def find_or_initialize_by_identifier(attributes)
79
+ attributes = attributes.symbolize_keys
80
+ identifier = attributes.delete(:internal_identifier)
81
+ identifier = identifier.first if identifier.is_a?(Array)
82
+ find_or_initialize_by(internal_identifier: identifier)
83
+ end
84
+
85
+ def flush_old_records(source_id, job_id)
86
+ where(
87
+ :'fragments.source_id' => source_id,
88
+ :'fragments.job_id'.ne => job_id,
89
+ :status.in => %w(active supressed)
90
+ ).update_all(status: 'deleted', updated_at: Time.now)
91
+
92
+ cursor = deleted.where('fragments.source_id': source_id)
93
+ total = cursor.count
94
+ start = 0
95
+ chunk_size = 10_000
96
+ while start < total
97
+ records = cursor.limit(chunk_size).skip(start)
98
+ Sunspot.remove(records)
99
+ start += chunk_size
100
+ end
101
+ end
102
+ end
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,115 @@
1
+ # frozen_string_literal: true
2
+ # The majority of the Supplejack API code is Crown copyright (C) 2014, New Zealand Government,
3
+ # and is licensed under the GNU General Public License, version 3.
4
+ # One component is a third party component. See https://github.com/DigitalNZ/supplejack_api for details.
5
+ #
6
+ # Supplejack was created by DigitalNZ at the National Library of NZ and
7
+ # the Department of Internal Affairs. http://digitalnz.org/supplejack
8
+
9
+ module SupplejackApi
10
+ module Support
11
+ module Searchable
12
+ extend ActiveSupport::Concern
13
+
14
+ included do
15
+ include Sunspot::Mongoid
16
+
17
+ searchable if: :should_index? do
18
+ string :internal_identifier
19
+ integer :record_type
20
+
21
+ string :source_id do
22
+ primary_fragment.source_id
23
+ end
24
+
25
+ build_sunspot_schema(self)
26
+ end
27
+ end
28
+
29
+ SUNSPOT_TYPE_NAMES = {
30
+ string: :string,
31
+ integer: :integer,
32
+ datetime: :time,
33
+ boolean: :boolean,
34
+ latlon: :latlon
35
+ }.freeze
36
+
37
+ module ClassMethods
38
+ def schema_class
39
+ "#{to_s.demodulize}Schema".constantize
40
+ end
41
+
42
+ def custom_find(id, scope = nil, options = {})
43
+ options ||= {}
44
+ class_scope = unscoped
45
+ class_scope = class_scope.active unless options.delete(:status) == :all
46
+ column = "#{name.demodulize.downcase}_id"
47
+
48
+ if id.to_s =~ /^\d+$/
49
+ data = class_scope.where(column => id).first
50
+ elsif id.to_s =~ /^[0-9a-f]{24}$/i
51
+ data = class_scope.find(id)
52
+ end
53
+
54
+ raise Mongoid::Errors::DocumentNotFound.new(self, [id], [id]) unless data
55
+
56
+ begin
57
+ data.find_next_and_previous_records(scope, options) if options.any?
58
+ rescue Sunspot::UnrecognizedFieldError,
59
+ RSolr::Error::Http, Timeout::Error,
60
+ Errno::ECONNREFUSED,
61
+ Errno::ECONNRESET => e
62
+
63
+ Rails.logger.error e.inspect
64
+ end
65
+
66
+ data
67
+ end
68
+
69
+ def build_sunspot_schema(builder)
70
+ schema_class.fields.each do |_name, field|
71
+ options = {}
72
+ search_as = field.search_as || []
73
+
74
+ value_block = nil
75
+ if field.search_value.present?
76
+ value_block = proc do
77
+ field.search_value.call(self)
78
+ end
79
+ end
80
+
81
+ options[:as] = field.solr_name if field.solr_name.present?
82
+
83
+ if search_as.include? :filter
84
+ filter_options = {}
85
+ filter_options[:multiple] = true if field.multi_value.present?
86
+ type = SUNSPOT_TYPE_NAMES[field.type]
87
+
88
+ builder.public_send(type, field.name, options.merge(filter_options), &value_block)
89
+ end
90
+
91
+ if search_as.include? :fulltext
92
+ options[:boost] = field.search_boost if field.search_boost.present?
93
+ builder.text field.name, options, &value_block
94
+ end
95
+ end
96
+ end
97
+
98
+ def valid_facets
99
+ facets = []
100
+
101
+ schema_class.fields.each do |name, field|
102
+ search_as = field.search_as || []
103
+ facets << name.to_sym if search_as.include? :filter
104
+ end
105
+
106
+ facets
107
+ end
108
+
109
+ def valid_groups
110
+ schema_class.groups.keys
111
+ end
112
+ end
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+ # The majority of the Supplejack API code is Crown copyright (C) 2014, New Zealand Government,
3
+ # and is licensed under the GNU General Public License, version 3.
4
+ # One component is a third party component. See https://github.com/DigitalNZ/supplejack_api for details.
5
+ #
6
+ # Supplejack was created by DigitalNZ at the National Library of NZ and
7
+ # the Department of Internal Affairs. http://digitalnz.org/supplejack
8
+
9
+ module SupplejackApi
10
+ module Support
11
+ module StatusLogger
12
+ def self.logger
13
+ logfile = File.open("#{Rails.root}/log/status.log", 'a')
14
+ logfile.sync = true
15
+ @logger ||= Logger.new(logfile)
16
+ @logger.formatter = proc do |_severity, datetime, _progname, msg|
17
+ "#{datetime.to_formatted_s(:db)} #{msg}\n"
18
+ end
19
+ @logger
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+ # The majority of the Supplejack API code is Crown copyright (C) 2014, New Zealand Government,
3
+ # and is licensed under the GNU General Public License, version 3.
4
+ # One component is a third party component. See https://github.com/DigitalNZ/supplejack_api for details.
5
+ #
6
+ # Supplejack was created by DigitalNZ at the National Library of NZ and
7
+ # the Department of Internal Affairs. http://digitalnz.org/supplejack
8
+
9
+ module SupplejackApi
10
+ module Support
11
+ module Storable
12
+ extend ActiveSupport::Concern
13
+
14
+ included do
15
+ include Mongoid::Document
16
+ include Mongoid::Timestamps
17
+ include Mongoid::Attributes::Dynamic
18
+
19
+ # Both of these fields are required in SJ API Core
20
+ # No need to configure in *Schema
21
+ field :internal_identifier, type: String
22
+ field :status, type: String
23
+ field :record_type, type: Integer, default: 0
24
+
25
+ index status: 1
26
+ index({ internal_identifier: 1 }, unique: true, drop_dups: true)
27
+ index record_type: 1
28
+ index({ record_id: 1 }, unique: true)
29
+
30
+ def self.build_model_fields
31
+ if RecordSchema.model_fields.present?
32
+ RecordSchema.model_fields.each do |name, index|
33
+ # Set the field
34
+ field name.to_sym, index.field_options if !!index.field_options
35
+
36
+ # Set the index
37
+ index_fields = !!index.index_fields ? index.index_fields : {}
38
+ index_options = !!index.index_options ? index.index_options : {}
39
+ index index_fields, index_options unless index_fields.empty?
40
+
41
+ # Set the validation
42
+ validates name.to_sym, index.validation if !!index.validation
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+ # The majority of the Supplejack API code is Crown copyright (C) 2014, New Zealand Government,
3
+ # and is licensed under the GNU General Public License, version 3.
4
+ # One component is a third party component. See https://github.com/DigitalNZ/supplejack_api for details.
5
+ #
6
+ # Supplejack was created by DigitalNZ at the National Library of NZ and
7
+ # the Department of Internal Affairs. http://digitalnz.org/supplejack
8
+
9
+ module SupplejackApi
10
+ module Support
11
+ module ValidationLogger
12
+ def self.logger
13
+ logfile = File.open("#{Rails.root}/log/validation.log", 'a')
14
+ logfile.sync = true # automatically flush data to file
15
+ @logger ||= Logger.new(logfile)
16
+ @logger.formatter = proc do |_severity, datetime, _progname, msg|
17
+ "#{datetime.to_formatted_s(:db)}: #{msg}\n"
18
+ end
19
+ @logger
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+ # The majority of the Supplejack API code is Crown copyright (C) 2014, New Zealand Government,
3
+ # and is licensed under the GNU General Public License, version 3.
4
+ # One component is a third party component. See https://github.com/DigitalNZ/supplejack_api for details.
5
+ #
6
+ # Supplejack was created by DigitalNZ at the National Library of NZ and
7
+ # the Department of Internal Affairs. http://digitalnz.org/supplejack
8
+
9
+ module SupplejackApi
10
+ class UsageMetrics
11
+ include Mongoid::Document
12
+ include Mongoid::Timestamps
13
+ include SupplejackApi::Concerns::QueryableByDate
14
+
15
+ store_in collection: 'usage_metrics'
16
+
17
+ field :record_field_value, type: String
18
+ field :searches, type: Integer, default: 0
19
+ field :gets, type: Integer, default: 0
20
+ field :user_set_views, type: Integer, default: 0
21
+ field :total_views, type: Integer, default: 0
22
+ field :records_added_to_user_sets, type: Integer, default: 0
23
+ field :date, type: Date
24
+ end
25
+ end
@@ -0,0 +1,211 @@
1
+ # frozen_string_literal: true
2
+ # The majority of the Supplejack API code is Crown copyright (C) 2014, New Zealand Government,
3
+ # and is licensed under the GNU General Public License, version 3.
4
+ # One component is a third party component. See https://github.com/DigitalNZ/supplejack_api for details.
5
+ #
6
+ # Supplejack was created by DigitalNZ at the National Library of NZ and
7
+ # the Department of Internal Affairs. http://digitalnz.org/supplejack
8
+
9
+ # TODO: Remove custom_search stuff to slim the class?
10
+ # rubocop:disable Metrics/ClassLength
11
+ module SupplejackApi
12
+ class User
13
+ include Mongoid::Document
14
+ include Mongoid::Timestamps
15
+ include ActiveModel::ForbiddenAttributesProtection
16
+ include Sortable::Query
17
+
18
+ store_in collection: 'users'
19
+
20
+ # Include default devise modules. Others available are:
21
+ # :token_authenticatable, :encryptable, :confirmable, :lockable, :timeoutable and :omniauthable
22
+ devise :trackable, :database_authenticatable, :token_authenticatable
23
+
24
+ # Database authenticatable
25
+ # field :email, type: String, null: false
26
+ # field :encrypted_password, type: String, null: false
27
+ field :email, type: String
28
+ field :encrypted_password, type: String
29
+ field :name, type: String
30
+ field :username, type: String
31
+
32
+ index authentication_token: 1
33
+
34
+ # Trackable
35
+ field :sign_in_count, type: Integer
36
+ field :current_sign_in_at, type: Time
37
+ field :last_sign_in_at, type: Time
38
+ field :current_sign_in_ip, type: String
39
+ field :last_sign_in_ip, type: String
40
+
41
+ # Token authenticatable
42
+ field :authentication_token, type: String
43
+
44
+ field :daily_requests, type: Integer, default: 0
45
+ field :monthly_requests, type: Integer, default: 0
46
+ field :max_requests, type: Integer, default: 10_000
47
+ field :role, type: String, default: 'developer'
48
+
49
+ field :daily_activity, type: Hash
50
+ field :daily_activity_stored, type: Boolean, default: true
51
+ index daily_activity_stored: 1
52
+
53
+ has_many :user_activities, class_name: 'SupplejackApi::UserActivity'
54
+
55
+ scope :with_daily_activity, -> { where(daily_activity_stored: false) }
56
+
57
+ alias api_key authentication_token
58
+
59
+ before_save :ensure_authentication_token
60
+
61
+ has_many :user_sets, dependent: :destroy, autosave: true, class_name: 'SupplejackApi::UserSet' do
62
+ def custom_find(id)
63
+ user_set = if BSON::ObjectId.legal?(id.to_s)
64
+ find(id) rescue nil
65
+ else
66
+ where(url: id).first
67
+ end
68
+ end
69
+ end
70
+
71
+ def sets=(attrs_array)
72
+ return false unless attrs_array.try(:any?)
73
+ attrs_array.each { |attrs| user_sets.build(attrs) }
74
+ end
75
+
76
+ def name
77
+ name = self[:name]
78
+ name.present? ? name : username
79
+ end
80
+
81
+ def updated_today?
82
+ updated_at > Time.now.beginning_of_day
83
+ end
84
+
85
+ def check_daily_requests
86
+ if updated_today?
87
+ increment_daily_requests
88
+ else
89
+ self.daily_requests = 1
90
+ end
91
+
92
+ if daily_requests == (max_requests * 0.9).floor
93
+ SupplejackApi::RequestLimitMailer.at90percent(self).deliver
94
+ SupplejackApi::RequestLimitMailer.at90percent_admin(self).deliver
95
+ elsif daily_requests == max_requests
96
+ SupplejackApi::RequestLimitMailer.at100percent(self).deliver
97
+ SupplejackApi::RequestLimitMailer.at100percent_admin(self).deliver
98
+ end
99
+ end
100
+
101
+ def increment_daily_requests
102
+ self.daily_requests ||= 0
103
+ self.daily_requests += 1
104
+ end
105
+
106
+ def update_tracked_fields(request)
107
+ old_current = current_sign_in_at
108
+ new_current = Time.now.utc
109
+ self.last_sign_in_at = old_current || new_current
110
+ self.current_sign_in_at = new_current
111
+
112
+ old_current = current_sign_in_ip
113
+ new_current = request.ip
114
+ self.last_sign_in_ip = old_current || new_current
115
+ self.current_sign_in_ip = new_current
116
+
117
+ self.sign_in_count ||= 0
118
+ self.sign_in_count += 1
119
+ end
120
+
121
+ def update_daily_activity(request)
122
+ # Get the controller name and strips out the `supplejack_api/` namespace
123
+ controller = request.params[:controller].to_s.gsub(%r{ supplejack_api/ }, '')
124
+ action = request.params[:action].to_s
125
+
126
+ if controller == 'records' && action == 'index'
127
+ controller = 'search'
128
+ action = 'records'
129
+ # TODO: Custom Search is deprecated. Evaluate for removal
130
+ elsif controller == 'custom_searches' && action == 'records'
131
+ controller = 'search'
132
+ action = 'custom_search'
133
+ elsif controller == 'set_items'
134
+ controller = 'user_sets'
135
+ action = "#{action}_item"
136
+ end
137
+
138
+ self.daily_activity ||= {}
139
+ self.daily_activity[controller] ||= {}
140
+
141
+ current_value = self.daily_activity[controller][action].to_i
142
+ self.daily_activity[controller][action] = current_value + 1
143
+
144
+ self.daily_activity_stored = false
145
+ end
146
+
147
+ def reset_daily_activity
148
+ self.daily_requests = 0
149
+ self.daily_activity = nil
150
+ self.daily_activity_stored = true
151
+ end
152
+
153
+ def over_limit?
154
+ updated_today? && daily_requests > max_requests
155
+ end
156
+
157
+ def calculate_last_30_days_requests
158
+ count = 0
159
+ user_activities.gt(created_at: Time.now - 30.days).each { |activity| count += activity.total.to_i }
160
+ self.monthly_requests = count
161
+ end
162
+
163
+ def requests_per_day(days = 30)
164
+ today = Time.zone.now.to_date
165
+ user_activities = self.user_activities.gt(created_at: today - days.days).asc(:created_at).to_a
166
+
167
+ requests = []
168
+ date = today - days.days
169
+ while date < today
170
+ date += 1.days
171
+ requests << (user_activities.find { |ua| ua.created_at.to_date == date }.try(:total) || 0)
172
+ end
173
+ requests
174
+ end
175
+
176
+ def name_or_user
177
+ name.present? ? split_on_at_symbol(name) : split_on_at_symbol(username)
178
+ end
179
+
180
+ def split_on_at_symbol(value)
181
+ if value.present? && value.include?('@')
182
+ value.split('@').first
183
+ else
184
+ value
185
+ end
186
+ end
187
+
188
+ def self.find_by_api_key(api_key)
189
+ where(authentication_token: api_key).first
190
+ end
191
+
192
+ def self.custom_find(id)
193
+ user = if id.to_s.length == 24
194
+ find(id)
195
+ else
196
+ find_by_api_key(id)
197
+ end
198
+
199
+ raise Mongoid::Errors::DocumentNotFound.new(self, id, id) unless user
200
+ user
201
+ end
202
+
203
+ def admin?
204
+ RecordSchema.roles[role.to_sym].try(:admin)
205
+ end
206
+
207
+ def can_change_featured_sets?
208
+ admin?
209
+ end
210
+ end
211
+ end