ddr-models 2.3.2 → 2.4.0.rc1

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.
Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +2 -3
  3. data/ddr-models.gemspec +1 -1
  4. data/lib/ddr/auth.rb +10 -6
  5. data/lib/ddr/auth/group.rb +2 -1
  6. data/lib/ddr/auth/grouper_gateway.rb +7 -6
  7. data/lib/ddr/auth/permissions.rb +2 -1
  8. data/lib/ddr/auth/roles.rb +3 -2
  9. data/lib/ddr/auth/roles/role_set.rb +3 -2
  10. data/lib/ddr/datastreams/administrative_metadata_datastream.rb +3 -0
  11. data/lib/ddr/derivatives/png_generator.rb +1 -1
  12. data/lib/ddr/index/fields.rb +11 -1
  13. data/lib/ddr/index/filter.rb +4 -3
  14. data/lib/ddr/index/legacy_license_fields.rb +0 -2
  15. data/lib/ddr/index/query_clause.rb +2 -2
  16. data/lib/ddr/index/query_value.rb +6 -3
  17. data/lib/ddr/jobs.rb +5 -1
  18. data/lib/ddr/jobs/fits_file_characterization.rb +2 -40
  19. data/lib/ddr/jobs/fixity_check.rb +13 -0
  20. data/lib/ddr/jobs/job.rb +36 -0
  21. data/lib/ddr/jobs/queue.rb +27 -0
  22. data/lib/ddr/jobs/update_index.rb +13 -0
  23. data/lib/ddr/managers/derivatives_manager.rb +21 -17
  24. data/lib/ddr/models.rb +14 -2
  25. data/lib/ddr/models/access_controllable.rb +3 -6
  26. data/lib/ddr/models/admin_set.rb +5 -3
  27. data/lib/ddr/models/base.rb +2 -3
  28. data/lib/ddr/models/contact.rb +17 -0
  29. data/lib/ddr/models/file_characterization.rb +37 -0
  30. data/lib/ddr/models/has_admin_metadata.rb +2 -1
  31. data/lib/ddr/models/has_content.rb +4 -2
  32. data/lib/ddr/models/indexing.rb +5 -0
  33. data/lib/ddr/models/licenses/license.rb +5 -3
  34. data/lib/ddr/models/solr_document.rb +1 -1
  35. data/lib/ddr/models/version.rb +1 -1
  36. data/lib/ddr/models/with_content_file.rb +37 -0
  37. data/lib/ddr/vocab/asset.rb +3 -0
  38. data/spec/derivatives/png_generator_spec.rb +7 -0
  39. data/spec/factories/test_model_factories.rb +1 -1
  40. data/spec/fixtures/arrow1rightred_e0.gif +0 -0
  41. data/spec/fixtures/bird.jpg +0 -0
  42. data/spec/index/query_value_spec.rb +33 -0
  43. data/spec/jobs/fits_file_characterization_spec.rb +8 -44
  44. data/spec/jobs/fixity_check_spec.rb +22 -0
  45. data/spec/jobs/job_spec.rb +40 -0
  46. data/spec/jobs/update_index_spec.rb +22 -0
  47. data/spec/managers/derivatives_manager_spec.rb +16 -12
  48. data/spec/models/admin_set_spec.rb +3 -3
  49. data/spec/models/contact_spec.rb +22 -0
  50. data/spec/models/effective_license_spec.rb +17 -7
  51. data/spec/models/file_characterization_spec.rb +39 -0
  52. data/spec/models/has_admin_metadata_spec.rb +8 -5
  53. data/spec/models/indexing_spec.rb +2 -0
  54. data/spec/models/license_spec.rb +3 -1
  55. data/spec/models/solr_document_spec.rb +6 -3
  56. data/spec/models/with_content_file_spec.rb +37 -0
  57. data/spec/spec_helper.rb +2 -0
  58. metadata +43 -30
  59. data/lib/ddr/contacts.rb +0 -25
  60. data/lib/ddr/index_fields.rb +0 -14
  61. data/spec/auth/ldap_gateway_spec.rb +0 -9
  62. data/spec/contacts/contacts_spec.rb +0 -26
@@ -51,23 +51,27 @@ module Ddr
51
51
  end
52
52
 
53
53
  def generate_derivative!(derivative)
