curation_concerns-models 0.8.0 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f40b99078f83355f035554d22016e711b0b0f379
4
- data.tar.gz: 79c5dd9cafdd3fa8da3f3407ccd3e9a1ea672a03
3
+ metadata.gz: 5660b6eec6ec27f6e8c00a1a9a001a0147a66fe6
4
+ data.tar.gz: e45350c36fd8061b4ef31871620eeeea5f450447
5
5
  SHA512:
6
- metadata.gz: f807e2358bf89d3af2ffb667fbd5740e389f202b4ff7d85e908065871f66072870b6d82c006407ad564e3b491b9b197f471c4434ed9e3d96b185bc398403110f
7
- data.tar.gz: 7cf972fb99dd8b58fb79ca6b4ccc12bcc8d60637aa0e50a5ace6178762644a7a110407ec8616b2344fab135ee90dfa9dca8a7c12f4e5f207aa095c62b8291b04
6
+ metadata.gz: 2c1ef86aa53fe09e26c1e800780c673b3499a50c01b528257683d3ee91baa2f8719e9dab83cd2e07a621b8f8b0ba90e7c407bf7188b434b4cbaf8144e2f0b950
7
+ data.tar.gz: c82db879f98a32b61da80ead6d519b3259cc4ca1ad696b2c313adb70d10854d79f1db9d9efe9643417c1a16fbe821b99392b8b7e7f3e074259dc7d8ec0f55d25
data/README.md CHANGED
@@ -16,6 +16,10 @@ To install FITS:
16
16
  * Adding the full fits.sh path to your PATH (e.g., in your .bash_profile), OR
17
17
  * Changing config/initializers/sufia.rb to point to your FITS location: config.fits_path = "/<your full path>/fits.sh"
18
18
 
19
+ ### Redis 2.6
20
+
21
+ The redlock gem requires Redis >= 2.6.
22
+
19
23
 
20
24
 
21
25
  ## Installation
@@ -0,0 +1,83 @@
1
+ module CurationConcerns
2
+ # actions for a file identified by file_set_id and relation (maps to use predicate)
3
+ class FileActor
4
+ attr_reader :file_set, :relation, :user
5
+
6
+ # @param [FileSet] file_set the parent FileSet
7
+ # @param [String] relation the type/use for the file.
8
+ # @param [User] user the user to record as the Agent acting upon the file
9
+ def initialize(file_set, relation, user)
10
+ @file_set = file_set
11
+ @relation = relation
12
+ @user = user
13
+ end
14
+
15
+ # Puts the uploaded content into a staging directory. Then kicks off a
16
+ # job to characterize and create derivatives with this on disk variant.
17
+ # Simultaneously moving a preservation copy to the repostiory.
18
+ # TODO: create a job to monitor this directory and prune old files that
19
+ # have made it to the repo
20
+ # @param [File, ActionDigest::HTTP::UploadedFile, Tempfile] file the file to save in the repository
21
+ def ingest_file(file)
22
+ working_file = copy_file_to_working_directory(file, file_set_id)
23
+ mime_type = file.respond_to?(:content_type) ? file.content_type : nil
24
+ IngestFileJob.perform_later(file_set_id, working_file, mime_type, user.user_key, relation)
25
+ make_derivative(file_set.id, working_file)
26
+ true
27
+ end
28
+
29
+ def revert_to(revision_id)
30
+ repository_file = file_set.send(relation.to_sym)
31
+ repository_file.restore_version(revision_id)
32
+
33
+ return false unless file_set.save
34
+
35
+ CurationConcerns::VersioningService.create(repository_file, user)
36
+
37
+ # Retrieve a copy of the orginal file from the repository
38
+ working_file = copy_repository_resource_to_working_directory(repository_file)
39
+ make_derivative(file_set_id, working_file)
40
+ true
41
+ end
42
+
43
+ private
44
+
45
+ def file_set_id
46
+ file_set.id
47
+ end
48
+
49
+ def make_derivative(file_set_id, working_file)
50
+ CharacterizeJob.perform_later(file_set_id, working_file)
51
+ end
52
+
53
+ # @param [File, ActionDispatch::Http::UploadedFile] file
54
+ # @param [String] id the identifer of the FileSet
55
+ # @return [String] path of the working file
56
+ def copy_file_to_working_directory(file, id)
57
+ file_name = file.respond_to?(:original_filename) ? file.original_filename : ::File.basename(file)
58
+ copy_stream_to_working_directory(id, file_name, file)
59
+ end
60
+
61
+ # @param [ActiveFedora::File] file the resource in the repo
62
+ # @return [String] path of the working file
63
+ def copy_repository_resource_to_working_directory(file)
64
+ copy_stream_to_working_directory(file_set_id, file.original_name, StringIO.new(file.content))
65
+ end
66
+
67
+ # @param [String] id the identifer
68
+ # @param [String] name the file name
69
+ # @param [#read] stream the stream to copy to the working directory
70
+ # @return [String] path of the working file
71
+ def copy_stream_to_working_directory(id, name, stream)
72
+ working_path = full_filename(id, name)
73
+ FileUtils.mkdir_p(File.dirname(working_path))
74
+ IO.copy_stream(stream, working_path)
75
+ working_path
76
+ end
77
+
78
+ def full_filename(id, original_name)
79
+ pair = id.scan(/..?/).first(4)
80
+ File.join(CurationConcerns.config.working_path, *pair, original_name)
81
+ end
82
+ end
83
+ end
@@ -35,46 +35,36 @@ module CurationConcerns
35
35
  yield(file_set) if block_given?
