diff --git a/Gemfile b/Gemfile index f90121b45..f9b7756a7 100644 --- a/Gemfile +++ b/Gemfile @@ -15,12 +15,12 @@ gem 'whenever', '~> 0.9' # Stanford stuff gem 'assembly-objectfile', '~> 1.5' -gem 'dor-services', '~> 6.1', require: false +# We don't require this by default, because we need it to load after hydrus models +# or we'll get a superclass mismatch for Hydrus::Item +gem 'dor-services', '~> 7.1', require: false gem 'dor-services-client', '~> 1.1' gem 'rubydora', '~> 2.1' gem 'bagit', '~> 0.4' -gem 'dor-workflow-client', '~> 3.1' -gem 'net-http-persistent', '~> 2.9' # https://github.com/sul-dlss/dor-workflow-service/issues/44 gem 'blacklight', '~> 6.19' gem 'cancancan', '~> 1.17' diff --git a/Gemfile.lock b/Gemfile.lock index 3cd961f5e..83fbfd841 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -173,24 +173,22 @@ GEM unf (>= 0.0.5, < 1.0.0) dor-rights-auth (1.3.0) nokogiri - dor-services (6.8.0) + dor-services (7.1.0) active-fedora (>= 8.7.0, < 9) - activesupport (>= 4.2.10, < 6.0.0) + activesupport (~> 5.1) confstruct (~> 0.2.7) deprecation (~> 0) dor-rights-auth (~> 1.0, >= 1.2.0) dor-services-client (~> 1.5) - dor-workflow-service (~> 2.11) + dor-workflow-client (~> 3.0) druid-tools (>= 0.4.1) - equivalent-xml (~> 0.5, >= 0.5.1) json (>= 1.8.1) moab-versioning (~> 4.0) - net-sftp (~> 2.1) nokogiri (~> 1.6) om (~> 3.0) rdf (~> 1.1, >= 1.1.7) rest-client (>= 1.7, < 3) - retries + retries (~> 0.0.5) rsolr (>= 1.0.3, < 3) ruby-cache (~> 0.3.0) rubydora (~> 2.1) @@ -212,14 +210,6 @@ GEM faraday_middleware net-http-persistent (>= 2.9.4, < 4.a) nokogiri (~> 1.6) - dor-workflow-service (2.12.0) - activesupport (>= 3.2.1, < 6) - confstruct (>= 0.2.7, < 2) - deprecation - faraday (~> 0.9, >= 0.9.2) - net-http-persistent (>= 2.9.4, < 4.a) - nokogiri (~> 1.6) - retries druid-tools (1.0.0) dry-configurable (0.8.2) concurrent-ruby (~> 1.0) @@ -342,8 +332,6 @@ GEM net-http-persistent (2.9.4) net-scp (2.0.0) net-ssh (>= 2.6.5, < 6.0.0) - net-sftp (2.1.2) - net-ssh (>= 2.6.5) net-ssh (5.2.0) netrc (0.11.0) nio4r (2.3.1) @@ -579,9 +567,8 @@ DEPENDENCIES devise (~> 4.0) devise-remote-user (~> 1.0) dlss-capistrano - dor-services (~> 6.1) + dor-services (~> 7.1) dor-services-client (~> 1.1) - dor-workflow-client (~> 3.1) dynamic_form equivalent-xml factory_bot_rails @@ -591,7 +578,6 @@ DEPENDENCIES letter_opener listen (>= 3.0.5, < 3.2) mysql2 (~> 0.4.5) - net-http-persistent (~> 2.9) okcomputer pry rails (~> 5.2) diff --git a/app/models/hydrus/admin_policy_object.rb b/app/models/hydrus/admin_policy_object.rb index a87befc1d..dc50e3213 100644 --- a/app/models/hydrus/admin_policy_object.rb +++ b/app/models/hydrus/admin_policy_object.rb @@ -4,7 +4,6 @@ class Hydrus::AdminPolicyObject < Dor::AdminPolicyObject include Hydrus::Validatable include Hydrus::Processable include Hydrus::Contentable - include Dor::Publishable extend Hydrus::Delegatable has_metadata( @@ -88,7 +87,7 @@ def self.create(user) args = [user, 'adminPolicy', dconf.ur_apo_druid] response = Hydrus::GenericObject.register_dor_object(*args) apo = Hydrus::AdminPolicyObject.find(response[:pid]) - workflow_client.create_workflow_by_name(response[:pid], Dor::Config.hydrus.app_workflow) + Dor::Config.workflow.client.create_workflow_by_name(response[:pid], Dor::Config.hydrus.app_workflow) apo.remove_relationship :has_model, 'info:fedora/afmodel:Dor_AdminPolicyObject' apo.assert_content_model diff --git a/app/models/hydrus/collection.rb b/app/models/hydrus/collection.rb index dd2d4957e..b154ceafa 100644 --- a/app/models/hydrus/collection.rb +++ b/app/models/hydrus/collection.rb @@ -94,7 +94,7 @@ def self.create(user) # Create the object, with the correct model. apo = Hydrus::AdminPolicyObject.create(user) response = Hydrus::GenericObject.register_dor_object(user, 'collection', apo.pid) - workflow_client.create_workflow_by_name(response[:pid], Dor::Config.hydrus.app_workflow) + Dor::Config.workflow.client.create_workflow_by_name(response[:pid], Dor::Config.hydrus.app_workflow) coll = Hydrus::Collection.find(response[:pid]) coll.remove_relationship :has_model, 'info:fedora/afmodel:Dor_Collection' diff --git a/app/models/hydrus/desc_metadata_ds.rb b/app/models/hydrus/desc_metadata_ds.rb index 87a799b4c..b5dfeaad7 100644 --- a/app/models/hydrus/desc_metadata_ds.rb +++ b/app/models/hydrus/desc_metadata_ds.rb @@ -148,6 +148,24 @@ def self.xml_template end.doc end + # Required by the indexer. This is something that Dor::DescMetadataDS has + # intended for read-access, "as SearchWorks would see it", mostly for to_solr() + # @param [Nokogiri::XML::Document] content Nokogiri descMetadata document (overriding internal data) + # @param [boolean] ns_aware namespace awareness toggle for from_nk_node() + def stanford_mods(content = nil, ns_aware = true) + @stanford_mods ||= begin + m = Stanford::Mods::Record.new + desc = content.nil? ? ng_xml : content + m.from_nk_node(desc.root, ns_aware) + m + end + end + + # This is something the Dor::DescMetadataDS has and the indexer expects of this class + def full_title + stanford_mods.sw_title_display + end + # This provides the prefix for the solr fields generated by ActiveFedora. # Since we don't want a prefix, we override this to return an empty string. def prefix diff --git a/app/models/hydrus/processable.rb b/app/models/hydrus/processable.rb index 79ad85fa1..cae7b0269 100644 --- a/app/models/hydrus/processable.rb +++ b/app/models/hydrus/processable.rb @@ -1,18 +1,12 @@ # A mixin for workflow stuff. module Hydrus::Processable - extend ActiveSupport::Concern REPO = 'dor' def workflow_client - @workflow_client ||= self.class.workflow_client + Dor::Config.workflow.client end - module ClassMethods - def workflow_client - Dor::Workflow::Client.new(url: Settings.workflow.url) - end - end # Takes the name of a step in the Hydrus workflow. # Calls the workflow service to mark that step as completed. def complete_workflow_step(step) diff --git a/app/models/hydrus/rights_metadata_ds.rb b/app/models/hydrus/rights_metadata_ds.rb index 3ced15974..22973f912 100644 --- a/app/models/hydrus/rights_metadata_ds.rb +++ b/app/models/hydrus/rights_metadata_ds.rb @@ -92,4 +92,18 @@ def self.xml_template } end.doc end + + # Copied in from Dor::Services because this is an interface that the rights metadata is supposed to implement + def rights + xml = ng_xml + if xml.search('//rightsMetadata/access[@type=\'read\']/machine/group').length == 1 + 'Stanford' + elsif xml.search('//rightsMetadata/access[@type=\'read\']/machine/world').length == 1 + 'World' + elsif xml.search('//rightsMetadata/access[@type=\'discover\']/machine/none').length == 1 + 'Dark' + else + 'None' + end + end end diff --git a/app/models/hydrus/workflow_ds_extension.rb b/app/models/hydrus/workflow_ds_extension.rb index 14d34ac01..c86e91b5f 100644 --- a/app/models/hydrus/workflow_ds_extension.rb +++ b/app/models/hydrus/workflow_ds_extension.rb @@ -19,7 +19,7 @@ def get_workflow_step(step) end # Takes the name of a hydrusAssemblyWF step. - # Returns the staus of the corresponding process node. + # Returns the status of the corresponding process node. def get_workflow_status(step) node = get_workflow_step(step) node && node['status'] diff --git a/app/services/item_service.rb b/app/services/item_service.rb index 658c8436f..da83eeba6 100644 --- a/app/services/item_service.rb +++ b/app/services/item_service.rb @@ -55,7 +55,7 @@ def build_item(item_type) end def workflow_client - @workflow_client ||= Dor::Workflow::Client.new(url: Settings.workflow.url) + Dor::Config.workflow.client end # Add the Item to the Collection. diff --git a/config/initializers/dor_config.rb b/config/initializers/dor_config.rb index 1a986577c..86c180e07 100644 --- a/config/initializers/dor_config.rb +++ b/config/initializers/dor_config.rb @@ -40,7 +40,6 @@ end solr.url Settings.solr.url - sdr.url Settings.sdr.url hydrus do initial_apo_title 'Intial Hydrus APO title' diff --git a/config/initializers/rights_overrides.rb b/config/initializers/rights_overrides.rb index e97f5dadb..c2edb7827 100644 --- a/config/initializers/rights_overrides.rb +++ b/config/initializers/rights_overrides.rb @@ -1,8 +1,6 @@ module Dor - module Publishable + class Abstract # need to override if we want to use the Hydra access permissions code - included do - has_metadata name: 'rightsMetadata', type: Hydra::Datastream::RightsMetadata, label: 'Rights Metadata' - end + has_metadata name: 'rightsMetadata', type: Hydra::Datastream::RightsMetadata, label: 'Rights Metadata' end end diff --git a/config/settings.yml b/config/settings.yml index bb8e6c496..817057018 100644 --- a/config/settings.yml +++ b/config/settings.yml @@ -33,10 +33,7 @@ stacks: solr: url: 'https://solr.example.com/solr/collection' - -sdr: - url: 'https://sdr.example.com/solr/collection' - + suri: url: 'http://localhost:3002' user: ~ diff --git a/spec/features/collection_create_spec.rb b/spec/features/collection_create_spec.rb index 8149d4c8b..0b118e1b6 100644 --- a/spec/features/collection_create_spec.rb +++ b/spec/features/collection_create_spec.rb @@ -4,7 +4,7 @@ let(:archivist1) { create :archivist1 } let(:archivist99) { create :archivist99 } - before(:each) do + before do @alert = 'div.alert' @notice_save = 'Your changes have been saved' @notice_open = 'Collection opened' diff --git a/spec/features/models/item_spec.rb b/spec/features/models/item_spec.rb index a63f32338..77656adcc 100644 --- a/spec/features/models/item_spec.rb +++ b/spec/features/models/item_spec.rb @@ -1,15 +1,15 @@ require 'spec_helper' -describe(Hydrus::Item, type: :feature, integration: true) do - describe('Content metadata generation') do - it 'should be able to generate content metadata, returning blank CM when no files exist and setting content metadata stream to a blank template' do +RSpec.describe Hydrus::Item, type: :feature, integration: true do + describe 'Content metadata generation' do + it 'generates content metadata, returning blank CM when no files exist and setting content metadata stream to a blank template' do xml = '' hi = Hydrus::Item.new pid: '__DO_NOT_USE__' hi.update_content_metadata expect(hi.datastreams['contentMetadata'].content).to be_equivalent_to(xml) end - it 'should be able to generate content metadata, returning and setting correct cm when files exist' do + it 'generates content metadata, returning and setting correct cm when files exist' do item = Hydrus::Item.find('druid:oo000oo0001') expect(item.files.size).to eq(4) expect(item.datastreams['contentMetadata'].content).to be_equivalent_to '' @@ -55,7 +55,7 @@ Dor::Config.configure.suri.mint_ids = @prev_mint_ids end - it 'should accept the terms for an item, updating the appropriate hydrusProperties metadata in item and collection' do + it 'accepts the terms for an item, updating the appropriate hydrusProperties metadata in item and collection' do expect(item.requires_terms_acceptance(user_key, collection)).to eq(true) expect(item.accepted_terms_of_deposit).to eq('false') expect(collection.users_accepted_terms_of_deposit.keys.include?(user_key)).to eq(false) @@ -70,31 +70,33 @@ describe 'do_publish()' do let(:user) { create :archivist1 } - - let(:mock_wf_client) { instance_double(Dor::Workflow::Client) } - - before(:each) do + let(:wfs) do + instance_double(Dor::Workflow::Client, + all_workflows_xml: '', + milestones: [], + update_workflow_status: nil, + create_workflow_by_name: nil) + end + before do @prev_mint_ids = config_mint_ids() - allow(Dor::Workflow::Client).to receive(:new).and_return(mock_wf_client) - allow(mock_wf_client).to receive(:create_workflow_by_name) - allow(mock_wf_client).to receive(:update_workflow_status) + allow(Dor::Config.workflow).to receive(:client).and_return(wfs) end - after(:each) do + after do config_mint_ids(@prev_mint_ids) end - it 'should modify workflows as expected' do + it 'modifies workflows' do druid = 'druid:oo000oo0003' hi = ItemService.create(druid, user) allow(hi).to receive(:should_start_assembly_wf).and_return(true) allow(hi).to receive(:is_assemblable).and_return(true) hi.do_publish() - expect(mock_wf_client).to have_received(:update_workflow_status).with('dor', hi.pid, - 'hydrusAssemblyWF', 'approve', 'completed') - expect(mock_wf_client).to have_received(:update_workflow_status).with('dor', hi.pid, - 'hydrusAssemblyWF', 'start-assembly', 'completed') - expect(mock_wf_client).to have_received(:create_workflow_by_name).with(hi.pid, 'assemblyWF') + expect(wfs).to have_received(:update_workflow_status).with('dor', hi.pid, + 'hydrusAssemblyWF', 'approve', 'completed') + expect(wfs).to have_received(:update_workflow_status).with('dor', hi.pid, + 'hydrusAssemblyWF', 'start-assembly', 'completed') + expect(wfs).to have_received(:create_workflow_by_name).with(hi.pid, 'assemblyWF') end end diff --git a/spec/models/hydrus/processable_spec.rb b/spec/models/hydrus/processable_spec.rb index fe31a3b69..4afc054ce 100644 --- a/spec/models/hydrus/processable_spec.rb +++ b/spec/models/hydrus/processable_spec.rb @@ -1,29 +1,40 @@ require 'spec_helper' -describe Hydrus::Processable, type: :model do - let(:mock_wf_client) { instance_double(Dor::Workflow::Client) } - - before(:each) do +RSpec.describe Hydrus::Processable, type: :model do + before do @cannot_do_regex = /\ACannot perform action/ @go = Hydrus::GenericObject.new - allow(Dor::Workflow::Client).to receive(:new).and_return(mock_wf_client) - allow(mock_wf_client).to receive(:update_workflow_status) end describe 'complete_workflow_step()' do + let(:wfs) { instance_double(Dor::Workflow::Client) } + before do + allow(Dor::Config.workflow).to receive(:client).and_return(wfs) + end + it 'can exercise the method, stubbing out call to WF service' do step = 'submit' args = ['dor', @go.pid, 'hydrusAssemblyWF', step, 'completed'] - expect(mock_wf_client).to receive(:update_workflow_status).with(*args) + expect(wfs).to receive(:update_workflow_status).with(*args) allow(@go).to receive_message_chain(:workflows, :workflow_step_is_done).and_return(false) expect(@go).to receive(:workflows_content_is_stale) @go.complete_workflow_step(step) end end - it 'can exercise start_hydrus_wf() stubbed' do - expect(mock_wf_client).to receive(:create_workflow_by_name).with(@go.pid, 'hydrusAssemblyWF') - @go.start_hydrus_wf() + describe '#start_hydrus_wf' do + subject(:start_hydrus_wf) { @go.start_hydrus_wf } + + let(:wfs) { instance_double(Dor::Workflow::Client, create_workflow_by_name: true) } + + before do + allow(Dor::Config.workflow).to receive(:client).and_return(wfs) + end + + it 'creates a workflow' do + start_hydrus_wf + expect(wfs).to have_received(:create_workflow_by_name).with(@go.pid, 'hydrusAssemblyWF') + end end it 'can exercise workflows_content_is_stale, stubbed' do @@ -60,10 +71,15 @@ end end - describe 'start_assembly_wf()' do - it 'should do nothing if the app is not configured to start assemblyWF' do + describe '#start_assembly_wf' do + let(:wfs) { instance_double(Dor::Workflow::Client) } + before do + allow(Dor::Config.workflow).to receive(:client).and_return(wfs) + end + + it 'does nothing if the app is not configured to start assemblyWF' do allow(@go).to receive(:should_start_assembly_wf).and_return(false) - expect(Dor::Workflow::Client).not_to receive(:create_workflow_by_name) + expect(wfs).not_to receive(:create_workflow_by_name) @go.start_assembly_wf end @@ -73,6 +89,11 @@ end describe 'is_accessioned()' do + let(:wfs) { instance_double(Dor::Workflow::Client) } + before do + allow(Dor::Config.workflow).to receive(:client).and_return(wfs) + end + it 'can exercise all logic branches' do # At each stage, we set a stub, call is_accessioned(), and then reverse the stub. # Not published: false. @@ -84,19 +105,24 @@ expect(@go.is_accessioned).to eq(true) allow(@go).to receive(:should_treat_as_accessioned).and_return(false) # Never accessioned: false. - allow(mock_wf_client).to receive(:lifecycle).with('dor', @go.pid, 'accessioned').and_return(false) + allow(wfs).to receive(:lifecycle).with('dor', @go.pid, 'accessioned').and_return(false) expect(@go.is_accessioned).to eq(false) - allow(mock_wf_client).to receive(:lifecycle).with('dor', @go.pid, 'accessioned').and_return(true) + allow(wfs).to receive(:lifecycle).with('dor', @go.pid, 'accessioned').and_return(true) # AccessionWF active for current version: true - allow(mock_wf_client).to receive(:active_lifecycle).with('dor', @go.pid, 'submitted').and_return(true) + allow(wfs).to receive(:active_lifecycle).with('dor', @go.pid, 'submitted').and_return(true) expect(@go.is_accessioned).to eq(false) - allow(mock_wf_client).to receive(:active_lifecycle).with('dor', @go.pid, 'submitted').and_return(false) + allow(wfs).to receive(:active_lifecycle).with('dor', @go.pid, 'submitted').and_return(false) # Survived all tests: true. expect(@go.is_accessioned).to eq(true) end end describe 'publish_time()' do + let(:wfs) { instance_double(Dor::Workflow::Client) } + before do + allow(Dor::Config.workflow).to receive(:client).and_return(wfs) + end + it 'development and test mode: 1 day after submitted_for_publish_time' do spt = '2013-02-27T00:38:22Z' exp = '2013-02-28T00:38:22Z' @@ -107,7 +133,7 @@ it 'production mode: query workflow service' do allow(@go).to receive(:should_treat_as_accessioned).and_return(false) exp = '2000-02-01T00:30:00Z' - allow(mock_wf_client).to receive(:lifecycle).and_return(exp) + allow(wfs).to receive(:lifecycle).and_return(exp) expect(@go.publish_time).to eq(exp) end end diff --git a/spec/services/item_service_spec.rb b/spec/services/item_service_spec.rb index 131ff8f7f..1fa932d47 100644 --- a/spec/services/item_service_spec.rb +++ b/spec/services/item_service_spec.rb @@ -13,11 +13,11 @@ describe '.create' do subject(:item) { described_class.create(collection.pid, user) } - let(:workflow_client) { instance_double(Dor::Workflow::Client, create_workflow_by_name: nil) } + let(:workflow_client) { instance_double(Dor::Workflow::Client, create_workflow_by_name: nil, all_workflows_xml: '', milestones: []) } let(:collection) { Hydrus::Collection.find('druid:oo000oo0003') } before do - allow(Dor::Workflow::Client).to receive(:new).and_return(workflow_client) + allow(Dor::Config.workflow).to receive(:client).and_return(workflow_client) end context 'if the user has already accepted another item in this collection but it was more than 1 year ago' do