54
- tempdir = FileUtils.mkdir(File.join(Dir.tmpdir, Dir::Tmpname.make_tmpname('',nil))).first
55
- generator_source = create_source_file(tempdir)
56
- generator_output = File.new(File.join(tempdir, "output.out"), 'wb')
57
- results = derivative.generator.new(generator_source.path, generator_output.path, derivative.options).generate
58
- generator_source.close unless generator_source.closed?
59
- if results.status.success?
60
- generator_output = File.open(generator_output, 'rb')
61
- object.reload if object.persisted?
62
- object.add_file generator_output, derivative.datastream, mime_type: derivative.generator.output_mime_type
63
- object.save!
64
- else
65
- Rails.logger.error results.stderr
66
- raise Ddr::Models::DerivativeGenerationFailure,
67
- "Failure generating #{derivative.name} for #{object.pid}: #{results.stderr}"
54
+ tempdir_path = File.join(Dir.tmpdir, Dir::Tmpname.make_tmpname('',nil))
55
+ begin
56
+ tempdir = FileUtils.mkdir(tempdir_path).first
57
+ generator_source = create_source_file(tempdir)
58
+ generator_output = File.new(File.join(tempdir, "output.out"), 'wb')
59
+ results = derivative.generator.new(generator_source.path, generator_output.path, derivative.options).generate
60
+ generator_source.close unless generator_source.closed?
61
+ if results.status.success?
62
+ generator_output = File.open(generator_output, 'rb')
63
+ object.reload if object.persisted?
64
+ object.add_file generator_output, derivative.datastream, mime_type: derivative.generator.output_mime_type
65
+ object.save!
66
+ else
67
+ Rails.logger.error results.stderr
68
+ raise Ddr::Models::DerivativeGenerationFailure,
69
+ "Failure generating #{derivative.name} for #{object.pid}: #{results.stderr}"
70
+ end
71
+ generator_output.close unless generator_output.closed?
72
+ ensure
73
+ FileUtils.remove_dir(tempdir_path) if File.exist?(tempdir_path)
68
74
  end
69
- generator_output.close unless generator_output.closed?
70
- FileUtils.remove_dir(tempdir)
71
75
  end
72
76
 
73
77
  def delete_derivative(derivative)
@@ -110,7 +114,7 @@ module Ddr
110
114
  when :multires_image
111
115
  object.content_type == "image/tiff"
112
116
  when :thumbnail
113
- object.image? || object.pdf?
117
+ object.image?
114
118
  else
115
119
  false
116
120
  end
@@ -11,15 +11,14 @@ require 'hydra/validations'
11
11
 
12
12
  module Ddr
13
13
  extend ActiveSupport::Autoload
14
+ extend Deprecation
14
15
 
15
16
  autoload :Actions
16
17
  autoload :Auth
17
- autoload :Contacts
18
18
  autoload :Datastreams
19
19
  autoload :Derivatives
20
20
  autoload :Events
21
21
  autoload :Index
22
- autoload :IndexFields
23
22
  autoload :Jobs
24
23
  autoload :Managers
25
24
  autoload :Metadata
@@ -27,6 +26,16 @@ module Ddr
27
26
  autoload :Utils
28
27
  autoload :Vocab
29
28
 
29
+ def self.const_missing(name)
30
+ if name == :IndexFields
31
+ Deprecation.warn(Ddr::Models, "`Ddr::IndexFields` is deprecated and will be removed in ddr-models 3.0." \
32
+ " Use `Ddr::Index::Fields` instead.")
33
+ Index::Fields
34
+ else
35
+ super
36
+ end
37
+ end
38
+
30
39
  module Models
31
40
  extend ActiveSupport::Autoload
32
41
 
@@ -34,11 +43,13 @@ module Ddr
34
43
  autoload :AdminSet
35
44
  autoload :Base
36
45
  autoload :ChecksumInvalid, 'ddr/models/error'
46
+ autoload :Contact
37
47
  autoload :ContentModelError, 'ddr/models/error'
38
48
  autoload :DerivativeGenerationFailure, 'ddr/models/error'
39
49
  autoload :Describable
40
50
  autoload :Error
41
51
  autoload :EventLoggable
52
+ autoload :FileCharacterization
42
53
  autoload :FileManagement
43
54
  autoload :FindingAid
44
55
  autoload :FixityCheckable
@@ -54,6 +65,7 @@ module Ddr
54
65
  autoload :SolrDocument
55
66
  autoload :StructDiv
56
67
  autoload :Structure
68
+ autoload :WithContentFile
57
69
  autoload :YearFacet
58
70
 
59
71
  autoload_under "licenses" do
@@ -2,26 +2,23 @@ module Ddr
2
2
  module Models
