sufia-models 4.3.1 → 5.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/app/actors/sufia/generic_file/actor.rb +7 -10
  3. data/app/jobs/active_fedora_pid_based_job.rb +2 -3
  4. data/app/jobs/audit_job.rb +28 -31
  5. data/app/jobs/batch_update_job.rb +9 -8
  6. data/app/jobs/import_url_job.rb +2 -2
  7. data/app/models/batch.rb +11 -12
  8. data/app/models/checksum_audit_log.rb +7 -8
  9. data/app/models/concerns/sufia/ability.rb +4 -6
  10. data/app/models/concerns/sufia/collection.rb +4 -5
  11. data/app/models/concerns/sufia/file_stat_utils.rb +3 -3
  12. data/app/models/concerns/sufia/generic_file.rb +16 -14
  13. data/app/models/concerns/sufia/generic_file/audit.rb +50 -31
  14. data/app/models/concerns/sufia/generic_file/characterization.rb +3 -3
  15. data/app/models/concerns/sufia/generic_file/derivatives.rb +5 -5
  16. data/app/models/concerns/sufia/generic_file/full_text_indexing.rb +2 -2
  17. data/app/models/concerns/sufia/generic_file/metadata.rb +82 -11
  18. data/app/models/concerns/sufia/generic_file/proxy_deposit.rb +12 -3
  19. data/app/models/concerns/sufia/generic_file/versions.rb +1 -4
  20. data/app/models/concerns/sufia/generic_file/web_form.rb +13 -6
  21. data/app/models/concerns/sufia/model_methods.rb +11 -9
  22. data/app/models/concerns/sufia/user.rb +11 -28
  23. data/app/models/datastreams/file_content_datastream.rb +1 -1
  24. data/app/models/datastreams/fits_datastream.rb +1 -1
  25. data/app/models/file_download_stat.rb +2 -2
  26. data/app/models/file_usage.rb +5 -9
  27. data/app/models/file_view_stat.rb +2 -2
  28. data/app/models/local_authority.rb +2 -2
  29. data/app/models/proxy_deposit_request.rb +1 -1
  30. data/app/services/sufia/id_service.rb +5 -5
  31. data/app/services/sufia/noid.rb +10 -7
  32. data/lib/generators/sufia/models/cached_stats_generator.rb +31 -2
  33. data/lib/generators/sufia/models/install_generator.rb +31 -11
  34. data/lib/generators/sufia/models/proxies_generator.rb +31 -2
  35. data/lib/generators/sufia/models/templates/config/sufia.rb +10 -3
  36. data/lib/generators/sufia/models/upgrade400_generator.rb +33 -2
  37. data/lib/sufia/models/engine.rb +13 -4
  38. data/lib/sufia/models/file_content/versions.rb +12 -8
  39. data/lib/sufia/models/version.rb +1 -1
  40. data/lib/sufia/permissions/writable.rb +34 -16
  41. data/sufia-models.gemspec +4 -2
  42. metadata +91 -79
  43. data/app/models/concerns/sufia/generic_file/reload_on_save.rb +0 -18
  44. data/app/models/concerns/sufia/properties_datastream_behavior.rb +0 -32
  45. data/app/models/concerns/sufia/user_usage_stats.rb +0 -15
  46. data/app/models/datastreams/batch_rdf_datastream.rb +0 -6
  47. data/app/models/datastreams/generic_file_rdf_datastream.rb +0 -69
  48. data/app/models/datastreams/paranoid_rights_datastream.rb +0 -22
  49. data/app/models/datastreams/properties_datastream.rb +0 -4
  50. data/app/models/sufia/orcid_validator.rb +0 -8
  51. data/app/models/user_stat.rb +0 -2
  52. data/lib/generators/sufia/models/abstract_migration_generator.rb +0 -30
  53. data/lib/generators/sufia/models/orcid_field_generator.rb +0 -19
  54. data/lib/generators/sufia/models/templates/migrations/add_orcid_to_users.rb +0 -5
  55. data/lib/generators/sufia/models/templates/migrations/create_user_stats.rb +0 -19
  56. data/lib/generators/sufia/models/user_stats_generator.rb +0 -31
  57. data/lib/sufia/models/stats/user_stat_importer.rb +0 -85
  58. data/lib/tasks/stats_tasks.rake +0 -12
