sufia-models 4.3.1 → 5.0.0.beta1
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.
- checksums.yaml +4 -4
- data/app/actors/sufia/generic_file/actor.rb +7 -10
- data/app/jobs/active_fedora_pid_based_job.rb +2 -3
- data/app/jobs/audit_job.rb +28 -31
- data/app/jobs/batch_update_job.rb +9 -8
- data/app/jobs/import_url_job.rb +2 -2
- data/app/models/batch.rb +11 -12
- data/app/models/checksum_audit_log.rb +7 -8
- data/app/models/concerns/sufia/ability.rb +4 -6
- data/app/models/concerns/sufia/collection.rb +4 -5
- data/app/models/concerns/sufia/file_stat_utils.rb +3 -3
- data/app/models/concerns/sufia/generic_file.rb +16 -14
- data/app/models/concerns/sufia/generic_file/audit.rb +50 -31
- data/app/models/concerns/sufia/generic_file/characterization.rb +3 -3
- data/app/models/concerns/sufia/generic_file/derivatives.rb +5 -5
- data/app/models/concerns/sufia/generic_file/full_text_indexing.rb +2 -2
- data/app/models/concerns/sufia/generic_file/metadata.rb +82 -11
- data/app/models/concerns/sufia/generic_file/proxy_deposit.rb +12 -3
- data/app/models/concerns/sufia/generic_file/versions.rb +1 -4
- data/app/models/concerns/sufia/generic_file/web_form.rb +13 -6
- data/app/models/concerns/sufia/model_methods.rb +11 -9
- data/app/models/concerns/sufia/user.rb +11 -28
- data/app/models/datastreams/file_content_datastream.rb +1 -1
- data/app/models/datastreams/fits_datastream.rb +1 -1
- data/app/models/file_download_stat.rb +2 -2
- data/app/models/file_usage.rb +5 -9
- data/app/models/file_view_stat.rb +2 -2
- data/app/models/local_authority.rb +2 -2
- data/app/models/proxy_deposit_request.rb +1 -1
- data/app/services/sufia/id_service.rb +5 -5
- data/app/services/sufia/noid.rb +10 -7
- data/lib/generators/sufia/models/cached_stats_generator.rb +31 -2
- data/lib/generators/sufia/models/install_generator.rb +31 -11
- data/lib/generators/sufia/models/proxies_generator.rb +31 -2
- data/lib/generators/sufia/models/templates/config/sufia.rb +10 -3
- data/lib/generators/sufia/models/upgrade400_generator.rb +33 -2
- data/lib/sufia/models/engine.rb +13 -4
- data/lib/sufia/models/file_content/versions.rb +12 -8
- data/lib/sufia/models/version.rb +1 -1
- data/lib/sufia/permissions/writable.rb +34 -16
- data/sufia-models.gemspec +4 -2
- metadata +91 -79
- data/app/models/concerns/sufia/generic_file/reload_on_save.rb +0 -18
- data/app/models/concerns/sufia/properties_datastream_behavior.rb +0 -32
- data/app/models/concerns/sufia/user_usage_stats.rb +0 -15
- data/app/models/datastreams/batch_rdf_datastream.rb +0 -6
- data/app/models/datastreams/generic_file_rdf_datastream.rb +0 -69
- data/app/models/datastreams/paranoid_rights_datastream.rb +0 -22
- data/app/models/datastreams/properties_datastream.rb +0 -4
- data/app/models/sufia/orcid_validator.rb +0 -8
- data/app/models/user_stat.rb +0 -2
- data/lib/generators/sufia/models/abstract_migration_generator.rb +0 -30
- data/lib/generators/sufia/models/orcid_field_generator.rb +0 -19
- data/lib/generators/sufia/models/templates/migrations/add_orcid_to_users.rb +0 -5
- data/lib/generators/sufia/models/templates/migrations/create_user_stats.rb +0 -19
- data/lib/generators/sufia/models/user_stats_generator.rb +0 -31
- data/lib/sufia/models/stats/user_stat_importer.rb +0 -85
- 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,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,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
|
data/app/models/user_stat.rb
DELETED
@@ -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,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
|
data/lib/tasks/stats_tasks.rake
DELETED
@@ -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
|