36
36
  end
37
37
 
38
- # Puts the uploaded content into a staging directory. Then kicks off a
39
- # job to characterize and create derivatives with this on disk variant.
40
- # Simultaneously moving a preservation copy to the repostiory.
41
- # TODO: create a job to monitor this directory and prune old files that
42
- # have made it to the repo
43
38
  # @param [File, ActionDigest::HTTP::UploadedFile, Tempfile] file the file uploaded by the user.
44
- def create_content(file)
45
- # Assign label and title of File Set is necessary.
39
+ # @param [String] relation ('original_file')
40
+ def create_content(file, relation = 'original_file')
41
+ # If the file set doesn't have a title or label assigned, set a default.
46
42
  file_set.label ||= file.respond_to?(:original_filename) ? file.original_filename : ::File.basename(file)
47
43
  file_set.title = [file_set.label] if file_set.title.blank?
48
44
 
49
45
  # Need to save the file_set in order to get an id
50
46
  return false unless file_set.save
51
47
 
52
- working_file = copy_file_to_working_directory(file, file_set.id)
53
- mime_type = file.respond_to?(:content_type) ? file.content_type : nil
54
- IngestFileJob.perform_later(file_set.id, working_file, mime_type, user.user_key)
55
- make_derivative(file_set.id, working_file)
48
+ FileActor.new(file_set, relation, user).ingest_file(file)
56
49
  true
57
50
  end
58
51
 
59
- def revert_content(revision_id)
60
- file_set.original_file.restore_version(revision_id)
61
-
62
- return false unless file_set.save
63
-
64
- CurationConcerns::VersioningService.create(file_set.original_file, user)
65
-
66
- # Retrieve a copy of the orginal file from the repository
67
- working_file = copy_repository_resource_to_working_directory(file_set)
68
- make_derivative(file_set.id, working_file)
69
-
70
- CurationConcerns.config.callback.run(:after_revert_content, file_set, user, revision_id)
71
- true
52
+ # @param [String] revision_id the revision to revert to
53
+ # @param [String] relation ('original_file')
54
+ def revert_content(revision_id, relation = 'original_file')
55
+ file_actor = FileActor.new(file_set, relation, user)
56
+ if file_actor.revert_to(revision_id)
57
+ CurationConcerns.config.callback.run(:after_revert_content, file_set, user, revision_id)
58
+ true
59
+ else
60
+ false
61
+ end
72
62
  end
73
63
 