3
3
  module AccessControllable
4
4
  extend ActiveSupport::Concern
5
+ extend Deprecation
5
6
 
6
7
  included do
7
8
  include Hydra::AccessControls::Permissions
8
9
  end
9
10
 
10
11
  def set_initial_permissions(user_creator = nil)
11
- warn "[DEPRECATION] `set_initial_permissions` is deprecated" \
12
- " and should not be used with role-based access control" \
13
- " (#{caller.first})."
14
12
  if user_creator
15
13
  self.permissions_attributes = [{type: "user", access: "edit", name: user_creator.to_s}]
16
14
  end
17
15
  end
16
+ deprecation_deprecate :set_initial_permissions
18
17
 
19
18
  def copy_permissions_from(other)
20
- warn "[DEPRECATION] `copy_permissions_from` is deprecated" \
21
- " and should not be used with role-based access control" \
22
- " (#{caller.first})."
23
19
  self.permissions_attributes = other.permissions.collect { |p| p.to_hash }
24
20
  end
21
+ deprecation_deprecate :copy_permissions_from
25
22
  end
26
23
  end
27
24
  end
@@ -1,11 +1,13 @@
1
- require "ddr_aux/client"
1
+ require "active_resource"
2
2
 
3
3
  module Ddr::Models
4
- class AdminSet < DdrAux::Client::AdminSet
4
+ class AdminSet < ActiveResource::Base
5
+
6
+ self.site = ENV["DDR_AUX_API_URL"]
5
7
 
6
8
  def self.call(obj)
7
9
  if obj.admin_set
8
- find(code: obj.admin_set)
10
+ get(:find, code: obj.admin_set)
9
11
  end
10
12
  end
11
13
 
@@ -22,9 +22,8 @@ module Ddr
22
22
  end
23
23
 
24
24
  def copy_admin_policy_or_permissions_from(other)
25
- warn "[DEPRECATION] `copy_admin_policy_or_permissions_from` is deprecated." \
26
- " Use `copy_admin_policy_or_roles_from` instead." \
27
- " (#{caller.first})."
25
+ Deprecation.warn(self.class, "`copy_admin_policy_or_permissions_from` is deprecated." \
26
+ " Use `copy_admin_policy_or_roles_from` instead.")
28
27
  copy_admin_policy_or_roles_from(other)
29
28
  end
30
29
 
@@ -0,0 +1,17 @@
1
+ require "active_resource"
2
+
3
+ module Ddr::Models
4
+ class Contact < ActiveResource::Base
5
+
6
+ self.site = ENV["DDR_AUX_API_URL"]
7
+
8
+ def self.call(slug)
9
+ get(:find, slug: slug)
10
+ end
11
+
12
+ def to_s
13
+ name
14
+ end
15
+
16
+ end
17
+ end
@@ -0,0 +1,37 @@
1
+ require "delegate"
2
+ require "shellwords"
3
+
4
+ module Ddr::Models
5
+ class FileCharacterization < SimpleDelegator
6
+
7
+ class FITSError < Error; end
8
+
9
+ def self.call(obj)
10
+ new(obj).call
11
+ end
12
+
13
+ def call
14
+ with_content_file do |path|
15
+ fits_output = run_fits(path)
16
+ reload
17
+ fits.content = fits_output
18
+ save!
19
+ end
20
+ end
21
+
22
+ private
23
+
24
+ def run_fits(path)
25
+ output = `#{fits_command} -i #{Shellwords.escape(path)}`
26
+ unless $?.success?
27
+ raise FITSError, output
28
+ end
29
+ output
30
+ end
31
+
32
+ def fits_command
33
+ File.join(Ddr::Models.fits_home, 'fits.sh')
34
+ end
35
+
36
+ end
37
+ end
@@ -20,6 +20,7 @@ module Ddr::Models
20
20
  :research_help_contact,
21
21
  :workflow_state,
22
22
  :ead_id,
23
+ :aspace_id,
23
24
  datastream: "adminMetadata",
24
25
  multiple: false
25
26
 
@@ -64,7 +65,7 @@ module Ddr::Models
64
65
  end
65
66
 
66
67
  def research_help
67
- Ddr::Contacts.get(research_help_contact) if research_help_contact
68
+ Ddr::Models::Contact.call(research_help_contact) if research_help_contact
68
69
  end
69
70
 
70
71
  def effective_license
@@ -1,5 +1,3 @@
1
- require 'openssl'
2
-
3
1
  module Ddr
