curation_concerns-models 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.md +177 -0
- data/README.md +42 -0
- data/Rakefile +1 -0
- data/app/actors/concerns/curation_concerns/manages_embargoes_actor.rb +99 -0
- data/app/actors/curation_concerns/base_actor.rb +90 -0
- data/app/actors/curation_concerns/generic_file_actor.rb +150 -0
- data/app/actors/curation_concerns/work_actor_behavior.rb +88 -0
- data/app/jobs/active_fedora_id_based_job.rb +22 -0
- data/app/jobs/active_fedora_pid_based_job.rb +6 -0
- data/app/jobs/audit_job.rb +58 -0
- data/app/jobs/characterize_job.rb +11 -0
- data/app/jobs/copy_permissions_job.rb +24 -0
- data/app/jobs/create_derivatives_job.rb +15 -0
- data/app/jobs/import_url_job.rb +56 -0
- data/app/jobs/ingest_local_file_job.rb +48 -0
- data/app/jobs/resolrize_job.rb +9 -0
- data/app/models/checksum_audit_log.rb +21 -0
- data/app/models/concerns/curation_concerns/ability.rb +34 -0
- data/app/models/concerns/curation_concerns/basic_metadata.rb +87 -0
- data/app/models/concerns/curation_concerns/collection_behavior.rb +47 -0
- data/app/models/concerns/curation_concerns/generic_file/belongs_to_works.rb +53 -0
- data/app/models/concerns/curation_concerns/generic_file/characterization.rb +89 -0
- data/app/models/concerns/curation_concerns/generic_file/content.rb +8 -0
- data/app/models/concerns/curation_concerns/generic_file/export.rb +343 -0
- data/app/models/concerns/curation_concerns/generic_file/full_text_indexing.rb +12 -0
- data/app/models/concerns/curation_concerns/generic_file/indexing.rb +14 -0
- data/app/models/concerns/curation_concerns/generic_file/versions.rb +16 -0
- data/app/models/concerns/curation_concerns/generic_file.rb +5 -0
- data/app/models/concerns/curation_concerns/generic_file_behavior.rb +44 -0
- data/app/models/concerns/curation_concerns/generic_work_behavior.rb +38 -0
- data/app/models/concerns/curation_concerns/has_representative.rb +14 -0
- data/app/models/concerns/curation_concerns/human_readable_type.rb +23 -0
- data/app/models/concerns/curation_concerns/permissions/readable.rb +19 -0
- data/app/models/concerns/curation_concerns/permissions/writable.rb +75 -0
- data/app/models/concerns/curation_concerns/permissions.rb +7 -0
- data/app/models/concerns/curation_concerns/serializers.rb +15 -0
- data/app/models/concerns/curation_concerns/solr_document_behavior.rb +135 -0
- data/app/models/concerns/curation_concerns/user.rb +65 -0
- data/app/models/concerns/curation_concerns/with_basic_metadata.rb +98 -0
- data/app/models/concerns/curation_concerns/with_generic_files.rb +29 -0
- data/app/models/curation_concerns/classify_concern.rb +47 -0
- data/app/models/curation_concerns/quick_classification_query.rb +31 -0
- data/app/models/datastreams/fits_datastream.rb +148 -0
- data/app/models/version_committer.rb +2 -0
- data/app/services/curation_concerns/characterization_service.rb +71 -0
- data/app/services/curation_concerns/full_text_extraction_service.rb +38 -0
- data/app/services/curation_concerns/generic_file_audit_service.rb +85 -0
- data/app/services/curation_concerns/generic_file_indexing_service.rb +14 -0
- data/app/services/curation_concerns/generic_work_indexing_service.rb +16 -0
- data/app/services/curation_concerns/noid.rb +23 -0
- data/app/services/curation_concerns/repository_audit_service.rb +9 -0
- data/app/services/curation_concerns/versioning_service.rb +27 -0
- data/config/locales/curation_concerns.en.yml +6 -0
- data/curation_concerns-models.gemspec +34 -0
- data/lib/curation_concerns/messages.rb +66 -0
- data/lib/curation_concerns/models/engine.rb +61 -0
- data/lib/curation_concerns/models/resque.rb +36 -0
- data/lib/curation_concerns/models/utils.rb +22 -0
- data/lib/curation_concerns/models/version.rb +5 -0
- data/lib/curation_concerns/models.rb +32 -0
- data/lib/generators/curation_concerns/models/abstract_migration_generator.rb +30 -0
- data/lib/generators/curation_concerns/models/clamav_generator.rb +19 -0
- data/lib/generators/curation_concerns/models/fulltext_generator.rb +28 -0
- data/lib/generators/curation_concerns/models/install_generator.rb +70 -0
- data/lib/generators/curation_concerns/models/templates/app/models/collection.rb +4 -0
- data/lib/generators/curation_concerns/models/templates/app/models/generic_file.rb +4 -0
- data/lib/generators/curation_concerns/models/templates/config/clamav.rb +1 -0
- data/lib/generators/curation_concerns/models/templates/config/curation_concerns.rb +123 -0
- data/lib/generators/curation_concerns/models/templates/config/mime_types.rb +6 -0
- data/lib/generators/curation_concerns/models/templates/config/redis.yml +9 -0
- data/lib/generators/curation_concerns/models/templates/config/redis_config.rb +32 -0
- data/lib/generators/curation_concerns/models/templates/config/resque-pool.yml +1 -0
- data/lib/generators/curation_concerns/models/templates/config/resque_admin.rb +10 -0
- data/lib/generators/curation_concerns/models/templates/config/resque_config.rb +5 -0
- data/lib/generators/curation_concerns/models/templates/migrations/create_checksum_audit_logs.rb +19 -0
- data/lib/generators/curation_concerns/models/templates/migrations/create_version_committers.rb +15 -0
- data/lib/tasks/curation_concerns-models_tasks.rake +75 -0
- data/lib/tasks/migrate.rake +13 -0
- data/lib/tasks/resque.rake +13 -0
- data/lib/tasks/solr_reindex.rake +8 -0
- metadata +282 -0
@@ -0,0 +1,85 @@
|
|
1
|
+
module CurationConcerns
|
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(stat)
|
12
|
+
case stat
|
13
|
+
when 0
|
14
|
+
'failing'
|
15
|
+
when 1
|
16
|
+
'passing'
|
17
|
+
else
|
18
|
+
stat
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# Audits each version of each file if it hasn't been audited recently
|
23
|
+
# Returns the set of most recent audit status for each version of the content file
|
24
|
+
# @param [Hash] log container for messages, mapping file ids to status
|
25
|
+
def audit(log={})
|
26
|
+
generic_file.files.each { |f| log[f.id] = audit_file(f) }
|
27
|
+
log
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
# Retrieve or generate the audit check for a file (all versions are checked for versioned files)
|
33
|
+
# @param [ActiveFedora::File] file to audit
|
34
|
+
# @param [Array] log container for messages
|
35
|
+
def audit_file(file, log=[])
|
36
|
+
versions = file.has_versions? ? file.versions.all : file
|
37
|
+
versions.each { |v| log << audit_file_version(file.id, v.uri) }
|
38
|
+
log
|
39
|
+
end
|
40
|
+
|
41
|
+
# Retrieve or generate the audit check for a file and provide a human-readable status message.
|
42
|
+
# @param [ActiveFedora::File] file to audit
|
43
|
+
def audit_stat(file)
|
44
|
+
audit_results = audit_file(file).collect { |result| result["pass"] }
|
45
|
+
# check how many non runs we had
|
46
|
+
non_runs = audit_results.reduce(0) { |sum, value| value == NO_RUNS ? sum += 1 : sum }
|
47
|
+
if non_runs == 0
|
48
|
+
audit_results.reduce(true) { |sum, value| sum && value }
|
49
|
+
elsif non_runs < audit_results.length
|
50
|
+
result = audit_results.reduce(true) { |sum, value| value == NO_RUNS ? sum : sum && value }
|
51
|
+
"Some audits have not been run, but the ones run were #{human_readable_audit_status(result)}."
|
52
|
+
else
|
53
|
+
'Audits have not yet been run on this file.'
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# Retrieve or generate the audit check for a specific version of a file
|
58
|
+
# @param [String] file_id used to find the file within its parent object (usually "original_file")
|
59
|
+
# @param [String] version_uri the version to be audited (or the file uri for non-versioned files)
|
60
|
+
def audit_file_version(file_id, version_uri)
|
61
|
+
latest_audit = ChecksumAuditLog.logs_for(generic_file.id, file_id).first
|
62
|
+
return latest_audit unless needs_audit?(latest_audit)
|
63
|
+
CurationConcerns.queue.push(AuditJob.new(generic_file.id, file_id, version_uri))
|
64
|
+
latest_audit || ChecksumAuditLog.new(pass: NO_RUNS, generic_file_id: generic_file.id, file_id: file_id, version: version_uri)
|
65
|
+
end
|
66
|
+
|
67
|
+
# Check if time since the last audit is greater than the maximum days allowed between audits
|
68
|
+
# @param [ChecksumAuditLog] latest_audit the most recent audit event
|
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) >= CurationConcerns.config.max_days_between_audits
|
76
|
+
end
|
77
|
+
|
78
|
+
# Return the number of days since the latest audit event
|
79
|
+
# @param [ChecksumAuditLog] latest_audit the most recent audit event
|
80
|
+
def days_since_last_audit(latest_audit)
|
81
|
+
(DateTime.now - latest_audit.updated_at.to_date).to_i
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module CurationConcerns
|
2
|
+
class GenericFileIndexingService < ActiveFedora::IndexingService
|
3
|
+
def generate_solr_document
|
4
|
+
super.tap do |solr_doc|
|
5
|
+
solr_doc[Solrizer.solr_name('label')] = object.label
|
6
|
+
solr_doc[Solrizer.solr_name('file_format')] = object.file_format
|
7
|
+
solr_doc[Solrizer.solr_name('file_format', :facetable)] = object.file_format
|
8
|
+
solr_doc[Solrizer.solr_name(:file_size, :symbol)] = object.file_size[0]
|
9
|
+
solr_doc['all_text_timv'] = object.full_text.content
|
10
|
+
solr_doc[Solrizer.solr_name('generic_work_ids', :symbol)] = object.generic_work_ids unless object.generic_work_ids.empty?
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module CurationConcerns
|
2
|
+
class GenericWorkIndexingService < ActiveFedora::IndexingService
|
3
|
+
|
4
|
+
def generate_solr_document
|
5
|
+
super.tap do |solr_doc|
|
6
|
+
# We know that all the members of GenericWorks are GenericFiles so we can use
|
7
|
+
# member_ids which requires fewer Fedora API calls than generic_file_ids.
|
8
|
+
# generic_file_ids requires loading all the members from Fedora but member_ids
|
9
|
+
# looks just at solr
|
10
|
+
solr_doc[Solrizer.solr_name('generic_file_ids', :symbol)] = object.member_ids
|
11
|
+
Solrizer.set_field(solr_doc, 'generic_type', 'Work', :facetable)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'active_fedora/noid'
|
2
|
+
|
3
|
+
module CurationConcerns
|
4
|
+
module Noid
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
## This overrides the default behavior, which is to ask Fedora for an id
|
8
|
+
# @see ActiveFedora::Persistence.assign_id
|
9
|
+
def assign_id
|
10
|
+
service.mint if CurationConcerns.config.enable_noids
|
11
|
+
end
|
12
|
+
|
13
|
+
def to_param
|
14
|
+
id
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def service
|
20
|
+
@service ||= ActiveFedora::Noid::Service.new
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module CurationConcerns
|
2
|
+
class VersioningService
|
3
|
+
# Make a version and record the version committer
|
4
|
+
# @param [ActiveFedora::File] content
|
5
|
+
# @param [User] user
|
6
|
+
def self.create(content, user=nil)
|
7
|
+
content.create_version
|
8
|
+
record_committer(content, user) if user
|
9
|
+
end
|
10
|
+
|
11
|
+
# @param [ActiveFedora::File] file
|
12
|
+
def self.latest_version_of(file)
|
13
|
+
file.versions.last
|
14
|
+
end
|
15
|
+
|
16
|
+
protected
|
17
|
+
|
18
|
+
# Record the version committer of the last version
|
19
|
+
# @param [ActiveFedora::File] content
|
20
|
+
# @param [User] user
|
21
|
+
def self.record_committer(content, user)
|
22
|
+
version = latest_version_of(content)
|
23
|
+
return if version.nil?
|
24
|
+
VersionCommitter.create(version_id: version.uri, committer_login: user.user_key)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
version = File.read(File.expand_path("../../VERSION", __FILE__)).strip
|
3
|
+
|
4
|
+
lib = File.expand_path('../lib', __FILE__)
|
5
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
6
|
+
|
7
|
+
Gem::Specification.new do |spec|
|
8
|
+
spec.name = "curation_concerns-models"
|
9
|
+
spec.version = version
|
10
|
+
spec.authors = ["Justin Coyne"]
|
11
|
+
spec.email = ["justin@curationexperts.com"]
|
12
|
+
spec.summary = %q{Simple institutional repository models for Hydra}
|
13
|
+
spec.description = %q{An extensible repository data-model with works and and many attached files}
|
14
|
+
spec.homepage = ""
|
15
|
+
spec.license = "APACHE2"
|
16
|
+
|
17
|
+
spec.files = `git ls-files -z`.split("\x0")
|
18
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
19
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
20
|
+
spec.require_paths = ["lib"]
|
21
|
+
|
22
|
+
spec.add_dependency 'active_attr'
|
23
|
+
spec.add_dependency 'nest', '~> 1.1'
|
24
|
+
spec.add_dependency 'hydra-collections', '~> 6.0.0.alpha'
|
25
|
+
spec.add_dependency 'hydra-head', '~> 9.2.2'
|
26
|
+
spec.add_dependency 'hydra-works', '~> 0.1'
|
27
|
+
spec.add_dependency 'active-fedora', '~> 9.3.0'
|
28
|
+
spec.add_dependency 'active_fedora-noid', '~> 1.0.2'
|
29
|
+
spec.add_dependency 'resque', '~> 1.23'
|
30
|
+
spec.add_dependency 'resque-pool', '~> 0.3'
|
31
|
+
|
32
|
+
spec.add_development_dependency 'bundler', '~> 1.6'
|
33
|
+
spec.add_development_dependency 'rake'
|
34
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module CurationConcerns
|
2
|
+
module Messages
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
# Borrowed from AbstractController so we can render html content tags
|
6
|
+
attr_accessor :output_buffer
|
7
|
+
include ActionView::Helpers::TagHelper
|
8
|
+
include ActionView::Helpers::UrlHelper
|
9
|
+
|
10
|
+
def success_subject
|
11
|
+
I18n.t("curation_concerns.messages.success.subject")
|
12
|
+
end
|
13
|
+
|
14
|
+
def failure_subject
|
15
|
+
I18n.t("curation_concerns.messages.failure.subject")
|
16
|
+
end
|
17
|
+
|
18
|
+
def single_success id, file
|
19
|
+
content_tag :span, id: "ss-"+id do
|
20
|
+
[link_to_file(file), I18n.t("curation_concerns.messages.success.single")].join(" ").html_safe
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def multiple_success id, files
|
25
|
+
content_tag :span, id: "ss-"+id do
|
26
|
+
[success_link(files), I18n.t("curation_concerns.messages.success.multiple.tag")].join(" ").html_safe
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def single_failure id, file
|
31
|
+
content_tag :span, id: "ss-"+id do
|
32
|
+
[link_to_file(file), I18n.t("curation_concerns.messages.failure.single")].join(" ").html_safe
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def multiple_failure id, files
|
37
|
+
content_tag :span, id: "ss-"+id do
|
38
|
+
[failure_link(files), I18n.t("curation_concerns.messages.failure.multiple.tag")].join(" ").html_safe
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# Double-quotes are replaced with single ones so this list can be included in a data block. Ex:
|
43
|
+
# <a href="#" data-content="<a href='#'>embedded link</a>" rel="popover">Click me</a>
|
44
|
+
def file_list files
|
45
|
+
files.map { |gf| link_to_file(gf) }.join(', ').gsub(/"/, "'")
|
46
|
+
end
|
47
|
+
|
48
|
+
def link_to_file file
|
49
|
+
link_to(file.to_s, Rails.application.class.routes.url_helpers.curation_concerns_generic_file_path(file))
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def success_link files
|
55
|
+
link_to I18n.t("curation_concerns.messages.success.multiple.link"), "#",
|
56
|
+
rel: "popover",
|
57
|
+
data: { content: file_list(files).html_safe, title: I18n.t("curation_concerns.messages.success.title") }
|
58
|
+
end
|
59
|
+
|
60
|
+
def failure_link files
|
61
|
+
link_to I18n.t("curation_concerns.messages.failure.multiple.link"), "#",
|
62
|
+
rel: "popover",
|
63
|
+
data: { content: file_list(files).html_safe, title: I18n.t("curation_concerns.messages.failure.title") }
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module CurationConcerns
|
2
|
+
module Models
|
3
|
+
|
4
|
+
def self.config(&block)
|
5
|
+
@@config ||= Engine::Configuration.new
|
6
|
+
yield @@config if block
|
7
|
+
return @@config
|
8
|
+
end
|
9
|
+
|
10
|
+
|
11
|
+
class Engine < ::Rails::Engine
|
12
|
+
|
13
|
+
require 'curation_concerns/models/resque'
|
14
|
+
|
15
|
+
# Set some configuration defaults
|
16
|
+
config.persistent_hostpath = "http://localhost/files/"
|
17
|
+
config.enable_ffmpeg = false
|
18
|
+
config.ffmpeg_path = 'ffmpeg'
|
19
|
+
config.fits_message_length = 5
|
20
|
+
config.temp_file_base = nil
|
21
|
+
config.enable_noids = true
|
22
|
+
config.noid_template = '.reeddeeddk'
|
23
|
+
config.minter_statefile = '/tmp/minter-state'
|
24
|
+
config.redis_namespace = "curation_concerns"
|
25
|
+
config.fits_path = "fits.sh"
|
26
|
+
config.enable_local_ingest = nil
|
27
|
+
config.queue = CurationConcerns::Resque::Queue
|
28
|
+
|
29
|
+
# Defaulting analytic start date to whenever the file was uploaded by leaving it blank
|
30
|
+
config.analytic_start_date = nil
|
31
|
+
|
32
|
+
config.autoload_paths += %W(
|
33
|
+
#{config.root}/app/actors/concerns
|
34
|
+
#{config.root}/lib/curation_concerns
|
35
|
+
#{config.root}/app/models/datastreams
|
36
|
+
)
|
37
|
+
|
38
|
+
initializer 'requires' do
|
39
|
+
require 'active_fedora/noid'
|
40
|
+
require 'curation_concerns/noid'
|
41
|
+
require 'curation_concerns/permissions'
|
42
|
+
end
|
43
|
+
|
44
|
+
initializer 'configure' do
|
45
|
+
CurationConcerns.config.tap do |c|
|
46
|
+
Hydra::Derivatives.ffmpeg_path = c.ffmpeg_path
|
47
|
+
Hydra::Derivatives.temp_file_base = c.temp_file_base
|
48
|
+
Hydra::Derivatives.fits_path = c.fits_path
|
49
|
+
Hydra::Derivatives.enable_ffmpeg = c.enable_ffmpeg
|
50
|
+
|
51
|
+
ActiveFedora::Base.translate_uri_to_id = ActiveFedora::Noid.config.translate_uri_to_id
|
52
|
+
ActiveFedora::Base.translate_id_to_uri = ActiveFedora::Noid.config.translate_id_to_uri
|
53
|
+
ActiveFedora::Noid.config.template = c.noid_template
|
54
|
+
ActiveFedora::Noid.config.statefile = c.minter_statefile
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# Borrowed from:
|
2
|
+
# https://github.com/jeremy/resque-rails/blob/master/lib/resque/rails/queue.rb
|
3
|
+
module CurationConcerns
|
4
|
+
module Resque
|
5
|
+
class Queue
|
6
|
+
attr_reader :default_queue_name
|
7
|
+
|
8
|
+
def initialize(default_queue_name)
|
9
|
+
@default_queue_name = default_queue_name
|
10
|
+
end
|
11
|
+
|
12
|
+
def push(job)
|
13
|
+
push_tries = 0
|
14
|
+
queue = job.respond_to?(:queue_name) ? job.queue_name : default_queue_name
|
15
|
+
begin
|
16
|
+
::Resque.enqueue_to queue, MarshaledJob, Base64.encode64(Marshal.dump(job))
|
17
|
+
rescue Redis::CannotConnectError
|
18
|
+
ActiveFedora::Base.logger.error "Redis is down!"
|
19
|
+
rescue Redis::TimeoutError => error
|
20
|
+
ActiveFedora::Base.logger.warn "Redis Timed out. Trying again! #{job.inspect}"
|
21
|
+
push_tries+=1
|
22
|
+
# fail for good if the tries is greater than 3
|
23
|
+
raise error if push_tries >=3
|
24
|
+
sleep 0.01
|
25
|
+
retry
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class MarshaledJob
|
31
|
+
def self.perform(marshaled_job)
|
32
|
+
Marshal.load(Base64.decode64(marshaled_job)).run
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module CurationConcerns
|
2
|
+
module Utils
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
def retry_unless(number_of_tries, condition, &block)
|
6
|
+
self.class.retry_unless(number_of_tries, condition, &block)
|
7
|
+
end
|
8
|
+
|
9
|
+
module ClassMethods
|
10
|
+
def retry_unless(number_of_tries, condition, &block)
|
11
|
+
raise ArgumentError, "First argument must be an enumerator" unless number_of_tries.is_a? Enumerator
|
12
|
+
raise ArgumentError, "Second argument must be a lambda" unless condition.respond_to? :call
|
13
|
+
raise ArgumentError, "Must pass a block of code to retry" unless block_given?
|
14
|
+
number_of_tries.each do
|
15
|
+
result = block.call
|
16
|
+
return result unless condition.call
|
17
|
+
end
|
18
|
+
raise RuntimeError, "retry_unless could not complete successfully. Try upping the # of tries?"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require "curation_concerns/models/version"
|
2
|
+
require "curation_concerns/models/engine"
|
3
|
+
|
4
|
+
require 'hydra/head'
|
5
|
+
require 'nest'
|
6
|
+
# require "active_resource" # used by GenericFile to catch errors & by GeoNamesResource
|
7
|
+
require 'resque/server'
|
8
|
+
|
9
|
+
module CurationConcerns
|
10
|
+
extend ActiveSupport::Autoload
|
11
|
+
|
12
|
+
module Models
|
13
|
+
end
|
14
|
+
|
15
|
+
autoload :Utils, 'curation_concerns/models/utils'
|
16
|
+
autoload :Permissions
|
17
|
+
autoload :Messages
|
18
|
+
|
19
|
+
attr_writer :queue
|
20
|
+
|
21
|
+
def self.queue
|
22
|
+
@queue ||= config.queue.new('curation_concerns')
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.config(&block)
|
26
|
+
@@config ||= CurationConcerns::Models::Engine::Configuration.new
|
27
|
+
|
28
|
+
yield @@config if block
|
29
|
+
|
30
|
+
return @@config
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
require 'rails/generators'
|
3
|
+
require 'rails/generators/migration'
|
4
|
+
|
5
|
+
class CurationConcerns::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
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
require 'rails/generators'
|
3
|
+
|
4
|
+
class CurationConcerns::Models::ClamavGenerator < Rails::Generators::Base
|
5
|
+
source_root File.expand_path('../templates', __FILE__)
|
6
|
+
|
7
|
+
desc """
|
8
|
+
This generator makes the following changes to your application:
|
9
|
+
1. Generates clamav initializer
|
10
|
+
"""
|
11
|
+
|
12
|
+
def banner
|
13
|
+
say_status("info", "Generating clamav initializers", :blue)
|
14
|
+
end
|
15
|
+
|
16
|
+
def create_initializer_file
|
17
|
+
copy_file 'config/clamav.rb', 'config/initializers/clamav.rb'
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
require 'rails/generators'
|
3
|
+
|
4
|
+
class CurationConcerns::Models::FulltextGenerator < Rails::Generators::Base
|
5
|
+
source_root File.expand_path('../templates', __FILE__)
|
6
|
+
|
7
|
+
desc """
|
8
|
+
This generator makes the following changes to your application:
|
9
|
+
1. Copies solrconfig.xml into solr_conf/conf/
|
10
|
+
2. Reconfigures jetty
|
11
|
+
"""
|
12
|
+
|
13
|
+
def banner
|
14
|
+
say_status("warning", "GENERATING CURATION_CONCERNS FULL-TEXT", :yellow)
|
15
|
+
end
|
16
|
+
|
17
|
+
# Copy CurationConcerns's solrconfig into the dir from which the jetty:config task pulls
|
18
|
+
# CurationConcerns's solrconfig includes full-text extraction
|
19
|
+
def copy_solr_config
|
20
|
+
src = File.join(__FILE__, '..', '..', '..', '..', '..', '..', 'solr_conf', 'conf', 'solrconfig.xml')
|
21
|
+
copy_file File.expand_path(src), 'solr_conf/conf/solrconfig.xml', force: true
|
22
|
+
end
|
23
|
+
|
24
|
+
# Copy config, schema, and jars into jetty dir if it exists
|
25
|
+
def reconfigure_jetty
|
26
|
+
rake "curation_concerns:jetty:config" if File.directory?('jetty')
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require_relative 'abstract_migration_generator'
|
2
|
+
|
3
|
+
class CurationConcerns::Models::InstallGenerator < CurationConcerns::Models::AbstractMigrationGenerator
|
4
|
+
source_root File.expand_path('../templates', __FILE__)
|
5
|
+
argument :model_name, type: :string , default: "user"
|
6
|
+
desc """
|
7
|
+
This generator makes the following changes to your application:
|
8
|
+
1. Creates several database migrations if they do not exist in /db/migrate
|
9
|
+
2. Creates the curation_concerns.rb configuration file and several others
|
10
|
+
3. Creates the generic_file.rb, generic_work.rb and collection.rb models
|
11
|
+
4. Runs full-text generator
|
12
|
+
"""
|
13
|
+
def banner
|
14
|
+
say_status("warning", "GENERATING CURATION_CONCERNS MODELS", :yellow)
|
15
|
+
end
|
16
|
+
|
17
|
+
# Setup the database migrations
|
18
|
+
def copy_migrations
|
19
|
+
[
|
20
|
+
"create_version_committers.rb",
|
21
|
+
"create_checksum_audit_logs.rb"#,
|
22
|
+
].each do |file|
|
23
|
+
better_migration_template file
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# Add behaviors to the user model
|
28
|
+
def inject_curation_concerns_user_behavior
|
29
|
+
file_path = "app/models/#{model_name.underscore}.rb"
|
30
|
+
if File.exists?(file_path)
|
31
|
+
inject_into_file file_path, after: /include Hydra\:\:User.*$/ do
|
32
|
+
"\n # Connects this user object to Curation Concerns behaviors." +
|
33
|
+
"\n include CurationConcerns::User\n"
|
34
|
+
end
|
35
|
+
else
|
36
|
+
puts " \e[31mFailure\e[0m CurationConcerns 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 curation_concerns client"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def create_configuration_files
|
41
|
+
append_file 'config/initializers/mime_types.rb',
|
42
|
+
"\nMime::Type.register 'application/x-endnote-refer', :endnote", {verbose: false }
|
43
|
+
copy_file 'config/curation_concerns.rb', 'config/initializers/curation_concerns.rb'
|
44
|
+
copy_file 'config/redis.yml', 'config/redis.yml'
|
45
|
+
copy_file 'config/resque-pool.yml', 'config/resque-pool.yml'
|
46
|
+
copy_file 'config/redis_config.rb', 'config/initializers/redis_config.rb'
|
47
|
+
copy_file 'config/resque_admin.rb', 'config/initializers/resque_admin.rb'
|
48
|
+
copy_file 'config/resque_config.rb', 'config/initializers/resque_config.rb'
|
49
|
+
end
|
50
|
+
|
51
|
+
def create_collection
|
52
|
+
copy_file 'app/models/collection.rb', 'app/models/collection.rb'
|
53
|
+
end
|
54
|
+
|
55
|
+
def create_generic_file
|
56
|
+
copy_file 'app/models/generic_file.rb', 'app/models/generic_file.rb'
|
57
|
+
end
|
58
|
+
|
59
|
+
# Sets up full-text indexing (Solr config + jars)
|
60
|
+
def full_text_indexing
|
61
|
+
generate "curation_concerns:models:fulltext"
|
62
|
+
end
|
63
|
+
|
64
|
+
# Adds clamav initializtion
|
65
|
+
def clamav
|
66
|
+
generate 'curation_concerns:models:clamav'
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
ClamAV.instance.loaddb() if defined? ClamAV
|