sufia-models 5.0.0 → 6.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 +8 -10
- data/app/jobs/active_fedora_pid_based_job.rb +2 -3
- data/app/jobs/audit_job.rb +46 -32
- 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 +12 -10
- data/app/models/concerns/sufia/ability.rb +4 -6
- data/app/models/concerns/sufia/collection.rb +4 -5
- data/app/models/concerns/sufia/generic_file/batches.rb +29 -0
- data/app/models/concerns/sufia/generic_file/characterization.rb +3 -3
- data/app/models/concerns/sufia/generic_file/content.rb +13 -0
- data/app/models/concerns/sufia/generic_file/derivatives.rb +5 -5
- data/app/models/concerns/sufia/generic_file/export.rb +4 -0
- data/app/models/concerns/sufia/generic_file/full_text_indexing.rb +2 -2
- data/app/models/concerns/sufia/generic_file/indexing.rb +23 -0
- data/app/models/concerns/sufia/generic_file/metadata.rb +80 -11
- data/app/models/concerns/sufia/generic_file/proxy_deposit.rb +12 -3
- data/app/models/concerns/sufia/generic_file/versions.rb +4 -4
- data/app/models/concerns/sufia/generic_file/web_form.rb +14 -6
- data/app/models/concerns/sufia/generic_file.rb +3 -86
- data/app/models/concerns/sufia/model_methods.rb +11 -9
- data/app/models/concerns/sufia/user.rb +11 -33
- data/app/models/datastreams/file_content_datastream.rb +1 -1
- data/app/models/datastreams/fits_datastream.rb +1 -1
- data/app/models/file_usage.rb +3 -3
- data/app/models/local_authority.rb +2 -2
- data/app/models/proxy_deposit_request.rb +1 -1
- data/app/services/sufia/generic_file_audit_service.rb +83 -0
- data/app/services/sufia/id_service.rb +5 -5
- data/app/services/sufia/noid.rb +10 -7
- data/app/services/sufia/repository_audit_service.rb +9 -0
- data/lib/generators/sufia/models/cached_stats_generator.rb +47 -3
- 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 -0
- 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 +9 -11
- data/lib/sufia/models/stats/user_stat_importer.rb +5 -9
- data/lib/sufia/models/version.rb +1 -1
- data/lib/sufia/permissions/writable.rb +34 -16
- data/sufia-models.gemspec +4 -2
- metadata +54 -33
- data/app/models/concerns/sufia/generic_file/audit.rb +0 -116
- 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/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/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/user_stats_generator.rb +0 -31
@@ -1,14 +1,14 @@
|
|
1
1
|
module Sufia
|
2
2
|
module GenericFile
|
3
3
|
module Versions
|
4
|
+
@@count = 0
|
4
5
|
def record_version_committer(user)
|
5
6
|
version = content.latest_version
|
6
7
|
# content datastream not (yet?) present
|
7
8
|
return if version.nil?
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
committer_login: user.user_key)
|
9
|
+
@@count += 1
|
10
|
+
# raise "Recording #{@@count} #{version.uri} for #{user.user_key}" if @@count == 3
|
11
|
+
VersionCommitter.create(version_id: version.uri, committer_login: user.user_key)
|
12
12
|
end
|
13
13
|
|
14
14
|
end
|
@@ -5,19 +5,27 @@ module Sufia
|
|
5
5
|
include Sufia::GenericFile::AccessibleAttributes
|
6
6
|
included do
|
7
7
|
before_save :remove_blank_assertions
|
8
|
+
attr_accessible *(terms_for_display + [:part_of, :permissions_attributes])
|
8
9
|
end
|
9
10
|
|
10
11
|
def remove_blank_assertions
|
11
12
|
terms_for_editing.each do |key|
|
12
|
-
|
13
|
+
if self[key] == ['']
|
14
|
+
self[key] = []
|
15
|
+
changed_attributes.delete(key) if attribute_was(key) == []
|
16
|
+
end
|
13
17
|
end
|
14
18
|
end
|
15
19
|
|
16
20
|
# override this method if you need to initialize more complex RDF assertions (b-nodes)
|
17
21
|
def initialize_fields
|
18
|
-
terms_for_editing.each do |key|
|
22
|
+
terms_for_editing.select { |key| self[key].blank? }.each do |key|
|
19
23
|
# if value is empty, we create an one element array to loop over for output
|
20
|
-
|
24
|
+
if self.class.multiple?(key)
|
25
|
+
self[key] = ['']
|
26
|
+
else
|
27
|
+
self[key] = ''
|
28
|
+
end
|
21
29
|
end
|
22
30
|
end
|
23
31
|
|
@@ -40,10 +48,10 @@ module Sufia
|
|
40
48
|
|
41
49
|
def to_jq_upload
|
42
50
|
return {
|
43
|
-
"name" =>
|
44
|
-
"size" =>
|
51
|
+
"name" => title,
|
52
|
+
"size" => file_size,
|
45
53
|
"url" => "/files/#{noid}",
|
46
|
-
"thumbnail_url" =>
|
54
|
+
"thumbnail_url" => id,
|
47
55
|
"delete_url" => "deleteme", # generic_file_path(id: id),
|
48
56
|
"delete_type" => "DELETE"
|
49
57
|
}
|
@@ -8,102 +8,19 @@ module Sufia
|
|
8
8
|
include Sufia::GenericFile::MimeTypes
|
9
9
|
include Sufia::GenericFile::Export
|
10
10
|
include Sufia::GenericFile::Characterization
|
11
|
-
include Sufia::GenericFile::Audit
|
12
11
|
include Sufia::GenericFile::Permissions
|
13
12
|
include Sufia::GenericFile::WebForm
|
14
13
|
include Sufia::GenericFile::Derivatives
|
15
14
|
include Sufia::GenericFile::Trophies
|
16
15
|
include Sufia::GenericFile::Featured
|
17
16
|
include Sufia::GenericFile::Metadata
|
17
|
+
include Sufia::GenericFile::Content
|
18
18
|
include Sufia::GenericFile::Versions
|
19
19
|
include Sufia::GenericFile::VirusCheck
|
20
|
-
include Sufia::GenericFile::ReloadOnSave
|
21
20
|
include Sufia::GenericFile::FullTextIndexing
|
22
21
|
include Sufia::GenericFile::ProxyDeposit
|
23
22
|
include Hydra::Collections::Collectible
|
24
|
-
|
25
|
-
|
26
|
-
belongs_to :batch, property: :is_part_of
|
27
|
-
|
28
|
-
around_save :retry_warming
|
29
|
-
|
30
|
-
attr_accessible *(terms_for_display + [:part_of, :permissions])
|
31
|
-
end
|
32
|
-
|
33
|
-
def persistent_url
|
34
|
-
"#{Sufia.config.persistent_hostpath}#{noid}"
|
35
|
-
end
|
36
|
-
|
37
|
-
def retry_warming
|
38
|
-
save_tries = 0
|
39
|
-
conflict_tries = 0
|
40
|
-
begin
|
41
|
-
yield
|
42
|
-
rescue RSolr::Error::Http => error
|
43
|
-
save_tries += 1
|
44
|
-
logger.warn "Retry Solr caught RSOLR error on #{self.pid}: #{error.inspect}"
|
45
|
-
# fail for good if the tries is greater than 3
|
46
|
-
raise if save_tries >=3
|
47
|
-
sleep 0.01
|
48
|
-
retry
|
49
|
-
rescue ActiveResource::ResourceConflict => error
|
50
|
-
conflict_tries += 1
|
51
|
-
logger.warn "Retry caught Active Resource Conflict #{self.pid}: #{error.inspect}"
|
52
|
-
raise if conflict_tries >=10
|
53
|
-
sleep 0.01
|
54
|
-
retry
|
55
|
-
rescue => error
|
56
|
-
if error.to_s.downcase.include? "conflict"
|
57
|
-
conflict_tries += 1
|
58
|
-
logger.warn "Retry caught Active Resource Conflict #{self.pid}: #{error.inspect}"
|
59
|
-
raise if conflict_tries >=10
|
60
|
-
sleep 0.01
|
61
|
-
retry
|
62
|
-
else
|
63
|
-
raise
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
# Get the files with a sibling relationship (belongs_to :batch)
|
69
|
-
# The batch id is minted when visiting the upload screen and attached
|
70
|
-
# to each file when it is done uploading. The Batch object is not created
|
71
|
-
# until all objects are done uploading and the user is redirected to
|
72
|
-
# BatchController#edit. Therefore, we must handle the case where
|
73
|
-
# self.batch_id is set but self.batch returns nil.
|
74
|
-
def related_files
|
75
|
-
return [] if batch.nil?
|
76
|
-
batch.generic_files.reject { |sibling| sibling.id == id }
|
77
|
-
end
|
78
|
-
|
79
|
-
# Unstemmed, searchable, stored
|
80
|
-
def self.noid_indexer
|
81
|
-
@noid_indexer ||= Solrizer::Descriptor.new(:text, :indexed, :stored)
|
82
|
-
end
|
83
|
-
|
84
|
-
def to_solr(solr_doc={}, opts={})
|
85
|
-
super(solr_doc, opts).tap do |solr_doc|
|
86
|
-
solr_doc[Solrizer.solr_name('label')] = self.label
|
87
|
-
solr_doc[Solrizer.solr_name('noid', Sufia::GenericFile.noid_indexer)] = noid
|
88
|
-
solr_doc[Solrizer.solr_name('file_format')] = file_format
|
89
|
-
solr_doc[Solrizer.solr_name('file_format', :facetable)] = file_format
|
90
|
-
solr_doc['all_text_timv'] = full_text.content
|
91
|
-
solr_doc = index_collection_pids(solr_doc)
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
def label=(new_label)
|
96
|
-
@inner_object.label = new_label
|
97
|
-
if self.title.empty?
|
98
|
-
self.title = [new_label].compact
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
|
-
# Is this file in the middle of being processed by a batch?
|
103
|
-
def processing?
|
104
|
-
return false if self.batch.blank?
|
105
|
-
return false if !self.batch.methods.include? :status
|
106
|
-
return (!self.batch.status.empty?) && (self.batch.status.count == 1) && (self.batch.status[0] == "processing")
|
107
|
-
end
|
23
|
+
include Sufia::GenericFile::Batches
|
24
|
+
include Sufia::GenericFile::Indexing
|
108
25
|
end
|
109
26
|
end
|
@@ -8,23 +8,25 @@ module Sufia
|
|
8
8
|
|
9
9
|
# OVERRIDE to support Hydra::Datastream::Properties which does not
|
10
10
|
# respond to :depositor_values but :depositor
|
11
|
-
# Adds metadata about the depositor to the asset
|
12
|
-
#
|
13
|
-
|
11
|
+
# Adds metadata about the depositor to the asset and ads +depositor_id+ to
|
12
|
+
# its individual edit permissions.
|
14
13
|
def apply_depositor_metadata(depositor)
|
15
|
-
rights_ds = self.datastreams["rightsMetadata"]
|
16
|
-
prop_ds = self.datastreams["properties"]
|
17
14
|
depositor_id = depositor.respond_to?(:user_key) ? depositor.user_key : depositor
|
18
15
|
|
19
|
-
|
20
|
-
|
16
|
+
self.edit_users += [depositor_id]
|
17
|
+
self.depositor = depositor_id
|
21
18
|
|
22
19
|
return true
|
23
20
|
end
|
24
21
|
|
25
22
|
def to_s
|
26
|
-
|
27
|
-
|
23
|
+
if title.present?
|
24
|
+
Array(title).join(" | ")
|
25
|
+
elsif label.present?
|
26
|
+
Array(label).join(" | ")
|
27
|
+
else
|
28
|
+
"No Title"
|
29
|
+
end
|
28
30
|
end
|
29
31
|
|
30
32
|
end
|
@@ -18,55 +18,33 @@ module Sufia::User
|
|
18
18
|
# Users should be followable
|
19
19
|
acts_as_followable
|
20
20
|
|
21
|
-
#
|
21
|
+
# Setup accessible (or protected) attributes for your model
|
22
22
|
has_many :proxy_deposit_requests, foreign_key: 'receiving_user_id'
|
23
|
+
|
23
24
|
has_many :deposit_rights_given, foreign_key: 'grantor_id', class_name: 'ProxyDepositRights', dependent: :destroy
|
24
25
|
has_many :can_receive_deposits_from, through: :deposit_rights_given, source: :grantee
|
26
|
+
|
25
27
|
has_many :deposit_rights_received, foreign_key: 'grantee_id', class_name: 'ProxyDepositRights', dependent: :destroy
|
26
28
|
has_many :can_make_deposits_for, through: :deposit_rights_received, source: :grantor
|
27
29
|
|
28
|
-
# Validate and normalize ORCIDs
|
29
|
-
validates_with OrcidValidator
|
30
|
-
after_validation :normalize_orcid
|
31
|
-
|
32
|
-
# Set up user profile avatars
|
33
30
|
mount_uploader :avatar, AvatarUploader, mount_on: :avatar_file_name
|
34
31
|
validates_with AvatarValidator
|
35
|
-
|
36
32
|
has_many :trophies
|
37
33
|
attr_accessor :update_directory
|
38
34
|
end
|
39
35
|
|
40
|
-
# Coerce the ORCID into URL format
|
41
|
-
def normalize_orcid
|
42
|
-
# Skip normalization if:
|
43
|
-
# 1. validation has already flagged the ORCID as invalid
|
44
|
-
# 2. the orcid field is blank
|
45
|
-
# 3. the orcid is already in its normalized form
|
46
|
-
return if self.errors[:orcid].first.present? || self.orcid.blank? || self.orcid.starts_with?('http://orcid.org/')
|
47
|
-
bare_orcid = /\d{4}-\d{4}-\d{4}-\d{4}/.match(self.orcid).string
|
48
|
-
self.orcid = "http://orcid.org/#{bare_orcid}"
|
49
|
-
end
|
50
|
-
|
51
36
|
# Format the json for select2 which requires just an id and a field called text.
|
52
37
|
# If we need an alternate format we should probably look at a json template gem
|
53
38
|
def as_json(opts = nil)
|
54
|
-
{
|
55
|
-
end
|
56
|
-
|
57
|
-
# Populate user instance with attributes from remote system (e.g., LDAP)
|
58
|
-
# There is no default implementation -- override this in your application
|
59
|
-
def populate_attributes
|
39
|
+
{id: user_key, text: display_name ? "#{display_name} (#{user_key})" : user_key}
|
60
40
|
end
|
61
41
|
|
62
42
|
def email_address
|
63
|
-
self.email
|
43
|
+
return self.email
|
64
44
|
end
|
65
45
|
|
66
46
|
def name
|
67
|
-
self.display_name.titleize ||
|
68
|
-
rescue
|
69
|
-
self.user_key
|
47
|
+
return self.display_name.titleize || self.user_key rescue self.user_key
|
70
48
|
end
|
71
49
|
|
72
50
|
# Redefine this for more intuitive keys in Redis
|
@@ -77,13 +55,13 @@ module Sufia::User
|
|
77
55
|
|
78
56
|
def trophy_files
|
79
57
|
trophies.map do |t|
|
80
|
-
::GenericFile.load_instance_from_solr(
|
58
|
+
::GenericFile.load_instance_from_solr(t.generic_file_id)
|
81
59
|
end
|
82
60
|
end
|
83
61
|
|
84
62
|
# method needed for messaging
|
85
63
|
def mailboxer_email(obj=nil)
|
86
|
-
nil
|
64
|
+
return nil
|
87
65
|
end
|
88
66
|
|
89
67
|
# The basic groups method, override or will fallback to Sufia::Ldap::User
|
@@ -107,9 +85,7 @@ module Sufia::User
|
|
107
85
|
[:email, :login, :display_name, :address, :admin_area,
|
108
86
|
:department, :title, :office, :chat_id, :website, :affiliation,
|
109
87
|
:telephone, :avatar, :group_list, :groups_last_update, :facebook_handle,
|
110
|
-
:twitter_handle, :googleplus_handle, :linkedin_handle, :remove_avatar
|
111
|
-
:orcid
|
112
|
-
]
|
88
|
+
:twitter_handle, :googleplus_handle, :linkedin_handle, :remove_avatar]
|
113
89
|
end
|
114
90
|
|
115
91
|
def current
|
@@ -143,5 +119,7 @@ module Sufia::User
|
|
143
119
|
def from_url_component(component)
|
144
120
|
User.find_by_user_key(component.gsub(/-dot-/, '.'))
|
145
121
|
end
|
122
|
+
|
146
123
|
end
|
124
|
+
|
147
125
|
end
|
data/app/models/file_usage.rb
CHANGED
@@ -10,7 +10,7 @@ class FileUsage
|
|
10
10
|
self.id = id
|
11
11
|
self.path = Sufia::Engine.routes.url_helpers.generic_file_path(Sufia::Noid.noidify(id))
|
12
12
|
earliest = Sufia.config.analytic_start_date
|
13
|
-
self.created =
|
13
|
+
self.created = ::GenericFile.find(id).create_date
|
14
14
|
self.created = earliest > created ? earliest : created unless earliest.blank?
|
15
15
|
self.downloads = FileDownloadStat.to_flots FileDownloadStat.statistics(id, created, user_id)
|
16
16
|
self.pageviews = FileViewStat.to_flots FileViewStat.statistics(id, created, user_id)
|
@@ -23,8 +23,8 @@ class FileUsage
|
|
23
23
|
def total_pageviews
|
24
24
|
self.pageviews.reduce(0) { |total, result| total + result[1].to_i }
|
25
25
|
end
|
26
|
-
|
27
|
-
# Package data for visualization using JQuery Flot
|
26
|
+
|
27
|
+
# Package data for visualization using JQuery Flot
|
28
28
|
def to_flot
|
29
29
|
[
|
30
30
|
{ label: "Pageviews", data: pageviews },
|
@@ -9,10 +9,10 @@ class LocalAuthority < ActiveRecord::Base
|
|
9
9
|
return unless self.where(name: name).empty?
|
10
10
|
authority = self.create(name: name)
|
11
11
|
format = opts.fetch(:format, :ntriples)
|
12
|
-
predicate = opts.fetch(:predicate, RDF::SKOS.prefLabel)
|
12
|
+
predicate = opts.fetch(:predicate, ::RDF::SKOS.prefLabel)
|
13
13
|
entries = []
|
14
14
|
sources.each do |uri|
|
15
|
-
RDF::Reader.open(uri, format: format) do |reader|
|
15
|
+
::RDF::Reader.open(uri, format: format) do |reader|
|
16
16
|
reader.each_statement do |statement|
|
17
17
|
if statement.predicate == predicate
|
18
18
|
entries << LocalAuthorityEntry.new(local_authority: authority,
|
@@ -78,7 +78,7 @@ class ProxyDepositRequest < ActiveRecord::Base
|
|
78
78
|
|
79
79
|
def title
|
80
80
|
return 'file not found' if deleted_file?
|
81
|
-
query = ActiveFedora::
|
81
|
+
query = ActiveFedora::SolrQueryBuilder.construct_query_for_ids([pid])
|
82
82
|
solr_response = ActiveFedora::SolrService.query(query, raw: true)
|
83
83
|
SolrDocument.new(solr_response['response']['docs'].first, solr_response).title
|
84
84
|
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
module Sufia
|
2
|
+
class GenericFileAuditService
|
3
|
+
attr_reader :generic_file
|
4
|
+
def initialize(file)
|
5
|
+
@generic_file = file
|
6
|
+
end
|
7
|
+
|
8
|
+
NO_RUNS = 999
|
9
|
+
|
10
|
+
# provides a human readable version of the audit status
|
11
|
+
def human_readable_audit_status
|
12
|
+
stat = audit_stat
|
13
|
+
case stat
|
14
|
+
when 0
|
15
|
+
'failing'
|
16
|
+
when 1
|
17
|
+
'passing'
|
18
|
+
else
|
19
|
+
stat
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# TODO: Run audits on all attached files. We're only auditing "content" at tht moment
|
24
|
+
# Pushes an AuditJob for each version of content if it hasn't been audited recently
|
25
|
+
# Returns the set of most recent audit status for each version of the content file
|
26
|
+
def audit
|
27
|
+
audit_content([])
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
private
|
32
|
+
def audit_content(log)
|
33
|
+
if generic_file.content.has_versions?
|
34
|
+
audit_file_versions("content", log)
|
35
|
+
else
|
36
|
+
log << audit_file("content", generic_file.content.uri)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def audit_file_versions file, log
|
41
|
+
generic_file.attached_files[file].versions.all.each do |version|
|
42
|
+
log << audit_file(file, version.uri, version.label)
|
43
|
+
end
|
44
|
+
log
|
45
|
+
end
|
46
|
+
|
47
|
+
def audit_stat
|
48
|
+
audit_results = audit.collect { |result| result["pass"] }
|
49
|
+
|
50
|
+
# check how many non runs we had
|
51
|
+
non_runs = audit_results.reduce(0) { |sum, value| value == NO_RUNS ? sum += 1 : sum }
|
52
|
+
if non_runs == 0
|
53
|
+
audit_results.reduce(true) { |sum, value| sum && value }
|
54
|
+
elsif non_runs < audit_results.length
|
55
|
+
result = audit_results.reduce(true) { |sum, value| value == NO_RUNS ? sum : sum && value }
|
56
|
+
"Some audits have not been run, but the ones run were #{result ? 'passing' : 'failing'}."
|
57
|
+
else
|
58
|
+
'Audits have not yet been run on this file.'
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def audit_file(file, uri, label = nil)
|
63
|
+
latest_audit = ChecksumAuditLog.logs_for(generic_file.id, file).first
|
64
|
+
return latest_audit unless needs_audit?(latest_audit)
|
65
|
+
Sufia.queue.push(AuditJob.new(generic_file.id, file, uri))
|
66
|
+
latest_audit || ChecksumAuditLog.new(pass: NO_RUNS, pid: generic_file.id, dsid: file, version: label)
|
67
|
+
end
|
68
|
+
|
69
|
+
def needs_audit?(latest_audit)
|
70
|
+
return true unless latest_audit
|
71
|
+
unless latest_audit.updated_at
|
72
|
+
logger.warn "***AUDIT*** problem with audit log! Latest Audit is not nil, but updated_at is not set #{latest_audit}"
|
73
|
+
return true
|
74
|
+
end
|
75
|
+
days_since_last_audit(latest_audit) >= Sufia.config.max_days_between_audits
|
76
|
+
end
|
77
|
+
|
78
|
+
def days_since_last_audit(latest_audit)
|
79
|
+
(DateTime.now - latest_audit.updated_at.to_date).to_i
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
end
|
@@ -9,11 +9,11 @@ module Sufia
|
|
9
9
|
|
10
10
|
@minter = ::Noid::Minter.new(template: noid_template)
|
11
11
|
@pid = $$
|
12
|
-
|
12
|
+
#@namespace = Sufia.config.id_namespace
|
13
13
|
@semaphore = Mutex.new
|
14
14
|
def self.valid?(identifier)
|
15
15
|
# remove the fedora namespace since it's not part of the noid
|
16
|
-
noid = identifier
|
16
|
+
noid = identifier#.split(":").last
|
17
17
|
return @minter.valid? noid
|
18
18
|
end
|
19
19
|
def self.mint
|
@@ -28,20 +28,20 @@ module Sufia
|
|
28
28
|
protected
|
29
29
|
|
30
30
|
def self.next_id
|
31
|
-
|
31
|
+
id = ''
|
32
32
|
File.open(Sufia.config.minter_statefile, File::RDWR|File::CREAT, 0644) do |f|
|
33
33
|
f.flock(File::LOCK_EX)
|
34
34
|
yaml = YAML::load(f.read)
|
35
35
|
yaml = {template: noid_template} unless yaml
|
36
36
|
minter = ::Noid::Minter.new(yaml)
|
37
|
-
|
37
|
+
id = minter.mint
|
38
38
|
f.rewind
|
39
39
|
yaml = YAML::dump(minter.dump)
|
40
40
|
f.write yaml
|
41
41
|
f.flush
|
42
42
|
f.truncate(f.pos)
|
43
43
|
end
|
44
|
-
|
44
|
+
id
|
45
45
|
end
|
46
46
|
end
|
47
47
|
end
|
data/app/services/sufia/noid.rb
CHANGED
@@ -2,16 +2,14 @@ module Sufia
|
|
2
2
|
module Noid
|
3
3
|
extend ActiveSupport::Concern
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
Sufia::IdService.mint
|
10
|
-
end
|
5
|
+
## This overrides the default behavior, which is to ask Fedora for a pid
|
6
|
+
# @see ActiveFedora::Sharding.assign_pid
|
7
|
+
def assign_pid
|
8
|
+
Sufia::IdService.mint
|
11
9
|
end
|
12
10
|
|
13
11
|
def noid
|
14
|
-
Noid.noidify(
|
12
|
+
Noid.noidify(id)
|
15
13
|
end
|
16
14
|
|
17
15
|
# Redefine this for more intuitive keys in Redis
|
@@ -24,6 +22,11 @@ module Sufia
|
|
24
22
|
String(identifier).split(":").last
|
25
23
|
end
|
26
24
|
|
25
|
+
# Create a pairtree like path for the given identifier
|
26
|
+
def treeify(identifier)
|
27
|
+
(identifier.scan(/..?/).first(4) + [identifier]).join('/')
|
28
|
+
end
|
29
|
+
|
27
30
|
def namespaceize(identifier)
|
28
31
|
return identifier if identifier.include?(':')
|
29
32
|
"#{namespace}:#{identifier}"
|
@@ -1,12 +1,32 @@
|
|
1
|
-
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
require 'rails/generators'
|
3
|
+
require 'rails/generators/migration'
|
4
|
+
|
5
|
+
class Sufia::Models::CachedStatsGenerator < Rails::Generators::Base
|
6
|
+
include Rails::Generators::Migration
|
2
7
|
|
3
|
-
class Sufia::Models::CachedStatsGenerator < Sufia::Models::AbstractMigrationGenerator
|
4
8
|
source_root File.expand_path('../templates', __FILE__)
|
9
|
+
argument :model_name, type: :string , default: "user"
|
5
10
|
|
6
11
|
desc """
|
7
12
|
This generator adds the ability to cache usage stats to your application:
|
8
13
|
1. Creates several database migrations if they do not exist in /db/migrate
|
14
|
+
2. Adds stats methods to the user model
|
9
15
|
"""
|
16
|
+
# Implement the required interface for Rails::Generators::Migration.
|
17
|
+
# taken from http://github.com/rails/rails/blob/master/activerecord/lib/generators/active_record.rb
|
18
|
+
def self.next_migration_number(path)
|
19
|
+
if @prev_migration_nr
|
20
|
+
@prev_migration_nr += 1
|
21
|
+
else
|
22
|
+
if last_migration = Dir[File.join(path, '*.rb')].sort.last
|
23
|
+
@prev_migration_nr = last_migration.sub(File.join(path, '/'), '').to_i + 1
|
24
|
+
else
|
25
|
+
@prev_migration_nr = Time.now.utc.strftime("%Y%m%d%H%M%S").to_i
|
26
|
+
end
|
27
|
+
end
|
28
|
+
@prev_migration_nr.to_s
|
29
|
+
end
|
10
30
|
|
11
31
|
def banner
|
12
32
|
say_status("warning", "ADDING STATS CACHING-RELATED SUFIA MODELS", :yellow)
|
@@ -14,11 +34,35 @@ This generator adds the ability to cache usage stats to your application:
|
|
14
34
|
|
15
35
|
# Setup the database migrations
|
16
36
|
def copy_migrations
|
37
|
+
# Can't get this any more DRY, because we need this order.
|
17
38
|
[
|
18
39
|
'create_file_view_stats.rb',
|
19
|
-
'create_file_download_stats.rb'
|
40
|
+
'create_file_download_stats.rb',
|
41
|
+
'create_user_stats.rb'
|
20
42
|
].each do |file|
|
21
43
|
better_migration_template file
|
22
44
|
end
|
23
45
|
end
|
46
|
+
|
47
|
+
def add_stats_mixin_to_user_model
|
48
|
+
file_path = "app/models/#{model_name.underscore}.rb"
|
49
|
+
|
50
|
+
if File.exists?(file_path)
|
51
|
+
inject_into_file file_path, after: /include Sufia\:\:User.*$/ do
|
52
|
+
"\n include Sufia::UserUsageStats"
|
53
|
+
end
|
54
|
+
else
|
55
|
+
puts " \e[31mFailure\e[0m Sufia requires a user object. This generators 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 client"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
def better_migration_template(file)
|
62
|
+
begin
|
63
|
+
migration_template "migrations/#{file}", "db/migrate/#{file}"
|
64
|
+
rescue Rails::Generators::Error => e
|
65
|
+
say_status("warning", e.message, :yellow)
|
66
|
+
end
|
67
|
+
end
|
24
68
|
end
|
@@ -1,7 +1,12 @@
|
|
1
|
-
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
require 'rails/generators'
|
3
|
+
require 'rails/generators/migration'
|
4
|
+
|
5
|
+
class Sufia::Models::InstallGenerator < Rails::Generators::Base
|
6
|
+
include Rails::Generators::Migration
|
2
7
|
|
3
|
-
class Sufia::Models::InstallGenerator < Sufia::Models::AbstractMigrationGenerator
|
4
8
|
source_root File.expand_path('../templates', __FILE__)
|
9
|
+
|
5
10
|
argument :model_name, type: :string , default: "user"
|
6
11
|
desc """
|
7
12
|
This generator makes the following changes to your application:
|
@@ -14,15 +19,30 @@ This generator makes the following changes to your application:
|
|
14
19
|
7. Runs full-text generator
|
15
20
|
8. Runs proxies generator
|
16
21
|
9. Runs cached stats generator
|
17
|
-
10. Runs ORCID field generator
|
18
|
-
11. Runs user stats generator
|
19
22
|
"""
|
23
|
+
|
24
|
+
# Implement the required interface for Rails::Generators::Migration.
|
25
|
+
# taken from http://github.com/rails/rails/blob/master/activerecord/lib/generators/active_record.rb
|
26
|
+
def self.next_migration_number(path)
|
27
|
+
if @prev_migration_nr
|
28
|
+
@prev_migration_nr += 1
|
29
|
+
else
|
30
|
+
if last_migration = Dir[File.join(path, '*.rb')].sort.last
|
31
|
+
@prev_migration_nr = last_migration.sub(File.join(path, '/'), '').to_i + 1
|
32
|
+
else
|
33
|
+
@prev_migration_nr = Time.now.utc.strftime("%Y%m%d%H%M%S").to_i
|
34
|
+
end
|
35
|
+
end
|
36
|
+
@prev_migration_nr.to_s
|
37
|
+
end
|
38
|
+
|
20
39
|
def banner
|
21
40
|
say_status("warning", "GENERATING SUFIA MODELS", :yellow)
|
22
41
|
end
|
23
42
|
|
24
43
|
# Setup the database migrations
|
25
44
|
def copy_migrations
|
45
|
+
# Can't get this any more DRY, because we need this order.
|
26
46
|
[
|
27
47
|
"acts_as_follower_migration.rb",
|
28
48
|
"add_social_to_users.rb",
|
@@ -94,13 +114,13 @@ This generator makes the following changes to your application:
|
|
94
114
|
generate 'sufia:models:cached_stats'
|
95
115
|
end
|
96
116
|
|
97
|
-
|
98
|
-
def orcid_field
|
99
|
-
generate 'sufia:models:orcid_field'
|
100
|
-
end
|
117
|
+
private
|
101
118
|
|
102
|
-
|
103
|
-
|
104
|
-
|
119
|
+
def better_migration_template(file)
|
120
|
+
begin
|
121
|
+
migration_template "migrations/#{file}", "db/migrate/#{file}"
|
122
|
+
rescue Rails::Generators::Error => e
|
123
|
+
say_status("warning", e.message, :yellow)
|
124
|
+
end
|
105
125
|
end
|
106
126
|
end
|