74
- def update_content(file)
75
- working_file = copy_file_to_working_directory(file, file_set.id)
76
- IngestFileJob.perform_later(file_set.id, working_file, file.content_type, user.user_key)
77
- make_derivative(file_set.id, working_file)
64
+ # @param [File, ActionDigest::HTTP::UploadedFile, Tempfile] file the file uploaded by the user.
65
+ # @param [String] relation ('original_file')
66
+ def update_content(file, relation = 'original_file')
67
+ FileActor.new(file_set, relation, user).ingest_file(file)
78
68
  CurationConcerns.config.callback.run(:after_update_content, file_set, user)
79
69
  true
80
70
  end
@@ -96,42 +86,6 @@ module CurationConcerns
96
86
 
97
87
  private
98
88
 
99
- def make_derivative(file_set_id, working_file)
100
- CharacterizeJob.perform_later(file_set_id, working_file)
101
- end
102
-
103
- # @param [File, ActionDispatch::Http::UploadedFile] file
104
- # @param [String] id the identifer
105
- # @return [String] path of the working file
106
- def copy_file_to_working_directory(file, id)
107
- # file_set.label not gaurunteed to be set at this point (e.g. if called from update_content)
108
- file_set.label ||= file.respond_to?(:original_filename) ? file.original_filename : ::File.basename(file)
109
- copy_stream_to_working_directory(id, file_set.label, file)
110
- end
111
-
112
- # @param [FileSet] file_set the resource
113
- # @return [String] path of the working file
114
- def copy_repository_resource_to_working_directory(file_set)
115
- file = file_set.original_file
116
- copy_stream_to_working_directory(file_set.id, file.original_name, StringIO.new(file.content))
117
- end
118
-
119
- # @param [String] id the identifer
120
- # @param [String] name the file name
121
- # @param [#read] stream the stream to copy to the working directory
122
- # @return [String] path of the working file
123
- def copy_stream_to_working_directory(id, name, stream)
124
- working_path = full_filename(id, name)
125
- FileUtils.mkdir_p(File.dirname(working_path))
126
- IO.copy_stream(stream, working_path)
127
- working_path
128
- end
129
-
130
- def full_filename(id, original_name)
131
- pair = id.scan(/..?/).first(4)
132
- File.join(CurationConcerns.config.working_path, *pair, original_name)
133
- end
134
-
135
89
  # Takes an optional block and executes the block if the save was successful.
136
90
  # returns false if the save was unsuccessful
137
91
  def save
@@ -1,7 +1,12 @@
1
1
  class IngestFileJob < ActiveJob::Base
2
2
  queue_as :ingest
3
3
 
4
- def perform(file_set_id, filename, mime_type, user_key)
4
+ # @param [String] file_set_id
5
+ # @param [String] filename
6
+ # @param [String,NilClass] mime_type
7
+ # @param [String] user_key
8
+ # @param [String] relation ('original_file')
9
+ def perform(file_set_id, filename, mime_type, user_key, relation = 'original_file')
5
10
  file_set = FileSet.find(file_set_id)
6
11
 
7
12
  file = File.open(filename, "rb")
@@ -14,14 +19,14 @@ class IngestFileJob < ActiveJob::Base
14
19
  end
15
20
 
16
21
  # Tell AddFileToFileSet service to skip versioning because versions will be minted by VersionCommitter (called by save_characterize_and_record_committer) when necessary
17
- Hydra::Works::AddFileToFileSet.call(file_set, file, :original_file, versioning: false)
22
+ Hydra::Works::AddFileToFileSet.call(file_set, file, relation.to_sym, versioning: false)
18
23
 
19
24
  # Persist changes to the file_set
20
25
  file_set.save!
21
26
 
22
27
  # Do post file ingest actions
23
28
  user = User.find_by_user_key(user_key)
24
- CurationConcerns::VersioningService.create(file_set.original_file, user)
29
+ CurationConcerns::VersioningService.create(file_set.send(relation.to_sym), user)
25
30
  CurationConcerns.config.callback.run(:after_create_content, file_set, user)
