diff --git a/.circleci/config.yml b/.circleci/config.yml index dadab0ece..1810806af 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -4,6 +4,9 @@ orbs: jobs: bundle_lint_test: parameters: + ruby_type: + type: string + default: 'ruby' ruby_version: type: string bundler_version: @@ -14,23 +17,22 @@ jobs: solr_config_path: type: string default: lib/generators/active_fedora/config/solr/templates/solr/conf - ruby_type: - type: string - default: 'ruby' solr_port: type: string default: '8985' fcrepo_version: type: string - default: "4.7.5" + default: "5.1.0" solr_version: type: string default: "9" docker: - image: cimg/<< parameters.ruby_type >>:<< parameters.ruby_version >>-browsers - - image: samvera/fcrepo4:<< parameters.fcrepo_version >> + - image: fcrepo/fcrepo:6.5-tomcat9 environment: - CATALINA_OPTS: "-Djava.awt.headless=true -Dfile.encoding=UTF-8 -server -Xms512m -Xmx1024m -XX:NewSize=256m -XX:MaxNewSize=256m -XX:PermSize=256m -XX:MaxPermSize=256m -XX:+DisableExplicitGC" + JAVA_OPTS: -Dfcrepo.autoversioning.enabled=false -Dfcrepo.external.content.allowed=/fcrepo_allow.txt + command: | + /bin/bash -c "echo 'http://fedoraAdmin:fedoraAdmin@localhost:8080/' > /fcrepo_allow.txt && catalina.sh run" - image: zookeeper:3.9 environment: ZOO_ADMINSERVER_ENABLED: false @@ -48,6 +50,8 @@ jobs: FCREPO_TEST_PORT: 8080 SPEC_OPTS: --profile 10 --format RspecJunitFormatter --out /tmp/test-results/rspec.xml --format progress RAILS_VERSION: << parameters.rails_version >> + FCREPO_PORT: 8080 + FCREPO_REST_PATH: fcrepo/rest steps: - samvera/cached_checkout - checkout diff --git a/.fcrepo_wrapper b/.fcrepo_wrapper new file mode 100644 index 000000000..a07a0facb --- /dev/null +++ b/.fcrepo_wrapper @@ -0,0 +1,10 @@ +# Place any default configuration for solr_wrapper here +port: 8986 +version: 6.4.0 +enable_jms: false +java_options: ['-Dfcrepo.log.http.api=DEBUG','-Dfcrepo.log.kernel=ERROR','-Xmx512m', + '-Dfcrepo.external.content.allowed=config/fcrepo_allow.txt', '-Dfcrepo.autoversioning.enabled=false'] +#managed: true +#fcrepo_home_dir: tmp/fcrepo-development-data +url: https://github.com/fcrepo/fcrepo/releases/download/fcrepo-6.4.0/fcrepo-webapp-6.4.0-jetty-console.jar +ignore_md5sum: true diff --git a/.rubocop.yml b/.rubocop.yml index ecd2f96b0..8f1a43062 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -248,6 +248,9 @@ Rails/FilePath: Rails/ActiveRecordAliases: Enabled: false +Rails/RakeEnvironment: + Enabled: false + Rails/SkipsModelValidations: Enabled: false diff --git a/.solr_wrapper b/.solr_wrapper index 76f6388a2..a09b7f691 100644 --- a/.solr_wrapper +++ b/.solr_wrapper @@ -1,5 +1,5 @@ # Place any default configuration for solr_wrapper here -# version: 6.1.0 +version: 7.7.3 port: 8985 collection: dir: lib/generators/active_fedora/config/solr/templates/solr/conf/ diff --git a/active-fedora.gemspec b/active-fedora.gemspec index 908e1e920..dc191cfa2 100644 --- a/active-fedora.gemspec +++ b/active-fedora.gemspec @@ -20,8 +20,9 @@ Gem::Specification.new do |s| s.add_dependency "activesupport", '>= 6.1' s.add_dependency "active-triples", '>= 0.11.0', '< 2.0.0' s.add_dependency "deprecation" - s.add_dependency 'faraday', '>= 1.0' + s.add_dependency 'faraday', '>= 2.0' s.add_dependency 'faraday-encoding', '>= 0.0.5' + s.add_dependency 'faraday-follow_redirects' s.add_dependency "ldp", '>= 0.7.0', '< 2' s.add_dependency "mutex_m" s.add_dependency 'rsolr', '>= 1.1.2', '< 3' diff --git a/config/fcrepo_allow.txt b/config/fcrepo_allow.txt new file mode 100644 index 000000000..6788ce61f --- /dev/null +++ b/config/fcrepo_allow.txt @@ -0,0 +1,3 @@ +https://example.com/ +http://example.com/ +http://localhost:8986/ diff --git a/lib/active_fedora/attached_files.rb b/lib/active_fedora/attached_files.rb index 355e0d0cd..5f0008be2 100644 --- a/lib/active_fedora/attached_files.rb +++ b/lib/active_fedora/attached_files.rb @@ -80,6 +80,8 @@ def add_file(file, opts) node.content = file node.mime_type = opts[:mime_type] node.original_name = opts[:original_name] + node.external_uri = opts[:external_uri] + node.external_handling = opts[:external_handling] end end diff --git a/lib/active_fedora/change_set.rb b/lib/active_fedora/change_set.rb index f3492d2a3..e1edaa4df 100644 --- a/lib/active_fedora/change_set.rb +++ b/lib/active_fedora/change_set.rb @@ -32,7 +32,9 @@ def changes elsif key == 'type'.freeze # working around https://github.com/ActiveTriples/ActiveTriples/issues/122 predicate = ::RDF.type - result[predicate] = graph.query({ subject: object.rdf_subject, predicate: predicate }) + result[predicate] = graph.query({ subject: object.rdf_subject, predicate: predicate }).select do |statement| + !statement.object.to_s.start_with?("http://fedora.info/definitions/v4/repository#", "http://www.w3.org/ns/ldp#") + end elsif object.local_attributes.include?(key) raise "Unable to find a graph predicate corresponding to the attribute: \"#{key}\"" end diff --git a/lib/active_fedora/clean_connection.rb b/lib/active_fedora/clean_connection.rb index 24692f7c9..d1f0f1a62 100644 --- a/lib/active_fedora/clean_connection.rb +++ b/lib/active_fedora/clean_connection.rb @@ -13,6 +13,7 @@ def get(*args) def omit_uris [ + "http://fedora.info/definitions/fcrepo#ServerManaged", ::RDF::Vocab::Fcrepo4.ServerManaged, ::RDF::Vocab::LDP.PreferContainment, ::RDF::Vocab::LDP.PreferEmptyContainer, diff --git a/lib/active_fedora/containers/direct_container.rb b/lib/active_fedora/containers/direct_container.rb index a379314a6..591c61ec3 100644 --- a/lib/active_fedora/containers/direct_container.rb +++ b/lib/active_fedora/containers/direct_container.rb @@ -1,5 +1,4 @@ module ActiveFedora class DirectContainer < Container - type ::RDF::Vocab::LDP.DirectContainer end end diff --git a/lib/active_fedora/containers/indirect_container.rb b/lib/active_fedora/containers/indirect_container.rb index dfa49d3ff..0c5adee30 100644 --- a/lib/active_fedora/containers/indirect_container.rb +++ b/lib/active_fedora/containers/indirect_container.rb @@ -1,7 +1,5 @@ module ActiveFedora class IndirectContainer < Container - type ::RDF::Vocab::LDP.IndirectContainer - property :inserted_content_relation, predicate: ::RDF::Vocab::LDP.insertedContentRelation end end diff --git a/lib/active_fedora/file.rb b/lib/active_fedora/file.rb index 0ea555c57..96ba7db5e 100644 --- a/lib/active_fedora/file.rb +++ b/lib/active_fedora/file.rb @@ -8,10 +8,12 @@ class File autoload :Streaming autoload :Attributes + autoload :External include Common include ActiveFedora::File::Attributes include ActiveFedora::File::Streaming + include ActiveFedora::File::External include ActiveFedora::FilePersistence include ActiveFedora::Versionable include ActiveModel::Dirty @@ -175,6 +177,7 @@ def retrieve_content def ldp_headers headers = { 'Content-Type'.freeze => mime_type, 'Content-Length'.freeze => content.size.to_s } headers['Content-Disposition'.freeze] = "attachment; filename=\"#{URI::DEFAULT_PARSER.escape(@original_name)}\"" if @original_name + headers["Link"] = "<#{@external_uri}>; rel=\"http://fedora.info/definitions/fcrepo#ExternalContent\"; handling=\"#{@external_handling}\"; type=\"#{mime_type}\"" if @external_uri headers end diff --git a/lib/active_fedora/file/external.rb b/lib/active_fedora/file/external.rb new file mode 100644 index 000000000..12d3ce1b4 --- /dev/null +++ b/lib/active_fedora/file/external.rb @@ -0,0 +1,39 @@ +module ActiveFedora::File::External + HANDLING_TYPES = ['redirect', 'proxy', 'copy'].freeze + + def external_uri + @external_uri ||= fetch_external_uri + end + + def external_uri=(uri) + @external_uri = uri + end + + def external_handling=(handling) + @external_handling = handling + end + + def external_handling + @external_handling ||= fetch_external_handling + end + + private + + def fetch_external_uri + return if new_record? + ldp_source.head.response.headers['Content-Location'] + end + + def fetch_external_handling + return if new_record? + response = ldp_source.head.response + return unless response.headers.key?('Content-Location') + + case response.status + when Net::HTTPRedirection + 'redirect' + when Net::HTTPSuccess + 'proxy' + end + end +end diff --git a/lib/active_fedora/file/streaming.rb b/lib/active_fedora/file/streaming.rb index 1ef020d89..34501805c 100644 --- a/lib/active_fedora/file/streaming.rb +++ b/lib/active_fedora/file/streaming.rb @@ -1,17 +1,17 @@ +require 'faraday/follow_redirects' + module ActiveFedora::File::Streaming # @param range [String] the Range HTTP header # @return [Stream] an object that responds to each def stream(range = nil) uri = URI.parse(self.uri) - FileBody.new(uri, headers(range, authorization_key)) + FileBody.new(uri, headers(range, nil)) end # @param range [String] from #stream - # @param key [String] from #authorization_key # @return [Hash] - def headers(range, key, result = {}) + def headers(range, _key, result = {}) result["Range"] = range if range - result["Authorization"] = key if key result end @@ -22,32 +22,35 @@ def initialize(uri, headers) @headers = headers end - def each(no_of_requests_limit = 3, &block) - raise ArgumentError, 'HTTP redirect too deep' if no_of_requests_limit.zero? - Net::HTTP.start(uri.host, uri.port, use_ssl: (uri.scheme == 'https')) do |http| - request = Net::HTTP::Get.new uri, headers - http.request request do |response| - case response - when Net::HTTPSuccess - response.read_body do |chunk| - yield chunk - end - when Net::HTTPRedirection - no_of_requests_limit -= 1 - @uri = URI(response["location"]) - each(no_of_requests_limit, &block) - else - raise "Couldn't get data from Fedora (#{uri}). Response: #{response.code}" - end + def each(no_of_requests_limit = 3) + redirecting_connection(no_of_requests_limit).get(uri.to_s, nil, headers) do |req| + req.options.on_data = proc do |chunk, overall_received_bytes, _env| + yield chunk unless overall_received_bytes.zero? # Don't yield when redirecting end end + rescue Faraday::FollowRedirects::RedirectLimitReached + raise ArgumentError, 'HTTP redirect too deep' + rescue Faraday::Error => ex + raise "Couldn't get data from Fedora (#{uri}). Response: #{ex.response_status}" end - end - private + private - # @return [String] current authorization token from Ldp::Client - def authorization_key - ldp_source.client.http.headers.fetch("Authorization", nil) - end + # Create a new faraday connection with follow_redirects enabled and configured using passed value + def redirecting_connection(redirection_limit) + options = {} + options[:ssl] = ActiveFedora.fedora.ssl_options if ActiveFedora.fedora.ssl_options + options[:request] = ActiveFedora.fedora.request_options if ActiveFedora.fedora.request_options + Faraday.new(ActiveFedora.fedora.host, options) do |conn| + conn.response :encoding # use Faraday::Encoding middleware + conn.adapter Faraday.default_adapter # net/http + if Gem::Version.new(Faraday::VERSION) < Gem::Version.new('2') + conn.request :basic_auth, ActiveFedora.fedora.user, ActiveFedora.fedora.password + else + conn.request :authorization, :basic, ActiveFedora.fedora.user, ActiveFedora.fedora.password + conn.response :follow_redirects, limit: redirection_limit - 1 # Need to reduce by one to retain same behavior as before + end + end + end + end end diff --git a/lib/active_fedora/file_configurator.rb b/lib/active_fedora/file_configurator.rb index 2f2be7624..5ce16a99c 100644 --- a/lib/active_fedora/file_configurator.rb +++ b/lib/active_fedora/file_configurator.rb @@ -183,7 +183,7 @@ def config_path(config_type) end if defined?(Rails.root) - config_path = "#{Rails.root}/config/#{config_type}.yml" + config_path = [Rails.root, "config/#{config_type}.yml"].join('/') return config_path if ::File.file? config_path end diff --git a/lib/active_fedora/indexing/descendant_fetcher.rb b/lib/active_fedora/indexing/descendant_fetcher.rb index f12a62e96..99337f59f 100644 --- a/lib/active_fedora/indexing/descendant_fetcher.rb +++ b/lib/active_fedora/indexing/descendant_fetcher.rb @@ -55,7 +55,7 @@ def descendant_and_self_uris_partitioned def descendant_and_self_uris_partitioned_by_model # GET could be slow if it's a big resource, we're using HEAD to avoid this problem, # but this causes more requests to Fedora. - return partitioned_uris unless rdf_resource.head.rdf_source? + return partitioned_uris unless rdf_source? add_self_to_partitioned_uris unless @exclude_self @@ -76,6 +76,12 @@ def descendant_and_self_uris_partitioned_by_model protected + # Fcrepo 6.4 returns a 406 for file objects when returning ntriples + # so use the standard connection just for the head request + def rdf_source? + Ldp::Resource.new(ActiveFedora.fedora.connection, uri).head.rdf_source? + end + def rdf_resource @rdf_resource ||= Ldp::Resource::RdfSource.new(ActiveFedora.fedora.build_ntriples_connection, uri) end diff --git a/lib/active_fedora/ldp_resource.rb b/lib/active_fedora/ldp_resource.rb index 2181f4eb4..7ac556436 100644 --- a/lib/active_fedora/ldp_resource.rb +++ b/lib/active_fedora/ldp_resource.rb @@ -1,11 +1,14 @@ module ActiveFedora - class LdpResource < Ldp::Resource::RdfSource - def build_empty_graph - graph_class.new(subject_uri) + module LdpResourceAddons + extend ActiveSupport::Concern + module ClassMethods + def graph_class + ActiveTriples::Resource + end end - def self.graph_class - ActiveTriples::Resource + def build_empty_graph + graph_class.new(subject_uri) end def graph_class @@ -27,4 +30,16 @@ def response_as_graph(resp) graph_class.new(subject_uri, data: resp.graph.data) end end + + class LdpResource < Ldp::Resource::RdfSource + include LdpResourceAddons + end + + class IndirectContainerResource < Ldp::Container::Indirect + include LdpResourceAddons + end + + class DirectContainerResource < Ldp::Container::Direct + include LdpResourceAddons + end end diff --git a/lib/active_fedora/ldp_resource_service.rb b/lib/active_fedora/ldp_resource_service.rb index 296ff61d4..48a2f3f4f 100644 --- a/lib/active_fedora/ldp_resource_service.rb +++ b/lib/active_fedora/ldp_resource_service.rb @@ -7,11 +7,22 @@ def initialize(conn) end def build(klass, id) + resource_klass = resource_klass(klass) if id - LdpResource.new(connection, to_uri(klass, id)) + resource_klass.new(connection, to_uri(klass, id)) else parent_uri = ActiveFedora.fedora.host + ActiveFedora.fedora.base_path - LdpResource.new(connection, nil, nil, parent_uri) + resource_klass.new(connection, nil, nil, parent_uri) + end + end + + def resource_klass(klass) + if klass <= ActiveFedora::IndirectContainer + IndirectContainerResource + elsif klass <= ActiveFedora::DirectContainer + DirectContainerResource + else + LdpResource end end diff --git a/lib/active_fedora/persistence.rb b/lib/active_fedora/persistence.rb index 56d40936f..dc438428b 100644 --- a/lib/active_fedora/persistence.rb +++ b/lib/active_fedora/persistence.rb @@ -228,10 +228,11 @@ def identifier_service # and assign_id can mint an id for the object, then assign it to the resource. # Otherwise the resource will have the id assigned by the LDP server def assign_rdf_subject + ldp_resource_klass = ActiveFedora.fedora.ldp_resource_service.resource_klass(self.class) @ldp_source = if !id && new_id = assign_id - LdpResource.new(ActiveFedora.fedora.connection, self.class.id_to_uri(new_id), @resource) + ldp_resource_klass.new(ActiveFedora.fedora.connection, self.class.id_to_uri(new_id), @resource) else - LdpResource.new(ActiveFedora.fedora.connection, @ldp_source.subject, @resource, base_path_for_resource) + ldp_resource_klass.new(ActiveFedora.fedora.connection, @ldp_source.subject, @resource, base_path_for_resource) end end diff --git a/lib/active_fedora/versionable.rb b/lib/active_fedora/versionable.rb index d4fb6a84f..e39824ee1 100644 --- a/lib/active_fedora/versionable.rb +++ b/lib/active_fedora/versionable.rb @@ -6,21 +6,11 @@ module Versionable class_attribute :versionable end - def model_type - if respond_to?(:metadata) - metadata.ldp_source.graph.query({ predicate: ::RDF.type }).objects - else - resource.query({ subject: resource.rdf_subject, predicate: ::RDF.type }).objects - end - end - # Returns an array of ActiveFedora::VersionsGraph::ResourceVersion objects. - # Excludes auto-snapshot versions from Fedora. def versions(reload = false) response = versions_request return ActiveFedora::VersionsGraph.new unless response - if reload @versions = ActiveFedora::VersionsGraph.new << versions_request.reader else @@ -29,46 +19,32 @@ def versions(reload = false) end def create_version - resp = ActiveFedora.fedora.connection.post(versions_uri, nil, slug: version_name) + resp = ActiveFedora.fedora.connection.post(versions_uri, nil) @versions = nil resp.success? end # Queries Fedora to figure out if there are versions for the resource. def has_versions? - ActiveFedora.fedora.connection.head(versions_uri) - true + resp = ActiveFedora.fedora.connection.get(versions_uri) + graph = ::RDF::Graph.new << resp.reader + graph.query({ predicate: ::RDF::Vocab::LDP.contains }).present? rescue Ldp::NotFound false end - def restore_version(label) - resp = ActiveFedora.fedora.connection.patch(versions.with_label(label).uri, nil) - @versions = nil - reload - refresh_attributes if respond_to?("refresh_attributes") - resp.success? - end - private def versions_request - return false unless has_versions? ActiveFedora.fedora.connection.get(versions_uri) + rescue Ldp::NotFound + false end def versions_uri uri + '/fcr:versions' end - def version_name - if versions.all.empty? - "version1" - else - "version" + (versions.all.count + 1).to_s - end - end - def status_message(response) "Unexpected return value #{response.status} when retrieving datastream content at #{uri}\n\t#{response.body}" end diff --git a/lib/active_fedora/versions_graph.rb b/lib/active_fedora/versions_graph.rb index feabb5f7e..15aa3a469 100644 --- a/lib/active_fedora/versions_graph.rb +++ b/lib/active_fedora/versions_graph.rb @@ -1,8 +1,7 @@ module ActiveFedora class VersionsGraph < ::RDF::Graph - def all(opts = {}) + def all(_opts = {}) versions = fedora_versions - versions.reject! { |version| version.label =~ /auto/ } unless opts[:include_auto_save] versions.sort_by { |version| DateTime.parse(version.created) } rescue ArgumentError, NoMethodError raise ActiveFedora::VersionLacksCreateDate @@ -12,40 +11,31 @@ def all(opts = {}) delegate :last, to: :all - def with_label(label) + def with_datetime(datetime) all.each do |version| - return version if version.label == label + return version if version.created == datetime end end - def resources - query({ predicate: ::RDF::Vocab::Fcrepo4.hasVersion }) + def versions + query({ predicate: ::RDF::Vocab::LDP.contains }) end private class ResourceVersion - attr_accessor :uri, :label, :created + attr_accessor :uri, :created end def version_from_resource(statement) version = ResourceVersion.new - version.uri = statement.object.to_s.gsub(/\/fcr:metadata$/, "") - version.label = label_query(statement) - version.created = created_query(statement) + version.uri = statement.object + version.created = statement.object.to_s.split("fcr:versions/")[1] version end - def label_query(statement) - query({ subject: statement.object }).query({ predicate: ::RDF::Vocab::Fcrepo4.hasVersionLabel }).first.object.to_s - end - - def created_query(statement) - query({ subject: statement.object }).query({ predicate: ::RDF::Vocab::Fcrepo4.created }).first.object.to_s - end - def fedora_versions - resources.map { |statement| version_from_resource(statement) } + versions.map { |statement| version_from_resource(statement) } end end end diff --git a/lib/active_fedora/with_metadata/metadata_node.rb b/lib/active_fedora/with_metadata/metadata_node.rb index 121010a2d..ad576fb8c 100644 --- a/lib/active_fedora/with_metadata/metadata_node.rb +++ b/lib/active_fedora/with_metadata/metadata_node.rb @@ -14,8 +14,13 @@ class MetadataNode < ActiveTriples::Resource def initialize(file) @file = file super(file.uri, ldp_source.graph) + return unless self.class.type && !type.include?(self.class.type) - attribute_will_change!(:type) if type.present? + types = type.reject do |statement| + ::RDF::URI.new(statement.object).to_s.start_with?("http://fedora.info/definitions/v4/repository#", "http://www.w3.org/ns/ldp#") + end + + attribute_will_change!(:type) if types.present? # Workaround for https://github.com/ActiveTriples/ActiveTriples/issues/123 get_values(:type) << self.class.type end diff --git a/lib/tasks/active_fedora_dev.rake b/lib/tasks/active_fedora_dev.rake index 4b5f5f8f8..ff305cd52 100644 --- a/lib/tasks/active_fedora_dev.rake +++ b/lib/tasks/active_fedora_dev.rake @@ -19,7 +19,7 @@ namespace :active_fedora do end rescue LoadError desc "Generate YARD Documentation" - task doc: :environment do + task :doc do abort "Please install the YARD gem to generate rdoc." end end @@ -42,7 +42,7 @@ namespace :active_fedora do end desc "CI build" - task ci: :environment do + task :ci do Rake::Task['active_fedora:rubocop'].invoke unless ENV['NO_RUBOCOP'] ENV['environment'] = "test" with_test_server do @@ -51,7 +51,7 @@ namespace :active_fedora do end desc "Execute specs with coverage" - task coverage: :environment do + task :coverage do # Put spec opts in a file named .rspec in root ruby_engine = defined?(RUBY_ENGINE) ? RUBY_ENGINE : "ruby" ENV['COVERAGE'] = 'true' unless ruby_engine == 'jruby' @@ -59,7 +59,7 @@ namespace :active_fedora do end desc "Execute specs with coverage" - task spec: :environment do + task :spec do with_test_server do Rake::Task["active_fedora:rspec"].invoke end diff --git a/spec/integration/file_spec.rb b/spec/integration/file_spec.rb index 92d4ea5de..f527fbc60 100644 --- a/spec/integration/file_spec.rb +++ b/spec/integration/file_spec.rb @@ -196,7 +196,10 @@ class SampleResource < ActiveFedora::File context "when the request results in a redirect" do before do test_object.add_file('one1two2threfour', path: 'webm', mime_type: 'video/webm') - test_object.add_file('', path: 'redirector', mime_type: "message/external-body; access-type=URL; url=\"#{test_object.webm.uri}\"") + external_uri = test_object.webm.uri.clone + external_uri.user = 'fedoraAdmin' + external_uri.password = 'fedoraAdmin' + test_object.add_file('', path: 'redirector', mime_type: 'video/webm', external_uri: external_uri, external_handling: 'redirect') test_object.save! end subject { str = ''; test_object.redirector.stream.each { |chunk| str << chunk }; str } @@ -205,9 +208,18 @@ class SampleResource < ActiveFedora::File context "when there are more than 3 requests because of redirects" do before do - test_object.add_file('', path: 'one', mime_type: "message/external-body; access-type=URL; url=\"#{test_object.attached_files[path].uri}\"") - test_object.add_file('', path: 'two', mime_type: "message/external-body; access-type=URL; url=\"#{test_object.one.uri}\"") - test_object.add_file('', path: 'three', mime_type: "message/external-body; access-type=URL; url=\"#{test_object.two.uri}\"") + external_uri1 = test_object.attached_files[path].uri.clone + external_uri1.user = 'fedoraAdmin' + external_uri1.password = 'fedoraAdmin' + test_object.add_file('', path: 'one', external_uri: external_uri1, external_handling: 'redirect') + external_uri2 = test_object.one.uri.clone + external_uri2.user = 'fedoraAdmin' + external_uri2.password = 'fedoraAdmin' + test_object.add_file('', path: 'two', external_uri: external_uri2, external_handling: 'redirect') + external_uri3 = test_object.two.uri.clone + external_uri3.user = 'fedoraAdmin' + external_uri3.password = 'fedoraAdmin' + test_object.add_file('', path: 'three', external_uri: external_uri3, external_handling: 'redirect') test_object.save! end it "raises a HTTP redirect too deep Error" do diff --git a/spec/integration/versionable_spec.rb b/spec/integration/versionable_spec.rb index 94215609d..a3a5f953f 100644 --- a/spec/integration/versionable_spec.rb +++ b/spec/integration/versionable_spec.rb @@ -1,4 +1,5 @@ require 'spec_helper' +require 'time' describe ActiveFedora::Versionable do context "For ActiveFedora::Base" do @@ -38,16 +39,16 @@ class WithVersions < ActiveFedora::Base allow(graph).to receive(:fedora_versions) { versions } end - let(:version1) { instance_double(ActiveFedora::VersionsGraph::ResourceVersion, uri: 'http://localhost:8983/fedora/rest/test/84/61/63/98/84616398-f63a-4572-ba01-0689339e4fcb/fcr:versions/87a0a8c317f1e711aa993d-e1d2-4a65-93ee-3a12fc9541ab', label: 'version1', created: '2015-04-02T19:54:45.962Z') } - let(:version2) { instance_double(ActiveFedora::VersionsGraph::ResourceVersion, uri: 'http://localhost:8983/fedora/rest/test/84/61/63/98/84616398-f63a-4572-ba01-0689339e4fcb/fcr:versions/87a0a8c317f1e790373a67-c9ee-447d-b740-4faa882b1a1f', label: 'version2', created: '2015-04-02T19:54:45.96Z') } + let(:version1) { instance_double(ActiveFedora::VersionsGraph::ResourceVersion, uri: 'http://localhost:8983/fedora/rest/test/84/61/63/98/84616398-f63a-4572-ba01-0689339e4fcb/fcr:versions/20180518230244', created: "20180518230244") } + let(:version2) { instance_double(ActiveFedora::VersionsGraph::ResourceVersion, uri: 'http://localhost:8983/fedora/rest/test/84/61/63/98/84616398-f63a-4572-ba01-0689339e4fcb/fcr:versions/20180518230544', created: "20180518230544") } let(:versions) { [version1, version2] } it 'sorts by DateTime' do - expect(graph.first).to eq version2 + expect(graph.last).to eq version2 end context 'with an unparseable created date' do - let(:version2) { instance_double(ActiveFedora::VersionsGraph::ResourceVersion, uri: 'http://localhost:8983/fedora/rest/test/84/61/63/98/84616398-f63a-4572-ba01-0689339e4fcb/fcr:versions/87a0a8c317f1e790373a67-c9ee-447d-b740-4faa882b1a1f', label: 'version2', created: '') } + let(:version2) { instance_double(ActiveFedora::VersionsGraph::ResourceVersion, uri: 'http://localhost:8983/fedora/rest/test/84/61/63/98/84616398-f63a-4572-ba01-0689339e4fcb/fcr:versions/version2', created: '') } it 'raises an exception' do expect { graph.first }.to raise_error(ActiveFedora::VersionLacksCreateDate) @@ -60,7 +61,7 @@ class WithVersions < ActiveFedora::Base allow(version2).to receive(:created) { raise NoMethodError } end - let(:version2) { instance_double(ActiveFedora::VersionsGraph::ResourceVersion, uri: 'http://localhost:8983/fedora/rest/test/84/61/63/98/84616398-f63a-4572-ba01-0689339e4fcb/fcr:versions/87a0a8c317f1e790373a67-c9ee-447d-b740-4faa882b1a1f', label: 'version2') } + let(:version2) { instance_double(ActiveFedora::VersionsGraph::ResourceVersion, uri: 'http://localhost:8983/fedora/rest/test/84/61/63/98/84616398-f63a-4572-ba01-0689339e4fcb/fcr:versions') } it 'raises an exception' do expect { graph.first }.to raise_error(ActiveFedora::VersionLacksCreateDate) @@ -80,12 +81,12 @@ class WithVersions < ActiveFedora::Base it "has one version" do expect(object.versions).to be_kind_of ActiveFedora::VersionsGraph expect(object.versions.all.first).to be_kind_of ActiveFedora::VersionsGraph::ResourceVersion - expect(object.versions.all.first.label).to eql "version1" expect(object.versions.all.first.created).to start_with current_year end context "two times" do before do + sleep(1) object.title = ["Surrender and prepare to be boarded"] object.save object.create_version @@ -94,34 +95,9 @@ class WithVersions < ActiveFedora::Base it "has two versions" do expect(object.versions.all.size).to eq 2 object.versions.all.each_index do |index| - expect(object.versions.all[index].label).to end_with "version" + (index + 1).to_s expect(object.versions.all[index].created).to start_with current_year end end - - context "then restoring" do - let(:first_version) { "version1" } - before do - object.restore_version(first_version) - end - - it "will return to the first version's values" do - expect(object.title).to eq(["Greetings Earthlings"]) - end - - context "and creating additional versions" do - before do - object.title = ["Now, surrender and prepare to be boarded"] - object.save! - object.create_version - end - - it "has three versions" do - expect(object.versions.all.size).to eq 3 - expect(object.title).to eq(["Now, surrender and prepare to be boarded"]) - end - end - end end end end @@ -157,6 +133,7 @@ class MockAFBase < ActiveFedora::Base context "after creating the file" do let(:first_file) { File.new(File.join(File.dirname(__FILE__), "../fixtures/dino.jpg")) } let(:first_name) { "dino.jpg" } + before do content.content = first_file content.original_name = first_name @@ -164,15 +141,10 @@ class MockAFBase < ActiveFedora::Base content.create_version end - it "links to versions endpoint" do - expect(content.metadata.ldp_source.graph.query({ predicate: ::RDF::Vocab::Fcrepo4.hasVersions }).objects).to_not be_empty - end - it "has one version" do expect(content.versions.all.size).to eq 1 expect(content.original_name).to eql(first_name) expect(content.content.size).to eq first_file.size - expect(content.versions.first.label).to eql "version1" expect(content.versions.first.created).to start_with current_year end @@ -180,6 +152,7 @@ class MockAFBase < ActiveFedora::Base let(:second_file) { File.new(File.join(File.dirname(__FILE__), "../fixtures/minivan.jpg")) } let(:second_name) { "minivan.jpg" } before do + sleep(1) content.content = second_file content.original_name = second_name content.save @@ -191,62 +164,18 @@ class MockAFBase < ActiveFedora::Base expect(content.original_name).to eql(second_name) expect(content.content.size).to eq second_file.size content.versions.all.each_index do |index| - expect(content.versions.all[index].label).to end_with "version" + (index + 1).to_s expect(content.versions.all[index].created).to start_with current_year end end context "with fixity checking" do let(:results) do - results = [] - content.versions.all.each do |version| - results << ActiveFedora::FixityService.new(version.uri).check - end - return results + content.versions.all.collect { |version| ActiveFedora.fedora.connection.head(version.uri.to_s) { |req| req.headers["Want-Digest"] = "sha-512" }.response.headers["Digest"].gsub("sha-512=", "") } end + let(:file_checksums) { [Digest::SHA512.hexdigest(File.read(first_file)), Digest::SHA512.hexdigest(File.read(second_file))] } it "reports on the fixity of each version" do - results.each do |result| - expect(result).to be true - end - end - end - - context "then restoring" do - let(:first_version) { "version1" } - before do - content.restore_version(first_version) - end - - it "stills have two unique versions" do - expect(content.versions.all.size).to eq 2 - end - - it "loads the restored file's content" do - expect(content.content.size).to eq first_file.size - end - - it "loads the restored file's original name" do - expect(content.original_name).to eql(first_name) - end - - context "and creating additional versions" do - before do - content.content = first_file - content.original_name = first_name - content.save - content.create_version - end - - it "has three unique versions" do - expect(content.versions.all.size).to eq 3 - expect(content.original_name).to eql(first_name) - expect(content.content.size).to eq first_file.size - content.versions.all.each_index do |index| - expect(content.versions.all[index].label).to end_with "version" + (index + 1).to_s - expect(content.versions.all[index].created).to start_with current_year - end - end + expect(results).to eq file_checksums end end end diff --git a/spec/unit/file/streaming_spec.rb b/spec/unit/file/streaming_spec.rb index 196b10ef5..2a1b41da2 100644 --- a/spec/unit/file/streaming_spec.rb +++ b/spec/unit/file/streaming_spec.rb @@ -9,15 +9,19 @@ let(:streamer) do streamer = test_class.new allow(streamer).to receive(:uri).and_return(uri) - allow(streamer).to receive(:authorization_key).and_return("authorization_key") streamer end + let(:http_client) { instance_double("Faraday::Connection") } + + before do + allow(http_client).to receive(:get).and_return(nil) + end context "without ssl" do let(:uri) { "http://localhost/file/1" } it do - expect(Net::HTTP).to receive(:start).with('localhost', 80, use_ssl: false).and_return(nil) + expect(Faraday).to receive(:new).with(ActiveFedora.fedora.host, {}).and_return(http_client) streamer.stream.each end end @@ -25,8 +29,12 @@ context "with ssl" do let(:uri) { "https://localhost/file/1" } + before do + allow(ActiveFedora.fedora).to receive(:ssl_options).and_return(true) + end + it do - expect(Net::HTTP).to receive(:start).with('localhost', 443, use_ssl: true).and_return(nil) + expect(Faraday).to receive(:new).with(ActiveFedora.fedora.host, hash_including(ssl: true)).and_return(http_client) streamer.stream.each end end diff --git a/spec/unit/file_configurator_spec.rb b/spec/unit/file_configurator_spec.rb index 86def260b..17063cb8d 100644 --- a/spec/unit/file_configurator_spec.rb +++ b/spec/unit/file_configurator_spec.rb @@ -281,8 +281,8 @@ it "loads a config from Rails.root as a first choice" do configurator.init - expect(configurator.config_path(:fedora)).to eql("#{Rails.root}/config/fedora.yml") - expect(configurator.solr_config_path).to eql("#{Rails.root}/config/solr.yml") + expect(configurator.config_path(:fedora)).to eql([Rails.root, "config/fedora.yml"].join('/')) + expect(configurator.solr_config_path).to eql([Rails.root, "config/solr.yml"].join('/')) end it "can tell what environment it is set to run in" do