4
2
  module Models
5
3
  module HasContent
@@ -128,6 +126,10 @@ module Ddr
128
126
  extractedText.has_content?
129
127
  end
130
128
 
129
+ def with_content_file(&block)
130
+ WithContentFile.new(self, &block)
131
+ end
132
+
131
133
  protected
132
134
 
133
135
  def update_derivatives
@@ -4,6 +4,10 @@ module Ddr
4
4
 
5
5
  include Ddr::Index::Fields
6
6
 
7
+ def self.const_missing(name)
8
+ Ddr::Index::Fields.const_missing(name)
9
+ end
10
+
7
11
  def to_solr(solr_doc=Hash.new, opts={})
8
12
  solr_doc = super(solr_doc, opts)
9
13
  solr_doc.merge index_fields
@@ -13,6 +17,7 @@ module Ddr
13
17
  fields = {
14
18
  ACCESS_ROLE => roles.to_json,
15
19
  ADMIN_SET => admin_set,
20
+ ASPACE_ID => aspace_id,
16
21
  BOX_NUMBER_FACET => desc_metadata_values('box_number'),
17
22
  CREATOR_FACET => creator,
18
23
  DATE_FACET => date,
@@ -1,13 +1,15 @@
1
- require "ddr_aux/client"
1
+ require "active_resource"
2
2
 
3
3
  module Ddr::Models
4
- class License < DdrAux::Client::License
4
+ class License < ActiveResource::Base
5
+
6
+ self.site = ENV["DDR_AUX_API_URL"]
5
7
 
6
8
  attr_accessor :pid
7
9
 
8
10
  def self.call(obj)
9
11
  if obj.license
10
- license = find(url: obj.license)
12
+ license = get(:find, url: obj.license)
11
13
  license.pid = obj.pid
12
14
  license
13
15
  end
@@ -189,7 +189,7 @@ module Ddr::Models
189
189
 
190
190
  def research_help
191
191
  research_help_contact = self[Ddr::Index::Fields::RESEARCH_HELP_CONTACT] || inherited_research_help_contact
192
- Ddr::Contacts.get(research_help_contact) if research_help_contact
192
+ Ddr::Models::Contact.call(research_help_contact) if research_help_contact
193
193
  end
194
194
 
195
195
  def parent_uri
@@ -1,5 +1,5 @@
1
1
  module Ddr
2
2
  module Models
3
- VERSION = "2.3.2"
3
+ VERSION = "2.4.0.rc1"
4
4
  end
5
5
  end
@@ -0,0 +1,37 @@
1
+ require "tempfile"
2
+ require "delegate"
3
+
4
+ module Ddr::Models
5
+ class WithContentFile < SimpleDelegator
6
+
7
+ def initialize(obj, &block)
8
+ super(obj)
9
+ with_temp_file &block
10
+ end
11
+
12
+ # Yields path of tempfile containing content to block
13
+ # @yield [String] the path to the tempfile containing content
14
+ def with_temp_file
15
+ filename = original_filename || content.default_file_name
16
+ basename = [ File.basename(filename, ".*"), File.extname(filename) ]
17
+ infile = Tempfile.open(basename, Ddr::Models.tempdir, encoding: 'ascii-8bit')
18
+ begin
19
+ infile.write(content.content)
20
+ infile.close
21
+ verify_checksum!(infile)
22
+ yield infile.path
23
+ ensure
24
+ infile.close unless infile.closed?
25
+ File.unlink(infile)
26
+ end
27
+ end
28
+
29
+ def verify_checksum!(file)
30
+ digest = Ddr::Utils.digest(File.read(file), content.checksumType)
31
+ if digest != content.checksum
32
+ raise ChecksumInvalid, "The checksum of the downloaded file does not match the stored checksum of the content."
33
+ end
34
+ end
35
+
36
+ end
37
+ end
@@ -18,6 +18,9 @@
18
18
  property "eadId",
19
19
  label: "EAD ID"
20
20
 
21
+ property "archivesSpaceId",
22
+ label: "ArchivesSpace Identifier"
23
+
21
24
  end
22
25
  end
23
26
  end
@@ -17,6 +17,13 @@ module Ddr
17
17
  expect(File.size(output_file.path)).to be > 0
18
18
  end
19
19
  end
20
+ context "animated gif source" do
21
+ let(:source) { File.join(Ddr::Models::Engine.root, "spec", "fixtures", "arrow1rightred_e0.gif") }
22
+ it "should generate a non-empty file" do
23
+ generator.generate
24
+ expect(File.size(output_file.path)).to be > 0
25
+ end
26
+ end
20
27
  end
21
28
 
22
29
  end
@@ -34,7 +34,7 @@ FactoryGirl.define do
34
34
  sequence(:identifier) { |n| [ "testparent%05d" % n ] }
35
35
 
36
36
  factory :test_parent_has_children do
37
- ignore do
37
+ transient do
38
38
  child_count 3
39
39
  end
40
40
  after(:create) do |parent, evaluator|
Binary file
@@ -0,0 +1,33 @@
1
+ module Ddr::Index
2
+ RSpec.describe QueryValue do
3
+
4
+ describe ".or_values" do
5
+ describe "when argument is nil" do
6
+ it "raises an exception" do
7
+ expect { described_class.or_values(nil) }.to raise_error(ArgumentError)
8
+ end
9
+ end
10
+ describe "when argument is empty" do
11
+ it "raises an exception" do
12
+ expect { described_class.or_values([]) }.to raise_error(ArgumentError)
13
+ end
14
+ end
15
+ describe "when argument is not enumerable" do
16
+ it "raises an exception" do
17
+ expect { described_class.or_values("foo") }.to raise_error(ArgumentError)
18
+ end
19
+ end
20
+ describe "when argument size == 1" do
21
+ it "returns the first value, escaped" do
22
+ expect(described_class.or_values(["foo:bar"])).to eq("(foo\\:bar)")
23
+ end
24
+ end
25
+ describe "when argument size > 1" do
26
+ it "return the escaped values OR'd together in parentheses" do
27
+ expect(described_class.or_values(["foo:bar", "spam:eggs"])).to eq("(foo\\:bar OR spam\\:eggs)")
28
+ end
29
+ end
30
+ end
31
+
32
+ end
33
+ end
@@ -3,50 +3,14 @@ require 'spec_helper'
3
3
  module Ddr::Jobs
4
4
  RSpec.describe FitsFileCharacterization, jobs: true, file_characterization: true do
5
5
 
6
- shared_examples "has a fits update event" do
7
- let(:event) { object.update_events.last }
8
- it "should have the correct event attributes" do
9
- expect(event.outcome).to eq(expected_outcome)
10
- expect(event.detail).to eq(expected_detail)
11
- expect(event.software).to eq("fits #{fits_version}")
12
- end
13
- end
6
+ let(:obj) { double }
14
7
 
15
- context "content-bearing object" do
16
- let(:object) { TestContent.create }
17
- let(:stdout_msg) { '<fits />' }
18
- let(:stderr_msg) { 'stderr msg' }
19
- let(:fits_version) { '0.9.9 '}
20
- before { allow(Ddr::Jobs::FitsFileCharacterization).to receive(:fits_version) { fits_version } }
21
- context "fits command is successful" do
22
- let(:expected_outcome) { Ddr::Events::Event::SUCCESS }
23
- let(:expected_detail) { nil }
24
- before do
25
- allow(Open3).to receive(:capture3) { [ stdout_msg, stderr_msg, $? ] }
26
- allow_any_instance_of(Process::Status).to receive(:success?) { true }
27
- Ddr::Jobs::FitsFileCharacterization.perform(object.pid)
28
- object.reload
29
- end
30
- it "should populate the fits datastream" do
31
- expect(object.fits.content).to be_present
32
- end
33
- it_behaves_like "has a fits update event"
34
- end
35
- context "fits command is not successful" do
36
- let(:expected_outcome) { Ddr::Events::Event::FAILURE }
37
- let(:expected_detail) { stderr_msg }
38
- before do
39
- allow(Open3).to receive(:capture3) { [ stdout_msg, stderr_msg, $? ] }
40
- allow_any_instance_of(Process::Status).to receive(:success?) { false }
41
- Ddr::Jobs::FitsFileCharacterization.perform(object.pid)
42
- object.reload
43
- end
44
- it "should not populate the fits datastream" do
45
- expect(object.fits.content).to_not be_present
46
- end
47
- it_behaves_like "has a fits update event"
48
- end
49
- end
8
+ before { allow(ActiveFedora::Base).to receive(:find).with("test:1") { obj } }
9
+
10
+ specify {
11
+ expect(Ddr::Models::FileCharacterization).to receive(:call).with(obj) { nil }
12
+ described_class.perform("test:1")
13
+ }
50
14
 
51
15
  end
52
- end
16
+ end