26
31
  end
27
32
  end
@@ -38,20 +38,6 @@ module CurationConcerns
38
38
  index.as :stored_searchable
39
39
  end
40
40
 
41
- # We reserve date_uploaded for the original creation date of the record.
42
- # For example, when migrating data from a fedora3 repo to fedora4,
43
- # fedora's system created date will reflect the date when the record
44
- # was created in fedora4, but the date_uploaded will preserve the
45
- # original creation date from the old repository.
46
- property :date_uploaded, predicate: ::RDF::Vocab::DC.dateSubmitted, multiple: false do |index|
47
- index.type :date
48
- index.as :stored_sortable
49
- end
50
-
51
- property :date_modified, predicate: ::RDF::Vocab::DC.modified, multiple: false do |index|
52
- index.type :date
53
- index.as :stored_sortable
54
- end
55
41
  property :subject, predicate: ::RDF::Vocab::DC.subject do |index|
56
42
  index.as :stored_searchable, :facetable
57
43
  end
@@ -10,7 +10,7 @@ module CurationConcerns
10
10
  include CurationConcerns::Permissions
11
11
 
12
12
  included do
13
- validates :title, presence: true
13
+ validates_with HasOneTitleValidator
14
14
  end
15
15
 
16
16
  def to_s
@@ -6,9 +6,25 @@ module CurationConcerns
6
6
  property :depositor, predicate: ::RDF::URI.new('http://id.loc.gov/vocabulary/relators/dpt'), multiple: false do |index|
7
7
  index.as :symbol, :stored_searchable
8
8
  end
9
+
9
10
  property :title, predicate: ::RDF::Vocab::DC.title do |index|
10
11
  index.as :stored_searchable, :facetable
11
12
  end
13
+
14
+ # We reserve date_uploaded for the original creation date of the record.
15
+ # For example, when migrating data from a fedora3 repo to fedora4,
16
+ # fedora's system created date will reflect the date when the record
17
+ # was created in fedora4, but the date_uploaded will preserve the
18
+ # original creation date from the old repository.
19
+ property :date_uploaded, predicate: ::RDF::Vocab::DC.dateSubmitted, multiple: false do |index|
20
+ index.type :date
21
+ index.as :stored_sortable
22
+ end
23
+
24
+ property :date_modified, predicate: ::RDF::Vocab::DC.modified, multiple: false do |index|
25
+ index.type :date
26
+ index.as :stored_sortable
27
+ end
12
28
  end
13
29
  end
14
30
  end
@@ -0,0 +1,8 @@
1
+ # validates that the title has at least one title
2
+ class HasOneTitleValidator < ActiveModel::Validator
3
+ def validate(record)
4
+ if record.title.reject(&:empty?).empty?
5
+ record.errors[:title] << "You must provide a title"
6
+ end
7
+ end
8
+ end
@@ -20,7 +20,7 @@ Gem::Specification.new do |spec|
20
20
  spec.require_paths = ["lib"]
21
21
 
22
22
  spec.add_dependency 'active_attr'
23
- spec.add_dependency 'hydra-collections', '~> 7.0'
23
+ spec.add_dependency 'hydra-collections', '~> 8.0'
24
24
  spec.add_dependency 'hydra-head', '~> 9.3'
25
25
  spec.add_dependency 'hydra-works', '~> 0.7'
26
26
  spec.add_dependency 'active_fedora-noid', '~> 1.0'
@@ -56,11 +56,24 @@ module CurationConcerns
56
56
  @fits_message_length ||= 5
57
57
  end
58
58
 