@@ -1,18 +0,0 @@
1
- # add this in here until we can use a version of Active Fedora that contains this ability
2
- module Sufia
3
- module GenericFile
4
- module ReloadOnSave
5
-
6
- attr_writer :reload_on_save
7
-
8
- def reload_on_save?
9
- !!@reload_on_save
10
- end
11
-
12
- def refresh
13
- self.reload if reload_on_save?
14
- end
15
- end
16
- end
17
- end
18
-
@@ -1,32 +0,0 @@
1
- module Sufia
2
- module PropertiesDatastreamBehavior
3
- extend ActiveSupport::Concern
4
-
5
- included do
6
- set_terminology do |t|
7
- t.root(path: "fields")
8
- # This is where we put the user id of the object depositor -- impacts permissions/access controls
9
- t.depositor index_as: [:symbol, :stored_searchable]
10
- # This is where we put the relative path of the file if submitted as a folder
11
- t.relative_path
12
- t.import_url path: 'importUrl', index_as: :symbol
13
- t.proxy_depositor path: 'proxyDepositor', index_as: :symbol
14
- # This value is set when a user indicates they are depositing this for someone else
15
- t.on_behalf_of path: 'onBehalfOf', index_as: :symbol
16
- end
17
- end
18
-
19
- module ClassMethods
20
- def xml_template
21
- builder = Nokogiri::XML::Builder.new do |xml|
22
- xml.fields
23
- end
24
- builder.doc
25
- end
26
- end
27
-
28
- def prefix
29
- ""
30
- end
31
- end
32
- end
@@ -1,15 +0,0 @@
1
- module Sufia::UserUsageStats
2
-
3
- def stats
4
- @stats ||= UserStat.where(user_id: id).order(date: :asc)
5
- end
6
-
7
- def total_file_views
8
- stats.reduce(0) { |total, stat| total + stat.file_views }
9
- end
10
-
11
- def total_file_downloads
12
- stats.reduce(0) { |total, stat| total + stat.file_downloads }
13
- end
14
-
15
- end
@@ -1,6 +0,0 @@
1
- class BatchRdfDatastream < ActiveFedora::NtriplesRDFDatastream
2
- property :part, predicate: RDF::DC.hasPart
3
- property :creator, predicate: RDF::DC.creator
4
- property :title, predicate: RDF::DC.title
5
- property :status, predicate: RDF::DC.type
6
- end
@@ -1,69 +0,0 @@
1
- class GenericFileRdfDatastream < ActiveFedora::NtriplesRDFDatastream
2
- property :part_of, predicate: RDF::DC.isPartOf
3
- property :resource_type, predicate: RDF::DC.type do |index|
4
- index.as :stored_searchable, :facetable
5
- end
6
- property :title, predicate: RDF::DC.title do |index|
7
- index.as :stored_searchable, :facetable
8
- end
9
- property :creator, predicate: RDF::DC.creator do |index|
10
- index.as :stored_searchable, :facetable
11
- end
12
- property :contributor, predicate: RDF::DC.contributor do |index|
13
- index.as :stored_searchable, :facetable
14
- end
15
- property :description, predicate: RDF::DC.description do |index|
16
- index.type :text
17
- index.as :stored_searchable
18
- end
19
- property :tag, predicate: RDF::DC.relation do |index|
20
- index.as :stored_searchable, :facetable
21
- end
22
- property :rights, predicate: RDF::DC.rights do |index|
23
- index.as :stored_searchable
24
- end
25
- property :publisher, predicate: RDF::DC.publisher do |index|
26
- index.as :stored_searchable, :facetable
27
- end
28
- property :date_created, predicate: RDF::DC.created do |index|
29
- index.as :stored_searchable
30
- end
31
- property :date_uploaded, predicate: RDF::DC.dateSubmitted do |index|
32
- index.type :date
33
- index.as :stored_sortable
34
- end
35
- property :date_modified, predicate: RDF::DC.modified do |index|
36
- index.type :date
37
- index.as :stored_sortable
38
- end
39
- property :subject, predicate: RDF::DC.subject do |index|
40
- index.as :stored_searchable, :facetable
41
- end
42
- property :language, predicate: RDF::DC.language do |index|
43
- index.as :stored_searchable, :facetable
44
- end
45
- property :identifier, predicate: RDF::DC.identifier do |index|
46
- index.as :stored_searchable
47
- end
48
- property :based_near, predicate: RDF::FOAF.based_near do |index|
49
- index.as :stored_searchable, :facetable
50
- end
51
- property :related_url, predicate: RDF::RDFS.seeAlso do |index|
52
- index.as :stored_searchable
53
- end
54
- property :bibliographic_citation, predicate: RDF::DC.bibliographicCitation do |index|
55
- index.as :stored_searchable
56
- end
57
- property :source, predicate: RDF::DC.source do |index|
58
- index.as :stored_searchable
59
- end
60
-
61
- # TODO: Move this somewhere more appropriate
62
- begin
63
- LocalAuthority.register_vocabulary(self, "subject", "lc_subjects")
64
- LocalAuthority.register_vocabulary(self, "language", "lexvo_languages")
65
- LocalAuthority.register_vocabulary(self, "tag", "lc_genres")
66
- rescue
67
- puts "tables for vocabularies missing"
68
- end
69
- end
@@ -1,22 +0,0 @@
1
- # subclass built-in Hydra RightsDatastream and build in extra model-level validation
2
- class ParanoidRightsDatastream < Hydra::Datastream::RightsMetadata
3
- use_terminology Hydra::Datastream::RightsMetadata
4
-
5
- VALIDATIONS = [
6
- {key: :edit_users, message: 'Depositor must have edit access', condition: lambda { |obj| !obj.edit_users.include?(obj.depositor) }},
7
- {key: :edit_groups, message: 'Public cannot have edit access', condition: lambda { |obj| obj.edit_groups.include?('public') }},
8
- {key: :edit_groups, message: 'Registered cannot have edit access', condition: lambda { |obj| obj.edit_groups.include?('registered') }}
9
- ]
10
-
11
- def validate(object)
12
- valid = true
13
- VALIDATIONS.each do |validation|
14
- if validation[:condition].call(object)
15
- object.errors[validation[:key]] ||= []
16
- object.errors[validation[:key]] << validation[:message]
17
- valid = false
18
- end
19
- end
20
- return valid
21
- end
22
- end
@@ -1,4 +0,0 @@
1
- # properties datastream: catch-all for info that didn't have another home. Particularly depositor.
2
- class PropertiesDatastream < ActiveFedora::OmDatastream
3
- include Sufia::PropertiesDatastreamBehavior
4
- end
@@ -1,8 +0,0 @@
1
- module Sufia
2
- class OrcidValidator < ActiveModel::Validator
3
- def validate(record)
4
- return if record.orcid.blank?
5
- record.errors.add(:orcid, 'must be a string of 19 characters, e.g., "0000-0000-0000-0000"') unless /\d{4}-\d{4}-\d{4}-\d{4}/.match(record.orcid)
6
- end
7
- end
8
- end
@@ -1,2 +0,0 @@
1
- class UserStat < ActiveRecord::Base
2
- end
@@ -1,30 +0,0 @@
1
- # -*- encoding : utf-8 -*-
2
- require 'rails/generators'
3
- require 'rails/generators/migration'
4
-
5
- class Sufia::Models::AbstractMigrationGenerator < Rails::Generators::Base
6
- include Rails::Generators::Migration
7
-
8
- # Implement the required interface for Rails::Generators::Migration.
9
- # taken from http://github.com/rails/rails/blob/master/activerecord/lib/generators/active_record.rb
10
- def self.next_migration_number(path)
11
- if @prev_migration_nr
12
- @prev_migration_nr += 1
13
- else
14
- if last_migration = Dir[File.join(path, '*.rb')].sort.last
15
- @prev_migration_nr = last_migration.sub(File.join(path, '/'), '').to_i + 1
16
- else
17
- @prev_migration_nr = Time.now.utc.strftime("%Y%m%d%H%M%S").to_i
18
- end
19
- end
20
- @prev_migration_nr.to_s
21
- end
22
-
23
- protected
24
-
25
- def better_migration_template(file)
26
- migration_template "migrations/#{file}", "db/migrate/#{file}"
27
- rescue Rails::Generators::Error => e
28
- say_status("warning", e.message, :yellow)
29
- end
30
- end
@@ -1,19 +0,0 @@
1
- require_relative 'abstract_migration_generator'
2
-
3
- class Sufia::Models::OrcidFieldGenerator < Sufia::Models::AbstractMigrationGenerator
4
- source_root File.expand_path('../templates', __FILE__)
5
-
6
- desc """
7
- This generator adds a field to hold users' ORCIDs to your application:
8
- 1. Creates a database migration if they do not exist in /db/migrate
9
- """
10
-
11
- def banner
12
- say_status("warning", "ADDING ORCID FIELD TO USER MODEL", :yellow)
13
- end
14
-
15
- # Setup the database migration
16
- def copy_migrations
17
- better_migration_template 'add_orcid_to_users.rb'
18
- end
19
- end
@@ -1,5 +0,0 @@
1
- class AddOrcidToUsers < ActiveRecord::Migration
2
- def change
3
- add_column :users, :orcid, :string
4
- end
5
- end
@@ -1,19 +0,0 @@
1
- class CreateUserStats < ActiveRecord::Migration
2
- def change
3
- create_table :user_stats do |t|
4
- t.integer :user_id
5
- t.datetime :date
6
- t.integer :file_views
7
- t.integer :file_downloads
8
-
9
- t.timestamps
10
- end
11
-
12
- add_column :file_view_stats, :user_id, :integer
13
- add_column :file_download_stats, :user_id, :integer
14
-
15
- add_index :user_stats, :user_id
16
- add_index :file_view_stats, :user_id
17
- add_index :file_download_stats, :user_id
18
- end
19
- end
@@ -1,31 +0,0 @@
1
- require_relative 'abstract_migration_generator'
2
-
3
- class Sufia::Models::UserStatsGenerator < Sufia::Models::AbstractMigrationGenerator
4
- source_root File.expand_path('../templates', __FILE__)
5
- argument :model_name, type: :string , default: "user"
6
-
7
- desc """
8
- This generator adds usage stats methods to the user model in your application:
9
- """
10
-
11
- def banner
12
- say_status("warning", "ADDING USER STATS-RELATED ABILITIES TO SUFIA MODELS", :yellow)
13
- end
14
-
15
- # Setup the database migrations
16
- def copy_migrations
17
- better_migration_template 'create_user_stats.rb'
18
- end
19
-
20
- def add_stats_mixin_to_user_model
21
- file_path = "app/models/#{model_name.underscore}.rb"
22
-
23
- if File.exists?(file_path)
24
- inject_into_file file_path, after: /include Sufia\:\:User.*$/ do
25
- "\n include Sufia::UserUsageStats"
26
- end
27
- else
28
- puts " \e[31mFailure\e[0m Sufia requires a user object. This generator assumes that the model is defined in the file #{file_path}, which does not exist. If you used a different name, please re-run the generator and provide that name as an argument. Such as \b rails g sufia:models:user_stats client"
29
- end
30
- end
31
- end
@@ -1,85 +0,0 @@
1
- module Sufia
2
- class UserStatImporter
3
-
4
- def initialize(options={})
5
- @verbose = options[:verbose]
6
- @logging = options[:logging]
7
- end
8
-
9
- def import
10
- log_message('Begin import of User stats.')
11
- ::User.find_each do |user|
12
- start_date = date_since_last_cache(user)
13
-
14
- stats = {}
15
- files_for_user(user).each do |file|
16
- view_stats = FileViewStat.statistics(file.id, start_date, user.id)
17
- stats = tally_results(view_stats, :views, stats)
18
-
19
- dl_stats = FileDownloadStat.statistics(file.id, start_date, user.id)
20
- stats = tally_results(dl_stats, :downloads, stats)
21
- end
22
-
23
- create_or_update_user_stats(stats, user)
24
- end
25
- log_message('User stats import complete.')
26
- end
27
-
28
-
29
- private
30
-
31
- def date_since_last_cache(user)
32
- last_cached_stat = UserStat.where(user_id: user.id).order(date: :asc).last
33
-
34
- if last_cached_stat
35
- last_cached_stat.date + 1.day
36
- else
37
- Sufia.config.analytic_start_date
38
- end
39
- end
40
-
41
- def files_for_user(user)
42
- ::GenericFile.where(Solrizer.solr_name('depositor', :symbol) => user.user_key)
43
- end
44
-
45
- # For each date, add the view and download counts for this
46
- # file to the view & download sub-totals for that day.
47
- # The resulting hash will look something like this:
48
- # {"2014-11-30 00:00:00 UTC" => {:views=>2, :downloads=>5},
49
- # "2014-12-01 00:00:00 UTC" => {:views=>4, :downloads=>4}}
50
- def tally_results(file_stats, stat_name, total_stats)
51
- file_stats.each do |stats|
52
- # Exclude the stats from today since it will only be a partial day's worth of data
53
- break if stats.date == Date.today
54
-
55
- date_key = stats.date.to_s
56
- old_count = total_stats[date_key] ? total_stats[date_key].fetch(stat_name) { 0 } : 0
57
- new_count = old_count + stats.method(stat_name).call
58
-
59
- old_values = total_stats[date_key] || {}
60
- total_stats.store(date_key, old_values)
61
- total_stats[date_key].store(stat_name, new_count)
62
- end
63
- total_stats
64
- end
65
-
66
- def create_or_update_user_stats(stats, user)
67
- stats.each do |date_string, data|
68
- date = Time.zone.parse(date_string)
69
-
70
- user_stat = UserStat.where(user_id: user.id).where(date: date).first
71
- user_stat ||= UserStat.new(user_id: user.id, date: date)
72
-
73
- user_stat.file_views = data[:views] || 0
74
- user_stat.file_downloads = data[:downloads] || 0
75
- user_stat.save!
76
- end
77
- end
78
-
79
- def log_message(message)
80
- puts message if @verbose
81
- Rails.logger.info "#{self.class}: #{message}" if @logging
82
- end
83
-
84
- end
85
- end
@@ -1,12 +0,0 @@
1
- namespace :sufia do
2
- namespace :stats do
3
-
4
- desc "Cache file view & download stats for all users"
5
- task :user_stats => :environment do
6
- require 'sufia/models/stats/user_stat_importer'
7
- importer = Sufia::UserStatImporter.new(verbose: true, logging: true)
8
- importer.import
9
- end
10
-
11
- end
12
- end