From e9daf42e1fae56d4891cbdb1e30c7a4ce114b7e1 Mon Sep 17 00:00:00 2001 From: GriffinJ Date: Tue, 14 Aug 2018 12:41:36 -0400 Subject: [PATCH] Implementing IIIFResource#validate_iiif_manifest_collections! for validating Collection metadata --- app/models/exhibit_proxy.rb | 1 - app/models/iiif_resource.rb | 23 ++++- spec/models/iiif_resource_spec.rb | 135 +++++++++++++++--------------- 3 files changed, 91 insertions(+), 68 deletions(-) diff --git a/app/models/exhibit_proxy.rb b/app/models/exhibit_proxy.rb index 62fca155..1c6b95ed 100644 --- a/app/models/exhibit_proxy.rb +++ b/app/models/exhibit_proxy.rb @@ -5,7 +5,6 @@ def initialize(exhibit) end def reindex(*_args) - binding.pry members.each_slice(50) do |slice| IIIFIngestJob.perform_later slice, exhibit end diff --git a/app/models/iiif_resource.rb b/app/models/iiif_resource.rb index 42579300..80432f78 100644 --- a/app/models/iiif_resource.rb +++ b/app/models/iiif_resource.rb @@ -3,8 +3,29 @@ class IIIFResource < Spotlight::Resources::IiifHarvester after_destroy :cleanup_solr before_save :set_noid + class InvalidIIIFManifestError < TypeError; end + def iiif_manifests - @iiif_manifests ||= ::IiifService.parse(url) + @iiif_manifests ||= validate_iiif_manifest_collections! + end + + def validate_iiif_manifest_collections! + iiif_manifests = ::IiifService.parse(url) + + # Check for valid metadata + iiif_manifests.to_a.each do |iiif_manifest| + iiif_manifest.with_exhibit(exhibit) + + next unless iiif_manifest.as_json.key?("manifest") && + iiif_manifest.as_json["manifest"].key?("data") && + iiif_manifest.as_json["manifest"]["data"].key?("metadata") + + collection_metadata = iiif_manifest.as_json["manifest"]["data"]["metadata"].select { |metadata| metadata["label"] == "Collections" } + invalid_collection_metadata = collection_metadata.select { |metadata| metadata["value"].first.is_a?(Hash) } + raise(InvalidIIIFManifestError, "Invalid Collection metadata found in the IIIF Manifest: #{url}") unless invalid_collection_metadata.empty? + end + + @iiif_manifests = iiif_manifests end def cleanup_solr diff --git a/spec/models/iiif_resource_spec.rb b/spec/models/iiif_resource_spec.rb index 42884b26..456cbde9 100644 --- a/spec/models/iiif_resource_spec.rb +++ b/spec/models/iiif_resource_spec.rb @@ -83,16 +83,8 @@ "@id": "https://hydra-dev.princeton.edu/users/auth/cas", "label": "Login to Figgy using CAS", "profile": "http://iiif.io/api/auth/0/login", - "service": {"hsh": nil} + "service": { "hsh": nil } }, - "structures": [ - { - "@id":"https://hydra-dev.princeton.edu/concern/scanned_resources/1r66j1149/manifest/range/g70272255683880", - "@type":"sc:Range", - "label":"Logical", - "viewingHint":"top" - } - ], "structures": [ { "@id": "https://hydra-dev.princeton.edu/concern/scanned_resources/s9w032300r/manifest/range/g70237482003920", @@ -104,16 +96,16 @@ "@id": "https://hydra-dev.princeton.edu/concern/scanned_resources/s9w032300r/manifest/range/g70237482056940", "@type": "sc:Range", "label": "Chapter 1", - "canvases":[ + "canvases": [ "https://hydra-dev.princeton.edu/concern/scanned_resources/s9w032300r/manifest/canvas/sbn9996723", "https://hydra-dev.princeton.edu/concern/scanned_resources/s9w032300r/manifest/canvas/s9k41zd485" ] }, { - "@id":"https://hydra-dev.princeton.edu/concern/scanned_resources/s9w032300r/manifest/range/g70237482036180", - "@type":"sc:Range", - "label":"Chapter 2", - "canvases":[ + "@id": "https://hydra-dev.princeton.edu/concern/scanned_resources/s9w032300r/manifest/range/g70237482036180", + "@type": "sc:Range", + "label": "Chapter 2", + "canvases": [ "https://hydra-dev.princeton.edu/concern/scanned_resources/s9w032300r/manifest/canvas/sww72bb48n", "https://hydra-dev.princeton.edu/concern/scanned_resources/s9w032300r/manifest/canvas/sjs956f80z" ] @@ -121,35 +113,42 @@ ] } ], - "metadata":[ - {"label":"Date created","value":[{"@value":"1976"}]} + "metadata": [ + { + "label": "Date created", + "value": [{ "@value": "1976" }] + }, + { + "label": "Collections", + "value": [{ "id": { "id": "058c1862-30dc-431c-90b5-4e141282c7a1" }, "internal_resource": "Collection", "created_at": "11/29/17 12:46:50 PM UTC" }] + } ], - "seeAlso":[ - {"@id": "https://bibdata.princeton.edu/bibliographic/1234567/jsonld","format": "application/ld+json"}, - {"@id": "bla", "format":"text/xml"} + "seeAlso": [ + { "@id": "https://bibdata.princeton.edu/bibliographic/1234567/jsonld", "format": "application/ld+json" }, + { "@id": "bla", "format": "text/xml" } ], - "rendering": {"@id":"http://arks.princeton.edu/ark:88435/7w62fb79g", "format": "text/html"} + "rendering": { "@id": "http://arks.princeton.edu/ark:88435/7w62fb79g", "format": "text/html" } } end let(:collection_manifest) do { "@id": "https://localhost.localdomain/collections/2b88qc199/manifest", - "@type":"sc:Collection", - "label":"princeton", - "viewingHint":"individuals", - "structures":[ + "@type": "sc:Collection", + "label": "princeton", + "viewingHint": "individuals", + "structures": [ { - "@id":"https://localhost.localdomain/collections/2b88qc199/manifest/range/g70272079000020", - "@type":"sc:Range", - "label":"Logical", - "viewingHint":"top" + "@id": "https://localhost.localdomain/collections/2b88qc199/manifest/range/g70272079000020", + "@type": "sc:Range", + "label": "Logical", + "viewingHint": "top" } ], - "metadata":[ + "metadata": [ { - "label":"Exhibit", - "value":["princeton-best"] + "label": "Exhibit", + "value": ["princeton-best"] } ], "manifests": [ @@ -166,38 +165,38 @@ let(:collections_manifest) do { - "@context":"http://iiif.io/api/presentation/2/context.json", - "@id":"https://localhost.localdomain/collections/manifest", - "@type":"sc:Collection", - "label":"Figgy Collections", - "description":"All collections which are a part of Figgy.", - "viewingHint":"individuals", - "structures":[ + "@context": "http://iiif.io/api/presentation/2/context.json", + "@id": "https://localhost.localdomain/collections/manifest", + "@type": "sc:Collection", + "label": "Figgy Collections", + "description": "All collections which are a part of Figgy.", + "viewingHint": "individuals", + "structures": [ { - "@id":"https://localhost.localdomain/collections/manifest/range/g70272257673280", - "@type":"sc:Range", - "label":"Logical", - "viewingHint":"top" + "@id": "https://localhost.localdomain/collections/manifest/range/g70272257673280", + "@type": "sc:Range", + "label": "Logical", + "viewingHint": "top" } ], - "collections":[ + "collections": [ { - "@id":"https://localhost.localdomain/collections/2b88qc199/manifest", - "@type":"sc:Collection", - "label":"princeton", - "viewingHint":"individuals", - "structures":[ + "@id": "https://localhost.localdomain/collections/2b88qc199/manifest", + "@type": "sc:Collection", + "label": "princeton", + "viewingHint": "individuals", + "structures": [ { - "@id":"https://localhost.localdomain/collections/2b88qc199/manifest/range/g70272079000020", - "@type":"sc:Range", - "label":"Logical", - "viewingHint":"top" + "@id": "https://localhost.localdomain/collections/2b88qc199/manifest/range/g70272079000020", + "@type": "sc:Range", + "label": "Logical", + "viewingHint": "top" } ], - "metadata":[ + "metadata": [ { - "label":"Exhibit", - "value":["princeton-best"] + "label": "Exhibit", + "value": ["princeton-best"] } ] } @@ -206,22 +205,26 @@ end before do - stub_request(:get, "https://localhost.localdomain/scanned_resources/1r66j1149/manifest" + stub_request( + :get, + "https://localhost.localdomain/scanned_resources/1r66j1149/manifest" ).to_return(body: JSON.generate(scanned_resource_manifest)) - stub_request(:get, "https://localhost.localdomain/collections/2b88qc199/manifest" + stub_request( + :get, + "https://localhost.localdomain/collections/2b88qc199/manifest" ).to_return(body: JSON.generate(collection_manifest)) - stub_request(:get, url + stub_request( + :get, + url ).to_return(body: JSON.generate(collections_manifest)) - stub_request(:head, url - ).to_return(headers: { 'Content-Type' => 'application/json; charset=utf-8' }) + stub_request( + :head, + url + ).to_return(headers: { 'Content-Type' => 'application/json; charset=utf-8' }) end - it "does not index collections" do - expect(resource.save).to be true - - solr_doc = nil - resource.document_builder.to_solr { |x| solr_doc = x } - expect(solr_doc["readonly_collections_tesim"]).to be_empty + it "raises an error" do + expect { resource.save }.to raise_error(IIIFResource::InvalidIIIFManifestError, "Invalid Collection metadata found in the IIIF Manifest: #{url}") end end end