59
- attr_accessor :temp_file_base, :enable_local_ingest, :analytic_start_date,
60
- :fits_to_desc_mapping, :max_days_between_audits,
61
- :resource_types, :resource_types_to_schema,
62
- :permission_levels, :owner_permission_levels, :analytics,
63
- :display_microdata, :microdata_default_type
59
+ attr_accessor :temp_file_base, :enable_local_ingest,
60
+ :analytics, :analytic_start_date
61
+
62
+ attr_writer :display_microdata
63
+ def display_microdata
64
+ return @display_microdata unless @display_microdata.nil?
65
+ @display_microdata = true
66
+ end
67
+
68
+ attr_writer :microdata_default_type
69
+ def microdata_default_type
70
+ @microdata_default_type ||= 'http://schema.org/CreativeWork'
71
+ end
72
+
73
+ attr_writer :max_days_between_audits
74
+ def max_days_between_audits
75
+ @max_days_between_audits ||= 7
76
+ end
64
77
 
65
78
  attr_writer :enable_noids
66
79
  def enable_noids
@@ -4,7 +4,6 @@ module CurationConcerns
4
4
  config.autoload_paths += %W(
5
5
  #{config.root}/app/actors/concerns
6
6
  #{config.root}/lib/curation_concerns
7
- #{config.root}/app/models/datastreams
8
7
  )
9
8
 
10
9
  initializer 'requires' do
@@ -1,5 +1,5 @@
1
1
  module CurationConcerns
2
2
  module Models
3
- VERSION = "0.8.0".freeze
3
+ VERSION = "0.9.0".freeze
4
4
  end
5
5
  end
@@ -1,55 +1,18 @@
1
1
  CurationConcerns.configure do |config|
2
- config.fits_to_desc_mapping = {
3
- file_title: :title,
4
- file_author: :creator
5
- }
6
-
7
- config.max_days_between_audits = 7
8
-
9
- config.resource_types = {
10
- 'Article' => 'Article',
11
- 'Audio' => 'Audio',
12
- 'Book' => 'Book',
13
- 'Capstone Project' => 'Capstone Project',
14
- 'Conference Proceeding' => 'Conference Proceeding',
15
- 'Dataset' => 'Dataset',
16
- 'Dissertation' => 'Dissertation',
17
- 'Image' => 'Image',
18
- 'Journal' => 'Journal',
19
- 'Map or Cartographic Material' => 'Map or Cartographic Material',
20
- 'Masters Thesis' => 'Masters Thesis',
21
- 'Part of Book' => 'Part of Book',
22
- 'Poster' => 'Poster',
23
- 'Presentation' => 'Presentation',
24
- 'Project' => 'Project',
25
- 'Report' => 'Report',
26
- 'Research Paper' => 'Research Paper',
27
- 'Software or Program Code' => 'Software or Program Code',
28
- 'Video' => 'Video',
29
- 'Other' => 'Other'
30
- }
31
-
32
- config.display_microdata = true
33
- config.microdata_default_type = 'http://schema.org/CreativeWork'
34
-
35
- config.resource_types_to_schema = config.resource_types.map do |k, v|
36
- [k, I18n.t("curation_concerns.schema_org.resource_type.#{v}", default: config.microdata_default_type)]
37
- end.to_h
38
-
39
- config.permission_levels = {
40
- 'Choose Access' => 'none',
41
- 'View/Download' => 'read',
42
- 'Edit' => 'edit'
43
- }
44
-
45
- config.owner_permission_levels = {
46
- 'Edit' => 'edit'
47
- }
2
+ # Should schema.org microdata be displayed?
3
+ # config.display_microdata = true
4
+
5
+ # What default microdata type should be used if a more appropriate
6
+ # type can not be found in the locale file?
7
+ # config.microdata_default_type = 'http://schema.org/CreativeWork'
8
+
9
+ # How frequently should a file be audited.
10
+ # Note: In CurationConcerns you must trigger the FileSetAuditService manually.
11
+ # config.max_days_between_audits = 7
48
12
 
49
13
  # Enable displaying usage statistics in the UI
50
- # Defaults to FALSE
51
14
  # Requires a Google Analytics id and OAuth2 keyfile. See README for more info
52
- config.analytics = false
15
+ # config.analytics = false
53
16
 
54
17
  # Specify a Google Analytics tracking ID to gather usage statistics
55
18
  # config.google_analytics_id = 'UA-99999999-1'
@@ -60,12 +23,15 @@ CurationConcerns.configure do |config|
60
23
  # Where to store tempfiles, leave blank for the system temp directory (e.g. /tmp)
61
24
  # config.temp_file_base = '/home/developer1'
62
25
 
63
- # Specify the form of hostpath to be used in Endnote exports
64
- # config.persistent_hostpath = 'http://localhost/files/'
65
-
66
26
  # Location on local file system where derivatives will be stored.
27
+ # If you use a multi-server architecture, this MUST be a shared volume.
67
28
  # config.derivatives_path = File.join(Rails.root, 'tmp', 'derivatives')
68
29
 
30
+ # Location on local file system where uploaded files will be staged
31
+ # prior to being ingested into the repository or having derivatives generated.
32
+ # If you use a multi-server architecture, this MUST be a shared volume.
33
+ # config.working_path = File.join(Rails.root, 'tmp', 'uploads')
34
+
69
35
  # If you have ffmpeg installed and want to transcode audio and video uncomment this line
70
36
  # config.enable_ffmpeg = true
71
37
 
@@ -77,6 +43,7 @@ CurationConcerns.configure do |config|
77
43
  # config.noid_template = ".reeddeeddk"
78
44
 
79
45
  # Store identifier minter's state in a file for later replayability
46
+ # If you use a multi-server architecture, this MUST be on a shared volume.
80
47
  # config.minter_statefile = '/tmp/minter-state'
81
48
 
82
49
  # Specify the prefix for Redis keys:
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: curation_concerns-models
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.0
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Justin Coyne
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-02-16 00:00:00.000000000 Z
11
+ date: 2016-02-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: active_attr
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '7.0'
33
+ version: '8.0'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '7.0'
40
+ version: '8.0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: hydra-head
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -180,6 +180,7 @@ files:
180
180
  - app/actors/concerns/curation_concerns/manages_embargoes_actor.rb
181
181
  - app/actors/curation_concerns/base_actor.rb
182
182
  - app/actors/curation_concerns/embargo_actor.rb
183
+ - app/actors/curation_concerns/file_actor.rb
183
184
  - app/actors/curation_concerns/file_set_actor.rb
184
185
  - app/actors/curation_concerns/lease_actor.rb
185
186
  - app/actors/curation_concerns/work_actor_behavior.rb
@@ -203,7 +204,6 @@ files:
203
204
  - app/models/concerns/curation_concerns/file_set/full_text_indexing.rb
204
205
  - app/models/concerns/curation_concerns/file_set/indexing.rb
205
206
  - app/models/concerns/curation_concerns/file_set/querying.rb
206
- - app/models/concerns/curation_concerns/file_set/versions.rb
207
207
  - app/models/concerns/curation_concerns/file_set_behavior.rb
208
208
  - app/models/concerns/curation_concerns/has_representative.rb
209
209
  - app/models/concerns/curation_concerns/human_readable_type.rb
@@ -234,6 +234,7 @@ files:
234
234
  - app/services/curation_concerns/thumbnail_path_service.rb
235
235
  - app/services/curation_concerns/time_service.rb
236
236
  - app/services/curation_concerns/versioning_service.rb
237
+ - app/validators/has_one_title_validator.rb
237
238
  - config/locales/curation_concerns.en.yml
238
239
  - curation_concerns-models.gemspec
239
240
  - lib/curation_concerns/configuration.rb
@@ -282,7 +283,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
282
283
  version: '0'
283
284
  requirements: []
284
285
  rubyforge_project:
285
- rubygems_version: 2.4.5.1
286
+ rubygems_version: 2.5.1
286
287
  signing_key:
287
288
  specification_version: 4
288
289
  summary: Simple institutional repository models for Hydra
@@ -1,15 +0,0 @@
1
- module CurationConcerns
2
- module FileSet
3
- module Versions
4
- @@count = 0
5
- def record_version_committer(user)
6
- version = latest_version
7
- # content datastream not (yet?) present
8
- return if version.nil?
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
- end
13
- end
14
- end
15
- end